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
, const CRYPT_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 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA
*pEncodePara
, LPVOID pv
)
132 if (pEncodePara
&& pEncodePara
->pfnFree
)
133 pEncodePara
->pfnFree(pv
);
138 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
140 DWORD bytesNeeded
, significantBytes
= 0;
148 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
149 temp
<<= 8, significantBytes
--)
151 bytesNeeded
= significantBytes
+ 1;
155 *pcbEncoded
= bytesNeeded
;
158 if (*pcbEncoded
< bytesNeeded
)
160 SetLastError(ERROR_MORE_DATA
);
164 *pbEncoded
= (BYTE
)len
;
169 *pbEncoded
++ = significantBytes
| 0x80;
170 for (i
= 0; i
< significantBytes
; i
++)
172 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
176 *pcbEncoded
= bytesNeeded
;
180 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
181 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
182 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
185 DWORD i
, dataLen
= 0;
187 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
188 pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
189 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
191 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
192 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
193 NULL
, &items
[i
].size
);
194 /* Some functions propagate their errors through the size */
196 *pcbEncoded
= items
[i
].size
;
197 dataLen
+= items
[i
].size
;
201 DWORD lenBytes
, bytesNeeded
;
203 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
204 bytesNeeded
= 1 + lenBytes
+ dataLen
;
206 *pcbEncoded
= bytesNeeded
;
209 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
210 pcbEncoded
, bytesNeeded
)))
214 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
215 pbEncoded
= *(BYTE
**)pbEncoded
;
217 *out
++ = ASN_SEQUENCE
;
218 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
220 for (i
= 0; ret
&& i
< cItem
; i
++)
222 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
223 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
224 NULL
, out
, &items
[i
].size
);
225 /* Some functions propagate their errors through the size */
227 *pcbEncoded
= items
[i
].size
;
228 out
+= items
[i
].size
;
230 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
231 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
235 TRACE("returning %d (%08x)\n", ret
, GetLastError());
239 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
240 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
241 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
244 const struct AsnConstructedItem
*item
= pvStructInfo
;
247 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
248 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
250 DWORD dataLen
, bytesNeeded
;
252 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
253 bytesNeeded
= 1 + dataLen
+ len
;
255 *pcbEncoded
= bytesNeeded
;
256 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
257 pbEncoded
, pcbEncoded
, bytesNeeded
)))
261 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
262 pbEncoded
= *(BYTE
**)pbEncoded
;
264 *out
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
265 CRYPT_EncodeLen(len
, out
, &dataLen
);
267 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
268 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
272 /* Some functions propagate their errors through the size */
274 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
275 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
281 /* Some functions propagate their errors through the size */
287 struct AsnEncodeTagSwappedItem
290 const void *pvStructInfo
;
291 CryptEncodeObjectExFunc encodeFunc
;
294 /* Sort of a wacky hack, it encodes something using the struct
295 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
296 * given in the struct AsnEncodeTagSwappedItem.
298 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
299 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
300 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
303 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
305 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
306 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
307 if (ret
&& pbEncoded
)
308 *pbEncoded
= item
->tag
;
312 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
313 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
314 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
316 const DWORD
*ver
= pvStructInfo
;
319 /* CERT_V1 is not encoded */
327 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
329 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
330 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
335 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
336 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
337 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
339 const CRYPT_DER_BLOB
*blob
= pvStructInfo
;
344 *pcbEncoded
= blob
->cbData
;
349 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
350 pcbEncoded
, blob
->cbData
)))
352 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
353 pbEncoded
= *(BYTE
**)pbEncoded
;
355 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
356 *pcbEncoded
= blob
->cbData
;
362 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
363 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
364 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
367 /* This has two filetimes in a row, a NotBefore and a NotAfter */
368 const FILETIME
*timePtr
= pvStructInfo
;
369 struct AsnEncodeSequenceItem items
[] = {
370 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
371 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
374 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
375 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
383 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
384 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
385 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
388 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
389 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
390 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
393 struct AsnEncodeSequenceItem items
[2] = {
394 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
395 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
398 if (algo
->Parameters
.cbData
)
399 items
[1].pvStructInfo
= &algo
->Parameters
;
401 items
[1].pvStructInfo
= &nullBlob
;
402 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
403 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
408 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
409 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
410 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
412 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
414 struct AsnEncodeSequenceItem items
[] = {
415 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
416 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
419 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
420 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
425 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
426 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
427 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
433 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
434 struct AsnEncodeSequenceItem items
[] = {
435 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
436 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
439 TRACE("Encoding public key with OID %s\n",
440 debugstr_a(info
->Algorithm
.pszObjId
));
441 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
442 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
447 SetLastError(STATUS_ACCESS_VIOLATION
);
454 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
455 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
456 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
462 const CERT_SIGNED_CONTENT_INFO
*info
= pvStructInfo
;
463 struct AsnEncodeSequenceItem items
[] = {
464 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
465 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
466 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
469 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
470 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
471 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
472 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
477 SetLastError(STATUS_ACCESS_VIOLATION
);
484 BOOL WINAPI
CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType
,
485 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
486 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
489 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
490 struct AsnEncodeSequenceItem items
[] = {
491 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
492 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
495 TRACE("Encoding public key with OID %s\n",
496 debugstr_a(info
->Algorithm
.pszObjId
));
497 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
498 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
503 /* Like in Windows, this blithely ignores the validity of the passed-in
504 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
505 * decode properly, see CRYPT_AsnDecodeCertInfo.
507 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
508 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
509 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
515 const CERT_INFO
*info
= pvStructInfo
;
516 struct AsnEncodeSequenceItem items
[10] = {
517 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
518 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
519 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
520 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
521 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
522 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
523 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfoNoNull
, 0 },
526 struct AsnConstructedItem constructed
= { 0 };
527 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
528 DWORD cItem
= 7, cSwapped
= 0;
530 if (info
->IssuerUniqueId
.cbData
)
532 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
533 swapped
[cSwapped
].pvStructInfo
= &info
->IssuerUniqueId
;
534 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
535 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
536 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
540 if (info
->SubjectUniqueId
.cbData
)
542 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
543 swapped
[cSwapped
].pvStructInfo
= &info
->SubjectUniqueId
;
544 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
545 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
546 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
550 if (info
->cExtension
)
553 constructed
.pvStructInfo
= &info
->cExtension
;
554 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
555 items
[cItem
].pvStructInfo
= &constructed
;
556 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
560 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
561 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
565 SetLastError(STATUS_ACCESS_VIOLATION
);
572 static BOOL
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
573 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
575 struct AsnEncodeSequenceItem items
[3] = {
576 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
577 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
583 TRACE("%p, %p, %d\n", entry
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
585 if (entry
->cExtension
)
587 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
588 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
592 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
593 pbEncoded
, pcbEncoded
);
595 TRACE("returning %d (%08x)\n", ret
, GetLastError());
599 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
600 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
601 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
603 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
604 const CRL_INFO
*info
= pvStructInfo
;
605 const CRL_ENTRY
*rgCRLEntry
= info
->rgCRLEntry
;
608 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cCRLEntry
; i
++)
612 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
618 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
619 bytesNeeded
= 1 + lenBytes
+ dataLen
;
621 *pcbEncoded
= bytesNeeded
;
624 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
625 pcbEncoded
, bytesNeeded
)))
629 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
630 pbEncoded
= *(BYTE
**)pbEncoded
;
632 *out
++ = ASN_SEQUENCEOF
;
633 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
635 for (i
= 0; i
< info
->cCRLEntry
; i
++)
637 DWORD size
= dataLen
;
639 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], out
, &size
);
643 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
644 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
651 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
652 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
653 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
655 const DWORD
*ver
= pvStructInfo
;
658 /* CRL_V1 is not encoded */
665 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
666 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
670 /* Like in Windows, this blithely ignores the validity of the passed-in
671 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
672 * decode properly, see CRYPT_AsnDecodeCRLInfo.
674 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
675 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
676 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
682 const CRL_INFO
*info
= pvStructInfo
;
683 struct AsnEncodeSequenceItem items
[7] = {
684 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
685 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
686 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
687 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
690 struct AsnConstructedItem constructed
[1] = { { 0 } };
691 DWORD cItem
= 4, cConstructed
= 0;
693 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
695 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
696 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
701 items
[cItem
].pvStructInfo
= info
;
702 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
705 if (info
->cExtension
)
707 constructed
[cConstructed
].tag
= 0;
708 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
709 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
710 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
711 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
716 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
717 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
721 SetLastError(STATUS_ACCESS_VIOLATION
);
728 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
732 struct AsnEncodeSequenceItem items
[3] = {
733 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
739 TRACE("%p, %p, %d\n", ext
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
743 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
744 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
747 items
[cItem
].pvStructInfo
= &ext
->Value
;
748 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
751 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
752 pbEncoded
, pcbEncoded
);
753 TRACE("returning %d (%08x)\n", ret
, GetLastError());
757 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
758 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
759 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
765 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
766 const CERT_EXTENSIONS
*exts
= pvStructInfo
;
769 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
773 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
779 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
780 bytesNeeded
= 1 + lenBytes
+ dataLen
;
782 *pcbEncoded
= bytesNeeded
;
785 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
786 pbEncoded
, pcbEncoded
, bytesNeeded
)))
790 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
791 pbEncoded
= *(BYTE
**)pbEncoded
;
793 *out
++ = ASN_SEQUENCEOF
;
794 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
796 for (i
= 0; i
< exts
->cExtension
; i
++)
798 DWORD size
= dataLen
;
800 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
805 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
806 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
813 SetLastError(STATUS_ACCESS_VIOLATION
);
820 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
821 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
822 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
824 LPCSTR pszObjId
= pvStructInfo
;
825 DWORD bytesNeeded
= 0, lenBytes
;
830 TRACE("%s\n", debugstr_a(pszObjId
));
837 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
839 SetLastError(CRYPT_E_ASN1_ERROR
);
843 firstByte
= val1
* 40 + val2
;
844 ptr
= pszObjId
+ firstPos
;
854 /* note I assume each component is at most 32-bits long in base 2 */
855 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
857 if (val1
>= 0x10000000)
859 else if (val1
>= 0x200000)
861 else if (val1
>= 0x4000)
863 else if (val1
>= 0x80)
873 SetLastError(CRYPT_E_ASN1_ERROR
);
877 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
881 bytesNeeded
+= 1 + lenBytes
;
884 if (*pcbEncoded
< bytesNeeded
)
886 SetLastError(ERROR_MORE_DATA
);
891 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
892 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
893 pbEncoded
+= lenBytes
;
899 *pbEncoded
++ = firstByte
;
900 ptr
= pszObjId
+ firstPos
;
903 sscanf(ptr
, "%d%n", &val
, &pos
);
905 unsigned char outBytes
[5];
908 if (val
>= 0x10000000)
910 else if (val
>= 0x200000)
912 else if (val
>= 0x4000)
914 else if (val
>= 0x80)
918 for (i
= numBytes
; i
> 0; i
--)
920 outBytes
[i
- 1] = val
& 0x7f;
923 for (i
= 0; i
< numBytes
- 1; i
++)
924 *pbEncoded
++ = outBytes
[i
] | 0x80;
925 *pbEncoded
++ = outBytes
[i
];
934 *pcbEncoded
= bytesNeeded
;
938 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
939 BYTE tag
, DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
943 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
944 DWORD bytesNeeded
, lenBytes
, encodedLen
;
946 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
947 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
948 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
950 *pcbEncoded
= bytesNeeded
;
953 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
954 pbEncoded
, pcbEncoded
, bytesNeeded
)))
956 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
957 pbEncoded
= *(BYTE
**)pbEncoded
;
959 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
960 pbEncoded
+= lenBytes
;
961 memcpy(pbEncoded
, str
, encodedLen
);
967 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
968 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
972 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
973 DWORD bytesNeeded
, lenBytes
, strLen
;
975 if (value
->Value
.cbData
)
976 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
977 else if (value
->Value
.pbData
)
978 strLen
= lstrlenW(str
);
981 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
982 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
984 *pcbEncoded
= bytesNeeded
;
987 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
988 pbEncoded
, pcbEncoded
, bytesNeeded
)))
992 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
993 pbEncoded
= *(BYTE
**)pbEncoded
;
994 *pbEncoded
++ = ASN_BMPSTRING
;
995 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
996 pbEncoded
+= lenBytes
;
997 for (i
= 0; i
< strLen
; i
++)
999 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
1000 *pbEncoded
++ = str
[i
] & 0x00ff;
1007 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
1008 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
1012 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1013 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
1015 if (value
->Value
.cbData
)
1016 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
1018 strLen
= strlenW(str
);
1021 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
1023 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1024 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1026 *pcbEncoded
= bytesNeeded
;
1029 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1030 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1032 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1033 pbEncoded
= *(BYTE
**)pbEncoded
;
1034 *pbEncoded
++ = ASN_UTF8STRING
;
1035 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1036 pbEncoded
+= lenBytes
;
1037 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
1038 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
1044 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1045 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1046 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1052 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1054 switch (value
->dwValueType
)
1056 case CERT_RDN_ANY_TYPE
:
1057 /* explicitly disallowed */
1058 SetLastError(E_INVALIDARG
);
1061 case CERT_RDN_ENCODED_BLOB
:
1062 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1063 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1065 case CERT_RDN_OCTET_STRING
:
1066 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1067 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1069 case CERT_RDN_NUMERIC_STRING
:
1070 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1071 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1073 case CERT_RDN_PRINTABLE_STRING
:
1074 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1075 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1077 case CERT_RDN_TELETEX_STRING
:
1078 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1079 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1081 case CERT_RDN_VIDEOTEX_STRING
:
1082 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1083 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1085 case CERT_RDN_IA5_STRING
:
1086 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1087 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1089 case CERT_RDN_GRAPHIC_STRING
:
1090 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1091 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1093 case CERT_RDN_VISIBLE_STRING
:
1094 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1095 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1097 case CERT_RDN_GENERAL_STRING
:
1098 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1099 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1101 case CERT_RDN_UNIVERSAL_STRING
:
1102 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1103 SetLastError(CRYPT_E_ASN1_CHOICE
);
1106 case CERT_RDN_BMP_STRING
:
1107 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1108 pbEncoded
, pcbEncoded
);
1110 case CERT_RDN_UTF8_STRING
:
1111 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1112 pbEncoded
, pcbEncoded
);
1115 SetLastError(CRYPT_E_ASN1_CHOICE
);
1121 SetLastError(STATUS_ACCESS_VIOLATION
);
1128 static BOOL
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1129 const CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1130 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1132 DWORD bytesNeeded
= 0, lenBytes
, size
;
1135 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1136 0, NULL
, NULL
, &size
);
1139 bytesNeeded
+= size
;
1140 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1141 * with dwValueType, so "cast" it to get its encoded size
1143 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
, &attr
->dwValueType
,
1144 0, NULL
, NULL
, &size
);
1147 bytesNeeded
+= size
;
1148 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1149 bytesNeeded
+= 1 + lenBytes
;
1152 if (*pcbEncoded
< bytesNeeded
)
1154 SetLastError(ERROR_MORE_DATA
);
1159 *pbEncoded
++ = ASN_SEQUENCE
;
1160 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1162 pbEncoded
+= lenBytes
;
1163 size
= bytesNeeded
- 1 - lenBytes
;
1164 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1165 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1169 size
= bytesNeeded
- 1 - lenBytes
- size
;
1170 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1171 &attr
->dwValueType
, 0, NULL
, pbEncoded
, &size
);
1178 *pcbEncoded
= bytesNeeded
;
1182 /* Have to propagate index of failing character */
1189 static int BLOBComp(const void *l
, const void *r
)
1191 const CRYPT_DER_BLOB
*a
= l
, *b
= r
;
1194 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1195 ret
= a
->cbData
- b
->cbData
;
1199 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1201 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1202 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1203 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1205 const CRYPT_BLOB_ARRAY
*set
= pvStructInfo
;
1206 DWORD bytesNeeded
= 0, lenBytes
, i
;
1209 for (i
= 0; i
< set
->cBlob
; i
++)
1210 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1211 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1212 bytesNeeded
+= 1 + lenBytes
;
1215 *pcbEncoded
= bytesNeeded
;
1218 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1219 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1221 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1222 pbEncoded
= *(BYTE
**)pbEncoded
;
1223 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1224 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1225 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1226 pbEncoded
+= lenBytes
;
1227 for (i
= 0; i
< set
->cBlob
; i
++)
1229 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1230 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1236 struct DERSetDescriptor
1242 CryptEncodeObjectExFunc encode
;
1245 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1246 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1247 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1249 const struct DERSetDescriptor
*desc
= pvStructInfo
;
1250 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1256 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1261 setOf
.cBlob
= desc
->cItems
;
1262 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1265 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1267 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1268 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1269 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1272 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1273 if (!setOf
.rgBlob
[i
].pbData
)
1276 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1277 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1278 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1279 &setOf
.rgBlob
[i
].cbData
);
1281 /* Some functions propagate their errors through the size */
1283 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1287 DWORD bytesNeeded
= 0, lenBytes
;
1289 for (i
= 0; i
< setOf
.cBlob
; i
++)
1290 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1291 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1292 bytesNeeded
+= 1 + lenBytes
;
1294 *pcbEncoded
= bytesNeeded
;
1295 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1296 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1298 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1299 pbEncoded
= *(BYTE
**)pbEncoded
;
1300 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1302 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1303 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1304 pbEncoded
+= lenBytes
;
1305 for (i
= 0; i
< setOf
.cBlob
; i
++)
1307 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1308 setOf
.rgBlob
[i
].cbData
);
1309 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1313 for (i
= 0; i
< setOf
.cBlob
; i
++)
1314 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1315 CryptMemFree(setOf
.rgBlob
);
1319 static BOOL
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, const CERT_RDN
*rdn
,
1320 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1324 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1333 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1334 sizeof(CRYPT_DER_BLOB
));
1339 setOf
.cBlob
= rdn
->cRDNAttr
;
1340 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1343 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1345 setOf
.rgBlob
[i
].cbData
= 0;
1346 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1347 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1350 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1351 if (!setOf
.rgBlob
[i
].pbData
)
1354 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1355 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1356 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1360 /* Have to propagate index of failing character */
1361 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1365 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1366 pbEncoded
, pcbEncoded
);
1367 for (i
= 0; i
< setOf
.cBlob
; i
++)
1368 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1372 SetLastError(STATUS_ACCESS_VIOLATION
);
1376 CryptMemFree(setOf
.rgBlob
);
1380 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1381 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1382 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1384 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1385 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1386 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1389 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1392 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1393 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1394 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1396 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1397 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1401 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1402 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1403 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1409 const CERT_NAME_INFO
*info
= pvStructInfo
;
1410 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1412 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1414 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1416 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1417 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1419 bytesNeeded
+= size
;
1423 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1424 bytesNeeded
+= 1 + lenBytes
;
1428 *pcbEncoded
= bytesNeeded
;
1431 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1432 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1436 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1437 pbEncoded
= *(BYTE
**)pbEncoded
;
1439 *out
++ = ASN_SEQUENCEOF
;
1440 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
1442 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1445 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1446 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1451 bytesNeeded
-= size
;
1456 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1457 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1464 SetLastError(STATUS_ACCESS_VIOLATION
);
1471 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1472 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1473 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1475 const DWORD
*ver
= pvStructInfo
;
1478 /* CTL_V1 is not encoded */
1485 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1486 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1490 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1491 * if they are empty and the OID is not empty (otherwise omits them.)
1493 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1494 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1495 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1498 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
1500 struct AsnEncodeSequenceItem items
[2] = {
1501 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1507 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1508 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1511 if (algo
->Parameters
.cbData
)
1512 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1514 items
[cItem
].pvStructInfo
= &nullBlob
;
1515 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1518 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1519 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1523 static BOOL
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1524 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1526 struct AsnEncodeSequenceItem items
[2] = {
1527 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1528 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1532 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1533 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
1543 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1544 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1545 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1548 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1549 const struct CTLEntries
*entries
= pvStructInfo
;
1552 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1556 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1562 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1563 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1565 *pcbEncoded
= bytesNeeded
;
1568 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1569 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1573 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1574 pbEncoded
= *(BYTE
**)pbEncoded
;
1576 *out
++ = ASN_SEQUENCEOF
;
1577 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1579 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1581 DWORD size
= dataLen
;
1583 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1588 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1589 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1596 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1597 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1598 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1604 const CTL_INFO
*info
= pvStructInfo
;
1605 struct AsnEncodeSequenceItem items
[9] = {
1606 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1607 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1609 struct AsnConstructedItem constructed
= { 0 };
1612 if (info
->ListIdentifier
.cbData
)
1614 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1615 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1618 if (info
->SequenceNumber
.cbData
)
1620 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1621 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1624 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1625 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1627 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1629 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1630 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1633 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1634 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1636 if (info
->cCTLEntry
)
1638 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1639 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1642 if (info
->cExtension
)
1644 constructed
.tag
= 0;
1645 constructed
.pvStructInfo
= &info
->cExtension
;
1646 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1647 items
[cItem
].pvStructInfo
= &constructed
;
1648 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1651 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1652 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1656 SetLastError(STATUS_ACCESS_VIOLATION
);
1662 static BOOL
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1663 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1664 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1670 const CRYPT_SMIME_CAPABILITY
*capability
= pvStructInfo
;
1672 if (!capability
->pszObjId
)
1673 SetLastError(E_INVALIDARG
);
1676 struct AsnEncodeSequenceItem items
[] = {
1677 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1678 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1681 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1682 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1688 SetLastError(STATUS_ACCESS_VIOLATION
);
1694 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1695 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1696 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1702 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1703 const CRYPT_SMIME_CAPABILITIES
*capabilities
= pvStructInfo
;
1706 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1710 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1711 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1717 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1718 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1720 *pcbEncoded
= bytesNeeded
;
1723 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1724 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1728 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1729 pbEncoded
= *(BYTE
**)pbEncoded
;
1731 *out
++ = ASN_SEQUENCEOF
;
1732 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1734 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1736 DWORD size
= dataLen
;
1738 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1739 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1744 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1745 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1752 SetLastError(STATUS_ACCESS_VIOLATION
);
1758 static BOOL WINAPI
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType
,
1759 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1760 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1762 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1763 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1766 for (i
= 0, dataLen
= 0; ret
&& i
< noticeRef
->cNoticeNumbers
; i
++)
1770 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1771 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, NULL
, &size
);
1777 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1778 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1780 *pcbEncoded
= bytesNeeded
;
1783 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1784 pcbEncoded
, bytesNeeded
)))
1788 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1789 pbEncoded
= *(BYTE
**)pbEncoded
;
1791 *out
++ = ASN_SEQUENCE
;
1792 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1794 for (i
= 0; i
< noticeRef
->cNoticeNumbers
; i
++)
1796 DWORD size
= dataLen
;
1798 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1799 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, out
, &size
);
1803 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1804 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1811 static BOOL WINAPI
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType
,
1812 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1813 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1815 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1817 CERT_NAME_VALUE orgValue
= { CERT_RDN_IA5_STRING
,
1818 { 0, (LPBYTE
)noticeRef
->pszOrganization
} };
1819 struct AsnEncodeSequenceItem items
[] = {
1820 { &orgValue
, CRYPT_AsnEncodeNameValue
, 0 },
1821 { noticeRef
, CRYPT_AsnEncodeNoticeNumbers
, 0 },
1824 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1825 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1830 static BOOL WINAPI
CRYPT_AsnEncodePolicyQualifierUserNotice(
1831 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1832 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1839 const CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
= pvStructInfo
;
1840 struct AsnEncodeSequenceItem items
[2];
1841 CERT_NAME_VALUE displayTextValue
;
1844 if (notice
->pNoticeReference
)
1846 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNoticeReference
;
1847 items
[cItem
].pvStructInfo
= notice
->pNoticeReference
;
1850 if (notice
->pszDisplayText
)
1852 displayTextValue
.dwValueType
= CERT_RDN_BMP_STRING
;
1853 displayTextValue
.Value
.cbData
= 0;
1854 displayTextValue
.Value
.pbData
= (LPBYTE
)notice
->pszDisplayText
;
1855 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNameValue
;
1856 items
[cItem
].pvStructInfo
= &displayTextValue
;
1859 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1860 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1864 SetLastError(STATUS_ACCESS_VIOLATION
);
1870 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1871 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1872 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1878 const CRYPT_ATTRIBUTE
*attr
= pvStructInfo
;
1880 if (!attr
->pszObjId
)
1881 SetLastError(E_INVALIDARG
);
1884 struct AsnEncodeSequenceItem items
[2] = {
1885 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1886 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1889 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1890 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1896 SetLastError(STATUS_ACCESS_VIOLATION
);
1902 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1903 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1904 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1910 const CRYPT_ATTRIBUTES
*attributes
= pvStructInfo
;
1911 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1912 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1914 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1915 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1919 SetLastError(STATUS_ACCESS_VIOLATION
);
1925 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1926 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1927 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1928 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1931 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1932 struct AsnEncodeSequenceItem items
[2] = {
1933 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1936 struct AsnConstructedItem constructed
= { 0 };
1939 if (info
->Content
.cbData
)
1941 constructed
.tag
= 0;
1942 constructed
.pvStructInfo
= &info
->Content
;
1943 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1944 items
[cItem
].pvStructInfo
= &constructed
;
1945 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1948 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1949 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1952 BOOL
CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA
*digestedData
,
1953 void *pvData
, DWORD
*pcbData
)
1955 struct AsnEncodeSequenceItem items
[] = {
1956 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1957 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1959 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1960 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1963 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1964 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1967 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1968 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1969 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1975 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1977 if (!info
->pszObjId
)
1978 SetLastError(E_INVALIDARG
);
1980 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1981 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1986 SetLastError(STATUS_ACCESS_VIOLATION
);
1992 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1993 BYTE tag
, DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
1997 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1998 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2000 if (value
->Value
.cbData
)
2001 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2003 encodedLen
= strlenW(str
);
2006 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2007 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2009 *pcbEncoded
= bytesNeeded
;
2012 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2013 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2017 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2018 pbEncoded
= *(BYTE
**)pbEncoded
;
2020 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
2021 pbEncoded
+= lenBytes
;
2022 for (i
= 0; i
< encodedLen
; i
++)
2023 *pbEncoded
++ = (BYTE
)str
[i
];
2029 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
2030 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2034 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2035 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2037 if (value
->Value
.cbData
)
2038 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2040 encodedLen
= strlenW(str
);
2043 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2044 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2046 *pcbEncoded
= bytesNeeded
;
2049 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2050 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2055 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2056 ptr
= *(BYTE
**)pbEncoded
;
2059 *ptr
++ = ASN_NUMERICSTRING
;
2060 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2062 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2064 if (isdigitW(str
[i
]))
2065 *ptr
++ = (BYTE
)str
[i
];
2069 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2073 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2074 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2080 static inline int isprintableW(WCHAR wc
)
2082 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
2083 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
2084 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
2087 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2088 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2092 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2093 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2095 if (value
->Value
.cbData
)
2096 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2098 encodedLen
= strlenW(str
);
2101 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2102 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2104 *pcbEncoded
= bytesNeeded
;
2107 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2108 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2113 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2114 ptr
= *(BYTE
**)pbEncoded
;
2117 *ptr
++ = ASN_PRINTABLESTRING
;
2118 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2120 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2122 if (isprintableW(str
[i
]))
2123 *ptr
++ = (BYTE
)str
[i
];
2127 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2131 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2132 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2138 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2139 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2143 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2144 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2146 if (value
->Value
.cbData
)
2147 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2149 encodedLen
= strlenW(str
);
2152 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2153 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2155 *pcbEncoded
= bytesNeeded
;
2158 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2159 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2164 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2165 ptr
= *(BYTE
**)pbEncoded
;
2168 *ptr
++ = ASN_IA5STRING
;
2169 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2171 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2174 *ptr
++ = (BYTE
)str
[i
];
2178 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2182 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2183 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2189 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2190 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2194 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2195 DWORD bytesNeeded
, lenBytes
, strLen
;
2197 /* FIXME: doesn't handle composite characters */
2198 if (value
->Value
.cbData
)
2199 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2201 strLen
= strlenW(str
);
2204 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2205 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2207 *pcbEncoded
= bytesNeeded
;
2210 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2211 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2215 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2216 pbEncoded
= *(BYTE
**)pbEncoded
;
2217 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2218 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2219 pbEncoded
+= lenBytes
;
2220 for (i
= 0; i
< strLen
; i
++)
2224 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2225 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2232 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2233 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2234 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2240 const CERT_NAME_VALUE
*value
= pvStructInfo
;
2242 switch (value
->dwValueType
)
2244 case CERT_RDN_ANY_TYPE
:
2245 case CERT_RDN_ENCODED_BLOB
:
2246 case CERT_RDN_OCTET_STRING
:
2247 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2249 case CERT_RDN_NUMERIC_STRING
:
2250 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2251 pbEncoded
, pcbEncoded
);
2253 case CERT_RDN_PRINTABLE_STRING
:
2254 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2255 pbEncoded
, pcbEncoded
);
2257 case CERT_RDN_TELETEX_STRING
:
2258 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2259 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2261 case CERT_RDN_VIDEOTEX_STRING
:
2262 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2263 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2265 case CERT_RDN_IA5_STRING
:
2266 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2267 pbEncoded
, pcbEncoded
);
2269 case CERT_RDN_GRAPHIC_STRING
:
2270 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2271 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2273 case CERT_RDN_VISIBLE_STRING
:
2274 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2275 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2277 case CERT_RDN_GENERAL_STRING
:
2278 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2279 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2281 case CERT_RDN_UNIVERSAL_STRING
:
2282 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2283 pbEncoded
, pcbEncoded
);
2285 case CERT_RDN_BMP_STRING
:
2286 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2287 pbEncoded
, pcbEncoded
);
2289 case CERT_RDN_UTF8_STRING
:
2290 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2291 pbEncoded
, pcbEncoded
);
2294 SetLastError(CRYPT_E_ASN1_CHOICE
);
2299 SetLastError(STATUS_ACCESS_VIOLATION
);
2305 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2306 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2307 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2313 const CERT_NAME_INFO
*info
= pvStructInfo
;
2314 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2316 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2318 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2320 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2321 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2323 bytesNeeded
+= size
;
2325 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2326 bytesNeeded
+= 1 + lenBytes
;
2330 *pcbEncoded
= bytesNeeded
;
2333 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2334 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2338 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2339 pbEncoded
= *(BYTE
**)pbEncoded
;
2341 *out
++ = ASN_SEQUENCEOF
;
2342 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2344 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2347 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2348 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, out
, &size
);
2352 bytesNeeded
-= size
;
2355 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2356 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2363 SetLastError(STATUS_ACCESS_VIOLATION
);
2370 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2371 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2372 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2374 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2383 else if (*pcbEncoded
< 3)
2386 SetLastError(ERROR_MORE_DATA
);
2392 *pbEncoded
++ = ASN_BOOL
;
2394 *pbEncoded
++ = val
? 0xff : 0;
2397 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2401 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2402 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2403 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2405 const CERT_ALT_NAME_ENTRY
*entry
= pvStructInfo
;
2411 switch (entry
->dwAltNameChoice
)
2413 case CERT_ALT_NAME_RFC822_NAME
:
2414 case CERT_ALT_NAME_DNS_NAME
:
2415 case CERT_ALT_NAME_URL
:
2416 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2417 if (entry
->u
.pwszURL
)
2421 /* Not + 1: don't encode the NULL-terminator */
2422 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2423 for (i
= 0; ret
&& i
< dataLen
; i
++)
2425 if (entry
->u
.pwszURL
[i
] > 0x7f)
2427 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2436 case CERT_ALT_NAME_DIRECTORY_NAME
:
2437 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2438 dataLen
= entry
->u
.DirectoryName
.cbData
;
2440 case CERT_ALT_NAME_IP_ADDRESS
:
2441 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2442 dataLen
= entry
->u
.IPAddress
.cbData
;
2444 case CERT_ALT_NAME_REGISTERED_ID
:
2446 struct AsnEncodeTagSwappedItem swapped
=
2447 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2448 CRYPT_AsnEncodeOid
};
2450 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2453 case CERT_ALT_NAME_OTHER_NAME
:
2454 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2457 SetLastError(E_INVALIDARG
);
2462 DWORD bytesNeeded
, lenBytes
;
2464 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2465 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2467 *pcbEncoded
= bytesNeeded
;
2468 else if (*pcbEncoded
< bytesNeeded
)
2470 SetLastError(ERROR_MORE_DATA
);
2471 *pcbEncoded
= bytesNeeded
;
2477 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2478 pbEncoded
+= lenBytes
;
2479 switch (entry
->dwAltNameChoice
)
2481 case CERT_ALT_NAME_RFC822_NAME
:
2482 case CERT_ALT_NAME_DNS_NAME
:
2483 case CERT_ALT_NAME_URL
:
2487 for (i
= 0; i
< dataLen
; i
++)
2488 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2491 case CERT_ALT_NAME_DIRECTORY_NAME
:
2492 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2494 case CERT_ALT_NAME_IP_ADDRESS
:
2495 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2499 *pcbEncoded
= bytesNeeded
;
2502 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2506 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2507 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2508 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2514 const CERT_AUTHORITY_KEY_ID_INFO
*info
= pvStructInfo
;
2515 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2516 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2517 struct AsnConstructedItem constructed
= { 0 };
2518 DWORD cItem
= 0, cSwapped
= 0;
2520 if (info
->KeyId
.cbData
)
2522 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2523 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2524 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2525 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2526 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2530 if (info
->CertIssuer
.cbData
)
2532 constructed
.tag
= 1;
2533 constructed
.pvStructInfo
= &info
->CertIssuer
;
2534 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2535 items
[cItem
].pvStructInfo
= &constructed
;
2536 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2539 if (info
->CertSerialNumber
.cbData
)
2541 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2542 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2543 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2544 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2545 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2549 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2550 pEncodePara
, pbEncoded
, pcbEncoded
);
2554 SetLastError(STATUS_ACCESS_VIOLATION
);
2561 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2562 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2563 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2569 const CERT_ALT_NAME_INFO
*info
= pvStructInfo
;
2570 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2573 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2574 * can't encode an erroneous entry index if it's bigger than this.
2576 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2580 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2581 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2584 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2586 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2587 * the bad character, now set the index of the bad
2590 *pcbEncoded
= (BYTE
)i
<<
2591 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2596 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2597 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2600 *pcbEncoded
= bytesNeeded
;
2605 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2606 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2610 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2611 pbEncoded
= *(BYTE
**)pbEncoded
;
2613 *out
++ = ASN_SEQUENCEOF
;
2614 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2616 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2618 DWORD len
= dataLen
;
2620 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2621 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, out
, &len
);
2628 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2629 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2636 SetLastError(STATUS_ACCESS_VIOLATION
);
2643 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2644 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2645 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2651 const CERT_AUTHORITY_KEY_ID2_INFO
*info
= pvStructInfo
;
2652 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2653 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2654 DWORD cItem
= 0, cSwapped
= 0;
2656 if (info
->KeyId
.cbData
)
2658 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2659 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2660 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2661 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2662 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2666 if (info
->AuthorityCertIssuer
.cAltEntry
)
2668 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2669 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2670 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2671 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2672 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2676 if (info
->AuthorityCertSerialNumber
.cbData
)
2678 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2679 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2680 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2681 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2682 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2686 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2687 pEncodePara
, pbEncoded
, pcbEncoded
);
2691 SetLastError(STATUS_ACCESS_VIOLATION
);
2698 static BOOL
CRYPT_AsnEncodeAccessDescription(
2699 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2701 struct AsnEncodeSequenceItem items
[] = {
2702 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2703 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2706 if (!descr
->pszAccessMethod
)
2708 SetLastError(E_INVALIDARG
);
2711 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
2712 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
2715 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2716 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2717 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2723 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2724 const CERT_AUTHORITY_INFO_ACCESS
*info
= pvStructInfo
;
2727 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2731 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2738 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2739 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2741 *pcbEncoded
= bytesNeeded
;
2744 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2745 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2749 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2750 pbEncoded
= *(BYTE
**)pbEncoded
;
2752 *out
++ = ASN_SEQUENCEOF
;
2753 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2755 for (i
= 0; i
< info
->cAccDescr
; i
++)
2757 DWORD size
= dataLen
;
2759 ret
= CRYPT_AsnEncodeAccessDescription(
2760 &info
->rgAccDescr
[i
], out
, &size
);
2764 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2765 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2772 SetLastError(STATUS_ACCESS_VIOLATION
);
2779 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2780 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2781 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2787 const CERT_BASIC_CONSTRAINTS_INFO
*info
= pvStructInfo
;
2788 struct AsnEncodeSequenceItem items
[3] = {
2789 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2794 if (info
->fPathLenConstraint
)
2796 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2797 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2800 if (info
->cSubtreesConstraint
)
2802 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2803 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2806 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2807 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2811 SetLastError(STATUS_ACCESS_VIOLATION
);
2818 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2819 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2820 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2826 const CERT_BASIC_CONSTRAINTS2_INFO
*info
= pvStructInfo
;
2827 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2832 items
[cItem
].pvStructInfo
= &info
->fCA
;
2833 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2836 if (info
->fPathLenConstraint
)
2838 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2839 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2842 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2843 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2847 SetLastError(STATUS_ACCESS_VIOLATION
);
2854 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2855 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2856 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2858 const CERT_POLICY_INFO
*info
= pvStructInfo
;
2861 if (!info
->cPolicyQualifier
)
2868 struct AsnEncodeSequenceItem items
[2] = {
2869 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2870 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2872 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2875 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2877 items
[0].pvStructInfo
=
2878 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2879 items
[1].pvStructInfo
= &info
->rgPolicyQualifier
[i
].Qualifier
;
2880 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2881 sizeof(items
) / sizeof(items
[0]),
2882 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2884 bytesNeeded
+= size
;
2886 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2887 bytesNeeded
+= 1 + lenBytes
;
2891 *pcbEncoded
= bytesNeeded
;
2894 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2895 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2899 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2900 pbEncoded
= *(BYTE
**)pbEncoded
;
2902 *out
++ = ASN_SEQUENCEOF
;
2903 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2905 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2907 items
[0].pvStructInfo
=
2908 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2909 items
[1].pvStructInfo
=
2910 &info
->rgPolicyQualifier
[i
].Qualifier
;
2912 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2913 sizeof(items
) / sizeof(items
[0]),
2914 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
2918 bytesNeeded
-= size
;
2921 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2922 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2930 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2931 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2934 struct AsnEncodeSequenceItem items
[2] = {
2935 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2936 { info
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2940 if (!info
->pszPolicyIdentifier
)
2942 SetLastError(E_INVALIDARG
);
2945 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2946 sizeof(items
) / sizeof(items
[0]), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2950 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2951 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2952 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2958 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2959 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2962 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2964 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2965 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2968 bytesNeeded
+= size
;
2970 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2971 bytesNeeded
+= 1 + lenBytes
;
2975 *pcbEncoded
= bytesNeeded
;
2978 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2979 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2983 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2984 pbEncoded
= *(BYTE
**)pbEncoded
;
2986 *out
++ = ASN_SEQUENCEOF
;
2987 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2989 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2992 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2993 &info
->rgPolicyInfo
[i
],
2994 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
2998 bytesNeeded
-= size
;
3001 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3002 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3009 SetLastError(STATUS_ACCESS_VIOLATION
);
3015 static BOOL
CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType
,
3016 const CERT_POLICY_MAPPING
*mapping
, DWORD dwFlags
, BYTE
*pbEncoded
,
3019 struct AsnEncodeSequenceItem items
[] = {
3020 { mapping
->pszIssuerDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3021 { mapping
->pszSubjectDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3024 if (!mapping
->pszIssuerDomainPolicy
|| !mapping
->pszSubjectDomainPolicy
)
3026 SetLastError(E_INVALIDARG
);
3029 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3030 sizeof(items
) / sizeof(items
[0]), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3033 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType
,
3034 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3035 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3041 const CERT_POLICY_MAPPINGS_INFO
*info
= pvStructInfo
;
3042 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3045 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3047 ret
= CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType
,
3048 &info
->rgPolicyMapping
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
3051 bytesNeeded
+= size
;
3053 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3054 bytesNeeded
+= 1 + lenBytes
;
3058 *pcbEncoded
= bytesNeeded
;
3061 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3062 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3066 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3067 pbEncoded
= *(BYTE
**)pbEncoded
;
3069 *out
++ = ASN_SEQUENCEOF
;
3070 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3072 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3075 ret
= CRYPT_AsnEncodeCertPolicyMapping(
3076 dwCertEncodingType
, &info
->rgPolicyMapping
[i
],
3077 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
3081 bytesNeeded
-= size
;
3084 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3085 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3092 SetLastError(STATUS_ACCESS_VIOLATION
);
3098 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyConstraints(
3099 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3100 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3107 const CERT_POLICY_CONSTRAINTS_INFO
*info
= pvStructInfo
;
3108 struct AsnEncodeSequenceItem items
[2];
3109 struct AsnEncodeTagSwappedItem swapped
[2];
3110 DWORD cItem
= 0, cSwapped
= 0;
3112 if (info
->fRequireExplicitPolicy
)
3114 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3115 swapped
[cSwapped
].pvStructInfo
=
3116 &info
->dwRequireExplicitPolicySkipCerts
;
3117 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3118 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3119 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3123 if (info
->fInhibitPolicyMapping
)
3125 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3126 swapped
[cSwapped
].pvStructInfo
=
3127 &info
->dwInhibitPolicyMappingSkipCerts
;
3128 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3129 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3130 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3134 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3135 dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3139 SetLastError(STATUS_ACCESS_VIOLATION
);
3145 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
3146 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3147 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3153 const BLOBHEADER
*hdr
= pvStructInfo
;
3155 if (hdr
->bType
!= PUBLICKEYBLOB
)
3157 SetLastError(E_INVALIDARG
);
3162 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
3163 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
3164 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
3165 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
3166 struct AsnEncodeSequenceItem items
[] = {
3167 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3168 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
3171 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3172 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3178 SetLastError(STATUS_ACCESS_VIOLATION
);
3185 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
3186 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3187 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3193 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
3194 DWORD bytesNeeded
, lenBytes
;
3196 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3197 dwFlags
, pEncodePara
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
3199 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3200 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3203 *pcbEncoded
= bytesNeeded
;
3208 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3209 pcbEncoded
, bytesNeeded
)))
3211 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3212 pbEncoded
= *(BYTE
**)pbEncoded
;
3213 *pbEncoded
++ = ASN_OCTETSTRING
;
3214 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3215 pbEncoded
+= lenBytes
;
3217 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3223 SetLastError(STATUS_ACCESS_VIOLATION
);
3227 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3231 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3232 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3233 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3239 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3240 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3243 /* yep, MS allows cUnusedBits to be >= 8 */
3244 if (!blob
->cUnusedBits
)
3246 dataBytes
= blob
->cbData
;
3249 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3251 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3252 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3260 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3261 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3264 *pcbEncoded
= bytesNeeded
;
3269 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3270 pcbEncoded
, bytesNeeded
)))
3272 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3273 pbEncoded
= *(BYTE
**)pbEncoded
;
3274 *pbEncoded
++ = ASN_BITSTRING
;
3275 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3276 pbEncoded
+= lenBytes
;
3277 *pbEncoded
++ = unusedBits
;
3280 BYTE mask
= 0xff << unusedBits
;
3284 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3285 pbEncoded
+= dataBytes
- 1;
3287 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3294 SetLastError(STATUS_ACCESS_VIOLATION
);
3301 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3302 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3303 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3309 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3310 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3315 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3320 for (i
= 0; i
< newBlob
.cbData
; i
++)
3321 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3327 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3328 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3329 CryptMemFree(newBlob
.pbData
);
3333 SetLastError(STATUS_ACCESS_VIOLATION
);
3340 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3341 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3342 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3344 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3346 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3347 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3350 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3351 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3352 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3358 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3361 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3363 significantBytes
= blob
->cbData
;
3364 if (significantBytes
)
3366 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3368 /* negative, lop off leading (little-endian) 0xffs */
3369 for (; significantBytes
> 0 &&
3370 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3372 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3380 /* positive, lop off leading (little-endian) zeroes */
3381 for (; significantBytes
> 0 &&
3382 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3384 if (significantBytes
== 0)
3385 significantBytes
= 1;
3386 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3394 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3396 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3397 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3402 *pcbEncoded
= bytesNeeded
;
3407 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3408 pcbEncoded
, bytesNeeded
)))
3410 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3411 pbEncoded
= *(BYTE
**)pbEncoded
;
3412 *pbEncoded
++ = ASN_INTEGER
;
3415 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3416 pbEncoded
+= lenBytes
;
3417 *pbEncoded
++ = padByte
;
3421 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3422 pbEncoded
+= lenBytes
;
3424 for (; significantBytes
> 0; significantBytes
--)
3425 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3431 SetLastError(STATUS_ACCESS_VIOLATION
);
3438 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3439 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3440 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3446 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3448 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3450 significantBytes
= blob
->cbData
;
3451 if (significantBytes
)
3453 /* positive, lop off leading (little-endian) zeroes */
3454 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3457 if (significantBytes
== 0)
3458 significantBytes
= 1;
3459 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3463 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3465 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3466 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3471 *pcbEncoded
= bytesNeeded
;
3476 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3477 pcbEncoded
, bytesNeeded
)))
3479 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3480 pbEncoded
= *(BYTE
**)pbEncoded
;
3481 *pbEncoded
++ = ASN_INTEGER
;
3484 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3485 pbEncoded
+= lenBytes
;
3490 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3491 pbEncoded
+= lenBytes
;
3493 for (; significantBytes
> 0; significantBytes
--)
3494 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3500 SetLastError(STATUS_ACCESS_VIOLATION
);
3507 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3508 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3509 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3511 CRYPT_INTEGER_BLOB blob
;
3514 /* Encode as an unsigned integer, then change the tag to enumerated */
3515 blob
.cbData
= sizeof(DWORD
);
3516 blob
.pbData
= (BYTE
*)pvStructInfo
;
3517 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3518 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3519 if (ret
&& pbEncoded
)
3521 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3522 pbEncoded
= *(BYTE
**)pbEncoded
;
3523 pbEncoded
[0] = ASN_ENUMERATED
;
3528 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3529 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3530 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3537 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3538 * temporary buffer because the output buffer is not NULL-terminated.
3541 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3545 *pcbEncoded
= bytesNeeded
;
3550 /* Sanity check the year, this is a two-digit year format */
3551 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3552 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3554 SetLastError(CRYPT_E_BAD_ENCODE
);
3559 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3560 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3562 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3563 pbEncoded
= *(BYTE
**)pbEncoded
;
3564 buf
[0] = ASN_UTCTIME
;
3565 buf
[1] = bytesNeeded
- 2;
3566 snprintf(buf
+ 2, sizeof(buf
) - 2,
3567 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3568 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3569 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3570 sysTime
.wMinute
, sysTime
.wSecond
);
3571 memcpy(pbEncoded
, buf
, bytesNeeded
);
3578 SetLastError(STATUS_ACCESS_VIOLATION
);
3585 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3586 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3587 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3594 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3595 * temporary buffer because the output buffer is not NULL-terminated.
3598 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3602 *pcbEncoded
= bytesNeeded
;
3607 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3609 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3610 pcbEncoded
, bytesNeeded
);
3613 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3614 pbEncoded
= *(BYTE
**)pbEncoded
;
3615 buf
[0] = ASN_GENERALTIME
;
3616 buf
[1] = bytesNeeded
- 2;
3617 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3618 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3619 sysTime
.wMinute
, sysTime
.wSecond
);
3620 memcpy(pbEncoded
, buf
, bytesNeeded
);
3626 SetLastError(STATUS_ACCESS_VIOLATION
);
3633 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3634 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3635 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3643 /* Check the year, if it's in the UTCTime range call that encode func */
3644 if (!FileTimeToSystemTime(pvStructInfo
, &sysTime
))
3646 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3647 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3648 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3650 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3651 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3656 SetLastError(STATUS_ACCESS_VIOLATION
);
3663 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3664 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3665 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3671 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3672 const CRYPT_SEQUENCE_OF_ANY
*seq
= pvStructInfo
;
3674 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3675 dataLen
+= seq
->rgValue
[i
].cbData
;
3676 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3677 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3680 *pcbEncoded
= bytesNeeded
;
3685 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3686 pcbEncoded
, bytesNeeded
)))
3688 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3689 pbEncoded
= *(BYTE
**)pbEncoded
;
3690 *pbEncoded
++ = ASN_SEQUENCEOF
;
3691 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3692 pbEncoded
+= lenBytes
;
3693 for (i
= 0; i
< seq
->cValue
; i
++)
3695 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3696 seq
->rgValue
[i
].cbData
);
3697 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3704 SetLastError(STATUS_ACCESS_VIOLATION
);
3711 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3712 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3715 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3716 struct AsnConstructedItem constructed
= { 0 };
3717 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3718 DWORD cItem
= 0, cSwapped
= 0;
3720 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3722 case CRL_DIST_POINT_NO_NAME
:
3725 case CRL_DIST_POINT_FULL_NAME
:
3726 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3727 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3728 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3729 constructed
.tag
= 0;
3730 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3731 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3732 items
[cItem
].pvStructInfo
= &constructed
;
3733 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3737 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3738 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3744 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3746 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3747 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3748 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3749 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3750 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3754 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3756 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3757 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3758 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3759 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3760 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3765 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3766 pbEncoded
, pcbEncoded
);
3770 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3771 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3772 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3778 const CRL_DIST_POINTS_INFO
*info
= pvStructInfo
;
3780 if (!info
->cDistPoint
)
3782 SetLastError(E_INVALIDARG
);
3787 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3790 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3794 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3798 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3800 /* Have to propagate index of failing character */
3806 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3807 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3810 *pcbEncoded
= bytesNeeded
;
3815 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3816 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3820 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3821 pbEncoded
= *(BYTE
**)pbEncoded
;
3823 *out
++ = ASN_SEQUENCEOF
;
3824 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
3826 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3828 DWORD len
= dataLen
;
3830 ret
= CRYPT_AsnEncodeDistPoint(
3831 &info
->rgDistPoint
[i
], out
, &len
);
3838 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3839 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3847 SetLastError(STATUS_ACCESS_VIOLATION
);
3854 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3855 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3856 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3862 const CERT_ENHKEY_USAGE
*usage
= pvStructInfo
;
3863 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3866 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3868 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3869 usage
->rgpszUsageIdentifier
[i
],
3870 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3872 bytesNeeded
+= size
;
3874 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3875 bytesNeeded
+= 1 + lenBytes
;
3879 *pcbEncoded
= bytesNeeded
;
3882 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3883 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3887 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3888 pbEncoded
= *(BYTE
**)pbEncoded
;
3890 *out
++ = ASN_SEQUENCEOF
;
3891 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3893 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3896 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3897 usage
->rgpszUsageIdentifier
[i
],
3898 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
3902 bytesNeeded
-= size
;
3905 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3906 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3913 SetLastError(STATUS_ACCESS_VIOLATION
);
3920 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3921 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3922 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3928 const CRL_ISSUING_DIST_POINT
*point
= pvStructInfo
;
3929 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3930 struct AsnConstructedItem constructed
= { 0 };
3931 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3932 DWORD cItem
= 0, cSwapped
= 0;
3935 switch (point
->DistPointName
.dwDistPointNameChoice
)
3937 case CRL_DIST_POINT_NO_NAME
:
3940 case CRL_DIST_POINT_FULL_NAME
:
3941 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3942 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3943 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3944 constructed
.tag
= 0;
3945 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3946 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3947 items
[cItem
].pvStructInfo
= &constructed
;
3948 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3953 SetLastError(E_INVALIDARG
);
3956 if (ret
&& point
->fOnlyContainsUserCerts
)
3958 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3959 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3960 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3961 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3962 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3966 if (ret
&& point
->fOnlyContainsCACerts
)
3968 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3969 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3970 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3971 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3972 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3976 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3978 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3979 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3980 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3981 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3982 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3986 if (ret
&& point
->fIndirectCRL
)
3988 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3989 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3990 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3991 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3992 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3997 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3998 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4002 SetLastError(STATUS_ACCESS_VIOLATION
);
4009 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
4010 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4011 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4014 const CERT_GENERAL_SUBTREE
*subtree
= pvStructInfo
;
4015 struct AsnEncodeSequenceItem items
[3] = {
4016 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
4019 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4020 DWORD cItem
= 1, cSwapped
= 0;
4022 if (subtree
->dwMinimum
)
4024 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4025 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
4026 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4027 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4028 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4032 if (subtree
->fMaximum
)
4034 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
4035 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
4036 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4037 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4038 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4042 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
4043 pEncodePara
, pbEncoded
, pcbEncoded
);
4047 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
4048 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4049 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4052 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
4054 TRACE("%p\n", pvStructInfo
);
4058 const CERT_NAME_CONSTRAINTS_INFO
*constraints
= pvStructInfo
;
4059 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
4060 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4061 DWORD i
, cItem
= 0, cSwapped
= 0;
4064 if (constraints
->cPermittedSubtree
)
4066 permitted
.rgBlob
= CryptMemAlloc(
4067 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
4068 if (permitted
.rgBlob
)
4070 permitted
.cBlob
= constraints
->cPermittedSubtree
;
4071 memset(permitted
.rgBlob
, 0,
4072 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4073 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
4074 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4075 NULL
, &constraints
->rgPermittedSubtree
[i
],
4076 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4077 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
4078 &permitted
.rgBlob
[i
].cbData
);
4081 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4082 swapped
[cSwapped
].pvStructInfo
= &permitted
;
4083 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4084 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4085 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4093 if (constraints
->cExcludedSubtree
)
4095 excluded
.rgBlob
= CryptMemAlloc(
4096 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
4097 if (excluded
.rgBlob
)
4099 excluded
.cBlob
= constraints
->cExcludedSubtree
;
4100 memset(excluded
.rgBlob
, 0,
4101 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4102 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
4103 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4104 NULL
, &constraints
->rgExcludedSubtree
[i
],
4105 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4106 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
4107 &excluded
.rgBlob
[i
].cbData
);
4110 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4111 swapped
[cSwapped
].pvStructInfo
= &excluded
;
4112 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4113 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4114 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4123 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4124 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4125 for (i
= 0; i
< permitted
.cBlob
; i
++)
4126 LocalFree(permitted
.rgBlob
[i
].pbData
);
4127 for (i
= 0; i
< excluded
.cBlob
; i
++)
4128 LocalFree(excluded
.rgBlob
[i
].pbData
);
4132 SetLastError(STATUS_ACCESS_VIOLATION
);
4135 CryptMemFree(permitted
.rgBlob
);
4136 CryptMemFree(excluded
.rgBlob
);
4137 TRACE("returning %d\n", ret
);
4141 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
4142 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
4143 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
4147 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
= pvStructInfo
;
4148 struct AsnEncodeSequenceItem items
[] = {
4149 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
4150 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
4153 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4154 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
4159 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
4160 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4161 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4165 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4167 SetLastError(E_INVALIDARG
);
4173 const CMSG_SIGNER_INFO
*info
= pvStructInfo
;
4175 if (!info
->Issuer
.cbData
)
4176 SetLastError(E_INVALIDARG
);
4179 struct AsnEncodeSequenceItem items
[7] = {
4180 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4181 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4182 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
4185 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4186 DWORD cItem
= 3, cSwapped
= 0;
4188 if (info
->AuthAttrs
.cAttr
)
4190 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4191 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4192 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4193 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4194 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4198 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4199 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4201 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4202 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4204 if (info
->UnauthAttrs
.cAttr
)
4206 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4207 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4208 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4209 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4210 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4214 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4215 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4220 SetLastError(STATUS_ACCESS_VIOLATION
);
4226 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4227 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4228 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4232 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4234 SetLastError(E_INVALIDARG
);
4240 const CMSG_CMS_SIGNER_INFO
*info
= pvStructInfo
;
4242 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4243 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4244 SetLastError(E_INVALIDARG
);
4245 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4246 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4247 SetLastError(E_INVALIDARG
);
4250 struct AsnEncodeSequenceItem items
[7] = {
4251 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4253 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4254 DWORD cItem
= 1, cSwapped
= 0;
4256 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4258 items
[cItem
].pvStructInfo
=
4259 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4260 items
[cItem
].encodeFunc
=
4261 CRYPT_AsnEncodeIssuerSerialNumber
;
4266 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4267 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4268 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4269 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4270 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4274 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4275 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4277 if (info
->AuthAttrs
.cAttr
)
4279 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4280 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4281 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4282 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4283 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4287 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4288 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4290 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4291 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4293 if (info
->UnauthAttrs
.cAttr
)
4295 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4296 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4297 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4298 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4299 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4303 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4304 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4309 SetLastError(STATUS_ACCESS_VIOLATION
);
4315 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4318 struct AsnEncodeSequenceItem items
[7] = {
4319 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4321 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4322 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4323 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4324 DWORD cItem
= 1, cSwapped
= 0;
4327 if (signedInfo
->cSignerInfo
)
4329 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4330 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4331 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4332 digestAlgorithmsSet
.itemOffset
=
4333 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4334 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4335 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4336 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4339 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4340 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4342 if (signedInfo
->cCertEncoded
)
4344 certSet
.cItems
= signedInfo
->cCertEncoded
;
4345 certSet
.items
= signedInfo
->rgCertEncoded
;
4346 certSet
.itemSize
= sizeof(CERT_BLOB
);
4347 certSet
.itemOffset
= 0;
4348 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4349 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4350 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4351 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4352 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4353 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4357 if (signedInfo
->cCrlEncoded
)
4359 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4360 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4361 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4362 crlSet
.itemOffset
= 0;
4363 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4364 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4365 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4366 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4367 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4368 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4372 if (ret
&& signedInfo
->cSignerInfo
)
4374 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4375 signerSet
.items
= signedInfo
->rgSignerInfo
;
4376 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4377 signerSet
.itemOffset
= 0;
4378 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4379 items
[cItem
].pvStructInfo
= &signerSet
;
4380 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4384 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4385 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4390 static BOOL WINAPI
CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType
,
4391 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4392 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4394 const CMSG_KEY_TRANS_RECIPIENT_INFO
*info
= pvStructInfo
;
4395 struct AsnEncodeSequenceItem items
[] = {
4396 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4397 { &info
->RecipientId
.u
.IssuerSerialNumber
,
4398 CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4399 { &info
->KeyEncryptionAlgorithm
,
4400 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4401 { &info
->EncryptedKey
, CRYPT_AsnEncodeOctets
, 0 },
4404 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4405 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
4409 static BOOL WINAPI
CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType
,
4410 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4411 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4413 const CRYPT_ENCRYPTED_CONTENT_INFO
*info
= pvStructInfo
;
4414 struct AsnEncodeTagSwappedItem swapped
= { ASN_CONTEXT
| 0,
4415 &info
->encryptedContent
, CRYPT_AsnEncodeOctets
};
4416 struct AsnEncodeSequenceItem items
[] = {
4417 { info
->contentType
, CRYPT_AsnEncodeOid
, 0 },
4418 { &info
->contentEncryptionAlgorithm
,
4419 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4420 { &swapped
, CRYPT_AsnEncodeSwapTag
, 0 },
4423 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4424 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
4428 BOOL
CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA
*envelopedData
,
4429 void *pvData
, DWORD
*pcbData
)
4431 struct DERSetDescriptor recipientInfosSet
= { envelopedData
->cRecipientInfo
,
4432 envelopedData
->rgRecipientInfo
, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
), 0,
4433 CRYPT_AsnEncodeRecipientInfo
};
4434 struct AsnEncodeSequenceItem items
[] = {
4435 { &envelopedData
->version
, CRYPT_AsnEncodeInt
, 0 },
4436 { &recipientInfosSet
, CRYPT_DEREncodeItemsAsSet
, 0 },
4437 { &envelopedData
->encryptedContentInfo
,
4438 CRYPT_AsnEncodeEncryptedContentInfo
, 0 },
4441 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
4442 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
4445 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4446 LPCSTR lpszStructType
)
4448 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4450 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4451 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4453 SetLastError(ERROR_FILE_NOT_FOUND
);
4457 if (IS_INTOID(lpszStructType
))
4459 switch (LOWORD(lpszStructType
))
4461 case LOWORD(X509_CERT
):
4462 encodeFunc
= CRYPT_AsnEncodeCert
;
4464 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4465 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4467 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4468 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4470 case LOWORD(X509_EXTENSIONS
):
4471 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4473 case LOWORD(X509_NAME_VALUE
):
4474 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4476 case LOWORD(X509_NAME
):
4477 encodeFunc
= CRYPT_AsnEncodeName
;
4479 case LOWORD(X509_PUBLIC_KEY_INFO
):
4480 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4482 case LOWORD(X509_AUTHORITY_KEY_ID
):
4483 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4485 case LOWORD(X509_ALTERNATE_NAME
):
4486 encodeFunc
= CRYPT_AsnEncodeAltName
;
4488 case LOWORD(X509_BASIC_CONSTRAINTS
):
4489 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4491 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4492 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4494 case LOWORD(X509_CERT_POLICIES
):
4495 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4497 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4498 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4500 case LOWORD(X509_UNICODE_NAME
):
4501 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4503 case LOWORD(PKCS_CONTENT_INFO
):
4504 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4506 case LOWORD(PKCS_ATTRIBUTE
):
4507 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4509 case LOWORD(X509_UNICODE_NAME_VALUE
):
4510 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4512 case LOWORD(X509_OCTET_STRING
):
4513 encodeFunc
= CRYPT_AsnEncodeOctets
;
4515 case LOWORD(X509_BITS
):
4516 case LOWORD(X509_KEY_USAGE
):
4517 encodeFunc
= CRYPT_AsnEncodeBits
;
4519 case LOWORD(X509_INTEGER
):
4520 encodeFunc
= CRYPT_AsnEncodeInt
;
4522 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4523 encodeFunc
= CRYPT_AsnEncodeInteger
;
4525 case LOWORD(X509_MULTI_BYTE_UINT
):
4526 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4528 case LOWORD(X509_ENUMERATED
):
4529 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4531 case LOWORD(X509_CHOICE_OF_TIME
):
4532 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4534 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4535 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4537 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4538 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4540 case LOWORD(X509_SEQUENCE_OF_ANY
):
4541 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4543 case LOWORD(PKCS_UTC_TIME
):
4544 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4546 case LOWORD(X509_CRL_DIST_POINTS
):
4547 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4549 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4550 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4552 case LOWORD(PKCS_CTL
):
4553 encodeFunc
= CRYPT_AsnEncodeCTL
;
4555 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4556 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4558 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4559 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4561 case LOWORD(PKCS_ATTRIBUTES
):
4562 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4564 case LOWORD(X509_ISSUING_DIST_POINT
):
4565 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4567 case LOWORD(X509_NAME_CONSTRAINTS
):
4568 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4570 case LOWORD(X509_POLICY_MAPPINGS
):
4571 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4573 case LOWORD(X509_POLICY_CONSTRAINTS
):
4574 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4576 case LOWORD(PKCS7_SIGNER_INFO
):
4577 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4579 case LOWORD(CMS_SIGNER_INFO
):
4580 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4584 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4585 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4586 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4587 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4588 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4589 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4590 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4591 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4592 else if (!strcmp(lpszStructType
, szOID_LEGACY_POLICY_MAPPINGS
))
4593 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4594 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4595 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4596 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4597 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4598 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4599 encodeFunc
= CRYPT_AsnEncodeBits
;
4600 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4601 encodeFunc
= CRYPT_AsnEncodeOctets
;
4602 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4603 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4604 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4605 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4606 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4607 encodeFunc
= CRYPT_AsnEncodeAltName
;
4608 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4609 encodeFunc
= CRYPT_AsnEncodeAltName
;
4610 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4611 encodeFunc
= CRYPT_AsnEncodeAltName
;
4612 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4613 encodeFunc
= CRYPT_AsnEncodeAltName
;
4614 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4615 encodeFunc
= CRYPT_AsnEncodeAltName
;
4616 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4617 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4618 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4619 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4620 else if (!strcmp(lpszStructType
, szOID_POLICY_MAPPINGS
))
4621 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4622 else if (!strcmp(lpszStructType
, szOID_POLICY_CONSTRAINTS
))
4623 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4624 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4625 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4626 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4627 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4628 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4629 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4630 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4631 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4632 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4633 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4634 else if (!strcmp(lpszStructType
, szOID_CTL
))
4635 encodeFunc
= CRYPT_AsnEncodeCTL
;
4639 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4640 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4642 static HCRYPTOIDFUNCSET set
= NULL
;
4643 CryptEncodeObjectFunc encodeFunc
= NULL
;
4646 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4647 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4648 (void **)&encodeFunc
, hFunc
);
4652 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4653 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4655 static HCRYPTOIDFUNCSET set
= NULL
;
4656 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4659 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4660 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4661 (void **)&encodeFunc
, hFunc
);
4665 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4666 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4669 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4670 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4671 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4673 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4674 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4677 if (!pbEncoded
&& !pcbEncoded
)
4679 SetLastError(ERROR_INVALID_PARAMETER
);
4683 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4686 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4687 debugstr_a(lpszStructType
));
4688 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4689 lpszStructType
, &hFunc
);
4690 if (!pCryptEncodeObject
)
4691 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4692 lpszStructType
, &hFunc
);
4694 if (pCryptEncodeObject
)
4695 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4696 pvStructInfo
, pbEncoded
, pcbEncoded
);
4697 else if (pCryptEncodeObjectEx
)
4698 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4699 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4701 CryptFreeOIDFunctionAddress(hFunc
, 0);
4702 TRACE_(crypt
)("returning %d\n", ret
);
4706 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4707 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4708 void *pvEncoded
, DWORD
*pcbEncoded
)
4711 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4712 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4714 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4715 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4716 pvEncoded
, pcbEncoded
);
4718 if (!pvEncoded
&& !pcbEncoded
)
4720 SetLastError(ERROR_INVALID_PARAMETER
);
4724 SetLastError(NOERROR
);
4725 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
) {
4727 SetLastError(ERROR_INVALID_PARAMETER
);
4730 *(BYTE
**)pvEncoded
= NULL
;
4732 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4735 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4736 debugstr_a(lpszStructType
));
4737 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4741 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4742 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4745 CryptEncodeObjectFunc pCryptEncodeObject
=
4746 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4748 if (pCryptEncodeObject
)
4750 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4752 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4753 pvStructInfo
, NULL
, pcbEncoded
);
4754 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4755 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4756 ret
= pCryptEncodeObject(dwCertEncodingType
,
4757 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4761 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4762 pvStructInfo
, pvEncoded
, pcbEncoded
);
4766 CryptFreeOIDFunctionAddress(hFunc
, 0);
4767 TRACE_(crypt
)("returning %d\n", ret
);
4771 BOOL WINAPI
PFXExportCertStore(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4772 LPCWSTR szPassword
, DWORD dwFlags
)
4774 return PFXExportCertStoreEx(hStore
, pPFX
, szPassword
, NULL
, dwFlags
);
4777 BOOL WINAPI
PFXExportCertStoreEx(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4778 LPCWSTR szPassword
, void *pvReserved
, DWORD dwFlags
)
4780 FIXME_(crypt
)("(%p, %p, %p, %p, %08x): stub\n", hStore
, pPFX
, szPassword
,
4781 pvReserved
, dwFlags
);
4785 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4786 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4788 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4789 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4792 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4793 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4794 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4798 static CHAR oid
[] = szOID_RSA_RSA
;
4800 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4801 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4802 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4804 if (!pszPublicKeyObjId
)
4805 pszPublicKeyObjId
= oid
;
4806 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4810 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4813 LPBYTE pubKey
= CryptMemAlloc(keySize
);
4817 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4821 DWORD encodedLen
= 0;
4823 ret
= CryptEncodeObject(dwCertEncodingType
,
4824 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4827 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4828 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4831 *pcbInfo
= sizeNeeded
;
4832 else if (*pcbInfo
< sizeNeeded
)
4834 SetLastError(ERROR_MORE_DATA
);
4835 *pcbInfo
= sizeNeeded
;
4840 *pcbInfo
= sizeNeeded
;
4841 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4842 sizeof(CERT_PUBLIC_KEY_INFO
);
4843 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4845 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4846 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4847 pInfo
->PublicKey
.pbData
=
4848 (BYTE
*)pInfo
->Algorithm
.pszObjId
4849 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4850 pInfo
->PublicKey
.cbData
= encodedLen
;
4851 pInfo
->PublicKey
.cUnusedBits
= 0;
4852 ret
= CryptEncodeObject(dwCertEncodingType
,
4853 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4854 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4858 CryptMemFree(pubKey
);
4863 CryptDestroyKey(key
);
4868 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4869 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4870 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4872 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4873 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4874 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4876 static HCRYPTOIDFUNCSET set
= NULL
;
4878 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4879 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4881 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4882 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4883 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4887 SetLastError(ERROR_INVALID_PARAMETER
);
4891 if (pszPublicKeyObjId
)
4894 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4896 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4897 0, (void **)&exportFunc
, &hFunc
);
4900 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4901 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4902 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4904 CryptFreeOIDFunctionAddress(hFunc
, 0);
4908 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4909 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4911 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4915 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4916 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4917 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4920 DWORD pubKeySize
= 0;
4922 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4923 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4925 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4926 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4929 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4933 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4934 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4939 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4940 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4943 CryptMemFree(pubKey
);
4951 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4952 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4953 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4955 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4956 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4957 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4959 static HCRYPTOIDFUNCSET set
= NULL
;
4961 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4962 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4964 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4965 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4968 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4969 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4970 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4972 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4973 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4976 CryptFreeOIDFunctionAddress(hFunc
, 0);