source: trunk/src/crypt32/encode.c@ 21351

Last change on this file since 21351 was 21311, checked in by vladest, 16 years ago

Added CRYPT32 and MSCMS APIs support

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