2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
34 #include "wine/port.h"
41 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
55 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
93 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
95 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
96 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
97 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
98 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
99 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
100 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
101 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
103 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
104 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
108 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
110 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
111 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
113 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
114 if (!*(BYTE
**)pbEncoded
)
117 *pcbEncoded
= bytesNeeded
;
119 else if (bytesNeeded
> *pcbEncoded
)
121 *pcbEncoded
= bytesNeeded
;
122 SetLastError(ERROR_MORE_DATA
);
126 *pcbEncoded
= bytesNeeded
;
130 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
132 DWORD bytesNeeded
, significantBytes
= 0;
140 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
141 temp
<<= 8, significantBytes
--)
143 bytesNeeded
= significantBytes
+ 1;
147 *pcbEncoded
= bytesNeeded
;
150 if (*pcbEncoded
< bytesNeeded
)
152 SetLastError(ERROR_MORE_DATA
);
156 *pbEncoded
= (BYTE
)len
;
161 *pbEncoded
++ = significantBytes
| 0x80;
162 for (i
= 0; i
< significantBytes
; i
++)
164 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
168 *pcbEncoded
= bytesNeeded
;
172 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
173 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
174 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
177 DWORD i
, dataLen
= 0;
179 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
180 pbEncoded
, *pcbEncoded
);
181 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
183 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
184 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
185 NULL
, &items
[i
].size
);
186 /* Some functions propagate their errors through the size */
188 *pcbEncoded
= items
[i
].size
;
189 dataLen
+= items
[i
].size
;
193 DWORD lenBytes
, bytesNeeded
;
195 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
196 bytesNeeded
= 1 + lenBytes
+ dataLen
;
198 *pcbEncoded
= bytesNeeded
;
201 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
202 pcbEncoded
, bytesNeeded
)))
204 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
205 pbEncoded
= *(BYTE
**)pbEncoded
;
206 *pbEncoded
++ = ASN_SEQUENCE
;
207 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
208 pbEncoded
+= lenBytes
;
209 for (i
= 0; ret
&& i
< cItem
; i
++)
211 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
212 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
213 NULL
, pbEncoded
, &items
[i
].size
);
214 /* Some functions propagate their errors through the size */
216 *pcbEncoded
= items
[i
].size
;
217 pbEncoded
+= items
[i
].size
;
222 TRACE("returning %d (%08x)\n", ret
, GetLastError());
226 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
227 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
228 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
231 const struct AsnConstructedItem
*item
=
232 (const struct AsnConstructedItem
*)pvStructInfo
;
235 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
236 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
238 DWORD dataLen
, bytesNeeded
;
240 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
241 bytesNeeded
= 1 + dataLen
+ len
;
243 *pcbEncoded
= bytesNeeded
;
244 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
245 pbEncoded
, pcbEncoded
, bytesNeeded
)))
247 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
248 pbEncoded
= *(BYTE
**)pbEncoded
;
249 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
250 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
251 pbEncoded
+= dataLen
;
252 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
253 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
257 /* Some functions propagate their errors through the size */
264 /* Some functions propagate their errors through the size */
270 struct AsnEncodeTagSwappedItem
273 const void *pvStructInfo
;
274 CryptEncodeObjectExFunc encodeFunc
;
277 /* Sort of a wacky hack, it encodes something using the struct
278 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
279 * given in the struct AsnEncodeTagSwappedItem.
281 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
282 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
283 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
286 const struct AsnEncodeTagSwappedItem
*item
=
287 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
289 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
290 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
291 if (ret
&& pbEncoded
)
292 *pbEncoded
= item
->tag
;
296 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
297 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
298 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
300 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
303 /* CERT_V1 is not encoded */
311 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
313 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
314 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
319 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
320 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
321 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
323 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
328 *pcbEncoded
= blob
->cbData
;
333 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
334 pcbEncoded
, blob
->cbData
)))
336 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
337 pbEncoded
= *(BYTE
**)pbEncoded
;
339 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
340 *pcbEncoded
= blob
->cbData
;
347 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
348 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
349 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
352 /* This has two filetimes in a row, a NotBefore and a NotAfter */
353 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
354 struct AsnEncodeSequenceItem items
[] = {
355 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
356 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
359 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
360 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
365 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
368 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
369 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
370 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
373 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
374 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
375 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
376 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
379 struct AsnEncodeSequenceItem items
[2] = {
380 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
381 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
384 if (algo
->Parameters
.cbData
)
385 items
[1].pvStructInfo
= &algo
->Parameters
;
387 items
[1].pvStructInfo
= &nullBlob
;
388 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
389 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
394 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
395 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
396 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
398 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
399 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
401 struct AsnEncodeSequenceItem items
[] = {
402 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
403 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
406 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
407 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
412 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
413 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
414 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
420 const CERT_PUBLIC_KEY_INFO
*info
=
421 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
422 struct AsnEncodeSequenceItem items
[] = {
423 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
424 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
427 TRACE("Encoding public key with OID %s\n",
428 debugstr_a(info
->Algorithm
.pszObjId
));
429 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
430 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
435 SetLastError(STATUS_ACCESS_VIOLATION
);
442 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
443 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
444 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
450 const CERT_SIGNED_CONTENT_INFO
*info
=
451 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
452 struct AsnEncodeSequenceItem items
[] = {
453 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
454 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
455 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
458 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
459 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
460 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
461 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
466 SetLastError(STATUS_ACCESS_VIOLATION
);
473 /* Like in Windows, this blithely ignores the validity of the passed-in
474 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
475 * decode properly, see CRYPT_AsnDecodeCertInfo.
477 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
478 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
479 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
485 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
486 struct AsnEncodeSequenceItem items
[10] = {
487 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
488 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
489 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
490 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
491 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
492 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
493 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
496 struct AsnConstructedItem constructed
[3] = { { 0 } };
497 DWORD cItem
= 7, cConstructed
= 0;
499 if (info
->IssuerUniqueId
.cbData
)
501 constructed
[cConstructed
].tag
= 1;
502 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
503 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
504 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
505 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
509 if (info
->SubjectUniqueId
.cbData
)
511 constructed
[cConstructed
].tag
= 2;
512 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
513 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
514 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
515 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
519 if (info
->cExtension
)
521 constructed
[cConstructed
].tag
= 3;
522 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
523 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
524 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
525 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
530 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
531 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
535 SetLastError(STATUS_ACCESS_VIOLATION
);
542 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
543 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
545 struct AsnEncodeSequenceItem items
[3] = {
546 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
547 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
553 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
555 if (entry
->cExtension
)
557 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
558 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
562 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
563 pbEncoded
, pcbEncoded
);
565 TRACE("returning %d (%08x)\n", ret
, GetLastError());
569 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
570 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
571 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
573 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
574 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
575 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
576 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
579 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
583 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
589 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
590 bytesNeeded
= 1 + lenBytes
+ dataLen
;
592 *pcbEncoded
= bytesNeeded
;
595 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
596 pcbEncoded
, bytesNeeded
)))
598 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
599 pbEncoded
= *(BYTE
**)pbEncoded
;
600 *pbEncoded
++ = ASN_SEQUENCEOF
;
601 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
602 pbEncoded
+= lenBytes
;
603 for (i
= 0; i
< cCRLEntry
; i
++)
605 DWORD size
= dataLen
;
607 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
,
618 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
619 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
620 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
622 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
625 /* CRL_V1 is not encoded */
632 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
633 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
637 /* Like in Windows, this blithely ignores the validity of the passed-in
638 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
639 * decode properly, see CRYPT_AsnDecodeCRLInfo.
641 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
642 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
643 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
649 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
650 struct AsnEncodeSequenceItem items
[7] = {
651 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
652 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
653 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
654 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
657 struct AsnConstructedItem constructed
[1] = { { 0 } };
658 DWORD cItem
= 4, cConstructed
= 0;
660 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
662 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
663 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
668 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
669 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
672 if (info
->cExtension
)
674 constructed
[cConstructed
].tag
= 0;
675 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
676 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
677 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
678 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
683 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
684 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
688 SetLastError(STATUS_ACCESS_VIOLATION
);
695 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
699 struct AsnEncodeSequenceItem items
[3] = {
700 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
706 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
710 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
711 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
714 items
[cItem
].pvStructInfo
= &ext
->Value
;
715 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
718 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
719 pbEncoded
, pcbEncoded
);
720 TRACE("returning %d (%08x)\n", ret
, GetLastError());
724 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
725 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
726 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
732 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
733 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
736 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
740 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
746 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
747 bytesNeeded
= 1 + lenBytes
+ dataLen
;
749 *pcbEncoded
= bytesNeeded
;
752 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
753 pbEncoded
, pcbEncoded
, bytesNeeded
)))
755 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
756 pbEncoded
= *(BYTE
**)pbEncoded
;
757 *pbEncoded
++ = ASN_SEQUENCEOF
;
758 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
759 pbEncoded
+= lenBytes
;
760 for (i
= 0; i
< exts
->cExtension
; i
++)
762 DWORD size
= dataLen
;
764 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
775 SetLastError(STATUS_ACCESS_VIOLATION
);
782 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
783 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
784 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
786 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
787 DWORD bytesNeeded
= 0, lenBytes
;
792 TRACE("%s\n", debugstr_a(pszObjId
));
799 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
801 SetLastError(CRYPT_E_ASN1_ERROR
);
805 firstByte
= val1
* 40 + val2
;
806 ptr
= pszObjId
+ firstPos
;
811 /* note I assume each component is at most 32-bits long in base 2 */
812 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
814 if (val1
>= 0x10000000)
816 else if (val1
>= 0x200000)
818 else if (val1
>= 0x4000)
820 else if (val1
>= 0x80)
830 SetLastError(CRYPT_E_ASN1_ERROR
);
834 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
838 bytesNeeded
+= 1 + lenBytes
;
841 if (*pcbEncoded
< bytesNeeded
)
843 SetLastError(ERROR_MORE_DATA
);
848 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
849 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
850 pbEncoded
+= lenBytes
;
856 *pbEncoded
++ = firstByte
;
857 ptr
= pszObjId
+ firstPos
;
860 sscanf(ptr
, "%d%n", &val
, &pos
);
862 unsigned char outBytes
[5];
865 if (val
>= 0x10000000)
867 else if (val
>= 0x200000)
869 else if (val
>= 0x4000)
871 else if (val
>= 0x80)
875 for (i
= numBytes
; i
> 0; i
--)
877 outBytes
[i
- 1] = val
& 0x7f;
880 for (i
= 0; i
< numBytes
- 1; i
++)
881 *pbEncoded
++ = outBytes
[i
] | 0x80;
882 *pbEncoded
++ = outBytes
[i
];
891 *pcbEncoded
= bytesNeeded
;
895 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
896 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
900 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
901 DWORD bytesNeeded
, lenBytes
, encodedLen
;
903 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
904 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
905 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
907 *pcbEncoded
= bytesNeeded
;
910 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
911 pbEncoded
, pcbEncoded
, bytesNeeded
)))
913 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
914 pbEncoded
= *(BYTE
**)pbEncoded
;
916 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
917 pbEncoded
+= lenBytes
;
918 memcpy(pbEncoded
, str
, encodedLen
);
924 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
925 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
929 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
930 DWORD bytesNeeded
, lenBytes
, strLen
;
932 if (value
->Value
.cbData
)
933 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
934 else if (value
->Value
.pbData
)
935 strLen
= lstrlenW(str
);
938 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
939 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
941 *pcbEncoded
= bytesNeeded
;
944 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
945 pbEncoded
, pcbEncoded
, bytesNeeded
)))
949 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
950 pbEncoded
= *(BYTE
**)pbEncoded
;
951 *pbEncoded
++ = ASN_BMPSTRING
;
952 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
953 pbEncoded
+= lenBytes
;
954 for (i
= 0; i
< strLen
; i
++)
956 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
957 *pbEncoded
++ = str
[i
] & 0x00ff;
964 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
965 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
969 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
970 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
972 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
974 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
976 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
977 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
979 *pcbEncoded
= bytesNeeded
;
982 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
983 pbEncoded
, pcbEncoded
, bytesNeeded
)))
985 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
986 pbEncoded
= *(BYTE
**)pbEncoded
;
987 *pbEncoded
++ = ASN_UTF8STRING
;
988 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
989 pbEncoded
+= lenBytes
;
990 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
991 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
997 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
998 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
999 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1005 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1007 switch (value
->dwValueType
)
1009 case CERT_RDN_ANY_TYPE
:
1010 /* explicitly disallowed */
1011 SetLastError(E_INVALIDARG
);
1014 case CERT_RDN_ENCODED_BLOB
:
1015 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1016 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1018 case CERT_RDN_OCTET_STRING
:
1019 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1020 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1022 case CERT_RDN_NUMERIC_STRING
:
1023 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1024 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1026 case CERT_RDN_PRINTABLE_STRING
:
1027 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1028 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1030 case CERT_RDN_TELETEX_STRING
:
1031 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1032 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1034 case CERT_RDN_VIDEOTEX_STRING
:
1035 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1036 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1038 case CERT_RDN_IA5_STRING
:
1039 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1040 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1042 case CERT_RDN_GRAPHIC_STRING
:
1043 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1044 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1046 case CERT_RDN_VISIBLE_STRING
:
1047 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1048 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1050 case CERT_RDN_GENERAL_STRING
:
1051 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1052 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1054 case CERT_RDN_UNIVERSAL_STRING
:
1055 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1056 SetLastError(CRYPT_E_ASN1_CHOICE
);
1059 case CERT_RDN_BMP_STRING
:
1060 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1061 pbEncoded
, pcbEncoded
);
1063 case CERT_RDN_UTF8_STRING
:
1064 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1065 pbEncoded
, pcbEncoded
);
1068 SetLastError(CRYPT_E_ASN1_CHOICE
);
1074 SetLastError(STATUS_ACCESS_VIOLATION
);
1081 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1082 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1083 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1085 DWORD bytesNeeded
= 0, lenBytes
, size
;
1088 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1089 0, NULL
, NULL
, &size
);
1092 bytesNeeded
+= size
;
1093 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1094 * with dwValueType, so "cast" it to get its encoded size
1096 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1097 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1100 bytesNeeded
+= size
;
1101 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1102 bytesNeeded
+= 1 + lenBytes
;
1105 if (*pcbEncoded
< bytesNeeded
)
1107 SetLastError(ERROR_MORE_DATA
);
1112 *pbEncoded
++ = ASN_SEQUENCE
;
1113 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1115 pbEncoded
+= lenBytes
;
1116 size
= bytesNeeded
- 1 - lenBytes
;
1117 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1118 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1122 size
= bytesNeeded
- 1 - lenBytes
- size
;
1123 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1124 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1125 0, NULL
, pbEncoded
, &size
);
1132 *pcbEncoded
= bytesNeeded
;
1136 /* Have to propagate index of failing character */
1143 static int BLOBComp(const void *l
, const void *r
)
1145 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1148 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1149 ret
= a
->cbData
- b
->cbData
;
1153 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1155 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1156 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1157 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1159 const CRYPT_BLOB_ARRAY
*set
= (const CRYPT_BLOB_ARRAY
*)pvStructInfo
;
1160 DWORD bytesNeeded
= 0, lenBytes
, i
;
1163 for (i
= 0; i
< set
->cBlob
; i
++)
1164 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1165 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1166 bytesNeeded
+= 1 + lenBytes
;
1169 *pcbEncoded
= bytesNeeded
;
1172 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1173 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1175 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1176 pbEncoded
= *(BYTE
**)pbEncoded
;
1177 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1178 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1179 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1180 pbEncoded
+= lenBytes
;
1181 for (i
= 0; ret
&& i
< set
->cBlob
; i
++)
1183 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1184 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1190 struct DERSetDescriptor
1196 CryptEncodeObjectExFunc encode
;
1199 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1200 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1201 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1203 const struct DERSetDescriptor
*desc
=
1204 (const struct DERSetDescriptor
*)pvStructInfo
;
1205 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1211 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1216 setOf
.cBlob
= desc
->cItems
;
1217 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1220 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1222 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1223 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1224 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1227 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1228 if (!setOf
.rgBlob
[i
].pbData
)
1231 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1232 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1233 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1234 &setOf
.rgBlob
[i
].cbData
);
1236 /* Some functions propagate their errors through the size */
1238 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1242 DWORD bytesNeeded
= 0, lenBytes
;
1244 for (i
= 0; i
< setOf
.cBlob
; i
++)
1245 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1246 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1247 bytesNeeded
+= 1 + lenBytes
;
1249 *pcbEncoded
= bytesNeeded
;
1250 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1251 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1253 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1254 pbEncoded
= *(BYTE
**)pbEncoded
;
1255 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1257 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1258 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1259 pbEncoded
+= lenBytes
;
1260 for (i
= 0; i
< setOf
.cBlob
; i
++)
1262 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1263 setOf
.rgBlob
[i
].cbData
);
1264 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1268 for (i
= 0; i
< setOf
.cBlob
; i
++)
1269 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1270 CryptMemFree(setOf
.rgBlob
);
1274 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1275 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1279 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1288 setOf
.cBlob
= rdn
->cRDNAttr
;
1289 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1290 sizeof(CRYPT_DER_BLOB
));
1294 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1296 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1298 setOf
.rgBlob
[i
].cbData
= 0;
1299 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1300 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1303 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1304 if (!setOf
.rgBlob
[i
].pbData
)
1307 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1308 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1309 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1313 /* Have to propagate index of failing character */
1314 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1318 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1319 pbEncoded
, pcbEncoded
);
1320 for (i
= 0; i
< setOf
.cBlob
; i
++)
1321 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1325 SetLastError(STATUS_ACCESS_VIOLATION
);
1329 CryptMemFree(setOf
.rgBlob
);
1333 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1334 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1335 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1337 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1338 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1339 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1342 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1345 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1346 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1347 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1349 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1350 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1354 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1355 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1356 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1362 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1363 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1365 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1367 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1369 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1370 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1372 bytesNeeded
+= size
;
1376 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1377 bytesNeeded
+= 1 + lenBytes
;
1381 *pcbEncoded
= bytesNeeded
;
1384 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1385 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1387 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1388 pbEncoded
= *(BYTE
**)pbEncoded
;
1389 *pbEncoded
++ = ASN_SEQUENCEOF
;
1390 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1392 pbEncoded
+= lenBytes
;
1393 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1396 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1397 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1402 bytesNeeded
-= size
;
1413 SetLastError(STATUS_ACCESS_VIOLATION
);
1420 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1421 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1422 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1424 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
1427 /* CTL_V1 is not encoded */
1434 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1435 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1439 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1440 * if they are empty and the OID is not empty (otherwise omits them.)
1442 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1443 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1444 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1447 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
1448 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
1450 struct AsnEncodeSequenceItem items
[2] = {
1451 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1457 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1458 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1461 if (algo
->Parameters
.cbData
)
1462 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1464 items
[cItem
].pvStructInfo
= &nullBlob
;
1465 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1468 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1469 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1473 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1474 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1476 struct AsnEncodeSequenceItem items
[2] = {
1477 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1478 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1482 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1483 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
1493 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1494 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1495 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1498 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1499 const struct CTLEntries
*entries
= (const struct CTLEntries
*)pvStructInfo
;
1502 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1506 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1512 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1513 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1515 *pcbEncoded
= bytesNeeded
;
1518 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1519 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1521 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1522 pbEncoded
= *(BYTE
**)pbEncoded
;
1523 *pbEncoded
++ = ASN_SEQUENCEOF
;
1524 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1525 pbEncoded
+= lenBytes
;
1526 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1528 DWORD size
= dataLen
;
1530 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1541 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1542 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1543 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1549 const CTL_INFO
*info
= (const CTL_INFO
*)pvStructInfo
;
1550 struct AsnEncodeSequenceItem items
[9] = {
1551 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1552 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1554 struct AsnConstructedItem constructed
= { 0 };
1557 if (info
->ListIdentifier
.cbData
)
1559 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1560 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1563 if (info
->SequenceNumber
.cbData
)
1565 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1566 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1569 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1570 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1572 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1574 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1575 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1578 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1579 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1581 if (info
->cCTLEntry
)
1583 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1584 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1587 if (info
->cExtension
)
1589 constructed
.tag
= 0;
1590 constructed
.pvStructInfo
= &info
->cExtension
;
1591 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1592 items
[cItem
].pvStructInfo
= &constructed
;
1593 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1596 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1597 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1601 SetLastError(STATUS_ACCESS_VIOLATION
);
1607 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1608 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1609 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1615 const CRYPT_SMIME_CAPABILITY
*capability
=
1616 (const CRYPT_SMIME_CAPABILITY
*)pvStructInfo
;
1618 if (!capability
->pszObjId
)
1619 SetLastError(E_INVALIDARG
);
1622 struct AsnEncodeSequenceItem items
[] = {
1623 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1624 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1627 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1628 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1634 SetLastError(STATUS_ACCESS_VIOLATION
);
1640 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1641 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1642 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1648 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1649 const CRYPT_SMIME_CAPABILITIES
*capabilities
=
1650 (const CRYPT_SMIME_CAPABILITIES
*)pvStructInfo
;
1653 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1657 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1658 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1664 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1665 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1667 *pcbEncoded
= bytesNeeded
;
1670 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1671 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1673 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1674 pbEncoded
= *(BYTE
**)pbEncoded
;
1675 *pbEncoded
++ = ASN_SEQUENCEOF
;
1676 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1677 pbEncoded
+= lenBytes
;
1678 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1680 DWORD size
= dataLen
;
1682 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1683 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1694 SetLastError(STATUS_ACCESS_VIOLATION
);
1700 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1701 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1702 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1708 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1710 if (!attr
->pszObjId
)
1711 SetLastError(E_INVALIDARG
);
1714 struct AsnEncodeSequenceItem items
[2] = {
1715 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1716 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1719 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1720 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1726 SetLastError(STATUS_ACCESS_VIOLATION
);
1732 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1733 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1734 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1740 const CRYPT_ATTRIBUTES
*attributes
=
1741 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1742 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1743 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1745 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1746 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1750 SetLastError(STATUS_ACCESS_VIOLATION
);
1756 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1757 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1758 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1759 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1762 const CRYPT_CONTENT_INFO
*info
= (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1763 struct AsnEncodeSequenceItem items
[2] = {
1764 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1767 struct AsnConstructedItem constructed
= { 0 };
1770 if (info
->Content
.cbData
)
1772 constructed
.tag
= 0;
1773 constructed
.pvStructInfo
= &info
->Content
;
1774 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1775 items
[cItem
].pvStructInfo
= &constructed
;
1776 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1779 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1780 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1783 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1784 void *pvData
, DWORD
*pcbData
)
1786 struct AsnEncodeSequenceItem items
[] = {
1787 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1788 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1790 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1791 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1794 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1795 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1798 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1799 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1800 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1806 const CRYPT_CONTENT_INFO
*info
=
1807 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1809 if (!info
->pszObjId
)
1810 SetLastError(E_INVALIDARG
);
1812 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1813 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1818 SetLastError(STATUS_ACCESS_VIOLATION
);
1824 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1825 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1829 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1830 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1832 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1834 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1835 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1837 *pcbEncoded
= bytesNeeded
;
1840 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1841 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1845 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1846 pbEncoded
= *(BYTE
**)pbEncoded
;
1848 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1849 pbEncoded
+= lenBytes
;
1850 for (i
= 0; i
< encodedLen
; i
++)
1851 *pbEncoded
++ = (BYTE
)str
[i
];
1857 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara
, LPVOID pv
)
1859 if (pEncodePara
&& pEncodePara
->pfnFree
)
1860 pEncodePara
->pfnFree(pv
);
1865 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1866 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1870 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1871 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1873 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1875 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1876 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1878 *pcbEncoded
= bytesNeeded
;
1881 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1882 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1887 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1888 ptr
= *(BYTE
**)pbEncoded
;
1891 *ptr
++ = ASN_NUMERICSTRING
;
1892 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1894 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1896 if (isdigitW(str
[i
]))
1897 *ptr
++ = (BYTE
)str
[i
];
1901 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1905 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1906 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
1912 static inline int isprintableW(WCHAR wc
)
1914 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1915 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1916 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1919 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1920 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1924 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1925 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1927 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1929 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1930 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1932 *pcbEncoded
= bytesNeeded
;
1935 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1936 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1941 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1942 ptr
= *(BYTE
**)pbEncoded
;
1945 *ptr
++ = ASN_PRINTABLESTRING
;
1946 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1948 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1950 if (isprintableW(str
[i
]))
1951 *ptr
++ = (BYTE
)str
[i
];
1955 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1959 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1960 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
1966 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1967 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1971 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1972 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1974 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1976 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1977 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1979 *pcbEncoded
= bytesNeeded
;
1982 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1983 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1988 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1989 ptr
= *(BYTE
**)pbEncoded
;
1992 *ptr
++ = ASN_IA5STRING
;
1993 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1995 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1998 *ptr
++ = (BYTE
)str
[i
];
2002 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2006 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2007 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2013 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2014 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2018 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2019 DWORD bytesNeeded
, lenBytes
, strLen
;
2021 /* FIXME: doesn't handle composite characters */
2022 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2024 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2025 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2027 *pcbEncoded
= bytesNeeded
;
2030 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2031 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2035 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2036 pbEncoded
= *(BYTE
**)pbEncoded
;
2037 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2038 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2039 pbEncoded
+= lenBytes
;
2040 for (i
= 0; i
< strLen
; i
++)
2044 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2045 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2052 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2053 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2054 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2060 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
2062 switch (value
->dwValueType
)
2064 case CERT_RDN_ANY_TYPE
:
2065 case CERT_RDN_ENCODED_BLOB
:
2066 case CERT_RDN_OCTET_STRING
:
2067 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2069 case CERT_RDN_NUMERIC_STRING
:
2070 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2071 pbEncoded
, pcbEncoded
);
2073 case CERT_RDN_PRINTABLE_STRING
:
2074 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2075 pbEncoded
, pcbEncoded
);
2077 case CERT_RDN_TELETEX_STRING
:
2078 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2079 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2081 case CERT_RDN_VIDEOTEX_STRING
:
2082 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2083 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2085 case CERT_RDN_IA5_STRING
:
2086 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2087 pbEncoded
, pcbEncoded
);
2089 case CERT_RDN_GRAPHIC_STRING
:
2090 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2091 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2093 case CERT_RDN_VISIBLE_STRING
:
2094 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2095 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2097 case CERT_RDN_GENERAL_STRING
:
2098 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2099 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2101 case CERT_RDN_UNIVERSAL_STRING
:
2102 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2103 pbEncoded
, pcbEncoded
);
2105 case CERT_RDN_BMP_STRING
:
2106 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2107 pbEncoded
, pcbEncoded
);
2109 case CERT_RDN_UTF8_STRING
:
2110 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2111 pbEncoded
, pcbEncoded
);
2114 SetLastError(CRYPT_E_ASN1_CHOICE
);
2119 SetLastError(STATUS_ACCESS_VIOLATION
);
2125 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2126 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2127 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2133 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
2134 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2136 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2138 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2140 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2141 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2143 bytesNeeded
+= size
;
2145 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2146 bytesNeeded
+= 1 + lenBytes
;
2150 *pcbEncoded
= bytesNeeded
;
2153 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2154 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2156 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2157 pbEncoded
= *(BYTE
**)pbEncoded
;
2158 *pbEncoded
++ = ASN_SEQUENCEOF
;
2159 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2161 pbEncoded
+= lenBytes
;
2162 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2165 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2166 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
2171 bytesNeeded
-= size
;
2180 SetLastError(STATUS_ACCESS_VIOLATION
);
2187 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2188 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2189 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2191 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2200 else if (*pcbEncoded
< 3)
2203 SetLastError(ERROR_MORE_DATA
);
2209 *pbEncoded
++ = ASN_BOOL
;
2211 *pbEncoded
++ = val
? 0xff : 0;
2214 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2218 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2219 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2220 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2222 const CERT_ALT_NAME_ENTRY
*entry
=
2223 (const CERT_ALT_NAME_ENTRY
*)pvStructInfo
;
2229 switch (entry
->dwAltNameChoice
)
2231 case CERT_ALT_NAME_RFC822_NAME
:
2232 case CERT_ALT_NAME_DNS_NAME
:
2233 case CERT_ALT_NAME_URL
:
2234 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2235 if (entry
->u
.pwszURL
)
2239 /* Not + 1: don't encode the NULL-terminator */
2240 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2241 for (i
= 0; ret
&& i
< dataLen
; i
++)
2243 if (entry
->u
.pwszURL
[i
] > 0x7f)
2245 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2254 case CERT_ALT_NAME_DIRECTORY_NAME
:
2255 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2256 dataLen
= entry
->u
.DirectoryName
.cbData
;
2258 case CERT_ALT_NAME_IP_ADDRESS
:
2259 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2260 dataLen
= entry
->u
.IPAddress
.cbData
;
2262 case CERT_ALT_NAME_REGISTERED_ID
:
2264 struct AsnEncodeTagSwappedItem swapped
=
2265 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2266 CRYPT_AsnEncodeOid
};
2268 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2271 case CERT_ALT_NAME_OTHER_NAME
:
2272 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2275 SetLastError(E_INVALIDARG
);
2280 DWORD bytesNeeded
, lenBytes
;
2282 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2283 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2285 *pcbEncoded
= bytesNeeded
;
2286 else if (*pcbEncoded
< bytesNeeded
)
2288 SetLastError(ERROR_MORE_DATA
);
2289 *pcbEncoded
= bytesNeeded
;
2295 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2296 pbEncoded
+= lenBytes
;
2297 switch (entry
->dwAltNameChoice
)
2299 case CERT_ALT_NAME_RFC822_NAME
:
2300 case CERT_ALT_NAME_DNS_NAME
:
2301 case CERT_ALT_NAME_URL
:
2305 for (i
= 0; i
< dataLen
; i
++)
2306 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2309 case CERT_ALT_NAME_DIRECTORY_NAME
:
2310 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2312 case CERT_ALT_NAME_IP_ADDRESS
:
2313 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2317 *pcbEncoded
= bytesNeeded
;
2320 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2324 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2325 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2326 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2332 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2333 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2338 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2343 for (i
= 0; i
< newBlob
.cbData
; i
++)
2344 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2350 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2351 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2352 CryptMemFree(newBlob
.pbData
);
2356 SetLastError(STATUS_ACCESS_VIOLATION
);
2363 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2364 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2365 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2371 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
2372 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
2373 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2374 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2375 struct AsnConstructedItem constructed
= { 0 };
2376 DWORD cItem
= 0, cSwapped
= 0;
2378 if (info
->KeyId
.cbData
)
2380 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2381 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2382 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2383 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2384 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2388 if (info
->CertIssuer
.cbData
)
2390 constructed
.tag
= 1;
2391 constructed
.pvStructInfo
= &info
->CertIssuer
;
2392 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2393 items
[cItem
].pvStructInfo
= &constructed
;
2394 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2397 if (info
->CertSerialNumber
.cbData
)
2399 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2400 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2401 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2402 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2403 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2407 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2408 pEncodePara
, pbEncoded
, pcbEncoded
);
2412 SetLastError(STATUS_ACCESS_VIOLATION
);
2419 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2420 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2421 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2427 const CERT_ALT_NAME_INFO
*info
=
2428 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2429 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2432 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2433 * can't encode an erroneous entry index if it's bigger than this.
2435 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2439 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2440 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2443 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2445 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2446 * the bad character, now set the index of the bad
2449 *pcbEncoded
= (BYTE
)i
<<
2450 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2455 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2456 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2459 *pcbEncoded
= bytesNeeded
;
2464 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2465 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2467 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2468 pbEncoded
= *(BYTE
**)pbEncoded
;
2469 *pbEncoded
++ = ASN_SEQUENCEOF
;
2470 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2471 pbEncoded
+= lenBytes
;
2472 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2474 DWORD len
= dataLen
;
2476 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2477 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, pbEncoded
, &len
);
2490 SetLastError(STATUS_ACCESS_VIOLATION
);
2497 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2498 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2499 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2505 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2506 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2507 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2508 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2509 DWORD cItem
= 0, cSwapped
= 0;
2511 if (info
->KeyId
.cbData
)
2513 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2514 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2515 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2516 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2517 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2521 if (info
->AuthorityCertIssuer
.cAltEntry
)
2523 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2524 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2525 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2526 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2527 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2531 if (info
->AuthorityCertSerialNumber
.cbData
)
2533 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2534 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2535 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2536 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2537 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2541 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2542 pEncodePara
, pbEncoded
, pcbEncoded
);
2546 SetLastError(STATUS_ACCESS_VIOLATION
);
2553 static BOOL WINAPI
CRYPT_AsnEncodeAccessDescription(
2554 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2556 struct AsnEncodeSequenceItem items
[] = {
2557 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2558 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2561 if (!descr
->pszAccessMethod
)
2563 SetLastError(E_INVALIDARG
);
2566 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
2567 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
2570 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2571 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2572 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2578 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2579 const CERT_AUTHORITY_INFO_ACCESS
*info
=
2580 (const CERT_AUTHORITY_INFO_ACCESS
*)pvStructInfo
;
2583 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2587 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2594 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2595 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2597 *pcbEncoded
= bytesNeeded
;
2600 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2601 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2603 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2604 pbEncoded
= *(BYTE
**)pbEncoded
;
2605 *pbEncoded
++ = ASN_SEQUENCEOF
;
2606 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2607 pbEncoded
+= lenBytes
;
2608 for (i
= 0; i
< info
->cAccDescr
; i
++)
2610 DWORD size
= dataLen
;
2612 ret
= CRYPT_AsnEncodeAccessDescription(
2613 &info
->rgAccDescr
[i
], pbEncoded
, &size
);
2623 SetLastError(STATUS_ACCESS_VIOLATION
);
2630 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2631 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2632 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2638 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2639 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2640 struct AsnEncodeSequenceItem items
[3] = {
2641 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2646 if (info
->fPathLenConstraint
)
2648 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2649 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2652 if (info
->cSubtreesConstraint
)
2654 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2655 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2658 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2659 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2663 SetLastError(STATUS_ACCESS_VIOLATION
);
2670 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2671 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2672 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2678 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2679 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2680 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2685 items
[cItem
].pvStructInfo
= &info
->fCA
;
2686 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2689 if (info
->fPathLenConstraint
)
2691 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2692 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2695 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2696 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2700 SetLastError(STATUS_ACCESS_VIOLATION
);
2707 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2708 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2709 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2715 const BLOBHEADER
*hdr
=
2716 (const BLOBHEADER
*)pvStructInfo
;
2718 if (hdr
->bType
!= PUBLICKEYBLOB
)
2720 SetLastError(E_INVALIDARG
);
2725 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2726 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2727 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2728 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2729 struct AsnEncodeSequenceItem items
[] = {
2730 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2731 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2734 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2735 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2741 SetLastError(STATUS_ACCESS_VIOLATION
);
2748 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2749 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2750 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2756 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2757 DWORD bytesNeeded
, lenBytes
;
2759 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2760 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2762 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2763 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2766 *pcbEncoded
= bytesNeeded
;
2771 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2772 pcbEncoded
, bytesNeeded
)))
2774 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2775 pbEncoded
= *(BYTE
**)pbEncoded
;
2776 *pbEncoded
++ = ASN_OCTETSTRING
;
2777 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2778 pbEncoded
+= lenBytes
;
2780 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2786 SetLastError(STATUS_ACCESS_VIOLATION
);
2790 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2794 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2795 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2796 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2802 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2803 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2806 /* yep, MS allows cUnusedBits to be >= 8 */
2807 if (!blob
->cUnusedBits
)
2809 dataBytes
= blob
->cbData
;
2812 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2814 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2815 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2823 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2824 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2827 *pcbEncoded
= bytesNeeded
;
2832 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2833 pcbEncoded
, bytesNeeded
)))
2835 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2836 pbEncoded
= *(BYTE
**)pbEncoded
;
2837 *pbEncoded
++ = ASN_BITSTRING
;
2838 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2839 pbEncoded
+= lenBytes
;
2840 *pbEncoded
++ = unusedBits
;
2843 BYTE mask
= 0xff << unusedBits
;
2847 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2848 pbEncoded
+= dataBytes
- 1;
2850 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2857 SetLastError(STATUS_ACCESS_VIOLATION
);
2864 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2865 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2866 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2872 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2873 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2878 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2883 for (i
= 0; i
< newBlob
.cbData
; i
++)
2884 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2890 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2891 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2892 CryptMemFree(newBlob
.pbData
);
2896 SetLastError(STATUS_ACCESS_VIOLATION
);
2903 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2904 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2905 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2907 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2909 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2910 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2913 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2914 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2915 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2921 DWORD significantBytes
, lenBytes
, bytesNeeded
;
2924 const CRYPT_INTEGER_BLOB
*blob
=
2925 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2927 significantBytes
= blob
->cbData
;
2928 if (significantBytes
)
2930 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2932 /* negative, lop off leading (little-endian) 0xffs */
2933 for (; significantBytes
> 0 &&
2934 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2936 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2944 /* positive, lop off leading (little-endian) zeroes */
2945 for (; significantBytes
> 0 &&
2946 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2948 if (significantBytes
== 0)
2949 significantBytes
= 1;
2950 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2958 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2960 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2961 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2966 *pcbEncoded
= bytesNeeded
;
2971 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2972 pcbEncoded
, bytesNeeded
)))
2974 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2975 pbEncoded
= *(BYTE
**)pbEncoded
;
2976 *pbEncoded
++ = ASN_INTEGER
;
2979 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2980 pbEncoded
+= lenBytes
;
2981 *pbEncoded
++ = padByte
;
2985 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2986 pbEncoded
+= lenBytes
;
2988 for (; significantBytes
> 0; significantBytes
--)
2989 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2995 SetLastError(STATUS_ACCESS_VIOLATION
);
3002 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3003 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3004 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3010 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3012 const CRYPT_INTEGER_BLOB
*blob
=
3013 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3015 significantBytes
= blob
->cbData
;
3016 if (significantBytes
)
3018 /* positive, lop off leading (little-endian) zeroes */
3019 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3022 if (significantBytes
== 0)
3023 significantBytes
= 1;
3024 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3028 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3030 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3031 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3036 *pcbEncoded
= bytesNeeded
;
3041 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3042 pcbEncoded
, bytesNeeded
)))
3044 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3045 pbEncoded
= *(BYTE
**)pbEncoded
;
3046 *pbEncoded
++ = ASN_INTEGER
;
3049 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3050 pbEncoded
+= lenBytes
;
3055 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3056 pbEncoded
+= lenBytes
;
3058 for (; significantBytes
> 0; significantBytes
--)
3059 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3065 SetLastError(STATUS_ACCESS_VIOLATION
);
3072 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3073 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3074 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3076 CRYPT_INTEGER_BLOB blob
;
3079 /* Encode as an unsigned integer, then change the tag to enumerated */
3080 blob
.cbData
= sizeof(DWORD
);
3081 blob
.pbData
= (BYTE
*)pvStructInfo
;
3082 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3083 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3084 if (ret
&& pbEncoded
)
3086 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3087 pbEncoded
= *(BYTE
**)pbEncoded
;
3088 pbEncoded
[0] = ASN_ENUMERATED
;
3093 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3094 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3095 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3102 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3103 * temporary buffer because the output buffer is not NULL-terminated.
3106 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3110 *pcbEncoded
= bytesNeeded
;
3115 /* Sanity check the year, this is a two-digit year format */
3116 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
3118 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3120 SetLastError(CRYPT_E_BAD_ENCODE
);
3125 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3126 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3128 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3129 pbEncoded
= *(BYTE
**)pbEncoded
;
3130 buf
[0] = ASN_UTCTIME
;
3131 buf
[1] = bytesNeeded
- 2;
3132 snprintf(buf
+ 2, sizeof(buf
) - 2,
3133 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3134 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3135 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3136 sysTime
.wMinute
, sysTime
.wSecond
);
3137 memcpy(pbEncoded
, buf
, bytesNeeded
);
3144 SetLastError(STATUS_ACCESS_VIOLATION
);
3151 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3152 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3153 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3160 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3161 * temporary buffer because the output buffer is not NULL-terminated.
3164 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3168 *pcbEncoded
= bytesNeeded
;
3173 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
3176 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3177 pcbEncoded
, bytesNeeded
);
3180 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3181 pbEncoded
= *(BYTE
**)pbEncoded
;
3182 buf
[0] = ASN_GENERALTIME
;
3183 buf
[1] = bytesNeeded
- 2;
3184 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3185 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3186 sysTime
.wMinute
, sysTime
.wSecond
);
3187 memcpy(pbEncoded
, buf
, bytesNeeded
);
3193 SetLastError(STATUS_ACCESS_VIOLATION
);
3200 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3201 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3202 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3210 /* Check the year, if it's in the UTCTime range call that encode func */
3211 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
3213 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3214 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3215 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3217 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3218 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3223 SetLastError(STATUS_ACCESS_VIOLATION
);
3230 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3231 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3232 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3238 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3239 const CRYPT_SEQUENCE_OF_ANY
*seq
=
3240 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3242 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3243 dataLen
+= seq
->rgValue
[i
].cbData
;
3244 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3245 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3248 *pcbEncoded
= bytesNeeded
;
3253 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3254 pcbEncoded
, bytesNeeded
)))
3256 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3257 pbEncoded
= *(BYTE
**)pbEncoded
;
3258 *pbEncoded
++ = ASN_SEQUENCEOF
;
3259 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3260 pbEncoded
+= lenBytes
;
3261 for (i
= 0; i
< seq
->cValue
; i
++)
3263 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3264 seq
->rgValue
[i
].cbData
);
3265 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3272 SetLastError(STATUS_ACCESS_VIOLATION
);
3279 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3280 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3283 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3284 struct AsnConstructedItem constructed
= { 0 };
3285 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3286 DWORD cItem
= 0, cSwapped
= 0;
3288 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3290 case CRL_DIST_POINT_NO_NAME
:
3293 case CRL_DIST_POINT_FULL_NAME
:
3294 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3295 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3296 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3297 constructed
.tag
= 0;
3298 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3299 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3300 items
[cItem
].pvStructInfo
= &constructed
;
3301 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3305 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3306 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3312 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3314 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3315 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3316 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3317 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3318 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3322 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3324 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3325 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3326 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3327 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3328 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3333 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3334 pbEncoded
, pcbEncoded
);
3338 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3339 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3340 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3346 const CRL_DIST_POINTS_INFO
*info
=
3347 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
3349 if (!info
->cDistPoint
)
3351 SetLastError(E_INVALIDARG
);
3356 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3359 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3363 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3367 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3369 /* Have to propagate index of failing character */
3375 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3376 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3379 *pcbEncoded
= bytesNeeded
;
3384 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3385 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3387 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3388 pbEncoded
= *(BYTE
**)pbEncoded
;
3389 *pbEncoded
++ = ASN_SEQUENCEOF
;
3390 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3391 pbEncoded
+= lenBytes
;
3392 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3394 DWORD len
= dataLen
;
3396 ret
= CRYPT_AsnEncodeDistPoint(
3397 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3411 SetLastError(STATUS_ACCESS_VIOLATION
);
3418 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3419 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3420 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3426 const CERT_ENHKEY_USAGE
*usage
=
3427 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
3428 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3431 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3433 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3434 usage
->rgpszUsageIdentifier
[i
],
3435 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3437 bytesNeeded
+= size
;
3439 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3440 bytesNeeded
+= 1 + lenBytes
;
3444 *pcbEncoded
= bytesNeeded
;
3447 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3448 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3450 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3451 pbEncoded
= *(BYTE
**)pbEncoded
;
3452 *pbEncoded
++ = ASN_SEQUENCEOF
;
3453 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3455 pbEncoded
+= lenBytes
;
3456 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3459 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3460 usage
->rgpszUsageIdentifier
[i
],
3461 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3466 bytesNeeded
-= size
;
3475 SetLastError(STATUS_ACCESS_VIOLATION
);
3482 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3483 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3484 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3490 const CRL_ISSUING_DIST_POINT
*point
=
3491 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3492 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3493 struct AsnConstructedItem constructed
= { 0 };
3494 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3495 DWORD cItem
= 0, cSwapped
= 0;
3498 switch (point
->DistPointName
.dwDistPointNameChoice
)
3500 case CRL_DIST_POINT_NO_NAME
:
3503 case CRL_DIST_POINT_FULL_NAME
:
3504 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3505 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3506 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3507 constructed
.tag
= 0;
3508 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3509 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3510 items
[cItem
].pvStructInfo
= &constructed
;
3511 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3516 SetLastError(E_INVALIDARG
);
3519 if (ret
&& point
->fOnlyContainsUserCerts
)
3521 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3522 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3523 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3524 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3525 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3529 if (ret
&& point
->fOnlyContainsCACerts
)
3531 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3532 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3533 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3534 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3535 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3539 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3541 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3542 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3543 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3544 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3545 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3549 if (ret
&& point
->fIndirectCRL
)
3551 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3552 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3553 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3554 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3555 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3560 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3561 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3565 SetLastError(STATUS_ACCESS_VIOLATION
);
3572 static BOOL WINAPI
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3573 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3574 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3577 const CERT_GENERAL_SUBTREE
*subtree
=
3578 (const CERT_GENERAL_SUBTREE
*)pvStructInfo
;
3579 struct AsnEncodeSequenceItem items
[3] = {
3580 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
3583 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3584 DWORD cItem
= 1, cSwapped
= 0;
3586 if (subtree
->dwMinimum
)
3588 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3589 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
3590 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3591 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3592 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3596 if (subtree
->fMaximum
)
3598 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3599 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
3600 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3601 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3602 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3606 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
3607 pEncodePara
, pbEncoded
, pcbEncoded
);
3611 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
3612 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3613 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3616 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
3618 TRACE("%p\n", pvStructInfo
);
3622 const CERT_NAME_CONSTRAINTS_INFO
*constraints
=
3623 (const CERT_NAME_CONSTRAINTS_INFO
*)pvStructInfo
;
3624 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
3625 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3626 DWORD i
, cItem
= 0, cSwapped
= 0;
3629 if (constraints
->cPermittedSubtree
)
3631 permitted
.rgBlob
= CryptMemAlloc(
3632 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
3633 if (permitted
.rgBlob
)
3635 permitted
.cBlob
= constraints
->cPermittedSubtree
;
3636 memset(permitted
.rgBlob
, 0,
3637 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3638 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
3639 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3640 NULL
, &constraints
->rgPermittedSubtree
[i
],
3641 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3642 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
3643 &permitted
.rgBlob
[i
].cbData
);
3646 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3647 swapped
[cSwapped
].pvStructInfo
= &permitted
;
3648 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3649 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3650 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3658 if (constraints
->cExcludedSubtree
)
3660 excluded
.rgBlob
= CryptMemAlloc(
3661 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
3662 if (excluded
.rgBlob
)
3664 excluded
.cBlob
= constraints
->cExcludedSubtree
;
3665 memset(excluded
.rgBlob
, 0,
3666 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3667 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
3668 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3669 NULL
, &constraints
->rgExcludedSubtree
[i
],
3670 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3671 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
3672 &excluded
.rgBlob
[i
].cbData
);
3675 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3676 swapped
[cSwapped
].pvStructInfo
= &excluded
;
3677 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3678 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3679 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3688 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3689 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3690 for (i
= 0; i
< permitted
.cBlob
; i
++)
3691 LocalFree(permitted
.rgBlob
[i
].pbData
);
3692 for (i
= 0; i
< excluded
.cBlob
; i
++)
3693 LocalFree(excluded
.rgBlob
[i
].pbData
);
3697 SetLastError(STATUS_ACCESS_VIOLATION
);
3700 CryptMemFree(permitted
.rgBlob
);
3701 CryptMemFree(excluded
.rgBlob
);
3702 TRACE("returning %d\n", ret
);
3706 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3707 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3708 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3712 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3713 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3714 struct AsnEncodeSequenceItem items
[] = {
3715 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3716 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3719 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3720 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3725 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3726 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3727 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3731 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3733 SetLastError(E_INVALIDARG
);
3739 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
3741 if (!info
->Issuer
.cbData
)
3742 SetLastError(E_INVALIDARG
);
3745 struct AsnEncodeSequenceItem items
[7] = {
3746 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3747 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3748 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
3751 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3752 DWORD cItem
= 3, cSwapped
= 0;
3754 if (info
->AuthAttrs
.cAttr
)
3756 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3757 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3758 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3759 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3760 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3764 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
3765 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3767 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3768 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3770 if (info
->UnauthAttrs
.cAttr
)
3772 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3773 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
3774 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3775 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3776 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3780 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3781 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3786 SetLastError(STATUS_ACCESS_VIOLATION
);
3792 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
3793 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3794 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3798 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3800 SetLastError(E_INVALIDARG
);
3806 const CMSG_CMS_SIGNER_INFO
*info
= (const CMSG_CMS_SIGNER_INFO
*)pvStructInfo
;
3808 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
3809 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
3810 SetLastError(E_INVALIDARG
);
3811 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
3812 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
3813 SetLastError(E_INVALIDARG
);
3816 struct AsnEncodeSequenceItem items
[7] = {
3817 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3819 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3820 DWORD cItem
= 1, cSwapped
= 0;
3822 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
3824 items
[cItem
].pvStructInfo
=
3825 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
3826 items
[cItem
].encodeFunc
=
3827 CRYPT_AsnEncodeIssuerSerialNumber
;
3832 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3833 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
3834 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3835 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3836 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3840 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
3841 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3843 if (info
->AuthAttrs
.cAttr
)
3845 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3846 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3847 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3848 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3849 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3853 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
3854 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3856 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3857 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3859 if (info
->UnauthAttrs
.cAttr
)
3861 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3862 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
3863 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3864 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3865 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3869 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3870 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3875 SetLastError(STATUS_ACCESS_VIOLATION
);
3881 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
3884 struct AsnEncodeSequenceItem items
[7] = {
3885 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
3887 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
3888 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
3889 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3890 DWORD cItem
= 1, cSwapped
= 0;
3893 if (signedInfo
->cSignerInfo
)
3895 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
3896 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
3897 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
3898 digestAlgorithmsSet
.itemOffset
=
3899 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
3900 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3901 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
3902 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3905 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
3906 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
3908 if (signedInfo
->cCertEncoded
)
3910 certSet
.cItems
= signedInfo
->cCertEncoded
;
3911 certSet
.items
= signedInfo
->rgCertEncoded
;
3912 certSet
.itemSize
= sizeof(CERT_BLOB
);
3913 certSet
.itemOffset
= 0;
3914 certSet
.encode
= CRYPT_CopyEncodedBlob
;
3915 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
3916 swapped
[cSwapped
].pvStructInfo
= &certSet
;
3917 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3918 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3919 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3923 if (signedInfo
->cCrlEncoded
)
3925 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
3926 crlSet
.items
= signedInfo
->rgCrlEncoded
;
3927 crlSet
.itemSize
= sizeof(CRL_BLOB
);
3928 crlSet
.itemOffset
= 0;
3929 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
3930 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
3931 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
3932 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3933 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3934 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3938 if (ret
&& signedInfo
->cSignerInfo
)
3940 signerSet
.cItems
= signedInfo
->cSignerInfo
;
3941 signerSet
.items
= signedInfo
->rgSignerInfo
;
3942 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
3943 signerSet
.itemOffset
= 0;
3944 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
3945 items
[cItem
].pvStructInfo
= &signerSet
;
3946 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3950 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
3951 items
, cItem
, 0, NULL
, pvData
, pcbData
);
3956 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
3957 LPCSTR lpszStructType
)
3959 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3961 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3962 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3964 SetLastError(ERROR_FILE_NOT_FOUND
);
3968 if (!HIWORD(lpszStructType
))
3970 switch (LOWORD(lpszStructType
))
3972 case LOWORD(X509_CERT
):
3973 encodeFunc
= CRYPT_AsnEncodeCert
;
3975 case LOWORD(X509_CERT_TO_BE_SIGNED
):
3976 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
3978 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
3979 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
3981 case LOWORD(X509_EXTENSIONS
):
3982 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3984 case LOWORD(X509_NAME_VALUE
):
3985 encodeFunc
= CRYPT_AsnEncodeNameValue
;
3987 case LOWORD(X509_NAME
):
3988 encodeFunc
= CRYPT_AsnEncodeName
;
3990 case LOWORD(X509_PUBLIC_KEY_INFO
):
3991 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
3993 case LOWORD(X509_AUTHORITY_KEY_ID
):
3994 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3996 case LOWORD(X509_ALTERNATE_NAME
):
3997 encodeFunc
= CRYPT_AsnEncodeAltName
;
3999 case LOWORD(X509_BASIC_CONSTRAINTS
):
4000 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4002 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4003 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4005 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4006 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4008 case LOWORD(X509_UNICODE_NAME
):
4009 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4011 case LOWORD(PKCS_CONTENT_INFO
):
4012 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4014 case LOWORD(PKCS_ATTRIBUTE
):
4015 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4017 case LOWORD(X509_UNICODE_NAME_VALUE
):
4018 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4020 case LOWORD(X509_OCTET_STRING
):
4021 encodeFunc
= CRYPT_AsnEncodeOctets
;
4023 case LOWORD(X509_BITS
):
4024 case LOWORD(X509_KEY_USAGE
):
4025 encodeFunc
= CRYPT_AsnEncodeBits
;
4027 case LOWORD(X509_INTEGER
):
4028 encodeFunc
= CRYPT_AsnEncodeInt
;
4030 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4031 encodeFunc
= CRYPT_AsnEncodeInteger
;
4033 case LOWORD(X509_MULTI_BYTE_UINT
):
4034 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4036 case LOWORD(X509_ENUMERATED
):
4037 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4039 case LOWORD(X509_CHOICE_OF_TIME
):
4040 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4042 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4043 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4045 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4046 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4048 case LOWORD(X509_SEQUENCE_OF_ANY
):
4049 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4051 case LOWORD(PKCS_UTC_TIME
):
4052 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4054 case LOWORD(X509_CRL_DIST_POINTS
):
4055 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4057 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4058 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4060 case LOWORD(PKCS_CTL
):
4061 encodeFunc
= CRYPT_AsnEncodeCTL
;
4063 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4064 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4066 case LOWORD(PKCS_ATTRIBUTES
):
4067 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4069 case LOWORD(X509_ISSUING_DIST_POINT
):
4070 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4072 case LOWORD(X509_NAME_CONSTRAINTS
):
4073 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4075 case LOWORD(PKCS7_SIGNER_INFO
):
4076 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4078 case LOWORD(CMS_SIGNER_INFO
):
4079 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4083 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4084 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4085 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4086 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4087 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4088 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4089 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4090 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4091 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4092 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4093 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4094 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4095 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4096 encodeFunc
= CRYPT_AsnEncodeBits
;
4097 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4098 encodeFunc
= CRYPT_AsnEncodeOctets
;
4099 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4100 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4101 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4102 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4103 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4104 encodeFunc
= CRYPT_AsnEncodeAltName
;
4105 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4106 encodeFunc
= CRYPT_AsnEncodeAltName
;
4107 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4108 encodeFunc
= CRYPT_AsnEncodeAltName
;
4109 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4110 encodeFunc
= CRYPT_AsnEncodeAltName
;
4111 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4112 encodeFunc
= CRYPT_AsnEncodeAltName
;
4113 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4114 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4115 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4116 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4117 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4118 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4119 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4120 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4121 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4122 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4123 else if (!strcmp(lpszStructType
, szOID_CTL
))
4124 encodeFunc
= CRYPT_AsnEncodeCTL
;
4128 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4129 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4131 static HCRYPTOIDFUNCSET set
= NULL
;
4132 CryptEncodeObjectFunc encodeFunc
= NULL
;
4135 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4136 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4137 (void **)&encodeFunc
, hFunc
);
4141 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4142 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4144 static HCRYPTOIDFUNCSET set
= NULL
;
4145 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4148 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4149 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4150 (void **)&encodeFunc
, hFunc
);
4154 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4155 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4158 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4159 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4160 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4162 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4163 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4166 if (!pbEncoded
&& !pcbEncoded
)
4168 SetLastError(ERROR_INVALID_PARAMETER
);
4172 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4175 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4176 debugstr_a(lpszStructType
));
4177 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4178 lpszStructType
, &hFunc
);
4179 if (!pCryptEncodeObject
)
4180 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4181 lpszStructType
, &hFunc
);
4183 if (pCryptEncodeObject
)
4184 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4185 pvStructInfo
, pbEncoded
, pcbEncoded
);
4186 else if (pCryptEncodeObjectEx
)
4187 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4188 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4190 CryptFreeOIDFunctionAddress(hFunc
, 0);
4191 TRACE_(crypt
)("returning %d\n", ret
);
4195 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4196 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4197 void *pvEncoded
, DWORD
*pcbEncoded
)
4200 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4201 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4203 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4204 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4205 pvEncoded
, pcbEncoded
);
4207 if (!pvEncoded
&& !pcbEncoded
)
4209 SetLastError(ERROR_INVALID_PARAMETER
);
4213 SetLastError(NOERROR
);
4214 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
4215 *(BYTE
**)pvEncoded
= NULL
;
4216 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4219 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4220 debugstr_a(lpszStructType
));
4221 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4225 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4226 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4229 CryptEncodeObjectFunc pCryptEncodeObject
=
4230 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4232 if (pCryptEncodeObject
)
4234 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4236 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4237 pvStructInfo
, NULL
, pcbEncoded
);
4238 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4239 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4240 ret
= pCryptEncodeObject(dwCertEncodingType
,
4241 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4245 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4246 pvStructInfo
, pvEncoded
, pcbEncoded
);
4250 CryptFreeOIDFunctionAddress(hFunc
, 0);
4251 TRACE_(crypt
)("returning %d\n", ret
);
4255 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4256 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4258 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4259 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4262 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4263 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4264 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4268 static CHAR oid
[] = szOID_RSA_RSA
;
4270 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4271 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4272 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4274 if (!pszPublicKeyObjId
)
4275 pszPublicKeyObjId
= oid
;
4276 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4280 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4283 LPBYTE pubKey
= CryptMemAlloc(keySize
);
4287 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4291 DWORD encodedLen
= 0;
4293 ret
= CryptEncodeObject(dwCertEncodingType
,
4294 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4297 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4298 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4301 *pcbInfo
= sizeNeeded
;
4302 else if (*pcbInfo
< sizeNeeded
)
4304 SetLastError(ERROR_MORE_DATA
);
4305 *pcbInfo
= sizeNeeded
;
4310 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4311 sizeof(CERT_PUBLIC_KEY_INFO
);
4312 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4314 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4315 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4316 pInfo
->PublicKey
.pbData
=
4317 (BYTE
*)pInfo
->Algorithm
.pszObjId
4318 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4319 pInfo
->PublicKey
.cbData
= encodedLen
;
4320 pInfo
->PublicKey
.cUnusedBits
= 0;
4321 ret
= CryptEncodeObject(dwCertEncodingType
,
4322 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4323 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4327 CryptMemFree(pubKey
);
4332 CryptDestroyKey(key
);
4337 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4338 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4339 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4341 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4342 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4343 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4345 static HCRYPTOIDFUNCSET set
= NULL
;
4347 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4348 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4350 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4351 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4352 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4356 SetLastError(ERROR_INVALID_PARAMETER
);
4360 if (pszPublicKeyObjId
)
4363 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4365 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4366 0, (void **)&exportFunc
, &hFunc
);
4369 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4370 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4371 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4373 CryptFreeOIDFunctionAddress(hFunc
, 0);
4377 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4378 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4380 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4384 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4385 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4386 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4389 DWORD pubKeySize
= 0;
4391 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4392 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4394 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4395 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4398 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4402 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4403 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4408 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4409 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4412 CryptMemFree(pubKey
);
4420 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4421 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4422 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4424 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4425 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4426 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4428 static HCRYPTOIDFUNCSET set
= NULL
;
4430 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4431 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4433 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4434 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4437 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4438 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4439 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4441 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4442 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4445 CryptFreeOIDFunctionAddress(hFunc
, 0);