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"
42 #include "wine/debug.h"
43 #include "wine/exception.h"
44 #include "crypt32_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
47 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
49 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
52 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
53 * The dwCertEncodingType and lpszStructType are ignored by the built-in
54 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
55 * since it must call functions in external DLLs that follow these signatures.
57 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
58 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
59 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
60 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
61 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
62 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
63 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
93 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
95 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
97 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
,
98 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
102 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
104 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
105 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
107 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
108 if (!*(BYTE
**)pbEncoded
)
111 *pcbEncoded
= bytesNeeded
;
113 else if (bytesNeeded
> *pcbEncoded
)
115 *pcbEncoded
= bytesNeeded
;
116 SetLastError(ERROR_MORE_DATA
);
120 *pcbEncoded
= bytesNeeded
;
124 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA
*pEncodePara
, LPVOID pv
)
126 if (pEncodePara
&& pEncodePara
->pfnFree
)
127 pEncodePara
->pfnFree(pv
);
132 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
134 DWORD bytesNeeded
, significantBytes
= 0;
142 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
143 temp
<<= 8, significantBytes
--)
145 bytesNeeded
= significantBytes
+ 1;
149 *pcbEncoded
= bytesNeeded
;
152 if (*pcbEncoded
< bytesNeeded
)
154 SetLastError(ERROR_MORE_DATA
);
158 *pbEncoded
= (BYTE
)len
;
163 *pbEncoded
++ = significantBytes
| 0x80;
164 for (i
= 0; i
< significantBytes
; i
++)
166 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
170 *pcbEncoded
= bytesNeeded
;
174 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
175 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
176 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
179 DWORD i
, dataLen
= 0;
181 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
182 pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
183 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
185 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
186 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
187 NULL
, &items
[i
].size
);
188 /* Some functions propagate their errors through the size */
190 *pcbEncoded
= items
[i
].size
;
191 dataLen
+= items
[i
].size
;
195 DWORD lenBytes
, bytesNeeded
;
197 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
198 bytesNeeded
= 1 + lenBytes
+ dataLen
;
200 *pcbEncoded
= bytesNeeded
;
203 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
204 pcbEncoded
, bytesNeeded
)))
208 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
209 pbEncoded
= *(BYTE
**)pbEncoded
;
211 *out
++ = ASN_SEQUENCE
;
212 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
214 for (i
= 0; ret
&& i
< cItem
; i
++)
216 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
217 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
218 NULL
, out
, &items
[i
].size
);
219 /* Some functions propagate their errors through the size */
221 *pcbEncoded
= items
[i
].size
;
222 out
+= items
[i
].size
;
224 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
225 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
229 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
233 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
234 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
235 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
238 const struct AsnConstructedItem
*item
= pvStructInfo
;
241 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
242 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
244 DWORD dataLen
, bytesNeeded
;
246 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
247 bytesNeeded
= 1 + dataLen
+ len
;
249 *pcbEncoded
= bytesNeeded
;
250 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
251 pbEncoded
, pcbEncoded
, bytesNeeded
)))
255 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
256 pbEncoded
= *(BYTE
**)pbEncoded
;
258 *out
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
259 CRYPT_EncodeLen(len
, out
, &dataLen
);
261 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
262 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
266 /* Some functions propagate their errors through the size */
268 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
269 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
275 /* Some functions propagate their errors through the size */
281 struct AsnEncodeTagSwappedItem
284 const void *pvStructInfo
;
285 CryptEncodeObjectExFunc encodeFunc
;
288 /* Sort of a wacky hack, it encodes something using the struct
289 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
290 * given in the struct AsnEncodeTagSwappedItem.
292 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
293 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
294 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
297 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
299 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
300 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
301 if (ret
&& pbEncoded
)
302 *pbEncoded
= item
->tag
;
306 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
307 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
308 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
310 const DWORD
*ver
= pvStructInfo
;
313 /* CERT_V1 is not encoded */
321 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
323 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
324 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
329 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
330 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
331 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
333 const CRYPT_DER_BLOB
*blob
= pvStructInfo
;
338 *pcbEncoded
= blob
->cbData
;
343 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
344 pcbEncoded
, blob
->cbData
)))
346 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
347 pbEncoded
= *(BYTE
**)pbEncoded
;
349 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
350 *pcbEncoded
= blob
->cbData
;
356 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
357 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
358 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
361 /* This has two filetimes in a row, a NotBefore and a NotAfter */
362 const FILETIME
*timePtr
= pvStructInfo
;
363 struct AsnEncodeSequenceItem items
[] = {
364 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
365 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
368 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
369 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
374 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
377 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
378 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
379 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
382 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
383 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
384 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
387 struct AsnEncodeSequenceItem items
[2] = {
388 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
389 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
392 if (algo
->Parameters
.cbData
)
393 items
[1].pvStructInfo
= &algo
->Parameters
;
395 items
[1].pvStructInfo
= &nullBlob
;
396 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
397 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
402 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
403 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
404 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
406 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
408 struct AsnEncodeSequenceItem items
[] = {
409 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
410 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
413 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
414 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
419 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
420 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
421 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
427 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
428 struct AsnEncodeSequenceItem items
[] = {
429 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
430 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
433 TRACE("Encoding public key with OID %s\n",
434 debugstr_a(info
->Algorithm
.pszObjId
));
435 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
436 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
441 SetLastError(STATUS_ACCESS_VIOLATION
);
448 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
449 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
450 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
456 const CERT_SIGNED_CONTENT_INFO
*info
= pvStructInfo
;
457 struct AsnEncodeSequenceItem items
[] = {
458 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
459 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
460 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
463 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
464 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
465 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
466 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
471 SetLastError(STATUS_ACCESS_VIOLATION
);
478 BOOL WINAPI
CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType
,
479 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
480 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
483 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
484 struct AsnEncodeSequenceItem items
[] = {
485 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
486 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
489 TRACE("Encoding public key with OID %s\n",
490 debugstr_a(info
->Algorithm
.pszObjId
));
491 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
492 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
497 /* Like in Windows, this blithely ignores the validity of the passed-in
498 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
499 * decode properly, see CRYPT_AsnDecodeCertInfo.
501 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
502 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
503 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
509 const CERT_INFO
*info
= pvStructInfo
;
510 struct AsnEncodeSequenceItem items
[10] = {
511 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
512 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
513 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
514 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
515 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
516 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
517 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfoNoNull
, 0 },
520 struct AsnConstructedItem constructed
= { 0 };
521 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
522 DWORD cItem
= 7, cSwapped
= 0;
524 if (info
->IssuerUniqueId
.cbData
)
526 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
527 swapped
[cSwapped
].pvStructInfo
= &info
->IssuerUniqueId
;
528 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
529 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
530 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
534 if (info
->SubjectUniqueId
.cbData
)
536 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
537 swapped
[cSwapped
].pvStructInfo
= &info
->SubjectUniqueId
;
538 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
539 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
540 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
544 if (info
->cExtension
)
547 constructed
.pvStructInfo
= &info
->cExtension
;
548 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
549 items
[cItem
].pvStructInfo
= &constructed
;
550 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
554 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
555 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
559 SetLastError(STATUS_ACCESS_VIOLATION
);
566 static BOOL
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
567 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
569 struct AsnEncodeSequenceItem items
[3] = {
570 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
571 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
577 TRACE("%p, %p, %ld\n", entry
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
579 if (entry
->cExtension
)
581 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
582 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
586 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
587 pbEncoded
, pcbEncoded
);
589 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
593 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
594 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
595 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
597 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
598 const CRL_INFO
*info
= pvStructInfo
;
599 const CRL_ENTRY
*rgCRLEntry
= info
->rgCRLEntry
;
602 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cCRLEntry
; i
++)
606 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
612 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
613 bytesNeeded
= 1 + lenBytes
+ dataLen
;
615 *pcbEncoded
= bytesNeeded
;
618 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
619 pcbEncoded
, bytesNeeded
)))
623 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
624 pbEncoded
= *(BYTE
**)pbEncoded
;
626 *out
++ = ASN_SEQUENCEOF
;
627 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
629 for (i
= 0; i
< info
->cCRLEntry
; i
++)
631 DWORD size
= dataLen
;
633 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], out
, &size
);
637 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
638 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
645 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
646 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
647 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
649 const DWORD
*ver
= pvStructInfo
;
652 /* CRL_V1 is not encoded */
659 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
660 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
664 /* Like in Windows, this blithely ignores the validity of the passed-in
665 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
666 * decode properly, see CRYPT_AsnDecodeCRLInfo.
668 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
669 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
670 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
676 const CRL_INFO
*info
= pvStructInfo
;
677 struct AsnEncodeSequenceItem items
[7] = {
678 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
679 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
680 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
681 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
684 struct AsnConstructedItem constructed
[1] = { { 0 } };
685 DWORD cItem
= 4, cConstructed
= 0;
687 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
689 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
690 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
695 items
[cItem
].pvStructInfo
= info
;
696 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
699 if (info
->cExtension
)
701 constructed
[cConstructed
].tag
= 0;
702 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
703 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
704 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
705 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
710 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
711 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
715 SetLastError(STATUS_ACCESS_VIOLATION
);
722 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
726 struct AsnEncodeSequenceItem items
[3] = {
727 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
733 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
737 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
738 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
741 items
[cItem
].pvStructInfo
= &ext
->Value
;
742 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
745 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
746 pbEncoded
, pcbEncoded
);
747 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
751 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
752 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
753 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
759 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
760 const CERT_EXTENSIONS
*exts
= pvStructInfo
;
763 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
767 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
773 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
774 bytesNeeded
= 1 + lenBytes
+ dataLen
;
776 *pcbEncoded
= bytesNeeded
;
779 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
780 pbEncoded
, pcbEncoded
, bytesNeeded
)))
784 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
785 pbEncoded
= *(BYTE
**)pbEncoded
;
787 *out
++ = ASN_SEQUENCEOF
;
788 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
790 for (i
= 0; i
< exts
->cExtension
; i
++)
792 DWORD size
= dataLen
;
794 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
799 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
800 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
807 SetLastError(STATUS_ACCESS_VIOLATION
);
814 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
815 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
816 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
818 LPCSTR pszObjId
= pvStructInfo
;
819 DWORD bytesNeeded
= 0, lenBytes
;
824 TRACE("%s\n", debugstr_a(pszObjId
));
831 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
833 SetLastError(CRYPT_E_ASN1_ERROR
);
837 firstByte
= val1
* 40 + val2
;
838 ptr
= pszObjId
+ firstPos
;
848 /* note I assume each component is at most 32-bits long in base 2 */
849 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
851 if (val1
>= 0x10000000)
853 else if (val1
>= 0x200000)
855 else if (val1
>= 0x4000)
857 else if (val1
>= 0x80)
867 SetLastError(CRYPT_E_ASN1_ERROR
);
871 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
875 bytesNeeded
+= 1 + lenBytes
;
878 if (*pcbEncoded
< bytesNeeded
)
880 SetLastError(ERROR_MORE_DATA
);
885 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
886 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
887 pbEncoded
+= lenBytes
;
893 *pbEncoded
++ = firstByte
;
894 ptr
= pszObjId
+ firstPos
;
897 sscanf(ptr
, "%d%n", &val
, &pos
);
899 unsigned char outBytes
[5];
902 if (val
>= 0x10000000)
904 else if (val
>= 0x200000)
906 else if (val
>= 0x4000)
908 else if (val
>= 0x80)
912 for (i
= numBytes
; i
> 0; i
--)
914 outBytes
[i
- 1] = val
& 0x7f;
917 for (i
= 0; i
< numBytes
- 1; i
++)
918 *pbEncoded
++ = outBytes
[i
] | 0x80;
919 *pbEncoded
++ = outBytes
[i
];
928 *pcbEncoded
= bytesNeeded
;
932 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
933 BYTE tag
, DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
937 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
938 DWORD bytesNeeded
, lenBytes
, encodedLen
;
940 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
941 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
942 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
944 *pcbEncoded
= bytesNeeded
;
947 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
948 pbEncoded
, pcbEncoded
, bytesNeeded
)))
950 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
951 pbEncoded
= *(BYTE
**)pbEncoded
;
953 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
954 pbEncoded
+= lenBytes
;
955 memcpy(pbEncoded
, str
, encodedLen
);
961 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
962 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
966 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
967 DWORD bytesNeeded
, lenBytes
, strLen
;
969 if (value
->Value
.cbData
)
970 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
971 else if (value
->Value
.pbData
)
972 strLen
= lstrlenW(str
);
975 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
976 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
978 *pcbEncoded
= bytesNeeded
;
981 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
982 pbEncoded
, pcbEncoded
, bytesNeeded
)))
986 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
987 pbEncoded
= *(BYTE
**)pbEncoded
;
988 *pbEncoded
++ = ASN_BMPSTRING
;
989 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
990 pbEncoded
+= lenBytes
;
991 for (i
= 0; i
< strLen
; i
++)
993 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
994 *pbEncoded
++ = str
[i
] & 0x00ff;
1001 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
1002 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
1006 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1007 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
1009 if (value
->Value
.cbData
)
1010 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
1012 strLen
= lstrlenW(str
);
1015 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
1017 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1018 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1020 *pcbEncoded
= bytesNeeded
;
1023 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1024 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1026 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1027 pbEncoded
= *(BYTE
**)pbEncoded
;
1028 *pbEncoded
++ = ASN_UTF8STRING
;
1029 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1030 pbEncoded
+= lenBytes
;
1031 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
1032 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
1038 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1039 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1040 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1046 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1048 switch (value
->dwValueType
)
1050 case CERT_RDN_ANY_TYPE
:
1051 /* explicitly disallowed */
1052 SetLastError(E_INVALIDARG
);
1055 case CERT_RDN_ENCODED_BLOB
:
1056 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1057 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1059 case CERT_RDN_OCTET_STRING
:
1060 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1061 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1063 case CERT_RDN_NUMERIC_STRING
:
1064 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1065 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1067 case CERT_RDN_PRINTABLE_STRING
:
1068 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1069 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1071 case CERT_RDN_TELETEX_STRING
:
1072 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1073 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1075 case CERT_RDN_VIDEOTEX_STRING
:
1076 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1077 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1079 case CERT_RDN_IA5_STRING
:
1080 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1081 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1083 case CERT_RDN_GRAPHIC_STRING
:
1084 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1085 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1087 case CERT_RDN_VISIBLE_STRING
:
1088 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1089 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1091 case CERT_RDN_GENERAL_STRING
:
1092 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1093 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1095 case CERT_RDN_UNIVERSAL_STRING
:
1096 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1097 SetLastError(CRYPT_E_ASN1_CHOICE
);
1100 case CERT_RDN_BMP_STRING
:
1101 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1102 pbEncoded
, pcbEncoded
);
1104 case CERT_RDN_UTF8_STRING
:
1105 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1106 pbEncoded
, pcbEncoded
);
1109 SetLastError(CRYPT_E_ASN1_CHOICE
);
1115 SetLastError(STATUS_ACCESS_VIOLATION
);
1122 static BOOL
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1123 const CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1124 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1126 DWORD bytesNeeded
= 0, lenBytes
, size
;
1129 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1130 0, NULL
, NULL
, &size
);
1133 bytesNeeded
+= size
;
1134 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1135 * with dwValueType, so "cast" it to get its encoded size
1137 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
, &attr
->dwValueType
,
1138 0, NULL
, NULL
, &size
);
1141 bytesNeeded
+= size
;
1142 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1143 bytesNeeded
+= 1 + lenBytes
;
1146 if (*pcbEncoded
< bytesNeeded
)
1148 SetLastError(ERROR_MORE_DATA
);
1153 *pbEncoded
++ = ASN_SEQUENCE
;
1154 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1156 pbEncoded
+= lenBytes
;
1157 size
= bytesNeeded
- 1 - lenBytes
;
1158 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1159 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1163 size
= bytesNeeded
- 1 - lenBytes
- size
;
1164 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1165 &attr
->dwValueType
, 0, NULL
, pbEncoded
, &size
);
1172 *pcbEncoded
= bytesNeeded
;
1176 /* Have to propagate index of failing character */
1183 static int __cdecl
BLOBComp(const void *l
, const void *r
)
1185 const CRYPT_DER_BLOB
*a
= l
, *b
= r
;
1188 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1189 ret
= a
->cbData
- b
->cbData
;
1193 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1195 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1196 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1197 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1199 const CRYPT_BLOB_ARRAY
*set
= pvStructInfo
;
1200 DWORD bytesNeeded
= 0, lenBytes
, i
;
1203 for (i
= 0; i
< set
->cBlob
; i
++)
1204 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1205 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1206 bytesNeeded
+= 1 + lenBytes
;
1209 *pcbEncoded
= bytesNeeded
;
1212 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1213 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1215 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1216 pbEncoded
= *(BYTE
**)pbEncoded
;
1217 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1218 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1219 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1220 pbEncoded
+= lenBytes
;
1221 for (i
= 0; i
< set
->cBlob
; i
++)
1223 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1224 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1230 struct DERSetDescriptor
1236 CryptEncodeObjectExFunc encode
;
1239 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1240 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1241 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1243 const struct DERSetDescriptor
*desc
= pvStructInfo
;
1244 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1250 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1255 setOf
.cBlob
= desc
->cItems
;
1256 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1259 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1261 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1262 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1263 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1266 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1267 if (!setOf
.rgBlob
[i
].pbData
)
1270 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1271 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1272 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1273 &setOf
.rgBlob
[i
].cbData
);
1275 /* Some functions propagate their errors through the size */
1277 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1281 DWORD bytesNeeded
= 0, lenBytes
;
1283 for (i
= 0; i
< setOf
.cBlob
; i
++)
1284 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1285 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1286 bytesNeeded
+= 1 + lenBytes
;
1288 *pcbEncoded
= bytesNeeded
;
1289 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1290 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1292 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1293 pbEncoded
= *(BYTE
**)pbEncoded
;
1294 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1296 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1297 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1298 pbEncoded
+= lenBytes
;
1299 for (i
= 0; i
< setOf
.cBlob
; i
++)
1301 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1302 setOf
.rgBlob
[i
].cbData
);
1303 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1307 for (i
= 0; i
< setOf
.cBlob
; i
++)
1308 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1309 CryptMemFree(setOf
.rgBlob
);
1313 static BOOL
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, const CERT_RDN
*rdn
,
1314 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1318 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1327 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1328 sizeof(CRYPT_DER_BLOB
));
1333 setOf
.cBlob
= rdn
->cRDNAttr
;
1334 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1337 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1339 setOf
.rgBlob
[i
].cbData
= 0;
1340 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1341 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1344 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1345 if (!setOf
.rgBlob
[i
].pbData
)
1348 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1349 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1350 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1354 /* Have to propagate index of failing character */
1355 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1359 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1360 pbEncoded
, pcbEncoded
);
1361 for (i
= 0; i
< setOf
.cBlob
; i
++)
1362 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1366 SetLastError(STATUS_ACCESS_VIOLATION
);
1370 CryptMemFree(setOf
.rgBlob
);
1374 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1375 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1376 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1378 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1379 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1380 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1383 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1386 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1387 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1388 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1390 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1391 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1395 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1396 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1397 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1403 const CERT_NAME_INFO
*info
= pvStructInfo
;
1404 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1406 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1408 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1410 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1411 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1413 bytesNeeded
+= size
;
1417 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1418 bytesNeeded
+= 1 + lenBytes
;
1422 *pcbEncoded
= bytesNeeded
;
1425 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1426 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1430 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1431 pbEncoded
= *(BYTE
**)pbEncoded
;
1433 *out
++ = ASN_SEQUENCEOF
;
1434 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
1436 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1439 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1440 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1445 bytesNeeded
-= size
;
1450 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1451 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1458 SetLastError(STATUS_ACCESS_VIOLATION
);
1465 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1466 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1467 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1469 const DWORD
*ver
= pvStructInfo
;
1472 /* CTL_V1 is not encoded */
1479 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1480 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1484 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1485 * if they are empty and the OID is not empty (otherwise omits them.)
1487 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1488 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1489 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1492 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
1494 struct AsnEncodeSequenceItem items
[2] = {
1495 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1501 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1502 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1505 if (algo
->Parameters
.cbData
)
1506 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1508 items
[cItem
].pvStructInfo
= &nullBlob
;
1509 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1512 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1513 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1517 static BOOL
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1518 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1520 struct AsnEncodeSequenceItem items
[2] = {
1521 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1522 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1526 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1527 ARRAY_SIZE(items
), 0, NULL
, pbEncoded
, pcbEncoded
);
1537 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1538 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1539 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1542 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1543 const struct CTLEntries
*entries
= pvStructInfo
;
1546 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1550 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1556 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1557 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1559 *pcbEncoded
= bytesNeeded
;
1562 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1563 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1567 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1568 pbEncoded
= *(BYTE
**)pbEncoded
;
1570 *out
++ = ASN_SEQUENCEOF
;
1571 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1573 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1575 DWORD size
= dataLen
;
1577 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1582 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1583 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1590 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1591 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1592 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1598 const CTL_INFO
*info
= pvStructInfo
;
1599 struct AsnEncodeSequenceItem items
[9] = {
1600 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1601 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1603 struct AsnConstructedItem constructed
= { 0 };
1606 if (info
->ListIdentifier
.cbData
)
1608 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1609 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1612 if (info
->SequenceNumber
.cbData
)
1614 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1615 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1618 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1619 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1621 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1623 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1624 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1627 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1628 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1630 if (info
->cCTLEntry
)
1632 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1633 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1636 if (info
->cExtension
)
1638 constructed
.tag
= 0;
1639 constructed
.pvStructInfo
= &info
->cExtension
;
1640 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1641 items
[cItem
].pvStructInfo
= &constructed
;
1642 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1645 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1646 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1650 SetLastError(STATUS_ACCESS_VIOLATION
);
1656 static BOOL
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1657 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1658 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1664 const CRYPT_SMIME_CAPABILITY
*capability
= pvStructInfo
;
1666 if (!capability
->pszObjId
)
1667 SetLastError(E_INVALIDARG
);
1670 struct AsnEncodeSequenceItem items
[] = {
1671 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1672 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1675 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1676 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
1682 SetLastError(STATUS_ACCESS_VIOLATION
);
1688 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1689 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1690 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1696 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1697 const CRYPT_SMIME_CAPABILITIES
*capabilities
= pvStructInfo
;
1700 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1704 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1705 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1711 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1712 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1714 *pcbEncoded
= bytesNeeded
;
1717 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1718 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1722 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1723 pbEncoded
= *(BYTE
**)pbEncoded
;
1725 *out
++ = ASN_SEQUENCEOF
;
1726 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1728 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1730 DWORD size
= dataLen
;
1732 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1733 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1738 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1739 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1746 SetLastError(STATUS_ACCESS_VIOLATION
);
1752 static BOOL WINAPI
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType
,
1753 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1754 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1756 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1757 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1760 for (i
= 0, dataLen
= 0; ret
&& i
< noticeRef
->cNoticeNumbers
; i
++)
1764 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1765 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, NULL
, &size
);
1771 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1772 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1774 *pcbEncoded
= bytesNeeded
;
1777 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1778 pcbEncoded
, bytesNeeded
)))
1782 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1783 pbEncoded
= *(BYTE
**)pbEncoded
;
1785 *out
++ = ASN_SEQUENCE
;
1786 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1788 for (i
= 0; i
< noticeRef
->cNoticeNumbers
; i
++)
1790 DWORD size
= dataLen
;
1792 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1793 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, out
, &size
);
1797 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1798 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1805 static BOOL WINAPI
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType
,
1806 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1807 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1809 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1811 CERT_NAME_VALUE orgValue
= { CERT_RDN_IA5_STRING
,
1812 { 0, (LPBYTE
)noticeRef
->pszOrganization
} };
1813 struct AsnEncodeSequenceItem items
[] = {
1814 { &orgValue
, CRYPT_AsnEncodeNameValue
, 0 },
1815 { noticeRef
, CRYPT_AsnEncodeNoticeNumbers
, 0 },
1818 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1819 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
1824 static BOOL WINAPI
CRYPT_AsnEncodePolicyQualifierUserNotice(
1825 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1826 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1833 const CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
= pvStructInfo
;
1834 struct AsnEncodeSequenceItem items
[2];
1835 CERT_NAME_VALUE displayTextValue
;
1838 if (notice
->pNoticeReference
)
1840 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNoticeReference
;
1841 items
[cItem
].pvStructInfo
= notice
->pNoticeReference
;
1844 if (notice
->pszDisplayText
)
1846 displayTextValue
.dwValueType
= CERT_RDN_BMP_STRING
;
1847 displayTextValue
.Value
.cbData
= 0;
1848 displayTextValue
.Value
.pbData
= (LPBYTE
)notice
->pszDisplayText
;
1849 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNameValue
;
1850 items
[cItem
].pvStructInfo
= &displayTextValue
;
1853 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1854 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1858 SetLastError(STATUS_ACCESS_VIOLATION
);
1864 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1865 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1866 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1872 const CRYPT_ATTRIBUTE
*attr
= pvStructInfo
;
1874 if (!attr
->pszObjId
)
1875 SetLastError(E_INVALIDARG
);
1878 struct AsnEncodeSequenceItem items
[2] = {
1879 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1880 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1883 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1884 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
1890 SetLastError(STATUS_ACCESS_VIOLATION
);
1896 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1897 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1898 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1904 const CRYPT_ATTRIBUTES
*attributes
= pvStructInfo
;
1905 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1906 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1908 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1909 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1913 SetLastError(STATUS_ACCESS_VIOLATION
);
1919 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1920 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1921 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1922 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1925 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1926 struct AsnEncodeSequenceItem items
[2] = {
1927 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1930 struct AsnConstructedItem constructed
= { 0 };
1933 if (info
->Content
.cbData
)
1935 constructed
.tag
= 0;
1936 constructed
.pvStructInfo
= &info
->Content
;
1937 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1938 items
[cItem
].pvStructInfo
= &constructed
;
1939 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1942 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1943 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1946 BOOL
CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA
*digestedData
,
1947 void *pvData
, DWORD
*pcbData
)
1949 struct AsnEncodeSequenceItem items
[] = {
1950 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1951 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1953 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1954 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1957 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
), 0, NULL
, pvData
, pcbData
);
1960 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1961 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1962 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1968 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1970 if (!info
->pszObjId
)
1971 SetLastError(E_INVALIDARG
);
1973 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1974 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1979 SetLastError(STATUS_ACCESS_VIOLATION
);
1985 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1986 BYTE tag
, DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
1990 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1991 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1993 if (value
->Value
.cbData
)
1994 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
1996 encodedLen
= lstrlenW(str
);
1999 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2000 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2002 *pcbEncoded
= bytesNeeded
;
2005 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2006 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2010 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2011 pbEncoded
= *(BYTE
**)pbEncoded
;
2013 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
2014 pbEncoded
+= lenBytes
;
2015 for (i
= 0; i
< encodedLen
; i
++)
2016 *pbEncoded
++ = (BYTE
)str
[i
];
2022 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
2023 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2027 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2028 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2030 if (value
->Value
.cbData
)
2031 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2033 encodedLen
= lstrlenW(str
);
2036 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2037 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2039 *pcbEncoded
= bytesNeeded
;
2042 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2043 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2048 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2049 ptr
= *(BYTE
**)pbEncoded
;
2052 *ptr
++ = ASN_NUMERICSTRING
;
2053 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2055 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2057 if ('0' <= str
[i
] && str
[i
] <= '9')
2058 *ptr
++ = (BYTE
)str
[i
];
2062 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2066 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2067 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2073 static inline BOOL
isprintableW(WCHAR wc
)
2075 return wc
&& wcschr( L
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?", wc
);
2078 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2079 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2083 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2084 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2086 if (value
->Value
.cbData
)
2087 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2089 encodedLen
= lstrlenW(str
);
2092 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2093 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2095 *pcbEncoded
= bytesNeeded
;
2098 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2099 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2104 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2105 ptr
= *(BYTE
**)pbEncoded
;
2108 *ptr
++ = ASN_PRINTABLESTRING
;
2109 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2111 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2113 if (isprintableW(str
[i
]))
2114 *ptr
++ = (BYTE
)str
[i
];
2118 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2122 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2123 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2129 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2130 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2134 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2135 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2137 if (value
->Value
.cbData
)
2138 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2140 encodedLen
= lstrlenW(str
);
2143 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2144 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2146 *pcbEncoded
= bytesNeeded
;
2149 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2150 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2155 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2156 ptr
= *(BYTE
**)pbEncoded
;
2159 *ptr
++ = ASN_IA5STRING
;
2160 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2162 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2165 *ptr
++ = (BYTE
)str
[i
];
2169 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2173 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2174 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2180 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2181 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2185 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2186 DWORD bytesNeeded
, lenBytes
, strLen
;
2188 /* FIXME: doesn't handle composite characters */
2189 if (value
->Value
.cbData
)
2190 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2192 strLen
= lstrlenW(str
);
2195 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2196 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2198 *pcbEncoded
= bytesNeeded
;
2201 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2202 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2206 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2207 pbEncoded
= *(BYTE
**)pbEncoded
;
2208 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2209 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2210 pbEncoded
+= lenBytes
;
2211 for (i
= 0; i
< strLen
; i
++)
2215 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2216 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2223 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2224 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2225 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2231 const CERT_NAME_VALUE
*value
= pvStructInfo
;
2233 switch (value
->dwValueType
)
2235 case CERT_RDN_ANY_TYPE
:
2236 case CERT_RDN_ENCODED_BLOB
:
2237 case CERT_RDN_OCTET_STRING
:
2238 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2240 case CERT_RDN_NUMERIC_STRING
:
2241 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2242 pbEncoded
, pcbEncoded
);
2244 case CERT_RDN_PRINTABLE_STRING
:
2245 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2246 pbEncoded
, pcbEncoded
);
2248 case CERT_RDN_TELETEX_STRING
:
2249 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2250 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2252 case CERT_RDN_VIDEOTEX_STRING
:
2253 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2254 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2256 case CERT_RDN_IA5_STRING
:
2257 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2258 pbEncoded
, pcbEncoded
);
2260 case CERT_RDN_GRAPHIC_STRING
:
2261 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2262 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2264 case CERT_RDN_VISIBLE_STRING
:
2265 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2266 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2268 case CERT_RDN_GENERAL_STRING
:
2269 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2270 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2272 case CERT_RDN_UNIVERSAL_STRING
:
2273 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2274 pbEncoded
, pcbEncoded
);
2276 case CERT_RDN_BMP_STRING
:
2277 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2278 pbEncoded
, pcbEncoded
);
2280 case CERT_RDN_UTF8_STRING
:
2281 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2282 pbEncoded
, pcbEncoded
);
2285 SetLastError(CRYPT_E_ASN1_CHOICE
);
2290 SetLastError(STATUS_ACCESS_VIOLATION
);
2296 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2297 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2298 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2304 const CERT_NAME_INFO
*info
= pvStructInfo
;
2305 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2307 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
2309 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2311 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2312 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2314 bytesNeeded
+= size
;
2316 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2317 bytesNeeded
+= 1 + lenBytes
;
2321 *pcbEncoded
= bytesNeeded
;
2324 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2325 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2329 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2330 pbEncoded
= *(BYTE
**)pbEncoded
;
2332 *out
++ = ASN_SEQUENCEOF
;
2333 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2335 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2338 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2339 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, out
, &size
);
2343 bytesNeeded
-= size
;
2346 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2347 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2354 SetLastError(STATUS_ACCESS_VIOLATION
);
2361 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2362 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2363 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2365 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2374 else if (*pcbEncoded
< 3)
2377 SetLastError(ERROR_MORE_DATA
);
2383 *pbEncoded
++ = ASN_BOOL
;
2385 *pbEncoded
++ = val
? 0xff : 0;
2388 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2392 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2393 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2394 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2396 const CERT_ALT_NAME_ENTRY
*entry
= pvStructInfo
;
2402 switch (entry
->dwAltNameChoice
)
2404 case CERT_ALT_NAME_RFC822_NAME
:
2405 case CERT_ALT_NAME_DNS_NAME
:
2406 case CERT_ALT_NAME_URL
:
2407 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2412 /* Not + 1: don't encode the NULL-terminator */
2413 dataLen
= lstrlenW(entry
->pwszURL
);
2414 for (i
= 0; ret
&& i
< dataLen
; i
++)
2416 if (entry
->pwszURL
[i
] > 0x7f)
2418 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2427 case CERT_ALT_NAME_DIRECTORY_NAME
:
2428 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2429 dataLen
= entry
->DirectoryName
.cbData
;
2431 case CERT_ALT_NAME_IP_ADDRESS
:
2432 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2433 dataLen
= entry
->IPAddress
.cbData
;
2435 case CERT_ALT_NAME_REGISTERED_ID
:
2437 struct AsnEncodeTagSwappedItem swapped
=
2438 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->pszRegisteredID
,
2439 CRYPT_AsnEncodeOid
};
2441 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2444 case CERT_ALT_NAME_OTHER_NAME
:
2445 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
2448 SetLastError(E_INVALIDARG
);
2453 DWORD bytesNeeded
, lenBytes
;
2455 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2456 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2458 *pcbEncoded
= bytesNeeded
;
2459 else if (*pcbEncoded
< bytesNeeded
)
2461 SetLastError(ERROR_MORE_DATA
);
2462 *pcbEncoded
= bytesNeeded
;
2468 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2469 pbEncoded
+= lenBytes
;
2470 switch (entry
->dwAltNameChoice
)
2472 case CERT_ALT_NAME_RFC822_NAME
:
2473 case CERT_ALT_NAME_DNS_NAME
:
2474 case CERT_ALT_NAME_URL
:
2478 for (i
= 0; i
< dataLen
; i
++)
2479 *pbEncoded
++ = (BYTE
)entry
->pwszURL
[i
];
2482 case CERT_ALT_NAME_DIRECTORY_NAME
:
2483 memcpy(pbEncoded
, entry
->DirectoryName
.pbData
, dataLen
);
2485 case CERT_ALT_NAME_IP_ADDRESS
:
2486 memcpy(pbEncoded
, entry
->IPAddress
.pbData
, dataLen
);
2490 *pcbEncoded
= bytesNeeded
;
2493 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2497 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2498 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2499 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2505 const CERT_AUTHORITY_KEY_ID_INFO
*info
= pvStructInfo
;
2506 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2507 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2508 struct AsnConstructedItem constructed
= { 0 };
2509 DWORD cItem
= 0, cSwapped
= 0;
2511 if (info
->KeyId
.cbData
)
2513 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2514 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2515 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2516 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2517 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2521 if (info
->CertIssuer
.cbData
)
2523 constructed
.tag
= 1;
2524 constructed
.pvStructInfo
= &info
->CertIssuer
;
2525 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2526 items
[cItem
].pvStructInfo
= &constructed
;
2527 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2530 if (info
->CertSerialNumber
.cbData
)
2532 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2533 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2534 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2535 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2536 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2540 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2541 pEncodePara
, pbEncoded
, pcbEncoded
);
2545 SetLastError(STATUS_ACCESS_VIOLATION
);
2552 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2553 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2554 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2560 const CERT_ALT_NAME_INFO
*info
= pvStructInfo
;
2561 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2564 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2565 * can't encode an erroneous entry index if it's bigger than this.
2567 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2571 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2572 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2575 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2577 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2578 * the bad character, now set the index of the bad
2581 *pcbEncoded
= (BYTE
)i
<<
2582 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2587 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2588 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2591 *pcbEncoded
= bytesNeeded
;
2596 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2597 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2601 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2602 pbEncoded
= *(BYTE
**)pbEncoded
;
2604 *out
++ = ASN_SEQUENCEOF
;
2605 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2607 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2609 DWORD len
= dataLen
;
2611 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2612 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, out
, &len
);
2619 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2620 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2627 SetLastError(STATUS_ACCESS_VIOLATION
);
2634 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2635 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2636 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2642 const CERT_AUTHORITY_KEY_ID2_INFO
*info
= pvStructInfo
;
2643 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2644 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2645 DWORD cItem
= 0, cSwapped
= 0;
2647 if (info
->KeyId
.cbData
)
2649 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2650 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2651 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2652 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2653 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2657 if (info
->AuthorityCertIssuer
.cAltEntry
)
2659 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2660 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2661 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2662 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2663 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2667 if (info
->AuthorityCertSerialNumber
.cbData
)
2669 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2670 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2671 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2672 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2673 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2677 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2678 pEncodePara
, pbEncoded
, pcbEncoded
);
2682 SetLastError(STATUS_ACCESS_VIOLATION
);
2689 static BOOL
CRYPT_AsnEncodeAccessDescription(
2690 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2692 struct AsnEncodeSequenceItem items
[] = {
2693 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2694 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2697 if (!descr
->pszAccessMethod
)
2699 SetLastError(E_INVALIDARG
);
2702 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
), 0, NULL
, pbEncoded
, pcbEncoded
);
2705 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2706 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2707 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2713 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2714 const CERT_AUTHORITY_INFO_ACCESS
*info
= pvStructInfo
;
2717 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2721 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2728 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2729 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2731 *pcbEncoded
= bytesNeeded
;
2734 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2735 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2739 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2740 pbEncoded
= *(BYTE
**)pbEncoded
;
2742 *out
++ = ASN_SEQUENCEOF
;
2743 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2745 for (i
= 0; i
< info
->cAccDescr
; i
++)
2747 DWORD size
= dataLen
;
2749 ret
= CRYPT_AsnEncodeAccessDescription(
2750 &info
->rgAccDescr
[i
], out
, &size
);
2754 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2755 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2762 SetLastError(STATUS_ACCESS_VIOLATION
);
2769 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2770 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2771 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2777 const CERT_BASIC_CONSTRAINTS_INFO
*info
= pvStructInfo
;
2778 struct AsnEncodeSequenceItem items
[3] = {
2779 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2784 if (info
->fPathLenConstraint
)
2786 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2787 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2790 if (info
->cSubtreesConstraint
)
2792 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2793 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2796 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2797 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2801 SetLastError(STATUS_ACCESS_VIOLATION
);
2808 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2809 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2810 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2816 const CERT_BASIC_CONSTRAINTS2_INFO
*info
= pvStructInfo
;
2817 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2822 items
[cItem
].pvStructInfo
= &info
->fCA
;
2823 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2826 if (info
->fPathLenConstraint
)
2828 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2829 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2832 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2833 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2837 SetLastError(STATUS_ACCESS_VIOLATION
);
2844 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2845 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2846 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2848 const CERT_POLICY_INFO
*info
= pvStructInfo
;
2851 if (!info
->cPolicyQualifier
)
2858 struct AsnEncodeSequenceItem items
[2] = {
2859 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2860 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2862 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2865 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2867 items
[0].pvStructInfo
=
2868 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2869 items
[1].pvStructInfo
= &info
->rgPolicyQualifier
[i
].Qualifier
;
2870 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2871 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2873 bytesNeeded
+= size
;
2875 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2876 bytesNeeded
+= 1 + lenBytes
;
2880 *pcbEncoded
= bytesNeeded
;
2883 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2884 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2888 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2889 pbEncoded
= *(BYTE
**)pbEncoded
;
2891 *out
++ = ASN_SEQUENCEOF
;
2892 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2894 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2896 items
[0].pvStructInfo
=
2897 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2898 items
[1].pvStructInfo
=
2899 &info
->rgPolicyQualifier
[i
].Qualifier
;
2901 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2902 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
2906 bytesNeeded
-= size
;
2909 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2910 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2918 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2919 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2922 struct AsnEncodeSequenceItem items
[2] = {
2923 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2924 { info
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2928 if (!info
->pszPolicyIdentifier
)
2930 SetLastError(E_INVALIDARG
);
2933 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2937 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2938 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2939 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2945 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2946 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2949 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2951 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2952 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2955 bytesNeeded
+= size
;
2957 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2958 bytesNeeded
+= 1 + lenBytes
;
2962 *pcbEncoded
= bytesNeeded
;
2965 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2966 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2970 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2971 pbEncoded
= *(BYTE
**)pbEncoded
;
2973 *out
++ = ASN_SEQUENCEOF
;
2974 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2976 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2979 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2980 &info
->rgPolicyInfo
[i
],
2981 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
2985 bytesNeeded
-= size
;
2988 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2989 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2996 SetLastError(STATUS_ACCESS_VIOLATION
);
3002 static BOOL
CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType
,
3003 const CERT_POLICY_MAPPING
*mapping
, DWORD dwFlags
, BYTE
*pbEncoded
,
3006 struct AsnEncodeSequenceItem items
[] = {
3007 { mapping
->pszIssuerDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3008 { mapping
->pszSubjectDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3011 if (!mapping
->pszIssuerDomainPolicy
|| !mapping
->pszSubjectDomainPolicy
)
3013 SetLastError(E_INVALIDARG
);
3016 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3019 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType
,
3020 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3021 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3027 const CERT_POLICY_MAPPINGS_INFO
*info
= pvStructInfo
;
3028 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3031 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3033 ret
= CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType
,
3034 &info
->rgPolicyMapping
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
3037 bytesNeeded
+= size
;
3039 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3040 bytesNeeded
+= 1 + lenBytes
;
3044 *pcbEncoded
= bytesNeeded
;
3047 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3048 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3052 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3053 pbEncoded
= *(BYTE
**)pbEncoded
;
3055 *out
++ = ASN_SEQUENCEOF
;
3056 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3058 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3061 ret
= CRYPT_AsnEncodeCertPolicyMapping(
3062 dwCertEncodingType
, &info
->rgPolicyMapping
[i
],
3063 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
3067 bytesNeeded
-= size
;
3070 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3071 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3078 SetLastError(STATUS_ACCESS_VIOLATION
);
3084 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyConstraints(
3085 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3086 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3093 const CERT_POLICY_CONSTRAINTS_INFO
*info
= pvStructInfo
;
3094 struct AsnEncodeSequenceItem items
[2];
3095 struct AsnEncodeTagSwappedItem swapped
[2];
3096 DWORD cItem
= 0, cSwapped
= 0;
3098 if (info
->fRequireExplicitPolicy
)
3100 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3101 swapped
[cSwapped
].pvStructInfo
=
3102 &info
->dwRequireExplicitPolicySkipCerts
;
3103 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3104 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3105 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3109 if (info
->fInhibitPolicyMapping
)
3111 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3112 swapped
[cSwapped
].pvStructInfo
=
3113 &info
->dwInhibitPolicyMappingSkipCerts
;
3114 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3115 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3116 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3120 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3121 dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3125 SetLastError(STATUS_ACCESS_VIOLATION
);
3131 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey_Bcrypt(DWORD dwCertEncodingType
,
3132 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3133 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3139 const BCRYPT_RSAKEY_BLOB
*hdr
= pvStructInfo
;
3141 BYTE
*pubexp
= (BYTE
*)pvStructInfo
+ sizeof(BCRYPT_RSAKEY_BLOB
);
3142 BYTE
*modulus
= (BYTE
*)pvStructInfo
+ sizeof(BCRYPT_RSAKEY_BLOB
) + hdr
->cbPublicExp
;
3143 BYTE
*pubexp_be
= CryptMemAlloc(hdr
->cbPublicExp
);
3144 BYTE
*modulus_be
= CryptMemAlloc(hdr
->cbModulus
);
3145 CRYPT_INTEGER_BLOB pubexp_int
= { hdr
->cbPublicExp
, pubexp_be
};
3146 CRYPT_INTEGER_BLOB modulus_int
= { hdr
->cbModulus
, modulus_be
};
3148 struct AsnEncodeSequenceItem items
[] = {
3149 { &modulus_int
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3150 { &pubexp_int
, CRYPT_AsnEncodeInteger
, 0 },
3153 /* CNG_RSA_PUBLIC_KEY_BLOB stores the exponent and modulus
3154 * in big-endian format, so we need to convert them
3155 * to little-endian format before encoding
3157 CRYPT_CopyReversed(pubexp_be
, pubexp
, hdr
->cbPublicExp
);
3158 CRYPT_CopyReversed(modulus_be
, modulus
, hdr
->cbModulus
);
3160 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3161 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3163 CryptMemFree(pubexp_be
);
3164 CryptMemFree(modulus_be
);
3168 SetLastError(STATUS_ACCESS_VIOLATION
);
3177 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
3178 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3179 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3185 const BLOBHEADER
*hdr
= pvStructInfo
;
3187 if (hdr
->bType
!= PUBLICKEYBLOB
)
3189 SetLastError(E_INVALIDARG
);
3194 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
3195 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
3196 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
3197 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
3198 struct AsnEncodeSequenceItem items
[] = {
3199 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3200 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
3203 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3204 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3209 SetLastError(STATUS_ACCESS_VIOLATION
);
3216 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
3217 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3218 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3224 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
3225 DWORD bytesNeeded
, lenBytes
;
3227 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
3228 dwFlags
, pEncodePara
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
3230 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3231 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3234 *pcbEncoded
= bytesNeeded
;
3239 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3240 pcbEncoded
, bytesNeeded
)))
3242 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3243 pbEncoded
= *(BYTE
**)pbEncoded
;
3244 *pbEncoded
++ = ASN_OCTETSTRING
;
3245 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3246 pbEncoded
+= lenBytes
;
3248 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3254 SetLastError(STATUS_ACCESS_VIOLATION
);
3258 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3262 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3263 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3264 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3270 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3271 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3274 /* yep, MS allows cUnusedBits to be >= 8 */
3275 if (!blob
->cUnusedBits
)
3277 dataBytes
= blob
->cbData
;
3280 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3282 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3283 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3291 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3292 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3295 *pcbEncoded
= bytesNeeded
;
3300 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3301 pcbEncoded
, bytesNeeded
)))
3303 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3304 pbEncoded
= *(BYTE
**)pbEncoded
;
3305 *pbEncoded
++ = ASN_BITSTRING
;
3306 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3307 pbEncoded
+= lenBytes
;
3308 *pbEncoded
++ = unusedBits
;
3311 BYTE mask
= 0xff << unusedBits
;
3315 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3316 pbEncoded
+= dataBytes
- 1;
3318 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3325 SetLastError(STATUS_ACCESS_VIOLATION
);
3332 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3333 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3334 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3340 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3341 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3346 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3351 for (i
= 0; i
< newBlob
.cbData
; i
++)
3352 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3358 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3359 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3360 CryptMemFree(newBlob
.pbData
);
3364 SetLastError(STATUS_ACCESS_VIOLATION
);
3371 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3372 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3373 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3375 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3377 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3378 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3381 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3382 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3383 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3389 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3392 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3394 significantBytes
= blob
->cbData
;
3395 if (significantBytes
)
3397 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3399 /* negative, lop off leading (little-endian) 0xffs */
3400 for (; significantBytes
> 0 &&
3401 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3403 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3411 /* positive, lop off leading (little-endian) zeroes */
3412 for (; significantBytes
> 0 &&
3413 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3415 if (significantBytes
== 0)
3416 significantBytes
= 1;
3417 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3425 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3427 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3428 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3433 *pcbEncoded
= bytesNeeded
;
3438 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3439 pcbEncoded
, bytesNeeded
)))
3441 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3442 pbEncoded
= *(BYTE
**)pbEncoded
;
3443 *pbEncoded
++ = ASN_INTEGER
;
3446 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3447 pbEncoded
+= lenBytes
;
3448 *pbEncoded
++ = padByte
;
3452 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3453 pbEncoded
+= lenBytes
;
3455 for (; significantBytes
> 0; significantBytes
--)
3456 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3462 SetLastError(STATUS_ACCESS_VIOLATION
);
3469 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3470 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3471 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3477 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3479 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3481 significantBytes
= blob
->cbData
;
3482 if (significantBytes
)
3484 /* positive, lop off leading (little-endian) zeroes */
3485 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3488 if (significantBytes
== 0)
3489 significantBytes
= 1;
3490 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3494 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3496 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3497 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3502 *pcbEncoded
= bytesNeeded
;
3507 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3508 pcbEncoded
, bytesNeeded
)))
3510 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3511 pbEncoded
= *(BYTE
**)pbEncoded
;
3512 *pbEncoded
++ = ASN_INTEGER
;
3515 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3516 pbEncoded
+= lenBytes
;
3521 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3522 pbEncoded
+= lenBytes
;
3524 for (; significantBytes
> 0; significantBytes
--)
3525 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3531 SetLastError(STATUS_ACCESS_VIOLATION
);
3538 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3539 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3540 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3542 CRYPT_INTEGER_BLOB blob
;
3545 /* Encode as an unsigned integer, then change the tag to enumerated */
3546 blob
.cbData
= sizeof(DWORD
);
3547 blob
.pbData
= (BYTE
*)pvStructInfo
;
3548 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3549 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3550 if (ret
&& pbEncoded
)
3552 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3553 pbEncoded
= *(BYTE
**)pbEncoded
;
3554 pbEncoded
[0] = ASN_ENUMERATED
;
3559 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3560 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3561 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3568 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a
3569 * temporary buffer because the output buffer is not NULL-terminated.
3571 static const DWORD bytesNeeded
= 15;
3576 *pcbEncoded
= bytesNeeded
;
3581 /* Sanity check the year, this is a two-digit year format */
3582 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3583 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3585 SetLastError(CRYPT_E_BAD_ENCODE
);
3590 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3591 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3593 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3594 pbEncoded
= *(BYTE
**)pbEncoded
;
3595 buf
[0] = ASN_UTCTIME
;
3596 buf
[1] = bytesNeeded
- 2;
3597 snprintf(buf
+ 2, sizeof(buf
) - 2,
3598 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3599 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3600 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3601 sysTime
.wMinute
, sysTime
.wSecond
);
3602 memcpy(pbEncoded
, buf
, bytesNeeded
);
3609 SetLastError(STATUS_ACCESS_VIOLATION
);
3616 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3617 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3618 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3625 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a
3626 * temporary buffer because the output buffer is not NULL-terminated.
3628 static const DWORD bytesNeeded
= 17;
3633 *pcbEncoded
= bytesNeeded
;
3638 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3640 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3641 pcbEncoded
, bytesNeeded
);
3644 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3645 pbEncoded
= *(BYTE
**)pbEncoded
;
3646 buf
[0] = ASN_GENERALTIME
;
3647 buf
[1] = bytesNeeded
- 2;
3648 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3649 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3650 sysTime
.wMinute
, sysTime
.wSecond
);
3651 memcpy(pbEncoded
, buf
, bytesNeeded
);
3657 SetLastError(STATUS_ACCESS_VIOLATION
);
3664 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3665 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3666 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3674 /* Check the year, if it's in the UTCTime range call that encode func */
3675 if (!FileTimeToSystemTime(pvStructInfo
, &sysTime
))
3677 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3678 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3679 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3681 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3682 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3687 SetLastError(STATUS_ACCESS_VIOLATION
);
3694 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3695 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3696 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3702 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3703 const CRYPT_SEQUENCE_OF_ANY
*seq
= pvStructInfo
;
3705 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3706 dataLen
+= seq
->rgValue
[i
].cbData
;
3707 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3708 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3711 *pcbEncoded
= bytesNeeded
;
3716 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3717 pcbEncoded
, bytesNeeded
)))
3719 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3720 pbEncoded
= *(BYTE
**)pbEncoded
;
3721 *pbEncoded
++ = ASN_SEQUENCEOF
;
3722 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3723 pbEncoded
+= lenBytes
;
3724 for (i
= 0; i
< seq
->cValue
; i
++)
3726 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3727 seq
->rgValue
[i
].cbData
);
3728 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3735 SetLastError(STATUS_ACCESS_VIOLATION
);
3742 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3743 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3746 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3747 struct AsnConstructedItem constructed
= { 0 };
3748 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3749 DWORD cItem
= 0, cSwapped
= 0;
3751 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3753 case CRL_DIST_POINT_NO_NAME
:
3756 case CRL_DIST_POINT_FULL_NAME
:
3757 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3758 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.FullName
;
3759 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3760 constructed
.tag
= 0;
3761 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3762 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3763 items
[cItem
].pvStructInfo
= &constructed
;
3764 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3768 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3769 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3775 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3777 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3778 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3779 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3780 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3781 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3785 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3787 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3788 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3789 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3790 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3791 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3796 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3797 pbEncoded
, pcbEncoded
);
3801 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3802 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3803 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3809 const CRL_DIST_POINTS_INFO
*info
= pvStructInfo
;
3811 if (!info
->cDistPoint
)
3813 SetLastError(E_INVALIDARG
);
3818 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3821 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3825 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3829 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3831 /* Have to propagate index of failing character */
3837 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3838 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3841 *pcbEncoded
= bytesNeeded
;
3846 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3847 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3851 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3852 pbEncoded
= *(BYTE
**)pbEncoded
;
3854 *out
++ = ASN_SEQUENCEOF
;
3855 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
3857 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3859 DWORD len
= dataLen
;
3861 ret
= CRYPT_AsnEncodeDistPoint(
3862 &info
->rgDistPoint
[i
], out
, &len
);
3869 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3870 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3878 SetLastError(STATUS_ACCESS_VIOLATION
);
3885 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3886 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3887 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3893 const CERT_ENHKEY_USAGE
*usage
= pvStructInfo
;
3894 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3897 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3899 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3900 usage
->rgpszUsageIdentifier
[i
],
3901 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3903 bytesNeeded
+= size
;
3905 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3906 bytesNeeded
+= 1 + lenBytes
;
3910 *pcbEncoded
= bytesNeeded
;
3913 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3914 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3918 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3919 pbEncoded
= *(BYTE
**)pbEncoded
;
3921 *out
++ = ASN_SEQUENCEOF
;
3922 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3924 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3927 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3928 usage
->rgpszUsageIdentifier
[i
],
3929 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
3933 bytesNeeded
-= size
;
3936 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3937 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3944 SetLastError(STATUS_ACCESS_VIOLATION
);
3951 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3952 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3953 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3959 const CRL_ISSUING_DIST_POINT
*point
= pvStructInfo
;
3960 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3961 struct AsnConstructedItem constructed
= { 0 };
3962 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3963 DWORD cItem
= 0, cSwapped
= 0;
3966 switch (point
->DistPointName
.dwDistPointNameChoice
)
3968 case CRL_DIST_POINT_NO_NAME
:
3971 case CRL_DIST_POINT_FULL_NAME
:
3972 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3973 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.FullName
;
3974 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3975 constructed
.tag
= 0;
3976 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3977 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3978 items
[cItem
].pvStructInfo
= &constructed
;
3979 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3984 SetLastError(E_INVALIDARG
);
3987 if (ret
&& point
->fOnlyContainsUserCerts
)
3989 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3990 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3991 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3992 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3993 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3997 if (ret
&& point
->fOnlyContainsCACerts
)
3999 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
4000 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
4001 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
4002 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4003 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4007 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
4009 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
4010 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
4011 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
4012 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4013 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4017 if (ret
&& point
->fIndirectCRL
)
4019 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
4020 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
4021 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
4022 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4023 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4028 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4029 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4033 SetLastError(STATUS_ACCESS_VIOLATION
);
4040 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
4041 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4042 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4045 const CERT_GENERAL_SUBTREE
*subtree
= pvStructInfo
;
4046 struct AsnEncodeSequenceItem items
[3] = {
4047 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
4050 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4051 DWORD cItem
= 1, cSwapped
= 0;
4053 if (subtree
->dwMinimum
)
4055 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4056 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
4057 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4058 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4059 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4063 if (subtree
->fMaximum
)
4065 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
4066 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
4067 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4068 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4069 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4073 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
4074 pEncodePara
, pbEncoded
, pcbEncoded
);
4078 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
4079 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4080 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4083 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
4085 TRACE("%p\n", pvStructInfo
);
4089 const CERT_NAME_CONSTRAINTS_INFO
*constraints
= pvStructInfo
;
4090 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
4091 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4092 DWORD i
, cItem
= 0, cSwapped
= 0;
4095 if (constraints
->cPermittedSubtree
)
4097 permitted
.rgBlob
= CryptMemAlloc(
4098 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
4099 if (permitted
.rgBlob
)
4101 permitted
.cBlob
= constraints
->cPermittedSubtree
;
4102 memset(permitted
.rgBlob
, 0,
4103 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4104 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
4105 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4106 NULL
, &constraints
->rgPermittedSubtree
[i
],
4107 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4108 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
4109 &permitted
.rgBlob
[i
].cbData
);
4112 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4113 swapped
[cSwapped
].pvStructInfo
= &permitted
;
4114 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4115 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4116 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4124 if (constraints
->cExcludedSubtree
)
4126 excluded
.rgBlob
= CryptMemAlloc(
4127 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
4128 if (excluded
.rgBlob
)
4130 excluded
.cBlob
= constraints
->cExcludedSubtree
;
4131 memset(excluded
.rgBlob
, 0,
4132 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4133 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
4134 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4135 NULL
, &constraints
->rgExcludedSubtree
[i
],
4136 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4137 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
4138 &excluded
.rgBlob
[i
].cbData
);
4141 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4142 swapped
[cSwapped
].pvStructInfo
= &excluded
;
4143 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4144 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4145 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4154 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4155 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4156 for (i
= 0; i
< permitted
.cBlob
; i
++)
4157 LocalFree(permitted
.rgBlob
[i
].pbData
);
4158 for (i
= 0; i
< excluded
.cBlob
; i
++)
4159 LocalFree(excluded
.rgBlob
[i
].pbData
);
4163 SetLastError(STATUS_ACCESS_VIOLATION
);
4166 CryptMemFree(permitted
.rgBlob
);
4167 CryptMemFree(excluded
.rgBlob
);
4168 TRACE("returning %d\n", ret
);
4172 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
4173 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
4174 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
4178 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
= pvStructInfo
;
4179 struct AsnEncodeSequenceItem items
[] = {
4180 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
4181 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
4184 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4185 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4189 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
4190 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4191 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4195 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4197 SetLastError(E_INVALIDARG
);
4203 const CMSG_SIGNER_INFO
*info
= pvStructInfo
;
4205 if (!info
->Issuer
.cbData
)
4206 SetLastError(E_INVALIDARG
);
4209 struct AsnEncodeSequenceItem items
[7] = {
4210 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4211 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4212 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
4215 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4216 DWORD cItem
= 3, cSwapped
= 0;
4218 if (info
->AuthAttrs
.cAttr
)
4220 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4221 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4222 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4223 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4224 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4228 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4229 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4231 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4232 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4234 if (info
->UnauthAttrs
.cAttr
)
4236 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4237 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4238 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4239 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4240 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4244 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4245 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4250 SetLastError(STATUS_ACCESS_VIOLATION
);
4256 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4257 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4258 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4262 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4264 SetLastError(E_INVALIDARG
);
4270 const CMSG_CMS_SIGNER_INFO
*info
= pvStructInfo
;
4272 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4273 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4274 SetLastError(E_INVALIDARG
);
4275 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4276 !info
->SignerId
.IssuerSerialNumber
.Issuer
.cbData
)
4277 SetLastError(E_INVALIDARG
);
4280 struct AsnEncodeSequenceItem items
[7] = {
4281 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4283 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4284 DWORD cItem
= 1, cSwapped
= 0;
4286 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4288 items
[cItem
].pvStructInfo
=
4289 &info
->SignerId
.IssuerSerialNumber
.Issuer
;
4290 items
[cItem
].encodeFunc
=
4291 CRYPT_AsnEncodeIssuerSerialNumber
;
4296 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4297 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.KeyId
;
4298 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4299 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4300 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4304 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4305 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4307 if (info
->AuthAttrs
.cAttr
)
4309 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4310 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4311 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4312 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4313 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4317 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4318 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4320 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4321 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4323 if (info
->UnauthAttrs
.cAttr
)
4325 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4326 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4327 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4328 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4329 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4333 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4334 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4339 SetLastError(STATUS_ACCESS_VIOLATION
);
4345 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4348 struct DERSetDescriptor digestAlgorithmsSet
= { signedInfo
->cSignerInfo
,
4349 signedInfo
->rgSignerInfo
, sizeof(CMSG_CMS_SIGNER_INFO
),
4350 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
),
4351 CRYPT_AsnEncodeAlgorithmIdWithNullParams
};
4352 struct AsnEncodeSequenceItem items
[7] = {
4353 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4354 { &digestAlgorithmsSet
, CRYPT_DEREncodeItemsAsSet
, 0 },
4355 { &signedInfo
->content
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 }
4357 struct DERSetDescriptor certSet
= { 0 }, crlSet
= { 0 }, signerSet
= { 0 };
4358 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4359 DWORD cItem
= 3, cSwapped
= 0;
4361 if (signedInfo
->cCertEncoded
)
4363 certSet
.cItems
= signedInfo
->cCertEncoded
;
4364 certSet
.items
= signedInfo
->rgCertEncoded
;
4365 certSet
.itemSize
= sizeof(CERT_BLOB
);
4366 certSet
.itemOffset
= 0;
4367 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4368 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4369 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4370 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4371 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4372 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4376 if (signedInfo
->cCrlEncoded
)
4378 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4379 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4380 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4381 crlSet
.itemOffset
= 0;
4382 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4383 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4384 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4385 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4386 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4387 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4391 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4392 signerSet
.items
= signedInfo
->rgSignerInfo
;
4393 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4394 signerSet
.itemOffset
= 0;
4395 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4396 items
[cItem
].pvStructInfo
= &signerSet
;
4397 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4400 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4401 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4404 static BOOL WINAPI
CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType
,
4405 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4406 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4408 const CMSG_KEY_TRANS_RECIPIENT_INFO
*info
= pvStructInfo
;
4409 struct AsnEncodeSequenceItem items
[] = {
4410 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4411 { &info
->RecipientId
.IssuerSerialNumber
,
4412 CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4413 { &info
->KeyEncryptionAlgorithm
,
4414 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4415 { &info
->EncryptedKey
, CRYPT_AsnEncodeOctets
, 0 },
4418 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4419 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4422 static BOOL WINAPI
CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType
,
4423 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4424 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4426 const CRYPT_ENCRYPTED_CONTENT_INFO
*info
= pvStructInfo
;
4427 struct AsnEncodeTagSwappedItem swapped
= { ASN_CONTEXT
| 0,
4428 &info
->encryptedContent
, CRYPT_AsnEncodeOctets
};
4429 struct AsnEncodeSequenceItem items
[] = {
4430 { info
->contentType
, CRYPT_AsnEncodeOid
, 0 },
4431 { &info
->contentEncryptionAlgorithm
,
4432 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4433 { &swapped
, CRYPT_AsnEncodeSwapTag
, 0 },
4436 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4437 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4440 BOOL
CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA
*envelopedData
,
4441 void *pvData
, DWORD
*pcbData
)
4443 struct DERSetDescriptor recipientInfosSet
= { envelopedData
->cRecipientInfo
,
4444 envelopedData
->rgRecipientInfo
, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
), 0,
4445 CRYPT_AsnEncodeRecipientInfo
};
4446 struct AsnEncodeSequenceItem items
[] = {
4447 { &envelopedData
->version
, CRYPT_AsnEncodeInt
, 0 },
4448 { &recipientInfosSet
, CRYPT_DEREncodeItemsAsSet
, 0 },
4449 { &envelopedData
->encryptedContentInfo
,
4450 CRYPT_AsnEncodeEncryptedContentInfo
, 0 },
4453 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
4454 ARRAY_SIZE(items
), 0, NULL
, pvData
, pcbData
);
4457 static BOOL WINAPI
CRYPT_AsnEncodeCertId(DWORD dwCertEncodingType
,
4458 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4459 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4465 const OCSP_CERT_ID
*id
= pvStructInfo
;
4466 struct AsnEncodeSequenceItem items
[] = {
4467 { &id
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4468 { &id
->IssuerNameHash
, CRYPT_AsnEncodeOctets
, 0 },
4469 { &id
->IssuerKeyHash
, CRYPT_AsnEncodeOctets
, 0 },
4470 { &id
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
4473 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4474 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4478 SetLastError(STATUS_ACCESS_VIOLATION
);
4485 static BOOL
CRYPT_AsnEncodeOCSPRequestEntry(DWORD dwCertEncodingType
,
4486 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4487 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4493 const OCSP_REQUEST_ENTRY
*info
= pvStructInfo
;
4494 struct AsnEncodeSequenceItem items
[] = {
4495 { &info
->CertId
, CRYPT_AsnEncodeCertId
, 0 },
4498 if (info
->cExtension
)
4500 FIXME("extensions not supported\n");
4501 SetLastError(E_INVALIDARG
);
4506 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4507 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4512 SetLastError(STATUS_ACCESS_VIOLATION
);
4519 struct ocsp_request_list
4522 OCSP_REQUEST_ENTRY
*entry
;
4525 static BOOL WINAPI
CRYPT_AsnEncodeOCSPRequestEntries(DWORD dwCertEncodingType
,
4526 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4527 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4533 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
4534 const struct ocsp_request_list
*list
= pvStructInfo
;
4537 for (i
= 0, dataLen
= 0; ret
&& i
< list
->count
; i
++)
4540 ret
= CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType
, lpszStructType
, &list
->entry
[i
],
4541 dwFlags
, pEncodePara
, NULL
, &size
);
4547 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
4548 bytesNeeded
= 1 + lenBytes
+ dataLen
;
4550 *pcbEncoded
= bytesNeeded
;
4553 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4554 pbEncoded
, pcbEncoded
, bytesNeeded
)))
4558 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4559 pbEncoded
= *(BYTE
**)pbEncoded
;
4561 *out
++ = ASN_SEQUENCEOF
;
4562 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
4564 for (i
= 0; i
< list
->count
; i
++)
4566 DWORD size
= dataLen
;
4568 ret
= CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType
, lpszStructType
,
4569 &list
->entry
[i
], dwFlags
, pEncodePara
, out
, &size
);
4574 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
4575 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
4582 SetLastError(STATUS_ACCESS_VIOLATION
);
4589 static BOOL WINAPI
CRYPT_AsnEncodeOCSPRequest(DWORD dwCertEncodingType
,
4590 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4591 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4597 const OCSP_REQUEST_INFO
*info
= pvStructInfo
;
4599 if (info
->dwVersion
!= OCSP_REQUEST_V1
)
4601 FIXME("version %lu not supported\n", info
->dwVersion
);
4602 SetLastError(E_INVALIDARG
);
4607 if (info
->cExtension
)
4609 FIXME("extensions not supported\n");
4610 SetLastError(E_INVALIDARG
);
4615 struct AsnConstructedItem name
;
4616 struct AsnEncodeSequenceItem items
[2];
4619 if (info
->pRequestorName
)
4622 name
.pvStructInfo
= info
->pRequestorName
;
4623 name
.encodeFunc
= CRYPT_AsnEncodeAltNameEntry
;
4624 items
[count
].pvStructInfo
= &name
;
4625 items
[count
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
4628 if (info
->cRequestEntry
)
4630 items
[count
].pvStructInfo
= &info
->cRequestEntry
;
4631 items
[count
].encodeFunc
= CRYPT_AsnEncodeOCSPRequestEntries
;
4635 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4636 count
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4642 SetLastError(STATUS_ACCESS_VIOLATION
);
4649 static BOOL WINAPI
CRYPT_AsnEncodeOCSPSignedRequest(DWORD dwCertEncodingType
,
4650 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4651 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4657 const OCSP_SIGNED_REQUEST_INFO
*info
= pvStructInfo
;
4658 struct AsnEncodeSequenceItem items
[] = {
4659 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
4662 if (info
->pOptionalSignatureInfo
) FIXME("pOptionalSignatureInfo not supported\n");
4664 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4665 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4669 SetLastError(STATUS_ACCESS_VIOLATION
);
4676 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4677 LPCSTR lpszStructType
)
4679 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4681 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4682 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4684 SetLastError(ERROR_FILE_NOT_FOUND
);
4688 if (IS_INTOID(lpszStructType
))
4690 switch (LOWORD(lpszStructType
))
4692 case LOWORD(X509_CERT
):
4693 encodeFunc
= CRYPT_AsnEncodeCert
;
4695 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4696 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4698 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4699 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4701 case LOWORD(X509_EXTENSIONS
):
4702 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4704 case LOWORD(X509_NAME_VALUE
):
4705 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4707 case LOWORD(X509_NAME
):
4708 encodeFunc
= CRYPT_AsnEncodeName
;
4710 case LOWORD(X509_PUBLIC_KEY_INFO
):
4711 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4713 case LOWORD(X509_AUTHORITY_KEY_ID
):
4714 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4716 case LOWORD(X509_ALTERNATE_NAME
):
4717 encodeFunc
= CRYPT_AsnEncodeAltName
;
4719 case LOWORD(X509_BASIC_CONSTRAINTS
):
4720 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4722 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4723 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4725 case LOWORD(X509_CERT_POLICIES
):
4726 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4728 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4729 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4731 case LOWORD(X509_UNICODE_NAME
):
4732 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4734 case LOWORD(PKCS_CONTENT_INFO
):
4735 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4737 case LOWORD(PKCS_ATTRIBUTE
):
4738 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4740 case LOWORD(X509_UNICODE_NAME_VALUE
):
4741 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4743 case LOWORD(X509_OCTET_STRING
):
4744 encodeFunc
= CRYPT_AsnEncodeOctets
;
4746 case LOWORD(X509_BITS
):
4747 case LOWORD(X509_KEY_USAGE
):
4748 encodeFunc
= CRYPT_AsnEncodeBits
;
4750 case LOWORD(X509_INTEGER
):
4751 encodeFunc
= CRYPT_AsnEncodeInt
;
4753 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4754 encodeFunc
= CRYPT_AsnEncodeInteger
;
4756 case LOWORD(X509_MULTI_BYTE_UINT
):
4757 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4759 case LOWORD(X509_ENUMERATED
):
4760 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4762 case LOWORD(X509_CHOICE_OF_TIME
):
4763 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4765 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4766 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4768 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4769 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4771 case LOWORD(X509_SEQUENCE_OF_ANY
):
4772 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4774 case LOWORD(PKCS_UTC_TIME
):
4775 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4777 case LOWORD(X509_CRL_DIST_POINTS
):
4778 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4780 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4781 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4783 case LOWORD(PKCS_CTL
):
4784 encodeFunc
= CRYPT_AsnEncodeCTL
;
4786 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4787 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4789 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4790 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4792 case LOWORD(PKCS_ATTRIBUTES
):
4793 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4795 case LOWORD(X509_ISSUING_DIST_POINT
):
4796 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4798 case LOWORD(X509_NAME_CONSTRAINTS
):
4799 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4801 case LOWORD(X509_POLICY_MAPPINGS
):
4802 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4804 case LOWORD(X509_POLICY_CONSTRAINTS
):
4805 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4807 case LOWORD(PKCS7_SIGNER_INFO
):
4808 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4810 case LOWORD(CMS_SIGNER_INFO
):
4811 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4813 case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB
):
4814 encodeFunc
= CRYPT_AsnEncodeRsaPubKey_Bcrypt
;
4816 case LOWORD(OCSP_REQUEST
):
4817 encodeFunc
= CRYPT_AsnEncodeOCSPRequest
;
4819 case LOWORD(OCSP_SIGNED_REQUEST
):
4820 encodeFunc
= CRYPT_AsnEncodeOCSPSignedRequest
;
4823 FIXME("Unimplemented encoder for lpszStructType OID %d\n", LOWORD(lpszStructType
));
4826 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4827 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4828 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4829 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4830 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4831 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4832 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4833 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4834 else if (!strcmp(lpszStructType
, szOID_LEGACY_POLICY_MAPPINGS
))
4835 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4836 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4837 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4838 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4839 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4840 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4841 encodeFunc
= CRYPT_AsnEncodeBits
;
4842 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4843 encodeFunc
= CRYPT_AsnEncodeOctets
;
4844 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4845 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4846 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4847 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4848 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4849 encodeFunc
= CRYPT_AsnEncodeAltName
;
4850 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4851 encodeFunc
= CRYPT_AsnEncodeAltName
;
4852 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4853 encodeFunc
= CRYPT_AsnEncodeAltName
;
4854 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4855 encodeFunc
= CRYPT_AsnEncodeAltName
;
4856 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4857 encodeFunc
= CRYPT_AsnEncodeAltName
;
4858 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4859 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4860 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4861 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4862 else if (!strcmp(lpszStructType
, szOID_POLICY_MAPPINGS
))
4863 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4864 else if (!strcmp(lpszStructType
, szOID_POLICY_CONSTRAINTS
))
4865 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4866 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4867 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4868 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4869 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4870 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4871 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4872 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4873 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4874 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4875 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4876 else if (!strcmp(lpszStructType
, szOID_CTL
))
4877 encodeFunc
= CRYPT_AsnEncodeCTL
;
4879 FIXME("Unsupported encoder for lpszStructType %s\n", lpszStructType
);
4883 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4884 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4886 static HCRYPTOIDFUNCSET set
= NULL
;
4887 CryptEncodeObjectFunc encodeFunc
= NULL
;
4890 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4891 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4892 (void **)&encodeFunc
, hFunc
);
4896 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4897 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4899 static HCRYPTOIDFUNCSET set
= NULL
;
4900 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4903 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4904 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4905 (void **)&encodeFunc
, hFunc
);
4909 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4910 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4913 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4914 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4915 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4917 TRACE_(crypt
)("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
4918 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4921 if (!pbEncoded
&& !pcbEncoded
)
4923 SetLastError(ERROR_INVALID_PARAMETER
);
4927 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4930 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4931 debugstr_a(lpszStructType
));
4932 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4933 lpszStructType
, &hFunc
);
4934 if (!pCryptEncodeObject
)
4935 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4936 lpszStructType
, &hFunc
);
4938 if (pCryptEncodeObject
)
4939 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4940 pvStructInfo
, pbEncoded
, pcbEncoded
);
4941 else if (pCryptEncodeObjectEx
)
4942 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4943 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4945 CryptFreeOIDFunctionAddress(hFunc
, 0);
4946 TRACE_(crypt
)("returning %d\n", ret
);
4950 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4951 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4952 void *pvEncoded
, DWORD
*pcbEncoded
)
4955 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4956 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4958 TRACE_(crypt
)("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
4959 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4960 pvEncoded
, pcbEncoded
);
4962 if (!pvEncoded
&& !pcbEncoded
)
4964 SetLastError(ERROR_INVALID_PARAMETER
);
4968 SetLastError(NOERROR
);
4969 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
) {
4971 SetLastError(ERROR_INVALID_PARAMETER
);
4974 *(BYTE
**)pvEncoded
= NULL
;
4976 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4979 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4980 debugstr_a(lpszStructType
));
4981 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4985 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4986 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4989 CryptEncodeObjectFunc pCryptEncodeObject
=
4990 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4992 if (pCryptEncodeObject
)
4994 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4996 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4997 pvStructInfo
, NULL
, pcbEncoded
);
4998 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4999 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
5000 ret
= pCryptEncodeObject(dwCertEncodingType
,
5001 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
5005 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
5006 pvStructInfo
, pvEncoded
, pcbEncoded
);
5010 CryptFreeOIDFunctionAddress(hFunc
, 0);
5011 TRACE_(crypt
)("returning %d\n", ret
);
5015 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
5016 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5018 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5019 NULL
, 0, NULL
, pInfo
, pcbInfo
);
5022 typedef BOOL (WINAPI
*EncodePublicKeyAndParametersFunc
)(DWORD dwCertEncodingType
,
5023 LPSTR pszPublicKeyObjId
, BYTE
*pbPubKey
, DWORD cbPubKey
, DWORD dwFlags
, void *pvAuxInfo
,
5024 BYTE
**ppPublicKey
, DWORD
*pcbPublicKey
, BYTE
**ppbParams
, DWORD
*pcbParams
);
5026 static BOOL WINAPI
CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
5027 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5028 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5032 static CHAR rsa_oid
[] = szOID_RSA_RSA
;
5034 TRACE_(crypt
)("(%08Ix, %ld, %08lx, %s, %08lx, %p, %p, %ld)\n", hCryptProv
,
5035 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
5036 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
5038 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
5042 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
5045 PUBLICKEYSTRUC
*pubKey
= CryptMemAlloc(keySize
);
5049 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, (BYTE
*)pubKey
, &keySize
);
5054 if (!pszPublicKeyObjId
)
5056 static HCRYPTOIDFUNCSET set
;
5057 EncodePublicKeyAndParametersFunc encodeFunc
= NULL
;
5058 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5060 pszPublicKeyObjId
= (LPSTR
)CertAlgIdToOID(pubKey
->aiKeyAlg
);
5061 TRACE("public key algid %#x (%s)\n", pubKey
->aiKeyAlg
, debugstr_a(pszPublicKeyObjId
));
5063 if (!set
) /* FIXME: there is no a public macro */
5064 set
= CryptInitOIDFunctionSet("CryptDllEncodePublicKeyAndParameters", 0);
5066 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
, 0, (void **)&encodeFunc
, &hFunc
);
5069 BYTE
*key_data
= NULL
;
5071 BYTE
*params
= NULL
;
5072 DWORD params_size
= 0;
5074 ret
= encodeFunc(dwCertEncodingType
, pszPublicKeyObjId
, (BYTE
*)pubKey
, keySize
,
5075 dwFlags
, pvAuxInfo
, &key_data
, &key_size
, ¶ms
, ¶ms_size
);
5078 DWORD oid_size
= strlen(pszPublicKeyObjId
) + 1;
5079 DWORD size_needed
= sizeof(*pInfo
) + oid_size
+ key_size
+ params_size
;
5082 *pcbInfo
= size_needed
;
5083 else if (*pcbInfo
< size_needed
)
5085 *pcbInfo
= size_needed
;
5086 SetLastError(ERROR_MORE_DATA
);
5091 *pcbInfo
= size_needed
;
5092 pInfo
->Algorithm
.pszObjId
= (char *)(pInfo
+ 1);
5093 lstrcpyA(pInfo
->Algorithm
.pszObjId
, pszPublicKeyObjId
);
5096 pInfo
->Algorithm
.Parameters
.cbData
= params_size
;
5097 pInfo
->Algorithm
.Parameters
.pbData
= (BYTE
*)pInfo
->Algorithm
.pszObjId
+ oid_size
;
5098 memcpy(pInfo
->Algorithm
.Parameters
.pbData
, params
, params_size
);
5102 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5103 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5105 pInfo
->PublicKey
.pbData
= (BYTE
*)pInfo
->Algorithm
.pszObjId
+ oid_size
+ params_size
;
5106 pInfo
->PublicKey
.cbData
= key_size
;
5107 memcpy(pInfo
->PublicKey
.pbData
, key_data
, key_size
);
5108 pInfo
->PublicKey
.cUnusedBits
= 0;
5111 CryptMemFree(key_data
);
5112 CryptMemFree(params
);
5115 CryptMemFree(pubKey
);
5116 CryptFreeOIDFunctionAddress(hFunc
, 0);
5120 /* fallback to RSA */
5121 pszPublicKeyObjId
= rsa_oid
;
5125 ret
= CryptEncodeObject(dwCertEncodingType
,
5126 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
5129 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
5130 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
5133 *pcbInfo
= sizeNeeded
;
5134 else if (*pcbInfo
< sizeNeeded
)
5136 SetLastError(ERROR_MORE_DATA
);
5137 *pcbInfo
= sizeNeeded
;
5142 *pcbInfo
= sizeNeeded
;
5143 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
5144 sizeof(CERT_PUBLIC_KEY_INFO
);
5145 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
5147 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5148 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5149 pInfo
->PublicKey
.pbData
=
5150 (BYTE
*)pInfo
->Algorithm
.pszObjId
5151 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
5152 pInfo
->PublicKey
.cbData
= encodedLen
;
5153 pInfo
->PublicKey
.cUnusedBits
= 0;
5154 ret
= CryptEncodeObject(dwCertEncodingType
,
5155 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
5156 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
5160 CryptMemFree(pubKey
);
5165 CryptDestroyKey(key
);
5170 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
5171 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5172 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
5174 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
5175 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
5176 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5178 static HCRYPTOIDFUNCSET set
= NULL
;
5180 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
5181 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5183 TRACE_(crypt
)("(%08Ix, %ld, %08lx, %s, %08lx, %p, %p, %ld)\n", hCryptProv
,
5184 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
5185 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
5189 SetLastError(ERROR_INVALID_PARAMETER
);
5193 if (pszPublicKeyObjId
)
5196 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
5198 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
5199 0, (void **)&exportFunc
, &hFunc
);
5202 exportFunc
= CRYPT_ExportPublicKeyInfoEx
;
5203 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5204 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
5206 CryptFreeOIDFunctionAddress(hFunc
, 0);
5210 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5211 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5213 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5217 typedef BOOL (WINAPI
*ConvertPublicKeyInfoFunc
)(DWORD dwCertEncodingType
,
5218 PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
, DWORD dwFlags
,
5219 BYTE
**ppbData
, DWORD
*dwDataLen
);
5221 static BOOL WINAPI
CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5222 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5223 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5225 static HCRYPTOIDFUNCSET set
= NULL
;
5226 ConvertPublicKeyInfoFunc convertFunc
= NULL
;
5227 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5232 TRACE_(crypt
)("(%08Ix, %08lx, %p, %08x, %08lx, %p, %p)\n", hCryptProv
,
5233 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5236 set
= CryptInitOIDFunctionSet(CRYPT_OID_CONVERT_PUBLIC_KEY_INFO_FUNC
, 0);
5237 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pInfo
->Algorithm
.pszObjId
,
5238 0, (void **)&convertFunc
, &hFunc
);
5243 ret
= convertFunc(dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, &pubKey
, &pubKeySize
);
5246 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0, phKey
);
5247 CryptMemFree(pubKey
);
5250 CryptFreeOIDFunctionAddress(hFunc
, 0);
5254 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5255 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5258 pubKey
= CryptMemAlloc(pubKeySize
);
5262 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5263 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5268 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
5269 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5272 CryptMemFree(pubKey
);
5280 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5281 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5282 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5284 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5285 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5286 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5288 static HCRYPTOIDFUNCSET set
= NULL
;
5290 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5291 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5293 TRACE_(crypt
)("(%08Ix, %08lx, %p, %08x, %08lx, %p, %p)\n", hCryptProv
,
5294 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5297 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
5298 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
5299 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
5301 importFunc
= CRYPT_ImportPublicKeyInfoEx
;
5302 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
5305 CryptFreeOIDFunctionAddress(hFunc
, 0);
5309 BOOL WINAPI
CryptImportPublicKeyInfoEx2(DWORD dwCertEncodingType
,
5310 PCERT_PUBLIC_KEY_INFO pInfo
, DWORD dwFlags
, void *pvAuxInfo
,
5311 BCRYPT_KEY_HANDLE
*phKey
)
5313 TRACE_(crypt
)("(%ld, %p, %08lx, %p, %p)\n", dwCertEncodingType
, pInfo
,
5314 dwFlags
, pvAuxInfo
, phKey
);
5317 FIXME("flags %#lx ignored\n", dwFlags
);
5319 return CNG_ImportPubKey(pInfo
, phKey
);