2 * Copyright 2005-2008 Juan Lang
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.
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.
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
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.
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.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
34 #include "wine/port.h"
41 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
55 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
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.
63 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
93 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
95 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
96 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
97 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
98 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
99 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
100 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
101 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
103 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
104 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
108 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
110 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
111 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
113 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
114 if (!*(BYTE
**)pbEncoded
)
117 *pcbEncoded
= bytesNeeded
;
119 else if (bytesNeeded
> *pcbEncoded
)
121 *pcbEncoded
= bytesNeeded
;
122 SetLastError(ERROR_MORE_DATA
);
126 *pcbEncoded
= bytesNeeded
;
130 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
132 DWORD bytesNeeded
, significantBytes
= 0;
140 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
141 temp
<<= 8, significantBytes
--)
143 bytesNeeded
= significantBytes
+ 1;
147 *pcbEncoded
= bytesNeeded
;
150 if (*pcbEncoded
< bytesNeeded
)
152 SetLastError(ERROR_MORE_DATA
);
156 *pbEncoded
= (BYTE
)len
;
161 *pbEncoded
++ = significantBytes
| 0x80;
162 for (i
= 0; i
< significantBytes
; i
++)
164 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
168 *pcbEncoded
= bytesNeeded
;
172 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
173 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
174 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
177 DWORD i
, dataLen
= 0;
179 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
180 pbEncoded
, *pcbEncoded
);
181 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
183 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
184 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
185 NULL
, &items
[i
].size
);
186 /* Some functions propagate their errors through the size */
188 *pcbEncoded
= items
[i
].size
;
189 dataLen
+= items
[i
].size
;
193 DWORD lenBytes
, bytesNeeded
;
195 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
196 bytesNeeded
= 1 + lenBytes
+ dataLen
;
198 *pcbEncoded
= bytesNeeded
;
201 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
202 pcbEncoded
, bytesNeeded
)))
204 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
205 pbEncoded
= *(BYTE
**)pbEncoded
;
206 *pbEncoded
++ = ASN_SEQUENCE
;
207 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
208 pbEncoded
+= lenBytes
;
209 for (i
= 0; ret
&& i
< cItem
; i
++)
211 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
212 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
213 NULL
, pbEncoded
, &items
[i
].size
);
214 /* Some functions propagate their errors through the size */
216 *pcbEncoded
= items
[i
].size
;
217 pbEncoded
+= items
[i
].size
;
222 TRACE("returning %d (%08x)\n", ret
, GetLastError());
226 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
227 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
228 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
231 const struct AsnConstructedItem
*item
= pvStructInfo
;
234 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
235 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
237 DWORD dataLen
, bytesNeeded
;
239 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
240 bytesNeeded
= 1 + dataLen
+ len
;
242 *pcbEncoded
= bytesNeeded
;
243 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
244 pbEncoded
, pcbEncoded
, bytesNeeded
)))
246 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
247 pbEncoded
= *(BYTE
**)pbEncoded
;
248 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
249 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
250 pbEncoded
+= dataLen
;
251 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
252 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
256 /* Some functions propagate their errors through the size */
263 /* Some functions propagate their errors through the size */
269 struct AsnEncodeTagSwappedItem
272 const void *pvStructInfo
;
273 CryptEncodeObjectExFunc encodeFunc
;
276 /* Sort of a wacky hack, it encodes something using the struct
277 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
278 * given in the struct AsnEncodeTagSwappedItem.
280 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
281 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
282 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
285 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
287 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
288 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
289 if (ret
&& pbEncoded
)
290 *pbEncoded
= item
->tag
;
294 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
295 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
296 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
298 const DWORD
*ver
= pvStructInfo
;
301 /* CERT_V1 is not encoded */
309 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
311 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
312 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
317 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
318 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
319 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
321 const CRYPT_DER_BLOB
*blob
= pvStructInfo
;
326 *pcbEncoded
= blob
->cbData
;
331 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
332 pcbEncoded
, blob
->cbData
)))
334 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
335 pbEncoded
= *(BYTE
**)pbEncoded
;
337 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
338 *pcbEncoded
= blob
->cbData
;
345 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
346 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
347 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
350 /* This has two filetimes in a row, a NotBefore and a NotAfter */
351 const FILETIME
*timePtr
= pvStructInfo
;
352 struct AsnEncodeSequenceItem items
[] = {
353 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
354 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
357 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
358 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
363 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
366 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
367 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
368 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
371 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
372 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
373 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
376 struct AsnEncodeSequenceItem items
[2] = {
377 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
378 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
381 if (algo
->Parameters
.cbData
)
382 items
[1].pvStructInfo
= &algo
->Parameters
;
384 items
[1].pvStructInfo
= &nullBlob
;
385 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
386 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
391 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
392 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
393 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
395 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
397 struct AsnEncodeSequenceItem items
[] = {
398 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
399 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
402 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
403 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
408 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
409 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
410 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
416 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
417 struct AsnEncodeSequenceItem items
[] = {
418 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
419 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
422 TRACE("Encoding public key with OID %s\n",
423 debugstr_a(info
->Algorithm
.pszObjId
));
424 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
425 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
430 SetLastError(STATUS_ACCESS_VIOLATION
);
437 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
438 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
439 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
445 const CERT_SIGNED_CONTENT_INFO
*info
= pvStructInfo
;
446 struct AsnEncodeSequenceItem items
[] = {
447 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
448 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
449 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
452 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
453 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
454 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
455 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
460 SetLastError(STATUS_ACCESS_VIOLATION
);
467 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
472 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
473 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
479 const CERT_INFO
*info
= pvStructInfo
;
480 struct AsnEncodeSequenceItem items
[10] = {
481 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
482 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
483 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
484 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
485 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
486 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
487 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
490 struct AsnConstructedItem constructed
[3] = { { 0 } };
491 DWORD cItem
= 7, cConstructed
= 0;
493 if (info
->IssuerUniqueId
.cbData
)
495 constructed
[cConstructed
].tag
= 1;
496 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
497 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
498 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
499 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
503 if (info
->SubjectUniqueId
.cbData
)
505 constructed
[cConstructed
].tag
= 2;
506 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
507 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
508 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
509 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
513 if (info
->cExtension
)
515 constructed
[cConstructed
].tag
= 3;
516 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
517 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
518 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
519 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
524 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
525 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
529 SetLastError(STATUS_ACCESS_VIOLATION
);
536 static BOOL
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
537 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
539 struct AsnEncodeSequenceItem items
[3] = {
540 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
541 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
547 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
549 if (entry
->cExtension
)
551 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
552 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
556 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
557 pbEncoded
, pcbEncoded
);
559 TRACE("returning %d (%08x)\n", ret
, GetLastError());
563 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
564 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
565 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
567 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
568 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
569 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
570 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
573 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
577 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
583 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
584 bytesNeeded
= 1 + lenBytes
+ dataLen
;
586 *pcbEncoded
= bytesNeeded
;
589 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
590 pcbEncoded
, bytesNeeded
)))
592 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
593 pbEncoded
= *(BYTE
**)pbEncoded
;
594 *pbEncoded
++ = ASN_SEQUENCEOF
;
595 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
596 pbEncoded
+= lenBytes
;
597 for (i
= 0; i
< cCRLEntry
; i
++)
599 DWORD size
= dataLen
;
601 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
,
612 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
613 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
614 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
616 const DWORD
*ver
= pvStructInfo
;
619 /* CRL_V1 is not encoded */
626 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
627 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
631 /* Like in Windows, this blithely ignores the validity of the passed-in
632 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
633 * decode properly, see CRYPT_AsnDecodeCRLInfo.
635 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
636 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
637 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
643 const CRL_INFO
*info
= pvStructInfo
;
644 struct AsnEncodeSequenceItem items
[7] = {
645 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
646 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
647 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
648 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
651 struct AsnConstructedItem constructed
[1] = { { 0 } };
652 DWORD cItem
= 4, cConstructed
= 0;
654 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
656 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
657 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
662 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
663 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
666 if (info
->cExtension
)
668 constructed
[cConstructed
].tag
= 0;
669 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
670 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
671 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
672 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
677 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
678 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
682 SetLastError(STATUS_ACCESS_VIOLATION
);
689 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
693 struct AsnEncodeSequenceItem items
[3] = {
694 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
700 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
704 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
705 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
708 items
[cItem
].pvStructInfo
= &ext
->Value
;
709 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
712 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
713 pbEncoded
, pcbEncoded
);
714 TRACE("returning %d (%08x)\n", ret
, GetLastError());
718 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
719 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
720 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
726 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
727 const CERT_EXTENSIONS
*exts
= pvStructInfo
;
730 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
734 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
740 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
741 bytesNeeded
= 1 + lenBytes
+ dataLen
;
743 *pcbEncoded
= bytesNeeded
;
746 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
747 pbEncoded
, pcbEncoded
, bytesNeeded
)))
749 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
750 pbEncoded
= *(BYTE
**)pbEncoded
;
751 *pbEncoded
++ = ASN_SEQUENCEOF
;
752 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
753 pbEncoded
+= lenBytes
;
754 for (i
= 0; i
< exts
->cExtension
; i
++)
756 DWORD size
= dataLen
;
758 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
769 SetLastError(STATUS_ACCESS_VIOLATION
);
776 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
777 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
778 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
780 LPCSTR pszObjId
= pvStructInfo
;
781 DWORD bytesNeeded
= 0, lenBytes
;
786 TRACE("%s\n", debugstr_a(pszObjId
));
793 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
795 SetLastError(CRYPT_E_ASN1_ERROR
);
799 firstByte
= val1
* 40 + val2
;
800 ptr
= pszObjId
+ firstPos
;
810 /* note I assume each component is at most 32-bits long in base 2 */
811 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
813 if (val1
>= 0x10000000)
815 else if (val1
>= 0x200000)
817 else if (val1
>= 0x4000)
819 else if (val1
>= 0x80)
829 SetLastError(CRYPT_E_ASN1_ERROR
);
833 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
837 bytesNeeded
+= 1 + lenBytes
;
840 if (*pcbEncoded
< bytesNeeded
)
842 SetLastError(ERROR_MORE_DATA
);
847 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
848 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
849 pbEncoded
+= lenBytes
;
855 *pbEncoded
++ = firstByte
;
856 ptr
= pszObjId
+ firstPos
;
859 sscanf(ptr
, "%d%n", &val
, &pos
);
861 unsigned char outBytes
[5];
864 if (val
>= 0x10000000)
866 else if (val
>= 0x200000)
868 else if (val
>= 0x4000)
870 else if (val
>= 0x80)
874 for (i
= numBytes
; i
> 0; i
--)
876 outBytes
[i
- 1] = val
& 0x7f;
879 for (i
= 0; i
< numBytes
- 1; i
++)
880 *pbEncoded
++ = outBytes
[i
] | 0x80;
881 *pbEncoded
++ = outBytes
[i
];
890 *pcbEncoded
= bytesNeeded
;
894 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
895 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
899 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
900 DWORD bytesNeeded
, lenBytes
, encodedLen
;
902 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
903 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
904 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
906 *pcbEncoded
= bytesNeeded
;
909 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
910 pbEncoded
, pcbEncoded
, bytesNeeded
)))
912 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
913 pbEncoded
= *(BYTE
**)pbEncoded
;
915 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
916 pbEncoded
+= lenBytes
;
917 memcpy(pbEncoded
, str
, encodedLen
);
923 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
924 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
928 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
929 DWORD bytesNeeded
, lenBytes
, strLen
;
931 if (value
->Value
.cbData
)
932 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
933 else if (value
->Value
.pbData
)
934 strLen
= lstrlenW(str
);
937 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
938 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
940 *pcbEncoded
= bytesNeeded
;
943 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
944 pbEncoded
, pcbEncoded
, bytesNeeded
)))
948 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
949 pbEncoded
= *(BYTE
**)pbEncoded
;
950 *pbEncoded
++ = ASN_BMPSTRING
;
951 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
952 pbEncoded
+= lenBytes
;
953 for (i
= 0; i
< strLen
; i
++)
955 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
956 *pbEncoded
++ = str
[i
] & 0x00ff;
963 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
964 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
968 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
969 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
971 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
973 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
975 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
976 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
978 *pcbEncoded
= bytesNeeded
;
981 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
982 pbEncoded
, pcbEncoded
, bytesNeeded
)))
984 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
985 pbEncoded
= *(BYTE
**)pbEncoded
;
986 *pbEncoded
++ = ASN_UTF8STRING
;
987 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
988 pbEncoded
+= lenBytes
;
989 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
990 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
996 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
997 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
998 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1004 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1006 switch (value
->dwValueType
)
1008 case CERT_RDN_ANY_TYPE
:
1009 /* explicitly disallowed */
1010 SetLastError(E_INVALIDARG
);
1013 case CERT_RDN_ENCODED_BLOB
:
1014 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1015 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1017 case CERT_RDN_OCTET_STRING
:
1018 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1019 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1021 case CERT_RDN_NUMERIC_STRING
:
1022 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1023 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1025 case CERT_RDN_PRINTABLE_STRING
:
1026 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1027 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1029 case CERT_RDN_TELETEX_STRING
:
1030 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1031 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1033 case CERT_RDN_VIDEOTEX_STRING
:
1034 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1035 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1037 case CERT_RDN_IA5_STRING
:
1038 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1039 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1041 case CERT_RDN_GRAPHIC_STRING
:
1042 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1043 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1045 case CERT_RDN_VISIBLE_STRING
:
1046 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1047 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1049 case CERT_RDN_GENERAL_STRING
:
1050 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1051 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1053 case CERT_RDN_UNIVERSAL_STRING
:
1054 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1055 SetLastError(CRYPT_E_ASN1_CHOICE
);
1058 case CERT_RDN_BMP_STRING
:
1059 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1060 pbEncoded
, pcbEncoded
);
1062 case CERT_RDN_UTF8_STRING
:
1063 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1064 pbEncoded
, pcbEncoded
);
1067 SetLastError(CRYPT_E_ASN1_CHOICE
);
1073 SetLastError(STATUS_ACCESS_VIOLATION
);
1080 static BOOL
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1081 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1082 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1084 DWORD bytesNeeded
= 0, lenBytes
, size
;
1087 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1088 0, NULL
, NULL
, &size
);
1091 bytesNeeded
+= size
;
1092 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1093 * with dwValueType, so "cast" it to get its encoded size
1095 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
, &attr
->dwValueType
,
1096 0, NULL
, NULL
, &size
);
1099 bytesNeeded
+= size
;
1100 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1101 bytesNeeded
+= 1 + lenBytes
;
1104 if (*pcbEncoded
< bytesNeeded
)
1106 SetLastError(ERROR_MORE_DATA
);
1111 *pbEncoded
++ = ASN_SEQUENCE
;
1112 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1114 pbEncoded
+= lenBytes
;
1115 size
= bytesNeeded
- 1 - lenBytes
;
1116 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1117 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1121 size
= bytesNeeded
- 1 - lenBytes
- size
;
1122 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1123 &attr
->dwValueType
, 0, NULL
, pbEncoded
, &size
);
1130 *pcbEncoded
= bytesNeeded
;
1134 /* Have to propagate index of failing character */
1141 static int BLOBComp(const void *l
, const void *r
)
1143 const CRYPT_DER_BLOB
*a
= l
, *b
= r
;
1146 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1147 ret
= a
->cbData
- b
->cbData
;
1151 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1153 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1154 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1155 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1157 const CRYPT_BLOB_ARRAY
*set
= pvStructInfo
;
1158 DWORD bytesNeeded
= 0, lenBytes
, i
;
1161 for (i
= 0; i
< set
->cBlob
; i
++)
1162 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1163 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1164 bytesNeeded
+= 1 + lenBytes
;
1167 *pcbEncoded
= bytesNeeded
;
1170 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1171 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1173 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1174 pbEncoded
= *(BYTE
**)pbEncoded
;
1175 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1176 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1177 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1178 pbEncoded
+= lenBytes
;
1179 for (i
= 0; ret
&& i
< set
->cBlob
; i
++)
1181 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1182 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1188 struct DERSetDescriptor
1194 CryptEncodeObjectExFunc encode
;
1197 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1198 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1199 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1201 const struct DERSetDescriptor
*desc
= pvStructInfo
;
1202 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1208 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1213 setOf
.cBlob
= desc
->cItems
;
1214 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1217 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1219 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1220 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1221 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1224 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1225 if (!setOf
.rgBlob
[i
].pbData
)
1228 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1229 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1230 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1231 &setOf
.rgBlob
[i
].cbData
);
1233 /* Some functions propagate their errors through the size */
1235 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1239 DWORD bytesNeeded
= 0, lenBytes
;
1241 for (i
= 0; i
< setOf
.cBlob
; i
++)
1242 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1243 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1244 bytesNeeded
+= 1 + lenBytes
;
1246 *pcbEncoded
= bytesNeeded
;
1247 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1248 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1250 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1251 pbEncoded
= *(BYTE
**)pbEncoded
;
1252 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1254 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1255 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1256 pbEncoded
+= lenBytes
;
1257 for (i
= 0; i
< setOf
.cBlob
; i
++)
1259 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1260 setOf
.rgBlob
[i
].cbData
);
1261 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1265 for (i
= 0; i
< setOf
.cBlob
; i
++)
1266 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1267 CryptMemFree(setOf
.rgBlob
);
1271 static BOOL
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1272 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1276 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1285 setOf
.cBlob
= rdn
->cRDNAttr
;
1286 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1287 sizeof(CRYPT_DER_BLOB
));
1291 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1293 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1295 setOf
.rgBlob
[i
].cbData
= 0;
1296 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1297 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1300 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1301 if (!setOf
.rgBlob
[i
].pbData
)
1304 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1305 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1306 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1310 /* Have to propagate index of failing character */
1311 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1315 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1316 pbEncoded
, pcbEncoded
);
1317 for (i
= 0; i
< setOf
.cBlob
; i
++)
1318 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1322 SetLastError(STATUS_ACCESS_VIOLATION
);
1326 CryptMemFree(setOf
.rgBlob
);
1330 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1331 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1332 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1334 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1335 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1336 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1339 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1342 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1343 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1344 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1346 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1347 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1351 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1352 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1353 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1359 const CERT_NAME_INFO
*info
= pvStructInfo
;
1360 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1362 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1364 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1366 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1367 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1369 bytesNeeded
+= size
;
1373 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1374 bytesNeeded
+= 1 + lenBytes
;
1378 *pcbEncoded
= bytesNeeded
;
1381 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1382 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1384 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1385 pbEncoded
= *(BYTE
**)pbEncoded
;
1386 *pbEncoded
++ = ASN_SEQUENCEOF
;
1387 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1389 pbEncoded
+= lenBytes
;
1390 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1393 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1394 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1399 bytesNeeded
-= size
;
1410 SetLastError(STATUS_ACCESS_VIOLATION
);
1417 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1418 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1419 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1421 const DWORD
*ver
= pvStructInfo
;
1424 /* CTL_V1 is not encoded */
1431 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1432 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1436 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1437 * if they are empty and the OID is not empty (otherwise omits them.)
1439 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1440 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1441 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1444 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
1446 struct AsnEncodeSequenceItem items
[2] = {
1447 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1453 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1454 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1457 if (algo
->Parameters
.cbData
)
1458 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1460 items
[cItem
].pvStructInfo
= &nullBlob
;
1461 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1464 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1465 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1469 static BOOL
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1470 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1472 struct AsnEncodeSequenceItem items
[2] = {
1473 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1474 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1478 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1479 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
1489 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1490 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1491 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1494 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1495 const struct CTLEntries
*entries
= pvStructInfo
;
1498 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1502 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1508 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1509 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1511 *pcbEncoded
= bytesNeeded
;
1514 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1515 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1517 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1518 pbEncoded
= *(BYTE
**)pbEncoded
;
1519 *pbEncoded
++ = ASN_SEQUENCEOF
;
1520 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1521 pbEncoded
+= lenBytes
;
1522 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1524 DWORD size
= dataLen
;
1526 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1537 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1538 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1539 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1545 const CTL_INFO
*info
= pvStructInfo
;
1546 struct AsnEncodeSequenceItem items
[9] = {
1547 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1548 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1550 struct AsnConstructedItem constructed
= { 0 };
1553 if (info
->ListIdentifier
.cbData
)
1555 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1556 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1559 if (info
->SequenceNumber
.cbData
)
1561 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1562 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1565 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1566 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1568 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1570 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1571 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1574 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1575 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1577 if (info
->cCTLEntry
)
1579 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1580 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1583 if (info
->cExtension
)
1585 constructed
.tag
= 0;
1586 constructed
.pvStructInfo
= &info
->cExtension
;
1587 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1588 items
[cItem
].pvStructInfo
= &constructed
;
1589 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1592 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1593 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1597 SetLastError(STATUS_ACCESS_VIOLATION
);
1603 static BOOL
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1604 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1605 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1611 const CRYPT_SMIME_CAPABILITY
*capability
= pvStructInfo
;
1613 if (!capability
->pszObjId
)
1614 SetLastError(E_INVALIDARG
);
1617 struct AsnEncodeSequenceItem items
[] = {
1618 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1619 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1622 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1623 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1629 SetLastError(STATUS_ACCESS_VIOLATION
);
1635 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1636 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1637 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1643 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1644 const CRYPT_SMIME_CAPABILITIES
*capabilities
= pvStructInfo
;
1647 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1651 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1652 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1658 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1659 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1661 *pcbEncoded
= bytesNeeded
;
1664 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1665 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1667 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1668 pbEncoded
= *(BYTE
**)pbEncoded
;
1669 *pbEncoded
++ = ASN_SEQUENCEOF
;
1670 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1671 pbEncoded
+= lenBytes
;
1672 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1674 DWORD size
= dataLen
;
1676 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1677 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1688 SetLastError(STATUS_ACCESS_VIOLATION
);
1694 static BOOL WINAPI
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType
,
1695 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1696 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1698 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1699 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1702 for (i
= 0, dataLen
= 0; ret
&& i
< noticeRef
->cNoticeNumbers
; i
++)
1706 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1707 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, NULL
, &size
);
1713 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1714 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1716 *pcbEncoded
= bytesNeeded
;
1719 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1720 pcbEncoded
, bytesNeeded
)))
1722 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1723 pbEncoded
= *(BYTE
**)pbEncoded
;
1724 *pbEncoded
++ = ASN_SEQUENCE
;
1725 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1726 pbEncoded
+= lenBytes
;
1727 for (i
= 0; i
< noticeRef
->cNoticeNumbers
; i
++)
1729 DWORD size
= dataLen
;
1731 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1732 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, pbEncoded
, &size
);
1742 static BOOL WINAPI
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType
,
1743 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1744 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1746 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1748 CERT_NAME_VALUE orgValue
= { CERT_RDN_IA5_STRING
,
1749 { 0, (LPBYTE
)noticeRef
->pszOrganization
} };
1750 struct AsnEncodeSequenceItem items
[] = {
1751 { &orgValue
, CRYPT_AsnEncodeNameValue
, 0 },
1752 { noticeRef
, CRYPT_AsnEncodeNoticeNumbers
, 0 },
1755 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1756 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1761 static BOOL WINAPI
CRYPT_AsnEncodePolicyQualifierUserNotice(
1762 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1763 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1770 const CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
= pvStructInfo
;
1771 struct AsnEncodeSequenceItem items
[2];
1772 CERT_NAME_VALUE displayTextValue
;
1776 if (notice
->pNoticeReference
)
1778 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNoticeReference
;
1779 items
[cItem
].pvStructInfo
= notice
->pNoticeReference
;
1782 if (notice
->pszDisplayText
)
1784 displayTextValue
.dwValueType
= CERT_RDN_BMP_STRING
;
1785 displayTextValue
.Value
.cbData
= 0;
1786 displayTextValue
.Value
.pbData
= (LPBYTE
)notice
->pszDisplayText
;
1787 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNameValue
;
1788 items
[cItem
].pvStructInfo
= &displayTextValue
;
1791 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1792 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1796 SetLastError(STATUS_ACCESS_VIOLATION
);
1802 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1803 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1804 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1810 const CRYPT_ATTRIBUTE
*attr
= pvStructInfo
;
1812 if (!attr
->pszObjId
)
1813 SetLastError(E_INVALIDARG
);
1816 struct AsnEncodeSequenceItem items
[2] = {
1817 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1818 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1821 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1822 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1828 SetLastError(STATUS_ACCESS_VIOLATION
);
1834 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1835 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1836 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1842 const CRYPT_ATTRIBUTES
*attributes
= pvStructInfo
;
1843 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1844 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1846 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1847 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1851 SetLastError(STATUS_ACCESS_VIOLATION
);
1857 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1858 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1859 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1860 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1863 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1864 struct AsnEncodeSequenceItem items
[2] = {
1865 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1868 struct AsnConstructedItem constructed
= { 0 };
1871 if (info
->Content
.cbData
)
1873 constructed
.tag
= 0;
1874 constructed
.pvStructInfo
= &info
->Content
;
1875 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1876 items
[cItem
].pvStructInfo
= &constructed
;
1877 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1880 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1881 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1884 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1885 void *pvData
, DWORD
*pcbData
)
1887 struct AsnEncodeSequenceItem items
[] = {
1888 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1889 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1891 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1892 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1895 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1896 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1899 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1900 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1901 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1907 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1909 if (!info
->pszObjId
)
1910 SetLastError(E_INVALIDARG
);
1912 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1913 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1918 SetLastError(STATUS_ACCESS_VIOLATION
);
1924 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1925 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1929 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1930 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1932 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1934 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1935 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1937 *pcbEncoded
= bytesNeeded
;
1940 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1941 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1945 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1946 pbEncoded
= *(BYTE
**)pbEncoded
;
1948 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1949 pbEncoded
+= lenBytes
;
1950 for (i
= 0; i
< encodedLen
; i
++)
1951 *pbEncoded
++ = (BYTE
)str
[i
];
1957 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara
, LPVOID pv
)
1959 if (pEncodePara
&& pEncodePara
->pfnFree
)
1960 pEncodePara
->pfnFree(pv
);
1965 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1966 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1970 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1971 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1973 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1975 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1976 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1978 *pcbEncoded
= bytesNeeded
;
1981 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1982 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1987 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1988 ptr
= *(BYTE
**)pbEncoded
;
1991 *ptr
++ = ASN_NUMERICSTRING
;
1992 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1994 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1996 if (isdigitW(str
[i
]))
1997 *ptr
++ = (BYTE
)str
[i
];
2001 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2005 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2006 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2012 static inline int isprintableW(WCHAR wc
)
2014 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
2015 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
2016 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
2019 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2020 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2024 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2025 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2027 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2029 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2030 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2032 *pcbEncoded
= bytesNeeded
;
2035 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2036 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2041 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2042 ptr
= *(BYTE
**)pbEncoded
;
2045 *ptr
++ = ASN_PRINTABLESTRING
;
2046 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2048 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2050 if (isprintableW(str
[i
]))
2051 *ptr
++ = (BYTE
)str
[i
];
2055 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2059 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2060 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2066 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2067 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2071 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2072 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2074 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2076 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2077 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2079 *pcbEncoded
= bytesNeeded
;
2082 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2083 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2088 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2089 ptr
= *(BYTE
**)pbEncoded
;
2092 *ptr
++ = ASN_IA5STRING
;
2093 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2095 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2098 *ptr
++ = (BYTE
)str
[i
];
2102 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2106 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2107 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2113 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2114 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2118 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2119 DWORD bytesNeeded
, lenBytes
, strLen
;
2121 /* FIXME: doesn't handle composite characters */
2122 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2124 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2125 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2127 *pcbEncoded
= bytesNeeded
;
2130 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2131 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2135 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2136 pbEncoded
= *(BYTE
**)pbEncoded
;
2137 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2138 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2139 pbEncoded
+= lenBytes
;
2140 for (i
= 0; i
< strLen
; i
++)
2144 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2145 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2152 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2153 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2154 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2160 const CERT_NAME_VALUE
*value
= pvStructInfo
;
2162 switch (value
->dwValueType
)
2164 case CERT_RDN_ANY_TYPE
:
2165 case CERT_RDN_ENCODED_BLOB
:
2166 case CERT_RDN_OCTET_STRING
:
2167 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2169 case CERT_RDN_NUMERIC_STRING
:
2170 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2171 pbEncoded
, pcbEncoded
);
2173 case CERT_RDN_PRINTABLE_STRING
:
2174 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2175 pbEncoded
, pcbEncoded
);
2177 case CERT_RDN_TELETEX_STRING
:
2178 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2179 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2181 case CERT_RDN_VIDEOTEX_STRING
:
2182 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2183 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2185 case CERT_RDN_IA5_STRING
:
2186 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2187 pbEncoded
, pcbEncoded
);
2189 case CERT_RDN_GRAPHIC_STRING
:
2190 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2191 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2193 case CERT_RDN_VISIBLE_STRING
:
2194 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2195 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2197 case CERT_RDN_GENERAL_STRING
:
2198 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2199 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2201 case CERT_RDN_UNIVERSAL_STRING
:
2202 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2203 pbEncoded
, pcbEncoded
);
2205 case CERT_RDN_BMP_STRING
:
2206 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2207 pbEncoded
, pcbEncoded
);
2209 case CERT_RDN_UTF8_STRING
:
2210 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2211 pbEncoded
, pcbEncoded
);
2214 SetLastError(CRYPT_E_ASN1_CHOICE
);
2219 SetLastError(STATUS_ACCESS_VIOLATION
);
2225 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2226 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2227 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2233 const CERT_NAME_INFO
*info
= pvStructInfo
;
2234 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2236 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2238 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2240 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2241 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2243 bytesNeeded
+= size
;
2245 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2246 bytesNeeded
+= 1 + lenBytes
;
2250 *pcbEncoded
= bytesNeeded
;
2253 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2254 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2256 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2257 pbEncoded
= *(BYTE
**)pbEncoded
;
2258 *pbEncoded
++ = ASN_SEQUENCEOF
;
2259 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2261 pbEncoded
+= lenBytes
;
2262 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2265 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2266 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
2271 bytesNeeded
-= size
;
2280 SetLastError(STATUS_ACCESS_VIOLATION
);
2287 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2288 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2289 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2291 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2300 else if (*pcbEncoded
< 3)
2303 SetLastError(ERROR_MORE_DATA
);
2309 *pbEncoded
++ = ASN_BOOL
;
2311 *pbEncoded
++ = val
? 0xff : 0;
2314 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2318 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2319 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2320 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2322 const CERT_ALT_NAME_ENTRY
*entry
= pvStructInfo
;
2328 switch (entry
->dwAltNameChoice
)
2330 case CERT_ALT_NAME_RFC822_NAME
:
2331 case CERT_ALT_NAME_DNS_NAME
:
2332 case CERT_ALT_NAME_URL
:
2333 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2334 if (entry
->u
.pwszURL
)
2338 /* Not + 1: don't encode the NULL-terminator */
2339 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2340 for (i
= 0; ret
&& i
< dataLen
; i
++)
2342 if (entry
->u
.pwszURL
[i
] > 0x7f)
2344 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2353 case CERT_ALT_NAME_DIRECTORY_NAME
:
2354 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2355 dataLen
= entry
->u
.DirectoryName
.cbData
;
2357 case CERT_ALT_NAME_IP_ADDRESS
:
2358 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2359 dataLen
= entry
->u
.IPAddress
.cbData
;
2361 case CERT_ALT_NAME_REGISTERED_ID
:
2363 struct AsnEncodeTagSwappedItem swapped
=
2364 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2365 CRYPT_AsnEncodeOid
};
2367 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2370 case CERT_ALT_NAME_OTHER_NAME
:
2371 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2374 SetLastError(E_INVALIDARG
);
2379 DWORD bytesNeeded
, lenBytes
;
2381 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2382 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2384 *pcbEncoded
= bytesNeeded
;
2385 else if (*pcbEncoded
< bytesNeeded
)
2387 SetLastError(ERROR_MORE_DATA
);
2388 *pcbEncoded
= bytesNeeded
;
2394 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2395 pbEncoded
+= lenBytes
;
2396 switch (entry
->dwAltNameChoice
)
2398 case CERT_ALT_NAME_RFC822_NAME
:
2399 case CERT_ALT_NAME_DNS_NAME
:
2400 case CERT_ALT_NAME_URL
:
2404 for (i
= 0; i
< dataLen
; i
++)
2405 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2408 case CERT_ALT_NAME_DIRECTORY_NAME
:
2409 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2411 case CERT_ALT_NAME_IP_ADDRESS
:
2412 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2416 *pcbEncoded
= bytesNeeded
;
2419 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2423 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2424 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2425 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2431 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
2432 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2437 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2442 for (i
= 0; i
< newBlob
.cbData
; i
++)
2443 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2449 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2450 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2451 CryptMemFree(newBlob
.pbData
);
2455 SetLastError(STATUS_ACCESS_VIOLATION
);
2462 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2463 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2464 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2470 const CERT_AUTHORITY_KEY_ID_INFO
*info
= pvStructInfo
;
2471 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2472 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2473 struct AsnConstructedItem constructed
= { 0 };
2474 DWORD cItem
= 0, cSwapped
= 0;
2476 if (info
->KeyId
.cbData
)
2478 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2479 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2480 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2481 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2482 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2486 if (info
->CertIssuer
.cbData
)
2488 constructed
.tag
= 1;
2489 constructed
.pvStructInfo
= &info
->CertIssuer
;
2490 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2491 items
[cItem
].pvStructInfo
= &constructed
;
2492 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2495 if (info
->CertSerialNumber
.cbData
)
2497 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2498 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2499 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2500 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2501 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2505 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2506 pEncodePara
, pbEncoded
, pcbEncoded
);
2510 SetLastError(STATUS_ACCESS_VIOLATION
);
2517 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2518 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2519 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2525 const CERT_ALT_NAME_INFO
*info
= pvStructInfo
;
2526 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2529 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2530 * can't encode an erroneous entry index if it's bigger than this.
2532 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2536 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2537 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2540 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2542 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2543 * the bad character, now set the index of the bad
2546 *pcbEncoded
= (BYTE
)i
<<
2547 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2552 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2553 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2556 *pcbEncoded
= bytesNeeded
;
2561 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2562 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2564 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2565 pbEncoded
= *(BYTE
**)pbEncoded
;
2566 *pbEncoded
++ = ASN_SEQUENCEOF
;
2567 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2568 pbEncoded
+= lenBytes
;
2569 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2571 DWORD len
= dataLen
;
2573 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2574 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, pbEncoded
, &len
);
2587 SetLastError(STATUS_ACCESS_VIOLATION
);
2594 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2595 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2596 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2602 const CERT_AUTHORITY_KEY_ID2_INFO
*info
= pvStructInfo
;
2603 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2604 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2605 DWORD cItem
= 0, cSwapped
= 0;
2607 if (info
->KeyId
.cbData
)
2609 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2610 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2611 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2612 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2613 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2617 if (info
->AuthorityCertIssuer
.cAltEntry
)
2619 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2620 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2621 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2622 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2623 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2627 if (info
->AuthorityCertSerialNumber
.cbData
)
2629 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2630 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2631 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2632 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2633 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2637 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2638 pEncodePara
, pbEncoded
, pcbEncoded
);
2642 SetLastError(STATUS_ACCESS_VIOLATION
);
2649 static BOOL
CRYPT_AsnEncodeAccessDescription(
2650 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2652 struct AsnEncodeSequenceItem items
[] = {
2653 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2654 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2657 if (!descr
->pszAccessMethod
)
2659 SetLastError(E_INVALIDARG
);
2662 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
2663 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
2666 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2667 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2668 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2674 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2675 const CERT_AUTHORITY_INFO_ACCESS
*info
= pvStructInfo
;
2678 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2682 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2689 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2690 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2692 *pcbEncoded
= bytesNeeded
;
2695 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2696 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2698 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2699 pbEncoded
= *(BYTE
**)pbEncoded
;
2700 *pbEncoded
++ = ASN_SEQUENCEOF
;
2701 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2702 pbEncoded
+= lenBytes
;
2703 for (i
= 0; i
< info
->cAccDescr
; i
++)
2705 DWORD size
= dataLen
;
2707 ret
= CRYPT_AsnEncodeAccessDescription(
2708 &info
->rgAccDescr
[i
], pbEncoded
, &size
);
2718 SetLastError(STATUS_ACCESS_VIOLATION
);
2725 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2726 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2727 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2733 const CERT_BASIC_CONSTRAINTS_INFO
*info
= pvStructInfo
;
2734 struct AsnEncodeSequenceItem items
[3] = {
2735 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2740 if (info
->fPathLenConstraint
)
2742 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2743 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2746 if (info
->cSubtreesConstraint
)
2748 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2749 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2752 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2753 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2757 SetLastError(STATUS_ACCESS_VIOLATION
);
2764 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2765 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2766 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2772 const CERT_BASIC_CONSTRAINTS2_INFO
*info
= pvStructInfo
;
2773 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2778 items
[cItem
].pvStructInfo
= &info
->fCA
;
2779 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2782 if (info
->fPathLenConstraint
)
2784 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2785 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2788 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2789 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2793 SetLastError(STATUS_ACCESS_VIOLATION
);
2800 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2801 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2802 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2804 DWORD cPolicyQualifier
= *(DWORD
*)pvStructInfo
;
2805 const CERT_POLICY_QUALIFIER_INFO
*rgPolicyQualifier
=
2806 *(const CERT_POLICY_QUALIFIER_INFO
**)
2807 ((LPBYTE
)pvStructInfo
+ sizeof(DWORD
));
2810 if (!cPolicyQualifier
)
2817 struct AsnEncodeSequenceItem items
[2] = {
2818 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2819 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2821 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2824 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2826 items
[0].pvStructInfo
= rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2827 items
[1].pvStructInfo
= &rgPolicyQualifier
[i
].Qualifier
;
2828 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2829 sizeof(items
) / sizeof(items
[0]),
2830 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2832 bytesNeeded
+= size
;
2834 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2835 bytesNeeded
+= 1 + lenBytes
;
2839 *pcbEncoded
= bytesNeeded
;
2842 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2843 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2845 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2846 pbEncoded
= *(BYTE
**)pbEncoded
;
2847 *pbEncoded
++ = ASN_SEQUENCEOF
;
2848 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2850 pbEncoded
+= lenBytes
;
2851 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2853 items
[0].pvStructInfo
=
2854 rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2855 items
[1].pvStructInfo
=
2856 &rgPolicyQualifier
[i
].Qualifier
;
2858 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2859 sizeof(items
) / sizeof(items
[0]),
2860 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2865 bytesNeeded
-= size
;
2875 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2876 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2879 struct AsnEncodeSequenceItem items
[2] = {
2880 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2881 { &info
->cPolicyQualifier
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2885 if (!info
->pszPolicyIdentifier
)
2887 SetLastError(E_INVALIDARG
);
2890 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2891 sizeof(items
) / sizeof(items
[0]), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2895 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2896 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2897 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2903 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2904 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2907 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2909 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2910 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2913 bytesNeeded
+= size
;
2915 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2916 bytesNeeded
+= 1 + lenBytes
;
2920 *pcbEncoded
= bytesNeeded
;
2923 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2924 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2926 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2927 pbEncoded
= *(BYTE
**)pbEncoded
;
2928 *pbEncoded
++ = ASN_SEQUENCEOF
;
2929 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2931 pbEncoded
+= lenBytes
;
2932 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2935 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2936 &info
->rgPolicyInfo
[i
],
2937 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pbEncoded
, &size
);
2941 bytesNeeded
-= size
;
2950 SetLastError(STATUS_ACCESS_VIOLATION
);
2956 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2957 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2958 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2964 const BLOBHEADER
*hdr
= pvStructInfo
;
2966 if (hdr
->bType
!= PUBLICKEYBLOB
)
2968 SetLastError(E_INVALIDARG
);
2973 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2974 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2975 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2976 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2977 struct AsnEncodeSequenceItem items
[] = {
2978 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2979 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2982 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2983 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2989 SetLastError(STATUS_ACCESS_VIOLATION
);
2996 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2997 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2998 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3004 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
3005 DWORD bytesNeeded
, lenBytes
;
3007 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3008 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
3010 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3011 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3014 *pcbEncoded
= bytesNeeded
;
3019 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3020 pcbEncoded
, bytesNeeded
)))
3022 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3023 pbEncoded
= *(BYTE
**)pbEncoded
;
3024 *pbEncoded
++ = ASN_OCTETSTRING
;
3025 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3026 pbEncoded
+= lenBytes
;
3028 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3034 SetLastError(STATUS_ACCESS_VIOLATION
);
3038 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3042 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3043 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3044 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3050 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3051 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3054 /* yep, MS allows cUnusedBits to be >= 8 */
3055 if (!blob
->cUnusedBits
)
3057 dataBytes
= blob
->cbData
;
3060 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3062 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3063 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3071 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3072 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3075 *pcbEncoded
= bytesNeeded
;
3080 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3081 pcbEncoded
, bytesNeeded
)))
3083 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3084 pbEncoded
= *(BYTE
**)pbEncoded
;
3085 *pbEncoded
++ = ASN_BITSTRING
;
3086 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3087 pbEncoded
+= lenBytes
;
3088 *pbEncoded
++ = unusedBits
;
3091 BYTE mask
= 0xff << unusedBits
;
3095 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3096 pbEncoded
+= dataBytes
- 1;
3098 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3105 SetLastError(STATUS_ACCESS_VIOLATION
);
3112 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3113 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3114 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3120 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3121 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3126 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3131 for (i
= 0; i
< newBlob
.cbData
; i
++)
3132 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3138 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3139 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3140 CryptMemFree(newBlob
.pbData
);
3144 SetLastError(STATUS_ACCESS_VIOLATION
);
3151 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3152 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3153 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3155 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3157 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3158 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3161 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3162 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3163 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3169 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3172 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3174 significantBytes
= blob
->cbData
;
3175 if (significantBytes
)
3177 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3179 /* negative, lop off leading (little-endian) 0xffs */
3180 for (; significantBytes
> 0 &&
3181 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3183 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3191 /* positive, lop off leading (little-endian) zeroes */
3192 for (; significantBytes
> 0 &&
3193 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3195 if (significantBytes
== 0)
3196 significantBytes
= 1;
3197 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3205 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3207 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3208 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3213 *pcbEncoded
= bytesNeeded
;
3218 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3219 pcbEncoded
, bytesNeeded
)))
3221 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3222 pbEncoded
= *(BYTE
**)pbEncoded
;
3223 *pbEncoded
++ = ASN_INTEGER
;
3226 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3227 pbEncoded
+= lenBytes
;
3228 *pbEncoded
++ = padByte
;
3232 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3233 pbEncoded
+= lenBytes
;
3235 for (; significantBytes
> 0; significantBytes
--)
3236 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3242 SetLastError(STATUS_ACCESS_VIOLATION
);
3249 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3250 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3251 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3257 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3259 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3261 significantBytes
= blob
->cbData
;
3262 if (significantBytes
)
3264 /* positive, lop off leading (little-endian) zeroes */
3265 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3268 if (significantBytes
== 0)
3269 significantBytes
= 1;
3270 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3274 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3276 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3277 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3282 *pcbEncoded
= bytesNeeded
;
3287 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3288 pcbEncoded
, bytesNeeded
)))
3290 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3291 pbEncoded
= *(BYTE
**)pbEncoded
;
3292 *pbEncoded
++ = ASN_INTEGER
;
3295 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3296 pbEncoded
+= lenBytes
;
3301 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3302 pbEncoded
+= lenBytes
;
3304 for (; significantBytes
> 0; significantBytes
--)
3305 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3311 SetLastError(STATUS_ACCESS_VIOLATION
);
3318 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3319 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3320 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3322 CRYPT_INTEGER_BLOB blob
;
3325 /* Encode as an unsigned integer, then change the tag to enumerated */
3326 blob
.cbData
= sizeof(DWORD
);
3327 blob
.pbData
= (BYTE
*)pvStructInfo
;
3328 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3329 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3330 if (ret
&& pbEncoded
)
3332 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3333 pbEncoded
= *(BYTE
**)pbEncoded
;
3334 pbEncoded
[0] = ASN_ENUMERATED
;
3339 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3340 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3341 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3348 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3349 * temporary buffer because the output buffer is not NULL-terminated.
3352 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3356 *pcbEncoded
= bytesNeeded
;
3361 /* Sanity check the year, this is a two-digit year format */
3362 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3363 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3365 SetLastError(CRYPT_E_BAD_ENCODE
);
3370 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3371 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3373 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3374 pbEncoded
= *(BYTE
**)pbEncoded
;
3375 buf
[0] = ASN_UTCTIME
;
3376 buf
[1] = bytesNeeded
- 2;
3377 snprintf(buf
+ 2, sizeof(buf
) - 2,
3378 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3379 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3380 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3381 sysTime
.wMinute
, sysTime
.wSecond
);
3382 memcpy(pbEncoded
, buf
, bytesNeeded
);
3389 SetLastError(STATUS_ACCESS_VIOLATION
);
3396 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3397 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3398 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3405 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3406 * temporary buffer because the output buffer is not NULL-terminated.
3409 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3413 *pcbEncoded
= bytesNeeded
;
3418 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3420 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3421 pcbEncoded
, bytesNeeded
);
3424 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3425 pbEncoded
= *(BYTE
**)pbEncoded
;
3426 buf
[0] = ASN_GENERALTIME
;
3427 buf
[1] = bytesNeeded
- 2;
3428 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3429 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3430 sysTime
.wMinute
, sysTime
.wSecond
);
3431 memcpy(pbEncoded
, buf
, bytesNeeded
);
3437 SetLastError(STATUS_ACCESS_VIOLATION
);
3444 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3445 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3446 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3454 /* Check the year, if it's in the UTCTime range call that encode func */
3455 if (!FileTimeToSystemTime(pvStructInfo
, &sysTime
))
3457 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3458 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3459 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3461 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3462 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3467 SetLastError(STATUS_ACCESS_VIOLATION
);
3474 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3475 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3476 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3482 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3483 const CRYPT_SEQUENCE_OF_ANY
*seq
= pvStructInfo
;
3485 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3486 dataLen
+= seq
->rgValue
[i
].cbData
;
3487 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3488 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3491 *pcbEncoded
= bytesNeeded
;
3496 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3497 pcbEncoded
, bytesNeeded
)))
3499 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3500 pbEncoded
= *(BYTE
**)pbEncoded
;
3501 *pbEncoded
++ = ASN_SEQUENCEOF
;
3502 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3503 pbEncoded
+= lenBytes
;
3504 for (i
= 0; i
< seq
->cValue
; i
++)
3506 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3507 seq
->rgValue
[i
].cbData
);
3508 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3515 SetLastError(STATUS_ACCESS_VIOLATION
);
3522 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3523 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3526 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3527 struct AsnConstructedItem constructed
= { 0 };
3528 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3529 DWORD cItem
= 0, cSwapped
= 0;
3531 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3533 case CRL_DIST_POINT_NO_NAME
:
3536 case CRL_DIST_POINT_FULL_NAME
:
3537 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3538 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3539 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3540 constructed
.tag
= 0;
3541 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3542 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3543 items
[cItem
].pvStructInfo
= &constructed
;
3544 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3548 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3549 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3555 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3557 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3558 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3559 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3560 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3561 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3565 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3567 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3568 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3569 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3570 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3571 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3576 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3577 pbEncoded
, pcbEncoded
);
3581 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3582 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3583 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3589 const CRL_DIST_POINTS_INFO
*info
= pvStructInfo
;
3591 if (!info
->cDistPoint
)
3593 SetLastError(E_INVALIDARG
);
3598 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3601 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3605 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3609 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3611 /* Have to propagate index of failing character */
3617 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3618 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3621 *pcbEncoded
= bytesNeeded
;
3626 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3627 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3629 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3630 pbEncoded
= *(BYTE
**)pbEncoded
;
3631 *pbEncoded
++ = ASN_SEQUENCEOF
;
3632 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3633 pbEncoded
+= lenBytes
;
3634 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3636 DWORD len
= dataLen
;
3638 ret
= CRYPT_AsnEncodeDistPoint(
3639 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3653 SetLastError(STATUS_ACCESS_VIOLATION
);
3660 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3661 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3662 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3668 const CERT_ENHKEY_USAGE
*usage
= pvStructInfo
;
3669 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3672 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3674 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3675 usage
->rgpszUsageIdentifier
[i
],
3676 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3678 bytesNeeded
+= size
;
3680 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3681 bytesNeeded
+= 1 + lenBytes
;
3685 *pcbEncoded
= bytesNeeded
;
3688 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3689 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3691 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3692 pbEncoded
= *(BYTE
**)pbEncoded
;
3693 *pbEncoded
++ = ASN_SEQUENCEOF
;
3694 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3696 pbEncoded
+= lenBytes
;
3697 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3700 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3701 usage
->rgpszUsageIdentifier
[i
],
3702 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3707 bytesNeeded
-= size
;
3716 SetLastError(STATUS_ACCESS_VIOLATION
);
3723 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3724 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3725 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3731 const CRL_ISSUING_DIST_POINT
*point
= pvStructInfo
;
3732 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3733 struct AsnConstructedItem constructed
= { 0 };
3734 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3735 DWORD cItem
= 0, cSwapped
= 0;
3738 switch (point
->DistPointName
.dwDistPointNameChoice
)
3740 case CRL_DIST_POINT_NO_NAME
:
3743 case CRL_DIST_POINT_FULL_NAME
:
3744 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3745 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3746 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3747 constructed
.tag
= 0;
3748 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3749 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3750 items
[cItem
].pvStructInfo
= &constructed
;
3751 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3756 SetLastError(E_INVALIDARG
);
3759 if (ret
&& point
->fOnlyContainsUserCerts
)
3761 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3762 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3763 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3764 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3765 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3769 if (ret
&& point
->fOnlyContainsCACerts
)
3771 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3772 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3773 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3774 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3775 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3779 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3781 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3782 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3783 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3784 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3785 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3789 if (ret
&& point
->fIndirectCRL
)
3791 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3792 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3793 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3794 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3795 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3800 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3801 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3805 SetLastError(STATUS_ACCESS_VIOLATION
);
3812 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3813 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3814 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3817 const CERT_GENERAL_SUBTREE
*subtree
= pvStructInfo
;
3818 struct AsnEncodeSequenceItem items
[3] = {
3819 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
3822 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3823 DWORD cItem
= 1, cSwapped
= 0;
3825 if (subtree
->dwMinimum
)
3827 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3828 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
3829 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3830 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3831 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3835 if (subtree
->fMaximum
)
3837 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3838 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
3839 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3840 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3841 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3845 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
3846 pEncodePara
, pbEncoded
, pcbEncoded
);
3850 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
3851 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3852 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3855 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
3857 TRACE("%p\n", pvStructInfo
);
3861 const CERT_NAME_CONSTRAINTS_INFO
*constraints
= pvStructInfo
;
3862 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
3863 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3864 DWORD i
, cItem
= 0, cSwapped
= 0;
3867 if (constraints
->cPermittedSubtree
)
3869 permitted
.rgBlob
= CryptMemAlloc(
3870 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
3871 if (permitted
.rgBlob
)
3873 permitted
.cBlob
= constraints
->cPermittedSubtree
;
3874 memset(permitted
.rgBlob
, 0,
3875 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3876 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
3877 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3878 NULL
, &constraints
->rgPermittedSubtree
[i
],
3879 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3880 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
3881 &permitted
.rgBlob
[i
].cbData
);
3884 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3885 swapped
[cSwapped
].pvStructInfo
= &permitted
;
3886 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3887 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3888 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3896 if (constraints
->cExcludedSubtree
)
3898 excluded
.rgBlob
= CryptMemAlloc(
3899 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
3900 if (excluded
.rgBlob
)
3902 excluded
.cBlob
= constraints
->cExcludedSubtree
;
3903 memset(excluded
.rgBlob
, 0,
3904 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3905 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
3906 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3907 NULL
, &constraints
->rgExcludedSubtree
[i
],
3908 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3909 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
3910 &excluded
.rgBlob
[i
].cbData
);
3913 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3914 swapped
[cSwapped
].pvStructInfo
= &excluded
;
3915 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3916 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3917 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3926 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3927 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3928 for (i
= 0; i
< permitted
.cBlob
; i
++)
3929 LocalFree(permitted
.rgBlob
[i
].pbData
);
3930 for (i
= 0; i
< excluded
.cBlob
; i
++)
3931 LocalFree(excluded
.rgBlob
[i
].pbData
);
3935 SetLastError(STATUS_ACCESS_VIOLATION
);
3938 CryptMemFree(permitted
.rgBlob
);
3939 CryptMemFree(excluded
.rgBlob
);
3940 TRACE("returning %d\n", ret
);
3944 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3945 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3946 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3950 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
= pvStructInfo
;
3951 struct AsnEncodeSequenceItem items
[] = {
3952 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3953 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3956 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3957 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3962 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3963 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3964 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3968 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3970 SetLastError(E_INVALIDARG
);
3976 const CMSG_SIGNER_INFO
*info
= pvStructInfo
;
3978 if (!info
->Issuer
.cbData
)
3979 SetLastError(E_INVALIDARG
);
3982 struct AsnEncodeSequenceItem items
[7] = {
3983 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3984 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3985 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
3988 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3989 DWORD cItem
= 3, cSwapped
= 0;
3991 if (info
->AuthAttrs
.cAttr
)
3993 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3994 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3995 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3996 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3997 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4001 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4002 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4004 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4005 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4007 if (info
->UnauthAttrs
.cAttr
)
4009 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4010 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4011 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4012 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4013 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4017 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4018 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4023 SetLastError(STATUS_ACCESS_VIOLATION
);
4029 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4030 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4031 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4035 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4037 SetLastError(E_INVALIDARG
);
4043 const CMSG_CMS_SIGNER_INFO
*info
= pvStructInfo
;
4045 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4046 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4047 SetLastError(E_INVALIDARG
);
4048 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4049 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4050 SetLastError(E_INVALIDARG
);
4053 struct AsnEncodeSequenceItem items
[7] = {
4054 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4056 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4057 DWORD cItem
= 1, cSwapped
= 0;
4059 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4061 items
[cItem
].pvStructInfo
=
4062 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4063 items
[cItem
].encodeFunc
=
4064 CRYPT_AsnEncodeIssuerSerialNumber
;
4069 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4070 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4071 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4072 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4073 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4077 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4078 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4080 if (info
->AuthAttrs
.cAttr
)
4082 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4083 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4084 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4085 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4086 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4090 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4091 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4093 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4094 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4096 if (info
->UnauthAttrs
.cAttr
)
4098 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4099 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4100 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4101 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4102 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4106 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4107 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4112 SetLastError(STATUS_ACCESS_VIOLATION
);
4118 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4121 struct AsnEncodeSequenceItem items
[7] = {
4122 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4124 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4125 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4126 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4127 DWORD cItem
= 1, cSwapped
= 0;
4130 if (signedInfo
->cSignerInfo
)
4132 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4133 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4134 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4135 digestAlgorithmsSet
.itemOffset
=
4136 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4137 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4138 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4139 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4142 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4143 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4145 if (signedInfo
->cCertEncoded
)
4147 certSet
.cItems
= signedInfo
->cCertEncoded
;
4148 certSet
.items
= signedInfo
->rgCertEncoded
;
4149 certSet
.itemSize
= sizeof(CERT_BLOB
);
4150 certSet
.itemOffset
= 0;
4151 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4152 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4153 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4154 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4155 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4156 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4160 if (signedInfo
->cCrlEncoded
)
4162 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4163 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4164 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4165 crlSet
.itemOffset
= 0;
4166 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4167 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4168 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4169 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4170 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4171 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4175 if (ret
&& signedInfo
->cSignerInfo
)
4177 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4178 signerSet
.items
= signedInfo
->rgSignerInfo
;
4179 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4180 signerSet
.itemOffset
= 0;
4181 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4182 items
[cItem
].pvStructInfo
= &signerSet
;
4183 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4187 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4188 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4193 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4194 LPCSTR lpszStructType
)
4196 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4198 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4199 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4201 SetLastError(ERROR_FILE_NOT_FOUND
);
4205 if (!HIWORD(lpszStructType
))
4207 switch (LOWORD(lpszStructType
))
4209 case LOWORD(X509_CERT
):
4210 encodeFunc
= CRYPT_AsnEncodeCert
;
4212 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4213 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4215 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4216 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4218 case LOWORD(X509_EXTENSIONS
):
4219 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4221 case LOWORD(X509_NAME_VALUE
):
4222 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4224 case LOWORD(X509_NAME
):
4225 encodeFunc
= CRYPT_AsnEncodeName
;
4227 case LOWORD(X509_PUBLIC_KEY_INFO
):
4228 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4230 case LOWORD(X509_AUTHORITY_KEY_ID
):
4231 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4233 case LOWORD(X509_ALTERNATE_NAME
):
4234 encodeFunc
= CRYPT_AsnEncodeAltName
;
4236 case LOWORD(X509_BASIC_CONSTRAINTS
):
4237 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4239 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4240 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4242 case LOWORD(X509_CERT_POLICIES
):
4243 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4245 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4246 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4248 case LOWORD(X509_UNICODE_NAME
):
4249 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4251 case LOWORD(PKCS_CONTENT_INFO
):
4252 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4254 case LOWORD(PKCS_ATTRIBUTE
):
4255 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4257 case LOWORD(X509_UNICODE_NAME_VALUE
):
4258 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4260 case LOWORD(X509_OCTET_STRING
):
4261 encodeFunc
= CRYPT_AsnEncodeOctets
;
4263 case LOWORD(X509_BITS
):
4264 case LOWORD(X509_KEY_USAGE
):
4265 encodeFunc
= CRYPT_AsnEncodeBits
;
4267 case LOWORD(X509_INTEGER
):
4268 encodeFunc
= CRYPT_AsnEncodeInt
;
4270 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4271 encodeFunc
= CRYPT_AsnEncodeInteger
;
4273 case LOWORD(X509_MULTI_BYTE_UINT
):
4274 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4276 case LOWORD(X509_ENUMERATED
):
4277 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4279 case LOWORD(X509_CHOICE_OF_TIME
):
4280 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4282 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4283 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4285 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4286 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4288 case LOWORD(X509_SEQUENCE_OF_ANY
):
4289 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4291 case LOWORD(PKCS_UTC_TIME
):
4292 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4294 case LOWORD(X509_CRL_DIST_POINTS
):
4295 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4297 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4298 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4300 case LOWORD(PKCS_CTL
):
4301 encodeFunc
= CRYPT_AsnEncodeCTL
;
4303 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4304 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4306 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4307 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4309 case LOWORD(PKCS_ATTRIBUTES
):
4310 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4312 case LOWORD(X509_ISSUING_DIST_POINT
):
4313 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4315 case LOWORD(X509_NAME_CONSTRAINTS
):
4316 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4318 case LOWORD(PKCS7_SIGNER_INFO
):
4319 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4321 case LOWORD(CMS_SIGNER_INFO
):
4322 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4326 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4327 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4328 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4329 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4330 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4331 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4332 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4333 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4334 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4335 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4336 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4337 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4338 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4339 encodeFunc
= CRYPT_AsnEncodeBits
;
4340 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4341 encodeFunc
= CRYPT_AsnEncodeOctets
;
4342 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4343 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4344 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4345 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4346 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4347 encodeFunc
= CRYPT_AsnEncodeAltName
;
4348 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4349 encodeFunc
= CRYPT_AsnEncodeAltName
;
4350 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4351 encodeFunc
= CRYPT_AsnEncodeAltName
;
4352 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4353 encodeFunc
= CRYPT_AsnEncodeAltName
;
4354 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4355 encodeFunc
= CRYPT_AsnEncodeAltName
;
4356 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4357 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4358 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4359 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4360 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4361 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4362 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4363 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4364 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4365 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4366 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4367 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4368 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4369 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4370 else if (!strcmp(lpszStructType
, szOID_CTL
))
4371 encodeFunc
= CRYPT_AsnEncodeCTL
;
4375 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4376 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4378 static HCRYPTOIDFUNCSET set
= NULL
;
4379 CryptEncodeObjectFunc encodeFunc
= NULL
;
4382 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4383 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4384 (void **)&encodeFunc
, hFunc
);
4388 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4389 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4391 static HCRYPTOIDFUNCSET set
= NULL
;
4392 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4395 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4396 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4397 (void **)&encodeFunc
, hFunc
);
4401 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4402 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4405 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4406 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4407 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4409 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4410 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4413 if (!pbEncoded
&& !pcbEncoded
)
4415 SetLastError(ERROR_INVALID_PARAMETER
);
4419 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4422 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4423 debugstr_a(lpszStructType
));
4424 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4425 lpszStructType
, &hFunc
);
4426 if (!pCryptEncodeObject
)
4427 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4428 lpszStructType
, &hFunc
);
4430 if (pCryptEncodeObject
)
4431 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4432 pvStructInfo
, pbEncoded
, pcbEncoded
);
4433 else if (pCryptEncodeObjectEx
)
4434 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4435 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4437 CryptFreeOIDFunctionAddress(hFunc
, 0);
4438 TRACE_(crypt
)("returning %d\n", ret
);
4442 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4443 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4444 void *pvEncoded
, DWORD
*pcbEncoded
)
4447 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4448 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4450 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4451 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4452 pvEncoded
, pcbEncoded
);
4454 if (!pvEncoded
&& !pcbEncoded
)
4456 SetLastError(ERROR_INVALID_PARAMETER
);
4460 SetLastError(NOERROR
);
4461 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
4462 *(BYTE
**)pvEncoded
= NULL
;
4463 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4466 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4467 debugstr_a(lpszStructType
));
4468 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4472 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4473 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4476 CryptEncodeObjectFunc pCryptEncodeObject
=
4477 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4479 if (pCryptEncodeObject
)
4481 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4483 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4484 pvStructInfo
, NULL
, pcbEncoded
);
4485 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4486 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4487 ret
= pCryptEncodeObject(dwCertEncodingType
,
4488 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4492 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4493 pvStructInfo
, pvEncoded
, pcbEncoded
);
4497 CryptFreeOIDFunctionAddress(hFunc
, 0);
4498 TRACE_(crypt
)("returning %d\n", ret
);
4502 BOOL WINAPI
PFXExportCertStore(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4503 LPCWSTR szPassword
, DWORD dwFlags
)
4505 return PFXExportCertStoreEx(hStore
, pPFX
, szPassword
, NULL
, dwFlags
);
4508 BOOL WINAPI
PFXExportCertStoreEx(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4509 LPCWSTR szPassword
, void *pvReserved
, DWORD dwFlags
)
4511 FIXME_(crypt
)("(%p, %p, %p, %p, %08x): stub\n", hStore
, pPFX
, szPassword
,
4512 pvReserved
, dwFlags
);
4516 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4517 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4519 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4520 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4523 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4524 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4525 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4529 static CHAR oid
[] = szOID_RSA_RSA
;
4531 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4532 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4533 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4535 if (!pszPublicKeyObjId
)
4536 pszPublicKeyObjId
= oid
;
4537 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4541 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4544 LPBYTE pubKey
= CryptMemAlloc(keySize
);
4548 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4552 DWORD encodedLen
= 0;
4554 ret
= CryptEncodeObject(dwCertEncodingType
,
4555 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4558 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4559 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4562 *pcbInfo
= sizeNeeded
;
4563 else if (*pcbInfo
< sizeNeeded
)
4565 SetLastError(ERROR_MORE_DATA
);
4566 *pcbInfo
= sizeNeeded
;
4571 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4572 sizeof(CERT_PUBLIC_KEY_INFO
);
4573 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4575 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4576 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4577 pInfo
->PublicKey
.pbData
=
4578 (BYTE
*)pInfo
->Algorithm
.pszObjId
4579 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4580 pInfo
->PublicKey
.cbData
= encodedLen
;
4581 pInfo
->PublicKey
.cUnusedBits
= 0;
4582 ret
= CryptEncodeObject(dwCertEncodingType
,
4583 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4584 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4588 CryptMemFree(pubKey
);
4593 CryptDestroyKey(key
);
4598 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4599 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4600 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4602 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4603 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4604 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4606 static HCRYPTOIDFUNCSET set
= NULL
;
4608 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4609 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4611 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4612 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4613 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4617 SetLastError(ERROR_INVALID_PARAMETER
);
4621 if (pszPublicKeyObjId
)
4624 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4626 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4627 0, (void **)&exportFunc
, &hFunc
);
4630 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4631 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4632 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4634 CryptFreeOIDFunctionAddress(hFunc
, 0);
4638 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4639 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4641 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4645 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4646 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4647 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4650 DWORD pubKeySize
= 0;
4652 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4653 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4655 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4656 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4659 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4663 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4664 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4669 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4670 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4673 CryptMemFree(pubKey
);
4681 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4682 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4683 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4685 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4686 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4687 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4689 static HCRYPTOIDFUNCSET set
= NULL
;
4691 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4692 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4694 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4695 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4698 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4699 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4700 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4702 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4703 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4706 CryptFreeOIDFunctionAddress(hFunc
, 0);