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
=
232 (const struct AsnConstructedItem
*)pvStructInfo
;
235 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
236 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
238 DWORD dataLen
, bytesNeeded
;
240 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
241 bytesNeeded
= 1 + dataLen
+ len
;
243 *pcbEncoded
= bytesNeeded
;
244 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
245 pbEncoded
, pcbEncoded
, bytesNeeded
)))
247 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
248 pbEncoded
= *(BYTE
**)pbEncoded
;
249 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
250 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
251 pbEncoded
+= dataLen
;
252 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
253 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
257 /* Some functions propagate their errors through the size */
264 /* Some functions propagate their errors through the size */
270 struct AsnEncodeTagSwappedItem
273 const void *pvStructInfo
;
274 CryptEncodeObjectExFunc encodeFunc
;
277 /* Sort of a wacky hack, it encodes something using the struct
278 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
279 * given in the struct AsnEncodeTagSwappedItem.
281 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
282 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
283 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
286 const struct AsnEncodeTagSwappedItem
*item
=
287 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
289 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
290 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
291 if (ret
&& pbEncoded
)
292 *pbEncoded
= item
->tag
;
296 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
297 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
298 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
300 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
303 /* CERT_V1 is not encoded */
311 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
313 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
314 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
319 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
320 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
321 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
323 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
328 *pcbEncoded
= blob
->cbData
;
333 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
334 pcbEncoded
, blob
->cbData
)))
336 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
337 pbEncoded
= *(BYTE
**)pbEncoded
;
339 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
340 *pcbEncoded
= blob
->cbData
;
347 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
348 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
349 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
352 /* This has two filetimes in a row, a NotBefore and a NotAfter */
353 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
354 struct AsnEncodeSequenceItem items
[] = {
355 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
356 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
359 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
360 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
365 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
368 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
369 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
370 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
373 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
374 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
375 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
376 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
379 struct AsnEncodeSequenceItem items
[2] = {
380 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
381 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
384 if (algo
->Parameters
.cbData
)
385 items
[1].pvStructInfo
= &algo
->Parameters
;
387 items
[1].pvStructInfo
= &nullBlob
;
388 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
389 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
394 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
395 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
396 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
398 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
399 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
401 struct AsnEncodeSequenceItem items
[] = {
402 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
403 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
406 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
407 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
412 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
413 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
414 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
420 const CERT_PUBLIC_KEY_INFO
*info
=
421 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
422 struct AsnEncodeSequenceItem items
[] = {
423 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
424 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
427 TRACE("Encoding public key with OID %s\n",
428 debugstr_a(info
->Algorithm
.pszObjId
));
429 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
430 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
435 SetLastError(STATUS_ACCESS_VIOLATION
);
442 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
443 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
444 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
450 const CERT_SIGNED_CONTENT_INFO
*info
=
451 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
452 struct AsnEncodeSequenceItem items
[] = {
453 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
454 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
455 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
458 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
459 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
460 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
461 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
466 SetLastError(STATUS_ACCESS_VIOLATION
);
473 /* Like in Windows, this blithely ignores the validity of the passed-in
474 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
475 * decode properly, see CRYPT_AsnDecodeCertInfo.
477 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
478 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
479 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
485 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
486 struct AsnEncodeSequenceItem items
[10] = {
487 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
488 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
489 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
490 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
491 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
492 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
493 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
496 struct AsnConstructedItem constructed
[3] = { { 0 } };
497 DWORD cItem
= 7, cConstructed
= 0;
499 if (info
->IssuerUniqueId
.cbData
)
501 constructed
[cConstructed
].tag
= 1;
502 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
503 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
504 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
505 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
509 if (info
->SubjectUniqueId
.cbData
)
511 constructed
[cConstructed
].tag
= 2;
512 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
513 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
514 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
515 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
519 if (info
->cExtension
)
521 constructed
[cConstructed
].tag
= 3;
522 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
523 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
524 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
525 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
530 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
531 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
535 SetLastError(STATUS_ACCESS_VIOLATION
);
542 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
543 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
545 struct AsnEncodeSequenceItem items
[3] = {
546 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
547 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
553 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
555 if (entry
->cExtension
)
557 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
558 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
562 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
563 pbEncoded
, pcbEncoded
);
565 TRACE("returning %d (%08x)\n", ret
, GetLastError());
569 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
570 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
571 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
573 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
574 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
575 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
576 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
579 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
583 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
589 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
590 bytesNeeded
= 1 + lenBytes
+ dataLen
;
592 *pcbEncoded
= bytesNeeded
;
595 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
596 pcbEncoded
, bytesNeeded
)))
598 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
599 pbEncoded
= *(BYTE
**)pbEncoded
;
600 *pbEncoded
++ = ASN_SEQUENCEOF
;
601 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
602 pbEncoded
+= lenBytes
;
603 for (i
= 0; i
< cCRLEntry
; i
++)
605 DWORD size
= dataLen
;
607 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
,
618 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
619 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
620 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
622 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
625 /* CRL_V1 is not encoded */
632 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
633 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
637 /* Like in Windows, this blithely ignores the validity of the passed-in
638 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
639 * decode properly, see CRYPT_AsnDecodeCRLInfo.
641 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
642 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
643 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
649 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
650 struct AsnEncodeSequenceItem items
[7] = {
651 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
652 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
653 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
654 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
657 struct AsnConstructedItem constructed
[1] = { { 0 } };
658 DWORD cItem
= 4, cConstructed
= 0;
660 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
662 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
663 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
668 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
669 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
672 if (info
->cExtension
)
674 constructed
[cConstructed
].tag
= 0;
675 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
676 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
677 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
678 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
683 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
684 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
688 SetLastError(STATUS_ACCESS_VIOLATION
);
695 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
699 struct AsnEncodeSequenceItem items
[3] = {
700 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
706 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
710 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
711 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
714 items
[cItem
].pvStructInfo
= &ext
->Value
;
715 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
718 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
719 pbEncoded
, pcbEncoded
);
720 TRACE("returning %d (%08x)\n", ret
, GetLastError());
724 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
725 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
726 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
732 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
733 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
736 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
740 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
746 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
747 bytesNeeded
= 1 + lenBytes
+ dataLen
;
749 *pcbEncoded
= bytesNeeded
;
752 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
753 pbEncoded
, pcbEncoded
, bytesNeeded
)))
755 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
756 pbEncoded
= *(BYTE
**)pbEncoded
;
757 *pbEncoded
++ = ASN_SEQUENCEOF
;
758 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
759 pbEncoded
+= lenBytes
;
760 for (i
= 0; i
< exts
->cExtension
; i
++)
762 DWORD size
= dataLen
;
764 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
775 SetLastError(STATUS_ACCESS_VIOLATION
);
782 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
783 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
784 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
786 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
787 DWORD bytesNeeded
= 0, lenBytes
;
792 TRACE("%s\n", debugstr_a(pszObjId
));
799 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
801 SetLastError(CRYPT_E_ASN1_ERROR
);
805 firstByte
= val1
* 40 + val2
;
806 ptr
= pszObjId
+ firstPos
;
811 /* note I assume each component is at most 32-bits long in base 2 */
812 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
814 if (val1
>= 0x10000000)
816 else if (val1
>= 0x200000)
818 else if (val1
>= 0x4000)
820 else if (val1
>= 0x80)
830 SetLastError(CRYPT_E_ASN1_ERROR
);
834 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
838 bytesNeeded
+= 1 + lenBytes
;
841 if (*pcbEncoded
< bytesNeeded
)
843 SetLastError(ERROR_MORE_DATA
);
848 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
849 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
850 pbEncoded
+= lenBytes
;
856 *pbEncoded
++ = firstByte
;
857 ptr
= pszObjId
+ firstPos
;
860 sscanf(ptr
, "%d%n", &val
, &pos
);
862 unsigned char outBytes
[5];
865 if (val
>= 0x10000000)
867 else if (val
>= 0x200000)
869 else if (val
>= 0x4000)
871 else if (val
>= 0x80)
875 for (i
= numBytes
; i
> 0; i
--)
877 outBytes
[i
- 1] = val
& 0x7f;
880 for (i
= 0; i
< numBytes
- 1; i
++)
881 *pbEncoded
++ = outBytes
[i
] | 0x80;
882 *pbEncoded
++ = outBytes
[i
];
891 *pcbEncoded
= bytesNeeded
;
895 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
896 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
900 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
901 DWORD bytesNeeded
, lenBytes
, encodedLen
;
903 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
904 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
905 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
907 *pcbEncoded
= bytesNeeded
;
910 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
911 pbEncoded
, pcbEncoded
, bytesNeeded
)))
913 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
914 pbEncoded
= *(BYTE
**)pbEncoded
;
916 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
917 pbEncoded
+= lenBytes
;
918 memcpy(pbEncoded
, str
, encodedLen
);
924 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
925 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
929 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
930 DWORD bytesNeeded
, lenBytes
, strLen
;
932 if (value
->Value
.cbData
)
933 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
934 else if (value
->Value
.pbData
)
935 strLen
= lstrlenW(str
);
938 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
939 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
941 *pcbEncoded
= bytesNeeded
;
944 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
945 pbEncoded
, pcbEncoded
, bytesNeeded
)))
949 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
950 pbEncoded
= *(BYTE
**)pbEncoded
;
951 *pbEncoded
++ = ASN_BMPSTRING
;
952 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
953 pbEncoded
+= lenBytes
;
954 for (i
= 0; i
< strLen
; i
++)
956 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
957 *pbEncoded
++ = str
[i
] & 0x00ff;
964 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
965 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
969 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
970 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
972 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
974 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
976 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
977 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
979 *pcbEncoded
= bytesNeeded
;
982 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
983 pbEncoded
, pcbEncoded
, bytesNeeded
)))
985 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
986 pbEncoded
= *(BYTE
**)pbEncoded
;
987 *pbEncoded
++ = ASN_UTF8STRING
;
988 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
989 pbEncoded
+= lenBytes
;
990 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
991 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
997 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
998 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
999 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1005 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1007 switch (value
->dwValueType
)
1009 case CERT_RDN_ANY_TYPE
:
1010 /* explicitly disallowed */
1011 SetLastError(E_INVALIDARG
);
1014 case CERT_RDN_ENCODED_BLOB
:
1015 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1016 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1018 case CERT_RDN_OCTET_STRING
:
1019 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1020 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1022 case CERT_RDN_NUMERIC_STRING
:
1023 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1024 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1026 case CERT_RDN_PRINTABLE_STRING
:
1027 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1028 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1030 case CERT_RDN_TELETEX_STRING
:
1031 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1032 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1034 case CERT_RDN_VIDEOTEX_STRING
:
1035 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1036 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1038 case CERT_RDN_IA5_STRING
:
1039 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1040 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1042 case CERT_RDN_GRAPHIC_STRING
:
1043 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1044 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1046 case CERT_RDN_VISIBLE_STRING
:
1047 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1048 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1050 case CERT_RDN_GENERAL_STRING
:
1051 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1052 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1054 case CERT_RDN_UNIVERSAL_STRING
:
1055 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1056 SetLastError(CRYPT_E_ASN1_CHOICE
);
1059 case CERT_RDN_BMP_STRING
:
1060 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1061 pbEncoded
, pcbEncoded
);
1063 case CERT_RDN_UTF8_STRING
:
1064 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1065 pbEncoded
, pcbEncoded
);
1068 SetLastError(CRYPT_E_ASN1_CHOICE
);
1074 SetLastError(STATUS_ACCESS_VIOLATION
);
1081 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1082 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1083 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1085 DWORD bytesNeeded
= 0, lenBytes
, size
;
1088 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1089 0, NULL
, NULL
, &size
);
1092 bytesNeeded
+= size
;
1093 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1094 * with dwValueType, so "cast" it to get its encoded size
1096 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1097 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1100 bytesNeeded
+= size
;
1101 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1102 bytesNeeded
+= 1 + lenBytes
;
1105 if (*pcbEncoded
< bytesNeeded
)
1107 SetLastError(ERROR_MORE_DATA
);
1112 *pbEncoded
++ = ASN_SEQUENCE
;
1113 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1115 pbEncoded
+= lenBytes
;
1116 size
= bytesNeeded
- 1 - lenBytes
;
1117 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1118 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1122 size
= bytesNeeded
- 1 - lenBytes
- size
;
1123 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1124 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1125 0, NULL
, pbEncoded
, &size
);
1132 *pcbEncoded
= bytesNeeded
;
1136 /* Have to propagate index of failing character */
1143 static int BLOBComp(const void *l
, const void *r
)
1145 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1148 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1149 ret
= a
->cbData
- b
->cbData
;
1153 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1155 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1156 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1157 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1159 const CRYPT_BLOB_ARRAY
*set
= (const CRYPT_BLOB_ARRAY
*)pvStructInfo
;
1160 DWORD bytesNeeded
= 0, lenBytes
, i
;
1163 for (i
= 0; i
< set
->cBlob
; i
++)
1164 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1165 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1166 bytesNeeded
+= 1 + lenBytes
;
1169 *pcbEncoded
= bytesNeeded
;
1172 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1173 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1175 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1176 pbEncoded
= *(BYTE
**)pbEncoded
;
1177 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1178 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1179 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1180 pbEncoded
+= lenBytes
;
1181 for (i
= 0; ret
&& i
< set
->cBlob
; i
++)
1183 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1184 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1190 struct DERSetDescriptor
1196 CryptEncodeObjectExFunc encode
;
1199 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1200 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1201 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1203 const struct DERSetDescriptor
*desc
=
1204 (const struct DERSetDescriptor
*)pvStructInfo
;
1205 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1211 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1216 setOf
.cBlob
= desc
->cItems
;
1217 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1220 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1222 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1223 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1224 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1227 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1228 if (!setOf
.rgBlob
[i
].pbData
)
1231 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1232 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1233 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1234 &setOf
.rgBlob
[i
].cbData
);
1236 /* Some functions propagate their errors through the size */
1238 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1242 DWORD bytesNeeded
= 0, lenBytes
;
1244 for (i
= 0; i
< setOf
.cBlob
; i
++)
1245 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1246 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1247 bytesNeeded
+= 1 + lenBytes
;
1249 *pcbEncoded
= bytesNeeded
;
1250 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1251 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1253 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1254 pbEncoded
= *(BYTE
**)pbEncoded
;
1255 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1257 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1258 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1259 pbEncoded
+= lenBytes
;
1260 for (i
= 0; i
< setOf
.cBlob
; i
++)
1262 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1263 setOf
.rgBlob
[i
].cbData
);
1264 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1268 for (i
= 0; i
< setOf
.cBlob
; i
++)
1269 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1270 CryptMemFree(setOf
.rgBlob
);
1274 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1275 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1279 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1288 setOf
.cBlob
= rdn
->cRDNAttr
;
1289 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1290 sizeof(CRYPT_DER_BLOB
));
1294 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1296 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1298 setOf
.rgBlob
[i
].cbData
= 0;
1299 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1300 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1303 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1304 if (!setOf
.rgBlob
[i
].pbData
)
1307 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1308 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1309 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1313 /* Have to propagate index of failing character */
1314 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1318 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1319 pbEncoded
, pcbEncoded
);
1320 for (i
= 0; i
< setOf
.cBlob
; i
++)
1321 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1325 SetLastError(STATUS_ACCESS_VIOLATION
);
1329 CryptMemFree(setOf
.rgBlob
);
1333 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1334 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1335 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1337 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1338 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1339 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1342 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1345 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1346 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1347 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1349 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1350 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1354 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1355 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1356 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1362 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1363 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1365 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1367 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1369 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1370 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1372 bytesNeeded
+= size
;
1376 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1377 bytesNeeded
+= 1 + lenBytes
;
1381 *pcbEncoded
= bytesNeeded
;
1384 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1385 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1387 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1388 pbEncoded
= *(BYTE
**)pbEncoded
;
1389 *pbEncoded
++ = ASN_SEQUENCEOF
;
1390 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1392 pbEncoded
+= lenBytes
;
1393 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1396 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1397 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1402 bytesNeeded
-= size
;
1413 SetLastError(STATUS_ACCESS_VIOLATION
);
1420 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1421 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1422 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1424 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
1427 /* CTL_V1 is not encoded */
1434 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1435 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1439 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1440 * if they are empty and the OID is not empty (otherwise omits them.)
1442 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1443 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1444 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1447 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
1448 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
1450 struct AsnEncodeSequenceItem items
[2] = {
1451 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1457 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1458 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1461 if (algo
->Parameters
.cbData
)
1462 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1464 items
[cItem
].pvStructInfo
= &nullBlob
;
1465 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1468 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1469 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1473 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1474 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1476 struct AsnEncodeSequenceItem items
[2] = {
1477 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1478 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1482 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1483 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
1493 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1494 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1495 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1498 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1499 const struct CTLEntries
*entries
= (const struct CTLEntries
*)pvStructInfo
;
1502 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1506 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1512 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1513 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1515 *pcbEncoded
= bytesNeeded
;
1518 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1519 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1521 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1522 pbEncoded
= *(BYTE
**)pbEncoded
;
1523 *pbEncoded
++ = ASN_SEQUENCEOF
;
1524 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1525 pbEncoded
+= lenBytes
;
1526 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1528 DWORD size
= dataLen
;
1530 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1541 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1542 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1543 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1549 const CTL_INFO
*info
= (const CTL_INFO
*)pvStructInfo
;
1550 struct AsnEncodeSequenceItem items
[9] = {
1551 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1552 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1554 struct AsnConstructedItem constructed
= { 0 };
1557 if (info
->ListIdentifier
.cbData
)
1559 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1560 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1563 if (info
->SequenceNumber
.cbData
)
1565 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1566 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1569 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1570 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1572 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1574 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1575 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1578 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1579 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1581 if (info
->cCTLEntry
)
1583 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1584 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1587 if (info
->cExtension
)
1589 constructed
.tag
= 0;
1590 constructed
.pvStructInfo
= &info
->cExtension
;
1591 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1592 items
[cItem
].pvStructInfo
= &constructed
;
1593 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1596 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1597 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1601 SetLastError(STATUS_ACCESS_VIOLATION
);
1607 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1608 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1609 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1615 const CRYPT_SMIME_CAPABILITY
*capability
=
1616 (const CRYPT_SMIME_CAPABILITY
*)pvStructInfo
;
1618 if (!capability
->pszObjId
)
1619 SetLastError(E_INVALIDARG
);
1622 struct AsnEncodeSequenceItem items
[] = {
1623 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1624 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1627 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1628 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1634 SetLastError(STATUS_ACCESS_VIOLATION
);
1640 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1641 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1642 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1648 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1649 const CRYPT_SMIME_CAPABILITIES
*capabilities
=
1650 (const CRYPT_SMIME_CAPABILITIES
*)pvStructInfo
;
1653 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1657 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1658 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1664 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1665 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1667 *pcbEncoded
= bytesNeeded
;
1670 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1671 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1673 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1674 pbEncoded
= *(BYTE
**)pbEncoded
;
1675 *pbEncoded
++ = ASN_SEQUENCEOF
;
1676 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1677 pbEncoded
+= lenBytes
;
1678 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1680 DWORD size
= dataLen
;
1682 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1683 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1694 SetLastError(STATUS_ACCESS_VIOLATION
);
1700 static BOOL WINAPI
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType
,
1701 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1702 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1704 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1705 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1708 for (i
= 0, dataLen
= 0; ret
&& i
< noticeRef
->cNoticeNumbers
; i
++)
1712 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1713 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, NULL
, &size
);
1719 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1720 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1722 *pcbEncoded
= bytesNeeded
;
1725 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1726 pcbEncoded
, bytesNeeded
)))
1728 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1729 pbEncoded
= *(BYTE
**)pbEncoded
;
1730 *pbEncoded
++ = ASN_SEQUENCE
;
1731 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1732 pbEncoded
+= lenBytes
;
1733 for (i
= 0; i
< noticeRef
->cNoticeNumbers
; i
++)
1735 DWORD size
= dataLen
;
1737 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1738 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, pbEncoded
, &size
);
1748 static BOOL WINAPI
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType
,
1749 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1750 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1752 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1754 CERT_NAME_VALUE orgValue
= { CERT_RDN_IA5_STRING
,
1755 { 0, (LPBYTE
)noticeRef
->pszOrganization
} };
1756 struct AsnEncodeSequenceItem items
[] = {
1757 { &orgValue
, CRYPT_AsnEncodeNameValue
, 0 },
1758 { noticeRef
, CRYPT_AsnEncodeNoticeNumbers
, 0 },
1761 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1762 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1767 static BOOL WINAPI
CRYPT_AsnEncodePolicyQualifierUserNotice(
1768 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1769 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1776 const CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
= pvStructInfo
;
1777 struct AsnEncodeSequenceItem items
[2];
1778 CERT_NAME_VALUE displayTextValue
;
1782 if (notice
->pNoticeReference
)
1784 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNoticeReference
;
1785 items
[cItem
].pvStructInfo
= notice
->pNoticeReference
;
1788 if (notice
->pszDisplayText
)
1790 displayTextValue
.dwValueType
= CERT_RDN_BMP_STRING
;
1791 displayTextValue
.Value
.cbData
= 0;
1792 displayTextValue
.Value
.pbData
= (LPBYTE
)notice
->pszDisplayText
;
1793 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNameValue
;
1794 items
[cItem
].pvStructInfo
= &displayTextValue
;
1797 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1798 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1802 SetLastError(STATUS_ACCESS_VIOLATION
);
1808 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1809 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1810 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1816 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1818 if (!attr
->pszObjId
)
1819 SetLastError(E_INVALIDARG
);
1822 struct AsnEncodeSequenceItem items
[2] = {
1823 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1824 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1827 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1828 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1834 SetLastError(STATUS_ACCESS_VIOLATION
);
1840 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1841 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1842 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1848 const CRYPT_ATTRIBUTES
*attributes
=
1849 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1850 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1851 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1853 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1854 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1858 SetLastError(STATUS_ACCESS_VIOLATION
);
1864 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1865 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1866 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1867 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1870 const CRYPT_CONTENT_INFO
*info
= (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1871 struct AsnEncodeSequenceItem items
[2] = {
1872 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1875 struct AsnConstructedItem constructed
= { 0 };
1878 if (info
->Content
.cbData
)
1880 constructed
.tag
= 0;
1881 constructed
.pvStructInfo
= &info
->Content
;
1882 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1883 items
[cItem
].pvStructInfo
= &constructed
;
1884 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1887 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1888 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1891 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1892 void *pvData
, DWORD
*pcbData
)
1894 struct AsnEncodeSequenceItem items
[] = {
1895 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1896 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1898 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1899 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1902 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1903 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1906 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1907 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1908 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1914 const CRYPT_CONTENT_INFO
*info
=
1915 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1917 if (!info
->pszObjId
)
1918 SetLastError(E_INVALIDARG
);
1920 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1921 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1926 SetLastError(STATUS_ACCESS_VIOLATION
);
1932 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1933 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1937 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1938 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1940 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1942 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1943 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1945 *pcbEncoded
= bytesNeeded
;
1948 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1949 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1953 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1954 pbEncoded
= *(BYTE
**)pbEncoded
;
1956 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1957 pbEncoded
+= lenBytes
;
1958 for (i
= 0; i
< encodedLen
; i
++)
1959 *pbEncoded
++ = (BYTE
)str
[i
];
1965 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara
, LPVOID pv
)
1967 if (pEncodePara
&& pEncodePara
->pfnFree
)
1968 pEncodePara
->pfnFree(pv
);
1973 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1974 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1978 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1979 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1981 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1983 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1984 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1986 *pcbEncoded
= bytesNeeded
;
1989 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1990 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1995 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1996 ptr
= *(BYTE
**)pbEncoded
;
1999 *ptr
++ = ASN_NUMERICSTRING
;
2000 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2002 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2004 if (isdigitW(str
[i
]))
2005 *ptr
++ = (BYTE
)str
[i
];
2009 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2013 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2014 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2020 static inline int isprintableW(WCHAR wc
)
2022 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
2023 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
2024 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
2027 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2028 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2032 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2033 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2035 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2037 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2038 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2040 *pcbEncoded
= bytesNeeded
;
2043 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2044 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2049 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2050 ptr
= *(BYTE
**)pbEncoded
;
2053 *ptr
++ = ASN_PRINTABLESTRING
;
2054 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2056 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2058 if (isprintableW(str
[i
]))
2059 *ptr
++ = (BYTE
)str
[i
];
2063 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2067 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2068 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2074 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2075 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2079 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2080 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2082 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2084 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2085 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2087 *pcbEncoded
= bytesNeeded
;
2090 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2091 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2096 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2097 ptr
= *(BYTE
**)pbEncoded
;
2100 *ptr
++ = ASN_IA5STRING
;
2101 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2103 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2106 *ptr
++ = (BYTE
)str
[i
];
2110 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2114 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2115 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2121 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2122 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2126 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2127 DWORD bytesNeeded
, lenBytes
, strLen
;
2129 /* FIXME: doesn't handle composite characters */
2130 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2132 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2133 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2135 *pcbEncoded
= bytesNeeded
;
2138 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2139 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2143 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2144 pbEncoded
= *(BYTE
**)pbEncoded
;
2145 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2146 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2147 pbEncoded
+= lenBytes
;
2148 for (i
= 0; i
< strLen
; i
++)
2152 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2153 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2160 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2161 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2162 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2168 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
2170 switch (value
->dwValueType
)
2172 case CERT_RDN_ANY_TYPE
:
2173 case CERT_RDN_ENCODED_BLOB
:
2174 case CERT_RDN_OCTET_STRING
:
2175 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2177 case CERT_RDN_NUMERIC_STRING
:
2178 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2179 pbEncoded
, pcbEncoded
);
2181 case CERT_RDN_PRINTABLE_STRING
:
2182 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2183 pbEncoded
, pcbEncoded
);
2185 case CERT_RDN_TELETEX_STRING
:
2186 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2187 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2189 case CERT_RDN_VIDEOTEX_STRING
:
2190 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2191 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2193 case CERT_RDN_IA5_STRING
:
2194 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2195 pbEncoded
, pcbEncoded
);
2197 case CERT_RDN_GRAPHIC_STRING
:
2198 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2199 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2201 case CERT_RDN_VISIBLE_STRING
:
2202 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2203 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2205 case CERT_RDN_GENERAL_STRING
:
2206 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2207 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2209 case CERT_RDN_UNIVERSAL_STRING
:
2210 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2211 pbEncoded
, pcbEncoded
);
2213 case CERT_RDN_BMP_STRING
:
2214 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2215 pbEncoded
, pcbEncoded
);
2217 case CERT_RDN_UTF8_STRING
:
2218 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2219 pbEncoded
, pcbEncoded
);
2222 SetLastError(CRYPT_E_ASN1_CHOICE
);
2227 SetLastError(STATUS_ACCESS_VIOLATION
);
2233 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2234 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2235 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2241 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
2242 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2244 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2246 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2248 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2249 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2251 bytesNeeded
+= size
;
2253 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2254 bytesNeeded
+= 1 + lenBytes
;
2258 *pcbEncoded
= bytesNeeded
;
2261 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2262 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2264 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2265 pbEncoded
= *(BYTE
**)pbEncoded
;
2266 *pbEncoded
++ = ASN_SEQUENCEOF
;
2267 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2269 pbEncoded
+= lenBytes
;
2270 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2273 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2274 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
2279 bytesNeeded
-= size
;
2288 SetLastError(STATUS_ACCESS_VIOLATION
);
2295 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2296 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2297 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2299 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2308 else if (*pcbEncoded
< 3)
2311 SetLastError(ERROR_MORE_DATA
);
2317 *pbEncoded
++ = ASN_BOOL
;
2319 *pbEncoded
++ = val
? 0xff : 0;
2322 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2326 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2327 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2328 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2330 const CERT_ALT_NAME_ENTRY
*entry
=
2331 (const CERT_ALT_NAME_ENTRY
*)pvStructInfo
;
2337 switch (entry
->dwAltNameChoice
)
2339 case CERT_ALT_NAME_RFC822_NAME
:
2340 case CERT_ALT_NAME_DNS_NAME
:
2341 case CERT_ALT_NAME_URL
:
2342 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2343 if (entry
->u
.pwszURL
)
2347 /* Not + 1: don't encode the NULL-terminator */
2348 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2349 for (i
= 0; ret
&& i
< dataLen
; i
++)
2351 if (entry
->u
.pwszURL
[i
] > 0x7f)
2353 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2362 case CERT_ALT_NAME_DIRECTORY_NAME
:
2363 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2364 dataLen
= entry
->u
.DirectoryName
.cbData
;
2366 case CERT_ALT_NAME_IP_ADDRESS
:
2367 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2368 dataLen
= entry
->u
.IPAddress
.cbData
;
2370 case CERT_ALT_NAME_REGISTERED_ID
:
2372 struct AsnEncodeTagSwappedItem swapped
=
2373 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2374 CRYPT_AsnEncodeOid
};
2376 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2379 case CERT_ALT_NAME_OTHER_NAME
:
2380 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2383 SetLastError(E_INVALIDARG
);
2388 DWORD bytesNeeded
, lenBytes
;
2390 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2391 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2393 *pcbEncoded
= bytesNeeded
;
2394 else if (*pcbEncoded
< bytesNeeded
)
2396 SetLastError(ERROR_MORE_DATA
);
2397 *pcbEncoded
= bytesNeeded
;
2403 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2404 pbEncoded
+= lenBytes
;
2405 switch (entry
->dwAltNameChoice
)
2407 case CERT_ALT_NAME_RFC822_NAME
:
2408 case CERT_ALT_NAME_DNS_NAME
:
2409 case CERT_ALT_NAME_URL
:
2413 for (i
= 0; i
< dataLen
; i
++)
2414 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2417 case CERT_ALT_NAME_DIRECTORY_NAME
:
2418 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2420 case CERT_ALT_NAME_IP_ADDRESS
:
2421 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2425 *pcbEncoded
= bytesNeeded
;
2428 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2432 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2433 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2434 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2440 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2441 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2446 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2451 for (i
= 0; i
< newBlob
.cbData
; i
++)
2452 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2458 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2459 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2460 CryptMemFree(newBlob
.pbData
);
2464 SetLastError(STATUS_ACCESS_VIOLATION
);
2471 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2472 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2473 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2479 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
2480 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
2481 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2482 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2483 struct AsnConstructedItem constructed
= { 0 };
2484 DWORD cItem
= 0, cSwapped
= 0;
2486 if (info
->KeyId
.cbData
)
2488 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2489 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2490 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2491 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2492 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2496 if (info
->CertIssuer
.cbData
)
2498 constructed
.tag
= 1;
2499 constructed
.pvStructInfo
= &info
->CertIssuer
;
2500 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2501 items
[cItem
].pvStructInfo
= &constructed
;
2502 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2505 if (info
->CertSerialNumber
.cbData
)
2507 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2508 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2509 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2510 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2511 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2515 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2516 pEncodePara
, pbEncoded
, pcbEncoded
);
2520 SetLastError(STATUS_ACCESS_VIOLATION
);
2527 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2528 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2529 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2535 const CERT_ALT_NAME_INFO
*info
=
2536 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2537 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2540 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2541 * can't encode an erroneous entry index if it's bigger than this.
2543 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2547 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2548 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2551 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2553 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2554 * the bad character, now set the index of the bad
2557 *pcbEncoded
= (BYTE
)i
<<
2558 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2563 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2564 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2567 *pcbEncoded
= bytesNeeded
;
2572 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2573 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2575 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2576 pbEncoded
= *(BYTE
**)pbEncoded
;
2577 *pbEncoded
++ = ASN_SEQUENCEOF
;
2578 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2579 pbEncoded
+= lenBytes
;
2580 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2582 DWORD len
= dataLen
;
2584 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2585 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, pbEncoded
, &len
);
2598 SetLastError(STATUS_ACCESS_VIOLATION
);
2605 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2606 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2607 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2613 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2614 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2615 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2616 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2617 DWORD cItem
= 0, cSwapped
= 0;
2619 if (info
->KeyId
.cbData
)
2621 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2622 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2623 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2624 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2625 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2629 if (info
->AuthorityCertIssuer
.cAltEntry
)
2631 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2632 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2633 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2634 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2635 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2639 if (info
->AuthorityCertSerialNumber
.cbData
)
2641 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2642 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2643 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2644 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2645 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2649 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2650 pEncodePara
, pbEncoded
, pcbEncoded
);
2654 SetLastError(STATUS_ACCESS_VIOLATION
);
2661 static BOOL WINAPI
CRYPT_AsnEncodeAccessDescription(
2662 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2664 struct AsnEncodeSequenceItem items
[] = {
2665 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2666 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2669 if (!descr
->pszAccessMethod
)
2671 SetLastError(E_INVALIDARG
);
2674 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
2675 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
2678 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2679 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2680 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2686 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2687 const CERT_AUTHORITY_INFO_ACCESS
*info
=
2688 (const CERT_AUTHORITY_INFO_ACCESS
*)pvStructInfo
;
2691 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2695 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2702 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2703 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2705 *pcbEncoded
= bytesNeeded
;
2708 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2709 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2711 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2712 pbEncoded
= *(BYTE
**)pbEncoded
;
2713 *pbEncoded
++ = ASN_SEQUENCEOF
;
2714 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2715 pbEncoded
+= lenBytes
;
2716 for (i
= 0; i
< info
->cAccDescr
; i
++)
2718 DWORD size
= dataLen
;
2720 ret
= CRYPT_AsnEncodeAccessDescription(
2721 &info
->rgAccDescr
[i
], pbEncoded
, &size
);
2731 SetLastError(STATUS_ACCESS_VIOLATION
);
2738 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2739 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2740 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2746 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2747 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2748 struct AsnEncodeSequenceItem items
[3] = {
2749 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2754 if (info
->fPathLenConstraint
)
2756 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2757 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2760 if (info
->cSubtreesConstraint
)
2762 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2763 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2766 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2767 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2771 SetLastError(STATUS_ACCESS_VIOLATION
);
2778 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2779 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2780 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2786 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2787 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2788 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2793 items
[cItem
].pvStructInfo
= &info
->fCA
;
2794 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2797 if (info
->fPathLenConstraint
)
2799 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2800 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2803 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2804 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2808 SetLastError(STATUS_ACCESS_VIOLATION
);
2815 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2816 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2817 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2819 DWORD cPolicyQualifier
= *(DWORD
*)pvStructInfo
;
2820 const CERT_POLICY_QUALIFIER_INFO
*rgPolicyQualifier
=
2821 *(const CERT_POLICY_QUALIFIER_INFO
**)
2822 ((LPBYTE
)pvStructInfo
+ sizeof(DWORD
));
2825 if (!cPolicyQualifier
)
2832 struct AsnEncodeSequenceItem items
[2] = {
2833 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2834 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2836 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2839 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2841 items
[0].pvStructInfo
= rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2842 items
[1].pvStructInfo
= &rgPolicyQualifier
[i
].Qualifier
;
2843 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2844 sizeof(items
) / sizeof(items
[0]),
2845 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2847 bytesNeeded
+= size
;
2849 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2850 bytesNeeded
+= 1 + lenBytes
;
2854 *pcbEncoded
= bytesNeeded
;
2857 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2858 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2860 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2861 pbEncoded
= *(BYTE
**)pbEncoded
;
2862 *pbEncoded
++ = ASN_SEQUENCEOF
;
2863 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2865 pbEncoded
+= lenBytes
;
2866 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2868 items
[0].pvStructInfo
=
2869 rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2870 items
[1].pvStructInfo
=
2871 &rgPolicyQualifier
[i
].Qualifier
;
2873 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2874 sizeof(items
) / sizeof(items
[0]),
2875 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2880 bytesNeeded
-= size
;
2890 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2891 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2894 struct AsnEncodeSequenceItem items
[2] = {
2895 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2896 { &info
->cPolicyQualifier
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2900 if (!info
->pszPolicyIdentifier
)
2902 SetLastError(E_INVALIDARG
);
2905 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2906 sizeof(items
) / sizeof(items
[0]), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2910 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2911 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2912 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2918 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2919 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2922 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2924 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2925 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2928 bytesNeeded
+= size
;
2930 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2931 bytesNeeded
+= 1 + lenBytes
;
2935 *pcbEncoded
= bytesNeeded
;
2938 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2939 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2941 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2942 pbEncoded
= *(BYTE
**)pbEncoded
;
2943 *pbEncoded
++ = ASN_SEQUENCEOF
;
2944 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2946 pbEncoded
+= lenBytes
;
2947 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2950 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2951 &info
->rgPolicyInfo
[i
],
2952 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pbEncoded
, &size
);
2956 bytesNeeded
-= size
;
2965 SetLastError(STATUS_ACCESS_VIOLATION
);
2971 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2972 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2973 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2979 const BLOBHEADER
*hdr
=
2980 (const BLOBHEADER
*)pvStructInfo
;
2982 if (hdr
->bType
!= PUBLICKEYBLOB
)
2984 SetLastError(E_INVALIDARG
);
2989 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2990 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2991 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2992 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2993 struct AsnEncodeSequenceItem items
[] = {
2994 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2995 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2998 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2999 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3005 SetLastError(STATUS_ACCESS_VIOLATION
);
3012 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
3013 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3014 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3020 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
3021 DWORD bytesNeeded
, lenBytes
;
3023 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3024 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
3026 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3027 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3030 *pcbEncoded
= bytesNeeded
;
3035 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3036 pcbEncoded
, bytesNeeded
)))
3038 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3039 pbEncoded
= *(BYTE
**)pbEncoded
;
3040 *pbEncoded
++ = ASN_OCTETSTRING
;
3041 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3042 pbEncoded
+= lenBytes
;
3044 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3050 SetLastError(STATUS_ACCESS_VIOLATION
);
3054 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3058 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3059 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3060 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3066 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
3067 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3070 /* yep, MS allows cUnusedBits to be >= 8 */
3071 if (!blob
->cUnusedBits
)
3073 dataBytes
= blob
->cbData
;
3076 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3078 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3079 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3087 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3088 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3091 *pcbEncoded
= bytesNeeded
;
3096 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3097 pcbEncoded
, bytesNeeded
)))
3099 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3100 pbEncoded
= *(BYTE
**)pbEncoded
;
3101 *pbEncoded
++ = ASN_BITSTRING
;
3102 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3103 pbEncoded
+= lenBytes
;
3104 *pbEncoded
++ = unusedBits
;
3107 BYTE mask
= 0xff << unusedBits
;
3111 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3112 pbEncoded
+= dataBytes
- 1;
3114 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3121 SetLastError(STATUS_ACCESS_VIOLATION
);
3128 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3129 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3130 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3136 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
3137 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3142 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3147 for (i
= 0; i
< newBlob
.cbData
; i
++)
3148 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3154 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3155 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3156 CryptMemFree(newBlob
.pbData
);
3160 SetLastError(STATUS_ACCESS_VIOLATION
);
3167 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3168 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3169 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3171 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3173 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3174 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3177 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3178 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3179 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3185 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3188 const CRYPT_INTEGER_BLOB
*blob
=
3189 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3191 significantBytes
= blob
->cbData
;
3192 if (significantBytes
)
3194 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3196 /* negative, lop off leading (little-endian) 0xffs */
3197 for (; significantBytes
> 0 &&
3198 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3200 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3208 /* positive, lop off leading (little-endian) zeroes */
3209 for (; significantBytes
> 0 &&
3210 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3212 if (significantBytes
== 0)
3213 significantBytes
= 1;
3214 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3222 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3224 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3225 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3230 *pcbEncoded
= bytesNeeded
;
3235 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3236 pcbEncoded
, bytesNeeded
)))
3238 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3239 pbEncoded
= *(BYTE
**)pbEncoded
;
3240 *pbEncoded
++ = ASN_INTEGER
;
3243 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3244 pbEncoded
+= lenBytes
;
3245 *pbEncoded
++ = padByte
;
3249 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3250 pbEncoded
+= lenBytes
;
3252 for (; significantBytes
> 0; significantBytes
--)
3253 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3259 SetLastError(STATUS_ACCESS_VIOLATION
);
3266 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3267 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3268 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3274 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3276 const CRYPT_INTEGER_BLOB
*blob
=
3277 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3279 significantBytes
= blob
->cbData
;
3280 if (significantBytes
)
3282 /* positive, lop off leading (little-endian) zeroes */
3283 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3286 if (significantBytes
== 0)
3287 significantBytes
= 1;
3288 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3292 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3294 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3295 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3300 *pcbEncoded
= bytesNeeded
;
3305 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3306 pcbEncoded
, bytesNeeded
)))
3308 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3309 pbEncoded
= *(BYTE
**)pbEncoded
;
3310 *pbEncoded
++ = ASN_INTEGER
;
3313 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3314 pbEncoded
+= lenBytes
;
3319 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3320 pbEncoded
+= lenBytes
;
3322 for (; significantBytes
> 0; significantBytes
--)
3323 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3329 SetLastError(STATUS_ACCESS_VIOLATION
);
3336 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3337 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3338 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3340 CRYPT_INTEGER_BLOB blob
;
3343 /* Encode as an unsigned integer, then change the tag to enumerated */
3344 blob
.cbData
= sizeof(DWORD
);
3345 blob
.pbData
= (BYTE
*)pvStructInfo
;
3346 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3347 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3348 if (ret
&& pbEncoded
)
3350 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3351 pbEncoded
= *(BYTE
**)pbEncoded
;
3352 pbEncoded
[0] = ASN_ENUMERATED
;
3357 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3358 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3359 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3366 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3367 * temporary buffer because the output buffer is not NULL-terminated.
3370 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3374 *pcbEncoded
= bytesNeeded
;
3379 /* Sanity check the year, this is a two-digit year format */
3380 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
3382 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3384 SetLastError(CRYPT_E_BAD_ENCODE
);
3389 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3390 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3392 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3393 pbEncoded
= *(BYTE
**)pbEncoded
;
3394 buf
[0] = ASN_UTCTIME
;
3395 buf
[1] = bytesNeeded
- 2;
3396 snprintf(buf
+ 2, sizeof(buf
) - 2,
3397 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3398 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3399 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3400 sysTime
.wMinute
, sysTime
.wSecond
);
3401 memcpy(pbEncoded
, buf
, bytesNeeded
);
3408 SetLastError(STATUS_ACCESS_VIOLATION
);
3415 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3416 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3417 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3424 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3425 * temporary buffer because the output buffer is not NULL-terminated.
3428 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3432 *pcbEncoded
= bytesNeeded
;
3437 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
3440 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3441 pcbEncoded
, bytesNeeded
);
3444 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3445 pbEncoded
= *(BYTE
**)pbEncoded
;
3446 buf
[0] = ASN_GENERALTIME
;
3447 buf
[1] = bytesNeeded
- 2;
3448 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3449 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3450 sysTime
.wMinute
, sysTime
.wSecond
);
3451 memcpy(pbEncoded
, buf
, bytesNeeded
);
3457 SetLastError(STATUS_ACCESS_VIOLATION
);
3464 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3465 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3466 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3474 /* Check the year, if it's in the UTCTime range call that encode func */
3475 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
3477 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3478 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3479 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3481 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3482 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3487 SetLastError(STATUS_ACCESS_VIOLATION
);
3494 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3495 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3496 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3502 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3503 const CRYPT_SEQUENCE_OF_ANY
*seq
=
3504 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3506 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3507 dataLen
+= seq
->rgValue
[i
].cbData
;
3508 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3509 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3512 *pcbEncoded
= bytesNeeded
;
3517 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3518 pcbEncoded
, bytesNeeded
)))
3520 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3521 pbEncoded
= *(BYTE
**)pbEncoded
;
3522 *pbEncoded
++ = ASN_SEQUENCEOF
;
3523 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3524 pbEncoded
+= lenBytes
;
3525 for (i
= 0; i
< seq
->cValue
; i
++)
3527 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3528 seq
->rgValue
[i
].cbData
);
3529 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3536 SetLastError(STATUS_ACCESS_VIOLATION
);
3543 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3544 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3547 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3548 struct AsnConstructedItem constructed
= { 0 };
3549 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3550 DWORD cItem
= 0, cSwapped
= 0;
3552 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3554 case CRL_DIST_POINT_NO_NAME
:
3557 case CRL_DIST_POINT_FULL_NAME
:
3558 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3559 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3560 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3561 constructed
.tag
= 0;
3562 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3563 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3564 items
[cItem
].pvStructInfo
= &constructed
;
3565 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3569 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3570 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3576 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3578 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3579 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3580 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3581 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3582 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3586 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3588 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3589 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3590 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3591 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3592 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3597 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3598 pbEncoded
, pcbEncoded
);
3602 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3603 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3604 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3610 const CRL_DIST_POINTS_INFO
*info
=
3611 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
3613 if (!info
->cDistPoint
)
3615 SetLastError(E_INVALIDARG
);
3620 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3623 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3627 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3631 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3633 /* Have to propagate index of failing character */
3639 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3640 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3643 *pcbEncoded
= bytesNeeded
;
3648 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3649 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3651 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3652 pbEncoded
= *(BYTE
**)pbEncoded
;
3653 *pbEncoded
++ = ASN_SEQUENCEOF
;
3654 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3655 pbEncoded
+= lenBytes
;
3656 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3658 DWORD len
= dataLen
;
3660 ret
= CRYPT_AsnEncodeDistPoint(
3661 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3675 SetLastError(STATUS_ACCESS_VIOLATION
);
3682 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3683 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3684 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3690 const CERT_ENHKEY_USAGE
*usage
=
3691 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
3692 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3695 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3697 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3698 usage
->rgpszUsageIdentifier
[i
],
3699 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3701 bytesNeeded
+= size
;
3703 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3704 bytesNeeded
+= 1 + lenBytes
;
3708 *pcbEncoded
= bytesNeeded
;
3711 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3712 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3714 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3715 pbEncoded
= *(BYTE
**)pbEncoded
;
3716 *pbEncoded
++ = ASN_SEQUENCEOF
;
3717 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3719 pbEncoded
+= lenBytes
;
3720 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3723 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3724 usage
->rgpszUsageIdentifier
[i
],
3725 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3730 bytesNeeded
-= size
;
3739 SetLastError(STATUS_ACCESS_VIOLATION
);
3746 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3747 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3748 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3754 const CRL_ISSUING_DIST_POINT
*point
=
3755 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3756 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3757 struct AsnConstructedItem constructed
= { 0 };
3758 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3759 DWORD cItem
= 0, cSwapped
= 0;
3762 switch (point
->DistPointName
.dwDistPointNameChoice
)
3764 case CRL_DIST_POINT_NO_NAME
:
3767 case CRL_DIST_POINT_FULL_NAME
:
3768 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3769 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3770 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3771 constructed
.tag
= 0;
3772 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3773 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3774 items
[cItem
].pvStructInfo
= &constructed
;
3775 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3780 SetLastError(E_INVALIDARG
);
3783 if (ret
&& point
->fOnlyContainsUserCerts
)
3785 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3786 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3787 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3788 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3789 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3793 if (ret
&& point
->fOnlyContainsCACerts
)
3795 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3796 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3797 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3798 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3799 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3803 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3805 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3806 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3807 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3808 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3809 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3813 if (ret
&& point
->fIndirectCRL
)
3815 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3816 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3817 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3818 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3819 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3824 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3825 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3829 SetLastError(STATUS_ACCESS_VIOLATION
);
3836 static BOOL WINAPI
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3837 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3838 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3841 const CERT_GENERAL_SUBTREE
*subtree
=
3842 (const CERT_GENERAL_SUBTREE
*)pvStructInfo
;
3843 struct AsnEncodeSequenceItem items
[3] = {
3844 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
3847 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3848 DWORD cItem
= 1, cSwapped
= 0;
3850 if (subtree
->dwMinimum
)
3852 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3853 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
3854 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3855 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3856 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3860 if (subtree
->fMaximum
)
3862 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3863 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
3864 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3865 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3866 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3870 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
3871 pEncodePara
, pbEncoded
, pcbEncoded
);
3875 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
3876 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3877 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3880 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
3882 TRACE("%p\n", pvStructInfo
);
3886 const CERT_NAME_CONSTRAINTS_INFO
*constraints
=
3887 (const CERT_NAME_CONSTRAINTS_INFO
*)pvStructInfo
;
3888 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
3889 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3890 DWORD i
, cItem
= 0, cSwapped
= 0;
3893 if (constraints
->cPermittedSubtree
)
3895 permitted
.rgBlob
= CryptMemAlloc(
3896 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
3897 if (permitted
.rgBlob
)
3899 permitted
.cBlob
= constraints
->cPermittedSubtree
;
3900 memset(permitted
.rgBlob
, 0,
3901 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3902 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
3903 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3904 NULL
, &constraints
->rgPermittedSubtree
[i
],
3905 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3906 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
3907 &permitted
.rgBlob
[i
].cbData
);
3910 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3911 swapped
[cSwapped
].pvStructInfo
= &permitted
;
3912 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3913 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3914 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3922 if (constraints
->cExcludedSubtree
)
3924 excluded
.rgBlob
= CryptMemAlloc(
3925 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
3926 if (excluded
.rgBlob
)
3928 excluded
.cBlob
= constraints
->cExcludedSubtree
;
3929 memset(excluded
.rgBlob
, 0,
3930 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3931 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
3932 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3933 NULL
, &constraints
->rgExcludedSubtree
[i
],
3934 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3935 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
3936 &excluded
.rgBlob
[i
].cbData
);
3939 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3940 swapped
[cSwapped
].pvStructInfo
= &excluded
;
3941 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3942 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3943 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3952 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3953 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3954 for (i
= 0; i
< permitted
.cBlob
; i
++)
3955 LocalFree(permitted
.rgBlob
[i
].pbData
);
3956 for (i
= 0; i
< excluded
.cBlob
; i
++)
3957 LocalFree(excluded
.rgBlob
[i
].pbData
);
3961 SetLastError(STATUS_ACCESS_VIOLATION
);
3964 CryptMemFree(permitted
.rgBlob
);
3965 CryptMemFree(excluded
.rgBlob
);
3966 TRACE("returning %d\n", ret
);
3970 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3971 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3972 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3976 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3977 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3978 struct AsnEncodeSequenceItem items
[] = {
3979 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3980 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3983 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3984 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3989 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3990 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3991 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3995 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3997 SetLastError(E_INVALIDARG
);
4003 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
4005 if (!info
->Issuer
.cbData
)
4006 SetLastError(E_INVALIDARG
);
4009 struct AsnEncodeSequenceItem items
[7] = {
4010 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4011 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4012 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
4015 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4016 DWORD cItem
= 3, cSwapped
= 0;
4018 if (info
->AuthAttrs
.cAttr
)
4020 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4021 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4022 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4023 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4024 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4028 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4029 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4031 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4032 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4034 if (info
->UnauthAttrs
.cAttr
)
4036 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4037 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4038 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4039 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4040 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4044 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4045 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4050 SetLastError(STATUS_ACCESS_VIOLATION
);
4056 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4057 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4058 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4062 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4064 SetLastError(E_INVALIDARG
);
4070 const CMSG_CMS_SIGNER_INFO
*info
= (const CMSG_CMS_SIGNER_INFO
*)pvStructInfo
;
4072 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4073 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4074 SetLastError(E_INVALIDARG
);
4075 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4076 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4077 SetLastError(E_INVALIDARG
);
4080 struct AsnEncodeSequenceItem items
[7] = {
4081 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4083 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4084 DWORD cItem
= 1, cSwapped
= 0;
4086 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4088 items
[cItem
].pvStructInfo
=
4089 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4090 items
[cItem
].encodeFunc
=
4091 CRYPT_AsnEncodeIssuerSerialNumber
;
4096 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4097 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4098 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4099 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4100 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4104 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4105 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4107 if (info
->AuthAttrs
.cAttr
)
4109 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4110 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4111 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4112 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4113 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4117 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4118 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4120 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4121 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4123 if (info
->UnauthAttrs
.cAttr
)
4125 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4126 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4127 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4128 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4129 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4133 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4134 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4139 SetLastError(STATUS_ACCESS_VIOLATION
);
4145 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4148 struct AsnEncodeSequenceItem items
[7] = {
4149 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4151 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4152 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4153 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4154 DWORD cItem
= 1, cSwapped
= 0;
4157 if (signedInfo
->cSignerInfo
)
4159 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4160 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4161 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4162 digestAlgorithmsSet
.itemOffset
=
4163 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4164 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4165 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4166 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4169 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4170 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4172 if (signedInfo
->cCertEncoded
)
4174 certSet
.cItems
= signedInfo
->cCertEncoded
;
4175 certSet
.items
= signedInfo
->rgCertEncoded
;
4176 certSet
.itemSize
= sizeof(CERT_BLOB
);
4177 certSet
.itemOffset
= 0;
4178 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4179 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4180 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4181 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4182 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4183 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4187 if (signedInfo
->cCrlEncoded
)
4189 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4190 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4191 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4192 crlSet
.itemOffset
= 0;
4193 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4194 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4195 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4196 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4197 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4198 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4202 if (ret
&& signedInfo
->cSignerInfo
)
4204 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4205 signerSet
.items
= signedInfo
->rgSignerInfo
;
4206 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4207 signerSet
.itemOffset
= 0;
4208 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4209 items
[cItem
].pvStructInfo
= &signerSet
;
4210 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4214 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4215 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4220 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4221 LPCSTR lpszStructType
)
4223 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4225 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4226 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4228 SetLastError(ERROR_FILE_NOT_FOUND
);
4232 if (!HIWORD(lpszStructType
))
4234 switch (LOWORD(lpszStructType
))
4236 case LOWORD(X509_CERT
):
4237 encodeFunc
= CRYPT_AsnEncodeCert
;
4239 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4240 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4242 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4243 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4245 case LOWORD(X509_EXTENSIONS
):
4246 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4248 case LOWORD(X509_NAME_VALUE
):
4249 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4251 case LOWORD(X509_NAME
):
4252 encodeFunc
= CRYPT_AsnEncodeName
;
4254 case LOWORD(X509_PUBLIC_KEY_INFO
):
4255 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4257 case LOWORD(X509_AUTHORITY_KEY_ID
):
4258 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4260 case LOWORD(X509_ALTERNATE_NAME
):
4261 encodeFunc
= CRYPT_AsnEncodeAltName
;
4263 case LOWORD(X509_BASIC_CONSTRAINTS
):
4264 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4266 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4267 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4269 case LOWORD(X509_CERT_POLICIES
):
4270 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4272 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4273 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4275 case LOWORD(X509_UNICODE_NAME
):
4276 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4278 case LOWORD(PKCS_CONTENT_INFO
):
4279 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4281 case LOWORD(PKCS_ATTRIBUTE
):
4282 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4284 case LOWORD(X509_UNICODE_NAME_VALUE
):
4285 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4287 case LOWORD(X509_OCTET_STRING
):
4288 encodeFunc
= CRYPT_AsnEncodeOctets
;
4290 case LOWORD(X509_BITS
):
4291 case LOWORD(X509_KEY_USAGE
):
4292 encodeFunc
= CRYPT_AsnEncodeBits
;
4294 case LOWORD(X509_INTEGER
):
4295 encodeFunc
= CRYPT_AsnEncodeInt
;
4297 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4298 encodeFunc
= CRYPT_AsnEncodeInteger
;
4300 case LOWORD(X509_MULTI_BYTE_UINT
):
4301 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4303 case LOWORD(X509_ENUMERATED
):
4304 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4306 case LOWORD(X509_CHOICE_OF_TIME
):
4307 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4309 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4310 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4312 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4313 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4315 case LOWORD(X509_SEQUENCE_OF_ANY
):
4316 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4318 case LOWORD(PKCS_UTC_TIME
):
4319 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4321 case LOWORD(X509_CRL_DIST_POINTS
):
4322 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4324 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4325 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4327 case LOWORD(PKCS_CTL
):
4328 encodeFunc
= CRYPT_AsnEncodeCTL
;
4330 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4331 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4333 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4334 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4336 case LOWORD(PKCS_ATTRIBUTES
):
4337 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4339 case LOWORD(X509_ISSUING_DIST_POINT
):
4340 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4342 case LOWORD(X509_NAME_CONSTRAINTS
):
4343 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4345 case LOWORD(PKCS7_SIGNER_INFO
):
4346 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4348 case LOWORD(CMS_SIGNER_INFO
):
4349 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4353 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4354 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4355 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4356 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4357 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4358 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4359 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4360 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4361 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4362 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4363 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4364 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4365 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4366 encodeFunc
= CRYPT_AsnEncodeBits
;
4367 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4368 encodeFunc
= CRYPT_AsnEncodeOctets
;
4369 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4370 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4371 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4372 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4373 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4374 encodeFunc
= CRYPT_AsnEncodeAltName
;
4375 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4376 encodeFunc
= CRYPT_AsnEncodeAltName
;
4377 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4378 encodeFunc
= CRYPT_AsnEncodeAltName
;
4379 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4380 encodeFunc
= CRYPT_AsnEncodeAltName
;
4381 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4382 encodeFunc
= CRYPT_AsnEncodeAltName
;
4383 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4384 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4385 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4386 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4387 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4388 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4389 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4390 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4391 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4392 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4393 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4394 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4395 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4396 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4397 else if (!strcmp(lpszStructType
, szOID_CTL
))
4398 encodeFunc
= CRYPT_AsnEncodeCTL
;
4402 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4403 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4405 static HCRYPTOIDFUNCSET set
= NULL
;
4406 CryptEncodeObjectFunc encodeFunc
= NULL
;
4409 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4410 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4411 (void **)&encodeFunc
, hFunc
);
4415 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4416 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4418 static HCRYPTOIDFUNCSET set
= NULL
;
4419 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4422 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4423 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4424 (void **)&encodeFunc
, hFunc
);
4428 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4429 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4432 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4433 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4434 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4436 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4437 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4440 if (!pbEncoded
&& !pcbEncoded
)
4442 SetLastError(ERROR_INVALID_PARAMETER
);
4446 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4449 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4450 debugstr_a(lpszStructType
));
4451 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4452 lpszStructType
, &hFunc
);
4453 if (!pCryptEncodeObject
)
4454 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4455 lpszStructType
, &hFunc
);
4457 if (pCryptEncodeObject
)
4458 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4459 pvStructInfo
, pbEncoded
, pcbEncoded
);
4460 else if (pCryptEncodeObjectEx
)
4461 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4462 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4464 CryptFreeOIDFunctionAddress(hFunc
, 0);
4465 TRACE_(crypt
)("returning %d\n", ret
);
4469 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4470 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4471 void *pvEncoded
, DWORD
*pcbEncoded
)
4474 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4475 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4477 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4478 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4479 pvEncoded
, pcbEncoded
);
4481 if (!pvEncoded
&& !pcbEncoded
)
4483 SetLastError(ERROR_INVALID_PARAMETER
);
4487 SetLastError(NOERROR
);
4488 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
4489 *(BYTE
**)pvEncoded
= NULL
;
4490 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4493 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4494 debugstr_a(lpszStructType
));
4495 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4499 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4500 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4503 CryptEncodeObjectFunc pCryptEncodeObject
=
4504 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4506 if (pCryptEncodeObject
)
4508 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4510 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4511 pvStructInfo
, NULL
, pcbEncoded
);
4512 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4513 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4514 ret
= pCryptEncodeObject(dwCertEncodingType
,
4515 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4519 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4520 pvStructInfo
, pvEncoded
, pcbEncoded
);
4524 CryptFreeOIDFunctionAddress(hFunc
, 0);
4525 TRACE_(crypt
)("returning %d\n", ret
);
4529 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4530 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4532 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4533 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4536 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4537 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4538 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4542 static CHAR oid
[] = szOID_RSA_RSA
;
4544 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4545 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4546 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4548 if (!pszPublicKeyObjId
)
4549 pszPublicKeyObjId
= oid
;
4550 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4554 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4557 LPBYTE pubKey
= CryptMemAlloc(keySize
);
4561 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4565 DWORD encodedLen
= 0;
4567 ret
= CryptEncodeObject(dwCertEncodingType
,
4568 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4571 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4572 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4575 *pcbInfo
= sizeNeeded
;
4576 else if (*pcbInfo
< sizeNeeded
)
4578 SetLastError(ERROR_MORE_DATA
);
4579 *pcbInfo
= sizeNeeded
;
4584 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4585 sizeof(CERT_PUBLIC_KEY_INFO
);
4586 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4588 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4589 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4590 pInfo
->PublicKey
.pbData
=
4591 (BYTE
*)pInfo
->Algorithm
.pszObjId
4592 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4593 pInfo
->PublicKey
.cbData
= encodedLen
;
4594 pInfo
->PublicKey
.cUnusedBits
= 0;
4595 ret
= CryptEncodeObject(dwCertEncodingType
,
4596 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4597 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4601 CryptMemFree(pubKey
);
4606 CryptDestroyKey(key
);
4611 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4612 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4613 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4615 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4616 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4617 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4619 static HCRYPTOIDFUNCSET set
= NULL
;
4621 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4622 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4624 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4625 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4626 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4630 SetLastError(ERROR_INVALID_PARAMETER
);
4634 if (pszPublicKeyObjId
)
4637 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4639 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4640 0, (void **)&exportFunc
, &hFunc
);
4643 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4644 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4645 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4647 CryptFreeOIDFunctionAddress(hFunc
, 0);
4651 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4652 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4654 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4658 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4659 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4660 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4663 DWORD pubKeySize
= 0;
4665 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4666 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4668 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4669 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4672 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4676 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4677 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4682 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4683 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4686 CryptMemFree(pubKey
);
4694 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4695 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4696 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4698 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4699 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4700 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4702 static HCRYPTOIDFUNCSET set
= NULL
;
4704 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4705 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4707 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4708 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4711 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4712 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4713 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4715 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4716 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4719 CryptFreeOIDFunctionAddress(hFunc
, 0);