ReactOS  0.4.13-dev-39-g8b6696f
encode.c
Go to the documentation of this file.
1 /*
2  * Copyright 2005-2008 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * This file implements ASN.1 DER encoding of a limited set of types.
19  * It isn't a full ASN.1 implementation. Microsoft implements BER
20  * encoding of many of the basic types in msasn1.dll, but that interface isn't
21  * implemented, so I implement them here.
22  *
23  * References:
24  * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25  * (available online, look for a PDF copy as the HTML versions tend to have
26  * translation errors.)
27  *
28  * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
29  *
30  * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
31  */
32 
33 #include "config.h"
34 #include "wine/port.h"
35 
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 
41 #define NONAMELESSUNION
42 
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "snmp.h"
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
51 
54 
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
56  BYTE *, DWORD *);
57 
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59  * The dwCertEncodingType and lpszStructType are ignored by the built-in
60  * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61  * since it must call functions in external DLLs that follow these signatures.
62  */
64  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
67  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
70  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
73  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
76  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
79  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
82  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
85  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
88  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
91  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
94  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
97  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
100  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
102 
104  BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
105 {
106  BOOL ret = TRUE;
107 
109  {
110  if (pEncodePara && pEncodePara->pfnAlloc)
111  *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
112  else
113  *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
114  if (!*(BYTE **)pbEncoded)
115  ret = FALSE;
116  else
117  *pcbEncoded = bytesNeeded;
118  }
119  else if (bytesNeeded > *pcbEncoded)
120  {
121  *pcbEncoded = bytesNeeded;
123  ret = FALSE;
124  }
125  else
126  *pcbEncoded = bytesNeeded;
127  return ret;
128 }
129 
130 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
131 {
132  if (pEncodePara && pEncodePara->pfnFree)
133  pEncodePara->pfnFree(pv);
134  else
135  LocalFree(pv);
136 }
137 
139 {
140  DWORD bytesNeeded, significantBytes = 0;
141 
142  if (len <= 0x7f)
143  bytesNeeded = 1;
144  else
145  {
146  DWORD temp;
147 
148  for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
149  temp <<= 8, significantBytes--)
150  ;
151  bytesNeeded = significantBytes + 1;
152  }
153  if (!pbEncoded)
154  {
155  *pcbEncoded = bytesNeeded;
156  return TRUE;
157  }
158  if (*pcbEncoded < bytesNeeded)
159  {
161  return FALSE;
162  }
163  if (len <= 0x7f)
164  *pbEncoded = (BYTE)len;
165  else
166  {
167  DWORD i;
168 
169  *pbEncoded++ = significantBytes | 0x80;
170  for (i = 0; i < significantBytes; i++)
171  {
172  *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
173  len >>= 8;
174  }
175  }
176  *pcbEncoded = bytesNeeded;
177  return TRUE;
178 }
179 
181  struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
183 {
184  BOOL ret;
185  DWORD i, dataLen = 0;
186 
187  TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
188  pbEncoded, pbEncoded ? *pcbEncoded : 0);
189  for (i = 0, ret = TRUE; ret && i < cItem; i++)
190  {
191  ret = items[i].encodeFunc(dwCertEncodingType, NULL,
192  items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
193  NULL, &items[i].size);
194  /* Some functions propagate their errors through the size */
195  if (!ret)
196  *pcbEncoded = items[i].size;
197  dataLen += items[i].size;
198  }
199  if (ret)
200  {
201  DWORD lenBytes, bytesNeeded;
202 
203  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
204  bytesNeeded = 1 + lenBytes + dataLen;
205  if (!pbEncoded)
206  *pcbEncoded = bytesNeeded;
207  else
208  {
209  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
210  pcbEncoded, bytesNeeded)))
211  {
212  BYTE *out;
213 
215  pbEncoded = *(BYTE **)pbEncoded;
216  out = pbEncoded;
217  *out++ = ASN_SEQUENCE;
218  CRYPT_EncodeLen(dataLen, out, &lenBytes);
219  out += lenBytes;
220  for (i = 0; ret && i < cItem; i++)
221  {
222  ret = items[i].encodeFunc(dwCertEncodingType, NULL,
223  items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
224  NULL, out, &items[i].size);
225  /* Some functions propagate their errors through the size */
226  if (!ret)
227  *pcbEncoded = items[i].size;
228  out += items[i].size;
229  }
230  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
231  CRYPT_FreeSpace(pEncodePara, pbEncoded);
232  }
233  }
234  }
235  TRACE("returning %d (%08x)\n", ret, GetLastError());
236  return ret;
237 }
238 
240  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
242 {
243  BOOL ret;
244  const struct AsnConstructedItem *item = pvStructInfo;
245  DWORD len;
246 
247  if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
248  item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
249  {
250  DWORD dataLen, bytesNeeded;
251 
252  CRYPT_EncodeLen(len, NULL, &dataLen);
253  bytesNeeded = 1 + dataLen + len;
254  if (!pbEncoded)
255  *pcbEncoded = bytesNeeded;
256  else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
257  pbEncoded, pcbEncoded, bytesNeeded)))
258  {
259  BYTE *out;
260 
262  pbEncoded = *(BYTE **)pbEncoded;
263  out = pbEncoded;
264  *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
265  CRYPT_EncodeLen(len, out, &dataLen);
266  out += dataLen;
267  ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
268  item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
269  out, &len);
270  if (!ret)
271  {
272  /* Some functions propagate their errors through the size */
273  *pcbEncoded = len;
275  CRYPT_FreeSpace(pEncodePara, pbEncoded);
276  }
277  }
278  }
279  else
280  {
281  /* Some functions propagate their errors through the size */
282  *pcbEncoded = len;
283  }
284  return ret;
285 }
286 
288 {
290  const void *pvStructInfo;
292 };
293 
294 /* Sort of a wacky hack, it encodes something using the struct
295  * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
296  * given in the struct AsnEncodeTagSwappedItem.
297  */
299  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
301 {
302  BOOL ret;
303  const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
304 
305  ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
306  item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
307  if (ret && pbEncoded)
308  *pbEncoded = item->tag;
309  return ret;
310 }
311 
313  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
315 {
316  const DWORD *ver = pvStructInfo;
317  BOOL ret;
318 
319  /* CERT_V1 is not encoded */
320  if (*ver == CERT_V1)
321  {
322  *pcbEncoded = 0;
323  ret = TRUE;
324  }
325  else
326  {
327  struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
328 
330  &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
331  }
332  return ret;
333 }
334 
336  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
338 {
340  BOOL ret;
341 
342  if (!pbEncoded)
343  {
344  *pcbEncoded = blob->cbData;
345  ret = TRUE;
346  }
347  else
348  {
349  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
350  pcbEncoded, blob->cbData)))
351  {
353  pbEncoded = *(BYTE **)pbEncoded;
354  if (blob->cbData)
355  memcpy(pbEncoded, blob->pbData, blob->cbData);
356  *pcbEncoded = blob->cbData;
357  }
358  }
359  return ret;
360 }
361 
363  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
365 {
366  BOOL ret;
367  /* This has two filetimes in a row, a NotBefore and a NotAfter */
368  const FILETIME *timePtr = pvStructInfo;
369  struct AsnEncodeSequenceItem items[] = {
370  { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
371  { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
372  };
373 
375  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
376  pcbEncoded);
377  return ret;
378 }
379 
380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
381  * if they are empty.
382  */
384  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
386  DWORD *pcbEncoded)
387 {
389  static const BYTE asn1Null[] = { ASN_NULL, 0 };
390  static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
391  (LPBYTE)asn1Null };
392  BOOL ret;
393  struct AsnEncodeSequenceItem items[2] = {
394  { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
395  { NULL, CRYPT_CopyEncodedBlob, 0 },
396  };
397 
398  if (algo->Parameters.cbData)
399  items[1].pvStructInfo = &algo->Parameters;
400  else
401  items[1].pvStructInfo = &nullBlob;
403  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
404  pcbEncoded);
405  return ret;
406 }
407 
409  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
411 {
413  BOOL ret;
414  struct AsnEncodeSequenceItem items[] = {
415  { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
416  { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
417  };
418 
420  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
421  pcbEncoded);
422  return ret;
423 }
424 
426  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
428 {
429  BOOL ret;
430 
431  __TRY
432  {
434  struct AsnEncodeSequenceItem items[] = {
436  { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
437  };
438 
439  TRACE("Encoding public key with OID %s\n",
440  debugstr_a(info->Algorithm.pszObjId));
442  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
443  pcbEncoded);
444  }
446  {
448  ret = FALSE;
449  }
450  __ENDTRY
451  return ret;
452 }
453 
455  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
457 {
458  BOOL ret;
459 
460  __TRY
461  {
463  struct AsnEncodeSequenceItem items[] = {
464  { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
465  { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
466  { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
467  };
468 
470  items[2].encodeFunc = CRYPT_AsnEncodeBits;
472  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
473  pcbEncoded);
474  }
476  {
478  ret = FALSE;
479  }
480  __ENDTRY
481  return ret;
482 }
483 
485  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
487 {
488  BOOL ret;
490  struct AsnEncodeSequenceItem items[] = {
491  { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
492  { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
493  };
494 
495  TRACE("Encoding public key with OID %s\n",
496  debugstr_a(info->Algorithm.pszObjId));
498  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
499  pcbEncoded);
500  return ret;
501 }
502 
503 /* Like in Windows, this blithely ignores the validity of the passed-in
504  * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
505  * decode properly, see CRYPT_AsnDecodeCertInfo.
506  */
508  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
510 {
511  BOOL ret;
512 
513  __TRY
514  {
515  const CERT_INFO *info = pvStructInfo;
516  struct AsnEncodeSequenceItem items[10] = {
517  { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
518  { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
519  { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
520  { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
521  { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
522  { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
523  { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 },
524  { 0 }
525  };
526  struct AsnConstructedItem constructed = { 0 };
527  struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
528  DWORD cItem = 7, cSwapped = 0;
529 
530  if (info->IssuerUniqueId.cbData)
531  {
532  swapped[cSwapped].tag = ASN_CONTEXT | 1;
533  swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId;
534  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
535  items[cItem].pvStructInfo = &swapped[cSwapped];
536  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
537  cSwapped++;
538  cItem++;
539  }
540  if (info->SubjectUniqueId.cbData)
541  {
542  swapped[cSwapped].tag = ASN_CONTEXT | 2;
543  swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId;
544  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
545  items[cItem].pvStructInfo = &swapped[cSwapped];
546  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
547  cSwapped++;
548  cItem++;
549  }
550  if (info->cExtension)
551  {
552  constructed.tag = 3;
553  constructed.pvStructInfo = &info->cExtension;
555  items[cItem].pvStructInfo = &constructed;
556  items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
557  cItem++;
558  }
559 
561  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
562  }
564  {
566  ret = FALSE;
567  }
568  __ENDTRY
569  return ret;
570 }
571 
574 {
575  struct AsnEncodeSequenceItem items[3] = {
576  { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
577  { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
578  { 0 }
579  };
580  DWORD cItem = 2;
581  BOOL ret;
582 
583  TRACE("%p, %p, %d\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0);
584 
585  if (entry->cExtension)
586  {
587  items[cItem].pvStructInfo = &entry->cExtension;
588  items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
589  cItem++;
590  }
591 
594 
595  TRACE("returning %d (%08x)\n", ret, GetLastError());
596  return ret;
597 }
598 
600  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
602 {
603  DWORD bytesNeeded, dataLen, lenBytes, i;
604  const CRL_INFO *info = pvStructInfo;
605  const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
606  BOOL ret = TRUE;
607 
608  for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
609  {
610  DWORD size;
611 
612  ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
613  if (ret)
614  dataLen += size;
615  }
616  if (ret)
617  {
618  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
619  bytesNeeded = 1 + lenBytes + dataLen;
620  if (!pbEncoded)
621  *pcbEncoded = bytesNeeded;
622  else
623  {
624  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
625  pcbEncoded, bytesNeeded)))
626  {
627  BYTE *out;
628 
630  pbEncoded = *(BYTE **)pbEncoded;
631  out = pbEncoded;
632  *out++ = ASN_SEQUENCEOF;
633  CRYPT_EncodeLen(dataLen, out, &lenBytes);
634  out += lenBytes;
635  for (i = 0; i < info->cCRLEntry; i++)
636  {
637  DWORD size = dataLen;
638 
639  ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
640  out += size;
641  dataLen -= size;
642  }
643  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
644  CRYPT_FreeSpace(pEncodePara, pbEncoded);
645  }
646  }
647  }
648  return ret;
649 }
650 
652  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
654 {
655  const DWORD *ver = pvStructInfo;
656  BOOL ret;
657 
658  /* CRL_V1 is not encoded */
659  if (*ver == CRL_V1)
660  {
661  *pcbEncoded = 0;
662  ret = TRUE;
663  }
664  else
666  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
667  return ret;
668 }
669 
670 /* Like in Windows, this blithely ignores the validity of the passed-in
671  * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
672  * decode properly, see CRYPT_AsnDecodeCRLInfo.
673  */
675  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
677 {
678  BOOL ret;
679 
680  __TRY
681  {
682  const CRL_INFO *info = pvStructInfo;
683  struct AsnEncodeSequenceItem items[7] = {
684  { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
685  { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
686  { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
687  { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
688  { 0 }
689  };
690  struct AsnConstructedItem constructed[1] = { { 0 } };
691  DWORD cItem = 4, cConstructed = 0;
692 
693  if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
694  {
695  items[cItem].pvStructInfo = &info->NextUpdate;
696  items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
697  cItem++;
698  }
699  if (info->cCRLEntry)
700  {
701  items[cItem].pvStructInfo = info;
702  items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
703  cItem++;
704  }
705  if (info->cExtension)
706  {
707  constructed[cConstructed].tag = 0;
708  constructed[cConstructed].pvStructInfo = &info->cExtension;
709  constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
710  items[cItem].pvStructInfo = &constructed[cConstructed];
711  items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
712  cConstructed++;
713  cItem++;
714  }
715 
717  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
718  }
720  {
722  ret = FALSE;
723  }
724  __ENDTRY
725  return ret;
726 }
727 
729  DWORD *pcbEncoded)
730 {
731  BOOL ret;
732  struct AsnEncodeSequenceItem items[3] = {
733  { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
734  { NULL, NULL, 0 },
735  { NULL, NULL, 0 },
736  };
737  DWORD cItem = 1;
738 
739  TRACE("%p, %p, %d\n", ext, pbEncoded, pbEncoded ? *pcbEncoded : 0);
740 
741  if (ext->fCritical)
742  {
743  items[cItem].pvStructInfo = &ext->fCritical;
744  items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
745  cItem++;
746  }
747  items[cItem].pvStructInfo = &ext->Value;
748  items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
749  cItem++;
750 
753  TRACE("returning %d (%08x)\n", ret, GetLastError());
754  return ret;
755 }
756 
758  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
760 {
761  BOOL ret;
762 
763  __TRY
764  {
765  DWORD bytesNeeded, dataLen, lenBytes, i;
767 
768  ret = TRUE;
769  for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
770  {
771  DWORD size;
772 
773  ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
774  if (ret)
775  dataLen += size;
776  }
777  if (ret)
778  {
779  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
780  bytesNeeded = 1 + lenBytes + dataLen;
781  if (!pbEncoded)
782  *pcbEncoded = bytesNeeded;
783  else
784  {
785  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
786  pbEncoded, pcbEncoded, bytesNeeded)))
787  {
788  BYTE *out;
789 
791  pbEncoded = *(BYTE **)pbEncoded;
792  out = pbEncoded;
793  *out++ = ASN_SEQUENCEOF;
794  CRYPT_EncodeLen(dataLen, out, &lenBytes);
795  out += lenBytes;
796  for (i = 0; i < exts->cExtension; i++)
797  {
798  DWORD size = dataLen;
799 
800  ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
801  out, &size);
802  out += size;
803  dataLen -= size;
804  }
805  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
806  CRYPT_FreeSpace(pEncodePara, pbEncoded);
807  }
808  }
809  }
810  }
812  {
814  ret = FALSE;
815  }
816  __ENDTRY
817  return ret;
818 }
819 
821  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
823 {
824  LPCSTR pszObjId = pvStructInfo;
825  DWORD bytesNeeded = 0, lenBytes;
826  BOOL ret = TRUE;
827  int firstPos = 0;
828  BYTE firstByte = 0;
829 
830  TRACE("%s\n", debugstr_a(pszObjId));
831 
832  if (pszObjId)
833  {
834  const char *ptr;
835  int val1, val2;
836 
837  if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
838  {
840  return FALSE;
841  }
842  bytesNeeded++;
843  firstByte = val1 * 40 + val2;
844  ptr = pszObjId + firstPos;
845  if (*ptr == '.')
846  {
847  ptr++;
848  firstPos++;
849  }
850  while (ret && *ptr)
851  {
852  int pos;
853 
854  /* note I assume each component is at most 32-bits long in base 2 */
855  if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
856  {
857  if (val1 >= 0x10000000)
858  bytesNeeded += 5;
859  else if (val1 >= 0x200000)
860  bytesNeeded += 4;
861  else if (val1 >= 0x4000)
862  bytesNeeded += 3;
863  else if (val1 >= 0x80)
864  bytesNeeded += 2;
865  else
866  bytesNeeded += 1;
867  ptr += pos;
868  if (*ptr == '.')
869  ptr++;
870  }
871  else
872  {
874  return FALSE;
875  }
876  }
877  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
878  }
879  else
880  lenBytes = 1;
881  bytesNeeded += 1 + lenBytes;
882  if (pbEncoded)
883  {
884  if (*pcbEncoded < bytesNeeded)
885  {
887  ret = FALSE;
888  }
889  else
890  {
892  CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
893  pbEncoded += lenBytes;
894  if (pszObjId)
895  {
896  const char *ptr;
897  int val, pos;
898 
899  *pbEncoded++ = firstByte;
900  ptr = pszObjId + firstPos;
901  while (ret && *ptr)
902  {
903  sscanf(ptr, "%d%n", &val, &pos);
904  {
905  unsigned char outBytes[5];
906  int numBytes, i;
907 
908  if (val >= 0x10000000)
909  numBytes = 5;
910  else if (val >= 0x200000)
911  numBytes = 4;
912  else if (val >= 0x4000)
913  numBytes = 3;
914  else if (val >= 0x80)
915  numBytes = 2;
916  else
917  numBytes = 1;
918  for (i = numBytes; i > 0; i--)
919  {
920  outBytes[i - 1] = val & 0x7f;
921  val >>= 7;
922  }
923  for (i = 0; i < numBytes - 1; i++)
924  *pbEncoded++ = outBytes[i] | 0x80;
925  *pbEncoded++ = outBytes[i];
926  ptr += pos;
927  if (*ptr == '.')
928  ptr++;
929  }
930  }
931  }
932  }
933  }
934  *pcbEncoded = bytesNeeded;
935  return ret;
936 }
937 
939  BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
940  DWORD *pcbEncoded)
941 {
942  BOOL ret = TRUE;
943  LPCSTR str = (LPCSTR)value->Value.pbData;
944  DWORD bytesNeeded, lenBytes, encodedLen;
945 
946  encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
947  CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
948  bytesNeeded = 1 + lenBytes + encodedLen;
949  if (!pbEncoded)
950  *pcbEncoded = bytesNeeded;
951  else
952  {
953  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
954  pbEncoded, pcbEncoded, bytesNeeded)))
955  {
957  pbEncoded = *(BYTE **)pbEncoded;
958  *pbEncoded++ = tag;
959  CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
960  pbEncoded += lenBytes;
961  memcpy(pbEncoded, str, encodedLen);
962  }
963  }
964  return ret;
965 }
966 
968  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
969  DWORD *pcbEncoded)
970 {
971  BOOL ret = TRUE;
972  LPCWSTR str = (LPCWSTR)value->Value.pbData;
973  DWORD bytesNeeded, lenBytes, strLen;
974 
975  if (value->Value.cbData)
976  strLen = value->Value.cbData / sizeof(WCHAR);
977  else if (value->Value.pbData)
978  strLen = lstrlenW(str);
979  else
980  strLen = 0;
981  CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
982  bytesNeeded = 1 + lenBytes + strLen * 2;
983  if (!pbEncoded)
984  *pcbEncoded = bytesNeeded;
985  else
986  {
987  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
988  pbEncoded, pcbEncoded, bytesNeeded)))
989  {
990  DWORD i;
991 
993  pbEncoded = *(BYTE **)pbEncoded;
995  CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
996  pbEncoded += lenBytes;
997  for (i = 0; i < strLen; i++)
998  {
999  *pbEncoded++ = (str[i] & 0xff00) >> 8;
1000  *pbEncoded++ = str[i] & 0x00ff;
1001  }
1002  }
1003  }
1004  return ret;
1005 }
1006 
1008  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1009  DWORD *pcbEncoded)
1010 {
1011  BOOL ret = TRUE;
1012  LPCWSTR str = (LPCWSTR)value->Value.pbData;
1013  DWORD bytesNeeded, lenBytes, encodedLen, strLen;
1014 
1015  if (value->Value.cbData)
1016  strLen = value->Value.cbData / sizeof(WCHAR);
1017  else if (str)
1018  strLen = strlenW(str);
1019  else
1020  strLen = 0;
1021  encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
1022  NULL);
1023  CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1024  bytesNeeded = 1 + lenBytes + encodedLen;
1025  if (!pbEncoded)
1026  *pcbEncoded = bytesNeeded;
1027  else
1028  {
1029  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1030  pbEncoded, pcbEncoded, bytesNeeded)))
1031  {
1033  pbEncoded = *(BYTE **)pbEncoded;
1035  CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1036  pbEncoded += lenBytes;
1038  bytesNeeded - lenBytes - 1, NULL, NULL);
1039  }
1040  }
1041  return ret;
1042 }
1043 
1045  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1047 {
1048  BOOL ret = TRUE;
1049 
1050  __TRY
1051  {
1053 
1054  switch (value->dwValueType)
1055  {
1056  case CERT_RDN_ANY_TYPE:
1057  /* explicitly disallowed */
1059  ret = FALSE;
1060  break;
1061  case CERT_RDN_ENCODED_BLOB:
1063  &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1064  break;
1065  case CERT_RDN_OCTET_STRING:
1067  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1068  break;
1071  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1072  break;
1075  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1076  break;
1079  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1080  break;
1084  break;
1085  case CERT_RDN_IA5_STRING:
1087  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1088  break;
1091  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1092  break;
1095  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1096  break;
1099  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1100  break;
1102  FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1104  ret = FALSE;
1105  break;
1106  case CERT_RDN_BMP_STRING:
1107  ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1109  break;
1110  case CERT_RDN_UTF8_STRING:
1111  ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1113  break;
1114  default:
1116  ret = FALSE;
1117  }
1118  }
1120  {
1122  ret = FALSE;
1123  }
1124  __ENDTRY
1125  return ret;
1126 }
1127 
1129  const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1131 {
1132  DWORD bytesNeeded = 0, lenBytes, size;
1133  BOOL ret;
1134 
1136  0, NULL, NULL, &size);
1137  if (ret)
1138  {
1139  bytesNeeded += size;
1140  /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1141  * with dwValueType, so "cast" it to get its encoded size
1142  */
1143  ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1144  0, NULL, NULL, &size);
1145  if (ret)
1146  {
1147  bytesNeeded += size;
1148  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1149  bytesNeeded += 1 + lenBytes;
1150  if (pbEncoded)
1151  {
1152  if (*pcbEncoded < bytesNeeded)
1153  {
1155  ret = FALSE;
1156  }
1157  else
1158  {
1159  *pbEncoded++ = ASN_SEQUENCE;
1160  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1161  &lenBytes);
1162  pbEncoded += lenBytes;
1163  size = bytesNeeded - 1 - lenBytes;
1165  attr->pszObjId, 0, NULL, pbEncoded, &size);
1166  if (ret)
1167  {
1168  pbEncoded += size;
1169  size = bytesNeeded - 1 - lenBytes - size;
1170  ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1171  &attr->dwValueType, 0, NULL, pbEncoded, &size);
1172  if (!ret)
1173  *pcbEncoded = size;
1174  }
1175  }
1176  }
1177  if (ret)
1178  *pcbEncoded = bytesNeeded;
1179  }
1180  else
1181  {
1182  /* Have to propagate index of failing character */
1183  *pcbEncoded = size;
1184  }
1185  }
1186  return ret;
1187 }
1188 
1189 static int BLOBComp(const void *l, const void *r)
1190 {
1191  const CRYPT_DER_BLOB *a = l, *b = r;
1192  int ret;
1193 
1194  if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1195  ret = a->cbData - b->cbData;
1196  return ret;
1197 }
1198 
1199 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1200  */
1202  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1204 {
1206  DWORD bytesNeeded = 0, lenBytes, i;
1207  BOOL ret;
1208 
1209  for (i = 0; i < set->cBlob; i++)
1210  bytesNeeded += set->rgBlob[i].cbData;
1211  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1212  bytesNeeded += 1 + lenBytes;
1213  if (!pbEncoded)
1214  {
1215  *pcbEncoded = bytesNeeded;
1216  ret = TRUE;
1217  }
1218  else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1219  pbEncoded, pcbEncoded, bytesNeeded)))
1220  {
1222  pbEncoded = *(BYTE **)pbEncoded;
1223  qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1225  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1226  pbEncoded += lenBytes;
1227  for (i = 0; i < set->cBlob; i++)
1228  {
1229  memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1230  pbEncoded += set->rgBlob[i].cbData;
1231  }
1232  }
1233  return ret;
1234 }
1235 
1237 {
1239  const void *items;
1240  size_t itemSize;
1241  size_t itemOffset;
1243 };
1244 
1246  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1248 {
1249  const struct DERSetDescriptor *desc = pvStructInfo;
1250  CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1251  BOOL ret = TRUE;
1252  DWORD i;
1253 
1254  if (desc->cItems)
1255  {
1256  setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1257  if (!setOf.rgBlob)
1258  ret = FALSE;
1259  else
1260  {
1261  setOf.cBlob = desc->cItems;
1262  memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1263  }
1264  }
1265  for (i = 0; ret && i < setOf.cBlob; i++)
1266  {
1267  ret = desc->encode(dwCertEncodingType, lpszStructType,
1268  (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1269  0, NULL, NULL, &setOf.rgBlob[i].cbData);
1270  if (ret)
1271  {
1272  setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1273  if (!setOf.rgBlob[i].pbData)
1274  ret = FALSE;
1275  else
1276  ret = desc->encode(dwCertEncodingType, lpszStructType,
1277  (const BYTE *)desc->items + i * desc->itemSize +
1278  desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1279  &setOf.rgBlob[i].cbData);
1280  }
1281  /* Some functions propagate their errors through the size */
1282  if (!ret)
1283  *pcbEncoded = setOf.rgBlob[i].cbData;
1284  }
1285  if (ret)
1286  {
1287  DWORD bytesNeeded = 0, lenBytes;
1288 
1289  for (i = 0; i < setOf.cBlob; i++)
1290  bytesNeeded += setOf.rgBlob[i].cbData;
1291  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1292  bytesNeeded += 1 + lenBytes;
1293  if (!pbEncoded)
1294  *pcbEncoded = bytesNeeded;
1295  else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1296  pbEncoded, pcbEncoded, bytesNeeded)))
1297  {
1299  pbEncoded = *(BYTE **)pbEncoded;
1300  qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1301  BLOBComp);
1303  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1304  pbEncoded += lenBytes;
1305  for (i = 0; i < setOf.cBlob; i++)
1306  {
1307  memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1308  setOf.rgBlob[i].cbData);
1309  pbEncoded += setOf.rgBlob[i].cbData;
1310  }
1311  }
1312  }
1313  for (i = 0; i < setOf.cBlob; i++)
1314  CryptMemFree(setOf.rgBlob[i].pbData);
1315  CryptMemFree(setOf.rgBlob);
1316  return ret;
1317 }
1318 
1320  CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1321  DWORD *pcbEncoded)
1322 {
1323  BOOL ret;
1324  CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1325 
1326  __TRY
1327  {
1328  DWORD i;
1329 
1330  ret = TRUE;
1331  if (rdn->cRDNAttr)
1332  {
1333  setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1334  sizeof(CRYPT_DER_BLOB));
1335  if (!setOf.rgBlob)
1336  ret = FALSE;
1337  else
1338  {
1339  setOf.cBlob = rdn->cRDNAttr;
1340  memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1341  }
1342  }
1343  for (i = 0; ret && i < rdn->cRDNAttr; i++)
1344  {
1345  setOf.rgBlob[i].cbData = 0;
1347  nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1348  if (ret)
1349  {
1350  setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1351  if (!setOf.rgBlob[i].pbData)
1352  ret = FALSE;
1353  else
1355  &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1356  setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1357  }
1358  if (!ret)
1359  {
1360  /* Have to propagate index of failing character */
1361  *pcbEncoded = setOf.rgBlob[i].cbData;
1362  }
1363  }
1364  if (ret)
1367  for (i = 0; i < setOf.cBlob; i++)
1368  CryptMemFree(setOf.rgBlob[i].pbData);
1369  }
1371  {
1373  ret = FALSE;
1374  }
1375  __ENDTRY
1376  CryptMemFree(setOf.rgBlob);
1377  return ret;
1378 }
1379 
1381  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1383 
1385  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1387  DWORD *pcbEncoded)
1388 {
1389  const CERT_NAME_VALUE *value = pvStructInfo;
1390  BOOL ret;
1391 
1392  if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1394  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1395  else
1397  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1398  return ret;
1399 }
1400 
1402  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1404 {
1405  BOOL ret = TRUE;
1406 
1407  __TRY
1408  {
1409  const CERT_NAME_INFO *info = pvStructInfo;
1410  DWORD bytesNeeded = 0, lenBytes, size, i;
1411 
1412  TRACE("encoding name with %d RDNs\n", info->cRDN);
1413  ret = TRUE;
1414  for (i = 0; ret && i < info->cRDN; i++)
1415  {
1418  if (ret)
1419  bytesNeeded += size;
1420  else
1421  *pcbEncoded = size;
1422  }
1423  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1424  bytesNeeded += 1 + lenBytes;
1425  if (ret)
1426  {
1427  if (!pbEncoded)
1428  *pcbEncoded = bytesNeeded;
1429  else
1430  {
1431  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1432  pbEncoded, pcbEncoded, bytesNeeded)))
1433  {
1434  BYTE *out;
1435 
1437  pbEncoded = *(BYTE **)pbEncoded;
1438  out = pbEncoded;
1439  *out++ = ASN_SEQUENCEOF;
1440  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
1441  out += lenBytes;
1442  for (i = 0; ret && i < info->cRDN; i++)
1443  {
1444  size = bytesNeeded;
1447  out, &size);
1448  if (ret)
1449  {
1450  out += size;
1451  bytesNeeded -= size;
1452  }
1453  else
1454  *pcbEncoded = size;
1455  }
1456  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1457  CRYPT_FreeSpace(pEncodePara, pbEncoded);
1458  }
1459  }
1460  }
1461  }
1463  {
1465  ret = FALSE;
1466  }
1467  __ENDTRY
1468  return ret;
1469 }
1470 
1472  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1474 {
1475  const DWORD *ver = pvStructInfo;
1476  BOOL ret;
1477 
1478  /* CTL_V1 is not encoded */
1479  if (*ver == CTL_V1)
1480  {
1481  *pcbEncoded = 0;
1482  ret = TRUE;
1483  }
1484  else
1486  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1487  return ret;
1488 }
1489 
1490 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1491  * if they are empty and the OID is not empty (otherwise omits them.)
1492  */
1494  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1496  DWORD *pcbEncoded)
1497 {
1498  const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1499  BOOL ret;
1500  struct AsnEncodeSequenceItem items[2] = {
1501  { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1502  };
1503  DWORD cItem = 1;
1504 
1505  if (algo->pszObjId)
1506  {
1507  static const BYTE asn1Null[] = { ASN_NULL, 0 };
1508  static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1509  (LPBYTE)asn1Null };
1510 
1511  if (algo->Parameters.cbData)
1512  items[cItem].pvStructInfo = &algo->Parameters;
1513  else
1514  items[cItem].pvStructInfo = &nullBlob;
1515  items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1516  cItem++;
1517  }
1519  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1520  return ret;
1521 }
1522 
1525 {
1526  struct AsnEncodeSequenceItem items[2] = {
1527  { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1528  { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1529  };
1530  BOOL ret;
1531 
1534  return ret;
1535 }
1536 
1538 {
1541 };
1542 
1544  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1546 {
1547  BOOL ret;
1548  DWORD bytesNeeded, dataLen, lenBytes, i;
1549  const struct CTLEntries *entries = pvStructInfo;
1550 
1551  ret = TRUE;
1552  for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1553  {
1554  DWORD size;
1555 
1556  ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1557  if (ret)
1558  dataLen += size;
1559  }
1560  if (ret)
1561  {
1562  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1563  bytesNeeded = 1 + lenBytes + dataLen;
1564  if (!pbEncoded)
1565  *pcbEncoded = bytesNeeded;
1566  else
1567  {
1568  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1569  pbEncoded, pcbEncoded, bytesNeeded)))
1570  {
1571  BYTE *out;
1572 
1574  pbEncoded = *(BYTE **)pbEncoded;
1575  out = pbEncoded;
1576  *out++ = ASN_SEQUENCEOF;
1577  CRYPT_EncodeLen(dataLen, out, &lenBytes);
1578  out += lenBytes;
1579  for (i = 0; ret && i < entries->cEntry; i++)
1580  {
1581  DWORD size = dataLen;
1582 
1583  ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1584  out, &size);
1585  out += size;
1586  dataLen -= size;
1587  }
1588  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1589  CRYPT_FreeSpace(pEncodePara, pbEncoded);
1590  }
1591  }
1592  }
1593  return ret;
1594 }
1595 
1597  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1599 {
1600  BOOL ret = FALSE;
1601 
1602  __TRY
1603  {
1604  const CTL_INFO *info = pvStructInfo;
1605  struct AsnEncodeSequenceItem items[9] = {
1606  { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1607  { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1608  };
1609  struct AsnConstructedItem constructed = { 0 };
1610  DWORD cItem = 2;
1611 
1612  if (info->ListIdentifier.cbData)
1613  {
1614  items[cItem].pvStructInfo = &info->ListIdentifier;
1615  items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1616  cItem++;
1617  }
1618  if (info->SequenceNumber.cbData)
1619  {
1620  items[cItem].pvStructInfo = &info->SequenceNumber;
1621  items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1622  cItem++;
1623  }
1624  items[cItem].pvStructInfo = &info->ThisUpdate;
1625  items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1626  cItem++;
1627  if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1628  {
1629  items[cItem].pvStructInfo = &info->NextUpdate;
1630  items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1631  cItem++;
1632  }
1633  items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1634  items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1635  cItem++;
1636  if (info->cCTLEntry)
1637  {
1638  items[cItem].pvStructInfo = &info->cCTLEntry;
1639  items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1640  cItem++;
1641  }
1642  if (info->cExtension)
1643  {
1644  constructed.tag = 0;
1645  constructed.pvStructInfo = &info->cExtension;
1646  constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1647  items[cItem].pvStructInfo = &constructed;
1648  items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1649  cItem++;
1650  }
1652  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1653  }
1655  {
1657  }
1658  __ENDTRY
1659  return ret;
1660 }
1661 
1663  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1665 {
1666  BOOL ret = FALSE;
1667 
1668  __TRY
1669  {
1670  const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1671 
1672  if (!capability->pszObjId)
1674  else
1675  {
1676  struct AsnEncodeSequenceItem items[] = {
1677  { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1678  { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1679  };
1680 
1682  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1683  pcbEncoded);
1684  }
1685  }
1687  {
1689  }
1690  __ENDTRY
1691  return ret;
1692 }
1693 
1695  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1697 {
1698  BOOL ret = FALSE;
1699 
1700  __TRY
1701  {
1702  DWORD bytesNeeded, dataLen, lenBytes, i;
1703  const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1704 
1705  ret = TRUE;
1706  for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1707  {
1708  DWORD size;
1709 
1711  &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1712  if (ret)
1713  dataLen += size;
1714  }
1715  if (ret)
1716  {
1717  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1718  bytesNeeded = 1 + lenBytes + dataLen;
1719  if (!pbEncoded)
1720  *pcbEncoded = bytesNeeded;
1721  else
1722  {
1723  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1724  pbEncoded, pcbEncoded, bytesNeeded)))
1725  {
1726  BYTE *out;
1727 
1729  pbEncoded = *(BYTE **)pbEncoded;
1730  out = pbEncoded;
1731  *out++ = ASN_SEQUENCEOF;
1732  CRYPT_EncodeLen(dataLen, out, &lenBytes);
1733  out += lenBytes;
1734  for (i = 0; i < capabilities->cCapability; i++)
1735  {
1736  DWORD size = dataLen;
1737 
1739  NULL, &capabilities->rgCapability[i], 0, NULL,
1740  out, &size);
1741  out += size;
1742  dataLen -= size;
1743  }
1744  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1745  CRYPT_FreeSpace(pEncodePara, pbEncoded);
1746  }
1747  }
1748  }
1749  }
1751  {
1753  }
1754  __ENDTRY
1755  return ret;
1756 }
1757 
1759  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1761 {
1763  DWORD bytesNeeded, dataLen, lenBytes, i;
1764  BOOL ret = TRUE;
1765 
1766  for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1767  {
1768  DWORD size;
1769 
1771  &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1772  if (ret)
1773  dataLen += size;
1774  }
1775  if (ret)
1776  {
1777  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1778  bytesNeeded = 1 + lenBytes + dataLen;
1779  if (!pbEncoded)
1780  *pcbEncoded = bytesNeeded;
1781  else
1782  {
1783  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1784  pcbEncoded, bytesNeeded)))
1785  {
1786  BYTE *out;
1787 
1789  pbEncoded = *(BYTE **)pbEncoded;
1790  out = pbEncoded;
1791  *out++ = ASN_SEQUENCE;
1792  CRYPT_EncodeLen(dataLen, out, &lenBytes);
1793  out += lenBytes;
1794  for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1795  {
1796  DWORD size = dataLen;
1797 
1799  &noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
1800  out += size;
1801  dataLen -= size;
1802  }
1803  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1804  CRYPT_FreeSpace(pEncodePara, pbEncoded);
1805  }
1806  }
1807  }
1808  return ret;
1809 }
1810 
1812  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1814 {
1816  BOOL ret;
1817  CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1818  { 0, (LPBYTE)noticeRef->pszOrganization } };
1819  struct AsnEncodeSequenceItem items[] = {
1820  { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1821  { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1822  };
1823 
1825  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1826  pcbEncoded);
1827  return ret;
1828 }
1829 
1831  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1833  DWORD *pcbEncoded)
1834 {
1835  BOOL ret = FALSE;
1836 
1837  __TRY
1838  {
1840  struct AsnEncodeSequenceItem items[2];
1841  CERT_NAME_VALUE displayTextValue;
1842  DWORD cItem = 0;
1843 
1844  if (notice->pNoticeReference)
1845  {
1846  items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1847  items[cItem].pvStructInfo = notice->pNoticeReference;
1848  cItem++;
1849  }
1850  if (notice->pszDisplayText)
1851  {
1852  displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1853  displayTextValue.Value.cbData = 0;
1854  displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1855  items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1856  items[cItem].pvStructInfo = &displayTextValue;
1857  cItem++;
1858  }
1860  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1861  }
1863  {
1865  }
1866  __ENDTRY
1867  return ret;
1868 }
1869 
1871  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1873 {
1874  BOOL ret = FALSE;
1875 
1876  __TRY
1877  {
1879 
1880  if (!attr->pszObjId)
1882  else
1883  {
1884  struct AsnEncodeSequenceItem items[2] = {
1885  { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1886  { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1887  };
1888 
1890  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1891  pcbEncoded);
1892  }
1893  }
1895  {
1897  }
1898  __ENDTRY
1899  return ret;
1900 }
1901 
1903  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1905 {
1906  BOOL ret = FALSE;
1907 
1908  __TRY
1909  {
1910  const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1911  struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1913 
1915  &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1916  }
1918  {
1920  }
1921  __ENDTRY
1922  return ret;
1923 }
1924 
1925 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1927  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1929  DWORD *pcbEncoded)
1930 {
1931  const CRYPT_CONTENT_INFO *info = pvStructInfo;
1932  struct AsnEncodeSequenceItem items[2] = {
1933  { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1934  { NULL, NULL, 0 },
1935  };
1936  struct AsnConstructedItem constructed = { 0 };
1937  DWORD cItem = 1;
1938 
1939  if (info->Content.cbData)
1940  {
1941  constructed.tag = 0;
1942  constructed.pvStructInfo = &info->Content;
1943  constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1944  items[cItem].pvStructInfo = &constructed;
1945  items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1946  cItem++;
1947  }
1949  cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1950 }
1951 
1953  void *pvData, DWORD *pcbData)
1954 {
1955  struct AsnEncodeSequenceItem items[] = {
1956  { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1958  0 },
1959  { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1960  { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1961  };
1962 
1964 }
1965 
1967  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1969 {
1970  BOOL ret = FALSE;
1971 
1972  __TRY
1973  {
1975 
1976  if (!info->pszObjId)
1978  else
1980  lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1981  pcbEncoded);
1982  }
1984  {
1986  }
1987  __ENDTRY
1988  return ret;
1989 }
1990 
1992  BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1993  DWORD *pcbEncoded)
1994 {
1995  BOOL ret = TRUE;
1996  LPCWSTR str = (LPCWSTR)value->Value.pbData;
1997  DWORD bytesNeeded, lenBytes, encodedLen;
1998 
1999  if (value->Value.cbData)
2000  encodedLen = value->Value.cbData / sizeof(WCHAR);
2001  else if (str)
2002  encodedLen = strlenW(str);
2003  else
2004  encodedLen = 0;
2005  CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2006  bytesNeeded = 1 + lenBytes + encodedLen;
2007  if (!pbEncoded)
2008  *pcbEncoded = bytesNeeded;
2009  else
2010  {
2011  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2012  pbEncoded, pcbEncoded, bytesNeeded)))
2013  {
2014  DWORD i;
2015 
2017  pbEncoded = *(BYTE **)pbEncoded;
2018  *pbEncoded++ = tag;
2019  CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
2020  pbEncoded += lenBytes;
2021  for (i = 0; i < encodedLen; i++)
2022  *pbEncoded++ = (BYTE)str[i];
2023  }
2024  }
2025  return ret;
2026 }
2027 
2029  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2030  DWORD *pcbEncoded)
2031 {
2032  BOOL ret = TRUE;
2033  LPCWSTR str = (LPCWSTR)value->Value.pbData;
2034  DWORD bytesNeeded, lenBytes, encodedLen;
2035 
2036  if (value->Value.cbData)
2037  encodedLen = value->Value.cbData / sizeof(WCHAR);
2038  else if (str)
2039  encodedLen = strlenW(str);
2040  else
2041  encodedLen = 0;
2042  CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2043  bytesNeeded = 1 + lenBytes + encodedLen;
2044  if (!pbEncoded)
2045  *pcbEncoded = bytesNeeded;
2046  else
2047  {
2048  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2049  pbEncoded, pcbEncoded, bytesNeeded)))
2050  {
2051  DWORD i;
2052  BYTE *ptr;
2053 
2055  ptr = *(BYTE **)pbEncoded;
2056  else
2057  ptr = pbEncoded;
2058  *ptr++ = ASN_NUMERICSTRING;
2059  CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2060  ptr += lenBytes;
2061  for (i = 0; ret && i < encodedLen; i++)
2062  {
2063  if (isdigitW(str[i]))
2064  *ptr++ = (BYTE)str[i];
2065  else
2066  {
2067  *pcbEncoded = i;
2069  ret = FALSE;
2070  }
2071  }
2072  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2073  CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2074  }
2075  }
2076  return ret;
2077 }
2078 
2079 static inline BOOL isprintableW(WCHAR wc)
2080 {
2081  return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2082  wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2083  wc == '/' || wc == ':' || wc == '=' || wc == '?';
2084 }
2085 
2087  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2088  DWORD *pcbEncoded)
2089 {
2090  BOOL ret = TRUE;
2091  LPCWSTR str = (LPCWSTR)value->Value.pbData;
2092  DWORD bytesNeeded, lenBytes, encodedLen;
2093 
2094  if (value->Value.cbData)
2095  encodedLen = value->Value.cbData / sizeof(WCHAR);
2096  else if (str)
2097  encodedLen = strlenW(str);
2098  else
2099  encodedLen = 0;
2100  CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2101  bytesNeeded = 1 + lenBytes + encodedLen;
2102  if (!pbEncoded)
2103  *pcbEncoded = bytesNeeded;
2104  else
2105  {
2106  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2107  pbEncoded, pcbEncoded, bytesNeeded)))
2108  {
2109  DWORD i;
2110  BYTE *ptr;
2111 
2113  ptr = *(BYTE **)pbEncoded;
2114  else
2115  ptr = pbEncoded;
2116  *ptr++ = ASN_PRINTABLESTRING;
2117  CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2118  ptr += lenBytes;
2119  for (i = 0; ret && i < encodedLen; i++)
2120  {
2121  if (isprintableW(str[i]))
2122  *ptr++ = (BYTE)str[i];
2123  else
2124  {
2125  *pcbEncoded = i;
2127  ret = FALSE;
2128  }
2129  }
2130  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2131  CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2132  }
2133  }
2134  return ret;
2135 }
2136 
2138  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2139  DWORD *pcbEncoded)
2140 {
2141  BOOL ret = TRUE;
2142  LPCWSTR str = (LPCWSTR)value->Value.pbData;
2143  DWORD bytesNeeded, lenBytes, encodedLen;
2144 
2145  if (value->Value.cbData)
2146  encodedLen = value->Value.cbData / sizeof(WCHAR);
2147  else if (str)
2148  encodedLen = strlenW(str);
2149  else
2150  encodedLen = 0;
2151  CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2152  bytesNeeded = 1 + lenBytes + encodedLen;
2153  if (!pbEncoded)
2154  *pcbEncoded = bytesNeeded;
2155  else
2156  {
2157  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2158  pbEncoded, pcbEncoded, bytesNeeded)))
2159  {
2160  DWORD i;
2161  BYTE *ptr;
2162 
2164  ptr = *(BYTE **)pbEncoded;
2165  else
2166  ptr = pbEncoded;
2167  *ptr++ = ASN_IA5STRING;
2168  CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2169  ptr += lenBytes;
2170  for (i = 0; ret && i < encodedLen; i++)
2171  {
2172  if (str[i] <= 0x7f)
2173  *ptr++ = (BYTE)str[i];
2174  else
2175  {
2176  *pcbEncoded = i;
2178  ret = FALSE;
2179  }
2180  }
2181  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2182  CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2183  }
2184  }
2185  return ret;
2186 }
2187 
2189  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2190  DWORD *pcbEncoded)
2191 {
2192  BOOL ret = TRUE;
2193  LPCWSTR str = (LPCWSTR)value->Value.pbData;
2194  DWORD bytesNeeded, lenBytes, strLen;
2195 
2196  /* FIXME: doesn't handle composite characters */
2197  if (value->Value.cbData)
2198  strLen = value->Value.cbData / sizeof(WCHAR);
2199  else if (str)
2200  strLen = strlenW(str);
2201  else
2202  strLen = 0;
2203  CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2204  bytesNeeded = 1 + lenBytes + strLen * 4;
2205  if (!pbEncoded)
2206  *pcbEncoded = bytesNeeded;
2207  else
2208  {
2209  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2210  pbEncoded, pcbEncoded, bytesNeeded)))
2211  {
2212  DWORD i;
2213 
2215  pbEncoded = *(BYTE **)pbEncoded;
2217  CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2218  pbEncoded += lenBytes;
2219  for (i = 0; i < strLen; i++)
2220  {
2221  *pbEncoded++ = 0;
2222  *pbEncoded++ = 0;
2223  *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2224  *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2225  }
2226  }
2227  }
2228  return ret;
2229 }
2230 
2232  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2234 {
2235  BOOL ret = FALSE;
2236 
2237  __TRY
2238  {
2240 
2241  switch (value->dwValueType)
2242  {
2243  case CERT_RDN_ANY_TYPE:
2244  case CERT_RDN_ENCODED_BLOB:
2245  case CERT_RDN_OCTET_STRING:
2247  break;
2251  break;
2255  break;
2258  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2259  break;
2263  break;
2264  case CERT_RDN_IA5_STRING:
2265  ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2267  break;
2270  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2271  break;
2274  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2275  break;
2278  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2279  break;
2283  break;
2284  case CERT_RDN_BMP_STRING:
2285  ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2287  break;
2288  case CERT_RDN_UTF8_STRING:
2289  ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2291  break;
2292  default:
2294  }
2295  }
2297  {
2299  }
2300  __ENDTRY
2301  return ret;
2302 }
2303 
2305  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2307 {
2308  BOOL ret;
2309 
2310  __TRY
2311  {
2312  const CERT_NAME_INFO *info = pvStructInfo;
2313  DWORD bytesNeeded = 0, lenBytes, size, i;
2314 
2315  TRACE("encoding name with %d RDNs\n", info->cRDN);
2316  ret = TRUE;
2317  for (i = 0; ret && i < info->cRDN; i++)
2318  {
2321  if (ret)
2322  bytesNeeded += size;
2323  }
2324  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2325  bytesNeeded += 1 + lenBytes;
2326  if (ret)
2327  {
2328  if (!pbEncoded)
2329  *pcbEncoded = bytesNeeded;
2330  else
2331  {
2332  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2333  pbEncoded, pcbEncoded, bytesNeeded)))
2334  {
2335  BYTE *out;
2336 
2338  pbEncoded = *(BYTE **)pbEncoded;
2339  out = pbEncoded;
2340  *out++ = ASN_SEQUENCEOF;
2341  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2342  out += lenBytes;
2343  for (i = 0; ret && i < info->cRDN; i++)
2344  {
2345  size = bytesNeeded;
2347  &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
2348  if (ret)
2349  {
2350  out += size;
2351  bytesNeeded -= size;
2352  }
2353  }
2354  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2355  CRYPT_FreeSpace(pEncodePara, pbEncoded);
2356  }
2357  }
2358  }
2359  }
2361  {
2363  ret = FALSE;
2364  }
2365  __ENDTRY
2366  return ret;
2367 }
2368 
2370  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2372 {
2373  BOOL val = *(const BOOL *)pvStructInfo, ret;
2374 
2375  TRACE("%d\n", val);
2376 
2377  if (!pbEncoded)
2378  {
2379  *pcbEncoded = 3;
2380  ret = TRUE;
2381  }
2382  else if (*pcbEncoded < 3)
2383  {
2384  *pcbEncoded = 3;
2386  ret = FALSE;
2387  }
2388  else
2389  {
2390  *pcbEncoded = 3;
2391  *pbEncoded++ = ASN_BOOL;
2392  *pbEncoded++ = 1;
2393  *pbEncoded++ = val ? 0xff : 0;
2394  ret = TRUE;
2395  }
2396  TRACE("returning %d (%08x)\n", ret, GetLastError());
2397  return ret;
2398 }
2399 
2401  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2403 {
2405  BOOL ret;
2406  DWORD dataLen;
2407  BYTE tag;
2408 
2409  ret = TRUE;
2410  switch (entry->dwAltNameChoice)
2411  {
2414  case CERT_ALT_NAME_URL:
2415  tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2416  if (entry->u.pwszURL)
2417  {
2418  DWORD i;
2419 
2420  /* Not + 1: don't encode the NULL-terminator */
2421  dataLen = lstrlenW(entry->u.pwszURL);
2422  for (i = 0; ret && i < dataLen; i++)
2423  {
2424  if (entry->u.pwszURL[i] > 0x7f)
2425  {
2427  ret = FALSE;
2428  *pcbEncoded = i;
2429  }
2430  }
2431  }
2432  else
2433  dataLen = 0;
2434  break;
2436  tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2437  dataLen = entry->u.DirectoryName.cbData;
2438  break;
2440  tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2441  dataLen = entry->u.IPAddress.cbData;
2442  break;
2444  {
2445  struct AsnEncodeTagSwappedItem swapped =
2446  { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2448 
2449  return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2450  pcbEncoded);
2451  }
2453  FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2454  return FALSE;
2455  default:
2457  return FALSE;
2458  }
2459  if (ret)
2460  {
2461  DWORD bytesNeeded, lenBytes;
2462 
2463  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2464  bytesNeeded = 1 + dataLen + lenBytes;
2465  if (!pbEncoded)
2466  *pcbEncoded = bytesNeeded;
2467  else if (*pcbEncoded < bytesNeeded)
2468  {
2470  *pcbEncoded = bytesNeeded;
2471  ret = FALSE;
2472  }
2473  else
2474  {
2475  *pbEncoded++ = tag;
2476  CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2477  pbEncoded += lenBytes;
2478  switch (entry->dwAltNameChoice)
2479  {
2482  case CERT_ALT_NAME_URL:
2483  {
2484  DWORD i;
2485 
2486  for (i = 0; i < dataLen; i++)
2487  *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2488  break;
2489  }
2491  memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2492  break;
2494  memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2495  break;
2496  }
2497  if (ret)
2498  *pcbEncoded = bytesNeeded;
2499  }
2500  }
2501  TRACE("returning %d (%08x)\n", ret, GetLastError());
2502  return ret;
2503 }
2504 
2506  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2508 {
2509  BOOL ret;
2510 
2511  __TRY
2512  {
2514  struct AsnEncodeSequenceItem items[3] = { { 0 } };
2515  struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2516  struct AsnConstructedItem constructed = { 0 };
2517  DWORD cItem = 0, cSwapped = 0;
2518 
2519  if (info->KeyId.cbData)
2520  {
2521  swapped[cSwapped].tag = ASN_CONTEXT | 0;
2522  swapped[cSwapped].pvStructInfo = &info->KeyId;
2523  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2524  items[cItem].pvStructInfo = &swapped[cSwapped];
2525  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2526  cSwapped++;
2527  cItem++;
2528  }
2529  if (info->CertIssuer.cbData)
2530  {
2531  constructed.tag = 1;
2532  constructed.pvStructInfo = &info->CertIssuer;
2533  constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2534  items[cItem].pvStructInfo = &constructed;
2535  items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2536  cItem++;
2537  }
2538  if (info->CertSerialNumber.cbData)
2539  {
2540  swapped[cSwapped].tag = ASN_CONTEXT | 2;
2541  swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2542  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2543  items[cItem].pvStructInfo = &swapped[cSwapped];
2544  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2545  cSwapped++;
2546  cItem++;
2547  }
2549  pEncodePara, pbEncoded, pcbEncoded);
2550  }
2552  {
2554  ret = FALSE;
2555  }
2556  __ENDTRY
2557  return ret;
2558 }
2559 
2561  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2563 {
2564  BOOL ret;
2565 
2566  __TRY
2567  {
2569  DWORD bytesNeeded, dataLen, lenBytes, i;
2570 
2571  ret = TRUE;
2572  /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2573  * can't encode an erroneous entry index if it's bigger than this.
2574  */
2575  for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2576  {
2577  DWORD len;
2578 
2580  &info->rgAltEntry[i], 0, NULL, NULL, &len);
2581  if (ret)
2582  dataLen += len;
2584  {
2585  /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2586  * the bad character, now set the index of the bad
2587  * entry
2588  */
2589  *pcbEncoded = (BYTE)i <<
2591  }
2592  }
2593  if (ret)
2594  {
2595  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2596  bytesNeeded = 1 + lenBytes + dataLen;
2597  if (!pbEncoded)
2598  {
2599  *pcbEncoded = bytesNeeded;
2600  ret = TRUE;
2601  }
2602  else
2603  {
2604  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2605  pbEncoded, pcbEncoded, bytesNeeded)))
2606  {
2607  BYTE *out;
2608 
2610  pbEncoded = *(BYTE **)pbEncoded;
2611  out = pbEncoded;
2612  *out++ = ASN_SEQUENCEOF;
2613  CRYPT_EncodeLen(dataLen, out, &lenBytes);
2614  out += lenBytes;
2615  for (i = 0; ret && i < info->cAltEntry; i++)
2616  {
2617  DWORD len = dataLen;
2618 
2620  NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
2621  if (ret)
2622  {
2623  out += len;
2624  dataLen -= len;
2625  }
2626  }
2627  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2628  CRYPT_FreeSpace(pEncodePara, pbEncoded);
2629  }
2630  }
2631  }
2632  }
2634  {
2636  ret = FALSE;
2637  }
2638  __ENDTRY
2639  return ret;
2640 }
2641 
2643  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2645 {
2646  BOOL ret;
2647 
2648  __TRY
2649  {
2651  struct AsnEncodeSequenceItem items[3] = { { 0 } };
2652  struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2653  DWORD cItem = 0, cSwapped = 0;
2654 
2655  if (info->KeyId.cbData)
2656  {
2657  swapped[cSwapped].tag = ASN_CONTEXT | 0;
2658  swapped[cSwapped].pvStructInfo = &info->KeyId;
2659  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2660  items[cItem].pvStructInfo = &swapped[cSwapped];
2661  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2662  cSwapped++;
2663  cItem++;
2664  }
2665  if (info->AuthorityCertIssuer.cAltEntry)
2666  {
2667  swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2668  swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2669  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2670  items[cItem].pvStructInfo = &swapped[cSwapped];
2671  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2672  cSwapped++;
2673  cItem++;
2674  }
2675  if (info->AuthorityCertSerialNumber.cbData)
2676  {
2677  swapped[cSwapped].tag = ASN_CONTEXT | 2;
2678  swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2679  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2680  items[cItem].pvStructInfo = &swapped[cSwapped];
2681  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2682  cSwapped++;
2683  cItem++;
2684  }
2686  pEncodePara, pbEncoded, pcbEncoded);
2687  }
2689  {
2691  ret = FALSE;
2692  }
2693  __ENDTRY
2694  return ret;
2695 }
2696 
2699 {
2700  struct AsnEncodeSequenceItem items[] = {
2701  { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2702  { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2703  };
2704 
2705  if (!descr->pszAccessMethod)
2706  {
2708  return FALSE;
2709  }
2711 }
2712 
2714  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2716 {
2717  BOOL ret;
2718 
2719  __TRY
2720  {
2721  DWORD bytesNeeded, dataLen, lenBytes, i;
2723 
2724  ret = TRUE;
2725  for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2726  {
2727  DWORD size;
2728 
2729  ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2730  &size);
2731  if (ret)
2732  dataLen += size;
2733  }
2734  if (ret)
2735  {
2736  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2737  bytesNeeded = 1 + lenBytes + dataLen;
2738  if (!pbEncoded)
2739  *pcbEncoded = bytesNeeded;
2740  else
2741  {
2742  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2743  pbEncoded, pcbEncoded, bytesNeeded)))
2744  {
2745  BYTE *out;
2746 
2748  pbEncoded = *(BYTE **)pbEncoded;
2749  out = pbEncoded;
2750  *out++ = ASN_SEQUENCEOF;
2751  CRYPT_EncodeLen(dataLen, out, &lenBytes);
2752  out += lenBytes;
2753  for (i = 0; i < info->cAccDescr; i++)
2754  {
2755  DWORD size = dataLen;
2756 
2758  &info->rgAccDescr[i], out, &size);
2759  out += size;
2760  dataLen -= size;
2761  }
2762  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2763  CRYPT_FreeSpace(pEncodePara, pbEncoded);
2764  }
2765  }
2766  }
2767  }
2769  {
2771  ret = FALSE;
2772  }
2773  __ENDTRY
2774  return ret;
2775 }
2776 
2778  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2780 {
2781  BOOL ret;
2782 
2783  __TRY
2784  {
2786  struct AsnEncodeSequenceItem items[3] = {
2787  { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2788  { 0 }
2789  };
2790  DWORD cItem = 1;
2791 
2792  if (info->fPathLenConstraint)
2793  {
2794  items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2795  items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2796  cItem++;
2797  }
2798  if (info->cSubtreesConstraint)
2799  {
2800  items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2801  items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2802  cItem++;
2803  }
2805  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2806  }
2808  {
2810  ret = FALSE;
2811  }
2812  __ENDTRY
2813  return ret;
2814 }
2815 
2817  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2819 {
2820  BOOL ret;
2821 
2822  __TRY
2823  {
2825  struct AsnEncodeSequenceItem items[2] = { { 0 } };
2826  DWORD cItem = 0;
2827 
2828  if (info->fCA)
2829  {
2830  items[cItem].pvStructInfo = &info->fCA;
2831  items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2832  cItem++;
2833  }
2834  if (info->fPathLenConstraint)
2835  {
2836  items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2837  items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2838  cItem++;
2839  }
2841  dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2842  }
2844  {
2846  ret = FALSE;
2847  }
2848  __ENDTRY
2849  return ret;
2850 }
2851 
2853  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2855 {
2857  BOOL ret;
2858 
2859  if (!info->cPolicyQualifier)
2860  {
2861  *pcbEncoded = 0;
2862  ret = TRUE;
2863  }
2864  else
2865  {
2866  struct AsnEncodeSequenceItem items[2] = {
2867  { NULL, CRYPT_AsnEncodeOid, 0 },
2868  { NULL, CRYPT_CopyEncodedBlob, 0 },
2869  };
2870  DWORD bytesNeeded = 0, lenBytes, size, i;
2871 
2872  ret = TRUE;
2873  for (i = 0; ret && i < info->cPolicyQualifier; i++)
2874  {
2875  items[0].pvStructInfo =
2876  info->rgPolicyQualifier[i].pszPolicyQualifierId;
2877  items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2880  if (ret)
2881  bytesNeeded += size;
2882  }
2883  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2884  bytesNeeded += 1 + lenBytes;
2885  if (ret)
2886  {
2887  if (!pbEncoded)
2888  *pcbEncoded = bytesNeeded;
2889  else
2890  {
2891  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2892  pbEncoded, pcbEncoded, bytesNeeded)))
2893  {
2894  BYTE *out;
2895 
2897  pbEncoded = *(BYTE **)pbEncoded;
2898  out = pbEncoded;
2899  *out++ = ASN_SEQUENCEOF;
2900  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2901  out += lenBytes;
2902  for (i = 0; ret && i < info->cPolicyQualifier; i++)
2903  {
2904  items[0].pvStructInfo =
2905  info->rgPolicyQualifier[i].pszPolicyQualifierId;
2906  items[1].pvStructInfo =
2907  &info->rgPolicyQualifier[i].Qualifier;
2908  size = bytesNeeded;
2911  if (ret)
2912  {
2913  out += size;
2914  bytesNeeded -= size;
2915  }
2916  }
2917  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2918  CRYPT_FreeSpace(pEncodePara, pbEncoded);
2919  }
2920  }
2921  }
2922  }
2923  return ret;
2924 }
2925 
2928  DWORD *pcbEncoded)
2929 {
2930  struct AsnEncodeSequenceItem items[2] = {
2931  { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2933  };
2934  BOOL ret;
2935 
2936  if (!info->pszPolicyIdentifier)
2937  {
2939  return FALSE;
2940  }
2942  return ret;
2943 }
2944 
2946  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2948 {
2949  BOOL ret = FALSE;
2950 
2951  __TRY
2952  {
2954  DWORD bytesNeeded = 0, lenBytes, size, i;
2955 
2956  ret = TRUE;
2957  for (i = 0; ret && i < info->cPolicyInfo; i++)
2958  {
2960  &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2961  &size);
2962  if (ret)
2963  bytesNeeded += size;
2964  }
2965  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2966  bytesNeeded += 1 + lenBytes;
2967  if (ret)
2968  {
2969  if (!pbEncoded)
2970  *pcbEncoded = bytesNeeded;
2971  else
2972  {
2973  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2974  pbEncoded, pcbEncoded, bytesNeeded)))
2975  {
2976  BYTE *out;
2977 
2979  pbEncoded = *(BYTE **)pbEncoded;
2980  out = pbEncoded;
2981  *out++ = ASN_SEQUENCEOF;
2982  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2983  out += lenBytes;
2984  for (i = 0; ret && i < info->cPolicyInfo; i++)
2985  {
2986  size = bytesNeeded;
2988  &info->rgPolicyInfo[i],
2990  if (ret)
2991  {
2992  out += size;
2993  bytesNeeded -= size;
2994  }
2995  }
2996  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2997  CRYPT_FreeSpace(pEncodePara, pbEncoded);
2998  }
2999  }
3000  }
3001  }
3003  {
3005  }
3006  __ENDTRY
3007  return ret;
3008 }
3009 
3012  DWORD *pcbEncoded)
3013 {
3014  struct AsnEncodeSequenceItem items[] = {
3015  { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3016  { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3017  };
3018 
3019  if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
3020  {
3022  return FALSE;
3023  }
3025 }
3026 
3028  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3030 {
3031  BOOL ret = FALSE;
3032 
3033  __TRY
3034  {
3036  DWORD bytesNeeded = 0, lenBytes, size, i;
3037 
3038  ret = TRUE;
3039  for (i = 0; ret && i < info->cPolicyMapping; i++)
3040  {
3042  &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3043  NULL, &size);
3044  if (ret)
3045  bytesNeeded += size;
3046  }
3047  CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3048  bytesNeeded += 1 + lenBytes;
3049  if (ret)
3050  {
3051  if (!pbEncoded)
3052  *pcbEncoded = bytesNeeded;
3053  else
3054  {
3055  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3056  pbEncoded, pcbEncoded, bytesNeeded)))
3057  {
3058  BYTE *out;
3059 
3061  pbEncoded = *(BYTE **)pbEncoded;
3062  out = pbEncoded;
3063  *out++ = ASN_SEQUENCEOF;
3064  CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3065  out += lenBytes;
3066  for (i = 0; ret && i < info->cPolicyMapping; i++)
3067  {
3068  size = bytesNeeded;
3070  dwCertEncodingType, &info->rgPolicyMapping[i],
3072  if (ret)
3073  {
3074  out += size;
3075  bytesNeeded -= size;
3076  }
3077  }
3078  if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3079  CRYPT_FreeSpace(pEncodePara, pbEncoded);
3080  }
3081  }
3082  }
3083  }
3085  {
3087  }
3088  __ENDTRY
3089  return ret;
3090 }
3091 
3093  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3095  DWORD *pcbEncoded)
3096 {
3097  BOOL ret = FALSE;
3098 
3099  __TRY
3100  {
3102  struct AsnEncodeSequenceItem items[2];
3103  struct AsnEncodeTagSwappedItem swapped[2];
3104  DWORD cItem = 0, cSwapped = 0;
3105 
3106  if (info->fRequireExplicitPolicy)
3107  {
3108  swapped[cSwapped].tag = ASN_CONTEXT | 0;
3109  swapped[cSwapped].pvStructInfo =
3110  &info->dwRequireExplicitPolicySkipCerts;
3111  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3112  items[cItem].pvStructInfo = &swapped[cSwapped];
3113  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3114  cSwapped++;
3115  cItem++;
3116  }
3117  if (info->fInhibitPolicyMapping)
3118  {
3119  swapped[cSwapped].tag = ASN_CONTEXT | 1;
3120  swapped[cSwapped].pvStructInfo =
3121  &info->dwInhibitPolicyMappingSkipCerts;
3122  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3123  items[cItem].pvStructInfo = &swapped[cSwapped];
3124  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3125  cSwapped++;
3126  cItem++;
3127  }
3130  }
3132  {
3134  }
3135  __ENDTRY
3136  return ret;
3137 }
3138 
3140  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3142 {
3143  BOOL ret;
3144 
3145  __TRY
3146  {
3147  const BLOBHEADER *hdr = pvStructInfo;
3148 
3149  if (hdr->bType != PUBLICKEYBLOB)
3150  {
3152  ret = FALSE;
3153  }
3154  else
3155  {
3156  const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3157  ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3158  CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3159  (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3160  struct AsnEncodeSequenceItem items[] = {
3162  { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3163  };
3164 
3166  ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3167  }
3168  }
3170  {
3172  ret = FALSE;
3173  }
3174  __ENDTRY
3175  return ret;
3176 }
3177 
3179  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3181 {
3182  BOOL ret;
3183 
3184  __TRY
3185  {
3187  DWORD bytesNeeded, lenBytes;
3188 
3189  TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3190  dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0);
3191 
3192  CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3193  bytesNeeded = 1 + lenBytes + blob->cbData;
3194  if (!pbEncoded)
3195  {
3196  *pcbEncoded = bytesNeeded;
3197  ret = TRUE;
3198  }
3199  else
3200  {
3201  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3202  pcbEncoded, bytesNeeded)))
3203  {
3205  pbEncoded = *(BYTE **)pbEncoded;
3207  CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3208  pbEncoded += lenBytes;
3209  if (blob->cbData)
3210  memcpy(pbEncoded, blob->pbData, blob->cbData);
3211  }
3212  }
3213  }
3215  {
3217  ret = FALSE;
3218  }
3219  __ENDTRY
3220  TRACE("returning %d (%08x)\n", ret, GetLastError());
3221  return ret;
3222 }
3223 
3225  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3227 {
3228  BOOL ret;
3229 
3230  __TRY
3231  {
3232  const CRYPT_BIT_BLOB *blob = pvStructInfo;
3233  DWORD bytesNeeded, lenBytes, dataBytes;
3234  BYTE unusedBits;
3235 
3236  /* yep, MS allows cUnusedBits to be >= 8 */
3237  if (!blob->cUnusedBits)
3238  {
3239  dataBytes = blob->cbData;
3240  unusedBits = 0;
3241  }
3242  else if (blob->cbData * 8 > blob->cUnusedBits)
3243  {
3244  dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3245  unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3246  blob->cUnusedBits;
3247  }
3248  else
3249  {
3250  dataBytes = 0;
3251  unusedBits = 0;
3252  }
3253  CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3254  bytesNeeded = 1 + lenBytes + dataBytes + 1;
3255  if (!pbEncoded)
3256  {
3257  *pcbEncoded = bytesNeeded;
3258  ret = TRUE;
3259  }
3260  else
3261  {
3262  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3263  pcbEncoded, bytesNeeded)))
3264  {
3266  pbEncoded = *(BYTE **)pbEncoded;
3267  *pbEncoded++ = ASN_BITSTRING;
3268  CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3269  pbEncoded += lenBytes;
3270  *pbEncoded++ = unusedBits;
3271  if (dataBytes)
3272  {
3273  BYTE mask = 0xff << unusedBits;
3274 
3275  if (dataBytes > 1)
3276  {
3277  memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3278  pbEncoded += dataBytes - 1;
3279  }
3280  *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3281  }
3282  }
3283  }
3284  }
3286  {
3288  ret = FALSE;
3289  }
3290  __ENDTRY
3291  return ret;
3292 }
3293 
3295  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3297 {
3298  BOOL ret;
3299 
3300  __TRY
3301  {
3302  const CRYPT_BIT_BLOB *blob = pvStructInfo;
3303  CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3304 
3305  ret = TRUE;
3306  if (newBlob.cbData)
3307  {
3308  newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3309  if (newBlob.pbData)
3310  {
3311  DWORD i;
3312 
3313  for (i = 0; i < newBlob.cbData; i++)
3314  newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3315  }
3316  else
3317  ret = FALSE;
3318  }
3319  if (ret)
3320  ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3321  &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3322  CryptMemFree(newBlob.pbData);
3323  }
3325  {
3327  ret = FALSE;
3328  }
3329  __ENDTRY
3330  return ret;
3331 }
3332 
3334  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3336 {
3337  CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3338 
3340  &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3341 }
3342 
3344  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3346 {
3347  BOOL ret;
3348 
3349  __TRY
3350  {
3351  DWORD significantBytes, lenBytes, bytesNeeded;
3352  BYTE padByte = 0;
3353  BOOL pad = FALSE;
3355 
3356  significantBytes = blob->cbData;
3357  if (significantBytes)
3358  {
3359  if (blob->pbData[significantBytes - 1] & 0x80)
3360  {
3361  /* negative, lop off leading (little-endian) 0xffs */
3362  for (; significantBytes > 0 &&
3363  blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3364  ;
3365  if (blob->pbData[significantBytes - 1] < 0x80)
3366  {
3367  padByte = 0xff;
3368  pad = TRUE;
3369  }
3370  }
3371  else
3372  {
3373  /* positive, lop off leading (little-endian) zeroes */
3374  for (; significantBytes > 0 &&
3375  !blob->pbData[significantBytes - 1]; significantBytes--)
3376  ;
3377  if (significantBytes == 0)
3378  significantBytes = 1;
3379  if (blob->pbData[significantBytes - 1] > 0x7f)
3380  {
3381  padByte = 0;
3382  pad = TRUE;
3383  }
3384  }
3385  }
3386  if (pad)
3387  CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3388  else
3389  CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3390  bytesNeeded = 1 + lenBytes + significantBytes;
3391  if (pad)
3392  bytesNeeded++;
3393  if (!pbEncoded)
3394  {
3395  *pcbEncoded = bytesNeeded;
3396  ret = TRUE;
3397  }
3398  else
3399  {
3400  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3401  pcbEncoded, bytesNeeded)))
3402  {
3404  pbEncoded = *(BYTE **)pbEncoded;
3405  *pbEncoded++ = ASN_INTEGER;
3406  if (pad)
3407  {
3408  CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3409  pbEncoded += lenBytes;
3410  *pbEncoded++ = padByte;
3411  }
3412  else
3413  {
3414  CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3415  pbEncoded += lenBytes;
3416  }
3417  for (; significantBytes > 0; significantBytes--)
3418  *(pbEncoded++) = blob->pbData[significantBytes - 1];
3419  }
3420  }
3421  }
3423  {
3425  ret = FALSE;
3426  }
3427  __ENDTRY
3428  return ret;
3429 }
3430 
3432  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3434 {
3435  BOOL ret;
3436 
3437  __TRY
3438  {
3439  DWORD significantBytes, lenBytes, bytesNeeded;
3440  BOOL pad = FALSE;
3442 
3443  significantBytes = blob->cbData;
3444  if (significantBytes)
3445  {
3446  /* positive, lop off leading (little-endian) zeroes */
3447  for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3448  significantBytes--)
3449  ;
3450  if (significantBytes == 0)
3451  significantBytes = 1;
3452  if (blob->pbData[significantBytes - 1] > 0x7f)
3453  pad = TRUE;
3454  }
3455  if (pad)
3456  CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3457  else
3458  CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3459  bytesNeeded = 1 + lenBytes + significantBytes;
3460  if (pad)
3461  bytesNeeded++;
3462  if (!pbEncoded)
3463  {
3464  *pcbEncoded = bytesNeeded;
3465  ret = TRUE;
3466  }
3467  else
3468  {
3469  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3470  pcbEncoded, bytesNeeded)))
3471  {
3473  pbEncoded = *(BYTE **)pbEncoded;
3474  *pbEncoded++ = ASN_INTEGER;
3475  if (pad)
3476  {
3477  CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3478  pbEncoded += lenBytes;
3479  *pbEncoded++ = 0;
3480  }
3481  else
3482  {
3483  CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3484  pbEncoded += lenBytes;
3485  }
3486  for (; significantBytes > 0; significantBytes--)
3487  *(pbEncoded++) = blob->pbData[significantBytes - 1];
3488  }
3489  }
3490  }
3492  {
3494  ret = FALSE;
3495  }
3496  __ENDTRY
3497  return ret;
3498 }
3499 
3501  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3503 {
3505  BOOL ret;
3506 
3507  /* Encode as an unsigned integer, then change the tag to enumerated */
3508  blob.cbData = sizeof(DWORD);
3509  blob.pbData = (BYTE *)pvStructInfo;
3512  if (ret && pbEncoded)
3513  {
3515  pbEncoded = *(BYTE **)pbEncoded;
3517  }
3518  return ret;
3519 }
3520 
3522  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3524 {
3525  BOOL ret;
3526 
3527  __TRY
3528  {
3529  SYSTEMTIME sysTime;
3530  /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a
3531  * temporary buffer because the output buffer is not NULL-terminated.
3532  */
3533  static const DWORD bytesNeeded = 15;
3534  char buf[40];
3535 
3536  if (!pbEncoded)
3537  {
3538  *pcbEncoded = bytesNeeded;
3539  ret = TRUE;
3540  }
3541  else
3542  {
3543  /* Sanity check the year, this is a two-digit year format */
3544  ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3545  if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3546  {
3548  ret = FALSE;
3549  }
3550  if (ret)
3551  {
3552  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3553  pbEncoded, pcbEncoded, bytesNeeded)))
3554  {
3556  pbEncoded = *(BYTE **)pbEncoded;
3557  buf[0] = ASN_UTCTIME;
3558  buf[1] = bytesNeeded - 2;
3559  snprintf(buf + 2, sizeof(buf) - 2,
3560  "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3561  sysTime.wYear - 2000 : sysTime.wYear - 1900,
3562  sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3563  sysTime.wMinute, sysTime.wSecond);
3564  memcpy(pbEncoded, buf, bytesNeeded);
3565  }
3566  }
3567  }
3568  }
3570  {
3572  ret = FALSE;
3573  }
3574  __ENDTRY
3575  return ret;
3576 }
3577 
3579  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3581 {
3582  BOOL ret;
3583 
3584  __TRY
3585  {
3586  SYSTEMTIME sysTime;
3587  /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a
3588  * temporary buffer because the output buffer is not NULL-terminated.
3589  */
3590  static const DWORD bytesNeeded = 17;
3591  char buf[40];
3592 
3593  if (!pbEncoded)
3594  {
3595  *pcbEncoded = bytesNeeded;
3596  ret = TRUE;
3597  }
3598  else
3599  {
3600  ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3601  if (ret)
3602  ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3603  pcbEncoded, bytesNeeded);
3604  if (ret)
3605  {
3607  pbEncoded = *(BYTE **)pbEncoded;
3608  buf[0] = ASN_GENERALTIME;
3609  buf[1] = bytesNeeded - 2;
3610  snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3611  sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3612  sysTime.wMinute, sysTime.wSecond);
3613  memcpy(pbEncoded, buf, bytesNeeded);
3614  }
3615  }
3616  }
3618  {
3620  ret = FALSE;
3621  }
3622  __ENDTRY
3623  return ret;
3624 }
3625 
3627  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3629 {
3630  BOOL ret;
3631 
3632  __TRY
3633  {
3634  SYSTEMTIME sysTime;
3635 
3636  /* Check the year, if it's in the UTCTime range call that encode func */
3637  if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3638  return FALSE;
3639  if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3640  ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3641  pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3642  else
3644  lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3645  pcbEncoded);
3646  }
3648  {
3650  ret = FALSE;
3651  }
3652  __ENDTRY
3653  return ret;
3654 }
3655 
3657  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3659 {
3660  BOOL ret;
3661 
3662  __TRY
3663  {
3664  DWORD bytesNeeded, dataLen, lenBytes, i;
3665  const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3666 
3667  for (i = 0, dataLen = 0; i < seq->cValue; i++)
3668  dataLen += seq->rgValue[i].cbData;
3669  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3670  bytesNeeded = 1 + lenBytes + dataLen;
3671  if (!pbEncoded)
3672  {
3673  *pcbEncoded = bytesNeeded;
3674  ret = TRUE;
3675  }
3676  else
3677  {
3678  if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3679  pcbEncoded, bytesNeeded)))
3680  {
3682  pbEncoded = *(BYTE **)pbEncoded;
3684  CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3685  pbEncoded += lenBytes;
3686  for (i = 0; i < seq->cValue; i++)
3687  {
3688  memcpy(pbEncoded, seq->rgValue[i].pbData,
3689  seq->rgValue[i].cbData);
3690  pbEncoded += seq->rgValue[i].cbData;
3691  }
3692  }
3693  }
3694  }
3696  {
3698  ret = FALSE;
3699  }
3700  __ENDTRY
3701  return ret;
3702 }
3703 
3706 {
3707  BOOL ret = TRUE;
3708  struct AsnEncodeSequenceItem items[3] = { { 0 } };
3709  struct AsnConstructedItem constructed = { 0 };
3710  struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3711  DWORD cItem = 0, cSwapped = 0;
3712 
3713  switch (distPoint->DistPointName.dwDistPointNameChoice)
3714  {
3716  /* do nothing */
3717  break;
3719  swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3720  swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3721  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3722  constructed.tag = 0;
3723  constructed.pvStructInfo = &swapped[cSwapped];
3724  constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3725  items[cItem].pvStructInfo = &constructed;
3726  items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3727  cSwapped++;
3728  cItem++;
3729  break;
3731  FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3732  ret = FALSE;
3733  break;
3734  default:
3735  ret = FALSE;
3736  }
3737  if (ret && distPoint->ReasonFlags.cbData)
3738  {
3739  swapped[cSwapped].tag = ASN_CONTEXT | 1;
3740  swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3741  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3742  items[cItem].pvStructInfo = &swapped[cSwapped];
3743  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3744  cSwapped++;
3745  cItem++;
3746  }
3747  if (ret && distPoint->CRLIssuer.cAltEntry)
3748  {
3749  swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3750  swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3751  swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3752  items[cItem].pvStructInfo = &swapped[cSwapped];
3753  items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3754  cSwapped++;
3755  cItem++;
3756  }
3757  if (ret)
3760  return ret;
3761 }
3762 
3764  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3766 {
3767  BOOL ret;
3768 
3769  __TRY
3770  {
3772 
3773  if (!info->cDistPoint)
3774  {
3776  ret = FALSE;
3777  }
3778  else
3779  {
3780  DWORD bytesNeeded, dataLen, lenBytes, i;
3781 
3782  ret = TRUE;
3783  for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3784  {
3785  DWORD len;
3786 
3787  ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3788  &len);
3789  if (ret)
3790  dataLen += len;
3792  {
3793  /* Have to propagate index of failing character */
3794  *pcbEncoded = len;
3795  }
3796  }
3797  if (ret)
3798  {
3799  CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3800  bytesNeeded = 1 + lenBytes + dataLen;
3801  if (!pbEncoded)
3802  {
3803  *pcbEncoded = bytesNeeded;
3804  ret =