2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
34 #include "wine/port.h"
41 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
55 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
93 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
95 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
96 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
97 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
98 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
99 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
100 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
101 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
103 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
104 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
108 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
110 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
111 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
113 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
114 if (!*(BYTE
**)pbEncoded
)
117 *pcbEncoded
= bytesNeeded
;
119 else if (bytesNeeded
> *pcbEncoded
)
121 *pcbEncoded
= bytesNeeded
;
122 SetLastError(ERROR_MORE_DATA
);
126 *pcbEncoded
= bytesNeeded
;
130 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
132 DWORD bytesNeeded
, significantBytes
= 0;
140 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
141 temp
<<= 8, significantBytes
--)
143 bytesNeeded
= significantBytes
+ 1;
147 *pcbEncoded
= bytesNeeded
;
150 if (*pcbEncoded
< bytesNeeded
)
152 SetLastError(ERROR_MORE_DATA
);
156 *pbEncoded
= (BYTE
)len
;
161 *pbEncoded
++ = significantBytes
| 0x80;
162 for (i
= 0; i
< significantBytes
; i
++)
164 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
168 *pcbEncoded
= bytesNeeded
;
172 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
173 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
174 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
177 DWORD i
, dataLen
= 0;
179 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
180 pbEncoded
, *pcbEncoded
);
181 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
183 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
184 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
185 NULL
, &items
[i
].size
);
186 /* Some functions propagate their errors through the size */
188 *pcbEncoded
= items
[i
].size
;
189 dataLen
+= items
[i
].size
;
193 DWORD lenBytes
, bytesNeeded
;
195 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
196 bytesNeeded
= 1 + lenBytes
+ dataLen
;
198 *pcbEncoded
= bytesNeeded
;
201 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
202 pcbEncoded
, bytesNeeded
)))
204 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
205 pbEncoded
= *(BYTE
**)pbEncoded
;
206 *pbEncoded
++ = ASN_SEQUENCE
;
207 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
208 pbEncoded
+= lenBytes
;
209 for (i
= 0; ret
&& i
< cItem
; i
++)
211 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
212 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
213 NULL
, pbEncoded
, &items
[i
].size
);
214 /* Some functions propagate their errors through the size */
216 *pcbEncoded
= items
[i
].size
;
217 pbEncoded
+= items
[i
].size
;
222 TRACE("returning %d (%08x)\n", ret
, GetLastError());
226 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
227 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
228 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
231 const struct AsnConstructedItem
*item
= pvStructInfo
;
234 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
235 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
237 DWORD dataLen
, bytesNeeded
;
239 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
240 bytesNeeded
= 1 + dataLen
+ len
;
242 *pcbEncoded
= bytesNeeded
;
243 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
244 pbEncoded
, pcbEncoded
, bytesNeeded
)))
246 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
247 pbEncoded
= *(BYTE
**)pbEncoded
;
248 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
249 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
250 pbEncoded
+= dataLen
;
251 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
252 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
256 /* Some functions propagate their errors through the size */
263 /* Some functions propagate their errors through the size */
269 struct AsnEncodeTagSwappedItem
272 const void *pvStructInfo
;
273 CryptEncodeObjectExFunc encodeFunc
;
276 /* Sort of a wacky hack, it encodes something using the struct
277 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
278 * given in the struct AsnEncodeTagSwappedItem.
280 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
281 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
282 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
285 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
287 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
288 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
289 if (ret
&& pbEncoded
)
290 *pbEncoded
= item
->tag
;
294 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
295 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
296 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
298 const DWORD
*ver
= pvStructInfo
;
301 /* CERT_V1 is not encoded */
309 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
311 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
312 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
317 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
318 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
319 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
321 const CRYPT_DER_BLOB
*blob
= pvStructInfo
;
326 *pcbEncoded
= blob
->cbData
;
331 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
332 pcbEncoded
, blob
->cbData
)))
334 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
335 pbEncoded
= *(BYTE
**)pbEncoded
;
337 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
338 *pcbEncoded
= blob
->cbData
;
345 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
346 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
347 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
350 /* This has two filetimes in a row, a NotBefore and a NotAfter */
351 const FILETIME
*timePtr
= pvStructInfo
;
352 struct AsnEncodeSequenceItem items
[] = {
353 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
354 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
357 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
358 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
363 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
366 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
367 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
368 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
371 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
372 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
373 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
376 struct AsnEncodeSequenceItem items
[2] = {
377 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
378 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
381 if (algo
->Parameters
.cbData
)
382 items
[1].pvStructInfo
= &algo
->Parameters
;
384 items
[1].pvStructInfo
= &nullBlob
;
385 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
386 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
391 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
392 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
393 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
395 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
397 struct AsnEncodeSequenceItem items
[] = {
398 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
399 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
402 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
403 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
408 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
409 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
410 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
416 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
417 struct AsnEncodeSequenceItem items
[] = {
418 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
419 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
422 TRACE("Encoding public key with OID %s\n",
423 debugstr_a(info
->Algorithm
.pszObjId
));
424 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
425 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
430 SetLastError(STATUS_ACCESS_VIOLATION
);
437 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
438 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
439 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
445 const CERT_SIGNED_CONTENT_INFO
*info
= pvStructInfo
;
446 struct AsnEncodeSequenceItem items
[] = {
447 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
448 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
449 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
452 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
453 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
454 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
455 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
460 SetLastError(STATUS_ACCESS_VIOLATION
);
467 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
472 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
473 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
479 const CERT_INFO
*info
= pvStructInfo
;
480 struct AsnEncodeSequenceItem items
[10] = {
481 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
482 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
483 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
484 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
485 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
486 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
487 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
490 struct AsnConstructedItem constructed
[3] = { { 0 } };
491 DWORD cItem
= 7, cConstructed
= 0;
493 if (info
->IssuerUniqueId
.cbData
)
495 constructed
[cConstructed
].tag
= 1;
496 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
497 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
498 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
499 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
503 if (info
->SubjectUniqueId
.cbData
)
505 constructed
[cConstructed
].tag
= 2;
506 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
507 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
508 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
509 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
513 if (info
->cExtension
)
515 constructed
[cConstructed
].tag
= 3;
516 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
517 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
518 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
519 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
524 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
525 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
529 SetLastError(STATUS_ACCESS_VIOLATION
);
536 static BOOL
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
537 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
539 struct AsnEncodeSequenceItem items
[3] = {
540 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
541 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
547 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
549 if (entry
->cExtension
)
551 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
552 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
556 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
557 pbEncoded
, pcbEncoded
);
559 TRACE("returning %d (%08x)\n", ret
, GetLastError());
563 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
564 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
565 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
567 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
568 const CRL_INFO
*info
= pvStructInfo
;
569 const CRL_ENTRY
*rgCRLEntry
= info
->rgCRLEntry
;
572 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cCRLEntry
; i
++)
576 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
582 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
583 bytesNeeded
= 1 + lenBytes
+ dataLen
;
585 *pcbEncoded
= bytesNeeded
;
588 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
589 pcbEncoded
, bytesNeeded
)))
591 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
592 pbEncoded
= *(BYTE
**)pbEncoded
;
593 *pbEncoded
++ = ASN_SEQUENCEOF
;
594 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
595 pbEncoded
+= lenBytes
;
596 for (i
= 0; i
< info
->cCRLEntry
; i
++)
598 DWORD size
= dataLen
;
600 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
,
611 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
612 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
613 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
615 const DWORD
*ver
= pvStructInfo
;
618 /* CRL_V1 is not encoded */
625 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
626 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
630 /* Like in Windows, this blithely ignores the validity of the passed-in
631 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
632 * decode properly, see CRYPT_AsnDecodeCRLInfo.
634 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
635 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
636 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
642 const CRL_INFO
*info
= pvStructInfo
;
643 struct AsnEncodeSequenceItem items
[7] = {
644 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
645 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
646 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
647 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
650 struct AsnConstructedItem constructed
[1] = { { 0 } };
651 DWORD cItem
= 4, cConstructed
= 0;
653 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
655 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
656 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
661 items
[cItem
].pvStructInfo
= info
;
662 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
665 if (info
->cExtension
)
667 constructed
[cConstructed
].tag
= 0;
668 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
669 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
670 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
671 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
676 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
677 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
681 SetLastError(STATUS_ACCESS_VIOLATION
);
688 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
692 struct AsnEncodeSequenceItem items
[3] = {
693 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
699 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
703 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
704 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
707 items
[cItem
].pvStructInfo
= &ext
->Value
;
708 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
711 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
712 pbEncoded
, pcbEncoded
);
713 TRACE("returning %d (%08x)\n", ret
, GetLastError());
717 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
718 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
719 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
725 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
726 const CERT_EXTENSIONS
*exts
= pvStructInfo
;
729 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
733 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
739 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
740 bytesNeeded
= 1 + lenBytes
+ dataLen
;
742 *pcbEncoded
= bytesNeeded
;
745 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
746 pbEncoded
, pcbEncoded
, bytesNeeded
)))
748 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
749 pbEncoded
= *(BYTE
**)pbEncoded
;
750 *pbEncoded
++ = ASN_SEQUENCEOF
;
751 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
752 pbEncoded
+= lenBytes
;
753 for (i
= 0; i
< exts
->cExtension
; i
++)
755 DWORD size
= dataLen
;
757 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
768 SetLastError(STATUS_ACCESS_VIOLATION
);
775 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
776 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
777 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
779 LPCSTR pszObjId
= pvStructInfo
;
780 DWORD bytesNeeded
= 0, lenBytes
;
785 TRACE("%s\n", debugstr_a(pszObjId
));
792 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
794 SetLastError(CRYPT_E_ASN1_ERROR
);
798 firstByte
= val1
* 40 + val2
;
799 ptr
= pszObjId
+ firstPos
;
809 /* note I assume each component is at most 32-bits long in base 2 */
810 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
812 if (val1
>= 0x10000000)
814 else if (val1
>= 0x200000)
816 else if (val1
>= 0x4000)
818 else if (val1
>= 0x80)
828 SetLastError(CRYPT_E_ASN1_ERROR
);
832 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
836 bytesNeeded
+= 1 + lenBytes
;
839 if (*pcbEncoded
< bytesNeeded
)
841 SetLastError(ERROR_MORE_DATA
);
846 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
847 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
848 pbEncoded
+= lenBytes
;
854 *pbEncoded
++ = firstByte
;
855 ptr
= pszObjId
+ firstPos
;
858 sscanf(ptr
, "%d%n", &val
, &pos
);
860 unsigned char outBytes
[5];
863 if (val
>= 0x10000000)
865 else if (val
>= 0x200000)
867 else if (val
>= 0x4000)
869 else if (val
>= 0x80)
873 for (i
= numBytes
; i
> 0; i
--)
875 outBytes
[i
- 1] = val
& 0x7f;
878 for (i
= 0; i
< numBytes
- 1; i
++)
879 *pbEncoded
++ = outBytes
[i
] | 0x80;
880 *pbEncoded
++ = outBytes
[i
];
889 *pcbEncoded
= bytesNeeded
;
893 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
894 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
898 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
899 DWORD bytesNeeded
, lenBytes
, encodedLen
;
901 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
902 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
903 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
905 *pcbEncoded
= bytesNeeded
;
908 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
909 pbEncoded
, pcbEncoded
, bytesNeeded
)))
911 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
912 pbEncoded
= *(BYTE
**)pbEncoded
;
914 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
915 pbEncoded
+= lenBytes
;
916 memcpy(pbEncoded
, str
, encodedLen
);
922 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
923 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
927 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
928 DWORD bytesNeeded
, lenBytes
, strLen
;
930 if (value
->Value
.cbData
)
931 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
932 else if (value
->Value
.pbData
)
933 strLen
= lstrlenW(str
);
936 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
937 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
939 *pcbEncoded
= bytesNeeded
;
942 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
943 pbEncoded
, pcbEncoded
, bytesNeeded
)))
947 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
948 pbEncoded
= *(BYTE
**)pbEncoded
;
949 *pbEncoded
++ = ASN_BMPSTRING
;
950 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
951 pbEncoded
+= lenBytes
;
952 for (i
= 0; i
< strLen
; i
++)
954 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
955 *pbEncoded
++ = str
[i
] & 0x00ff;
962 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
963 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
967 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
968 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
970 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
972 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
974 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
975 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
977 *pcbEncoded
= bytesNeeded
;
980 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
981 pbEncoded
, pcbEncoded
, bytesNeeded
)))
983 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
984 pbEncoded
= *(BYTE
**)pbEncoded
;
985 *pbEncoded
++ = ASN_UTF8STRING
;
986 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
987 pbEncoded
+= lenBytes
;
988 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
989 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
995 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
996 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
997 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1003 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1005 switch (value
->dwValueType
)
1007 case CERT_RDN_ANY_TYPE
:
1008 /* explicitly disallowed */
1009 SetLastError(E_INVALIDARG
);
1012 case CERT_RDN_ENCODED_BLOB
:
1013 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1014 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1016 case CERT_RDN_OCTET_STRING
:
1017 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1018 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1020 case CERT_RDN_NUMERIC_STRING
:
1021 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1022 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1024 case CERT_RDN_PRINTABLE_STRING
:
1025 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1026 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1028 case CERT_RDN_TELETEX_STRING
:
1029 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1030 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1032 case CERT_RDN_VIDEOTEX_STRING
:
1033 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1034 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1036 case CERT_RDN_IA5_STRING
:
1037 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1038 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1040 case CERT_RDN_GRAPHIC_STRING
:
1041 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1042 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1044 case CERT_RDN_VISIBLE_STRING
:
1045 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1046 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1048 case CERT_RDN_GENERAL_STRING
:
1049 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1050 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1052 case CERT_RDN_UNIVERSAL_STRING
:
1053 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1054 SetLastError(CRYPT_E_ASN1_CHOICE
);
1057 case CERT_RDN_BMP_STRING
:
1058 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1059 pbEncoded
, pcbEncoded
);
1061 case CERT_RDN_UTF8_STRING
:
1062 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1063 pbEncoded
, pcbEncoded
);
1066 SetLastError(CRYPT_E_ASN1_CHOICE
);
1072 SetLastError(STATUS_ACCESS_VIOLATION
);
1079 static BOOL
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1080 const CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1081 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1083 DWORD bytesNeeded
= 0, lenBytes
, size
;
1086 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1087 0, NULL
, NULL
, &size
);
1090 bytesNeeded
+= size
;
1091 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1092 * with dwValueType, so "cast" it to get its encoded size
1094 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
, &attr
->dwValueType
,
1095 0, NULL
, NULL
, &size
);
1098 bytesNeeded
+= size
;
1099 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1100 bytesNeeded
+= 1 + lenBytes
;
1103 if (*pcbEncoded
< bytesNeeded
)
1105 SetLastError(ERROR_MORE_DATA
);
1110 *pbEncoded
++ = ASN_SEQUENCE
;
1111 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1113 pbEncoded
+= lenBytes
;
1114 size
= bytesNeeded
- 1 - lenBytes
;
1115 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1116 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1120 size
= bytesNeeded
- 1 - lenBytes
- size
;
1121 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1122 &attr
->dwValueType
, 0, NULL
, pbEncoded
, &size
);
1129 *pcbEncoded
= bytesNeeded
;
1133 /* Have to propagate index of failing character */
1140 static int BLOBComp(const void *l
, const void *r
)
1142 const CRYPT_DER_BLOB
*a
= l
, *b
= r
;
1145 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1146 ret
= a
->cbData
- b
->cbData
;
1150 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1152 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1153 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1154 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1156 const CRYPT_BLOB_ARRAY
*set
= pvStructInfo
;
1157 DWORD bytesNeeded
= 0, lenBytes
, i
;
1160 for (i
= 0; i
< set
->cBlob
; i
++)
1161 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1162 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1163 bytesNeeded
+= 1 + lenBytes
;
1166 *pcbEncoded
= bytesNeeded
;
1169 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1170 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1172 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1173 pbEncoded
= *(BYTE
**)pbEncoded
;
1174 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1175 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1176 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1177 pbEncoded
+= lenBytes
;
1178 for (i
= 0; ret
&& i
< set
->cBlob
; i
++)
1180 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1181 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1187 struct DERSetDescriptor
1193 CryptEncodeObjectExFunc encode
;
1196 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1197 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1198 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1200 const struct DERSetDescriptor
*desc
= pvStructInfo
;
1201 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1207 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1212 setOf
.cBlob
= desc
->cItems
;
1213 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1216 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1218 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1219 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1220 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1223 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1224 if (!setOf
.rgBlob
[i
].pbData
)
1227 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1228 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1229 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1230 &setOf
.rgBlob
[i
].cbData
);
1232 /* Some functions propagate their errors through the size */
1234 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1238 DWORD bytesNeeded
= 0, lenBytes
;
1240 for (i
= 0; i
< setOf
.cBlob
; i
++)
1241 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1242 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1243 bytesNeeded
+= 1 + lenBytes
;
1245 *pcbEncoded
= bytesNeeded
;
1246 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1247 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1249 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1250 pbEncoded
= *(BYTE
**)pbEncoded
;
1251 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1253 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1254 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1255 pbEncoded
+= lenBytes
;
1256 for (i
= 0; i
< setOf
.cBlob
; i
++)
1258 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1259 setOf
.rgBlob
[i
].cbData
);
1260 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1264 for (i
= 0; i
< setOf
.cBlob
; i
++)
1265 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1266 CryptMemFree(setOf
.rgBlob
);
1270 static BOOL
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, const CERT_RDN
*rdn
,
1271 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1275 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1284 setOf
.cBlob
= rdn
->cRDNAttr
;
1285 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1286 sizeof(CRYPT_DER_BLOB
));
1290 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1292 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1294 setOf
.rgBlob
[i
].cbData
= 0;
1295 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1296 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1299 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1300 if (!setOf
.rgBlob
[i
].pbData
)
1303 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1304 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1305 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1309 /* Have to propagate index of failing character */
1310 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1314 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1315 pbEncoded
, pcbEncoded
);
1316 for (i
= 0; i
< setOf
.cBlob
; i
++)
1317 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1321 SetLastError(STATUS_ACCESS_VIOLATION
);
1325 CryptMemFree(setOf
.rgBlob
);
1329 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1330 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1331 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1333 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1334 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1335 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1338 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1341 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1342 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1343 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1345 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1346 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1350 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1351 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1352 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1358 const CERT_NAME_INFO
*info
= pvStructInfo
;
1359 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1361 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1363 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1365 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1366 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1368 bytesNeeded
+= size
;
1372 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1373 bytesNeeded
+= 1 + lenBytes
;
1377 *pcbEncoded
= bytesNeeded
;
1380 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1381 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1383 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1384 pbEncoded
= *(BYTE
**)pbEncoded
;
1385 *pbEncoded
++ = ASN_SEQUENCEOF
;
1386 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1388 pbEncoded
+= lenBytes
;
1389 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1392 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1393 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1398 bytesNeeded
-= size
;
1409 SetLastError(STATUS_ACCESS_VIOLATION
);
1416 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1417 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1418 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1420 const DWORD
*ver
= pvStructInfo
;
1423 /* CTL_V1 is not encoded */
1430 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1431 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1435 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1436 * if they are empty and the OID is not empty (otherwise omits them.)
1438 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1439 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1440 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1443 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
1445 struct AsnEncodeSequenceItem items
[2] = {
1446 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1452 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1453 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1456 if (algo
->Parameters
.cbData
)
1457 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1459 items
[cItem
].pvStructInfo
= &nullBlob
;
1460 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1463 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1464 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1468 static BOOL
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1469 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1471 struct AsnEncodeSequenceItem items
[2] = {
1472 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1473 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1477 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1478 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
1488 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1489 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1490 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1493 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1494 const struct CTLEntries
*entries
= pvStructInfo
;
1497 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1501 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1507 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1508 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1510 *pcbEncoded
= bytesNeeded
;
1513 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1514 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1516 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1517 pbEncoded
= *(BYTE
**)pbEncoded
;
1518 *pbEncoded
++ = ASN_SEQUENCEOF
;
1519 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1520 pbEncoded
+= lenBytes
;
1521 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1523 DWORD size
= dataLen
;
1525 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1536 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1537 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1538 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1544 const CTL_INFO
*info
= pvStructInfo
;
1545 struct AsnEncodeSequenceItem items
[9] = {
1546 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1547 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1549 struct AsnConstructedItem constructed
= { 0 };
1552 if (info
->ListIdentifier
.cbData
)
1554 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1555 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1558 if (info
->SequenceNumber
.cbData
)
1560 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1561 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1564 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1565 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1567 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1569 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1570 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1573 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1574 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1576 if (info
->cCTLEntry
)
1578 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1579 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1582 if (info
->cExtension
)
1584 constructed
.tag
= 0;
1585 constructed
.pvStructInfo
= &info
->cExtension
;
1586 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1587 items
[cItem
].pvStructInfo
= &constructed
;
1588 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1591 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1592 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1596 SetLastError(STATUS_ACCESS_VIOLATION
);
1602 static BOOL
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1603 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1604 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1610 const CRYPT_SMIME_CAPABILITY
*capability
= pvStructInfo
;
1612 if (!capability
->pszObjId
)
1613 SetLastError(E_INVALIDARG
);
1616 struct AsnEncodeSequenceItem items
[] = {
1617 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1618 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1621 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1622 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1628 SetLastError(STATUS_ACCESS_VIOLATION
);
1634 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1635 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1636 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1642 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1643 const CRYPT_SMIME_CAPABILITIES
*capabilities
= pvStructInfo
;
1646 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1650 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1651 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1657 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1658 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1660 *pcbEncoded
= bytesNeeded
;
1663 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1664 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1666 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1667 pbEncoded
= *(BYTE
**)pbEncoded
;
1668 *pbEncoded
++ = ASN_SEQUENCEOF
;
1669 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1670 pbEncoded
+= lenBytes
;
1671 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1673 DWORD size
= dataLen
;
1675 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1676 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1687 SetLastError(STATUS_ACCESS_VIOLATION
);
1693 static BOOL WINAPI
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType
,
1694 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1695 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1697 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1698 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1701 for (i
= 0, dataLen
= 0; ret
&& i
< noticeRef
->cNoticeNumbers
; i
++)
1705 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1706 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, NULL
, &size
);
1712 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1713 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1715 *pcbEncoded
= bytesNeeded
;
1718 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1719 pcbEncoded
, bytesNeeded
)))
1721 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1722 pbEncoded
= *(BYTE
**)pbEncoded
;
1723 *pbEncoded
++ = ASN_SEQUENCE
;
1724 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1725 pbEncoded
+= lenBytes
;
1726 for (i
= 0; i
< noticeRef
->cNoticeNumbers
; i
++)
1728 DWORD size
= dataLen
;
1730 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1731 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, pbEncoded
, &size
);
1741 static BOOL WINAPI
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType
,
1742 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1743 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1745 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1747 CERT_NAME_VALUE orgValue
= { CERT_RDN_IA5_STRING
,
1748 { 0, (LPBYTE
)noticeRef
->pszOrganization
} };
1749 struct AsnEncodeSequenceItem items
[] = {
1750 { &orgValue
, CRYPT_AsnEncodeNameValue
, 0 },
1751 { noticeRef
, CRYPT_AsnEncodeNoticeNumbers
, 0 },
1754 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1755 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1760 static BOOL WINAPI
CRYPT_AsnEncodePolicyQualifierUserNotice(
1761 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1762 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1769 const CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
= pvStructInfo
;
1770 struct AsnEncodeSequenceItem items
[2];
1771 CERT_NAME_VALUE displayTextValue
;
1775 if (notice
->pNoticeReference
)
1777 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNoticeReference
;
1778 items
[cItem
].pvStructInfo
= notice
->pNoticeReference
;
1781 if (notice
->pszDisplayText
)
1783 displayTextValue
.dwValueType
= CERT_RDN_BMP_STRING
;
1784 displayTextValue
.Value
.cbData
= 0;
1785 displayTextValue
.Value
.pbData
= (LPBYTE
)notice
->pszDisplayText
;
1786 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNameValue
;
1787 items
[cItem
].pvStructInfo
= &displayTextValue
;
1790 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1791 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1795 SetLastError(STATUS_ACCESS_VIOLATION
);
1801 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1802 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1803 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1809 const CRYPT_ATTRIBUTE
*attr
= pvStructInfo
;
1811 if (!attr
->pszObjId
)
1812 SetLastError(E_INVALIDARG
);
1815 struct AsnEncodeSequenceItem items
[2] = {
1816 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1817 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1820 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1821 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1827 SetLastError(STATUS_ACCESS_VIOLATION
);
1833 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1834 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1835 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1841 const CRYPT_ATTRIBUTES
*attributes
= pvStructInfo
;
1842 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1843 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1845 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1846 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1850 SetLastError(STATUS_ACCESS_VIOLATION
);
1856 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1857 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1858 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1859 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1862 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1863 struct AsnEncodeSequenceItem items
[2] = {
1864 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1867 struct AsnConstructedItem constructed
= { 0 };
1870 if (info
->Content
.cbData
)
1872 constructed
.tag
= 0;
1873 constructed
.pvStructInfo
= &info
->Content
;
1874 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1875 items
[cItem
].pvStructInfo
= &constructed
;
1876 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1879 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1880 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1883 BOOL
CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA
*digestedData
,
1884 void *pvData
, DWORD
*pcbData
)
1886 struct AsnEncodeSequenceItem items
[] = {
1887 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1888 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1890 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1891 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1894 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1895 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1898 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1899 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1900 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1906 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1908 if (!info
->pszObjId
)
1909 SetLastError(E_INVALIDARG
);
1911 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1912 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1917 SetLastError(STATUS_ACCESS_VIOLATION
);
1923 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1924 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1928 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1929 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1931 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1933 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1934 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1936 *pcbEncoded
= bytesNeeded
;
1939 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1940 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1944 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1945 pbEncoded
= *(BYTE
**)pbEncoded
;
1947 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1948 pbEncoded
+= lenBytes
;
1949 for (i
= 0; i
< encodedLen
; i
++)
1950 *pbEncoded
++ = (BYTE
)str
[i
];
1956 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara
, LPVOID pv
)
1958 if (pEncodePara
&& pEncodePara
->pfnFree
)
1959 pEncodePara
->pfnFree(pv
);
1964 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1965 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1969 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1970 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1972 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1974 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1975 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1977 *pcbEncoded
= bytesNeeded
;
1980 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1981 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1986 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1987 ptr
= *(BYTE
**)pbEncoded
;
1990 *ptr
++ = ASN_NUMERICSTRING
;
1991 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1993 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1995 if (isdigitW(str
[i
]))
1996 *ptr
++ = (BYTE
)str
[i
];
2000 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2004 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2005 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2011 static inline int isprintableW(WCHAR wc
)
2013 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
2014 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
2015 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
2018 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2019 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2023 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2024 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2026 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2028 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2029 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2031 *pcbEncoded
= bytesNeeded
;
2034 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2035 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2040 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2041 ptr
= *(BYTE
**)pbEncoded
;
2044 *ptr
++ = ASN_PRINTABLESTRING
;
2045 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2047 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2049 if (isprintableW(str
[i
]))
2050 *ptr
++ = (BYTE
)str
[i
];
2054 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2058 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2059 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2065 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2066 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2070 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2071 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2073 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2075 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2076 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2078 *pcbEncoded
= bytesNeeded
;
2081 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2082 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2087 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2088 ptr
= *(BYTE
**)pbEncoded
;
2091 *ptr
++ = ASN_IA5STRING
;
2092 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2094 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2097 *ptr
++ = (BYTE
)str
[i
];
2101 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2105 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2106 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2112 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2113 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
2117 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2118 DWORD bytesNeeded
, lenBytes
, strLen
;
2120 /* FIXME: doesn't handle composite characters */
2121 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
2123 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2124 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2126 *pcbEncoded
= bytesNeeded
;
2129 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2130 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2134 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2135 pbEncoded
= *(BYTE
**)pbEncoded
;
2136 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2137 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2138 pbEncoded
+= lenBytes
;
2139 for (i
= 0; i
< strLen
; i
++)
2143 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2144 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2151 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2152 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2153 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2159 const CERT_NAME_VALUE
*value
= pvStructInfo
;
2161 switch (value
->dwValueType
)
2163 case CERT_RDN_ANY_TYPE
:
2164 case CERT_RDN_ENCODED_BLOB
:
2165 case CERT_RDN_OCTET_STRING
:
2166 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2168 case CERT_RDN_NUMERIC_STRING
:
2169 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2170 pbEncoded
, pcbEncoded
);
2172 case CERT_RDN_PRINTABLE_STRING
:
2173 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2174 pbEncoded
, pcbEncoded
);
2176 case CERT_RDN_TELETEX_STRING
:
2177 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2178 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2180 case CERT_RDN_VIDEOTEX_STRING
:
2181 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2182 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2184 case CERT_RDN_IA5_STRING
:
2185 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2186 pbEncoded
, pcbEncoded
);
2188 case CERT_RDN_GRAPHIC_STRING
:
2189 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2190 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2192 case CERT_RDN_VISIBLE_STRING
:
2193 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2194 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2196 case CERT_RDN_GENERAL_STRING
:
2197 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2198 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2200 case CERT_RDN_UNIVERSAL_STRING
:
2201 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2202 pbEncoded
, pcbEncoded
);
2204 case CERT_RDN_BMP_STRING
:
2205 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2206 pbEncoded
, pcbEncoded
);
2208 case CERT_RDN_UTF8_STRING
:
2209 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2210 pbEncoded
, pcbEncoded
);
2213 SetLastError(CRYPT_E_ASN1_CHOICE
);
2218 SetLastError(STATUS_ACCESS_VIOLATION
);
2224 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2225 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2226 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2232 const CERT_NAME_INFO
*info
= pvStructInfo
;
2233 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2235 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2237 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2239 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2240 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2242 bytesNeeded
+= size
;
2244 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2245 bytesNeeded
+= 1 + lenBytes
;
2249 *pcbEncoded
= bytesNeeded
;
2252 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2253 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2255 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2256 pbEncoded
= *(BYTE
**)pbEncoded
;
2257 *pbEncoded
++ = ASN_SEQUENCEOF
;
2258 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2260 pbEncoded
+= lenBytes
;
2261 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2264 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2265 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
2270 bytesNeeded
-= size
;
2279 SetLastError(STATUS_ACCESS_VIOLATION
);
2286 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2287 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2288 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2290 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2299 else if (*pcbEncoded
< 3)
2302 SetLastError(ERROR_MORE_DATA
);
2308 *pbEncoded
++ = ASN_BOOL
;
2310 *pbEncoded
++ = val
? 0xff : 0;
2313 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2317 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2318 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2319 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2321 const CERT_ALT_NAME_ENTRY
*entry
= pvStructInfo
;
2327 switch (entry
->dwAltNameChoice
)
2329 case CERT_ALT_NAME_RFC822_NAME
:
2330 case CERT_ALT_NAME_DNS_NAME
:
2331 case CERT_ALT_NAME_URL
:
2332 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2333 if (entry
->u
.pwszURL
)
2337 /* Not + 1: don't encode the NULL-terminator */
2338 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2339 for (i
= 0; ret
&& i
< dataLen
; i
++)
2341 if (entry
->u
.pwszURL
[i
] > 0x7f)
2343 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2352 case CERT_ALT_NAME_DIRECTORY_NAME
:
2353 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2354 dataLen
= entry
->u
.DirectoryName
.cbData
;
2356 case CERT_ALT_NAME_IP_ADDRESS
:
2357 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2358 dataLen
= entry
->u
.IPAddress
.cbData
;
2360 case CERT_ALT_NAME_REGISTERED_ID
:
2362 struct AsnEncodeTagSwappedItem swapped
=
2363 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2364 CRYPT_AsnEncodeOid
};
2366 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2369 case CERT_ALT_NAME_OTHER_NAME
:
2370 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2373 SetLastError(E_INVALIDARG
);
2378 DWORD bytesNeeded
, lenBytes
;
2380 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2381 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2383 *pcbEncoded
= bytesNeeded
;
2384 else if (*pcbEncoded
< bytesNeeded
)
2386 SetLastError(ERROR_MORE_DATA
);
2387 *pcbEncoded
= bytesNeeded
;
2393 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2394 pbEncoded
+= lenBytes
;
2395 switch (entry
->dwAltNameChoice
)
2397 case CERT_ALT_NAME_RFC822_NAME
:
2398 case CERT_ALT_NAME_DNS_NAME
:
2399 case CERT_ALT_NAME_URL
:
2403 for (i
= 0; i
< dataLen
; i
++)
2404 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2407 case CERT_ALT_NAME_DIRECTORY_NAME
:
2408 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2410 case CERT_ALT_NAME_IP_ADDRESS
:
2411 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2415 *pcbEncoded
= bytesNeeded
;
2418 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2422 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2423 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2424 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2430 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
2431 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2436 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2441 for (i
= 0; i
< newBlob
.cbData
; i
++)
2442 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2448 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2449 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2450 CryptMemFree(newBlob
.pbData
);
2454 SetLastError(STATUS_ACCESS_VIOLATION
);
2461 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2462 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2463 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2469 const CERT_AUTHORITY_KEY_ID_INFO
*info
= pvStructInfo
;
2470 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2471 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2472 struct AsnConstructedItem constructed
= { 0 };
2473 DWORD cItem
= 0, cSwapped
= 0;
2475 if (info
->KeyId
.cbData
)
2477 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2478 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2479 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2480 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2481 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2485 if (info
->CertIssuer
.cbData
)
2487 constructed
.tag
= 1;
2488 constructed
.pvStructInfo
= &info
->CertIssuer
;
2489 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2490 items
[cItem
].pvStructInfo
= &constructed
;
2491 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2494 if (info
->CertSerialNumber
.cbData
)
2496 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2497 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2498 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2499 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2500 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2504 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2505 pEncodePara
, pbEncoded
, pcbEncoded
);
2509 SetLastError(STATUS_ACCESS_VIOLATION
);
2516 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2517 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2518 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2524 const CERT_ALT_NAME_INFO
*info
= pvStructInfo
;
2525 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2528 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2529 * can't encode an erroneous entry index if it's bigger than this.
2531 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2535 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2536 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2539 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2541 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2542 * the bad character, now set the index of the bad
2545 *pcbEncoded
= (BYTE
)i
<<
2546 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2551 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2552 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2555 *pcbEncoded
= bytesNeeded
;
2560 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2561 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2563 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2564 pbEncoded
= *(BYTE
**)pbEncoded
;
2565 *pbEncoded
++ = ASN_SEQUENCEOF
;
2566 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2567 pbEncoded
+= lenBytes
;
2568 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2570 DWORD len
= dataLen
;
2572 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2573 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, pbEncoded
, &len
);
2586 SetLastError(STATUS_ACCESS_VIOLATION
);
2593 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2594 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2595 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2601 const CERT_AUTHORITY_KEY_ID2_INFO
*info
= pvStructInfo
;
2602 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2603 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2604 DWORD cItem
= 0, cSwapped
= 0;
2606 if (info
->KeyId
.cbData
)
2608 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2609 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2610 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2611 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2612 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2616 if (info
->AuthorityCertIssuer
.cAltEntry
)
2618 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2619 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2620 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2621 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2622 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2626 if (info
->AuthorityCertSerialNumber
.cbData
)
2628 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2629 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2630 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2631 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2632 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2636 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2637 pEncodePara
, pbEncoded
, pcbEncoded
);
2641 SetLastError(STATUS_ACCESS_VIOLATION
);
2648 static BOOL
CRYPT_AsnEncodeAccessDescription(
2649 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2651 struct AsnEncodeSequenceItem items
[] = {
2652 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2653 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2656 if (!descr
->pszAccessMethod
)
2658 SetLastError(E_INVALIDARG
);
2661 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
2662 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pbEncoded
, pcbEncoded
);
2665 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2666 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2667 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2673 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2674 const CERT_AUTHORITY_INFO_ACCESS
*info
= pvStructInfo
;
2677 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2681 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2688 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2689 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2691 *pcbEncoded
= bytesNeeded
;
2694 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2695 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2697 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2698 pbEncoded
= *(BYTE
**)pbEncoded
;
2699 *pbEncoded
++ = ASN_SEQUENCEOF
;
2700 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2701 pbEncoded
+= lenBytes
;
2702 for (i
= 0; i
< info
->cAccDescr
; i
++)
2704 DWORD size
= dataLen
;
2706 ret
= CRYPT_AsnEncodeAccessDescription(
2707 &info
->rgAccDescr
[i
], pbEncoded
, &size
);
2717 SetLastError(STATUS_ACCESS_VIOLATION
);
2724 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2725 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2726 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2732 const CERT_BASIC_CONSTRAINTS_INFO
*info
= pvStructInfo
;
2733 struct AsnEncodeSequenceItem items
[3] = {
2734 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2739 if (info
->fPathLenConstraint
)
2741 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2742 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2745 if (info
->cSubtreesConstraint
)
2747 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2748 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2751 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2752 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2756 SetLastError(STATUS_ACCESS_VIOLATION
);
2763 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2764 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2765 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2771 const CERT_BASIC_CONSTRAINTS2_INFO
*info
= pvStructInfo
;
2772 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2777 items
[cItem
].pvStructInfo
= &info
->fCA
;
2778 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2781 if (info
->fPathLenConstraint
)
2783 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2784 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2787 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2788 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2792 SetLastError(STATUS_ACCESS_VIOLATION
);
2799 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2800 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2801 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2803 DWORD cPolicyQualifier
= *(DWORD
*)pvStructInfo
;
2804 const CERT_POLICY_QUALIFIER_INFO
*rgPolicyQualifier
=
2805 *(const CERT_POLICY_QUALIFIER_INFO
**)
2806 ((LPBYTE
)pvStructInfo
+ sizeof(DWORD
));
2809 if (!cPolicyQualifier
)
2816 struct AsnEncodeSequenceItem items
[2] = {
2817 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2818 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2820 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2823 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2825 items
[0].pvStructInfo
= rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2826 items
[1].pvStructInfo
= &rgPolicyQualifier
[i
].Qualifier
;
2827 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2828 sizeof(items
) / sizeof(items
[0]),
2829 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2831 bytesNeeded
+= size
;
2833 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2834 bytesNeeded
+= 1 + lenBytes
;
2838 *pcbEncoded
= bytesNeeded
;
2841 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2842 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2844 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2845 pbEncoded
= *(BYTE
**)pbEncoded
;
2846 *pbEncoded
++ = ASN_SEQUENCEOF
;
2847 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2849 pbEncoded
+= lenBytes
;
2850 for (i
= 0; ret
&& i
< cPolicyQualifier
; i
++)
2852 items
[0].pvStructInfo
=
2853 rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2854 items
[1].pvStructInfo
=
2855 &rgPolicyQualifier
[i
].Qualifier
;
2857 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2858 sizeof(items
) / sizeof(items
[0]),
2859 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2864 bytesNeeded
-= size
;
2874 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2875 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2878 struct AsnEncodeSequenceItem items
[2] = {
2879 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2880 { &info
->cPolicyQualifier
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2884 if (!info
->pszPolicyIdentifier
)
2886 SetLastError(E_INVALIDARG
);
2889 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2890 sizeof(items
) / sizeof(items
[0]), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2894 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2895 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2896 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2902 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2903 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2906 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2908 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2909 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2912 bytesNeeded
+= size
;
2914 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2915 bytesNeeded
+= 1 + lenBytes
;
2919 *pcbEncoded
= bytesNeeded
;
2922 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2923 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2925 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2926 pbEncoded
= *(BYTE
**)pbEncoded
;
2927 *pbEncoded
++ = ASN_SEQUENCEOF
;
2928 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2930 pbEncoded
+= lenBytes
;
2931 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2934 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2935 &info
->rgPolicyInfo
[i
],
2936 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pbEncoded
, &size
);
2940 bytesNeeded
-= size
;
2949 SetLastError(STATUS_ACCESS_VIOLATION
);
2955 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2956 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2957 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2963 const BLOBHEADER
*hdr
= pvStructInfo
;
2965 if (hdr
->bType
!= PUBLICKEYBLOB
)
2967 SetLastError(E_INVALIDARG
);
2972 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2973 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2974 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2975 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2976 struct AsnEncodeSequenceItem items
[] = {
2977 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2978 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2981 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2982 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2988 SetLastError(STATUS_ACCESS_VIOLATION
);
2995 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2996 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2997 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3003 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
3004 DWORD bytesNeeded
, lenBytes
;
3006 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3007 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
3009 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3010 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3013 *pcbEncoded
= bytesNeeded
;
3018 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3019 pcbEncoded
, bytesNeeded
)))
3021 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3022 pbEncoded
= *(BYTE
**)pbEncoded
;
3023 *pbEncoded
++ = ASN_OCTETSTRING
;
3024 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3025 pbEncoded
+= lenBytes
;
3027 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3033 SetLastError(STATUS_ACCESS_VIOLATION
);
3037 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3041 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3042 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3043 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3049 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3050 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3053 /* yep, MS allows cUnusedBits to be >= 8 */
3054 if (!blob
->cUnusedBits
)
3056 dataBytes
= blob
->cbData
;
3059 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3061 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3062 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3070 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3071 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3074 *pcbEncoded
= bytesNeeded
;
3079 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3080 pcbEncoded
, bytesNeeded
)))
3082 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3083 pbEncoded
= *(BYTE
**)pbEncoded
;
3084 *pbEncoded
++ = ASN_BITSTRING
;
3085 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3086 pbEncoded
+= lenBytes
;
3087 *pbEncoded
++ = unusedBits
;
3090 BYTE mask
= 0xff << unusedBits
;
3094 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3095 pbEncoded
+= dataBytes
- 1;
3097 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3104 SetLastError(STATUS_ACCESS_VIOLATION
);
3111 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3112 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3113 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3119 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3120 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3125 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3130 for (i
= 0; i
< newBlob
.cbData
; i
++)
3131 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3137 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3138 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3139 CryptMemFree(newBlob
.pbData
);
3143 SetLastError(STATUS_ACCESS_VIOLATION
);
3150 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3151 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3152 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3154 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3156 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3157 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3160 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3161 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3162 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3168 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3171 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3173 significantBytes
= blob
->cbData
;
3174 if (significantBytes
)
3176 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3178 /* negative, lop off leading (little-endian) 0xffs */
3179 for (; significantBytes
> 0 &&
3180 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3182 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3190 /* positive, lop off leading (little-endian) zeroes */
3191 for (; significantBytes
> 0 &&
3192 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3194 if (significantBytes
== 0)
3195 significantBytes
= 1;
3196 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3204 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3206 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3207 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3212 *pcbEncoded
= bytesNeeded
;
3217 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3218 pcbEncoded
, bytesNeeded
)))
3220 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3221 pbEncoded
= *(BYTE
**)pbEncoded
;
3222 *pbEncoded
++ = ASN_INTEGER
;
3225 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3226 pbEncoded
+= lenBytes
;
3227 *pbEncoded
++ = padByte
;
3231 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3232 pbEncoded
+= lenBytes
;
3234 for (; significantBytes
> 0; significantBytes
--)
3235 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3241 SetLastError(STATUS_ACCESS_VIOLATION
);
3248 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3249 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3250 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3256 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3258 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3260 significantBytes
= blob
->cbData
;
3261 if (significantBytes
)
3263 /* positive, lop off leading (little-endian) zeroes */
3264 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3267 if (significantBytes
== 0)
3268 significantBytes
= 1;
3269 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3273 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3275 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3276 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3281 *pcbEncoded
= bytesNeeded
;
3286 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3287 pcbEncoded
, bytesNeeded
)))
3289 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3290 pbEncoded
= *(BYTE
**)pbEncoded
;
3291 *pbEncoded
++ = ASN_INTEGER
;
3294 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3295 pbEncoded
+= lenBytes
;
3300 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3301 pbEncoded
+= lenBytes
;
3303 for (; significantBytes
> 0; significantBytes
--)
3304 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3310 SetLastError(STATUS_ACCESS_VIOLATION
);
3317 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3318 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3319 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3321 CRYPT_INTEGER_BLOB blob
;
3324 /* Encode as an unsigned integer, then change the tag to enumerated */
3325 blob
.cbData
= sizeof(DWORD
);
3326 blob
.pbData
= (BYTE
*)pvStructInfo
;
3327 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3328 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3329 if (ret
&& pbEncoded
)
3331 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3332 pbEncoded
= *(BYTE
**)pbEncoded
;
3333 pbEncoded
[0] = ASN_ENUMERATED
;
3338 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3339 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3340 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3347 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3348 * temporary buffer because the output buffer is not NULL-terminated.
3351 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3355 *pcbEncoded
= bytesNeeded
;
3360 /* Sanity check the year, this is a two-digit year format */
3361 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3362 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3364 SetLastError(CRYPT_E_BAD_ENCODE
);
3369 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3370 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3372 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3373 pbEncoded
= *(BYTE
**)pbEncoded
;
3374 buf
[0] = ASN_UTCTIME
;
3375 buf
[1] = bytesNeeded
- 2;
3376 snprintf(buf
+ 2, sizeof(buf
) - 2,
3377 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3378 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3379 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3380 sysTime
.wMinute
, sysTime
.wSecond
);
3381 memcpy(pbEncoded
, buf
, bytesNeeded
);
3388 SetLastError(STATUS_ACCESS_VIOLATION
);
3395 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3396 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3397 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3404 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3405 * temporary buffer because the output buffer is not NULL-terminated.
3408 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
3412 *pcbEncoded
= bytesNeeded
;
3417 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3419 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3420 pcbEncoded
, bytesNeeded
);
3423 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3424 pbEncoded
= *(BYTE
**)pbEncoded
;
3425 buf
[0] = ASN_GENERALTIME
;
3426 buf
[1] = bytesNeeded
- 2;
3427 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3428 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3429 sysTime
.wMinute
, sysTime
.wSecond
);
3430 memcpy(pbEncoded
, buf
, bytesNeeded
);
3436 SetLastError(STATUS_ACCESS_VIOLATION
);
3443 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3444 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3445 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3453 /* Check the year, if it's in the UTCTime range call that encode func */
3454 if (!FileTimeToSystemTime(pvStructInfo
, &sysTime
))
3456 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3457 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3458 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3460 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3461 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3466 SetLastError(STATUS_ACCESS_VIOLATION
);
3473 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3474 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3475 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3481 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3482 const CRYPT_SEQUENCE_OF_ANY
*seq
= pvStructInfo
;
3484 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3485 dataLen
+= seq
->rgValue
[i
].cbData
;
3486 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3487 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3490 *pcbEncoded
= bytesNeeded
;
3495 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3496 pcbEncoded
, bytesNeeded
)))
3498 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3499 pbEncoded
= *(BYTE
**)pbEncoded
;
3500 *pbEncoded
++ = ASN_SEQUENCEOF
;
3501 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3502 pbEncoded
+= lenBytes
;
3503 for (i
= 0; i
< seq
->cValue
; i
++)
3505 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3506 seq
->rgValue
[i
].cbData
);
3507 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3514 SetLastError(STATUS_ACCESS_VIOLATION
);
3521 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3522 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3525 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3526 struct AsnConstructedItem constructed
= { 0 };
3527 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3528 DWORD cItem
= 0, cSwapped
= 0;
3530 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3532 case CRL_DIST_POINT_NO_NAME
:
3535 case CRL_DIST_POINT_FULL_NAME
:
3536 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3537 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3538 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3539 constructed
.tag
= 0;
3540 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3541 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3542 items
[cItem
].pvStructInfo
= &constructed
;
3543 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3547 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3548 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3554 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3556 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3557 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3558 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3559 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3560 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3564 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3566 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3567 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3568 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3569 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3570 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3575 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3576 pbEncoded
, pcbEncoded
);
3580 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3581 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3582 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3588 const CRL_DIST_POINTS_INFO
*info
= pvStructInfo
;
3590 if (!info
->cDistPoint
)
3592 SetLastError(E_INVALIDARG
);
3597 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3600 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3604 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3608 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3610 /* Have to propagate index of failing character */
3616 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3617 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3620 *pcbEncoded
= bytesNeeded
;
3625 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3626 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3628 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3629 pbEncoded
= *(BYTE
**)pbEncoded
;
3630 *pbEncoded
++ = ASN_SEQUENCEOF
;
3631 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3632 pbEncoded
+= lenBytes
;
3633 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3635 DWORD len
= dataLen
;
3637 ret
= CRYPT_AsnEncodeDistPoint(
3638 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3652 SetLastError(STATUS_ACCESS_VIOLATION
);
3659 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3660 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3661 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3667 const CERT_ENHKEY_USAGE
*usage
= pvStructInfo
;
3668 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3671 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3673 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3674 usage
->rgpszUsageIdentifier
[i
],
3675 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3677 bytesNeeded
+= size
;
3679 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3680 bytesNeeded
+= 1 + lenBytes
;
3684 *pcbEncoded
= bytesNeeded
;
3687 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3688 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3690 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3691 pbEncoded
= *(BYTE
**)pbEncoded
;
3692 *pbEncoded
++ = ASN_SEQUENCEOF
;
3693 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3695 pbEncoded
+= lenBytes
;
3696 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3699 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3700 usage
->rgpszUsageIdentifier
[i
],
3701 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3706 bytesNeeded
-= size
;
3715 SetLastError(STATUS_ACCESS_VIOLATION
);
3722 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3723 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3724 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3730 const CRL_ISSUING_DIST_POINT
*point
= pvStructInfo
;
3731 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3732 struct AsnConstructedItem constructed
= { 0 };
3733 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3734 DWORD cItem
= 0, cSwapped
= 0;
3737 switch (point
->DistPointName
.dwDistPointNameChoice
)
3739 case CRL_DIST_POINT_NO_NAME
:
3742 case CRL_DIST_POINT_FULL_NAME
:
3743 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3744 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3745 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3746 constructed
.tag
= 0;
3747 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3748 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3749 items
[cItem
].pvStructInfo
= &constructed
;
3750 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3755 SetLastError(E_INVALIDARG
);
3758 if (ret
&& point
->fOnlyContainsUserCerts
)
3760 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3761 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3762 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3763 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3764 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3768 if (ret
&& point
->fOnlyContainsCACerts
)
3770 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3771 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3772 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3773 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3774 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3778 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3780 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3781 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3782 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3783 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3784 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3788 if (ret
&& point
->fIndirectCRL
)
3790 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3791 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3792 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3793 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3794 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3799 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3800 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3804 SetLastError(STATUS_ACCESS_VIOLATION
);
3811 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3812 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3813 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3816 const CERT_GENERAL_SUBTREE
*subtree
= pvStructInfo
;
3817 struct AsnEncodeSequenceItem items
[3] = {
3818 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
3821 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3822 DWORD cItem
= 1, cSwapped
= 0;
3824 if (subtree
->dwMinimum
)
3826 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3827 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
3828 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3829 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3830 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3834 if (subtree
->fMaximum
)
3836 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3837 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
3838 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3839 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3840 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3844 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
3845 pEncodePara
, pbEncoded
, pcbEncoded
);
3849 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
3850 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3851 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3854 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
3856 TRACE("%p\n", pvStructInfo
);
3860 const CERT_NAME_CONSTRAINTS_INFO
*constraints
= pvStructInfo
;
3861 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
3862 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3863 DWORD i
, cItem
= 0, cSwapped
= 0;
3866 if (constraints
->cPermittedSubtree
)
3868 permitted
.rgBlob
= CryptMemAlloc(
3869 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
3870 if (permitted
.rgBlob
)
3872 permitted
.cBlob
= constraints
->cPermittedSubtree
;
3873 memset(permitted
.rgBlob
, 0,
3874 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3875 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
3876 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3877 NULL
, &constraints
->rgPermittedSubtree
[i
],
3878 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3879 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
3880 &permitted
.rgBlob
[i
].cbData
);
3883 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3884 swapped
[cSwapped
].pvStructInfo
= &permitted
;
3885 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3886 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3887 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3895 if (constraints
->cExcludedSubtree
)
3897 excluded
.rgBlob
= CryptMemAlloc(
3898 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
3899 if (excluded
.rgBlob
)
3901 excluded
.cBlob
= constraints
->cExcludedSubtree
;
3902 memset(excluded
.rgBlob
, 0,
3903 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3904 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
3905 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3906 NULL
, &constraints
->rgExcludedSubtree
[i
],
3907 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3908 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
3909 &excluded
.rgBlob
[i
].cbData
);
3912 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3913 swapped
[cSwapped
].pvStructInfo
= &excluded
;
3914 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3915 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3916 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3925 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3926 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3927 for (i
= 0; i
< permitted
.cBlob
; i
++)
3928 LocalFree(permitted
.rgBlob
[i
].pbData
);
3929 for (i
= 0; i
< excluded
.cBlob
; i
++)
3930 LocalFree(excluded
.rgBlob
[i
].pbData
);
3934 SetLastError(STATUS_ACCESS_VIOLATION
);
3937 CryptMemFree(permitted
.rgBlob
);
3938 CryptMemFree(excluded
.rgBlob
);
3939 TRACE("returning %d\n", ret
);
3943 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3944 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3945 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3949 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
= pvStructInfo
;
3950 struct AsnEncodeSequenceItem items
[] = {
3951 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3952 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3955 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3956 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3961 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3962 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3963 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3967 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3969 SetLastError(E_INVALIDARG
);
3975 const CMSG_SIGNER_INFO
*info
= pvStructInfo
;
3977 if (!info
->Issuer
.cbData
)
3978 SetLastError(E_INVALIDARG
);
3981 struct AsnEncodeSequenceItem items
[7] = {
3982 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3983 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3984 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
3987 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3988 DWORD cItem
= 3, cSwapped
= 0;
3990 if (info
->AuthAttrs
.cAttr
)
3992 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3993 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3994 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3995 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3996 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4000 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4001 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4003 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4004 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4006 if (info
->UnauthAttrs
.cAttr
)
4008 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4009 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4010 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4011 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4012 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4016 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4017 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4022 SetLastError(STATUS_ACCESS_VIOLATION
);
4028 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4029 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4030 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4034 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4036 SetLastError(E_INVALIDARG
);
4042 const CMSG_CMS_SIGNER_INFO
*info
= pvStructInfo
;
4044 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4045 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4046 SetLastError(E_INVALIDARG
);
4047 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4048 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4049 SetLastError(E_INVALIDARG
);
4052 struct AsnEncodeSequenceItem items
[7] = {
4053 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4055 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4056 DWORD cItem
= 1, cSwapped
= 0;
4058 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4060 items
[cItem
].pvStructInfo
=
4061 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4062 items
[cItem
].encodeFunc
=
4063 CRYPT_AsnEncodeIssuerSerialNumber
;
4068 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4069 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4070 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4071 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4072 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4076 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4077 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4079 if (info
->AuthAttrs
.cAttr
)
4081 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4082 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4083 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4084 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4085 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4089 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4090 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4092 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4093 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4095 if (info
->UnauthAttrs
.cAttr
)
4097 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4098 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4099 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4100 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4101 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4105 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4106 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4111 SetLastError(STATUS_ACCESS_VIOLATION
);
4117 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4120 struct AsnEncodeSequenceItem items
[7] = {
4121 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4123 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4124 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4125 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4126 DWORD cItem
= 1, cSwapped
= 0;
4129 if (signedInfo
->cSignerInfo
)
4131 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4132 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4133 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4134 digestAlgorithmsSet
.itemOffset
=
4135 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4136 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4137 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4138 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4141 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4142 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4144 if (signedInfo
->cCertEncoded
)
4146 certSet
.cItems
= signedInfo
->cCertEncoded
;
4147 certSet
.items
= signedInfo
->rgCertEncoded
;
4148 certSet
.itemSize
= sizeof(CERT_BLOB
);
4149 certSet
.itemOffset
= 0;
4150 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4151 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4152 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4153 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4154 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4155 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4159 if (signedInfo
->cCrlEncoded
)
4161 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4162 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4163 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4164 crlSet
.itemOffset
= 0;
4165 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4166 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4167 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4168 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4169 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4170 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4174 if (ret
&& signedInfo
->cSignerInfo
)
4176 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4177 signerSet
.items
= signedInfo
->rgSignerInfo
;
4178 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4179 signerSet
.itemOffset
= 0;
4180 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4181 items
[cItem
].pvStructInfo
= &signerSet
;
4182 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4186 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4187 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4192 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4193 LPCSTR lpszStructType
)
4195 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4197 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4198 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4200 SetLastError(ERROR_FILE_NOT_FOUND
);
4204 if (!HIWORD(lpszStructType
))
4206 switch (LOWORD(lpszStructType
))
4208 case LOWORD(X509_CERT
):
4209 encodeFunc
= CRYPT_AsnEncodeCert
;
4211 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4212 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4214 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4215 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4217 case LOWORD(X509_EXTENSIONS
):
4218 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4220 case LOWORD(X509_NAME_VALUE
):
4221 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4223 case LOWORD(X509_NAME
):
4224 encodeFunc
= CRYPT_AsnEncodeName
;
4226 case LOWORD(X509_PUBLIC_KEY_INFO
):
4227 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4229 case LOWORD(X509_AUTHORITY_KEY_ID
):
4230 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4232 case LOWORD(X509_ALTERNATE_NAME
):
4233 encodeFunc
= CRYPT_AsnEncodeAltName
;
4235 case LOWORD(X509_BASIC_CONSTRAINTS
):
4236 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4238 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4239 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4241 case LOWORD(X509_CERT_POLICIES
):
4242 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4244 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4245 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4247 case LOWORD(X509_UNICODE_NAME
):
4248 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4250 case LOWORD(PKCS_CONTENT_INFO
):
4251 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4253 case LOWORD(PKCS_ATTRIBUTE
):
4254 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4256 case LOWORD(X509_UNICODE_NAME_VALUE
):
4257 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4259 case LOWORD(X509_OCTET_STRING
):
4260 encodeFunc
= CRYPT_AsnEncodeOctets
;
4262 case LOWORD(X509_BITS
):
4263 case LOWORD(X509_KEY_USAGE
):
4264 encodeFunc
= CRYPT_AsnEncodeBits
;
4266 case LOWORD(X509_INTEGER
):
4267 encodeFunc
= CRYPT_AsnEncodeInt
;
4269 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4270 encodeFunc
= CRYPT_AsnEncodeInteger
;
4272 case LOWORD(X509_MULTI_BYTE_UINT
):
4273 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4275 case LOWORD(X509_ENUMERATED
):
4276 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4278 case LOWORD(X509_CHOICE_OF_TIME
):
4279 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4281 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4282 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4284 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4285 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4287 case LOWORD(X509_SEQUENCE_OF_ANY
):
4288 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4290 case LOWORD(PKCS_UTC_TIME
):
4291 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4293 case LOWORD(X509_CRL_DIST_POINTS
):
4294 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4296 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4297 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4299 case LOWORD(PKCS_CTL
):
4300 encodeFunc
= CRYPT_AsnEncodeCTL
;
4302 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4303 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4305 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4306 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4308 case LOWORD(PKCS_ATTRIBUTES
):
4309 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4311 case LOWORD(X509_ISSUING_DIST_POINT
):
4312 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4314 case LOWORD(X509_NAME_CONSTRAINTS
):
4315 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4317 case LOWORD(PKCS7_SIGNER_INFO
):
4318 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4320 case LOWORD(CMS_SIGNER_INFO
):
4321 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4325 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4326 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4327 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4328 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4329 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4330 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4331 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4332 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4333 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4334 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4335 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4336 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4337 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4338 encodeFunc
= CRYPT_AsnEncodeBits
;
4339 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4340 encodeFunc
= CRYPT_AsnEncodeOctets
;
4341 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4342 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4343 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4344 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4345 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4346 encodeFunc
= CRYPT_AsnEncodeAltName
;
4347 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4348 encodeFunc
= CRYPT_AsnEncodeAltName
;
4349 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4350 encodeFunc
= CRYPT_AsnEncodeAltName
;
4351 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4352 encodeFunc
= CRYPT_AsnEncodeAltName
;
4353 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4354 encodeFunc
= CRYPT_AsnEncodeAltName
;
4355 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4356 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4357 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4358 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4359 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4360 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4361 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4362 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4363 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4364 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4365 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4366 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4367 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4368 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4369 else if (!strcmp(lpszStructType
, szOID_CTL
))
4370 encodeFunc
= CRYPT_AsnEncodeCTL
;
4374 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4375 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4377 static HCRYPTOIDFUNCSET set
= NULL
;
4378 CryptEncodeObjectFunc encodeFunc
= NULL
;
4381 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4382 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4383 (void **)&encodeFunc
, hFunc
);
4387 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4388 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4390 static HCRYPTOIDFUNCSET set
= NULL
;
4391 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4394 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4395 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4396 (void **)&encodeFunc
, hFunc
);
4400 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4401 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4404 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4405 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4406 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4408 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4409 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4412 if (!pbEncoded
&& !pcbEncoded
)
4414 SetLastError(ERROR_INVALID_PARAMETER
);
4418 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4421 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4422 debugstr_a(lpszStructType
));
4423 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4424 lpszStructType
, &hFunc
);
4425 if (!pCryptEncodeObject
)
4426 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4427 lpszStructType
, &hFunc
);
4429 if (pCryptEncodeObject
)
4430 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4431 pvStructInfo
, pbEncoded
, pcbEncoded
);
4432 else if (pCryptEncodeObjectEx
)
4433 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4434 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4436 CryptFreeOIDFunctionAddress(hFunc
, 0);
4437 TRACE_(crypt
)("returning %d\n", ret
);
4441 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4442 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4443 void *pvEncoded
, DWORD
*pcbEncoded
)
4446 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4447 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4449 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4450 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4451 pvEncoded
, pcbEncoded
);
4453 if (!pvEncoded
&& !pcbEncoded
)
4455 SetLastError(ERROR_INVALID_PARAMETER
);
4459 SetLastError(NOERROR
);
4460 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
4461 *(BYTE
**)pvEncoded
= NULL
;
4462 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4465 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4466 debugstr_a(lpszStructType
));
4467 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4471 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4472 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4475 CryptEncodeObjectFunc pCryptEncodeObject
=
4476 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4478 if (pCryptEncodeObject
)
4480 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4482 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4483 pvStructInfo
, NULL
, pcbEncoded
);
4484 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4485 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4486 ret
= pCryptEncodeObject(dwCertEncodingType
,
4487 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4491 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4492 pvStructInfo
, pvEncoded
, pcbEncoded
);
4496 CryptFreeOIDFunctionAddress(hFunc
, 0);
4497 TRACE_(crypt
)("returning %d\n", ret
);
4501 BOOL WINAPI
PFXExportCertStore(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4502 LPCWSTR szPassword
, DWORD dwFlags
)
4504 return PFXExportCertStoreEx(hStore
, pPFX
, szPassword
, NULL
, dwFlags
);
4507 BOOL WINAPI
PFXExportCertStoreEx(HCERTSTORE hStore
, CRYPT_DATA_BLOB
*pPFX
,
4508 LPCWSTR szPassword
, void *pvReserved
, DWORD dwFlags
)
4510 FIXME_(crypt
)("(%p, %p, %p, %p, %08x): stub\n", hStore
, pPFX
, szPassword
,
4511 pvReserved
, dwFlags
);
4515 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4516 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4518 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4519 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4522 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4523 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4524 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4528 static CHAR oid
[] = szOID_RSA_RSA
;
4530 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4531 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4532 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4534 if (!pszPublicKeyObjId
)
4535 pszPublicKeyObjId
= oid
;
4536 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4540 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4543 LPBYTE pubKey
= CryptMemAlloc(keySize
);
4547 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4551 DWORD encodedLen
= 0;
4553 ret
= CryptEncodeObject(dwCertEncodingType
,
4554 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4557 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4558 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4561 *pcbInfo
= sizeNeeded
;
4562 else if (*pcbInfo
< sizeNeeded
)
4564 SetLastError(ERROR_MORE_DATA
);
4565 *pcbInfo
= sizeNeeded
;
4570 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4571 sizeof(CERT_PUBLIC_KEY_INFO
);
4572 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4574 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4575 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4576 pInfo
->PublicKey
.pbData
=
4577 (BYTE
*)pInfo
->Algorithm
.pszObjId
4578 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4579 pInfo
->PublicKey
.cbData
= encodedLen
;
4580 pInfo
->PublicKey
.cUnusedBits
= 0;
4581 ret
= CryptEncodeObject(dwCertEncodingType
,
4582 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4583 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4587 CryptMemFree(pubKey
);
4592 CryptDestroyKey(key
);
4597 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4598 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4599 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4601 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4602 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4603 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4605 static HCRYPTOIDFUNCSET set
= NULL
;
4607 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4608 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4610 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4611 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4612 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4616 SetLastError(ERROR_INVALID_PARAMETER
);
4620 if (pszPublicKeyObjId
)
4623 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4625 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4626 0, (void **)&exportFunc
, &hFunc
);
4629 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4630 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4631 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4633 CryptFreeOIDFunctionAddress(hFunc
, 0);
4637 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4638 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4640 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4644 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4645 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4646 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4649 DWORD pubKeySize
= 0;
4651 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4652 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4654 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4655 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4658 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4662 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4663 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4668 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4669 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4672 CryptMemFree(pubKey
);
4680 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4681 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4682 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4684 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4685 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4686 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4688 static HCRYPTOIDFUNCSET set
= NULL
;
4690 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4691 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4693 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4694 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4697 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4698 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4699 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4701 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4702 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4705 CryptFreeOIDFunctionAddress(hFunc
, 0);