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

Last change on this file since 21916 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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