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
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
;
816 /* note I assume each component is at most 32-bits long in base 2 */
817 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
819 if (val1
>= 0x10000000)
821 else if (val1
>= 0x200000)
823 else if (val1
>= 0x4000)
825 else if (val1
>= 0x80)
835 SetLastError(CRYPT_E_ASN1_ERROR
);
839 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
843 bytesNeeded
+= 1 + lenBytes
;
846 if (*pcbEncoded
< bytesNeeded
)
848 SetLastError(ERROR_MORE_DATA
);
853 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
854 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
855 pbEncoded
+= lenBytes
;
861 *pbEncoded
++ = firstByte
;
862 ptr
= pszObjId
+ firstPos
;
865 sscanf(ptr
, "%d%n", &val
, &pos
);
867 unsigned char outBytes
[5];
870 if (val
>= 0x10000000)
872 else if (val
>= 0x200000)
874 else if (val
>= 0x4000)
876 else if (val
>= 0x80)
880 for (i
= numBytes
; i
> 0; i
--)
882 outBytes
[i
- 1] = val
& 0x7f;
885 for (i
= 0; i
< numBytes
- 1; i
++)
886 *pbEncoded
++ = outBytes
[i
] | 0x80;
887 *pbEncoded
++ = outBytes
[i
];
896 *pcbEncoded
= bytesNeeded
;
900 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
901 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
905 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
906 DWORD bytesNeeded
, lenBytes
, encodedLen
;
908 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
909 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
910 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
912 *pcbEncoded
= bytesNeeded
;
915 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
916 pbEncoded
, pcbEncoded
, bytesNeeded
)))
918 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
919 pbEncoded
= *(BYTE
**)pbEncoded
;
921 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
922 pbEncoded
+= lenBytes
;
923 memcpy(pbEncoded
, str
, encodedLen
);
929 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
930 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
934 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
935 DWORD bytesNeeded
, lenBytes
, strLen
;
937 if (value
->Value
.cbData
)
938 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
939 else if (value
->Value
.pbData
)
940 strLen
= lstrlenW(str
);
943 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
944 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
946 *pcbEncoded
= bytesNeeded
;
949 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
950 pbEncoded
, pcbEncoded
, bytesNeeded
)))
954 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
955 pbEncoded
= *(BYTE
**)pbEncoded
;
956 *pbEncoded
++ = ASN_BMPSTRING
;
957 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
958 pbEncoded
+= lenBytes
;
959 for (i
= 0; i
< strLen
; i
++)
961 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
962 *pbEncoded
++ = str
[i
] & 0x00ff;
969 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
970 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
974 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
975 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
977 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
979 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
981 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
982 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
984 *pcbEncoded
= bytesNeeded
;
987 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
988 pbEncoded
, pcbEncoded
, bytesNeeded
)))
990 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
991 pbEncoded
= *(BYTE
**)pbEncoded
;
992 *pbEncoded
++ = ASN_UTF8STRING
;
993 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
994 pbEncoded
+= lenBytes
;
995 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
996 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
1002 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1003 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1004 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1010 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1012 switch (value
->dwValueType
)
1014 case CERT_RDN_ANY_TYPE
:
1015 /* explicitly disallowed */
1016 SetLastError(E_INVALIDARG
);
1019 case CERT_RDN_ENCODED_BLOB
:
1020 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1021 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1023 case CERT_RDN_OCTET_STRING
:
1024 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1025 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1027 case CERT_RDN_NUMERIC_STRING
:
1028 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1029 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1031 case CERT_RDN_PRINTABLE_STRING
:
1032 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1033 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1035 case CERT_RDN_TELETEX_STRING
:
1036 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1037 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1039 case CERT_RDN_VIDEOTEX_STRING
:
1040 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1041 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1043 case CERT_RDN_IA5_STRING
:
1044 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1045 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1047 case CERT_RDN_GRAPHIC_STRING
:
1048 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1049 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1051 case CERT_RDN_VISIBLE_STRING
:
1052 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1053 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1055 case CERT_RDN_GENERAL_STRING
:
1056 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1057 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1059 case CERT_RDN_UNIVERSAL_STRING
:
1060 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1061 SetLastError(CRYPT_E_ASN1_CHOICE
);
1064 case CERT_RDN_BMP_STRING
:
1065 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1066 pbEncoded
, pcbEncoded
);
1068 case CERT_RDN_UTF8_STRING
:
1069 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1070 pbEncoded
, pcbEncoded
);
1073 SetLastError(CRYPT_E_ASN1_CHOICE
);
1079 SetLastError(STATUS_ACCESS_VIOLATION
);
1086 static BOOL
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1087 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1088 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1090 DWORD bytesNeeded
= 0, lenBytes
, size
;
1093 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1094 0, NULL
, NULL
, &size
);
1097 bytesNeeded
+= size
;
1098 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1099 * with dwValueType, so "cast" it to get its encoded size
1101 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1102 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1105 bytesNeeded
+= size
;
1106 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1107 bytesNeeded
+= 1 + lenBytes
;
1110 if (*pcbEncoded
< bytesNeeded
)
1112 SetLastError(ERROR_MORE_DATA
);
1117 *pbEncoded
++ = ASN_SEQUENCE
;
1118 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1120 pbEncoded
+= lenBytes
;
1121 size
= bytesNeeded
- 1 - lenBytes
;
1122 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1123 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1127 size
= bytesNeeded
- 1 - lenBytes
- size
;
1128 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1129 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1130 0, NULL
, pbEncoded
, &size
);
1137 *pcbEncoded
= bytesNeeded
;
1141 /* Have to propagate index of failing character */
1148 static int BLOBComp(const void *l
, const void *r
)
1150 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1153 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1154 ret
= a
->cbData
- b
->cbData
;
1158 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1160 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1161 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1162 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1164 const CRYPT_BLOB_ARRAY
*set
= (const CRYPT_BLOB_ARRAY
*)pvStructInfo
;
1165 DWORD bytesNeeded
= 0, lenBytes
, i
;
1168 for (i
= 0; i
< set
->cBlob
; i
++)
1169 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1170 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1171 bytesNeeded
+= 1 + lenBytes
;
1174 *pcbEncoded
= bytesNeeded
;
1177 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1178 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1180 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1181 pbEncoded
= *(BYTE
**)pbEncoded
;
1182 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1183 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1184 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1185 pbEncoded
+= lenBytes
;
1186 for (i
= 0; ret
&& i
< set
->cBlob
; i
++)
1188 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1189 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1195 struct DERSetDescriptor
1201 CryptEncodeObjectExFunc encode
;
1204 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1205 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1206 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1208 const struct DERSetDescriptor
*desc
=
1209 (const struct DERSetDescriptor
*)pvStructInfo
;
1210 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1216 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1221 setOf
.cBlob
= desc
->cItems
;
1222 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1225 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1227 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1228 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1229 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1232 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1233 if (!setOf
.rgBlob
[i
].pbData
)
1236 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1237 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1238 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1239 &setOf
.rgBlob
[i
].cbData
);
1241 /* Some functions propagate their errors through the size */
1243 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1247 DWORD bytesNeeded
= 0, lenBytes
;
1249 for (i
= 0; i
< setOf
.cBlob
; i
++)
1250 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1251 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1252 bytesNeeded
+= 1 + lenBytes
;
1254 *pcbEncoded
= bytesNeeded
;
1255 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1256 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1258 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1259 pbEncoded
= *(BYTE
**)pbEncoded
;
1260 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1262 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1263 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1264 pbEncoded
+= lenBytes
;
1265 for (i
= 0; i
< setOf
.cBlob
; i
++)
1267 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1268 setOf
.rgBlob
[i
].cbData
);
1269 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1273 for (i
= 0; i
< setOf
.cBlob
; i
++)
1274 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1275 CryptMemFree(setOf
.rgBlob
);
1279 static BOOL
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1280 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1284 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1293 setOf
.cBlob
= rdn
->cRDNAttr
;
1294 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1295 sizeof(CRYPT_DER_BLOB
));
1299 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1301 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1303 setOf
.rgBlob
[i
].cbData
= 0;
1304 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1305 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1308 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1309 if (!setOf
.rgBlob
[i
].pbData
)
1312 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1313 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1314 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1318 /* Have to propagate index of failing character */
1319 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1323 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1324 pbEncoded
, pcbEncoded
);
1325 for (i
= 0; i
< setOf
.cBlob
; i
++)
1326 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1330 SetLastError(STATUS_ACCESS_VIOLATION
);
1334 CryptMemFree(setOf
.rgBlob
);
1338 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1339 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1340 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1342 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1343 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1344 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1347 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1350 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1351 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1352 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1354 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1355 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1359 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1360 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1361 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1367 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1368 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1370 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1372 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1374 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1375 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1377 bytesNeeded
+= size
;
1381 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1382 bytesNeeded
+= 1 + lenBytes
;
1386 *pcbEncoded
= bytesNeeded
;
1389 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1390 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1392 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1393 pbEncoded
= *(BYTE
**)pbEncoded
;
1394 *pbEncoded
++ = ASN_SEQUENCEOF
;
1395 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1397 pbEncoded
+= lenBytes
;
1398 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1401 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1402 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1407 bytesNeeded
-= size
;
1418 SetLastError(STATUS_ACCESS_VIOLATION
);
1425 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1426 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1427 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1429 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
1432 /* CTL_V1 is not encoded */
1439 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1440 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1444 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1445 * if they are empty and the OID is not empty (otherwise omits them.)
1447 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1448 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1449 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1452 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
1453 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
1455 struct AsnEncodeSequenceItem items
[2] = {
1456 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1462 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1463 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1466 if (algo
->Parameters
.cbData
)
1467 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1469 items
[cItem
].pvStructInfo
= &nullBlob
;
1470 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1473 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1474 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1478 static BOOL
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1479 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1481 struct AsnEncodeSequenceItem items
[2] = {
1482 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1483 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1487 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1488 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
1498 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1499 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1500 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1503 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1504 const struct CTLEntries
*entries
= (const struct CTLEntries
*)pvStructInfo
;
1507 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1511 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1517 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1518 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1520 *pcbEncoded
= bytesNeeded
;
1523 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1524 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1526 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1527 pbEncoded
= *(BYTE
**)pbEncoded
;
1528 *pbEncoded
++ = ASN_SEQUENCEOF
;
1529 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1530 pbEncoded
+= lenBytes
;
1531 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1533 DWORD size
= dataLen
;
1535 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1546 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1547 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1548 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1554 const CTL_INFO
*info
= (const CTL_INFO
*)pvStructInfo
;
1555 struct AsnEncodeSequenceItem items
[9] = {
1556 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1557 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1559 struct AsnConstructedItem constructed
= { 0 };
1562 if (info
->ListIdentifier
.cbData
)
1564 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1565 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1568 if (info
->SequenceNumber
.cbData
)
1570 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1571 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1574 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1575 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1577 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1579 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1580 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1583 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1584 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1586 if (info
->cCTLEntry
)
1588 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1589 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1592 if (info
->cExtension
)
1594 constructed
.tag
= 0;
1595 constructed
.pvStructInfo
= &info
->cExtension
;
1596 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1597 items
[cItem
].pvStructInfo
= &constructed
;
1598 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1601 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1602 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1606 SetLastError(STATUS_ACCESS_VIOLATION
);
1612 static BOOL
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1613 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1614 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1620 const CRYPT_SMIME_CAPABILITY
*capability
=
1621 (const CRYPT_SMIME_CAPABILITY
*)pvStructInfo
;
1623 if (!capability
->pszObjId
)
1624 SetLastError(E_INVALIDARG
);
1627 struct AsnEncodeSequenceItem items
[] = {
1628 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1629 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1632 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1633 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1639 SetLastError(STATUS_ACCESS_VIOLATION
);
1645 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1646 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1647 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1653 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1654 const CRYPT_SMIME_CAPABILITIES
*capabilities
=
1655 (const CRYPT_SMIME_CAPABILITIES
*)pvStructInfo
;
1658 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1662 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1663 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1669 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1670 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1672 *pcbEncoded
= bytesNeeded
;
1675 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1676 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1678 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1679 pbEncoded
= *(BYTE
**)pbEncoded
;
1680 *pbEncoded
++ = ASN_SEQUENCEOF
;
1681 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1682 pbEncoded
+= lenBytes
;
1683 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1685 DWORD size
= dataLen
;
1687 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1688 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1699 SetLastError(STATUS_ACCESS_VIOLATION
);
1705 static BOOL WINAPI
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType
,
1706 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1707 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1709 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1710 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1713 for (i
= 0, dataLen
= 0; ret
&& i
< noticeRef
->cNoticeNumbers
; i
++)
1717 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1718 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, NULL
, &size
);
1724 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1725 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1727 *pcbEncoded
= bytesNeeded
;
1730 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1731 pcbEncoded
, bytesNeeded
)))
1733 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1734 pbEncoded
= *(BYTE
**)pbEncoded
;
1735 *pbEncoded
++ = ASN_SEQUENCE
;
1736 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1737 pbEncoded
+= lenBytes
;
1738 for (i
= 0; i
< noticeRef
->cNoticeNumbers
; i
++)
1740 DWORD size
= dataLen
;
1742 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1743 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, pbEncoded
, &size
);
1753 static BOOL WINAPI
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType
,
1754 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1755 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1757 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1759 CERT_NAME_VALUE orgValue
= { CERT_RDN_IA5_STRING
,
1760 { 0, (LPBYTE
)noticeRef
->pszOrganization
} };
1761 struct AsnEncodeSequenceItem items
[] = {
1762 { &orgValue
, CRYPT_AsnEncodeNameValue
, 0 },
1763 { noticeRef
, CRYPT_AsnEncodeNoticeNumbers
, 0 },
1766 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1767 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1772 static BOOL WINAPI
CRYPT_AsnEncodePolicyQualifierUserNotice(
1773 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1774 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1781 const CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
= pvStructInfo
;
1782 struct AsnEncodeSequenceItem items
[2];
1783 CERT_NAME_VALUE displayTextValue
;
1787 if (notice
->pNoticeReference
)
1789 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNoticeReference
;
1790 items
[cItem
].pvStructInfo
= notice
->pNoticeReference
;
1793 if (notice
->pszDisplayText
)
1795 displayTextValue
.dwValueType
= CERT_RDN_BMP_STRING
;
1796 displayTextValue
.Value
.cbData
= 0;
1797 displayTextValue
.Value
.pbData
= (LPBYTE
)notice
->pszDisplayText
;
1798 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNameValue
;
1799 items
[cItem
].pvStructInfo
= &displayTextValue
;
1802 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1803 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1807 SetLastError(STATUS_ACCESS_VIOLATION
);
1813 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1814 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1815 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1821 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1823 if (!attr
->pszObjId
)
1824 SetLastError(E_INVALIDARG
);
1827 struct AsnEncodeSequenceItem items
[2] = {
1828 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1829 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1832 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1833 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1839 SetLastError(STATUS_ACCESS_VIOLATION
);
1845 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1846 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1847 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1853 const CRYPT_ATTRIBUTES
*attributes
=
1854 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1855 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1856 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1858 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1859 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1863 SetLastError(STATUS_ACCESS_VIOLATION
);
1869 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1870 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1871 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1872 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1875 const CRYPT_CONTENT_INFO
*info
= (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1876 struct AsnEncodeSequenceItem items
[2] = {
1877 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1880 struct AsnConstructedItem constructed
= { 0 };
1883 if (info
->Content
.cbData
)
1885 constructed
.tag
= 0;
1886 constructed
.pvStructInfo
= &info
->Content
;
1887 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1888 items
[cItem
].pvStructInfo
= &constructed
;
1889 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1892 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1893 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1896 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1897 void *pvData
, DWORD
*pcbData
)
1899 struct AsnEncodeSequenceItem items
[] = {
1900 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1901 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1903 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1904 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1907 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1908 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1911 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1912 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1913 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1919 const CRYPT_CONTENT_INFO
*info
=
1920 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1922 if (!info
->pszObjId
)
1923 SetLastError(E_INVALIDARG
);
1925 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1926 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1931 SetLastError(STATUS_ACCESS_VIOLATION
);
1937 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1938 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1942 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1943 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1945 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1947 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1948 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1950 *pcbEncoded
= bytesNeeded
;
1953 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1954 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1958 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1959 pbEncoded
= *(BYTE
**)pbEncoded
;
1961 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1962 pbEncoded
+= lenBytes
;
1963 for (i
= 0; i
< encodedLen
; i
++)
1964 *pbEncoded
++ = (BYTE
)str
[i
];
1970 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara
, LPVOID pv
)
1972 if (pEncodePara
&& pEncodePara
->pfnFree
)
1973 pEncodePara
->pfnFree(pv
);
1978 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1979 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1983 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1984 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1986 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1988 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1989 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1991 *pcbEncoded
= bytesNeeded
;
1994 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1995 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2000 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2001 ptr
= *(BYTE
**)pbEncoded
;
2004 *ptr
++ = ASN_NUMERICSTRING
;
2005 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2007 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2009 if (isdigitW(str
[i
]))
2010 *ptr
++ = (BYTE
)str
[i
];
2014 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2018 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2019 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2025 static inline int isprintableW(WCHAR wc
)
2027 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
2028 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
2029 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
2032 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2033 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2037 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2038 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2040 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2042 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2043 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2045 *pcbEncoded
= bytesNeeded
;
2048 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2049 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2054 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2055 ptr
= *(BYTE
**)pbEncoded
;
2058 *ptr
++ = ASN_PRINTABLESTRING
;
2059 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2061 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2063 if (isprintableW(str
[i
]))
2064 *ptr
++ = (BYTE
)str
[i
];
2068 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2072 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2073 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2079 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2080 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2084 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2085 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2087 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2089 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2090 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2092 *pcbEncoded
= bytesNeeded
;
2095 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2096 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2101 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2102 ptr
= *(BYTE
**)pbEncoded
;
2105 *ptr
++ = ASN_IA5STRING
;
2106 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2108 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2111 *ptr
++ = (BYTE
)str
[i
];
2115 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2119 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2120 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2126 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2127 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2131 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2132 DWORD bytesNeeded
, lenBytes
, strLen
;
2134 /* FIXME: doesn't handle composite characters */
2135 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2137 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2138 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2140 *pcbEncoded
= bytesNeeded
;
2143 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2144 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2148 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2149 pbEncoded
= *(BYTE
**)pbEncoded
;
2150 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2151 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2152 pbEncoded
+= lenBytes
;
2153 for (i
= 0; i
< strLen
; i
++)
2157 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2158 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2165 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2166 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2167 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2173 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
2175 switch (value
->dwValueType
)
2177 case CERT_RDN_ANY_TYPE
:
2178 case CERT_RDN_ENCODED_BLOB
:
2179 case CERT_RDN_OCTET_STRING
:
2180 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2182 case CERT_RDN_NUMERIC_STRING
:
2183 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2184 pbEncoded
, pcbEncoded
);
2186 case CERT_RDN_PRINTABLE_STRING
:
2187 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2188 pbEncoded
, pcbEncoded
);
2190 case CERT_RDN_TELETEX_STRING
:
2191 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2192 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2194 case CERT_RDN_VIDEOTEX_STRING
:
2195 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2196 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2198 case CERT_RDN_IA5_STRING
:
2199 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2200 pbEncoded
, pcbEncoded
);
2202 case CERT_RDN_GRAPHIC_STRING
:
2203 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2204 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2206 case CERT_RDN_VISIBLE_STRING
:
2207 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2208 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2210 case CERT_RDN_GENERAL_STRING
:
2211 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2212 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2214 case CERT_RDN_UNIVERSAL_STRING
:
2215 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2216 pbEncoded
, pcbEncoded
);
2218 case CERT_RDN_BMP_STRING
:
2219 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2220 pbEncoded
, pcbEncoded
);
2222 case CERT_RDN_UTF8_STRING
:
2223 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2224 pbEncoded
, pcbEncoded
);
2227 SetLastError(CRYPT_E_ASN1_CHOICE
);
2232 SetLastError(STATUS_ACCESS_VIOLATION
);
2238 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2239 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2240 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2246 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
2247 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2249 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2251 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2253 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2254 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2256 bytesNeeded
+= size
;
2258 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2259 bytesNeeded
+= 1 + lenBytes
;
2263 *pcbEncoded
= bytesNeeded
;
2266 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2267 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2269 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2270 pbEncoded
= *(BYTE
**)pbEncoded
;
2271 *pbEncoded
++ = ASN_SEQUENCEOF
;
2272 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2274 pbEncoded
+= lenBytes
;
2275 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2278 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2279 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
2284 bytesNeeded
-= size
;
2293 SetLastError(STATUS_ACCESS_VIOLATION
);
2300 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2301 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2302 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2304 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2313 else if (*pcbEncoded
< 3)
2316 SetLastError(ERROR_MORE_DATA
);
2322 *pbEncoded
++ = ASN_BOOL
;
2324 *pbEncoded
++ = val
? 0xff : 0;
2327 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2331 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2332 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2333 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2335 const CERT_ALT_NAME_ENTRY
*entry
=
2336 (const CERT_ALT_NAME_ENTRY
*)pvStructInfo
;
2342 switch (entry
->dwAltNameChoice
)
2344 case CERT_ALT_NAME_RFC822_NAME
:
2345 case CERT_ALT_NAME_DNS_NAME
:
2346 case CERT_ALT_NAME_URL
:
2347 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2348 if (entry
->u
.pwszURL
)
2352 /* Not + 1: don't encode the NULL-terminator */
2353 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2354 for (i
= 0; ret
&& i
< dataLen
; i
++)
2356 if (entry
->u
.pwszURL
[i
] > 0x7f)
2358 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2367 case CERT_ALT_NAME_DIRECTORY_NAME
:
2368 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2369 dataLen
= entry
->u
.DirectoryName
.cbData
;
2371 case CERT_ALT_NAME_IP_ADDRESS
:
2372 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2373 dataLen
= entry
->u
.IPAddress
.cbData
;
2375 case CERT_ALT_NAME_REGISTERED_ID
:
2377 struct AsnEncodeTagSwappedItem swapped
=
2378 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2379 CRYPT_AsnEncodeOid
};
2381 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2384 case CERT_ALT_NAME_OTHER_NAME
:
2385 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2388 SetLastError(E_INVALIDARG
);
2393 DWORD bytesNeeded
, lenBytes
;
2395 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2396 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2398 *pcbEncoded
= bytesNeeded
;
2399 else if (*pcbEncoded
< bytesNeeded
)
2401 SetLastError(ERROR_MORE_DATA
);
2402 *pcbEncoded
= bytesNeeded
;
2408 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2409 pbEncoded
+= lenBytes
;
2410 switch (entry
->dwAltNameChoice
)
2412 case CERT_ALT_NAME_RFC822_NAME
:
2413 case CERT_ALT_NAME_DNS_NAME
:
2414 case CERT_ALT_NAME_URL
:
2418 for (i
= 0; i
< dataLen
; i
++)
2419 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2422 case CERT_ALT_NAME_DIRECTORY_NAME
:
2423 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2425 case CERT_ALT_NAME_IP_ADDRESS
:
2426 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2430 *pcbEncoded
= bytesNeeded
;
2433 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2437 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2438 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2439 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2445 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2446 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2451 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2456 for (i
= 0; i
< newBlob
.cbData
; i
++)
2457 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2463 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2464 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2465 CryptMemFree(newBlob
.pbData
);
2469 SetLastError(STATUS_ACCESS_VIOLATION
);
2476 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2477 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2478 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2484 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
2485 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
2486 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2487 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2488 struct AsnConstructedItem constructed
= { 0 };
2489 DWORD cItem
= 0, cSwapped
= 0;
2491 if (info
->KeyId
.cbData
)
2493 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2494 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2495 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2496 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2497 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2501 if (info
->CertIssuer
.cbData
)
2503 constructed
.tag
= 1;
2504 constructed
.pvStructInfo
= &info
->CertIssuer
;
2505 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2506 items
[cItem
].pvStructInfo
= &constructed
;
2507 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2510 if (info
->CertSerialNumber
.cbData
)
2512 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2513 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2514 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2515 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2516 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2520 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2521 pEncodePara
, pbEncoded
, pcbEncoded
);
2525 SetLastError(STATUS_ACCESS_VIOLATION
);
2532 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2533 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2534 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2540 const CERT_ALT_NAME_INFO
*info
=
2541 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2542 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2545 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2546 * can't encode an erroneous entry index if it's bigger than this.
2548 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2552 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2553 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2556 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2558 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2559 * the bad character, now set the index of the bad
2562 *pcbEncoded
= (BYTE
)i
<<
2563 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2568 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2569 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2572 *pcbEncoded
= bytesNeeded
;
2577 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2578 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2580 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2581 pbEncoded
= *(BYTE
**)pbEncoded
;
2582 *pbEncoded
++ = ASN_SEQUENCEOF
;
2583 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2584 pbEncoded
+= lenBytes
;
2585 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2587 DWORD len
= dataLen
;
2589 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2590 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, pbEncoded
, &len
);
2603 SetLastError(STATUS_ACCESS_VIOLATION
);
2610 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2611 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2612 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2618 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2619 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2620 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2621 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2622 DWORD cItem
= 0, cSwapped
= 0;
2624 if (info
->KeyId
.cbData
)
2626 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2627 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2628 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2629 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2630 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2634 if (info
->AuthorityCertIssuer
.cAltEntry
)
2636 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2637 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2638 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2639 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2640 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2644 if (info
->AuthorityCertSerialNumber
.cbData
)
2646 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2647 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2648 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2649 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2650 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2654 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2655 pEncodePara
, pbEncoded
, pcbEncoded
);
2659 SetLastError(STATUS_ACCESS_VIOLATION
);
2666 static BOOL
CRYPT_AsnEncodeAccessDescription(
2667 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2669 struct AsnEncodeSequenceItem items
[] = {
2670 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2671 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2674 if (!descr
->pszAccessMethod
)
2676 SetLastError(E_INVALIDARG
);
2679 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
2680 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
2683 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2684 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2685 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2691 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2692 const CERT_AUTHORITY_INFO_ACCESS
*info
=
2693 (const CERT_AUTHORITY_INFO_ACCESS
*)pvStructInfo
;
2696 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2700 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2707 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2708 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2710 *pcbEncoded
= bytesNeeded
;
2713 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2714 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2716 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2717 pbEncoded
= *(BYTE
**)pbEncoded
;
2718 *pbEncoded
++ = ASN_SEQUENCEOF
;
2719 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2720 pbEncoded
+= lenBytes
;
2721 for (i
= 0; i
< info
->cAccDescr
; i
++)
2723 DWORD size
= dataLen
;
2725 ret
= CRYPT_AsnEncodeAccessDescription(
2726 &info
->rgAccDescr
[i
], pbEncoded
, &size
);
2736 SetLastError(STATUS_ACCESS_VIOLATION
);
2743 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2744 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2745 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2751 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2752 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2753 struct AsnEncodeSequenceItem items
[3] = {
2754 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2759 if (info
->fPathLenConstraint
)
2761 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2762 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2765 if (info
->cSubtreesConstraint
)
2767 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2768 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2771 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2772 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2776 SetLastError(STATUS_ACCESS_VIOLATION
);
2783 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2784 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2785 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2791 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2792 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2793 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2798 items
[cItem
].pvStructInfo
= &info
->fCA
;
2799 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2802 if (info
->fPathLenConstraint
)
2804 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2805 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2808 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2809 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2813 SetLastError(STATUS_ACCESS_VIOLATION
);
2820 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2821 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2822 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2824 DWORD cPolicyQualifier
= *(DWORD
*)pvStructInfo
;
2825 const CERT_POLICY_QUALIFIER_INFO
*rgPolicyQualifier
=
2826 *(const CERT_POLICY_QUALIFIER_INFO
**)
2827 ((LPBYTE
)pvStructInfo
+ sizeof(DWORD
));
2830 if (!cPolicyQualifier
)
2837 struct AsnEncodeSequenceItem items
[2] = {
2838 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2839 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2841 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2844 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2846 items
[0].pvStructInfo
= rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2847 items
[1].pvStructInfo
= &rgPolicyQualifier
[i
].Qualifier
;
2848 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2849 sizeof(items
) / sizeof(items
[0]),
2850 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2852 bytesNeeded
+= size
;
2854 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2855 bytesNeeded
+= 1 + lenBytes
;
2859 *pcbEncoded
= bytesNeeded
;
2862 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2863 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2865 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2866 pbEncoded
= *(BYTE
**)pbEncoded
;
2867 *pbEncoded
++ = ASN_SEQUENCEOF
;
2868 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2870 pbEncoded
+= lenBytes
;
2871 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2873 items
[0].pvStructInfo
=
2874 rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2875 items
[1].pvStructInfo
=
2876 &rgPolicyQualifier
[i
].Qualifier
;
2878 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2879 sizeof(items
) / sizeof(items
[0]),
2880 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2885 bytesNeeded
-= size
;
2895 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2896 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2899 struct AsnEncodeSequenceItem items
[2] = {
2900 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2901 { &info
->cPolicyQualifier
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2905 if (!info
->pszPolicyIdentifier
)
2907 SetLastError(E_INVALIDARG
);
2910 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2911 sizeof(items
) / sizeof(items
[0]), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2915 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2916 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2917 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2923 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2924 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2927 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2929 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2930 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2933 bytesNeeded
+= size
;
2935 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2936 bytesNeeded
+= 1 + lenBytes
;
2940 *pcbEncoded
= bytesNeeded
;
2943 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2944 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2946 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2947 pbEncoded
= *(BYTE
**)pbEncoded
;
2948 *pbEncoded
++ = ASN_SEQUENCEOF
;
2949 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2951 pbEncoded
+= lenBytes
;
2952 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2955 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2956 &info
->rgPolicyInfo
[i
],
2957 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pbEncoded
, &size
);
2961 bytesNeeded
-= size
;
2970 SetLastError(STATUS_ACCESS_VIOLATION
);
2976 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2977 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2978 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2984 const BLOBHEADER
*hdr
=
2985 (const BLOBHEADER
*)pvStructInfo
;
2987 if (hdr
->bType
!= PUBLICKEYBLOB
)
2989 SetLastError(E_INVALIDARG
);
2994 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2995 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2996 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2997 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2998 struct AsnEncodeSequenceItem items
[] = {
2999 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3000 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
3003 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3004 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3010 SetLastError(STATUS_ACCESS_VIOLATION
);
3017 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
3018 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3019 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3025 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
3026 DWORD bytesNeeded
, lenBytes
;
3028 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3029 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
3031 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3032 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3035 *pcbEncoded
= bytesNeeded
;
3040 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3041 pcbEncoded
, bytesNeeded
)))
3043 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3044 pbEncoded
= *(BYTE
**)pbEncoded
;
3045 *pbEncoded
++ = ASN_OCTETSTRING
;
3046 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3047 pbEncoded
+= lenBytes
;
3049 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3055 SetLastError(STATUS_ACCESS_VIOLATION
);
3059 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3063 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3064 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3065 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3071 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
3072 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3075 /* yep, MS allows cUnusedBits to be >= 8 */
3076 if (!blob
->cUnusedBits
)
3078 dataBytes
= blob
->cbData
;
3081 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3083 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3084 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3092 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3093 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3096 *pcbEncoded
= bytesNeeded
;
3101 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3102 pcbEncoded
, bytesNeeded
)))
3104 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3105 pbEncoded
= *(BYTE
**)pbEncoded
;
3106 *pbEncoded
++ = ASN_BITSTRING
;
3107 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3108 pbEncoded
+= lenBytes
;
3109 *pbEncoded
++ = unusedBits
;
3112 BYTE mask
= 0xff << unusedBits
;
3116 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3117 pbEncoded
+= dataBytes
- 1;
3119 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3126 SetLastError(STATUS_ACCESS_VIOLATION
);
3133 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3134 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3135 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3141 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
3142 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3147 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3152 for (i
= 0; i
< newBlob
.cbData
; i
++)
3153 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3159 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3160 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3161 CryptMemFree(newBlob
.pbData
);
3165 SetLastError(STATUS_ACCESS_VIOLATION
);
3172 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3173 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3174 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3176 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3178 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3179 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3182 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3183 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3184 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3190 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3193 const CRYPT_INTEGER_BLOB
*blob
=
3194 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3196 significantBytes
= blob
->cbData
;
3197 if (significantBytes
)
3199 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3201 /* negative, lop off leading (little-endian) 0xffs */
3202 for (; significantBytes
> 0 &&
3203 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3205 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3213 /* positive, lop off leading (little-endian) zeroes */
3214 for (; significantBytes
> 0 &&
3215 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3217 if (significantBytes
== 0)
3218 significantBytes
= 1;
3219 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3227 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3229 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3230 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3235 *pcbEncoded
= bytesNeeded
;
3240 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3241 pcbEncoded
, bytesNeeded
)))
3243 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3244 pbEncoded
= *(BYTE
**)pbEncoded
;
3245 *pbEncoded
++ = ASN_INTEGER
;
3248 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3249 pbEncoded
+= lenBytes
;
3250 *pbEncoded
++ = padByte
;
3254 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3255 pbEncoded
+= lenBytes
;
3257 for (; significantBytes
> 0; significantBytes
--)
3258 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3264 SetLastError(STATUS_ACCESS_VIOLATION
);
3271 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3272 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3273 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3279 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3281 const CRYPT_INTEGER_BLOB
*blob
=
3282 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3284 significantBytes
= blob
->cbData
;
3285 if (significantBytes
)
3287 /* positive, lop off leading (little-endian) zeroes */
3288 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3291 if (significantBytes
== 0)
3292 significantBytes
= 1;
3293 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3297 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3299 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3300 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3305 *pcbEncoded
= bytesNeeded
;
3310 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3311 pcbEncoded
, bytesNeeded
)))
3313 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3314 pbEncoded
= *(BYTE
**)pbEncoded
;
3315 *pbEncoded
++ = ASN_INTEGER
;
3318 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3319 pbEncoded
+= lenBytes
;
3324 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3325 pbEncoded
+= lenBytes
;
3327 for (; significantBytes
> 0; significantBytes
--)
3328 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3334 SetLastError(STATUS_ACCESS_VIOLATION
);
3341 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3342 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3343 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3345 CRYPT_INTEGER_BLOB blob
;
3348 /* Encode as an unsigned integer, then change the tag to enumerated */
3349 blob
.cbData
= sizeof(DWORD
);
3350 blob
.pbData
= (BYTE
*)pvStructInfo
;
3351 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3352 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3353 if (ret
&& pbEncoded
)
3355 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3356 pbEncoded
= *(BYTE
**)pbEncoded
;
3357 pbEncoded
[0] = ASN_ENUMERATED
;
3362 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3363 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3364 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3371 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3372 * temporary buffer because the output buffer is not NULL-terminated.
3375 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3379 *pcbEncoded
= bytesNeeded
;
3384 /* Sanity check the year, this is a two-digit year format */
3385 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
3387 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3389 SetLastError(CRYPT_E_BAD_ENCODE
);
3394 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3395 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3397 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3398 pbEncoded
= *(BYTE
**)pbEncoded
;
3399 buf
[0] = ASN_UTCTIME
;
3400 buf
[1] = bytesNeeded
- 2;
3401 snprintf(buf
+ 2, sizeof(buf
) - 2,
3402 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3403 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3404 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3405 sysTime
.wMinute
, sysTime
.wSecond
);
3406 memcpy(pbEncoded
, buf
, bytesNeeded
);
3413 SetLastError(STATUS_ACCESS_VIOLATION
);
3420 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3421 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3422 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3429 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3430 * temporary buffer because the output buffer is not NULL-terminated.
3433 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3437 *pcbEncoded
= bytesNeeded
;
3442 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
3445 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3446 pcbEncoded
, bytesNeeded
);
3449 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3450 pbEncoded
= *(BYTE
**)pbEncoded
;
3451 buf
[0] = ASN_GENERALTIME
;
3452 buf
[1] = bytesNeeded
- 2;
3453 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3454 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3455 sysTime
.wMinute
, sysTime
.wSecond
);
3456 memcpy(pbEncoded
, buf
, bytesNeeded
);
3462 SetLastError(STATUS_ACCESS_VIOLATION
);
3469 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3470 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3471 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3479 /* Check the year, if it's in the UTCTime range call that encode func */
3480 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
3482 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3483 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3484 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3486 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3487 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3492 SetLastError(STATUS_ACCESS_VIOLATION
);
3499 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3500 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3501 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3507 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3508 const CRYPT_SEQUENCE_OF_ANY
*seq
=
3509 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3511 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3512 dataLen
+= seq
->rgValue
[i
].cbData
;
3513 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3514 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3517 *pcbEncoded
= bytesNeeded
;
3522 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3523 pcbEncoded
, bytesNeeded
)))
3525 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3526 pbEncoded
= *(BYTE
**)pbEncoded
;
3527 *pbEncoded
++ = ASN_SEQUENCEOF
;
3528 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3529 pbEncoded
+= lenBytes
;
3530 for (i
= 0; i
< seq
->cValue
; i
++)
3532 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3533 seq
->rgValue
[i
].cbData
);
3534 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3541 SetLastError(STATUS_ACCESS_VIOLATION
);
3548 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3549 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3552 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3553 struct AsnConstructedItem constructed
= { 0 };
3554 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3555 DWORD cItem
= 0, cSwapped
= 0;
3557 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3559 case CRL_DIST_POINT_NO_NAME
:
3562 case CRL_DIST_POINT_FULL_NAME
:
3563 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3564 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3565 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3566 constructed
.tag
= 0;
3567 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3568 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3569 items
[cItem
].pvStructInfo
= &constructed
;
3570 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3574 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3575 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3581 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3583 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3584 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3585 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3586 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3587 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3591 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3593 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3594 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3595 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3596 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3597 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3602 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3603 pbEncoded
, pcbEncoded
);
3607 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3608 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3609 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3615 const CRL_DIST_POINTS_INFO
*info
=
3616 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
3618 if (!info
->cDistPoint
)
3620 SetLastError(E_INVALIDARG
);
3625 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3628 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3632 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3636 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3638 /* Have to propagate index of failing character */
3644 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3645 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3648 *pcbEncoded
= bytesNeeded
;
3653 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3654 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3656 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3657 pbEncoded
= *(BYTE
**)pbEncoded
;
3658 *pbEncoded
++ = ASN_SEQUENCEOF
;
3659 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3660 pbEncoded
+= lenBytes
;
3661 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3663 DWORD len
= dataLen
;
3665 ret
= CRYPT_AsnEncodeDistPoint(
3666 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3680 SetLastError(STATUS_ACCESS_VIOLATION
);
3687 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3688 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3689 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3695 const CERT_ENHKEY_USAGE
*usage
=
3696 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
3697 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3700 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3702 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3703 usage
->rgpszUsageIdentifier
[i
],
3704 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3706 bytesNeeded
+= size
;
3708 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3709 bytesNeeded
+= 1 + lenBytes
;
3713 *pcbEncoded
= bytesNeeded
;
3716 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3717 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3719 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3720 pbEncoded
= *(BYTE
**)pbEncoded
;
3721 *pbEncoded
++ = ASN_SEQUENCEOF
;
3722 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3724 pbEncoded
+= lenBytes
;
3725 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3728 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3729 usage
->rgpszUsageIdentifier
[i
],
3730 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3735 bytesNeeded
-= size
;
3744 SetLastError(STATUS_ACCESS_VIOLATION
);
3751 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3752 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3753 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3759 const CRL_ISSUING_DIST_POINT
*point
=
3760 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3761 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3762 struct AsnConstructedItem constructed
= { 0 };
3763 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3764 DWORD cItem
= 0, cSwapped
= 0;
3767 switch (point
->DistPointName
.dwDistPointNameChoice
)
3769 case CRL_DIST_POINT_NO_NAME
:
3772 case CRL_DIST_POINT_FULL_NAME
:
3773 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3774 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3775 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3776 constructed
.tag
= 0;
3777 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3778 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3779 items
[cItem
].pvStructInfo
= &constructed
;
3780 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3785 SetLastError(E_INVALIDARG
);
3788 if (ret
&& point
->fOnlyContainsUserCerts
)
3790 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3791 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3792 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3793 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3794 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3798 if (ret
&& point
->fOnlyContainsCACerts
)
3800 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3801 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3802 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3803 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3804 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3808 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3810 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3811 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3812 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3813 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3814 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3818 if (ret
&& point
->fIndirectCRL
)
3820 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3821 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3822 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3823 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3824 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3829 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3830 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3834 SetLastError(STATUS_ACCESS_VIOLATION
);
3841 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3842 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3843 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3846 const CERT_GENERAL_SUBTREE
*subtree
=
3847 (const CERT_GENERAL_SUBTREE
*)pvStructInfo
;
3848 struct AsnEncodeSequenceItem items
[3] = {
3849 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
3852 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3853 DWORD cItem
= 1, cSwapped
= 0;
3855 if (subtree
->dwMinimum
)
3857 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3858 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
3859 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3860 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3861 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3865 if (subtree
->fMaximum
)
3867 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3868 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
3869 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3870 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3871 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3875 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
3876 pEncodePara
, pbEncoded
, pcbEncoded
);
3880 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
3881 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3882 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3885 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
3887 TRACE("%p\n", pvStructInfo
);
3891 const CERT_NAME_CONSTRAINTS_INFO
*constraints
=
3892 (const CERT_NAME_CONSTRAINTS_INFO
*)pvStructInfo
;
3893 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
3894 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3895 DWORD i
, cItem
= 0, cSwapped
= 0;
3898 if (constraints
->cPermittedSubtree
)
3900 permitted
.rgBlob
= CryptMemAlloc(
3901 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
3902 if (permitted
.rgBlob
)
3904 permitted
.cBlob
= constraints
->cPermittedSubtree
;
3905 memset(permitted
.rgBlob
, 0,
3906 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3907 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
3908 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3909 NULL
, &constraints
->rgPermittedSubtree
[i
],
3910 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3911 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
3912 &permitted
.rgBlob
[i
].cbData
);
3915 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3916 swapped
[cSwapped
].pvStructInfo
= &permitted
;
3917 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3918 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3919 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3927 if (constraints
->cExcludedSubtree
)
3929 excluded
.rgBlob
= CryptMemAlloc(
3930 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
3931 if (excluded
.rgBlob
)
3933 excluded
.cBlob
= constraints
->cExcludedSubtree
;
3934 memset(excluded
.rgBlob
, 0,
3935 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3936 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
3937 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3938 NULL
, &constraints
->rgExcludedSubtree
[i
],
3939 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3940 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
3941 &excluded
.rgBlob
[i
].cbData
);
3944 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3945 swapped
[cSwapped
].pvStructInfo
= &excluded
;
3946 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3947 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3948 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3957 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3958 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3959 for (i
= 0; i
< permitted
.cBlob
; i
++)
3960 LocalFree(permitted
.rgBlob
[i
].pbData
);
3961 for (i
= 0; i
< excluded
.cBlob
; i
++)
3962 LocalFree(excluded
.rgBlob
[i
].pbData
);
3966 SetLastError(STATUS_ACCESS_VIOLATION
);
3969 CryptMemFree(permitted
.rgBlob
);
3970 CryptMemFree(excluded
.rgBlob
);
3971 TRACE("returning %d\n", ret
);
3975 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3976 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3977 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3981 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3982 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3983 struct AsnEncodeSequenceItem items
[] = {
3984 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3985 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3988 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3989 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3994 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3995 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3996 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4000 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4002 SetLastError(E_INVALIDARG
);
4008 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
4010 if (!info
->Issuer
.cbData
)
4011 SetLastError(E_INVALIDARG
);
4014 struct AsnEncodeSequenceItem items
[7] = {
4015 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4016 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4017 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
4020 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4021 DWORD cItem
= 3, cSwapped
= 0;
4023 if (info
->AuthAttrs
.cAttr
)
4025 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4026 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4027 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4028 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4029 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4033 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4034 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4036 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4037 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4039 if (info
->UnauthAttrs
.cAttr
)
4041 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4042 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4043 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4044 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4045 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4049 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4050 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4055 SetLastError(STATUS_ACCESS_VIOLATION
);
4061 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4062 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4063 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4067 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4069 SetLastError(E_INVALIDARG
);
4075 const CMSG_CMS_SIGNER_INFO
*info
= (const CMSG_CMS_SIGNER_INFO
*)pvStructInfo
;
4077 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4078 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4079 SetLastError(E_INVALIDARG
);
4080 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4081 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4082 SetLastError(E_INVALIDARG
);
4085 struct AsnEncodeSequenceItem items
[7] = {
4086 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4088 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4089 DWORD cItem
= 1, cSwapped
= 0;
4091 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4093 items
[cItem
].pvStructInfo
=
4094 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4095 items
[cItem
].encodeFunc
=
4096 CRYPT_AsnEncodeIssuerSerialNumber
;
4101 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4102 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4103 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4104 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4105 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4109 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4110 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4112 if (info
->AuthAttrs
.cAttr
)
4114 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4115 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4116 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4117 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4118 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4122 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4123 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4125 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4126 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4128 if (info
->UnauthAttrs
.cAttr
)
4130 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4131 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4132 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4133 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4134 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4138 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4139 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4144 SetLastError(STATUS_ACCESS_VIOLATION
);
4150 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4153 struct AsnEncodeSequenceItem items
[7] = {
4154 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4156 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4157 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4158 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4159 DWORD cItem
= 1, cSwapped
= 0;
4162 if (signedInfo
->cSignerInfo
)
4164 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4165 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4166 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4167 digestAlgorithmsSet
.itemOffset
=
4168 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4169 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4170 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4171 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4174 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4175 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4177 if (signedInfo
->cCertEncoded
)
4179 certSet
.cItems
= signedInfo
->cCertEncoded
;
4180 certSet
.items
= signedInfo
->rgCertEncoded
;
4181 certSet
.itemSize
= sizeof(CERT_BLOB
);
4182 certSet
.itemOffset
= 0;
4183 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4184 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4185 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4186 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4187 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4188 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4192 if (signedInfo
->cCrlEncoded
)
4194 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4195 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4196 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4197 crlSet
.itemOffset
= 0;
4198 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4199 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4200 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4201 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4202 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4203 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4207 if (ret
&& signedInfo
->cSignerInfo
)
4209 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4210 signerSet
.items
= signedInfo
->rgSignerInfo
;
4211 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4212 signerSet
.itemOffset
= 0;
4213 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4214 items
[cItem
].pvStructInfo
= &signerSet
;
4215 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4219 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4220 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4225 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4226 LPCSTR lpszStructType
)
4228 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4230 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4231 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4233 SetLastError(ERROR_FILE_NOT_FOUND
);
4237 if (!HIWORD(lpszStructType
))
4239 switch (LOWORD(lpszStructType
))
4241 case LOWORD(X509_CERT
):
4242 encodeFunc
= CRYPT_AsnEncodeCert
;
4244 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4245 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4247 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4248 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4250 case LOWORD(X509_EXTENSIONS
):
4251 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4253 case LOWORD(X509_NAME_VALUE
):
4254 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4256 case LOWORD(X509_NAME
):
4257 encodeFunc
= CRYPT_AsnEncodeName
;
4259 case LOWORD(X509_PUBLIC_KEY_INFO
):
4260 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4262 case LOWORD(X509_AUTHORITY_KEY_ID
):
4263 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4265 case LOWORD(X509_ALTERNATE_NAME
):
4266 encodeFunc
= CRYPT_AsnEncodeAltName
;
4268 case LOWORD(X509_BASIC_CONSTRAINTS
):
4269 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4271 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4272 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4274 case LOWORD(X509_CERT_POLICIES
):
4275 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4277 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4278 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4280 case LOWORD(X509_UNICODE_NAME
):
4281 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4283 case LOWORD(PKCS_CONTENT_INFO
):
4284 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4286 case LOWORD(PKCS_ATTRIBUTE
):
4287 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4289 case LOWORD(X509_UNICODE_NAME_VALUE
):
4290 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4292 case LOWORD(X509_OCTET_STRING
):
4293 encodeFunc
= CRYPT_AsnEncodeOctets
;
4295 case LOWORD(X509_BITS
):
4296 case LOWORD(X509_KEY_USAGE
):
4297 encodeFunc
= CRYPT_AsnEncodeBits
;
4299 case LOWORD(X509_INTEGER
):
4300 encodeFunc
= CRYPT_AsnEncodeInt
;
4302 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4303 encodeFunc
= CRYPT_AsnEncodeInteger
;
4305 case LOWORD(X509_MULTI_BYTE_UINT
):
4306 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4308 case LOWORD(X509_ENUMERATED
):
4309 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4311 case LOWORD(X509_CHOICE_OF_TIME
):
4312 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4314 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4315 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4317 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4318 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4320 case LOWORD(X509_SEQUENCE_OF_ANY
):
4321 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4323 case LOWORD(PKCS_UTC_TIME
):
4324 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4326 case LOWORD(X509_CRL_DIST_POINTS
):
4327 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4329 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4330 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4332 case LOWORD(PKCS_CTL
):
4333 encodeFunc
= CRYPT_AsnEncodeCTL
;
4335 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4336 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4338 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4339 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4341 case LOWORD(PKCS_ATTRIBUTES
):
4342 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4344 case LOWORD(X509_ISSUING_DIST_POINT
):
4345 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4347 case LOWORD(X509_NAME_CONSTRAINTS
):
4348 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4350 case LOWORD(PKCS7_SIGNER_INFO
):
4351 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4353 case LOWORD(CMS_SIGNER_INFO
):
4354 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4358 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4359 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4360 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4361 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4362 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4363 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4364 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4365 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4366 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4367 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4368 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4369 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4370 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4371 encodeFunc
= CRYPT_AsnEncodeBits
;
4372 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4373 encodeFunc
= CRYPT_AsnEncodeOctets
;
4374 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4375 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4376 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4377 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4378 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4379 encodeFunc
= CRYPT_AsnEncodeAltName
;
4380 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4381 encodeFunc
= CRYPT_AsnEncodeAltName
;
4382 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4383 encodeFunc
= CRYPT_AsnEncodeAltName
;
4384 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4385 encodeFunc
= CRYPT_AsnEncodeAltName
;
4386 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4387 encodeFunc
= CRYPT_AsnEncodeAltName
;
4388 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4389 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4390 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4391 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4392 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4393 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4394 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4395 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4396 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4397 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4398 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4399 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4400 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4401 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4402 else if (!strcmp(lpszStructType
, szOID_CTL
))
4403 encodeFunc
= CRYPT_AsnEncodeCTL
;
4407 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4408 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4410 static HCRYPTOIDFUNCSET set
= NULL
;
4411 CryptEncodeObjectFunc encodeFunc
= NULL
;
4414 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4415 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4416 (void **)&encodeFunc
, hFunc
);
4420 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4421 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4423 static HCRYPTOIDFUNCSET set
= NULL
;
4424 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4427 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4428 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4429 (void **)&encodeFunc
, hFunc
);
4433 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4434 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4437 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4438 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4439 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4441 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4442 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4445 if (!pbEncoded
&& !pcbEncoded
)
4447 SetLastError(ERROR_INVALID_PARAMETER
);
4451 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4454 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4455 debugstr_a(lpszStructType
));
4456 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4457 lpszStructType
, &hFunc
);
4458 if (!pCryptEncodeObject
)
4459 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4460 lpszStructType
, &hFunc
);
4462 if (pCryptEncodeObject
)
4463 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4464 pvStructInfo
, pbEncoded
, pcbEncoded
);
4465 else if (pCryptEncodeObjectEx
)
4466 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4467 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4469 CryptFreeOIDFunctionAddress(hFunc
, 0);
4470 TRACE_(crypt
)("returning %d\n", ret
);
4474 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4475 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4476 void *pvEncoded
, DWORD
*pcbEncoded
)
4479 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4480 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4482 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4483 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4484 pvEncoded
, pcbEncoded
);
4486 if (!pvEncoded
&& !pcbEncoded
)
4488 SetLastError(ERROR_INVALID_PARAMETER
);
4492 SetLastError(NOERROR
);
4493 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
4494 *(BYTE
**)pvEncoded
= NULL
;
4495 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4498 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4499 debugstr_a(lpszStructType
));
4500 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4504 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4505 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4508 CryptEncodeObjectFunc pCryptEncodeObject
=
4509 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4511 if (pCryptEncodeObject
)
4513 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4515 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4516 pvStructInfo
, NULL
, pcbEncoded
);
4517 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4518 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4519 ret
= pCryptEncodeObject(dwCertEncodingType
,
4520 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4524 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4525 pvStructInfo
, pvEncoded
, pcbEncoded
);
4529 CryptFreeOIDFunctionAddress(hFunc
, 0);
4530 TRACE_(crypt
)("returning %d\n", ret
);
4534 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4535 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4537 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4538 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4541 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4542 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4543 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4547 static CHAR oid
[] = szOID_RSA_RSA
;
4549 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4550 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4551 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4553 if (!pszPublicKeyObjId
)
4554 pszPublicKeyObjId
= oid
;
4555 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4559 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4562 LPBYTE pubKey
= CryptMemAlloc(keySize
);
4566 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4570 DWORD encodedLen
= 0;
4572 ret
= CryptEncodeObject(dwCertEncodingType
,
4573 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4576 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4577 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4580 *pcbInfo
= sizeNeeded
;
4581 else if (*pcbInfo
< sizeNeeded
)
4583 SetLastError(ERROR_MORE_DATA
);
4584 *pcbInfo
= sizeNeeded
;
4589 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4590 sizeof(CERT_PUBLIC_KEY_INFO
);
4591 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4593 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4594 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4595 pInfo
->PublicKey
.pbData
=
4596 (BYTE
*)pInfo
->Algorithm
.pszObjId
4597 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4598 pInfo
->PublicKey
.cbData
= encodedLen
;
4599 pInfo
->PublicKey
.cUnusedBits
= 0;
4600 ret
= CryptEncodeObject(dwCertEncodingType
,
4601 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4602 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4606 CryptMemFree(pubKey
);
4611 CryptDestroyKey(key
);
4616 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4617 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4618 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4620 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4621 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4622 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4624 static HCRYPTOIDFUNCSET set
= NULL
;
4626 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4627 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4629 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4630 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4631 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4635 SetLastError(ERROR_INVALID_PARAMETER
);
4639 if (pszPublicKeyObjId
)
4642 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4644 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4645 0, (void **)&exportFunc
, &hFunc
);
4648 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4649 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4650 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4652 CryptFreeOIDFunctionAddress(hFunc
, 0);
4656 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4657 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4659 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4663 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4664 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4665 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4668 DWORD pubKeySize
= 0;
4670 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4671 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4673 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4674 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4677 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4681 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4682 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4687 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4688 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4691 CryptMemFree(pubKey
);
4699 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4700 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4701 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4703 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4704 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4705 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4707 static HCRYPTOIDFUNCSET set
= NULL
;
4709 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4710 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4712 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4713 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4716 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4717 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4718 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4720 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4721 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4724 CryptFreeOIDFunctionAddress(hFunc
, 0);