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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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 ARRAY_SIZE(items
), 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
, ARRAY_SIZE(items
), 0, NULL
, pvData
, pcbData
);
1966 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1967 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1968 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1974 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1976 if (!info
->pszObjId
)
1977 SetLastError(E_INVALIDARG
);
1979 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1980 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1985 SetLastError(STATUS_ACCESS_VIOLATION
);
1991 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1992 BYTE tag
, DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
1996 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1997 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1999 if (value
->Value
.cbData
)
2000 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2002 encodedLen
= strlenW(str
);
2005 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2006 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2008 *pcbEncoded
= bytesNeeded
;
2011 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2012 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2016 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2017 pbEncoded
= *(BYTE
**)pbEncoded
;
2019 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
2020 pbEncoded
+= lenBytes
;
2021 for (i
= 0; i
< encodedLen
; i
++)
2022 *pbEncoded
++ = (BYTE
)str
[i
];
2028 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
2029 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2033 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2034 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2036 if (value
->Value
.cbData
)
2037 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2039 encodedLen
= strlenW(str
);
2042 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2043 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2045 *pcbEncoded
= bytesNeeded
;
2048 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2049 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2054 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2055 ptr
= *(BYTE
**)pbEncoded
;
2058 *ptr
++ = ASN_NUMERICSTRING
;
2059 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2061 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2063 if (isdigitW(str
[i
]))
2064 *ptr
++ = (BYTE
)str
[i
];
2068 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2072 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2073 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2079 static inline BOOL
isprintableW(WCHAR wc
)
2081 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
2082 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
2083 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
2086 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2087 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2091 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2092 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2094 if (value
->Value
.cbData
)
2095 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2097 encodedLen
= strlenW(str
);
2100 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2101 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2103 *pcbEncoded
= bytesNeeded
;
2106 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2107 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2112 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2113 ptr
= *(BYTE
**)pbEncoded
;
2116 *ptr
++ = ASN_PRINTABLESTRING
;
2117 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2119 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2121 if (isprintableW(str
[i
]))
2122 *ptr
++ = (BYTE
)str
[i
];
2126 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2130 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2131 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2137 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2138 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2142 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2143 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2145 if (value
->Value
.cbData
)
2146 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2148 encodedLen
= strlenW(str
);
2151 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2152 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2154 *pcbEncoded
= bytesNeeded
;
2157 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2158 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2163 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2164 ptr
= *(BYTE
**)pbEncoded
;
2167 *ptr
++ = ASN_IA5STRING
;
2168 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2170 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2173 *ptr
++ = (BYTE
)str
[i
];
2177 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2181 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2182 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2188 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2189 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2193 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2194 DWORD bytesNeeded
, lenBytes
, strLen
;
2196 /* FIXME: doesn't handle composite characters */
2197 if (value
->Value
.cbData
)
2198 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2200 strLen
= strlenW(str
);
2203 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2204 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2206 *pcbEncoded
= bytesNeeded
;
2209 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2210 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2214 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2215 pbEncoded
= *(BYTE
**)pbEncoded
;
2216 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2217 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2218 pbEncoded
+= lenBytes
;
2219 for (i
= 0; i
< strLen
; i
++)
2223 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2224 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2231 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2232 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2233 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2239 const CERT_NAME_VALUE
*value
= pvStructInfo
;
2241 switch (value
->dwValueType
)
2243 case CERT_RDN_ANY_TYPE
:
2244 case CERT_RDN_ENCODED_BLOB
:
2245 case CERT_RDN_OCTET_STRING
:
2246 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2248 case CERT_RDN_NUMERIC_STRING
:
2249 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2250 pbEncoded
, pcbEncoded
);
2252 case CERT_RDN_PRINTABLE_STRING
:
2253 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2254 pbEncoded
, pcbEncoded
);
2256 case CERT_RDN_TELETEX_STRING
:
2257 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2258 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2260 case CERT_RDN_VIDEOTEX_STRING
:
2261 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2262 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2264 case CERT_RDN_IA5_STRING
:
2265 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2266 pbEncoded
, pcbEncoded
);
2268 case CERT_RDN_GRAPHIC_STRING
:
2269 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2270 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2272 case CERT_RDN_VISIBLE_STRING
:
2273 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2274 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2276 case CERT_RDN_GENERAL_STRING
:
2277 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2278 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2280 case CERT_RDN_UNIVERSAL_STRING
:
2281 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2282 pbEncoded
, pcbEncoded
);
2284 case CERT_RDN_BMP_STRING
:
2285 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2286 pbEncoded
, pcbEncoded
);
2288 case CERT_RDN_UTF8_STRING
:
2289 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2290 pbEncoded
, pcbEncoded
);
2293 SetLastError(CRYPT_E_ASN1_CHOICE
);
2298 SetLastError(STATUS_ACCESS_VIOLATION
);
2304 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2305 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2306 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2312 const CERT_NAME_INFO
*info
= pvStructInfo
;
2313 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2315 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2317 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2319 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2320 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2322 bytesNeeded
+= size
;
2324 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2325 bytesNeeded
+= 1 + lenBytes
;
2329 *pcbEncoded
= bytesNeeded
;
2332 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2333 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2337 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2338 pbEncoded
= *(BYTE
**)pbEncoded
;
2340 *out
++ = ASN_SEQUENCEOF
;
2341 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2343 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2346 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2347 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, out
, &size
);
2351 bytesNeeded
-= size
;
2354 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2355 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2362 SetLastError(STATUS_ACCESS_VIOLATION
);
2369 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2370 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2371 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2373 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2382 else if (*pcbEncoded
< 3)
2385 SetLastError(ERROR_MORE_DATA
);
2391 *pbEncoded
++ = ASN_BOOL
;
2393 *pbEncoded
++ = val
? 0xff : 0;
2396 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2400 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2401 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2402 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2404 const CERT_ALT_NAME_ENTRY
*entry
= pvStructInfo
;
2410 switch (entry
->dwAltNameChoice
)
2412 case CERT_ALT_NAME_RFC822_NAME
:
2413 case CERT_ALT_NAME_DNS_NAME
:
2414 case CERT_ALT_NAME_URL
:
2415 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2416 if (entry
->u
.pwszURL
)
2420 /* Not + 1: don't encode the NULL-terminator */
2421 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2422 for (i
= 0; ret
&& i
< dataLen
; i
++)
2424 if (entry
->u
.pwszURL
[i
] > 0x7f)
2426 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2435 case CERT_ALT_NAME_DIRECTORY_NAME
:
2436 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2437 dataLen
= entry
->u
.DirectoryName
.cbData
;
2439 case CERT_ALT_NAME_IP_ADDRESS
:
2440 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2441 dataLen
= entry
->u
.IPAddress
.cbData
;
2443 case CERT_ALT_NAME_REGISTERED_ID
:
2445 struct AsnEncodeTagSwappedItem swapped
=
2446 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2447 CRYPT_AsnEncodeOid
};
2449 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2452 case CERT_ALT_NAME_OTHER_NAME
:
2453 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2456 SetLastError(E_INVALIDARG
);
2461 DWORD bytesNeeded
, lenBytes
;
2463 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2464 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2466 *pcbEncoded
= bytesNeeded
;
2467 else if (*pcbEncoded
< bytesNeeded
)
2469 SetLastError(ERROR_MORE_DATA
);
2470 *pcbEncoded
= bytesNeeded
;
2476 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2477 pbEncoded
+= lenBytes
;
2478 switch (entry
->dwAltNameChoice
)
2480 case CERT_ALT_NAME_RFC822_NAME
:
2481 case CERT_ALT_NAME_DNS_NAME
:
2482 case CERT_ALT_NAME_URL
:
2486 for (i
= 0; i
< dataLen
; i
++)
2487 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2490 case CERT_ALT_NAME_DIRECTORY_NAME
:
2491 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2493 case CERT_ALT_NAME_IP_ADDRESS
:
2494 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2498 *pcbEncoded
= bytesNeeded
;
2501 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2505 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2506 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2507 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2513 const CERT_AUTHORITY_KEY_ID_INFO
*info
= pvStructInfo
;
2514 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2515 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2516 struct AsnConstructedItem constructed
= { 0 };
2517 DWORD cItem
= 0, cSwapped
= 0;
2519 if (info
->KeyId
.cbData
)
2521 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2522 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2523 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2524 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2525 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2529 if (info
->CertIssuer
.cbData
)
2531 constructed
.tag
= 1;
2532 constructed
.pvStructInfo
= &info
->CertIssuer
;
2533 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2534 items
[cItem
].pvStructInfo
= &constructed
;
2535 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2538 if (info
->CertSerialNumber
.cbData
)
2540 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2541 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2542 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2543 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2544 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2548 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2549 pEncodePara
, pbEncoded
, pcbEncoded
);
2553 SetLastError(STATUS_ACCESS_VIOLATION
);
2560 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2561 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2562 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2568 const CERT_ALT_NAME_INFO
*info
= pvStructInfo
;
2569 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2572 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2573 * can't encode an erroneous entry index if it's bigger than this.
2575 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2579 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2580 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2583 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2585 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2586 * the bad character, now set the index of the bad
2589 *pcbEncoded
= (BYTE
)i
<<
2590 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2595 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2596 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2599 *pcbEncoded
= bytesNeeded
;
2604 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2605 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2609 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2610 pbEncoded
= *(BYTE
**)pbEncoded
;
2612 *out
++ = ASN_SEQUENCEOF
;
2613 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2615 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2617 DWORD len
= dataLen
;
2619 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2620 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, out
, &len
);
2627 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2628 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2635 SetLastError(STATUS_ACCESS_VIOLATION
);
2642 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2643 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2644 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2650 const CERT_AUTHORITY_KEY_ID2_INFO
*info
= pvStructInfo
;
2651 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2652 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2653 DWORD cItem
= 0, cSwapped
= 0;
2655 if (info
->KeyId
.cbData
)
2657 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2658 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2659 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2660 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2661 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2665 if (info
->AuthorityCertIssuer
.cAltEntry
)
2667 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2668 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2669 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2670 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2671 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2675 if (info
->AuthorityCertSerialNumber
.cbData
)
2677 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2678 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2679 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2680 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2681 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2685 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2686 pEncodePara
, pbEncoded
, pcbEncoded
);
2690 SetLastError(STATUS_ACCESS_VIOLATION
);
2697 static BOOL
CRYPT_AsnEncodeAccessDescription(
2698 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2700 struct AsnEncodeSequenceItem items
[] = {
2701 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2702 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2705 if (!descr
->pszAccessMethod
)
2707 SetLastError(E_INVALIDARG
);
2710 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
), 0, NULL
, pbEncoded
, pcbEncoded
);
2713 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2714 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2715 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2721 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2722 const CERT_AUTHORITY_INFO_ACCESS
*info
= pvStructInfo
;
2725 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2729 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2736 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2737 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2739 *pcbEncoded
= bytesNeeded
;
2742 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2743 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2747 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2748 pbEncoded
= *(BYTE
**)pbEncoded
;
2750 *out
++ = ASN_SEQUENCEOF
;
2751 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2753 for (i
= 0; i
< info
->cAccDescr
; i
++)
2755 DWORD size
= dataLen
;
2757 ret
= CRYPT_AsnEncodeAccessDescription(
2758 &info
->rgAccDescr
[i
], out
, &size
);
2762 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2763 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2770 SetLastError(STATUS_ACCESS_VIOLATION
);
2777 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2778 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2779 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2785 const CERT_BASIC_CONSTRAINTS_INFO
*info
= pvStructInfo
;
2786 struct AsnEncodeSequenceItem items
[3] = {
2787 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2792 if (info
->fPathLenConstraint
)
2794 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2795 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2798 if (info
->cSubtreesConstraint
)
2800 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2801 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2804 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2805 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2809 SetLastError(STATUS_ACCESS_VIOLATION
);
2816 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2817 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2818 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2824 const CERT_BASIC_CONSTRAINTS2_INFO
*info
= pvStructInfo
;
2825 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2830 items
[cItem
].pvStructInfo
= &info
->fCA
;
2831 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2834 if (info
->fPathLenConstraint
)
2836 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2837 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2840 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2841 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2845 SetLastError(STATUS_ACCESS_VIOLATION
);
2852 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2853 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2854 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2856 const CERT_POLICY_INFO
*info
= pvStructInfo
;
2859 if (!info
->cPolicyQualifier
)
2866 struct AsnEncodeSequenceItem items
[2] = {
2867 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2868 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2870 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2873 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2875 items
[0].pvStructInfo
=
2876 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2877 items
[1].pvStructInfo
= &info
->rgPolicyQualifier
[i
].Qualifier
;
2878 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2879 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2881 bytesNeeded
+= size
;
2883 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2884 bytesNeeded
+= 1 + lenBytes
;
2888 *pcbEncoded
= bytesNeeded
;
2891 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2892 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2896 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2897 pbEncoded
= *(BYTE
**)pbEncoded
;
2899 *out
++ = ASN_SEQUENCEOF
;
2900 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2902 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2904 items
[0].pvStructInfo
=
2905 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2906 items
[1].pvStructInfo
=
2907 &info
->rgPolicyQualifier
[i
].Qualifier
;
2909 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2910 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
2914 bytesNeeded
-= size
;
2917 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2918 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2926 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2927 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2930 struct AsnEncodeSequenceItem items
[2] = {
2931 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2932 { info
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2936 if (!info
->pszPolicyIdentifier
)
2938 SetLastError(E_INVALIDARG
);
2941 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2945 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2946 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2947 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2953 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2954 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2957 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2959 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2960 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2963 bytesNeeded
+= size
;
2965 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2966 bytesNeeded
+= 1 + lenBytes
;
2970 *pcbEncoded
= bytesNeeded
;
2973 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2974 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2978 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2979 pbEncoded
= *(BYTE
**)pbEncoded
;
2981 *out
++ = ASN_SEQUENCEOF
;
2982 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2984 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2987 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2988 &info
->rgPolicyInfo
[i
],
2989 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
2993 bytesNeeded
-= size
;
2996 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2997 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3004 SetLastError(STATUS_ACCESS_VIOLATION
);
3010 static BOOL
CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType
,
3011 const CERT_POLICY_MAPPING
*mapping
, DWORD dwFlags
, BYTE
*pbEncoded
,
3014 struct AsnEncodeSequenceItem items
[] = {
3015 { mapping
->pszIssuerDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3016 { mapping
->pszSubjectDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3019 if (!mapping
->pszIssuerDomainPolicy
|| !mapping
->pszSubjectDomainPolicy
)
3021 SetLastError(E_INVALIDARG
);
3024 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3027 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType
,
3028 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3029 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3035 const CERT_POLICY_MAPPINGS_INFO
*info
= pvStructInfo
;
3036 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3039 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3041 ret
= CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType
,
3042 &info
->rgPolicyMapping
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
3045 bytesNeeded
+= size
;
3047 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3048 bytesNeeded
+= 1 + lenBytes
;
3052 *pcbEncoded
= bytesNeeded
;
3055 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3056 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3060 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3061 pbEncoded
= *(BYTE
**)pbEncoded
;
3063 *out
++ = ASN_SEQUENCEOF
;
3064 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3066 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3069 ret
= CRYPT_AsnEncodeCertPolicyMapping(
3070 dwCertEncodingType
, &info
->rgPolicyMapping
[i
],
3071 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
3075 bytesNeeded
-= size
;
3078 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3079 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3086 SetLastError(STATUS_ACCESS_VIOLATION
);
3092 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyConstraints(
3093 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3094 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3101 const CERT_POLICY_CONSTRAINTS_INFO
*info
= pvStructInfo
;
3102 struct AsnEncodeSequenceItem items
[2];
3103 struct AsnEncodeTagSwappedItem swapped
[2];
3104 DWORD cItem
= 0, cSwapped
= 0;
3106 if (info
->fRequireExplicitPolicy
)
3108 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3109 swapped
[cSwapped
].pvStructInfo
=
3110 &info
->dwRequireExplicitPolicySkipCerts
;
3111 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3112 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3113 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3117 if (info
->fInhibitPolicyMapping
)
3119 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3120 swapped
[cSwapped
].pvStructInfo
=
3121 &info
->dwInhibitPolicyMappingSkipCerts
;
3122 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3123 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3124 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3128 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3129 dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3133 SetLastError(STATUS_ACCESS_VIOLATION
);
3139 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
3140 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3141 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3147 const BLOBHEADER
*hdr
= pvStructInfo
;
3149 if (hdr
->bType
!= PUBLICKEYBLOB
)
3151 SetLastError(E_INVALIDARG
);
3156 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
3157 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
3158 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
3159 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
3160 struct AsnEncodeSequenceItem items
[] = {
3161 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3162 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
3165 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3166 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3171 SetLastError(STATUS_ACCESS_VIOLATION
);
3178 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
3179 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3180 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3186 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
3187 DWORD bytesNeeded
, lenBytes
;
3189 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3190 dwFlags
, pEncodePara
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
3192 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3193 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3196 *pcbEncoded
= bytesNeeded
;
3201 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3202 pcbEncoded
, bytesNeeded
)))
3204 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3205 pbEncoded
= *(BYTE
**)pbEncoded
;
3206 *pbEncoded
++ = ASN_OCTETSTRING
;
3207 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3208 pbEncoded
+= lenBytes
;
3210 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3216 SetLastError(STATUS_ACCESS_VIOLATION
);
3220 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3224 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3225 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3226 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3232 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3233 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3236 /* yep, MS allows cUnusedBits to be >= 8 */
3237 if (!blob
->cUnusedBits
)
3239 dataBytes
= blob
->cbData
;
3242 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3244 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3245 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3253 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3254 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3257 *pcbEncoded
= bytesNeeded
;
3262 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3263 pcbEncoded
, bytesNeeded
)))
3265 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3266 pbEncoded
= *(BYTE
**)pbEncoded
;
3267 *pbEncoded
++ = ASN_BITSTRING
;
3268 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3269 pbEncoded
+= lenBytes
;
3270 *pbEncoded
++ = unusedBits
;
3273 BYTE mask
= 0xff << unusedBits
;
3277 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3278 pbEncoded
+= dataBytes
- 1;
3280 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3287 SetLastError(STATUS_ACCESS_VIOLATION
);
3294 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3295 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3296 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3302 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3303 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3308 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3313 for (i
= 0; i
< newBlob
.cbData
; i
++)
3314 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3320 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3321 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3322 CryptMemFree(newBlob
.pbData
);
3326 SetLastError(STATUS_ACCESS_VIOLATION
);
3333 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3334 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3335 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3337 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3339 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3340 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3343 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3344 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3345 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3351 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3354 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3356 significantBytes
= blob
->cbData
;
3357 if (significantBytes
)
3359 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3361 /* negative, lop off leading (little-endian) 0xffs */
3362 for (; significantBytes
> 0 &&
3363 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3365 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3373 /* positive, lop off leading (little-endian) zeroes */
3374 for (; significantBytes
> 0 &&
3375 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3377 if (significantBytes
== 0)
3378 significantBytes
= 1;
3379 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3387 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3389 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3390 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3395 *pcbEncoded
= bytesNeeded
;
3400 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3401 pcbEncoded
, bytesNeeded
)))
3403 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3404 pbEncoded
= *(BYTE
**)pbEncoded
;
3405 *pbEncoded
++ = ASN_INTEGER
;
3408 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3409 pbEncoded
+= lenBytes
;
3410 *pbEncoded
++ = padByte
;
3414 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3415 pbEncoded
+= lenBytes
;
3417 for (; significantBytes
> 0; significantBytes
--)
3418 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3424 SetLastError(STATUS_ACCESS_VIOLATION
);
3431 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3432 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3433 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3439 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3441 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3443 significantBytes
= blob
->cbData
;
3444 if (significantBytes
)
3446 /* positive, lop off leading (little-endian) zeroes */
3447 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3450 if (significantBytes
== 0)
3451 significantBytes
= 1;
3452 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3456 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3458 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3459 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3464 *pcbEncoded
= bytesNeeded
;
3469 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3470 pcbEncoded
, bytesNeeded
)))
3472 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3473 pbEncoded
= *(BYTE
**)pbEncoded
;
3474 *pbEncoded
++ = ASN_INTEGER
;
3477 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3478 pbEncoded
+= lenBytes
;
3483 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3484 pbEncoded
+= lenBytes
;
3486 for (; significantBytes
> 0; significantBytes
--)
3487 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3493 SetLastError(STATUS_ACCESS_VIOLATION
);
3500 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3501 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3502 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3504 CRYPT_INTEGER_BLOB blob
;
3507 /* Encode as an unsigned integer, then change the tag to enumerated */
3508 blob
.cbData
= sizeof(DWORD
);
3509 blob
.pbData
= (BYTE
*)pvStructInfo
;
3510 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3511 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3512 if (ret
&& pbEncoded
)
3514 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3515 pbEncoded
= *(BYTE
**)pbEncoded
;
3516 pbEncoded
[0] = ASN_ENUMERATED
;
3521 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3522 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3523 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3530 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a
3531 * temporary buffer because the output buffer is not NULL-terminated.
3533 static const DWORD bytesNeeded
= 15;
3538 *pcbEncoded
= bytesNeeded
;
3543 /* Sanity check the year, this is a two-digit year format */
3544 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3545 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3547 SetLastError(CRYPT_E_BAD_ENCODE
);
3552 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3553 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3555 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3556 pbEncoded
= *(BYTE
**)pbEncoded
;
3557 buf
[0] = ASN_UTCTIME
;
3558 buf
[1] = bytesNeeded
- 2;
3559 snprintf(buf
+ 2, sizeof(buf
) - 2,
3560 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3561 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3562 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3563 sysTime
.wMinute
, sysTime
.wSecond
);
3564 memcpy(pbEncoded
, buf
, bytesNeeded
);
3571 SetLastError(STATUS_ACCESS_VIOLATION
);
3578 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3579 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3580 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3587 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a
3588 * temporary buffer because the output buffer is not NULL-terminated.
3590 static const DWORD bytesNeeded
= 17;
3595 *pcbEncoded
= bytesNeeded
;
3600 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3602 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3603 pcbEncoded
, bytesNeeded
);
3606 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3607 pbEncoded
= *(BYTE
**)pbEncoded
;
3608 buf
[0] = ASN_GENERALTIME
;
3609 buf
[1] = bytesNeeded
- 2;
3610 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3611 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3612 sysTime
.wMinute
, sysTime
.wSecond
);
3613 memcpy(pbEncoded
, buf
, bytesNeeded
);
3619 SetLastError(STATUS_ACCESS_VIOLATION
);
3626 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3627 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3628 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3636 /* Check the year, if it's in the UTCTime range call that encode func */
3637 if (!FileTimeToSystemTime(pvStructInfo
, &sysTime
))
3639 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3640 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3641 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3643 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3644 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3649 SetLastError(STATUS_ACCESS_VIOLATION
);
3656 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3657 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3658 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3664 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3665 const CRYPT_SEQUENCE_OF_ANY
*seq
= pvStructInfo
;
3667 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3668 dataLen
+= seq
->rgValue
[i
].cbData
;
3669 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3670 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3673 *pcbEncoded
= bytesNeeded
;
3678 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3679 pcbEncoded
, bytesNeeded
)))
3681 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3682 pbEncoded
= *(BYTE
**)pbEncoded
;
3683 *pbEncoded
++ = ASN_SEQUENCEOF
;
3684 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3685 pbEncoded
+= lenBytes
;
3686 for (i
= 0; i
< seq
->cValue
; i
++)
3688 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3689 seq
->rgValue
[i
].cbData
);
3690 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3697 SetLastError(STATUS_ACCESS_VIOLATION
);
3704 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3705 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3708 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3709 struct AsnConstructedItem constructed
= { 0 };
3710 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3711 DWORD cItem
= 0, cSwapped
= 0;
3713 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3715 case CRL_DIST_POINT_NO_NAME
:
3718 case CRL_DIST_POINT_FULL_NAME
:
3719 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3720 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3721 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3722 constructed
.tag
= 0;
3723 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3724 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3725 items
[cItem
].pvStructInfo
= &constructed
;
3726 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3730 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3731 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3737 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3739 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3740 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3741 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3742 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3743 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3747 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3749 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3750 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3751 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3752 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3753 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3758 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3759 pbEncoded
, pcbEncoded
);
3763 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3764 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3765 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3771 const CRL_DIST_POINTS_INFO
*info
= pvStructInfo
;
3773 if (!info
->cDistPoint
)
3775 SetLastError(E_INVALIDARG
);
3780 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3783 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3787 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3791 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3793 /* Have to propagate index of failing character */
3799 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3800 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3803 *pcbEncoded
= bytesNeeded
;
3808 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3809 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3813 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3814 pbEncoded
= *(BYTE
**)pbEncoded
;
3816 *out
++ = ASN_SEQUENCEOF
;
3817 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
3819 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3821 DWORD len
= dataLen
;
3823 ret
= CRYPT_AsnEncodeDistPoint(
3824 &info
->rgDistPoint
[i
], out
, &len
);
3831 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3832 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3840 SetLastError(STATUS_ACCESS_VIOLATION
);
3847 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3848 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3849 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3855 const CERT_ENHKEY_USAGE
*usage
= pvStructInfo
;
3856 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3859 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3861 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3862 usage
->rgpszUsageIdentifier
[i
],
3863 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3865 bytesNeeded
+= size
;
3867 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3868 bytesNeeded
+= 1 + lenBytes
;
3872 *pcbEncoded
= bytesNeeded
;
3875 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3876 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3880 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3881 pbEncoded
= *(BYTE
**)pbEncoded
;
3883 *out
++ = ASN_SEQUENCEOF
;
3884 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3886 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3889 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3890 usage
->rgpszUsageIdentifier
[i
],
3891 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
3895 bytesNeeded
-= size
;
3898 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3899 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3906 SetLastError(STATUS_ACCESS_VIOLATION
);
3913 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3914 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3915 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3921 const CRL_ISSUING_DIST_POINT
*point
= pvStructInfo
;
3922 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3923 struct AsnConstructedItem constructed
= { 0 };
3924 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3925 DWORD cItem
= 0, cSwapped
= 0;
3928 switch (point
->DistPointName
.dwDistPointNameChoice
)
3930 case CRL_DIST_POINT_NO_NAME
:
3933 case CRL_DIST_POINT_FULL_NAME
:
3934 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3935 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3936 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3937 constructed
.tag
= 0;
3938 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3939 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3940 items
[cItem
].pvStructInfo
= &constructed
;
3941 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3946 SetLastError(E_INVALIDARG
);
3949 if (ret
&& point
->fOnlyContainsUserCerts
)
3951 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3952 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3953 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3954 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3955 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3959 if (ret
&& point
->fOnlyContainsCACerts
)
3961 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3962 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3963 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3964 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3965 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3969 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3971 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3972 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3973 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3974 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3975 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3979 if (ret
&& point
->fIndirectCRL
)
3981 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3982 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3983 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3984 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3985 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3990 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3991 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3995 SetLastError(STATUS_ACCESS_VIOLATION
);
4002 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
4003 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4004 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4007 const CERT_GENERAL_SUBTREE
*subtree
= pvStructInfo
;
4008 struct AsnEncodeSequenceItem items
[3] = {
4009 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
4012 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4013 DWORD cItem
= 1, cSwapped
= 0;
4015 if (subtree
->dwMinimum
)
4017 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4018 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
4019 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4020 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4021 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4025 if (subtree
->fMaximum
)
4027 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
4028 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
4029 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4030 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4031 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4035 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
4036 pEncodePara
, pbEncoded
, pcbEncoded
);
4040 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
4041 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4042 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4045 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
4047 TRACE("%p\n", pvStructInfo
);
4051 const CERT_NAME_CONSTRAINTS_INFO
*constraints
= pvStructInfo
;
4052 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
4053 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4054 DWORD i
, cItem
= 0, cSwapped
= 0;
4057 if (constraints
->cPermittedSubtree
)
4059 permitted
.rgBlob
= CryptMemAlloc(
4060 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
4061 if (permitted
.rgBlob
)
4063 permitted
.cBlob
= constraints
->cPermittedSubtree
;
4064 memset(permitted
.rgBlob
, 0,
4065 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4066 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
4067 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4068 NULL
, &constraints
->rgPermittedSubtree
[i
],
4069 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4070 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
4071 &permitted
.rgBlob
[i
].cbData
);
4074 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4075 swapped
[cSwapped
].pvStructInfo
= &permitted
;
4076 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4077 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4078 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4086 if (constraints
->cExcludedSubtree
)
4088 excluded
.rgBlob
= CryptMemAlloc(
4089 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
4090 if (excluded
.rgBlob
)
4092 excluded
.cBlob
= constraints
->cExcludedSubtree
;
4093 memset(excluded
.rgBlob
, 0,
4094 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4095 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
4096 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4097 NULL
, &constraints
->rgExcludedSubtree
[i
],
4098 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4099 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
4100 &excluded
.rgBlob
[i
].cbData
);
4103 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4104 swapped
[cSwapped
].pvStructInfo
= &excluded
;
4105 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4106 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4107 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4116 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4117 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4118 for (i
= 0; i
< permitted
.cBlob
; i
++)
4119 LocalFree(permitted
.rgBlob
[i
].pbData
);
4120 for (i
= 0; i
< excluded
.cBlob
; i
++)
4121 LocalFree(excluded
.rgBlob
[i
].pbData
);
4125 SetLastError(STATUS_ACCESS_VIOLATION
);
4128 CryptMemFree(permitted
.rgBlob
);
4129 CryptMemFree(excluded
.rgBlob
);
4130 TRACE("returning %d\n", ret
);
4134 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
4135 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
4136 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
4140 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
= pvStructInfo
;
4141 struct AsnEncodeSequenceItem items
[] = {
4142 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
4143 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
4146 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4147 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4151 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
4152 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4153 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4157 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4159 SetLastError(E_INVALIDARG
);
4165 const CMSG_SIGNER_INFO
*info
= pvStructInfo
;
4167 if (!info
->Issuer
.cbData
)
4168 SetLastError(E_INVALIDARG
);
4171 struct AsnEncodeSequenceItem items
[7] = {
4172 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4173 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4174 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
4177 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4178 DWORD cItem
= 3, cSwapped
= 0;
4180 if (info
->AuthAttrs
.cAttr
)
4182 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4183 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4184 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4185 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4186 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4190 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4191 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4193 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4194 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4196 if (info
->UnauthAttrs
.cAttr
)
4198 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4199 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4200 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4201 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4202 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4206 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4207 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4212 SetLastError(STATUS_ACCESS_VIOLATION
);
4218 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4219 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4220 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4224 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4226 SetLastError(E_INVALIDARG
);
4232 const CMSG_CMS_SIGNER_INFO
*info
= pvStructInfo
;
4234 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4235 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4236 SetLastError(E_INVALIDARG
);
4237 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4238 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4239 SetLastError(E_INVALIDARG
);
4242 struct AsnEncodeSequenceItem items
[7] = {
4243 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4245 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4246 DWORD cItem
= 1, cSwapped
= 0;
4248 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4250 items
[cItem
].pvStructInfo
=
4251 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4252 items
[cItem
].encodeFunc
=
4253 CRYPT_AsnEncodeIssuerSerialNumber
;
4258 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4259 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4260 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4261 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4262 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4266 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4267 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4269 if (info
->AuthAttrs
.cAttr
)
4271 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4272 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4273 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4274 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4275 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4279 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4280 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4282 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4283 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4285 if (info
->UnauthAttrs
.cAttr
)
4287 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4288 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4289 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4290 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4291 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4295 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4296 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4301 SetLastError(STATUS_ACCESS_VIOLATION
);
4307 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4310 struct AsnEncodeSequenceItem items
[7] = {
4311 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4313 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4314 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4315 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4316 DWORD cItem
= 1, cSwapped
= 0;
4319 if (signedInfo
->cSignerInfo
)
4321 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4322 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4323 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4324 digestAlgorithmsSet
.itemOffset
=
4325 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4326 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4327 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4328 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4331 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4332 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4334 if (signedInfo
->cCertEncoded
)
4336 certSet
.cItems
= signedInfo
->cCertEncoded
;
4337 certSet
.items
= signedInfo
->rgCertEncoded
;
4338 certSet
.itemSize
= sizeof(CERT_BLOB
);
4339 certSet
.itemOffset
= 0;
4340 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4341 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4342 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4343 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4344 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4345 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4349 if (signedInfo
->cCrlEncoded
)
4351 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4352 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4353 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4354 crlSet
.itemOffset
= 0;
4355 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4356 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4357 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4358 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4359 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4360 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4364 if (ret
&& signedInfo
->cSignerInfo
)
4366 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4367 signerSet
.items
= signedInfo
->rgSignerInfo
;
4368 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4369 signerSet
.itemOffset
= 0;
4370 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4371 items
[cItem
].pvStructInfo
= &signerSet
;
4372 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4376 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4377 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4382 static BOOL WINAPI
CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType
,
4383 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4384 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4386 const CMSG_KEY_TRANS_RECIPIENT_INFO
*info
= pvStructInfo
;
4387 struct AsnEncodeSequenceItem items
[] = {
4388 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4389 { &info
->RecipientId
.u
.IssuerSerialNumber
,
4390 CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4391 { &info
->KeyEncryptionAlgorithm
,
4392 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4393 { &info
->EncryptedKey
, CRYPT_AsnEncodeOctets
, 0 },
4396 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4397 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4400 static BOOL WINAPI
CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType
,
4401 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4402 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4404 const CRYPT_ENCRYPTED_CONTENT_INFO
*info
= pvStructInfo
;
4405 struct AsnEncodeTagSwappedItem swapped
= { ASN_CONTEXT
| 0,
4406 &info
->encryptedContent
, CRYPT_AsnEncodeOctets
};
4407 struct AsnEncodeSequenceItem items
[] = {
4408 { info
->contentType
, CRYPT_AsnEncodeOid
, 0 },
4409 { &info
->contentEncryptionAlgorithm
,
4410 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4411 { &swapped
, CRYPT_AsnEncodeSwapTag
, 0 },
4414 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4415 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4418 BOOL
CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA
*envelopedData
,
4419 void *pvData
, DWORD
*pcbData
)
4421 struct DERSetDescriptor recipientInfosSet
= { envelopedData
->cRecipientInfo
,
4422 envelopedData
->rgRecipientInfo
, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
), 0,
4423 CRYPT_AsnEncodeRecipientInfo
};
4424 struct AsnEncodeSequenceItem items
[] = {
4425 { &envelopedData
->version
, CRYPT_AsnEncodeInt
, 0 },
4426 { &recipientInfosSet
, CRYPT_DEREncodeItemsAsSet
, 0 },
4427 { &envelopedData
->encryptedContentInfo
,
4428 CRYPT_AsnEncodeEncryptedContentInfo
, 0 },
4431 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
4432 ARRAY_SIZE(items
), 0, NULL
, pvData
, pcbData
);
4435 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4436 LPCSTR lpszStructType
)
4438 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4440 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4441 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4443 SetLastError(ERROR_FILE_NOT_FOUND
);
4447 if (IS_INTOID(lpszStructType
))
4449 switch (LOWORD(lpszStructType
))
4451 case LOWORD(X509_CERT
):
4452 encodeFunc
= CRYPT_AsnEncodeCert
;
4454 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4455 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4457 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4458 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4460 case LOWORD(X509_EXTENSIONS
):
4461 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4463 case LOWORD(X509_NAME_VALUE
):
4464 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4466 case LOWORD(X509_NAME
):
4467 encodeFunc
= CRYPT_AsnEncodeName
;
4469 case LOWORD(X509_PUBLIC_KEY_INFO
):
4470 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4472 case LOWORD(X509_AUTHORITY_KEY_ID
):
4473 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4475 case LOWORD(X509_ALTERNATE_NAME
):
4476 encodeFunc
= CRYPT_AsnEncodeAltName
;
4478 case LOWORD(X509_BASIC_CONSTRAINTS
):
4479 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4481 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4482 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4484 case LOWORD(X509_CERT_POLICIES
):
4485 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4487 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4488 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4490 case LOWORD(X509_UNICODE_NAME
):
4491 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4493 case LOWORD(PKCS_CONTENT_INFO
):
4494 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4496 case LOWORD(PKCS_ATTRIBUTE
):
4497 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4499 case LOWORD(X509_UNICODE_NAME_VALUE
):
4500 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4502 case LOWORD(X509_OCTET_STRING
):
4503 encodeFunc
= CRYPT_AsnEncodeOctets
;
4505 case LOWORD(X509_BITS
):
4506 case LOWORD(X509_KEY_USAGE
):
4507 encodeFunc
= CRYPT_AsnEncodeBits
;
4509 case LOWORD(X509_INTEGER
):
4510 encodeFunc
= CRYPT_AsnEncodeInt
;
4512 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4513 encodeFunc
= CRYPT_AsnEncodeInteger
;
4515 case LOWORD(X509_MULTI_BYTE_UINT
):
4516 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4518 case LOWORD(X509_ENUMERATED
):
4519 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4521 case LOWORD(X509_CHOICE_OF_TIME
):
4522 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4524 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4525 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4527 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4528 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4530 case LOWORD(X509_SEQUENCE_OF_ANY
):
4531 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4533 case LOWORD(PKCS_UTC_TIME
):
4534 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4536 case LOWORD(X509_CRL_DIST_POINTS
):
4537 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4539 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4540 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4542 case LOWORD(PKCS_CTL
):
4543 encodeFunc
= CRYPT_AsnEncodeCTL
;
4545 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4546 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4548 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4549 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4551 case LOWORD(PKCS_ATTRIBUTES
):
4552 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4554 case LOWORD(X509_ISSUING_DIST_POINT
):
4555 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4557 case LOWORD(X509_NAME_CONSTRAINTS
):
4558 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4560 case LOWORD(X509_POLICY_MAPPINGS
):
4561 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4563 case LOWORD(X509_POLICY_CONSTRAINTS
):
4564 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4566 case LOWORD(PKCS7_SIGNER_INFO
):
4567 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4569 case LOWORD(CMS_SIGNER_INFO
):
4570 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4574 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4575 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4576 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4577 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4578 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4579 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4580 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4581 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4582 else if (!strcmp(lpszStructType
, szOID_LEGACY_POLICY_MAPPINGS
))
4583 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4584 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4585 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4586 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4587 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4588 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4589 encodeFunc
= CRYPT_AsnEncodeBits
;
4590 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4591 encodeFunc
= CRYPT_AsnEncodeOctets
;
4592 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4593 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4594 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4595 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4596 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4597 encodeFunc
= CRYPT_AsnEncodeAltName
;
4598 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4599 encodeFunc
= CRYPT_AsnEncodeAltName
;
4600 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4601 encodeFunc
= CRYPT_AsnEncodeAltName
;
4602 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4603 encodeFunc
= CRYPT_AsnEncodeAltName
;
4604 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4605 encodeFunc
= CRYPT_AsnEncodeAltName
;
4606 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4607 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4608 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4609 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4610 else if (!strcmp(lpszStructType
, szOID_POLICY_MAPPINGS
))
4611 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4612 else if (!strcmp(lpszStructType
, szOID_POLICY_CONSTRAINTS
))
4613 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4614 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4615 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4616 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4617 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4618 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4619 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4620 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4621 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4622 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4623 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4624 else if (!strcmp(lpszStructType
, szOID_CTL
))
4625 encodeFunc
= CRYPT_AsnEncodeCTL
;
4629 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4630 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4632 static HCRYPTOIDFUNCSET set
= NULL
;
4633 CryptEncodeObjectFunc encodeFunc
= NULL
;
4636 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4637 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4638 (void **)&encodeFunc
, hFunc
);
4642 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4643 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4645 static HCRYPTOIDFUNCSET set
= NULL
;
4646 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4649 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4650 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4651 (void **)&encodeFunc
, hFunc
);
4655 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4656 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4659 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4660 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4661 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4663 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4664 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4667 if (!pbEncoded
&& !pcbEncoded
)
4669 SetLastError(ERROR_INVALID_PARAMETER
);
4673 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4676 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4677 debugstr_a(lpszStructType
));
4678 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4679 lpszStructType
, &hFunc
);
4680 if (!pCryptEncodeObject
)
4681 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4682 lpszStructType
, &hFunc
);
4684 if (pCryptEncodeObject
)
4685 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4686 pvStructInfo
, pbEncoded
, pcbEncoded
);
4687 else if (pCryptEncodeObjectEx
)
4688 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4689 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4691 CryptFreeOIDFunctionAddress(hFunc
, 0);
4692 TRACE_(crypt
)("returning %d\n", ret
);
4696 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4697 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4698 void *pvEncoded
, DWORD
*pcbEncoded
)
4701 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4702 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4704 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4705 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4706 pvEncoded
, pcbEncoded
);
4708 if (!pvEncoded
&& !pcbEncoded
)
4710 SetLastError(ERROR_INVALID_PARAMETER
);
4714 SetLastError(NOERROR
);
4715 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
) {
4717 SetLastError(ERROR_INVALID_PARAMETER
);
4720 *(BYTE
**)pvEncoded
= NULL
;
4722 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4725 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4726 debugstr_a(lpszStructType
));
4727 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4731 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4732 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4735 CryptEncodeObjectFunc pCryptEncodeObject
=
4736 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4738 if (pCryptEncodeObject
)
4740 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4742 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4743 pvStructInfo
, NULL
, pcbEncoded
);
4744 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4745 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4746 ret
= pCryptEncodeObject(dwCertEncodingType
,
4747 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4751 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4752 pvStructInfo
, pvEncoded
, pcbEncoded
);
4756 CryptFreeOIDFunctionAddress(hFunc
, 0);
4757 TRACE_(crypt
)("returning %d\n", ret
);
4761 BOOL WINAPI
PFXExportCertStore(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4762 LPCWSTR szPassword
, DWORD dwFlags
)
4764 return PFXExportCertStoreEx(hStore
, pPFX
, szPassword
, NULL
, dwFlags
);
4767 BOOL WINAPI
PFXExportCertStoreEx(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4768 LPCWSTR szPassword
, void *pvReserved
, DWORD dwFlags
)
4770 FIXME_(crypt
)("(%p, %p, %p, %p, %08x): stub\n", hStore
, pPFX
, szPassword
,
4771 pvReserved
, dwFlags
);
4775 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4776 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4778 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4779 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4782 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4783 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4784 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4788 static CHAR oid
[] = szOID_RSA_RSA
;
4790 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4791 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4792 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4794 if (!pszPublicKeyObjId
)
4795 pszPublicKeyObjId
= oid
;
4796 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4800 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4803 LPBYTE pubKey
= CryptMemAlloc(keySize
);
4807 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4811 DWORD encodedLen
= 0;
4813 ret
= CryptEncodeObject(dwCertEncodingType
,
4814 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4817 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4818 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4821 *pcbInfo
= sizeNeeded
;
4822 else if (*pcbInfo
< sizeNeeded
)
4824 SetLastError(ERROR_MORE_DATA
);
4825 *pcbInfo
= sizeNeeded
;
4830 *pcbInfo
= sizeNeeded
;
4831 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4832 sizeof(CERT_PUBLIC_KEY_INFO
);
4833 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4835 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4836 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4837 pInfo
->PublicKey
.pbData
=
4838 (BYTE
*)pInfo
->Algorithm
.pszObjId
4839 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4840 pInfo
->PublicKey
.cbData
= encodedLen
;
4841 pInfo
->PublicKey
.cUnusedBits
= 0;
4842 ret
= CryptEncodeObject(dwCertEncodingType
,
4843 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4844 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4848 CryptMemFree(pubKey
);
4853 CryptDestroyKey(key
);
4858 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4859 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4860 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4862 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4863 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4864 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4866 static HCRYPTOIDFUNCSET set
= NULL
;
4868 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4869 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4871 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4872 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4873 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4877 SetLastError(ERROR_INVALID_PARAMETER
);
4881 if (pszPublicKeyObjId
)
4884 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4886 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4887 0, (void **)&exportFunc
, &hFunc
);
4890 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4891 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4892 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4894 CryptFreeOIDFunctionAddress(hFunc
, 0);
4898 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4899 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4901 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4905 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4906 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4907 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4910 DWORD pubKeySize
= 0;
4912 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4913 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4915 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4916 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4919 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4923 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4924 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4929 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4930 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4933 CryptMemFree(pubKey
);
4941 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4942 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4943 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4945 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4946 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4947 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4949 static HCRYPTOIDFUNCSET set
= NULL
;
4951 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4952 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4954 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4955 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4958 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4959 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4960 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4962 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4963 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4966 CryptFreeOIDFunctionAddress(hFunc
, 0);