xref: /reactos/dll/win32/crypt32/encode.c (revision b1b70ef9)
1 /*
2  * Copyright 2005-2008 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  * This file implements ASN.1 DER encoding of a limited set of types.
19  * It isn't a full ASN.1 implementation.  Microsoft implements BER
20  * encoding of many of the basic types in msasn1.dll, but that interface isn't
21  * implemented, so I implement them here.
22  *
23  * References:
24  * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25  * (available online, look for a PDF copy as the HTML versions tend to have
26  * translation errors.)
27  *
28  * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
29  *
30  * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
31  */
32 
33 #include "config.h"
34 #include "wine/port.h"
35 
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 
41 #define NONAMELESSUNION
42 
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "snmp.h"
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
51 
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt);
54 
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
56  BYTE *, DWORD *);
57 
58 /* Prototypes for built-in encoders.  They follow the Ex style prototypes.
59  * The dwCertEncodingType and lpszStructType are ignored by the built-in
60  * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61  * since it must call functions in external DLLs that follow these signatures.
62  */
63 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
64  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
67  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
70  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
73  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
76  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
79  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
82  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
85  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
88  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
91  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
94  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
96 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
97  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
98  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
99 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
100  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
101  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
102 
CRYPT_EncodeEnsureSpace(DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded,DWORD bytesNeeded)103 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara,
104  BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
105 {
106     BOOL ret = TRUE;
107 
108     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
109     {
110         if (pEncodePara && pEncodePara->pfnAlloc)
111             *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
112         else
113             *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
114         if (!*(BYTE **)pbEncoded)
115             ret = FALSE;
116         else
117             *pcbEncoded = bytesNeeded;
118     }
119     else if (bytesNeeded > *pcbEncoded)
120     {
121         *pcbEncoded = bytesNeeded;
122         SetLastError(ERROR_MORE_DATA);
123         ret = FALSE;
124     }
125     else
126         *pcbEncoded = bytesNeeded;
127     return ret;
128 }
129 
CRYPT_FreeSpace(const CRYPT_ENCODE_PARA * pEncodePara,LPVOID pv)130 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
131 {
132     if (pEncodePara && pEncodePara->pfnFree)
133         pEncodePara->pfnFree(pv);
134     else
135         LocalFree(pv);
136 }
137 
CRYPT_EncodeLen(DWORD len,BYTE * pbEncoded,DWORD * pcbEncoded)138 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
139 {
140     DWORD bytesNeeded, significantBytes = 0;
141 
142     if (len <= 0x7f)
143         bytesNeeded = 1;
144     else
145     {
146         DWORD temp;
147 
148         for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
149          temp <<= 8, significantBytes--)
150             ;
151         bytesNeeded = significantBytes + 1;
152     }
153     if (!pbEncoded)
154     {
155         *pcbEncoded = bytesNeeded;
156         return TRUE;
157     }
158     if (*pcbEncoded < bytesNeeded)
159     {
160         SetLastError(ERROR_MORE_DATA);
161         return FALSE;
162     }
163     if (len <= 0x7f)
164         *pbEncoded = (BYTE)len;
165     else
166     {
167         DWORD i;
168 
169         *pbEncoded++ = significantBytes | 0x80;
170         for (i = 0; i < significantBytes; i++)
171         {
172             *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
173             len >>= 8;
174         }
175     }
176     *pcbEncoded = bytesNeeded;
177     return TRUE;
178 }
179 
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,struct AsnEncodeSequenceItem items[],DWORD cItem,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)180 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
181  struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
182  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
183 {
184     BOOL ret;
185     DWORD i, dataLen = 0;
186 
187     TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
188      pbEncoded, pbEncoded ? *pcbEncoded : 0);
189     for (i = 0, ret = TRUE; ret && i < cItem; i++)
190     {
191         ret = items[i].encodeFunc(dwCertEncodingType, NULL,
192          items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
193          NULL, &items[i].size);
194         /* Some functions propagate their errors through the size */
195         if (!ret)
196             *pcbEncoded = items[i].size;
197         dataLen += items[i].size;
198     }
199     if (ret)
200     {
201         DWORD lenBytes, bytesNeeded;
202 
203         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
204         bytesNeeded = 1 + lenBytes + dataLen;
205         if (!pbEncoded)
206             *pcbEncoded = bytesNeeded;
207         else
208         {
209             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
210              pcbEncoded, bytesNeeded)))
211             {
212                 BYTE *out;
213 
214                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
215                     pbEncoded = *(BYTE **)pbEncoded;
216                 out = pbEncoded;
217                 *out++ = ASN_SEQUENCE;
218                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
219                 out += lenBytes;
220                 for (i = 0; ret && i < cItem; i++)
221                 {
222                     ret = items[i].encodeFunc(dwCertEncodingType, NULL,
223                      items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
224                      NULL, out, &items[i].size);
225                     /* Some functions propagate their errors through the size */
226                     if (!ret)
227                         *pcbEncoded = items[i].size;
228                     out += items[i].size;
229                 }
230                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
231                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
232             }
233         }
234     }
235     TRACE("returning %d (%08x)\n", ret, GetLastError());
236     return ret;
237 }
238 
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)239 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
240  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
241  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
242 {
243     BOOL ret;
244     const struct AsnConstructedItem *item = pvStructInfo;
245     DWORD len;
246 
247     if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
248      item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
249     {
250         DWORD dataLen, bytesNeeded;
251 
252         CRYPT_EncodeLen(len, NULL, &dataLen);
253         bytesNeeded = 1 + dataLen + len;
254         if (!pbEncoded)
255             *pcbEncoded = bytesNeeded;
256         else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
257          pbEncoded, pcbEncoded, bytesNeeded)))
258         {
259             BYTE *out;
260 
261             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
262                 pbEncoded = *(BYTE **)pbEncoded;
263             out = pbEncoded;
264             *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
265             CRYPT_EncodeLen(len, out, &dataLen);
266             out += dataLen;
267             ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
268              item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
269              out, &len);
270             if (!ret)
271             {
272                 /* Some functions propagate their errors through the size */
273                 *pcbEncoded = len;
274                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
275                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
276             }
277         }
278     }
279     else
280     {
281         /* Some functions propagate their errors through the size */
282         *pcbEncoded = len;
283     }
284     return ret;
285 }
286 
287 struct AsnEncodeTagSwappedItem
288 {
289     BYTE                    tag;
290     const void             *pvStructInfo;
291     CryptEncodeObjectExFunc encodeFunc;
292 };
293 
294 /* Sort of a wacky hack, it encodes something using the struct
295  * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
296  * given in the struct AsnEncodeTagSwappedItem.
297  */
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)298 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
299  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
300  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
301 {
302     BOOL ret;
303     const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
304 
305     ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
306      item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
307     if (ret && pbEncoded)
308         *pbEncoded = item->tag;
309     return ret;
310 }
311 
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)312 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
313  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
314  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
315 {
316     const DWORD *ver = pvStructInfo;
317     BOOL ret;
318 
319     /* CERT_V1 is not encoded */
320     if (*ver == CERT_V1)
321     {
322         *pcbEncoded = 0;
323         ret = TRUE;
324     }
325     else
326     {
327         struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
328 
329         ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
330          &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
331     }
332     return ret;
333 }
334 
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)335 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
336  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
337  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
338 {
339     const CRYPT_DER_BLOB *blob = pvStructInfo;
340     BOOL ret;
341 
342     if (!pbEncoded)
343     {
344         *pcbEncoded = blob->cbData;
345         ret = TRUE;
346     }
347     else
348     {
349         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
350          pcbEncoded, blob->cbData)))
351         {
352             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
353                 pbEncoded = *(BYTE **)pbEncoded;
354             if (blob->cbData)
355                 memcpy(pbEncoded, blob->pbData, blob->cbData);
356             *pcbEncoded = blob->cbData;
357         }
358     }
359     return ret;
360 }
361 
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)362 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
363  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
364  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
365 {
366     BOOL ret;
367     /* This has two filetimes in a row, a NotBefore and a NotAfter */
368     const FILETIME *timePtr = pvStructInfo;
369     struct AsnEncodeSequenceItem items[] = {
370      { timePtr,     CRYPT_AsnEncodeChoiceOfTime, 0 },
371      { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
372     };
373 
374     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
375      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
376      pcbEncoded);
377     return ret;
378 }
379 
380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
381  * if they are empty.
382  */
CRYPT_AsnEncodeAlgorithmIdWithNullParams(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)383 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
384  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
385  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
386  DWORD *pcbEncoded)
387 {
388     const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
389     static const BYTE asn1Null[] = { ASN_NULL, 0 };
390     static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
391      (LPBYTE)asn1Null };
392     BOOL ret;
393     struct AsnEncodeSequenceItem items[2] = {
394      { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
395      { NULL,           CRYPT_CopyEncodedBlob, 0 },
396     };
397 
398     if (algo->Parameters.cbData)
399         items[1].pvStructInfo = &algo->Parameters;
400     else
401         items[1].pvStructInfo = &nullBlob;
402     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
403      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
404      pcbEncoded);
405     return ret;
406 }
407 
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)408 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
409  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
410  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
411 {
412     const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
413     BOOL ret;
414     struct AsnEncodeSequenceItem items[] = {
415      { algo->pszObjId,    CRYPT_AsnEncodeOid, 0 },
416      { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
417     };
418 
419     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
420      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
421      pcbEncoded);
422     return ret;
423 }
424 
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)425 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
426  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
427  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
428 {
429     BOOL ret;
430 
431     __TRY
432     {
433         const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
434         struct AsnEncodeSequenceItem items[] = {
435          { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
436          { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
437         };
438 
439         TRACE("Encoding public key with OID %s\n",
440          debugstr_a(info->Algorithm.pszObjId));
441         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
442          ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
443          pcbEncoded);
444     }
445     __EXCEPT_PAGE_FAULT
446     {
447         SetLastError(STATUS_ACCESS_VIOLATION);
448         ret = FALSE;
449     }
450     __ENDTRY
451     return ret;
452 }
453 
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)454 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
455  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
456  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
457 {
458     BOOL ret;
459 
460     __TRY
461     {
462         const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo;
463         struct AsnEncodeSequenceItem items[] = {
464          { &info->ToBeSigned,         CRYPT_CopyEncodedBlob, 0 },
465          { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
466          { &info->Signature,          CRYPT_AsnEncodeBitsSwapBytes, 0 },
467         };
468 
469         if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
470             items[2].encodeFunc = CRYPT_AsnEncodeBits;
471         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
472          ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
473          pcbEncoded);
474     }
475     __EXCEPT_PAGE_FAULT
476     {
477         SetLastError(STATUS_ACCESS_VIOLATION);
478         ret = FALSE;
479     }
480     __ENDTRY
481     return ret;
482 }
483 
CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)484 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
485  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
486  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
487 {
488     BOOL ret;
489     const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
490     struct AsnEncodeSequenceItem items[] = {
491      { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
492      { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
493     };
494 
495     TRACE("Encoding public key with OID %s\n",
496      debugstr_a(info->Algorithm.pszObjId));
497     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
498      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
499      pcbEncoded);
500     return ret;
501 }
502 
503 /* Like in Windows, this blithely ignores the validity of the passed-in
504  * CERT_INFO, and just encodes it as-is.  The resulting encoded data may not
505  * decode properly, see CRYPT_AsnDecodeCertInfo.
506  */
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)507 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
508  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
509  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
510 {
511     BOOL ret;
512 
513     __TRY
514     {
515         const CERT_INFO *info = pvStructInfo;
516         struct AsnEncodeSequenceItem items[10] = {
517          { &info->dwVersion,            CRYPT_AsnEncodeCertVersion, 0 },
518          { &info->SerialNumber,         CRYPT_AsnEncodeInteger, 0 },
519          { &info->SignatureAlgorithm,   CRYPT_AsnEncodeAlgorithmId, 0 },
520          { &info->Issuer,               CRYPT_CopyEncodedBlob, 0 },
521          { &info->NotBefore,            CRYPT_AsnEncodeValidity, 0 },
522          { &info->Subject,              CRYPT_CopyEncodedBlob, 0 },
523          { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 },
524          { 0 }
525         };
526         struct AsnConstructedItem constructed = { 0 };
527         struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
528         DWORD cItem = 7, cSwapped = 0;
529 
530         if (info->IssuerUniqueId.cbData)
531         {
532             swapped[cSwapped].tag = ASN_CONTEXT | 1;
533             swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId;
534             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
535             items[cItem].pvStructInfo = &swapped[cSwapped];
536             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
537             cSwapped++;
538             cItem++;
539         }
540         if (info->SubjectUniqueId.cbData)
541         {
542             swapped[cSwapped].tag = ASN_CONTEXT | 2;
543             swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId;
544             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
545             items[cItem].pvStructInfo = &swapped[cSwapped];
546             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
547             cSwapped++;
548             cItem++;
549         }
550         if (info->cExtension)
551         {
552             constructed.tag = 3;
553             constructed.pvStructInfo = &info->cExtension;
554             constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
555             items[cItem].pvStructInfo = &constructed;
556             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
557             cItem++;
558         }
559 
560         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
561          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
562     }
563     __EXCEPT_PAGE_FAULT
564     {
565         SetLastError(STATUS_ACCESS_VIOLATION);
566         ret = FALSE;
567     }
568     __ENDTRY
569     return ret;
570 }
571 
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY * entry,BYTE * pbEncoded,DWORD * pcbEncoded)572 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
573  BYTE *pbEncoded, DWORD *pcbEncoded)
574 {
575     struct AsnEncodeSequenceItem items[3] = {
576      { &entry->SerialNumber,   CRYPT_AsnEncodeInteger, 0 },
577      { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
578      { 0 }
579     };
580     DWORD cItem = 2;
581     BOOL ret;
582 
583     TRACE("%p, %p, %d\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0);
584 
585     if (entry->cExtension)
586     {
587         items[cItem].pvStructInfo = &entry->cExtension;
588         items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
589         cItem++;
590     }
591 
592     ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
593      pbEncoded, pcbEncoded);
594 
595     TRACE("returning %d (%08x)\n", ret, GetLastError());
596     return ret;
597 }
598 
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)599 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
600  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
601  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
602 {
603     DWORD bytesNeeded, dataLen, lenBytes, i;
604     const CRL_INFO *info = pvStructInfo;
605     const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
606     BOOL ret = TRUE;
607 
608     for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
609     {
610         DWORD size;
611 
612         ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
613         if (ret)
614             dataLen += size;
615     }
616     if (ret)
617     {
618         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
619         bytesNeeded = 1 + lenBytes + dataLen;
620         if (!pbEncoded)
621             *pcbEncoded = bytesNeeded;
622         else
623         {
624             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
625              pcbEncoded, bytesNeeded)))
626             {
627                 BYTE *out;
628 
629                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
630                     pbEncoded = *(BYTE **)pbEncoded;
631                 out = pbEncoded;
632                 *out++ = ASN_SEQUENCEOF;
633                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
634                 out += lenBytes;
635                 for (i = 0; i < info->cCRLEntry; i++)
636                 {
637                     DWORD size = dataLen;
638 
639                     ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
640                     out += size;
641                     dataLen -= size;
642                 }
643                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
644                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
645             }
646         }
647     }
648     return ret;
649 }
650 
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)651 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
652  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
653  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
654 {
655     const DWORD *ver = pvStructInfo;
656     BOOL ret;
657 
658     /* CRL_V1 is not encoded */
659     if (*ver == CRL_V1)
660     {
661         *pcbEncoded = 0;
662         ret = TRUE;
663     }
664     else
665         ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
666          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
667     return ret;
668 }
669 
670 /* Like in Windows, this blithely ignores the validity of the passed-in
671  * CRL_INFO, and just encodes it as-is.  The resulting encoded data may not
672  * decode properly, see CRYPT_AsnDecodeCRLInfo.
673  */
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)674 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
675  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
676  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
677 {
678     BOOL ret;
679 
680     __TRY
681     {
682         const CRL_INFO *info = pvStructInfo;
683         struct AsnEncodeSequenceItem items[7] = {
684          { &info->dwVersion,          CRYPT_AsnEncodeCRLVersion, 0 },
685          { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
686          { &info->Issuer,             CRYPT_CopyEncodedBlob, 0 },
687          { &info->ThisUpdate,         CRYPT_AsnEncodeChoiceOfTime, 0 },
688          { 0 }
689         };
690         struct AsnConstructedItem constructed[1] = { { 0 } };
691         DWORD cItem = 4, cConstructed = 0;
692 
693         if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
694         {
695             items[cItem].pvStructInfo = &info->NextUpdate;
696             items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
697             cItem++;
698         }
699         if (info->cCRLEntry)
700         {
701             items[cItem].pvStructInfo = info;
702             items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
703             cItem++;
704         }
705         if (info->cExtension)
706         {
707             constructed[cConstructed].tag = 0;
708             constructed[cConstructed].pvStructInfo = &info->cExtension;
709             constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
710             items[cItem].pvStructInfo = &constructed[cConstructed];
711             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
712             cConstructed++;
713             cItem++;
714         }
715 
716         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
717          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
718     }
719     __EXCEPT_PAGE_FAULT
720     {
721         SetLastError(STATUS_ACCESS_VIOLATION);
722         ret = FALSE;
723     }
724     __ENDTRY
725     return ret;
726 }
727 
CRYPT_AsnEncodeExtension(CERT_EXTENSION * ext,BYTE * pbEncoded,DWORD * pcbEncoded)728 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
729  DWORD *pcbEncoded)
730 {
731     BOOL ret;
732     struct AsnEncodeSequenceItem items[3] = {
733      { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
734      { NULL, NULL, 0 },
735      { NULL, NULL, 0 },
736     };
737     DWORD cItem = 1;
738 
739     TRACE("%p, %p, %d\n", ext, pbEncoded, pbEncoded ? *pcbEncoded : 0);
740 
741     if (ext->fCritical)
742     {
743         items[cItem].pvStructInfo = &ext->fCritical;
744         items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
745         cItem++;
746     }
747     items[cItem].pvStructInfo = &ext->Value;
748     items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
749     cItem++;
750 
751     ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
752      pbEncoded, pcbEncoded);
753     TRACE("returning %d (%08x)\n", ret, GetLastError());
754     return ret;
755 }
756 
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)757 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
758  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
759  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
760 {
761     BOOL ret;
762 
763     __TRY
764     {
765         DWORD bytesNeeded, dataLen, lenBytes, i;
766         const CERT_EXTENSIONS *exts = pvStructInfo;
767 
768         ret = TRUE;
769         for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
770         {
771             DWORD size;
772 
773             ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
774             if (ret)
775                 dataLen += size;
776         }
777         if (ret)
778         {
779             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
780             bytesNeeded = 1 + lenBytes + dataLen;
781             if (!pbEncoded)
782                 *pcbEncoded = bytesNeeded;
783             else
784             {
785                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
786                  pbEncoded, pcbEncoded, bytesNeeded)))
787                 {
788                     BYTE *out;
789 
790                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
791                         pbEncoded = *(BYTE **)pbEncoded;
792                     out = pbEncoded;
793                     *out++ = ASN_SEQUENCEOF;
794                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
795                     out += lenBytes;
796                     for (i = 0; i < exts->cExtension; i++)
797                     {
798                         DWORD size = dataLen;
799 
800                         ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
801                          out, &size);
802                         out += size;
803                         dataLen -= size;
804                     }
805                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
806                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
807                 }
808             }
809         }
810     }
811     __EXCEPT_PAGE_FAULT
812     {
813         SetLastError(STATUS_ACCESS_VIOLATION);
814         ret = FALSE;
815     }
816     __ENDTRY
817     return ret;
818 }
819 
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)820 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
821  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
822  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
823 {
824     LPCSTR pszObjId = pvStructInfo;
825     DWORD bytesNeeded = 0, lenBytes;
826     BOOL ret = TRUE;
827     int firstPos = 0;
828     BYTE firstByte = 0;
829 
830     TRACE("%s\n", debugstr_a(pszObjId));
831 
832     if (pszObjId)
833     {
834         const char *ptr;
835         int val1, val2;
836 
837         if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
838         {
839             SetLastError(CRYPT_E_ASN1_ERROR);
840             return FALSE;
841         }
842         bytesNeeded++;
843         firstByte = val1 * 40 + val2;
844         ptr = pszObjId + firstPos;
845         if (*ptr == '.')
846         {
847             ptr++;
848             firstPos++;
849         }
850         while (ret && *ptr)
851         {
852             int pos;
853 
854             /* note I assume each component is at most 32-bits long in base 2 */
855             if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
856             {
857                 if (val1 >= 0x10000000)
858                     bytesNeeded += 5;
859                 else if (val1 >= 0x200000)
860                     bytesNeeded += 4;
861                 else if (val1 >= 0x4000)
862                     bytesNeeded += 3;
863                 else if (val1 >= 0x80)
864                     bytesNeeded += 2;
865                 else
866                     bytesNeeded += 1;
867                 ptr += pos;
868                 if (*ptr == '.')
869                     ptr++;
870             }
871             else
872             {
873                 SetLastError(CRYPT_E_ASN1_ERROR);
874                 return FALSE;
875             }
876         }
877         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
878     }
879     else
880         lenBytes = 1;
881     bytesNeeded += 1 + lenBytes;
882     if (pbEncoded)
883     {
884         if (*pcbEncoded < bytesNeeded)
885         {
886             SetLastError(ERROR_MORE_DATA);
887             ret = FALSE;
888         }
889         else
890         {
891             *pbEncoded++ = ASN_OBJECTIDENTIFIER;
892             CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
893             pbEncoded += lenBytes;
894             if (pszObjId)
895             {
896                 const char *ptr;
897                 int val, pos;
898 
899                 *pbEncoded++ = firstByte;
900                 ptr = pszObjId + firstPos;
901                 while (ret && *ptr)
902                 {
903                     sscanf(ptr, "%d%n", &val, &pos);
904                     {
905                         unsigned char outBytes[5];
906                         int numBytes, i;
907 
908                         if (val >= 0x10000000)
909                             numBytes = 5;
910                         else if (val >= 0x200000)
911                             numBytes = 4;
912                         else if (val >= 0x4000)
913                             numBytes = 3;
914                         else if (val >= 0x80)
915                             numBytes = 2;
916                         else
917                             numBytes = 1;
918                         for (i = numBytes; i > 0; i--)
919                         {
920                             outBytes[i - 1] = val & 0x7f;
921                             val >>= 7;
922                         }
923                         for (i = 0; i < numBytes - 1; i++)
924                             *pbEncoded++ = outBytes[i] | 0x80;
925                         *pbEncoded++ = outBytes[i];
926                         ptr += pos;
927                         if (*ptr == '.')
928                             ptr++;
929                     }
930                 }
931             }
932         }
933     }
934     *pcbEncoded = bytesNeeded;
935     return ret;
936 }
937 
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE * value,BYTE tag,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)938 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
939  BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
940  DWORD *pcbEncoded)
941 {
942     BOOL ret = TRUE;
943     LPCSTR str = (LPCSTR)value->Value.pbData;
944     DWORD bytesNeeded, lenBytes, encodedLen;
945 
946     encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
947     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
948     bytesNeeded = 1 + lenBytes + encodedLen;
949     if (!pbEncoded)
950         *pcbEncoded = bytesNeeded;
951     else
952     {
953         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
954          pbEncoded, pcbEncoded, bytesNeeded)))
955         {
956             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
957                 pbEncoded = *(BYTE **)pbEncoded;
958             *pbEncoded++ = tag;
959             CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
960             pbEncoded += lenBytes;
961             memcpy(pbEncoded, str, encodedLen);
962         }
963     }
964     return ret;
965 }
966 
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE * value,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)967 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
968  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
969  DWORD *pcbEncoded)
970 {
971     BOOL ret = TRUE;
972     LPCWSTR str = (LPCWSTR)value->Value.pbData;
973     DWORD bytesNeeded, lenBytes, strLen;
974 
975     if (value->Value.cbData)
976         strLen = value->Value.cbData / sizeof(WCHAR);
977     else if (value->Value.pbData)
978         strLen = lstrlenW(str);
979     else
980         strLen = 0;
981     CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
982     bytesNeeded = 1 + lenBytes + strLen * 2;
983     if (!pbEncoded)
984         *pcbEncoded = bytesNeeded;
985     else
986     {
987         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
988          pbEncoded, pcbEncoded, bytesNeeded)))
989         {
990             DWORD i;
991 
992             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
993                 pbEncoded = *(BYTE **)pbEncoded;
994             *pbEncoded++ = ASN_BMPSTRING;
995             CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
996             pbEncoded += lenBytes;
997             for (i = 0; i < strLen; i++)
998             {
999                 *pbEncoded++ = (str[i] & 0xff00) >> 8;
1000                 *pbEncoded++ = str[i] & 0x00ff;
1001             }
1002         }
1003     }
1004     return ret;
1005 }
1006 
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE * value,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1007 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
1008  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1009  DWORD *pcbEncoded)
1010 {
1011     BOOL ret = TRUE;
1012     LPCWSTR str = (LPCWSTR)value->Value.pbData;
1013     DWORD bytesNeeded, lenBytes, encodedLen, strLen;
1014 
1015     if (value->Value.cbData)
1016         strLen = value->Value.cbData / sizeof(WCHAR);
1017     else if (str)
1018         strLen = strlenW(str);
1019     else
1020         strLen = 0;
1021     encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
1022      NULL);
1023     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1024     bytesNeeded = 1 + lenBytes + encodedLen;
1025     if (!pbEncoded)
1026         *pcbEncoded = bytesNeeded;
1027     else
1028     {
1029         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1030          pbEncoded, pcbEncoded, bytesNeeded)))
1031         {
1032             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1033                 pbEncoded = *(BYTE **)pbEncoded;
1034             *pbEncoded++ = ASN_UTF8STRING;
1035             CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1036             pbEncoded += lenBytes;
1037             WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1038              bytesNeeded - lenBytes - 1, NULL, NULL);
1039         }
1040     }
1041     return ret;
1042 }
1043 
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1044 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1045  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1046  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1047 {
1048     BOOL ret = TRUE;
1049 
1050     __TRY
1051     {
1052         const CERT_NAME_VALUE *value = pvStructInfo;
1053 
1054         switch (value->dwValueType)
1055         {
1056         case CERT_RDN_ANY_TYPE:
1057             /* explicitly disallowed */
1058             SetLastError(E_INVALIDARG);
1059             ret = FALSE;
1060             break;
1061         case CERT_RDN_ENCODED_BLOB:
1062             ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1063              &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1064             break;
1065         case CERT_RDN_OCTET_STRING:
1066             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1067              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1068             break;
1069         case CERT_RDN_NUMERIC_STRING:
1070             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1071              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1072             break;
1073         case CERT_RDN_PRINTABLE_STRING:
1074             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1075              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1076             break;
1077         case CERT_RDN_TELETEX_STRING:
1078             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1079              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1080             break;
1081         case CERT_RDN_VIDEOTEX_STRING:
1082             ret = CRYPT_AsnEncodeStringCoerce(value,
1083              ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1084             break;
1085         case CERT_RDN_IA5_STRING:
1086             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1087              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1088             break;
1089         case CERT_RDN_GRAPHIC_STRING:
1090             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1091              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1092             break;
1093         case CERT_RDN_VISIBLE_STRING:
1094             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1095              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1096             break;
1097         case CERT_RDN_GENERAL_STRING:
1098             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1099              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1100             break;
1101         case CERT_RDN_UNIVERSAL_STRING:
1102             FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1103             SetLastError(CRYPT_E_ASN1_CHOICE);
1104             ret = FALSE;
1105             break;
1106         case CERT_RDN_BMP_STRING:
1107             ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1108              pbEncoded, pcbEncoded);
1109             break;
1110         case CERT_RDN_UTF8_STRING:
1111             ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1112              pbEncoded, pcbEncoded);
1113             break;
1114         default:
1115             SetLastError(CRYPT_E_ASN1_CHOICE);
1116             ret = FALSE;
1117         }
1118     }
1119     __EXCEPT_PAGE_FAULT
1120     {
1121         SetLastError(STATUS_ACCESS_VIOLATION);
1122         ret = FALSE;
1123     }
1124     __ENDTRY
1125     return ret;
1126 }
1127 
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,const CERT_RDN_ATTR * attr,CryptEncodeObjectExFunc nameValueEncodeFunc,BYTE * pbEncoded,DWORD * pcbEncoded)1128 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1129  const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1130  BYTE *pbEncoded, DWORD *pcbEncoded)
1131 {
1132     DWORD bytesNeeded = 0, lenBytes, size;
1133     BOOL ret;
1134 
1135     ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1136      0, NULL, NULL, &size);
1137     if (ret)
1138     {
1139         bytesNeeded += size;
1140         /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1141          * with dwValueType, so "cast" it to get its encoded size
1142          */
1143         ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1144          0, NULL, NULL, &size);
1145         if (ret)
1146         {
1147             bytesNeeded += size;
1148             CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1149             bytesNeeded += 1 + lenBytes;
1150             if (pbEncoded)
1151             {
1152                 if (*pcbEncoded < bytesNeeded)
1153                 {
1154                     SetLastError(ERROR_MORE_DATA);
1155                     ret = FALSE;
1156                 }
1157                 else
1158                 {
1159                     *pbEncoded++ = ASN_SEQUENCE;
1160                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1161                      &lenBytes);
1162                     pbEncoded += lenBytes;
1163                     size = bytesNeeded - 1 - lenBytes;
1164                     ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1165                      attr->pszObjId, 0, NULL, pbEncoded, &size);
1166                     if (ret)
1167                     {
1168                         pbEncoded += size;
1169                         size = bytesNeeded - 1 - lenBytes - size;
1170                         ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1171                          &attr->dwValueType, 0, NULL, pbEncoded, &size);
1172                         if (!ret)
1173                             *pcbEncoded = size;
1174                     }
1175                 }
1176             }
1177             if (ret)
1178                 *pcbEncoded = bytesNeeded;
1179         }
1180         else
1181         {
1182             /* Have to propagate index of failing character */
1183             *pcbEncoded = size;
1184         }
1185     }
1186     return ret;
1187 }
1188 
BLOBComp(const void * l,const void * r)1189 static int BLOBComp(const void *l, const void *r)
1190 {
1191     const CRYPT_DER_BLOB *a = l, *b = r;
1192     int ret;
1193 
1194     if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1195         ret = a->cbData - b->cbData;
1196     return ret;
1197 }
1198 
1199 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1200  */
CRYPT_DEREncodeSet(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1201 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1202  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1203  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1204 {
1205     const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1206     DWORD bytesNeeded = 0, lenBytes, i;
1207     BOOL ret;
1208 
1209     for (i = 0; i < set->cBlob; i++)
1210         bytesNeeded += set->rgBlob[i].cbData;
1211     CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1212     bytesNeeded += 1 + lenBytes;
1213     if (!pbEncoded)
1214     {
1215         *pcbEncoded = bytesNeeded;
1216         ret = TRUE;
1217     }
1218     else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1219      pbEncoded, pcbEncoded, bytesNeeded)))
1220     {
1221         if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1222             pbEncoded = *(BYTE **)pbEncoded;
1223         qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1224         *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1225         CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1226         pbEncoded += lenBytes;
1227         for (i = 0; i < set->cBlob; i++)
1228         {
1229             memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1230             pbEncoded += set->rgBlob[i].cbData;
1231         }
1232     }
1233     return ret;
1234 }
1235 
1236 struct DERSetDescriptor
1237 {
1238     DWORD                   cItems;
1239     const void             *items;
1240     size_t                  itemSize;
1241     size_t                  itemOffset;
1242     CryptEncodeObjectExFunc encode;
1243 };
1244 
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1245 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1246  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1247  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1248 {
1249     const struct DERSetDescriptor *desc = pvStructInfo;
1250     CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1251     BOOL ret = TRUE;
1252     DWORD i;
1253 
1254     if (desc->cItems)
1255     {
1256         setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1257         if (!setOf.rgBlob)
1258             ret = FALSE;
1259         else
1260         {
1261             setOf.cBlob = desc->cItems;
1262             memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1263         }
1264     }
1265     for (i = 0; ret && i < setOf.cBlob; i++)
1266     {
1267         ret = desc->encode(dwCertEncodingType, lpszStructType,
1268          (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1269          0, NULL, NULL, &setOf.rgBlob[i].cbData);
1270         if (ret)
1271         {
1272             setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1273             if (!setOf.rgBlob[i].pbData)
1274                 ret = FALSE;
1275             else
1276                 ret = desc->encode(dwCertEncodingType, lpszStructType,
1277                  (const BYTE *)desc->items + i * desc->itemSize +
1278                  desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1279                  &setOf.rgBlob[i].cbData);
1280         }
1281         /* Some functions propagate their errors through the size */
1282         if (!ret)
1283             *pcbEncoded = setOf.rgBlob[i].cbData;
1284     }
1285     if (ret)
1286     {
1287         DWORD bytesNeeded = 0, lenBytes;
1288 
1289         for (i = 0; i < setOf.cBlob; i++)
1290             bytesNeeded += setOf.rgBlob[i].cbData;
1291         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1292         bytesNeeded += 1 + lenBytes;
1293         if (!pbEncoded)
1294             *pcbEncoded = bytesNeeded;
1295         else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1296          pbEncoded, pcbEncoded, bytesNeeded)))
1297         {
1298             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1299                 pbEncoded = *(BYTE **)pbEncoded;
1300             qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1301              BLOBComp);
1302             *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1303             CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1304             pbEncoded += lenBytes;
1305             for (i = 0; i < setOf.cBlob; i++)
1306             {
1307                 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1308                  setOf.rgBlob[i].cbData);
1309                 pbEncoded += setOf.rgBlob[i].cbData;
1310             }
1311         }
1312     }
1313     for (i = 0; i < setOf.cBlob; i++)
1314         CryptMemFree(setOf.rgBlob[i].pbData);
1315     CryptMemFree(setOf.rgBlob);
1316     return ret;
1317 }
1318 
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType,const CERT_RDN * rdn,CryptEncodeObjectExFunc nameValueEncodeFunc,BYTE * pbEncoded,DWORD * pcbEncoded)1319 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1320  CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1321  DWORD *pcbEncoded)
1322 {
1323     BOOL ret;
1324     CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1325 
1326     __TRY
1327     {
1328         DWORD i;
1329 
1330         ret = TRUE;
1331         if (rdn->cRDNAttr)
1332         {
1333             setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1334              sizeof(CRYPT_DER_BLOB));
1335             if (!setOf.rgBlob)
1336                 ret = FALSE;
1337             else
1338             {
1339                 setOf.cBlob = rdn->cRDNAttr;
1340                 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1341             }
1342         }
1343         for (i = 0; ret && i < rdn->cRDNAttr; i++)
1344         {
1345             setOf.rgBlob[i].cbData = 0;
1346             ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1347              nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1348             if (ret)
1349             {
1350                 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1351                 if (!setOf.rgBlob[i].pbData)
1352                     ret = FALSE;
1353                 else
1354                     ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1355                      &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1356                      setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1357             }
1358             if (!ret)
1359             {
1360                 /* Have to propagate index of failing character */
1361                 *pcbEncoded = setOf.rgBlob[i].cbData;
1362             }
1363         }
1364         if (ret)
1365             ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1366              pbEncoded, pcbEncoded);
1367         for (i = 0; i < setOf.cBlob; i++)
1368             CryptMemFree(setOf.rgBlob[i].pbData);
1369     }
1370     __EXCEPT_PAGE_FAULT
1371     {
1372         SetLastError(STATUS_ACCESS_VIOLATION);
1373         ret = FALSE;
1374     }
1375     __ENDTRY
1376     CryptMemFree(setOf.rgBlob);
1377     return ret;
1378 }
1379 
1380 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1381  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1382  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1383 
CRYPT_AsnEncodeOrCopyUnicodeNameValue(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1384 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1385  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1386  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1387  DWORD *pcbEncoded)
1388 {
1389     const CERT_NAME_VALUE *value = pvStructInfo;
1390     BOOL ret;
1391 
1392     if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1393         ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1394          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1395     else
1396         ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1397          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1398     return ret;
1399 }
1400 
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1401 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1402  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1403  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1404 {
1405     BOOL ret = TRUE;
1406 
1407     __TRY
1408     {
1409         const CERT_NAME_INFO *info = pvStructInfo;
1410         DWORD bytesNeeded = 0, lenBytes, size, i;
1411 
1412         TRACE("encoding name with %d RDNs\n", info->cRDN);
1413         ret = TRUE;
1414         for (i = 0; ret && i < info->cRDN; i++)
1415         {
1416             ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1417              CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1418             if (ret)
1419                 bytesNeeded += size;
1420             else
1421                 *pcbEncoded = size;
1422         }
1423         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1424         bytesNeeded += 1 + lenBytes;
1425         if (ret)
1426         {
1427             if (!pbEncoded)
1428                 *pcbEncoded = bytesNeeded;
1429             else
1430             {
1431                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1432                  pbEncoded, pcbEncoded, bytesNeeded)))
1433                 {
1434                     BYTE *out;
1435 
1436                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1437                         pbEncoded = *(BYTE **)pbEncoded;
1438                     out = pbEncoded;
1439                     *out++ = ASN_SEQUENCEOF;
1440                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
1441                     out += lenBytes;
1442                     for (i = 0; ret && i < info->cRDN; i++)
1443                     {
1444                         size = bytesNeeded;
1445                         ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1446                          &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1447                          out, &size);
1448                         if (ret)
1449                         {
1450                             out += size;
1451                             bytesNeeded -= size;
1452                         }
1453                         else
1454                             *pcbEncoded = size;
1455                     }
1456                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1457                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
1458                 }
1459             }
1460         }
1461     }
1462     __EXCEPT_PAGE_FAULT
1463     {
1464         SetLastError(STATUS_ACCESS_VIOLATION);
1465         ret = FALSE;
1466     }
1467     __ENDTRY
1468     return ret;
1469 }
1470 
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1471 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1472  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1473  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1474 {
1475     const DWORD *ver = pvStructInfo;
1476     BOOL ret;
1477 
1478     /* CTL_V1 is not encoded */
1479     if (*ver == CTL_V1)
1480     {
1481         *pcbEncoded = 0;
1482         ret = TRUE;
1483     }
1484     else
1485         ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1486          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1487     return ret;
1488 }
1489 
1490 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1491  * if they are empty and the OID is not empty (otherwise omits them.)
1492  */
CRYPT_AsnEncodeCTLSubjectAlgorithm(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1493 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1494  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1495  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1496  DWORD *pcbEncoded)
1497 {
1498     const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1499     BOOL ret;
1500     struct AsnEncodeSequenceItem items[2] = {
1501      { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1502     };
1503     DWORD cItem = 1;
1504 
1505     if (algo->pszObjId)
1506     {
1507         static const BYTE asn1Null[] = { ASN_NULL, 0 };
1508         static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1509          (LPBYTE)asn1Null };
1510 
1511         if (algo->Parameters.cbData)
1512             items[cItem].pvStructInfo = &algo->Parameters;
1513         else
1514             items[cItem].pvStructInfo = &nullBlob;
1515         items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1516         cItem++;
1517     }
1518     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1519      dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1520     return ret;
1521 }
1522 
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY * entry,BYTE * pbEncoded,DWORD * pcbEncoded)1523 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1524  BYTE *pbEncoded, DWORD *pcbEncoded)
1525 {
1526     struct AsnEncodeSequenceItem items[2] = {
1527      { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1528      { &entry->cAttribute,        CRYPT_AsnEncodePKCSAttributes, 0 },
1529     };
1530     BOOL ret;
1531 
1532     ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1533      ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded);
1534     return ret;
1535 }
1536 
1537 struct CTLEntries
1538 {
1539     DWORD      cEntry;
1540     CTL_ENTRY *rgEntry;
1541 };
1542 
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1543 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1544  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1545  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1546 {
1547     BOOL ret;
1548     DWORD bytesNeeded, dataLen, lenBytes, i;
1549     const struct CTLEntries *entries = pvStructInfo;
1550 
1551     ret = TRUE;
1552     for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1553     {
1554         DWORD size;
1555 
1556         ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1557         if (ret)
1558             dataLen += size;
1559     }
1560     if (ret)
1561     {
1562         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1563         bytesNeeded = 1 + lenBytes + dataLen;
1564         if (!pbEncoded)
1565             *pcbEncoded = bytesNeeded;
1566         else
1567         {
1568             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1569              pbEncoded, pcbEncoded, bytesNeeded)))
1570             {
1571                 BYTE *out;
1572 
1573                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1574                     pbEncoded = *(BYTE **)pbEncoded;
1575                 out = pbEncoded;
1576                 *out++ = ASN_SEQUENCEOF;
1577                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1578                 out += lenBytes;
1579                 for (i = 0; ret && i < entries->cEntry; i++)
1580                 {
1581                     DWORD size = dataLen;
1582 
1583                     ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1584                      out, &size);
1585                     out += size;
1586                     dataLen -= size;
1587                 }
1588                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1589                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
1590             }
1591         }
1592     }
1593     return ret;
1594 }
1595 
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1596 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1597  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1598  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1599 {
1600     BOOL ret = FALSE;
1601 
1602     __TRY
1603     {
1604         const CTL_INFO *info = pvStructInfo;
1605         struct AsnEncodeSequenceItem items[9] = {
1606          { &info->dwVersion,        CRYPT_AsnEncodeCTLVersion, 0 },
1607          { &info->SubjectUsage,     CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1608         };
1609         struct AsnConstructedItem constructed = { 0 };
1610         DWORD cItem = 2;
1611 
1612         if (info->ListIdentifier.cbData)
1613         {
1614             items[cItem].pvStructInfo = &info->ListIdentifier;
1615             items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1616             cItem++;
1617         }
1618         if (info->SequenceNumber.cbData)
1619         {
1620             items[cItem].pvStructInfo = &info->SequenceNumber;
1621             items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1622             cItem++;
1623         }
1624         items[cItem].pvStructInfo = &info->ThisUpdate;
1625         items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1626         cItem++;
1627         if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1628         {
1629             items[cItem].pvStructInfo = &info->NextUpdate;
1630             items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1631             cItem++;
1632         }
1633         items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1634         items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1635         cItem++;
1636         if (info->cCTLEntry)
1637         {
1638             items[cItem].pvStructInfo = &info->cCTLEntry;
1639             items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1640             cItem++;
1641         }
1642         if (info->cExtension)
1643         {
1644             constructed.tag = 0;
1645             constructed.pvStructInfo = &info->cExtension;
1646             constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1647             items[cItem].pvStructInfo = &constructed;
1648             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1649             cItem++;
1650         }
1651         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1652          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1653     }
1654     __EXCEPT_PAGE_FAULT
1655     {
1656         SetLastError(STATUS_ACCESS_VIOLATION);
1657     }
1658     __ENDTRY
1659     return ret;
1660 }
1661 
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1662 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1663  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1664  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1665 {
1666     BOOL ret = FALSE;
1667 
1668     __TRY
1669     {
1670         const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1671 
1672         if (!capability->pszObjId)
1673             SetLastError(E_INVALIDARG);
1674         else
1675         {
1676             struct AsnEncodeSequenceItem items[] = {
1677              { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1678              { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1679             };
1680 
1681             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1682              ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1683              pcbEncoded);
1684         }
1685     }
1686     __EXCEPT_PAGE_FAULT
1687     {
1688         SetLastError(STATUS_ACCESS_VIOLATION);
1689     }
1690     __ENDTRY
1691     return ret;
1692 }
1693 
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1694 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1695  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1696  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1697 {
1698     BOOL ret = FALSE;
1699 
1700     __TRY
1701     {
1702         DWORD bytesNeeded, dataLen, lenBytes, i;
1703         const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1704 
1705         ret = TRUE;
1706         for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1707         {
1708             DWORD size;
1709 
1710             ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1711              &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1712             if (ret)
1713                 dataLen += size;
1714         }
1715         if (ret)
1716         {
1717             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1718             bytesNeeded = 1 + lenBytes + dataLen;
1719             if (!pbEncoded)
1720                 *pcbEncoded = bytesNeeded;
1721             else
1722             {
1723                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1724                  pbEncoded, pcbEncoded, bytesNeeded)))
1725                 {
1726                     BYTE *out;
1727 
1728                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1729                         pbEncoded = *(BYTE **)pbEncoded;
1730                     out = pbEncoded;
1731                     *out++ = ASN_SEQUENCEOF;
1732                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
1733                     out += lenBytes;
1734                     for (i = 0; i < capabilities->cCapability; i++)
1735                     {
1736                         DWORD size = dataLen;
1737 
1738                         ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1739                          NULL, &capabilities->rgCapability[i], 0, NULL,
1740                          out, &size);
1741                         out += size;
1742                         dataLen -= size;
1743                     }
1744                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1745                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
1746                 }
1747             }
1748         }
1749     }
1750     __EXCEPT_PAGE_FAULT
1751     {
1752         SetLastError(STATUS_ACCESS_VIOLATION);
1753     }
1754     __ENDTRY
1755     return ret;
1756 }
1757 
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1758 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1759  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1760  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1761 {
1762     const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1763     DWORD bytesNeeded, dataLen, lenBytes, i;
1764     BOOL ret = TRUE;
1765 
1766     for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1767     {
1768         DWORD size;
1769 
1770         ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1771          &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1772         if (ret)
1773             dataLen += size;
1774     }
1775     if (ret)
1776     {
1777         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1778         bytesNeeded = 1 + lenBytes + dataLen;
1779         if (!pbEncoded)
1780             *pcbEncoded = bytesNeeded;
1781         else
1782         {
1783             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1784              pcbEncoded, bytesNeeded)))
1785             {
1786                 BYTE *out;
1787 
1788                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1789                     pbEncoded = *(BYTE **)pbEncoded;
1790                 out = pbEncoded;
1791                 *out++ = ASN_SEQUENCE;
1792                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1793                 out += lenBytes;
1794                 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1795                 {
1796                     DWORD size = dataLen;
1797 
1798                     ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1799                      &noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
1800                     out += size;
1801                     dataLen -= size;
1802                 }
1803                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1804                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
1805             }
1806         }
1807     }
1808     return ret;
1809 }
1810 
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1811 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1812  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1813  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1814 {
1815     const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1816     BOOL ret;
1817     CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1818      { 0, (LPBYTE)noticeRef->pszOrganization } };
1819     struct AsnEncodeSequenceItem items[] = {
1820      { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1821      { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1822     };
1823 
1824     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1825      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1826      pcbEncoded);
1827     return ret;
1828 }
1829 
CRYPT_AsnEncodePolicyQualifierUserNotice(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1830 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1831  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1832  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1833  DWORD *pcbEncoded)
1834 {
1835     BOOL ret = FALSE;
1836 
1837     __TRY
1838     {
1839         const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1840         struct AsnEncodeSequenceItem items[2];
1841         CERT_NAME_VALUE displayTextValue;
1842         DWORD cItem = 0;
1843 
1844         if (notice->pNoticeReference)
1845         {
1846             items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1847             items[cItem].pvStructInfo = notice->pNoticeReference;
1848             cItem++;
1849         }
1850         if (notice->pszDisplayText)
1851         {
1852             displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1853             displayTextValue.Value.cbData = 0;
1854             displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1855             items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1856             items[cItem].pvStructInfo = &displayTextValue;
1857             cItem++;
1858         }
1859         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1860          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1861     }
1862     __EXCEPT_PAGE_FAULT
1863     {
1864         SetLastError(STATUS_ACCESS_VIOLATION);
1865     }
1866     __ENDTRY
1867     return ret;
1868 }
1869 
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1870 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1871  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1872  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1873 {
1874     BOOL ret = FALSE;
1875 
1876     __TRY
1877     {
1878         const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1879 
1880         if (!attr->pszObjId)
1881             SetLastError(E_INVALIDARG);
1882         else
1883         {
1884             struct AsnEncodeSequenceItem items[2] = {
1885              { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1886              { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1887             };
1888 
1889             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1890              ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1891              pcbEncoded);
1892         }
1893     }
1894     __EXCEPT_PAGE_FAULT
1895     {
1896         SetLastError(STATUS_ACCESS_VIOLATION);
1897     }
1898     __ENDTRY
1899     return ret;
1900 }
1901 
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1902 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1903  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1904  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1905 {
1906     BOOL ret = FALSE;
1907 
1908     __TRY
1909     {
1910         const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1911         struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1912          sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1913 
1914         ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1915          &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1916     }
1917     __EXCEPT_PAGE_FAULT
1918     {
1919         SetLastError(STATUS_ACCESS_VIOLATION);
1920     }
1921     __ENDTRY
1922     return ret;
1923 }
1924 
1925 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
CRYPT_AsnEncodePKCSContentInfoInternal(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1926 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1927  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1928  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1929  DWORD *pcbEncoded)
1930 {
1931     const CRYPT_CONTENT_INFO *info = pvStructInfo;
1932     struct AsnEncodeSequenceItem items[2] = {
1933      { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1934      { NULL, NULL, 0 },
1935     };
1936     struct AsnConstructedItem constructed = { 0 };
1937     DWORD cItem = 1;
1938 
1939     if (info->Content.cbData)
1940     {
1941         constructed.tag = 0;
1942         constructed.pvStructInfo = &info->Content;
1943         constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1944         items[cItem].pvStructInfo = &constructed;
1945         items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1946         cItem++;
1947     }
1948     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1949      cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1950 }
1951 
CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA * digestedData,void * pvData,DWORD * pcbData)1952 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1953  void *pvData, DWORD *pcbData)
1954 {
1955     struct AsnEncodeSequenceItem items[] = {
1956      { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1957      { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1958        0 },
1959      { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1960      { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1961     };
1962 
1963     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pvData, pcbData);
1964 }
1965 
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1966 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1967  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1968  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1969 {
1970     BOOL ret = FALSE;
1971 
1972     __TRY
1973     {
1974         const CRYPT_CONTENT_INFO *info = pvStructInfo;
1975 
1976         if (!info->pszObjId)
1977             SetLastError(E_INVALIDARG);
1978         else
1979             ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1980              lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1981              pcbEncoded);
1982     }
1983     __EXCEPT_PAGE_FAULT
1984     {
1985         SetLastError(STATUS_ACCESS_VIOLATION);
1986     }
1987     __ENDTRY
1988     return ret;
1989 }
1990 
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE * value,BYTE tag,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)1991 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1992  BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1993  DWORD *pcbEncoded)
1994 {
1995     BOOL ret = TRUE;
1996     LPCWSTR str = (LPCWSTR)value->Value.pbData;
1997     DWORD bytesNeeded, lenBytes, encodedLen;
1998 
1999     if (value->Value.cbData)
2000         encodedLen = value->Value.cbData / sizeof(WCHAR);
2001     else if (str)
2002         encodedLen = strlenW(str);
2003     else
2004         encodedLen = 0;
2005     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2006     bytesNeeded = 1 + lenBytes + encodedLen;
2007     if (!pbEncoded)
2008         *pcbEncoded = bytesNeeded;
2009     else
2010     {
2011         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2012          pbEncoded, pcbEncoded, bytesNeeded)))
2013         {
2014             DWORD i;
2015 
2016             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2017                 pbEncoded = *(BYTE **)pbEncoded;
2018             *pbEncoded++ = tag;
2019             CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
2020             pbEncoded += lenBytes;
2021             for (i = 0; i < encodedLen; i++)
2022                 *pbEncoded++ = (BYTE)str[i];
2023         }
2024     }
2025     return ret;
2026 }
2027 
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE * value,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2028 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
2029  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2030  DWORD *pcbEncoded)
2031 {
2032     BOOL ret = TRUE;
2033     LPCWSTR str = (LPCWSTR)value->Value.pbData;
2034     DWORD bytesNeeded, lenBytes, encodedLen;
2035 
2036     if (value->Value.cbData)
2037         encodedLen = value->Value.cbData / sizeof(WCHAR);
2038     else if (str)
2039         encodedLen = strlenW(str);
2040     else
2041         encodedLen = 0;
2042     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2043     bytesNeeded = 1 + lenBytes + encodedLen;
2044     if (!pbEncoded)
2045         *pcbEncoded = bytesNeeded;
2046     else
2047     {
2048         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2049          pbEncoded, pcbEncoded, bytesNeeded)))
2050         {
2051             DWORD i;
2052             BYTE *ptr;
2053 
2054             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2055                 ptr = *(BYTE **)pbEncoded;
2056             else
2057                 ptr = pbEncoded;
2058             *ptr++ = ASN_NUMERICSTRING;
2059             CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2060             ptr += lenBytes;
2061             for (i = 0; ret && i < encodedLen; i++)
2062             {
2063                 if (isdigitW(str[i]))
2064                     *ptr++ = (BYTE)str[i];
2065                 else
2066                 {
2067                     *pcbEncoded = i;
2068                     SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2069                     ret = FALSE;
2070                 }
2071             }
2072             if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2073                 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2074         }
2075     }
2076     return ret;
2077 }
2078 
isprintableW(WCHAR wc)2079 static inline BOOL isprintableW(WCHAR wc)
2080 {
2081     return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2082      wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2083      wc == '/' || wc == ':' || wc == '=' || wc == '?';
2084 }
2085 
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE * value,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2086 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2087  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2088  DWORD *pcbEncoded)
2089 {
2090     BOOL ret = TRUE;
2091     LPCWSTR str = (LPCWSTR)value->Value.pbData;
2092     DWORD bytesNeeded, lenBytes, encodedLen;
2093 
2094     if (value->Value.cbData)
2095         encodedLen = value->Value.cbData / sizeof(WCHAR);
2096     else if (str)
2097         encodedLen = strlenW(str);
2098     else
2099         encodedLen = 0;
2100     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2101     bytesNeeded = 1 + lenBytes + encodedLen;
2102     if (!pbEncoded)
2103         *pcbEncoded = bytesNeeded;
2104     else
2105     {
2106         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2107          pbEncoded, pcbEncoded, bytesNeeded)))
2108         {
2109             DWORD i;
2110             BYTE *ptr;
2111 
2112             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2113                 ptr = *(BYTE **)pbEncoded;
2114             else
2115                 ptr = pbEncoded;
2116             *ptr++ = ASN_PRINTABLESTRING;
2117             CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2118             ptr += lenBytes;
2119             for (i = 0; ret && i < encodedLen; i++)
2120             {
2121                 if (isprintableW(str[i]))
2122                     *ptr++ = (BYTE)str[i];
2123                 else
2124                 {
2125                     *pcbEncoded = i;
2126                     SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2127                     ret = FALSE;
2128                 }
2129             }
2130             if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2131                 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2132         }
2133     }
2134     return ret;
2135 }
2136 
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE * value,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2137 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2138  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2139  DWORD *pcbEncoded)
2140 {
2141     BOOL ret = TRUE;
2142     LPCWSTR str = (LPCWSTR)value->Value.pbData;
2143     DWORD bytesNeeded, lenBytes, encodedLen;
2144 
2145     if (value->Value.cbData)
2146         encodedLen = value->Value.cbData / sizeof(WCHAR);
2147     else if (str)
2148         encodedLen = strlenW(str);
2149     else
2150         encodedLen = 0;
2151     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2152     bytesNeeded = 1 + lenBytes + encodedLen;
2153     if (!pbEncoded)
2154         *pcbEncoded = bytesNeeded;
2155     else
2156     {
2157         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2158          pbEncoded, pcbEncoded, bytesNeeded)))
2159         {
2160             DWORD i;
2161             BYTE *ptr;
2162 
2163             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2164                 ptr = *(BYTE **)pbEncoded;
2165             else
2166                 ptr = pbEncoded;
2167             *ptr++ = ASN_IA5STRING;
2168             CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2169             ptr += lenBytes;
2170             for (i = 0; ret && i < encodedLen; i++)
2171             {
2172                 if (str[i] <= 0x7f)
2173                     *ptr++ = (BYTE)str[i];
2174                 else
2175                 {
2176                     *pcbEncoded = i;
2177                     SetLastError(CRYPT_E_INVALID_IA5_STRING);
2178                     ret = FALSE;
2179                 }
2180             }
2181             if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2182                 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2183         }
2184     }
2185     return ret;
2186 }
2187 
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE * value,DWORD dwFlags,const CRYPT_ENCODE_PARA * pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2188 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2189  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2190  DWORD *pcbEncoded)
2191 {
2192     BOOL ret = TRUE;
2193     LPCWSTR str = (LPCWSTR)value->Value.pbData;
2194     DWORD bytesNeeded, lenBytes, strLen;
2195 
2196     /* FIXME: doesn't handle composite characters */
2197     if (value->Value.cbData)
2198         strLen = value->Value.cbData / sizeof(WCHAR);
2199     else if (str)
2200         strLen = strlenW(str);
2201     else
2202         strLen = 0;
2203     CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2204     bytesNeeded = 1 + lenBytes + strLen * 4;
2205     if (!pbEncoded)
2206         *pcbEncoded = bytesNeeded;
2207     else
2208     {
2209         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2210          pbEncoded, pcbEncoded, bytesNeeded)))
2211         {
2212             DWORD i;
2213 
2214             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2215                 pbEncoded = *(BYTE **)pbEncoded;
2216             *pbEncoded++ = ASN_UNIVERSALSTRING;
2217             CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2218             pbEncoded += lenBytes;
2219             for (i = 0; i < strLen; i++)
2220             {
2221                 *pbEncoded++ = 0;
2222                 *pbEncoded++ = 0;
2223                 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2224                 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2225             }
2226         }
2227     }
2228     return ret;
2229 }
2230 
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2231 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2232  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2233  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2234 {
2235     BOOL ret = FALSE;
2236 
2237     __TRY
2238     {
2239         const CERT_NAME_VALUE *value = pvStructInfo;
2240 
2241         switch (value->dwValueType)
2242         {
2243         case CERT_RDN_ANY_TYPE:
2244         case CERT_RDN_ENCODED_BLOB:
2245         case CERT_RDN_OCTET_STRING:
2246             SetLastError(CRYPT_E_NOT_CHAR_STRING);
2247             break;
2248         case CERT_RDN_NUMERIC_STRING:
2249             ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2250              pbEncoded, pcbEncoded);
2251             break;
2252         case CERT_RDN_PRINTABLE_STRING:
2253             ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2254              pbEncoded, pcbEncoded);
2255             break;
2256         case CERT_RDN_TELETEX_STRING:
2257             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2258              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2259             break;
2260         case CERT_RDN_VIDEOTEX_STRING:
2261             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2262              ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2263             break;
2264         case CERT_RDN_IA5_STRING:
2265             ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2266              pbEncoded, pcbEncoded);
2267             break;
2268         case CERT_RDN_GRAPHIC_STRING:
2269             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2270              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2271             break;
2272         case CERT_RDN_VISIBLE_STRING:
2273             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2274              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2275             break;
2276         case CERT_RDN_GENERAL_STRING:
2277             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2278              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2279             break;
2280         case CERT_RDN_UNIVERSAL_STRING:
2281             ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2282              pbEncoded, pcbEncoded);
2283             break;
2284         case CERT_RDN_BMP_STRING:
2285             ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2286              pbEncoded, pcbEncoded);
2287             break;
2288         case CERT_RDN_UTF8_STRING:
2289             ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2290              pbEncoded, pcbEncoded);
2291             break;
2292         default:
2293             SetLastError(CRYPT_E_ASN1_CHOICE);
2294         }
2295     }
2296     __EXCEPT_PAGE_FAULT
2297     {
2298         SetLastError(STATUS_ACCESS_VIOLATION);
2299     }
2300     __ENDTRY
2301     return ret;
2302 }
2303 
CRYPT_AsnEncodeName(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2304 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2305  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2306  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2307 {
2308     BOOL ret;
2309 
2310     __TRY
2311     {
2312         const CERT_NAME_INFO *info = pvStructInfo;
2313         DWORD bytesNeeded = 0, lenBytes, size, i;
2314 
2315         TRACE("encoding name with %d RDNs\n", info->cRDN);
2316         ret = TRUE;
2317         for (i = 0; ret && i < info->cRDN; i++)
2318         {
2319             ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2320              CRYPT_AsnEncodeNameValue, NULL, &size);
2321             if (ret)
2322                 bytesNeeded += size;
2323         }
2324         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2325         bytesNeeded += 1 + lenBytes;
2326         if (ret)
2327         {
2328             if (!pbEncoded)
2329                 *pcbEncoded = bytesNeeded;
2330             else
2331             {
2332                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2333                  pbEncoded, pcbEncoded, bytesNeeded)))
2334                 {
2335                     BYTE *out;
2336 
2337                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2338                         pbEncoded = *(BYTE **)pbEncoded;
2339                     out = pbEncoded;
2340                     *out++ = ASN_SEQUENCEOF;
2341                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2342                     out += lenBytes;
2343                     for (i = 0; ret && i < info->cRDN; i++)
2344                     {
2345                         size = bytesNeeded;
2346                         ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2347                          &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
2348                         if (ret)
2349                         {
2350                             out += size;
2351                             bytesNeeded -= size;
2352                         }
2353                     }
2354                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2355                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
2356                 }
2357             }
2358         }
2359     }
2360     __EXCEPT_PAGE_FAULT
2361     {
2362         SetLastError(STATUS_ACCESS_VIOLATION);
2363         ret = FALSE;
2364     }
2365     __ENDTRY
2366     return ret;
2367 }
2368 
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2369 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2370  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2371  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2372 {
2373     BOOL val = *(const BOOL *)pvStructInfo, ret;
2374 
2375     TRACE("%d\n", val);
2376 
2377     if (!pbEncoded)
2378     {
2379         *pcbEncoded = 3;
2380         ret = TRUE;
2381     }
2382     else if (*pcbEncoded < 3)
2383     {
2384         *pcbEncoded = 3;
2385         SetLastError(ERROR_MORE_DATA);
2386         ret = FALSE;
2387     }
2388     else
2389     {
2390         *pcbEncoded = 3;
2391         *pbEncoded++ = ASN_BOOL;
2392         *pbEncoded++ = 1;
2393         *pbEncoded++ = val ? 0xff : 0;
2394         ret = TRUE;
2395     }
2396     TRACE("returning %d (%08x)\n", ret, GetLastError());
2397     return ret;
2398 }
2399 
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2400 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2401  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2402  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2403 {
2404     const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2405     BOOL ret;
2406     DWORD dataLen;
2407     BYTE tag;
2408 
2409     ret = TRUE;
2410     switch (entry->dwAltNameChoice)
2411     {
2412     case CERT_ALT_NAME_RFC822_NAME:
2413     case CERT_ALT_NAME_DNS_NAME:
2414     case CERT_ALT_NAME_URL:
2415         tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2416         if (entry->u.pwszURL)
2417         {
2418             DWORD i;
2419 
2420             /* Not + 1: don't encode the NULL-terminator */
2421             dataLen = lstrlenW(entry->u.pwszURL);
2422             for (i = 0; ret && i < dataLen; i++)
2423             {
2424                 if (entry->u.pwszURL[i] > 0x7f)
2425                 {
2426                     SetLastError(CRYPT_E_INVALID_IA5_STRING);
2427                     ret = FALSE;
2428                     *pcbEncoded = i;
2429                 }
2430             }
2431         }
2432         else
2433             dataLen = 0;
2434         break;
2435     case CERT_ALT_NAME_DIRECTORY_NAME:
2436         tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2437         dataLen = entry->u.DirectoryName.cbData;
2438         break;
2439     case CERT_ALT_NAME_IP_ADDRESS:
2440         tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2441         dataLen = entry->u.IPAddress.cbData;
2442         break;
2443     case CERT_ALT_NAME_REGISTERED_ID:
2444     {
2445         struct AsnEncodeTagSwappedItem swapped =
2446          { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2447            CRYPT_AsnEncodeOid };
2448 
2449         return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2450          pcbEncoded);
2451     }
2452     case CERT_ALT_NAME_OTHER_NAME:
2453         FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2454         return FALSE;
2455     default:
2456         SetLastError(E_INVALIDARG);
2457         return FALSE;
2458     }
2459     if (ret)
2460     {
2461         DWORD bytesNeeded, lenBytes;
2462 
2463         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2464         bytesNeeded = 1 + dataLen + lenBytes;
2465         if (!pbEncoded)
2466             *pcbEncoded = bytesNeeded;
2467         else if (*pcbEncoded < bytesNeeded)
2468         {
2469             SetLastError(ERROR_MORE_DATA);
2470             *pcbEncoded = bytesNeeded;
2471             ret = FALSE;
2472         }
2473         else
2474         {
2475             *pbEncoded++ = tag;
2476             CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2477             pbEncoded += lenBytes;
2478             switch (entry->dwAltNameChoice)
2479             {
2480             case CERT_ALT_NAME_RFC822_NAME:
2481             case CERT_ALT_NAME_DNS_NAME:
2482             case CERT_ALT_NAME_URL:
2483             {
2484                 DWORD i;
2485 
2486                 for (i = 0; i < dataLen; i++)
2487                     *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2488                 break;
2489             }
2490             case CERT_ALT_NAME_DIRECTORY_NAME:
2491                 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2492                 break;
2493             case CERT_ALT_NAME_IP_ADDRESS:
2494                 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2495                 break;
2496             }
2497             if (ret)
2498                 *pcbEncoded = bytesNeeded;
2499         }
2500     }
2501     TRACE("returning %d (%08x)\n", ret, GetLastError());
2502     return ret;
2503 }
2504 
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2505 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2506  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2507  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2508 {
2509     BOOL ret;
2510 
2511     __TRY
2512     {
2513         const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2514         struct AsnEncodeSequenceItem items[3] = { { 0 } };
2515         struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2516         struct AsnConstructedItem constructed = { 0 };
2517         DWORD cItem = 0, cSwapped = 0;
2518 
2519         if (info->KeyId.cbData)
2520         {
2521             swapped[cSwapped].tag = ASN_CONTEXT | 0;
2522             swapped[cSwapped].pvStructInfo = &info->KeyId;
2523             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2524             items[cItem].pvStructInfo = &swapped[cSwapped];
2525             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2526             cSwapped++;
2527             cItem++;
2528         }
2529         if (info->CertIssuer.cbData)
2530         {
2531             constructed.tag = 1;
2532             constructed.pvStructInfo = &info->CertIssuer;
2533             constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2534             items[cItem].pvStructInfo = &constructed;
2535             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2536             cItem++;
2537         }
2538         if (info->CertSerialNumber.cbData)
2539         {
2540             swapped[cSwapped].tag = ASN_CONTEXT | 2;
2541             swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2542             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2543             items[cItem].pvStructInfo = &swapped[cSwapped];
2544             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2545             cSwapped++;
2546             cItem++;
2547         }
2548         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2549          pEncodePara, pbEncoded, pcbEncoded);
2550     }
2551     __EXCEPT_PAGE_FAULT
2552     {
2553         SetLastError(STATUS_ACCESS_VIOLATION);
2554         ret = FALSE;
2555     }
2556     __ENDTRY
2557     return ret;
2558 }
2559 
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2560 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2561  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2562  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2563 {
2564     BOOL ret;
2565 
2566     __TRY
2567     {
2568         const CERT_ALT_NAME_INFO *info = pvStructInfo;
2569         DWORD bytesNeeded, dataLen, lenBytes, i;
2570 
2571         ret = TRUE;
2572         /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2573          * can't encode an erroneous entry index if it's bigger than this.
2574          */
2575         for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2576         {
2577             DWORD len;
2578 
2579             ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2580              &info->rgAltEntry[i], 0, NULL, NULL, &len);
2581             if (ret)
2582                 dataLen += len;
2583             else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2584             {
2585                 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2586                  * the bad character, now set the index of the bad
2587                  * entry
2588                  */
2589                 *pcbEncoded = (BYTE)i <<
2590                  CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2591             }
2592         }
2593         if (ret)
2594         {
2595             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2596             bytesNeeded = 1 + lenBytes + dataLen;
2597             if (!pbEncoded)
2598             {
2599                 *pcbEncoded = bytesNeeded;
2600                 ret = TRUE;
2601             }
2602             else
2603             {
2604                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2605                  pbEncoded, pcbEncoded, bytesNeeded)))
2606                 {
2607                     BYTE *out;
2608 
2609                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2610                         pbEncoded = *(BYTE **)pbEncoded;
2611                     out = pbEncoded;
2612                     *out++ = ASN_SEQUENCEOF;
2613                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
2614                     out += lenBytes;
2615                     for (i = 0; ret && i < info->cAltEntry; i++)
2616                     {
2617                         DWORD len = dataLen;
2618 
2619                         ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2620                          NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
2621                         if (ret)
2622                         {
2623                             out += len;
2624                             dataLen -= len;
2625                         }
2626                     }
2627                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2628                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
2629                 }
2630             }
2631         }
2632     }
2633     __EXCEPT_PAGE_FAULT
2634     {
2635         SetLastError(STATUS_ACCESS_VIOLATION);
2636         ret = FALSE;
2637     }
2638     __ENDTRY
2639     return ret;
2640 }
2641 
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2642 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2643  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2644  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2645 {
2646     BOOL ret;
2647 
2648     __TRY
2649     {
2650         const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2651         struct AsnEncodeSequenceItem items[3] = { { 0 } };
2652         struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2653         DWORD cItem = 0, cSwapped = 0;
2654 
2655         if (info->KeyId.cbData)
2656         {
2657             swapped[cSwapped].tag = ASN_CONTEXT | 0;
2658             swapped[cSwapped].pvStructInfo = &info->KeyId;
2659             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2660             items[cItem].pvStructInfo = &swapped[cSwapped];
2661             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2662             cSwapped++;
2663             cItem++;
2664         }
2665         if (info->AuthorityCertIssuer.cAltEntry)
2666         {
2667             swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2668             swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2669             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2670             items[cItem].pvStructInfo = &swapped[cSwapped];
2671             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2672             cSwapped++;
2673             cItem++;
2674         }
2675         if (info->AuthorityCertSerialNumber.cbData)
2676         {
2677             swapped[cSwapped].tag = ASN_CONTEXT | 2;
2678             swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2679             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2680             items[cItem].pvStructInfo = &swapped[cSwapped];
2681             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2682             cSwapped++;
2683             cItem++;
2684         }
2685         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2686          pEncodePara, pbEncoded, pcbEncoded);
2687     }
2688     __EXCEPT_PAGE_FAULT
2689     {
2690         SetLastError(STATUS_ACCESS_VIOLATION);
2691         ret = FALSE;
2692     }
2693     __ENDTRY
2694     return ret;
2695 }
2696 
CRYPT_AsnEncodeAccessDescription(const CERT_ACCESS_DESCRIPTION * descr,BYTE * pbEncoded,DWORD * pcbEncoded)2697 static BOOL CRYPT_AsnEncodeAccessDescription(
2698  const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2699 {
2700     struct AsnEncodeSequenceItem items[] = {
2701      { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2702      { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2703     };
2704 
2705     if (!descr->pszAccessMethod)
2706     {
2707         SetLastError(E_INVALIDARG);
2708         return FALSE;
2709     }
2710     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded);
2711 }
2712 
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2713 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2714  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2715  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2716 {
2717     BOOL ret;
2718 
2719     __TRY
2720     {
2721         DWORD bytesNeeded, dataLen, lenBytes, i;
2722         const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2723 
2724         ret = TRUE;
2725         for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2726         {
2727             DWORD size;
2728 
2729             ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2730              &size);
2731             if (ret)
2732                 dataLen += size;
2733         }
2734         if (ret)
2735         {
2736             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2737             bytesNeeded = 1 + lenBytes + dataLen;
2738             if (!pbEncoded)
2739                 *pcbEncoded = bytesNeeded;
2740             else
2741             {
2742                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2743                  pbEncoded, pcbEncoded, bytesNeeded)))
2744                 {
2745                     BYTE *out;
2746 
2747                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2748                         pbEncoded = *(BYTE **)pbEncoded;
2749                     out = pbEncoded;
2750                     *out++ = ASN_SEQUENCEOF;
2751                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
2752                     out += lenBytes;
2753                     for (i = 0; i < info->cAccDescr; i++)
2754                     {
2755                         DWORD size = dataLen;
2756 
2757                         ret = CRYPT_AsnEncodeAccessDescription(
2758                          &info->rgAccDescr[i], out, &size);
2759                         out += size;
2760                         dataLen -= size;
2761                     }
2762                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2763                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
2764                 }
2765             }
2766         }
2767     }
2768     __EXCEPT_PAGE_FAULT
2769     {
2770         SetLastError(STATUS_ACCESS_VIOLATION);
2771         ret = FALSE;
2772     }
2773     __ENDTRY
2774     return ret;
2775 }
2776 
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2777 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2778  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2779  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2780 {
2781     BOOL ret;
2782 
2783     __TRY
2784     {
2785         const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2786         struct AsnEncodeSequenceItem items[3] = {
2787          { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2788          { 0 }
2789         };
2790         DWORD cItem = 1;
2791 
2792         if (info->fPathLenConstraint)
2793         {
2794             items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2795             items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2796             cItem++;
2797         }
2798         if (info->cSubtreesConstraint)
2799         {
2800             items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2801             items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2802             cItem++;
2803         }
2804         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2805          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2806     }
2807     __EXCEPT_PAGE_FAULT
2808     {
2809         SetLastError(STATUS_ACCESS_VIOLATION);
2810         ret = FALSE;
2811     }
2812     __ENDTRY
2813     return ret;
2814 }
2815 
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2816 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2817  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2818  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2819 {
2820     BOOL ret;
2821 
2822     __TRY
2823     {
2824         const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2825         struct AsnEncodeSequenceItem items[2] = { { 0 } };
2826         DWORD cItem = 0;
2827 
2828         if (info->fCA)
2829         {
2830             items[cItem].pvStructInfo = &info->fCA;
2831             items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2832             cItem++;
2833         }
2834         if (info->fPathLenConstraint)
2835         {
2836             items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2837             items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2838             cItem++;
2839         }
2840         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2841          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2842     }
2843     __EXCEPT_PAGE_FAULT
2844     {
2845         SetLastError(STATUS_ACCESS_VIOLATION);
2846         ret = FALSE;
2847     }
2848     __ENDTRY
2849     return ret;
2850 }
2851 
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2852 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2853  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2854  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2855 {
2856     const CERT_POLICY_INFO *info = pvStructInfo;
2857     BOOL ret;
2858 
2859     if (!info->cPolicyQualifier)
2860     {
2861         *pcbEncoded = 0;
2862         ret = TRUE;
2863     }
2864     else
2865     {
2866         struct AsnEncodeSequenceItem items[2] = {
2867          { NULL, CRYPT_AsnEncodeOid, 0 },
2868          { NULL, CRYPT_CopyEncodedBlob, 0 },
2869         };
2870         DWORD bytesNeeded = 0, lenBytes, size, i;
2871 
2872         ret = TRUE;
2873         for (i = 0; ret && i < info->cPolicyQualifier; i++)
2874         {
2875             items[0].pvStructInfo =
2876              info->rgPolicyQualifier[i].pszPolicyQualifierId;
2877             items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2878             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2879              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2880             if (ret)
2881                 bytesNeeded += size;
2882         }
2883         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2884         bytesNeeded += 1 + lenBytes;
2885         if (ret)
2886         {
2887             if (!pbEncoded)
2888                 *pcbEncoded = bytesNeeded;
2889             else
2890             {
2891                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2892                  pbEncoded, pcbEncoded, bytesNeeded)))
2893                 {
2894                     BYTE *out;
2895 
2896                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2897                         pbEncoded = *(BYTE **)pbEncoded;
2898                     out = pbEncoded;
2899                     *out++ = ASN_SEQUENCEOF;
2900                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2901                     out += lenBytes;
2902                     for (i = 0; ret && i < info->cPolicyQualifier; i++)
2903                     {
2904                         items[0].pvStructInfo =
2905                          info->rgPolicyQualifier[i].pszPolicyQualifierId;
2906                         items[1].pvStructInfo =
2907                          &info->rgPolicyQualifier[i].Qualifier;
2908                         size = bytesNeeded;
2909                         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2910                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
2911                         if (ret)
2912                         {
2913                             out += size;
2914                             bytesNeeded -= size;
2915                         }
2916                     }
2917                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2918                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
2919                 }
2920             }
2921         }
2922     }
2923     return ret;
2924 }
2925 
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,const CERT_POLICY_INFO * info,DWORD dwFlags,BYTE * pbEncoded,DWORD * pcbEncoded)2926 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2927  const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2928  DWORD *pcbEncoded)
2929 {
2930     struct AsnEncodeSequenceItem items[2] = {
2931      { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2932      { info,                      CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2933     };
2934     BOOL ret;
2935 
2936     if (!info->pszPolicyIdentifier)
2937     {
2938         SetLastError(E_INVALIDARG);
2939         return FALSE;
2940     }
2941     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded);
2942     return ret;
2943 }
2944 
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)2945 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2946  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2947  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2948 {
2949     BOOL ret = FALSE;
2950 
2951     __TRY
2952     {
2953         const CERT_POLICIES_INFO *info = pvStructInfo;
2954         DWORD bytesNeeded = 0, lenBytes, size, i;
2955 
2956         ret = TRUE;
2957         for (i = 0; ret && i < info->cPolicyInfo; i++)
2958         {
2959             ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2960              &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2961              &size);
2962             if (ret)
2963                 bytesNeeded += size;
2964         }
2965         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2966         bytesNeeded += 1 + lenBytes;
2967         if (ret)
2968         {
2969             if (!pbEncoded)
2970                 *pcbEncoded = bytesNeeded;
2971             else
2972             {
2973                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2974                  pbEncoded, pcbEncoded, bytesNeeded)))
2975                 {
2976                     BYTE *out;
2977 
2978                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2979                         pbEncoded = *(BYTE **)pbEncoded;
2980                     out = pbEncoded;
2981                     *out++ = ASN_SEQUENCEOF;
2982                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2983                     out += lenBytes;
2984                     for (i = 0; ret && i < info->cPolicyInfo; i++)
2985                     {
2986                         size = bytesNeeded;
2987                         ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2988                          &info->rgPolicyInfo[i],
2989                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
2990                         if (ret)
2991                         {
2992                             out += size;
2993                             bytesNeeded -= size;
2994                         }
2995                     }
2996                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2997                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
2998                 }
2999             }
3000         }
3001     }
3002     __EXCEPT_PAGE_FAULT
3003     {
3004         SetLastError(STATUS_ACCESS_VIOLATION);
3005     }
3006     __ENDTRY
3007     return ret;
3008 }
3009 
CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,const CERT_POLICY_MAPPING * mapping,DWORD dwFlags,BYTE * pbEncoded,DWORD * pcbEncoded)3010 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
3011  const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
3012  DWORD *pcbEncoded)
3013 {
3014     struct AsnEncodeSequenceItem items[] = {
3015      { mapping->pszIssuerDomainPolicy,  CRYPT_AsnEncodeOid, 0 },
3016      { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3017     };
3018 
3019     if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
3020     {
3021         SetLastError(E_INVALIDARG);
3022         return FALSE;
3023     }
3024     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded);
3025 }
3026 
CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3027 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
3028  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3029  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3030 {
3031     BOOL ret = FALSE;
3032 
3033     __TRY
3034     {
3035         const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3036         DWORD bytesNeeded = 0, lenBytes, size, i;
3037 
3038         ret = TRUE;
3039         for (i = 0; ret && i < info->cPolicyMapping; i++)
3040         {
3041             ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
3042              &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3043              NULL, &size);
3044             if (ret)
3045                 bytesNeeded += size;
3046         }
3047         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3048         bytesNeeded += 1 + lenBytes;
3049         if (ret)
3050         {
3051             if (!pbEncoded)
3052                 *pcbEncoded = bytesNeeded;
3053             else
3054             {
3055                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3056                  pbEncoded, pcbEncoded, bytesNeeded)))
3057                 {
3058                     BYTE *out;
3059 
3060                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3061                         pbEncoded = *(BYTE **)pbEncoded;
3062                     out = pbEncoded;
3063                     *out++ = ASN_SEQUENCEOF;
3064                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3065                     out += lenBytes;
3066                     for (i = 0; ret && i < info->cPolicyMapping; i++)
3067                     {
3068                         size = bytesNeeded;
3069                         ret = CRYPT_AsnEncodeCertPolicyMapping(
3070                          dwCertEncodingType, &info->rgPolicyMapping[i],
3071                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
3072                         if (ret)
3073                         {
3074                             out += size;
3075                             bytesNeeded -= size;
3076                         }
3077                     }
3078                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3079                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
3080                 }
3081             }
3082         }
3083     }
3084     __EXCEPT_PAGE_FAULT
3085     {
3086         SetLastError(STATUS_ACCESS_VIOLATION);
3087     }
3088     __ENDTRY
3089     return ret;
3090 }
3091 
CRYPT_AsnEncodeCertPolicyConstraints(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3092 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
3093  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3094  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3095  DWORD *pcbEncoded)
3096 {
3097     BOOL ret = FALSE;
3098 
3099     __TRY
3100     {
3101         const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
3102         struct AsnEncodeSequenceItem items[2];
3103         struct AsnEncodeTagSwappedItem swapped[2];
3104         DWORD cItem = 0, cSwapped = 0;
3105 
3106         if (info->fRequireExplicitPolicy)
3107         {
3108             swapped[cSwapped].tag = ASN_CONTEXT | 0;
3109             swapped[cSwapped].pvStructInfo =
3110              &info->dwRequireExplicitPolicySkipCerts;
3111             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3112             items[cItem].pvStructInfo = &swapped[cSwapped];
3113             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3114             cSwapped++;
3115             cItem++;
3116         }
3117         if (info->fInhibitPolicyMapping)
3118         {
3119             swapped[cSwapped].tag = ASN_CONTEXT | 1;
3120             swapped[cSwapped].pvStructInfo =
3121              &info->dwInhibitPolicyMappingSkipCerts;
3122             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3123             items[cItem].pvStructInfo = &swapped[cSwapped];
3124             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3125             cSwapped++;
3126             cItem++;
3127         }
3128         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3129          dwFlags, NULL, pbEncoded, pcbEncoded);
3130     }
3131     __EXCEPT_PAGE_FAULT
3132     {
3133         SetLastError(STATUS_ACCESS_VIOLATION);
3134     }
3135     __ENDTRY
3136     return ret;
3137 }
3138 
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3139 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
3140  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3141  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3142 {
3143     BOOL ret;
3144 
3145     __TRY
3146     {
3147         const BLOBHEADER *hdr = pvStructInfo;
3148 
3149         if (hdr->bType != PUBLICKEYBLOB)
3150         {
3151             SetLastError(E_INVALIDARG);
3152             ret = FALSE;
3153         }
3154         else
3155         {
3156             const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3157              ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3158             CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3159              (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3160             struct AsnEncodeSequenceItem items[] = {
3161              { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3162              { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3163             };
3164 
3165             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3166              ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3167         }
3168     }
3169     __EXCEPT_PAGE_FAULT
3170     {
3171         SetLastError(STATUS_ACCESS_VIOLATION);
3172         ret = FALSE;
3173     }
3174     __ENDTRY
3175     return ret;
3176 }
3177 
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3178 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3179  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3180  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3181 {
3182     BOOL ret;
3183 
3184     __TRY
3185     {
3186         const CRYPT_DATA_BLOB *blob = pvStructInfo;
3187         DWORD bytesNeeded, lenBytes;
3188 
3189         TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3190          dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0);
3191 
3192         CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3193         bytesNeeded = 1 + lenBytes + blob->cbData;
3194         if (!pbEncoded)
3195         {
3196             *pcbEncoded = bytesNeeded;
3197             ret = TRUE;
3198         }
3199         else
3200         {
3201             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3202              pcbEncoded, bytesNeeded)))
3203             {
3204                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3205                     pbEncoded = *(BYTE **)pbEncoded;
3206                 *pbEncoded++ = ASN_OCTETSTRING;
3207                 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3208                 pbEncoded += lenBytes;
3209                 if (blob->cbData)
3210                     memcpy(pbEncoded, blob->pbData, blob->cbData);
3211             }
3212         }
3213     }
3214     __EXCEPT_PAGE_FAULT
3215     {
3216         SetLastError(STATUS_ACCESS_VIOLATION);
3217         ret = FALSE;
3218     }
3219     __ENDTRY
3220     TRACE("returning %d (%08x)\n", ret, GetLastError());
3221     return ret;
3222 }
3223 
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3224 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3225  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3226  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3227 {
3228     BOOL ret;
3229 
3230     __TRY
3231     {
3232         const CRYPT_BIT_BLOB *blob = pvStructInfo;
3233         DWORD bytesNeeded, lenBytes, dataBytes;
3234         BYTE unusedBits;
3235 
3236         /* yep, MS allows cUnusedBits to be >= 8 */
3237         if (!blob->cUnusedBits)
3238         {
3239             dataBytes = blob->cbData;
3240             unusedBits = 0;
3241         }
3242         else if (blob->cbData * 8 > blob->cUnusedBits)
3243         {
3244             dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3245             unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3246              blob->cUnusedBits;
3247         }
3248         else
3249         {
3250             dataBytes = 0;
3251             unusedBits = 0;
3252         }
3253         CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3254         bytesNeeded = 1 + lenBytes + dataBytes + 1;
3255         if (!pbEncoded)
3256         {
3257             *pcbEncoded = bytesNeeded;
3258             ret = TRUE;
3259         }
3260         else
3261         {
3262             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3263              pcbEncoded, bytesNeeded)))
3264             {
3265                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3266                     pbEncoded = *(BYTE **)pbEncoded;
3267                 *pbEncoded++ = ASN_BITSTRING;
3268                 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3269                 pbEncoded += lenBytes;
3270                 *pbEncoded++ = unusedBits;
3271                 if (dataBytes)
3272                 {
3273                     BYTE mask = 0xff << unusedBits;
3274 
3275                     if (dataBytes > 1)
3276                     {
3277                         memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3278                         pbEncoded += dataBytes - 1;
3279                     }
3280                     *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3281                 }
3282             }
3283         }
3284     }
3285     __EXCEPT_PAGE_FAULT
3286     {
3287         SetLastError(STATUS_ACCESS_VIOLATION);
3288         ret = FALSE;
3289     }
3290     __ENDTRY
3291     return ret;
3292 }
3293 
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3294 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3295  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3296  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3297 {
3298     BOOL ret;
3299 
3300     __TRY
3301     {
3302         const CRYPT_BIT_BLOB *blob = pvStructInfo;
3303         CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3304 
3305         ret = TRUE;
3306         if (newBlob.cbData)
3307         {
3308             newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3309             if (newBlob.pbData)
3310             {
3311                 DWORD i;
3312 
3313                 for (i = 0; i < newBlob.cbData; i++)
3314                     newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3315             }
3316             else
3317                 ret = FALSE;
3318         }
3319         if (ret)
3320             ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3321              &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3322         CryptMemFree(newBlob.pbData);
3323     }
3324     __EXCEPT_PAGE_FAULT
3325     {
3326         SetLastError(STATUS_ACCESS_VIOLATION);
3327         ret = FALSE;
3328     }
3329     __ENDTRY
3330     return ret;
3331 }
3332 
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3333 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3334  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3335  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3336 {
3337     CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3338 
3339     return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3340      &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3341 }
3342 
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3343 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3344  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3345  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3346 {
3347     BOOL ret;
3348 
3349     __TRY
3350     {
3351         DWORD significantBytes, lenBytes, bytesNeeded;
3352         BYTE padByte = 0;
3353         BOOL pad = FALSE;
3354         const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3355 
3356         significantBytes = blob->cbData;
3357         if (significantBytes)
3358         {
3359             if (blob->pbData[significantBytes - 1] & 0x80)
3360             {
3361                 /* negative, lop off leading (little-endian) 0xffs */
3362                 for (; significantBytes > 0 &&
3363                  blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3364                     ;
3365                 if (blob->pbData[significantBytes - 1] < 0x80)
3366                 {
3367                     padByte = 0xff;
3368                     pad = TRUE;
3369                 }
3370             }
3371             else
3372             {
3373                 /* positive, lop off leading (little-endian) zeroes */
3374                 for (; significantBytes > 0 &&
3375                  !blob->pbData[significantBytes - 1]; significantBytes--)
3376                     ;
3377                 if (significantBytes == 0)
3378                     significantBytes = 1;
3379                 if (blob->pbData[significantBytes - 1] > 0x7f)
3380                 {
3381                     padByte = 0;
3382                     pad = TRUE;
3383                 }
3384             }
3385         }
3386         if (pad)
3387             CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3388         else
3389             CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3390         bytesNeeded = 1 + lenBytes + significantBytes;
3391         if (pad)
3392             bytesNeeded++;
3393         if (!pbEncoded)
3394         {
3395             *pcbEncoded = bytesNeeded;
3396             ret = TRUE;
3397         }
3398         else
3399         {
3400             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3401              pcbEncoded, bytesNeeded)))
3402             {
3403                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3404                     pbEncoded = *(BYTE **)pbEncoded;
3405                 *pbEncoded++ = ASN_INTEGER;
3406                 if (pad)
3407                 {
3408                     CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3409                     pbEncoded += lenBytes;
3410                     *pbEncoded++ = padByte;
3411                 }
3412                 else
3413                 {
3414                     CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3415                     pbEncoded += lenBytes;
3416                 }
3417                 for (; significantBytes > 0; significantBytes--)
3418                     *(pbEncoded++) = blob->pbData[significantBytes - 1];
3419             }
3420         }
3421     }
3422     __EXCEPT_PAGE_FAULT
3423     {
3424         SetLastError(STATUS_ACCESS_VIOLATION);
3425         ret = FALSE;
3426     }
3427     __ENDTRY
3428     return ret;
3429 }
3430 
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3431 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3432  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3433  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3434 {
3435     BOOL ret;
3436 
3437     __TRY
3438     {
3439         DWORD significantBytes, lenBytes, bytesNeeded;
3440         BOOL pad = FALSE;
3441         const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3442 
3443         significantBytes = blob->cbData;
3444         if (significantBytes)
3445         {
3446             /* positive, lop off leading (little-endian) zeroes */
3447             for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3448              significantBytes--)
3449                 ;
3450             if (significantBytes == 0)
3451                 significantBytes = 1;
3452             if (blob->pbData[significantBytes - 1] > 0x7f)
3453                 pad = TRUE;
3454         }
3455         if (pad)
3456             CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3457         else
3458             CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3459         bytesNeeded = 1 + lenBytes + significantBytes;
3460         if (pad)
3461             bytesNeeded++;
3462         if (!pbEncoded)
3463         {
3464             *pcbEncoded = bytesNeeded;
3465             ret = TRUE;
3466         }
3467         else
3468         {
3469             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3470              pcbEncoded, bytesNeeded)))
3471             {
3472                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3473                     pbEncoded = *(BYTE **)pbEncoded;
3474                 *pbEncoded++ = ASN_INTEGER;
3475                 if (pad)
3476                 {
3477                     CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3478                     pbEncoded += lenBytes;
3479                     *pbEncoded++ = 0;
3480                 }
3481                 else
3482                 {
3483                     CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3484                     pbEncoded += lenBytes;
3485                 }
3486                 for (; significantBytes > 0; significantBytes--)
3487                     *(pbEncoded++) = blob->pbData[significantBytes - 1];
3488             }
3489         }
3490     }
3491     __EXCEPT_PAGE_FAULT
3492     {
3493         SetLastError(STATUS_ACCESS_VIOLATION);
3494         ret = FALSE;
3495     }
3496     __ENDTRY
3497     return ret;
3498 }
3499 
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3500 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3501  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3502  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3503 {
3504     CRYPT_INTEGER_BLOB blob;
3505     BOOL ret;
3506 
3507     /* Encode as an unsigned integer, then change the tag to enumerated */
3508     blob.cbData = sizeof(DWORD);
3509     blob.pbData = (BYTE *)pvStructInfo;
3510     ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3511      X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3512     if (ret && pbEncoded)
3513     {
3514         if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3515             pbEncoded = *(BYTE **)pbEncoded;
3516         pbEncoded[0] = ASN_ENUMERATED;
3517     }
3518     return ret;
3519 }
3520 
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3521 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3522  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3523  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3524 {
3525     BOOL ret;
3526 
3527     __TRY
3528     {
3529         SYSTEMTIME sysTime;
3530         /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ.  I use a
3531          * temporary buffer because the output buffer is not NULL-terminated.
3532          */
3533         static const DWORD bytesNeeded = 15;
3534         char buf[40];
3535 
3536         if (!pbEncoded)
3537         {
3538             *pcbEncoded = bytesNeeded;
3539             ret = TRUE;
3540         }
3541         else
3542         {
3543             /* Sanity check the year, this is a two-digit year format */
3544             ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3545             if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3546             {
3547                 SetLastError(CRYPT_E_BAD_ENCODE);
3548                 ret = FALSE;
3549             }
3550             if (ret)
3551             {
3552                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3553                  pbEncoded, pcbEncoded, bytesNeeded)))
3554                 {
3555                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3556                         pbEncoded = *(BYTE **)pbEncoded;
3557                     buf[0] = ASN_UTCTIME;
3558                     buf[1] = bytesNeeded - 2;
3559                     snprintf(buf + 2, sizeof(buf) - 2,
3560                      "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3561                      sysTime.wYear - 2000 : sysTime.wYear - 1900,
3562                      sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3563                      sysTime.wMinute, sysTime.wSecond);
3564                     memcpy(pbEncoded, buf, bytesNeeded);
3565                 }
3566             }
3567         }
3568     }
3569     __EXCEPT_PAGE_FAULT
3570     {
3571         SetLastError(STATUS_ACCESS_VIOLATION);
3572         ret = FALSE;
3573     }
3574     __ENDTRY
3575     return ret;
3576 }
3577 
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3578 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3579  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3580  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3581 {
3582     BOOL ret;
3583 
3584     __TRY
3585     {
3586         SYSTEMTIME sysTime;
3587         /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ.  I use a
3588          * temporary buffer because the output buffer is not NULL-terminated.
3589          */
3590         static const DWORD bytesNeeded = 17;
3591         char buf[40];
3592 
3593         if (!pbEncoded)
3594         {
3595             *pcbEncoded = bytesNeeded;
3596             ret = TRUE;
3597         }
3598         else
3599         {
3600             ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3601             if (ret)
3602                 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3603                  pcbEncoded, bytesNeeded);
3604             if (ret)
3605             {
3606                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3607                     pbEncoded = *(BYTE **)pbEncoded;
3608                 buf[0] = ASN_GENERALTIME;
3609                 buf[1] = bytesNeeded - 2;
3610                 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3611                  sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3612                  sysTime.wMinute, sysTime.wSecond);
3613                 memcpy(pbEncoded, buf, bytesNeeded);
3614             }
3615         }
3616     }
3617     __EXCEPT_PAGE_FAULT
3618     {
3619         SetLastError(STATUS_ACCESS_VIOLATION);
3620         ret = FALSE;
3621     }
3622     __ENDTRY
3623     return ret;
3624 }
3625 
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3626 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3627  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3628  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3629 {
3630     BOOL ret;
3631 
3632     __TRY
3633     {
3634         SYSTEMTIME sysTime;
3635 
3636         /* Check the year, if it's in the UTCTime range call that encode func */
3637         if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3638             return FALSE;
3639         if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3640             ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3641              pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3642         else
3643             ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3644              lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3645              pcbEncoded);
3646     }
3647     __EXCEPT_PAGE_FAULT
3648     {
3649         SetLastError(STATUS_ACCESS_VIOLATION);
3650         ret = FALSE;
3651     }
3652     __ENDTRY
3653     return ret;
3654 }
3655 
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3656 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3657  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3658  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3659 {
3660     BOOL ret;
3661 
3662     __TRY
3663     {
3664         DWORD bytesNeeded, dataLen, lenBytes, i;
3665         const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3666 
3667         for (i = 0, dataLen = 0; i < seq->cValue; i++)
3668             dataLen += seq->rgValue[i].cbData;
3669         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3670         bytesNeeded = 1 + lenBytes + dataLen;
3671         if (!pbEncoded)
3672         {
3673             *pcbEncoded = bytesNeeded;
3674             ret = TRUE;
3675         }
3676         else
3677         {
3678             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3679              pcbEncoded, bytesNeeded)))
3680             {
3681                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3682                     pbEncoded = *(BYTE **)pbEncoded;
3683                 *pbEncoded++ = ASN_SEQUENCEOF;
3684                 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3685                 pbEncoded += lenBytes;
3686                 for (i = 0; i < seq->cValue; i++)
3687                 {
3688                     memcpy(pbEncoded, seq->rgValue[i].pbData,
3689                      seq->rgValue[i].cbData);
3690                     pbEncoded += seq->rgValue[i].cbData;
3691                 }
3692             }
3693         }
3694     }
3695     __EXCEPT_PAGE_FAULT
3696     {
3697         SetLastError(STATUS_ACCESS_VIOLATION);
3698         ret = FALSE;
3699     }
3700     __ENDTRY
3701     return ret;
3702 }
3703 
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT * distPoint,BYTE * pbEncoded,DWORD * pcbEncoded)3704 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3705  BYTE *pbEncoded, DWORD *pcbEncoded)
3706 {
3707     BOOL ret = TRUE;
3708     struct AsnEncodeSequenceItem items[3] = { { 0 } };
3709     struct AsnConstructedItem constructed = { 0 };
3710     struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3711     DWORD cItem = 0, cSwapped = 0;
3712 
3713     switch (distPoint->DistPointName.dwDistPointNameChoice)
3714     {
3715     case CRL_DIST_POINT_NO_NAME:
3716         /* do nothing */
3717         break;
3718     case CRL_DIST_POINT_FULL_NAME:
3719         swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3720         swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3721         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3722         constructed.tag = 0;
3723         constructed.pvStructInfo = &swapped[cSwapped];
3724         constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3725         items[cItem].pvStructInfo = &constructed;
3726         items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3727         cSwapped++;
3728         cItem++;
3729         break;
3730     case CRL_DIST_POINT_ISSUER_RDN_NAME:
3731         FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3732         ret = FALSE;
3733         break;
3734     default:
3735         ret = FALSE;
3736     }
3737     if (ret && distPoint->ReasonFlags.cbData)
3738     {
3739         swapped[cSwapped].tag = ASN_CONTEXT | 1;
3740         swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3741         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3742         items[cItem].pvStructInfo = &swapped[cSwapped];
3743         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3744         cSwapped++;
3745         cItem++;
3746     }
3747     if (ret && distPoint->CRLIssuer.cAltEntry)
3748     {
3749         swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3750         swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3751         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3752         items[cItem].pvStructInfo = &swapped[cSwapped];
3753         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3754         cSwapped++;
3755         cItem++;
3756     }
3757     if (ret)
3758         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3759          pbEncoded, pcbEncoded);
3760     return ret;
3761 }
3762 
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3763 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3764  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3765  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3766 {
3767     BOOL ret;
3768 
3769     __TRY
3770     {
3771         const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3772 
3773         if (!info->cDistPoint)
3774         {
3775             SetLastError(E_INVALIDARG);
3776             ret = FALSE;
3777         }
3778         else
3779         {
3780             DWORD bytesNeeded, dataLen, lenBytes, i;
3781 
3782             ret = TRUE;
3783             for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3784             {
3785                 DWORD len;
3786 
3787                 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3788                  &len);
3789                 if (ret)
3790                     dataLen += len;
3791                 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3792                 {
3793                     /* Have to propagate index of failing character */
3794                     *pcbEncoded = len;
3795                 }
3796             }
3797             if (ret)
3798             {
3799                 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3800                 bytesNeeded = 1 + lenBytes + dataLen;
3801                 if (!pbEncoded)
3802                 {
3803                     *pcbEncoded = bytesNeeded;
3804                     ret = TRUE;
3805                 }
3806                 else
3807                 {
3808                     if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3809                      pbEncoded, pcbEncoded, bytesNeeded)))
3810                     {
3811                         BYTE *out;
3812 
3813                         if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3814                             pbEncoded = *(BYTE **)pbEncoded;
3815                         out = pbEncoded;
3816                         *out++ = ASN_SEQUENCEOF;
3817                         CRYPT_EncodeLen(dataLen, out, &lenBytes);
3818                         out += lenBytes;
3819                         for (i = 0; ret && i < info->cDistPoint; i++)
3820                         {
3821                             DWORD len = dataLen;
3822 
3823                             ret = CRYPT_AsnEncodeDistPoint(
3824                              &info->rgDistPoint[i], out, &len);
3825                             if (ret)
3826                             {
3827                                 out += len;
3828                                 dataLen -= len;
3829                             }
3830                         }
3831                         if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3832                             CRYPT_FreeSpace(pEncodePara, pbEncoded);
3833                     }
3834                 }
3835             }
3836         }
3837     }
3838     __EXCEPT_PAGE_FAULT
3839     {
3840         SetLastError(STATUS_ACCESS_VIOLATION);
3841         ret = FALSE;
3842     }
3843     __ENDTRY
3844     return ret;
3845 }
3846 
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3847 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3848  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3849  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3850 {
3851     BOOL ret;
3852 
3853     __TRY
3854     {
3855         const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3856         DWORD bytesNeeded = 0, lenBytes, size, i;
3857 
3858         ret = TRUE;
3859         for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3860         {
3861             ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3862              usage->rgpszUsageIdentifier[i],
3863              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3864             if (ret)
3865                 bytesNeeded += size;
3866         }
3867         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3868         bytesNeeded += 1 + lenBytes;
3869         if (ret)
3870         {
3871             if (!pbEncoded)
3872                 *pcbEncoded = bytesNeeded;
3873             else
3874             {
3875                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3876                  pbEncoded, pcbEncoded, bytesNeeded)))
3877                 {
3878                     BYTE *out;
3879 
3880                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3881                         pbEncoded = *(BYTE **)pbEncoded;
3882                     out = pbEncoded;
3883                     *out++ = ASN_SEQUENCEOF;
3884                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3885                     out += lenBytes;
3886                     for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3887                     {
3888                         size = bytesNeeded;
3889                         ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3890                          usage->rgpszUsageIdentifier[i],
3891                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
3892                         if (ret)
3893                         {
3894                             out += size;
3895                             bytesNeeded -= size;
3896                         }
3897                     }
3898                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3899                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
3900                 }
3901             }
3902         }
3903     }
3904     __EXCEPT_PAGE_FAULT
3905     {
3906         SetLastError(STATUS_ACCESS_VIOLATION);
3907         ret = FALSE;
3908     }
3909     __ENDTRY
3910     return ret;
3911 }
3912 
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)3913 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3914  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3915  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3916 {
3917     BOOL ret;
3918 
3919     __TRY
3920     {
3921         const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3922         struct AsnEncodeSequenceItem items[6] = { { 0 } };
3923         struct AsnConstructedItem constructed = { 0 };
3924         struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3925         DWORD cItem = 0, cSwapped = 0;
3926 
3927         ret = TRUE;
3928         switch (point->DistPointName.dwDistPointNameChoice)
3929         {
3930         case CRL_DIST_POINT_NO_NAME:
3931             /* do nothing */
3932             break;
3933         case CRL_DIST_POINT_FULL_NAME:
3934             swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3935             swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3936             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3937             constructed.tag = 0;
3938             constructed.pvStructInfo = &swapped[cSwapped];
3939             constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3940             items[cItem].pvStructInfo = &constructed;
3941             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3942             cSwapped++;
3943             cItem++;
3944             break;
3945         default:
3946             SetLastError(E_INVALIDARG);
3947             ret = FALSE;
3948         }
3949         if (ret && point->fOnlyContainsUserCerts)
3950         {
3951             swapped[cSwapped].tag = ASN_CONTEXT | 1;
3952             swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3953             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3954             items[cItem].pvStructInfo = &swapped[cSwapped];
3955             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3956             cSwapped++;
3957             cItem++;
3958         }
3959         if (ret && point->fOnlyContainsCACerts)
3960         {
3961             swapped[cSwapped].tag = ASN_CONTEXT | 2;
3962             swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3963             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3964             items[cItem].pvStructInfo = &swapped[cSwapped];
3965             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3966             cSwapped++;
3967             cItem++;
3968         }
3969         if (ret && point->OnlySomeReasonFlags.cbData)
3970         {
3971             swapped[cSwapped].tag = ASN_CONTEXT | 3;
3972             swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3973             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3974             items[cItem].pvStructInfo = &swapped[cSwapped];
3975             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3976             cSwapped++;
3977             cItem++;
3978         }
3979         if (ret && point->fIndirectCRL)
3980         {
3981             swapped[cSwapped].tag = ASN_CONTEXT | 4;
3982             swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3983             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3984             items[cItem].pvStructInfo = &swapped[cSwapped];
3985             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3986             cSwapped++;
3987             cItem++;
3988         }
3989         if (ret)
3990             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3991              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3992     }
3993     __EXCEPT_PAGE_FAULT
3994     {
3995         SetLastError(STATUS_ACCESS_VIOLATION);
3996         ret = FALSE;
3997     }
3998     __ENDTRY
3999     return ret;
4000 }
4001 
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)4002 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
4003  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4004  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4005 {
4006     BOOL ret;
4007     const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4008     struct AsnEncodeSequenceItem items[3] = {
4009      { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
4010      { 0 }
4011     };
4012     struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4013     DWORD cItem = 1, cSwapped = 0;
4014 
4015     if (subtree->dwMinimum)
4016     {
4017         swapped[cSwapped].tag = ASN_CONTEXT | 0;
4018         swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
4019         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4020         items[cItem].pvStructInfo = &swapped[cSwapped];
4021         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4022         cSwapped++;
4023         cItem++;
4024     }
4025     if (subtree->fMaximum)
4026     {
4027         swapped[cSwapped].tag = ASN_CONTEXT | 1;
4028         swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
4029         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4030         items[cItem].pvStructInfo = &swapped[cSwapped];
4031         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4032         cSwapped++;
4033         cItem++;
4034     }
4035     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
4036      pEncodePara, pbEncoded, pcbEncoded);
4037     return ret;
4038 }
4039 
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)4040 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
4041  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4042  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4043 {
4044     BOOL ret = FALSE;
4045     CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
4046 
4047     TRACE("%p\n", pvStructInfo);
4048 
4049     __TRY
4050     {
4051         const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
4052         struct AsnEncodeSequenceItem items[2] = { { 0 } };
4053         struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4054         DWORD i, cItem = 0, cSwapped = 0;
4055 
4056         ret = TRUE;
4057         if (constraints->cPermittedSubtree)
4058         {
4059             permitted.rgBlob = CryptMemAlloc(
4060              constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
4061             if (permitted.rgBlob)
4062             {
4063                 permitted.cBlob = constraints->cPermittedSubtree;
4064                 memset(permitted.rgBlob, 0,
4065                  permitted.cBlob * sizeof(CRYPT_DER_BLOB));
4066                 for (i = 0; ret && i < permitted.cBlob; i++)
4067                     ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4068                      NULL, &constraints->rgPermittedSubtree[i],
4069                      CRYPT_ENCODE_ALLOC_FLAG, NULL,
4070                      (BYTE *)&permitted.rgBlob[i].pbData,
4071                      &permitted.rgBlob[i].cbData);
4072                 if (ret)
4073                 {
4074                     swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4075                     swapped[cSwapped].pvStructInfo = &permitted;
4076                     swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4077                     items[cItem].pvStructInfo = &swapped[cSwapped];
4078                     items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4079                     cSwapped++;
4080                     cItem++;
4081                 }
4082             }
4083             else
4084                 ret = FALSE;
4085         }
4086         if (constraints->cExcludedSubtree)
4087         {
4088             excluded.rgBlob = CryptMemAlloc(
4089              constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
4090             if (excluded.rgBlob)
4091             {
4092                 excluded.cBlob = constraints->cExcludedSubtree;
4093                 memset(excluded.rgBlob, 0,
4094                  excluded.cBlob * sizeof(CRYPT_DER_BLOB));
4095                 for (i = 0; ret && i < excluded.cBlob; i++)
4096                     ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4097                      NULL, &constraints->rgExcludedSubtree[i],
4098                      CRYPT_ENCODE_ALLOC_FLAG, NULL,
4099                      (BYTE *)&excluded.rgBlob[i].pbData,
4100                      &excluded.rgBlob[i].cbData);
4101                 if (ret)
4102                 {
4103                     swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4104                     swapped[cSwapped].pvStructInfo = &excluded;
4105                     swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4106                     items[cItem].pvStructInfo = &swapped[cSwapped];
4107                     items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4108                     cSwapped++;
4109                     cItem++;
4110                 }
4111             }
4112             else
4113                 ret = FALSE;
4114         }
4115         if (ret)
4116             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4117              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4118         for (i = 0; i < permitted.cBlob; i++)
4119             LocalFree(permitted.rgBlob[i].pbData);
4120         for (i = 0; i < excluded.cBlob; i++)
4121             LocalFree(excluded.rgBlob[i].pbData);
4122     }
4123     __EXCEPT_PAGE_FAULT
4124     {
4125         SetLastError(STATUS_ACCESS_VIOLATION);
4126     }
4127     __ENDTRY
4128     CryptMemFree(permitted.rgBlob);
4129     CryptMemFree(excluded.rgBlob);
4130     TRACE("returning %d\n", ret);
4131     return ret;
4132 }
4133 
CRYPT_AsnEncodeIssuerSerialNumber(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)4134 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
4135  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
4136  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
4137  DWORD *pcbEncoded)
4138 {
4139     BOOL ret;
4140     const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4141     struct AsnEncodeSequenceItem items[] = {
4142      { &issuerSerial->Issuer,       CRYPT_CopyEncodedBlob, 0 },
4143      { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4144     };
4145 
4146     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4147      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4148     return ret;
4149 }
4150 
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)4151 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
4152  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4153  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4154 {
4155     BOOL ret = FALSE;
4156 
4157     if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4158     {
4159         SetLastError(E_INVALIDARG);
4160         return FALSE;
4161     }
4162 
4163     __TRY
4164     {
4165         const CMSG_SIGNER_INFO *info = pvStructInfo;
4166 
4167         if (!info->Issuer.cbData)
4168             SetLastError(E_INVALIDARG);
4169         else
4170         {
4171             struct AsnEncodeSequenceItem items[7] = {
4172              { &info->dwVersion,     CRYPT_AsnEncodeInt, 0 },
4173              { &info->Issuer,        CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4174              { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4175                0 },
4176             };
4177             struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4178             DWORD cItem = 3, cSwapped = 0;
4179 
4180             if (info->AuthAttrs.cAttr)
4181             {
4182                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4183                 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4184                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4185                 items[cItem].pvStructInfo = &swapped[cSwapped];
4186                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4187                 cSwapped++;
4188                 cItem++;
4189             }
4190             items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4191             items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4192             cItem++;
4193             items[cItem].pvStructInfo = &info->EncryptedHash;
4194             items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4195             cItem++;
4196             if (info->UnauthAttrs.cAttr)
4197             {
4198                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4199                 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4200                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4201                 items[cItem].pvStructInfo = &swapped[cSwapped];
4202                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4203                 cSwapped++;
4204                 cItem++;
4205             }
4206             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4207              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4208         }
4209     }
4210     __EXCEPT_PAGE_FAULT
4211     {
4212         SetLastError(STATUS_ACCESS_VIOLATION);
4213     }
4214     __ENDTRY
4215     return ret;
4216 }
4217 
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)4218 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4219  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4220  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4221 {
4222     BOOL ret = FALSE;
4223 
4224     if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4225     {
4226         SetLastError(E_INVALIDARG);
4227         return FALSE;
4228     }
4229 
4230     __TRY
4231     {
4232         const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4233 
4234         if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4235          info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4236             SetLastError(E_INVALIDARG);
4237         else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4238          !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4239             SetLastError(E_INVALIDARG);
4240         else
4241         {
4242             struct AsnEncodeSequenceItem items[7] = {
4243              { &info->dwVersion,     CRYPT_AsnEncodeInt, 0 },
4244             };
4245             struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4246             DWORD cItem = 1, cSwapped = 0;
4247 
4248             if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4249             {
4250                 items[cItem].pvStructInfo =
4251                  &info->SignerId.u.IssuerSerialNumber.Issuer;
4252                 items[cItem].encodeFunc =
4253                  CRYPT_AsnEncodeIssuerSerialNumber;
4254                 cItem++;
4255             }
4256             else
4257             {
4258                 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4259                 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4260                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4261                 items[cItem].pvStructInfo = &swapped[cSwapped];
4262                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4263                 cSwapped++;
4264                 cItem++;
4265             }
4266             items[cItem].pvStructInfo = &info->HashAlgorithm;
4267             items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4268             cItem++;
4269             if (info->AuthAttrs.cAttr)
4270             {
4271                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4272                 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4273                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4274                 items[cItem].pvStructInfo = &swapped[cSwapped];
4275                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4276                 cSwapped++;
4277                 cItem++;
4278             }
4279             items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4280             items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4281             cItem++;
4282             items[cItem].pvStructInfo = &info->EncryptedHash;
4283             items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4284             cItem++;
4285             if (info->UnauthAttrs.cAttr)
4286             {
4287                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4288                 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4289                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4290                 items[cItem].pvStructInfo = &swapped[cSwapped];
4291                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4292                 cSwapped++;
4293                 cItem++;
4294             }
4295             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4296              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4297         }
4298     }
4299     __EXCEPT_PAGE_FAULT
4300     {
4301         SetLastError(STATUS_ACCESS_VIOLATION);
4302     }
4303     __ENDTRY
4304     return ret;
4305 }
4306 
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO * signedInfo,void * pvData,DWORD * pcbData)4307 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4308  DWORD *pcbData)
4309 {
4310     struct AsnEncodeSequenceItem items[7] = {
4311      { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4312     };
4313     struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4314     struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4315     struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4316     DWORD cItem = 1, cSwapped = 0;
4317     BOOL ret = TRUE;
4318 
4319     if (signedInfo->cSignerInfo)
4320     {
4321         digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4322         digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4323         digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4324         digestAlgorithmsSet.itemOffset =
4325          offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4326         digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4327         items[cItem].pvStructInfo = &digestAlgorithmsSet;
4328         items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4329         cItem++;
4330     }
4331     items[cItem].pvStructInfo = &signedInfo->content;
4332     items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4333     cItem++;
4334     if (signedInfo->cCertEncoded)
4335     {
4336         certSet.cItems = signedInfo->cCertEncoded;
4337         certSet.items = signedInfo->rgCertEncoded;
4338         certSet.itemSize = sizeof(CERT_BLOB);
4339         certSet.itemOffset = 0;
4340         certSet.encode = CRYPT_CopyEncodedBlob;
4341         swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4342         swapped[cSwapped].pvStructInfo = &certSet;
4343         swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4344         items[cItem].pvStructInfo = &swapped[cSwapped];
4345         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4346         cSwapped++;
4347         cItem++;
4348     }
4349     if (signedInfo->cCrlEncoded)
4350     {
4351         crlSet.cItems = signedInfo->cCrlEncoded;
4352         crlSet.items = signedInfo->rgCrlEncoded;
4353         crlSet.itemSize = sizeof(CRL_BLOB);
4354         crlSet.itemOffset = 0;
4355         crlSet.encode = CRYPT_CopyEncodedBlob;
4356         swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4357         swapped[cSwapped].pvStructInfo = &crlSet;
4358         swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4359         items[cItem].pvStructInfo = &swapped[cSwapped];
4360         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4361         cSwapped++;
4362         cItem++;
4363     }
4364     if (ret && signedInfo->cSignerInfo)
4365     {
4366         signerSet.cItems = signedInfo->cSignerInfo;
4367         signerSet.items = signedInfo->rgSignerInfo;
4368         signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4369         signerSet.itemOffset = 0;
4370         signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4371         items[cItem].pvStructInfo = &signerSet;
4372         items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4373         cItem++;
4374     }
4375     if (ret)
4376         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4377          items, cItem, 0, NULL, pvData, pcbData);
4378 
4379     return ret;
4380 }
4381 
CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)4382 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,
4383  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4384  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4385 {
4386     const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
4387     struct AsnEncodeSequenceItem items[] = {
4388      { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4389      { &info->RecipientId.u.IssuerSerialNumber,
4390        CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4391      { &info->KeyEncryptionAlgorithm,
4392        CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4393      { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 },
4394     };
4395 
4396     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4397      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4398 }
4399 
CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,BYTE * pbEncoded,DWORD * pcbEncoded)4400 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,
4401  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4402  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4403 {
4404     const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
4405     struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0,
4406      &info->encryptedContent, CRYPT_AsnEncodeOctets };
4407     struct AsnEncodeSequenceItem items[] = {
4408      { info->contentType, CRYPT_AsnEncodeOid, 0 },
4409      { &info->contentEncryptionAlgorithm,
4410        CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4411      { &swapped, CRYPT_AsnEncodeSwapTag, 0 },
4412     };
4413 
4414     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4415      ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4416 }
4417 
CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA * envelopedData,void * pvData,DWORD * pcbData)4418 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
4419  void *pvData, DWORD *pcbData)
4420 {
4421     struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo,
4422      envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0,
4423      CRYPT_AsnEncodeRecipientInfo };
4424     struct AsnEncodeSequenceItem items[] = {
4425      { &envelopedData->version, CRYPT_AsnEncodeInt, 0 },
4426      { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 },
4427      { &envelopedData->encryptedContentInfo,
4428        CRYPT_AsnEncodeEncryptedContentInfo, 0 },
4429     };
4430 
4431     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
4432      ARRAY_SIZE(items), 0, NULL, pvData, pcbData);
4433 }
4434 
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,LPCSTR lpszStructType)4435 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4436  LPCSTR lpszStructType)
4437 {
4438     CryptEncodeObjectExFunc encodeFunc = NULL;
4439 
4440     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4441      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4442     {
4443         SetLastError(ERROR_FILE_NOT_FOUND);
4444         return NULL;
4445     }
4446 
4447     if (IS_INTOID(lpszStructType))
4448     {
4449         switch (LOWORD(lpszStructType))
4450         {
4451         case LOWORD(X509_CERT):
4452             encodeFunc = CRYPT_AsnEncodeCert;
4453             break;
4454         case LOWORD(X509_CERT_TO_BE_SIGNED):
4455             encodeFunc = CRYPT_AsnEncodeCertInfo;
4456             break;
4457         case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4458             encodeFunc = CRYPT_AsnEncodeCRLInfo;
4459             break;
4460         case LOWORD(X509_EXTENSIONS):
4461             encodeFunc = CRYPT_AsnEncodeExtensions;
4462             break;
4463         case LOWORD(X509_NAME_VALUE):
4464             encodeFunc = CRYPT_AsnEncodeNameValue;
4465             break;
4466         case LOWORD(X509_NAME):
4467             encodeFunc = CRYPT_AsnEncodeName;
4468             break;
4469         case LOWORD(X509_PUBLIC_KEY_INFO):
4470             encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4471             break;
4472         case LOWORD(X509_AUTHORITY_KEY_ID):
4473             encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4474             break;
4475         case LOWORD(X509_ALTERNATE_NAME):
4476             encodeFunc = CRYPT_AsnEncodeAltName;
4477             break;
4478         case LOWORD(X509_BASIC_CONSTRAINTS):
4479             encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4480             break;
4481         case LOWORD(X509_BASIC_CONSTRAINTS2):
4482             encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4483             break;
4484         case LOWORD(X509_CERT_POLICIES):
4485             encodeFunc = CRYPT_AsnEncodeCertPolicies;
4486             break;
4487         case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4488             encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4489             break;
4490         case LOWORD(X509_UNICODE_NAME):
4491             encodeFunc = CRYPT_AsnEncodeUnicodeName;
4492             break;
4493         case LOWORD(PKCS_CONTENT_INFO):
4494             encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4495             break;
4496         case LOWORD(PKCS_ATTRIBUTE):
4497             encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4498             break;
4499         case LOWORD(X509_UNICODE_NAME_VALUE):
4500             encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4501             break;
4502         case LOWORD(X509_OCTET_STRING):
4503             encodeFunc = CRYPT_AsnEncodeOctets;
4504             break;
4505         case LOWORD(X509_BITS):
4506         case LOWORD(X509_KEY_USAGE):
4507             encodeFunc = CRYPT_AsnEncodeBits;
4508             break;
4509         case LOWORD(X509_INTEGER):
4510             encodeFunc = CRYPT_AsnEncodeInt;
4511             break;
4512         case LOWORD(X509_MULTI_BYTE_INTEGER):
4513             encodeFunc = CRYPT_AsnEncodeInteger;
4514             break;
4515         case LOWORD(X509_MULTI_BYTE_UINT):
4516             encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4517             break;
4518         case LOWORD(X509_ENUMERATED):
4519             encodeFunc = CRYPT_AsnEncodeEnumerated;
4520             break;
4521         case LOWORD(X509_CHOICE_OF_TIME):
4522             encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4523             break;
4524         case LOWORD(X509_AUTHORITY_KEY_ID2):
4525             encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4526             break;
4527         case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4528             encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4529             break;
4530         case LOWORD(X509_SEQUENCE_OF_ANY):
4531             encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4532             break;
4533         case LOWORD(PKCS_UTC_TIME):
4534             encodeFunc = CRYPT_AsnEncodeUtcTime;
4535             break;
4536         case LOWORD(X509_CRL_DIST_POINTS):
4537             encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4538             break;
4539         case LOWORD(X509_ENHANCED_KEY_USAGE):
4540             encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4541             break;
4542         case LOWORD(PKCS_CTL):
4543             encodeFunc = CRYPT_AsnEncodeCTL;
4544             break;
4545         case LOWORD(PKCS_SMIME_CAPABILITIES):
4546             encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4547             break;
4548         case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4549             encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4550             break;
4551         case LOWORD(PKCS_ATTRIBUTES):
4552             encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4553             break;
4554         case LOWORD(X509_ISSUING_DIST_POINT):
4555             encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4556             break;
4557         case LOWORD(X509_NAME_CONSTRAINTS):
4558             encodeFunc = CRYPT_AsnEncodeNameConstraints;
4559             break;
4560         case LOWORD(X509_POLICY_MAPPINGS):
4561             encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4562             break;
4563         case LOWORD(X509_POLICY_CONSTRAINTS):
4564             encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4565             break;
4566         case LOWORD(PKCS7_SIGNER_INFO):
4567             encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4568             break;
4569         case LOWORD(CMS_SIGNER_INFO):
4570             encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4571             break;
4572         }
4573     }
4574     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4575         encodeFunc = CRYPT_AsnEncodeExtensions;
4576     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4577         encodeFunc = CRYPT_AsnEncodeUtcTime;
4578     else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4579         encodeFunc = CRYPT_AsnEncodeUtcTime;
4580     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4581         encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4582     else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
4583         encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4584     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4585         encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4586     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4587         encodeFunc = CRYPT_AsnEncodeEnumerated;
4588     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4589         encodeFunc = CRYPT_AsnEncodeBits;
4590     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4591         encodeFunc = CRYPT_AsnEncodeOctets;
4592     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4593         encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4594     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4595         encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4596     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4597         encodeFunc = CRYPT_AsnEncodeAltName;
4598     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4599         encodeFunc = CRYPT_AsnEncodeAltName;
4600     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4601         encodeFunc = CRYPT_AsnEncodeAltName;
4602     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4603         encodeFunc = CRYPT_AsnEncodeAltName;
4604     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4605         encodeFunc = CRYPT_AsnEncodeAltName;
4606     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4607         encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4608     else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4609         encodeFunc = CRYPT_AsnEncodeCertPolicies;
4610     else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
4611         encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4612     else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
4613         encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4614     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4615         encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4616     else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4617         encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4618     else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4619         encodeFunc = CRYPT_AsnEncodeNameConstraints;
4620     else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4621         encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4622     else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4623         encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4624     else if (!strcmp(lpszStructType, szOID_CTL))
4625         encodeFunc = CRYPT_AsnEncodeCTL;
4626     return encodeFunc;
4627 }
4628 
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,LPCSTR lpszStructType,HCRYPTOIDFUNCADDR * hFunc)4629 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4630  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4631 {
4632     static HCRYPTOIDFUNCSET set = NULL;
4633     CryptEncodeObjectFunc encodeFunc = NULL;
4634 
4635     if (!set)
4636         set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4637     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4638      (void **)&encodeFunc, hFunc);
4639     return encodeFunc;
4640 }
4641 
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,LPCSTR lpszStructType,HCRYPTOIDFUNCADDR * hFunc)4642 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4643  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4644 {
4645     static HCRYPTOIDFUNCSET set = NULL;
4646     CryptEncodeObjectExFunc encodeFunc = NULL;
4647 
4648     if (!set)
4649         set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4650     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4651      (void **)&encodeFunc, hFunc);
4652     return encodeFunc;
4653 }
4654 
CryptEncodeObject(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,BYTE * pbEncoded,DWORD * pcbEncoded)4655 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4656  const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4657 {
4658     BOOL ret = FALSE;
4659     HCRYPTOIDFUNCADDR hFunc = NULL;
4660     CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4661     CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4662 
4663     TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4664      debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4665      pcbEncoded);
4666 
4667     if (!pbEncoded && !pcbEncoded)
4668     {
4669         SetLastError(ERROR_INVALID_PARAMETER);
4670         return FALSE;
4671     }
4672 
4673     if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4674      lpszStructType)))
4675     {
4676         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4677          debugstr_a(lpszStructType));
4678         pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4679          lpszStructType, &hFunc);
4680         if (!pCryptEncodeObject)
4681             pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4682              lpszStructType, &hFunc);
4683     }
4684     if (pCryptEncodeObject)
4685         ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4686          pvStructInfo, pbEncoded, pcbEncoded);
4687     else if (pCryptEncodeObjectEx)
4688         ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4689          pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4690     if (hFunc)
4691         CryptFreeOIDFunctionAddress(hFunc, 0);
4692     TRACE_(crypt)("returning %d\n", ret);
4693     return ret;
4694 }
4695 
CryptEncodeObjectEx(DWORD dwCertEncodingType,LPCSTR lpszStructType,const void * pvStructInfo,DWORD dwFlags,PCRYPT_ENCODE_PARA pEncodePara,void * pvEncoded,DWORD * pcbEncoded)4696 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4697  const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4698  void *pvEncoded, DWORD *pcbEncoded)
4699 {
4700     BOOL ret = FALSE;
4701     HCRYPTOIDFUNCADDR hFunc = NULL;
4702     CryptEncodeObjectExFunc encodeFunc = NULL;
4703 
4704     TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4705      debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4706      pvEncoded, pcbEncoded);
4707 
4708     if (!pvEncoded && !pcbEncoded)
4709     {
4710         SetLastError(ERROR_INVALID_PARAMETER);
4711         return FALSE;
4712     }
4713 
4714     SetLastError(NOERROR);
4715     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
4716         if (!pvEncoded) {
4717             SetLastError(ERROR_INVALID_PARAMETER);
4718             return FALSE;
4719         }
4720         *(BYTE **)pvEncoded = NULL;
4721     }
4722     encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4723     if (!encodeFunc)
4724     {
4725         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4726          debugstr_a(lpszStructType));
4727         encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4728          &hFunc);
4729     }
4730     if (encodeFunc)
4731         ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4732          dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4733     else
4734     {
4735         CryptEncodeObjectFunc pCryptEncodeObject =
4736          CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4737 
4738         if (pCryptEncodeObject)
4739         {
4740             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4741             {
4742                 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4743                  pvStructInfo, NULL, pcbEncoded);
4744                 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4745                  pvEncoded, pcbEncoded, *pcbEncoded)))
4746                     ret = pCryptEncodeObject(dwCertEncodingType,
4747                      lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4748                      pcbEncoded);
4749             }
4750             else
4751                 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4752                  pvStructInfo, pvEncoded, pcbEncoded);
4753         }
4754     }
4755     if (hFunc)
4756         CryptFreeOIDFunctionAddress(hFunc, 0);
4757     TRACE_(crypt)("returning %d\n", ret);
4758     return ret;
4759 }
4760 
PFXExportCertStore(HCERTSTORE hStore,CRYPT_DATA_BLOB * pPFX,LPCWSTR szPassword,DWORD dwFlags)4761 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4762  LPCWSTR szPassword, DWORD dwFlags)
4763 {
4764     return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
4765 }
4766 
PFXExportCertStoreEx(HCERTSTORE hStore,CRYPT_DATA_BLOB * pPFX,LPCWSTR szPassword,void * pvReserved,DWORD dwFlags)4767 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4768  LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
4769 {
4770     FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
4771      pvReserved, dwFlags);
4772     return FALSE;
4773 }
4774 
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,DWORD dwKeySpec,DWORD dwCertEncodingType,PCERT_PUBLIC_KEY_INFO pInfo,DWORD * pcbInfo)4775 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4776  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4777 {
4778     return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4779      NULL, 0, NULL, pInfo, pcbInfo);
4780 }
4781 
4782 typedef BOOL (WINAPI *EncodePublicKeyAndParametersFunc)(DWORD dwCertEncodingType,
4783  LPSTR pszPublicKeyObjId, BYTE *pbPubKey, DWORD cbPubKey, DWORD dwFlags, void *pvAuxInfo,
4784  BYTE **ppPublicKey, DWORD *pcbPublicKey, BYTE **ppbParams, DWORD *pcbParams);
4785 
CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,DWORD dwKeySpec,DWORD dwCertEncodingType,LPSTR pszPublicKeyObjId,DWORD dwFlags,void * pvAuxInfo,PCERT_PUBLIC_KEY_INFO pInfo,DWORD * pcbInfo)4786 static BOOL WINAPI CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4787  DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4788  DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4789 {
4790     BOOL ret;
4791     HCRYPTKEY key;
4792     static CHAR rsa_oid[] = szOID_RSA_RSA;
4793 
4794     TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4795      dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4796      pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4797 
4798     if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4799     {
4800         DWORD keySize = 0;
4801 
4802         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4803         if (ret)
4804         {
4805             PUBLICKEYSTRUC *pubKey = CryptMemAlloc(keySize);
4806 
4807             if (pubKey)
4808             {
4809                 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, (BYTE *)pubKey, &keySize);
4810                 if (ret)
4811                 {
4812                     DWORD encodedLen;
4813 
4814                     if (!pszPublicKeyObjId)
4815                     {
4816                         static HCRYPTOIDFUNCSET set;
4817                         EncodePublicKeyAndParametersFunc encodeFunc = NULL;
4818                         HCRYPTOIDFUNCADDR hFunc = NULL;
4819 
4820                         pszPublicKeyObjId = (LPSTR)CertAlgIdToOID(pubKey->aiKeyAlg);
4821                         TRACE("public key algid %#x (%s)\n", pubKey->aiKeyAlg, debugstr_a(pszPublicKeyObjId));
4822 
4823                         if (!set) /* FIXME: there is no a public macro */
4824                             set = CryptInitOIDFunctionSet("CryptDllEncodePublicKeyAndParameters", 0);
4825 
4826                         CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId, 0, (void **)&encodeFunc, &hFunc);
4827                         if (encodeFunc)
4828                         {
4829                             BYTE *key_data = NULL;
4830                             DWORD key_size = 0;
4831                             BYTE *params = NULL;
4832                             DWORD params_size = 0;
4833 
4834                             ret = encodeFunc(dwCertEncodingType, pszPublicKeyObjId, (BYTE *)pubKey, keySize,
4835                                              dwFlags, pvAuxInfo, &key_data, &key_size, &params, &params_size);
4836                             if (ret)
4837                             {
4838                                 DWORD oid_size = strlen(pszPublicKeyObjId) + 1;
4839                                 DWORD size_needed = sizeof(*pInfo) + oid_size + key_size + params_size;
4840 
4841                                 if (!pInfo)
4842                                     *pcbInfo = size_needed;
4843                                 else if (*pcbInfo < size_needed)
4844                                 {
4845                                     *pcbInfo = size_needed;
4846                                     SetLastError(ERROR_MORE_DATA);
4847                                     ret = FALSE;
4848                                 }
4849                                 else
4850                                 {
4851                                     *pcbInfo = size_needed;
4852                                     pInfo->Algorithm.pszObjId = (char *)(pInfo + 1);
4853                                     lstrcpyA(pInfo->Algorithm.pszObjId, pszPublicKeyObjId);
4854                                     if (params)
4855                                     {
4856                                         pInfo->Algorithm.Parameters.cbData = params_size;
4857                                         pInfo->Algorithm.Parameters.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size;
4858                                         memcpy(pInfo->Algorithm.Parameters.pbData, params, params_size);
4859                                     }
4860                                     else
4861                                     {
4862                                         pInfo->Algorithm.Parameters.cbData = 0;
4863                                         pInfo->Algorithm.Parameters.pbData = NULL;
4864                                     }
4865                                     pInfo->PublicKey.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size + params_size;
4866                                     pInfo->PublicKey.cbData = key_size;
4867                                     memcpy(pInfo->PublicKey.pbData, key_data, key_size);
4868                                     pInfo->PublicKey.cUnusedBits = 0;
4869                                 }
4870 
4871                                 CryptMemFree(key_data);
4872                                 CryptMemFree(params);
4873                             }
4874 
4875                             CryptMemFree(pubKey);
4876                             CryptFreeOIDFunctionAddress(hFunc, 0);
4877                             return ret;
4878                         }
4879 
4880                         /* fallback to RSA */
4881                         pszPublicKeyObjId = rsa_oid;
4882                     }
4883 
4884                     encodedLen = 0;
4885                     ret = CryptEncodeObject(dwCertEncodingType,
4886                      RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4887                     if (ret)
4888                     {
4889                         DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4890                          strlen(pszPublicKeyObjId) + 1 + encodedLen;
4891 
4892                         if (!pInfo)
4893                             *pcbInfo = sizeNeeded;
4894                         else if (*pcbInfo < sizeNeeded)
4895                         {
4896                             SetLastError(ERROR_MORE_DATA);
4897                             *pcbInfo = sizeNeeded;
4898                             ret = FALSE;
4899                         }
4900                         else
4901                         {
4902                             *pcbInfo = sizeNeeded;
4903                             pInfo->Algorithm.pszObjId = (char *)pInfo +
4904                              sizeof(CERT_PUBLIC_KEY_INFO);
4905                             lstrcpyA(pInfo->Algorithm.pszObjId,
4906                              pszPublicKeyObjId);
4907                             pInfo->Algorithm.Parameters.cbData = 0;
4908                             pInfo->Algorithm.Parameters.pbData = NULL;
4909                             pInfo->PublicKey.pbData =
4910                              (BYTE *)pInfo->Algorithm.pszObjId
4911                              + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4912                             pInfo->PublicKey.cbData = encodedLen;
4913                             pInfo->PublicKey.cUnusedBits = 0;
4914                             ret = CryptEncodeObject(dwCertEncodingType,
4915                              RSA_CSP_PUBLICKEYBLOB, pubKey,
4916                              pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4917                         }
4918                     }
4919                 }
4920                 CryptMemFree(pubKey);
4921             }
4922             else
4923                 ret = FALSE;
4924         }
4925         CryptDestroyKey(key);
4926     }
4927     return ret;
4928 }
4929 
4930 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4931  DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4932  DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4933 
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,DWORD dwKeySpec,DWORD dwCertEncodingType,LPSTR pszPublicKeyObjId,DWORD dwFlags,void * pvAuxInfo,PCERT_PUBLIC_KEY_INFO pInfo,DWORD * pcbInfo)4934 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4935  DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4936  void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4937 {
4938     static HCRYPTOIDFUNCSET set = NULL;
4939     BOOL ret;
4940     ExportPublicKeyInfoExFunc exportFunc = NULL;
4941     HCRYPTOIDFUNCADDR hFunc = NULL;
4942 
4943     TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4944      dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4945      pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4946 
4947     if (!hCryptProv)
4948     {
4949         SetLastError(ERROR_INVALID_PARAMETER);
4950         return FALSE;
4951     }
4952 
4953     if (pszPublicKeyObjId)
4954     {
4955         if (!set)
4956             set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4957              0);
4958         CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4959          0, (void **)&exportFunc, &hFunc);
4960     }
4961     if (!exportFunc)
4962         exportFunc = CRYPT_ExportPublicKeyInfoEx;
4963     ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4964      pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4965     if (hFunc)
4966         CryptFreeOIDFunctionAddress(hFunc, 0);
4967     return ret;
4968 }
4969 
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,DWORD dwCertEncodingType,PCERT_PUBLIC_KEY_INFO pInfo,HCRYPTKEY * phKey)4970 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4971  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4972 {
4973     return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4974      0, 0, NULL, phKey);
4975 }
4976 
4977 typedef BOOL (WINAPI *ConvertPublicKeyInfoFunc)(DWORD dwCertEncodingType,
4978  PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, DWORD dwFlags,
4979  BYTE **ppbData, DWORD *dwDataLen);
4980 
CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,DWORD dwCertEncodingType,PCERT_PUBLIC_KEY_INFO pInfo,ALG_ID aiKeyAlg,DWORD dwFlags,void * pvAuxInfo,HCRYPTKEY * phKey)4981 static BOOL WINAPI CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4982  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4983  DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4984 {
4985     static HCRYPTOIDFUNCSET set = NULL;
4986     ConvertPublicKeyInfoFunc convertFunc = NULL;
4987     HCRYPTOIDFUNCADDR hFunc = NULL;
4988     BOOL ret;
4989     DWORD pubKeySize;
4990     LPBYTE pubKey;
4991 
4992     TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4993      dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4994 
4995     if (!set)
4996         set = CryptInitOIDFunctionSet(CRYPT_OID_CONVERT_PUBLIC_KEY_INFO_FUNC, 0);
4997     CryptGetOIDFunctionAddress(set, dwCertEncodingType, pInfo->Algorithm.pszObjId,
4998                                0, (void **)&convertFunc, &hFunc);
4999     if (convertFunc)
5000     {
5001         pubKey = NULL;
5002         pubKeySize = 0;
5003         ret = convertFunc(dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, &pubKey, &pubKeySize);
5004         if (ret)
5005         {
5006             ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, phKey);
5007             CryptMemFree(pubKey);
5008         }
5009 
5010         CryptFreeOIDFunctionAddress(hFunc, 0);
5011         return ret;
5012     }
5013 
5014     ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5015      pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
5016     if (ret)
5017     {
5018         pubKey = CryptMemAlloc(pubKeySize);
5019 
5020         if (pubKey)
5021         {
5022             ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5023              pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
5024              &pubKeySize);
5025             if (ret)
5026             {
5027                 if(aiKeyAlg)
5028                   ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
5029                 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
5030                  phKey);
5031             }
5032             CryptMemFree(pubKey);
5033         }
5034         else
5035             ret = FALSE;
5036     }
5037     return ret;
5038 }
5039 
5040 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5041  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5042  DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
5043 
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,DWORD dwCertEncodingType,PCERT_PUBLIC_KEY_INFO pInfo,ALG_ID aiKeyAlg,DWORD dwFlags,void * pvAuxInfo,HCRYPTKEY * phKey)5044 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5045  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5046  DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5047 {
5048     static HCRYPTOIDFUNCSET set = NULL;
5049     BOOL ret;
5050     ImportPublicKeyInfoExFunc importFunc = NULL;
5051     HCRYPTOIDFUNCADDR hFunc = NULL;
5052 
5053     TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
5054      dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5055 
5056     if (!set)
5057         set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
5058     CryptGetOIDFunctionAddress(set, dwCertEncodingType,
5059      pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
5060     if (!importFunc)
5061         importFunc = CRYPT_ImportPublicKeyInfoEx;
5062     ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
5063      pvAuxInfo, phKey);
5064     if (hFunc)
5065         CryptFreeOIDFunctionAddress(hFunc, 0);
5066     return ret;
5067 }
5068