2 * Copyright 2005-2007 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"
38 #define NONAMELESSUNION
44 #include "wine/debug.h"
45 #include "wine/exception.h"
46 #include "wine/unicode.h"
47 #include "crypt32_private.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
50 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
52 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
61 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
62 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
63 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
94 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
95 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
99 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
101 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
102 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
104 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
105 if (!*(BYTE
**)pbEncoded
)
108 *pcbEncoded
= bytesNeeded
;
110 else if (bytesNeeded
> *pcbEncoded
)
112 *pcbEncoded
= bytesNeeded
;
113 SetLastError(ERROR_MORE_DATA
);
117 *pcbEncoded
= bytesNeeded
;
121 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
123 DWORD bytesNeeded
, significantBytes
= 0;
131 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
132 temp
<<= 8, significantBytes
--)
134 bytesNeeded
= significantBytes
+ 1;
138 *pcbEncoded
= bytesNeeded
;
141 if (*pcbEncoded
< bytesNeeded
)
143 SetLastError(ERROR_MORE_DATA
);
147 *pbEncoded
= (BYTE
)len
;
152 *pbEncoded
++ = significantBytes
| 0x80;
153 for (i
= 0; i
< significantBytes
; i
++)
155 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
159 *pcbEncoded
= bytesNeeded
;
163 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
164 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
165 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
168 DWORD i
, dataLen
= 0;
170 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
171 pbEncoded
, *pcbEncoded
);
172 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
174 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
175 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
176 NULL
, &items
[i
].size
);
177 /* Some functions propagate their errors through the size */
179 *pcbEncoded
= items
[i
].size
;
180 dataLen
+= items
[i
].size
;
184 DWORD lenBytes
, bytesNeeded
;
186 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
187 bytesNeeded
= 1 + lenBytes
+ dataLen
;
189 *pcbEncoded
= bytesNeeded
;
192 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
193 pcbEncoded
, bytesNeeded
)))
195 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
196 pbEncoded
= *(BYTE
**)pbEncoded
;
197 *pbEncoded
++ = ASN_SEQUENCE
;
198 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
199 pbEncoded
+= lenBytes
;
200 for (i
= 0; ret
&& i
< cItem
; i
++)
202 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
203 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
204 NULL
, pbEncoded
, &items
[i
].size
);
205 /* Some functions propagate their errors through the size */
207 *pcbEncoded
= items
[i
].size
;
208 pbEncoded
+= items
[i
].size
;
213 TRACE("returning %d (%08x)\n", ret
, GetLastError());
217 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
218 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
219 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
222 const struct AsnConstructedItem
*item
=
223 (const struct AsnConstructedItem
*)pvStructInfo
;
226 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
227 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
229 DWORD dataLen
, bytesNeeded
;
231 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
232 bytesNeeded
= 1 + dataLen
+ len
;
234 *pcbEncoded
= bytesNeeded
;
235 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
236 pbEncoded
, pcbEncoded
, bytesNeeded
)))
238 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
239 pbEncoded
= *(BYTE
**)pbEncoded
;
240 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
241 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
242 pbEncoded
+= dataLen
;
243 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
244 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
248 /* Some functions propagate their errors through the size */
255 /* Some functions propagate their errors through the size */
261 struct AsnEncodeTagSwappedItem
264 const void *pvStructInfo
;
265 CryptEncodeObjectExFunc encodeFunc
;
268 /* Sort of a wacky hack, it encodes something using the struct
269 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
270 * given in the struct AsnEncodeTagSwappedItem.
272 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
273 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
274 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
277 const struct AsnEncodeTagSwappedItem
*item
=
278 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
280 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
281 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
282 if (ret
&& pbEncoded
)
283 *pbEncoded
= item
->tag
;
287 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
288 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
289 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
291 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
294 /* CERT_V1 is not encoded */
302 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
304 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
305 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
310 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
311 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
312 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
314 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
319 *pcbEncoded
= blob
->cbData
;
324 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
325 pcbEncoded
, blob
->cbData
)))
327 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
328 pbEncoded
= *(BYTE
**)pbEncoded
;
330 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
331 *pcbEncoded
= blob
->cbData
;
338 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
339 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
340 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
343 /* This has two filetimes in a row, a NotBefore and a NotAfter */
344 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
345 struct AsnEncodeSequenceItem items
[] = {
346 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
347 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
350 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
351 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
356 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
359 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
360 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
361 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
364 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
365 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
366 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
367 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
370 struct AsnEncodeSequenceItem items
[2] = {
371 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
372 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
375 if (algo
->Parameters
.cbData
)
376 items
[1].pvStructInfo
= &algo
->Parameters
;
378 items
[1].pvStructInfo
= &nullBlob
;
379 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
380 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
385 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
386 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
387 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
389 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
390 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
392 struct AsnEncodeSequenceItem items
[] = {
393 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
394 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
397 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
398 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
403 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
404 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
405 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
411 const CERT_PUBLIC_KEY_INFO
*info
=
412 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
413 struct AsnEncodeSequenceItem items
[] = {
414 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
415 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
418 TRACE("Encoding public key with OID %s\n",
419 debugstr_a(info
->Algorithm
.pszObjId
));
420 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
421 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
426 SetLastError(STATUS_ACCESS_VIOLATION
);
433 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
434 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
435 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
441 const CERT_SIGNED_CONTENT_INFO
*info
=
442 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
443 struct AsnEncodeSequenceItem items
[] = {
444 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
445 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
446 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
449 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
450 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
451 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
452 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
457 SetLastError(STATUS_ACCESS_VIOLATION
);
464 /* Like in Windows, this blithely ignores the validity of the passed-in
465 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
466 * decode properly, see CRYPT_AsnDecodeCertInfo.
468 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
469 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
470 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
476 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
477 struct AsnEncodeSequenceItem items
[10] = {
478 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
479 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
480 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
481 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
482 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
483 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
484 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
487 struct AsnConstructedItem constructed
[3] = { { 0 } };
488 DWORD cItem
= 7, cConstructed
= 0;
490 if (info
->IssuerUniqueId
.cbData
)
492 constructed
[cConstructed
].tag
= 1;
493 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
494 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
495 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
496 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
500 if (info
->SubjectUniqueId
.cbData
)
502 constructed
[cConstructed
].tag
= 2;
503 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
504 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
505 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
506 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
510 if (info
->cExtension
)
512 constructed
[cConstructed
].tag
= 3;
513 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
514 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
515 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
516 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
521 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
522 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
526 SetLastError(STATUS_ACCESS_VIOLATION
);
533 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
534 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
536 struct AsnEncodeSequenceItem items
[3] = {
537 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
538 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
544 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
546 if (entry
->cExtension
)
548 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
549 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
553 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
554 pbEncoded
, pcbEncoded
);
556 TRACE("returning %d (%08x)\n", ret
, GetLastError());
560 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
561 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
562 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
564 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
565 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
566 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
567 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
570 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
574 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
578 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
579 bytesNeeded
= 1 + lenBytes
+ dataLen
;
581 *pcbEncoded
= bytesNeeded
;
584 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
585 pcbEncoded
, bytesNeeded
)))
587 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
588 pbEncoded
= *(BYTE
**)pbEncoded
;
589 *pbEncoded
++ = ASN_SEQUENCEOF
;
590 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
591 pbEncoded
+= lenBytes
;
592 for (i
= 0; i
< cCRLEntry
; i
++)
594 DWORD size
= dataLen
;
596 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
605 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
606 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
607 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
609 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
612 /* CRL_V1 is not encoded */
619 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
620 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
624 /* Like in Windows, this blithely ignores the validity of the passed-in
625 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
626 * decode properly, see CRYPT_AsnDecodeCRLInfo.
628 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
629 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
630 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
636 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
637 struct AsnEncodeSequenceItem items
[7] = {
638 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
639 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
640 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
641 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
644 struct AsnConstructedItem constructed
[1] = { { 0 } };
645 DWORD cItem
= 4, cConstructed
= 0;
647 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
649 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
650 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
655 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
656 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
659 if (info
->cExtension
)
661 constructed
[cConstructed
].tag
= 0;
662 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
663 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
664 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
665 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
670 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
671 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
675 SetLastError(STATUS_ACCESS_VIOLATION
);
682 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
686 struct AsnEncodeSequenceItem items
[3] = {
687 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
693 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
697 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
698 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
701 items
[cItem
].pvStructInfo
= &ext
->Value
;
702 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
705 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
706 pbEncoded
, pcbEncoded
);
707 TRACE("returning %d (%08x)\n", ret
, GetLastError());
711 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
712 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
713 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
719 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
720 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
723 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
727 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
731 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
732 bytesNeeded
= 1 + lenBytes
+ dataLen
;
734 *pcbEncoded
= bytesNeeded
;
737 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
738 pcbEncoded
, bytesNeeded
)))
740 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
741 pbEncoded
= *(BYTE
**)pbEncoded
;
742 *pbEncoded
++ = ASN_SEQUENCEOF
;
743 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
744 pbEncoded
+= lenBytes
;
745 for (i
= 0; i
< exts
->cExtension
; i
++)
747 DWORD size
= dataLen
;
749 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
759 SetLastError(STATUS_ACCESS_VIOLATION
);
766 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
767 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
768 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
770 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
771 DWORD bytesNeeded
= 0, lenBytes
;
776 TRACE("%s\n", debugstr_a(pszObjId
));
783 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
785 SetLastError(CRYPT_E_ASN1_ERROR
);
789 firstByte
= val1
* 40 + val2
;
790 ptr
= pszObjId
+ firstPos
;
795 /* note I assume each component is at most 32-bits long in base 2 */
796 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
798 if (val1
>= 0x10000000)
800 else if (val1
>= 0x200000)
802 else if (val1
>= 0x4000)
804 else if (val1
>= 0x80)
814 SetLastError(CRYPT_E_ASN1_ERROR
);
818 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
822 bytesNeeded
+= 1 + lenBytes
;
825 if (*pcbEncoded
< bytesNeeded
)
827 SetLastError(ERROR_MORE_DATA
);
832 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
833 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
834 pbEncoded
+= lenBytes
;
840 *pbEncoded
++ = firstByte
;
841 ptr
= pszObjId
+ firstPos
;
844 sscanf(ptr
, "%d%n", &val
, &pos
);
846 unsigned char outBytes
[5];
849 if (val
>= 0x10000000)
851 else if (val
>= 0x200000)
853 else if (val
>= 0x4000)
855 else if (val
>= 0x80)
859 for (i
= numBytes
; i
> 0; i
--)
861 outBytes
[i
- 1] = val
& 0x7f;
864 for (i
= 0; i
< numBytes
- 1; i
++)
865 *pbEncoded
++ = outBytes
[i
] | 0x80;
866 *pbEncoded
++ = outBytes
[i
];
875 *pcbEncoded
= bytesNeeded
;
879 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
880 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
884 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
885 DWORD bytesNeeded
, lenBytes
, encodedLen
;
887 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: lstrlenA(str
);
888 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
889 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
891 *pcbEncoded
= bytesNeeded
;
894 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
895 pbEncoded
, pcbEncoded
, bytesNeeded
)))
897 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
898 pbEncoded
= *(BYTE
**)pbEncoded
;
900 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
901 pbEncoded
+= lenBytes
;
902 memcpy(pbEncoded
, str
, encodedLen
);
908 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
909 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
913 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
914 DWORD bytesNeeded
, lenBytes
, strLen
;
916 if (value
->Value
.cbData
)
917 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
918 else if (value
->Value
.pbData
)
919 strLen
= lstrlenW(str
);
922 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
923 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
925 *pcbEncoded
= bytesNeeded
;
928 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
929 pbEncoded
, pcbEncoded
, bytesNeeded
)))
933 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
934 pbEncoded
= *(BYTE
**)pbEncoded
;
935 *pbEncoded
++ = ASN_BMPSTRING
;
936 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
937 pbEncoded
+= lenBytes
;
938 for (i
= 0; i
< strLen
; i
++)
940 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
941 *pbEncoded
++ = str
[i
] & 0x00ff;
948 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
949 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
953 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
954 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
956 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
958 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
960 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
961 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
963 *pcbEncoded
= bytesNeeded
;
966 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
967 pbEncoded
, pcbEncoded
, bytesNeeded
)))
969 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
970 pbEncoded
= *(BYTE
**)pbEncoded
;
971 *pbEncoded
++ = ASN_UTF8STRING
;
972 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
973 pbEncoded
+= lenBytes
;
974 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
975 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
981 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
982 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
983 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
989 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
991 switch (value
->dwValueType
)
993 case CERT_RDN_ANY_TYPE
:
994 /* explicitly disallowed */
995 SetLastError(E_INVALIDARG
);
998 case CERT_RDN_ENCODED_BLOB
:
999 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1000 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1002 case CERT_RDN_OCTET_STRING
:
1003 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1004 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1006 case CERT_RDN_NUMERIC_STRING
:
1007 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1008 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1010 case CERT_RDN_PRINTABLE_STRING
:
1011 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1012 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1014 case CERT_RDN_TELETEX_STRING
:
1015 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1016 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1018 case CERT_RDN_VIDEOTEX_STRING
:
1019 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1020 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1022 case CERT_RDN_IA5_STRING
:
1023 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1024 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1026 case CERT_RDN_GRAPHIC_STRING
:
1027 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1028 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1030 case CERT_RDN_VISIBLE_STRING
:
1031 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1032 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1034 case CERT_RDN_GENERAL_STRING
:
1035 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1036 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1038 case CERT_RDN_UNIVERSAL_STRING
:
1039 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1040 SetLastError(CRYPT_E_ASN1_CHOICE
);
1043 case CERT_RDN_BMP_STRING
:
1044 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1045 pbEncoded
, pcbEncoded
);
1047 case CERT_RDN_UTF8_STRING
:
1048 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1049 pbEncoded
, pcbEncoded
);
1052 SetLastError(CRYPT_E_ASN1_CHOICE
);
1058 SetLastError(STATUS_ACCESS_VIOLATION
);
1065 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1066 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1067 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1069 DWORD bytesNeeded
= 0, lenBytes
, size
;
1072 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1073 0, NULL
, NULL
, &size
);
1076 bytesNeeded
+= size
;
1077 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1078 * with dwValueType, so "cast" it to get its encoded size
1080 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1081 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1084 bytesNeeded
+= size
;
1085 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1086 bytesNeeded
+= 1 + lenBytes
;
1089 if (*pcbEncoded
< bytesNeeded
)
1091 SetLastError(ERROR_MORE_DATA
);
1096 *pbEncoded
++ = ASN_SEQUENCE
;
1097 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1099 pbEncoded
+= lenBytes
;
1100 size
= bytesNeeded
- 1 - lenBytes
;
1101 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1102 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1106 size
= bytesNeeded
- 1 - lenBytes
- size
;
1107 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1108 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1109 0, NULL
, pbEncoded
, &size
);
1116 *pcbEncoded
= bytesNeeded
;
1120 /* Have to propagate index of failing character */
1127 static int BLOBComp(const void *l
, const void *r
)
1129 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1132 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1133 ret
= a
->cbData
- b
->cbData
;
1137 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1139 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1140 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1141 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1143 const CRYPT_BLOB_ARRAY
*set
= (const CRYPT_BLOB_ARRAY
*)pvStructInfo
;
1144 DWORD bytesNeeded
= 0, lenBytes
, i
;
1147 for (i
= 0; i
< set
->cBlob
; i
++)
1148 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1149 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1150 bytesNeeded
+= 1 + lenBytes
;
1153 *pcbEncoded
= bytesNeeded
;
1156 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1157 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1159 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1160 pbEncoded
= *(BYTE
**)pbEncoded
;
1161 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1162 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1163 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1164 pbEncoded
+= lenBytes
;
1165 for (i
= 0; ret
&& i
< set
->cBlob
; i
++)
1167 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1168 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1174 struct DERSetDescriptor
1180 CryptEncodeObjectExFunc encode
;
1183 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1184 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1185 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1187 const struct DERSetDescriptor
*desc
=
1188 (const struct DERSetDescriptor
*)pvStructInfo
;
1189 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1195 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1200 setOf
.cBlob
= desc
->cItems
;
1201 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1204 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1206 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1207 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1208 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1211 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1212 if (!setOf
.rgBlob
[i
].pbData
)
1215 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1216 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1217 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1218 &setOf
.rgBlob
[i
].cbData
);
1220 /* Some functions propagate their errors through the size */
1222 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1226 DWORD bytesNeeded
= 0, lenBytes
;
1229 for (i
= 0; i
< setOf
.cBlob
; i
++)
1230 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1231 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1232 bytesNeeded
+= 1 + lenBytes
;
1234 *pcbEncoded
= bytesNeeded
;
1235 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1236 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1238 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1239 pbEncoded
= *(BYTE
**)pbEncoded
;
1240 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1242 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1243 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1244 pbEncoded
+= lenBytes
;
1245 for (i
= 0; i
< setOf
.cBlob
; i
++)
1247 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1248 setOf
.rgBlob
[i
].cbData
);
1249 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1253 for (i
= 0; i
< setOf
.cBlob
; i
++)
1254 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1255 CryptMemFree(setOf
.rgBlob
);
1259 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1260 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1264 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1273 setOf
.cBlob
= rdn
->cRDNAttr
;
1274 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1275 sizeof(CRYPT_DER_BLOB
));
1279 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1281 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1283 setOf
.rgBlob
[i
].cbData
= 0;
1284 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1285 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1288 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1289 if (!setOf
.rgBlob
[i
].pbData
)
1292 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1293 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1294 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1298 /* Have to propagate index of failing character */
1299 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1303 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1304 pbEncoded
, pcbEncoded
);
1305 for (i
= 0; i
< setOf
.cBlob
; i
++)
1306 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1310 SetLastError(STATUS_ACCESS_VIOLATION
);
1314 CryptMemFree(setOf
.rgBlob
);
1318 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1319 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1320 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1322 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1323 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1324 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1327 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1330 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1331 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1332 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1334 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1335 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1339 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1340 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1341 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1347 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1348 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1350 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1352 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1354 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1355 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1357 bytesNeeded
+= size
;
1361 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1362 bytesNeeded
+= 1 + lenBytes
;
1366 *pcbEncoded
= bytesNeeded
;
1369 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1370 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1372 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1373 pbEncoded
= *(BYTE
**)pbEncoded
;
1374 *pbEncoded
++ = ASN_SEQUENCEOF
;
1375 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1377 pbEncoded
+= lenBytes
;
1378 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1381 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1382 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1387 bytesNeeded
-= size
;
1398 SetLastError(STATUS_ACCESS_VIOLATION
);
1405 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1406 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1407 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1413 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1415 if (!attr
->pszObjId
)
1416 SetLastError(E_INVALIDARG
);
1419 struct AsnEncodeSequenceItem items
[2] = {
1420 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1421 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1424 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1425 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1431 SetLastError(STATUS_ACCESS_VIOLATION
);
1437 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1438 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1439 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1445 const CRYPT_ATTRIBUTES
*attributes
=
1446 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1447 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1448 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1450 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1451 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1455 SetLastError(STATUS_ACCESS_VIOLATION
);
1461 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1462 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1463 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1464 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1467 const CRYPT_CONTENT_INFO
*info
= (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1468 struct AsnEncodeSequenceItem items
[2] = {
1469 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1472 struct AsnConstructedItem constructed
= { 0 };
1475 if (info
->Content
.cbData
)
1477 constructed
.tag
= 0;
1478 constructed
.pvStructInfo
= &info
->Content
;
1479 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1480 items
[cItem
].pvStructInfo
= &constructed
;
1481 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1484 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1485 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1488 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1489 void *pvData
, DWORD
*pcbData
)
1491 struct AsnEncodeSequenceItem items
[] = {
1492 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1493 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1495 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1496 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1499 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1500 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1503 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1504 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1505 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1511 const CRYPT_CONTENT_INFO
*info
=
1512 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1514 if (!info
->pszObjId
)
1515 SetLastError(E_INVALIDARG
);
1517 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1518 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1523 SetLastError(STATUS_ACCESS_VIOLATION
);
1529 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1530 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1534 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1535 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1537 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1539 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1540 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1542 *pcbEncoded
= bytesNeeded
;
1545 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1546 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1550 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1551 pbEncoded
= *(BYTE
**)pbEncoded
;
1553 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1554 pbEncoded
+= lenBytes
;
1555 for (i
= 0; i
< encodedLen
; i
++)
1556 *pbEncoded
++ = (BYTE
)str
[i
];
1562 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1563 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1567 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1568 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1570 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1572 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1573 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1575 *pcbEncoded
= bytesNeeded
;
1578 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1579 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1584 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1585 ptr
= *(BYTE
**)pbEncoded
;
1588 *ptr
++ = ASN_NUMERICSTRING
;
1589 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1591 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1593 if (isdigitW(str
[i
]))
1594 *ptr
++ = (BYTE
)str
[i
];
1598 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1602 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1603 CryptMemFree(*(BYTE
**)pbEncoded
);
1609 static inline int isprintableW(WCHAR wc
)
1611 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1612 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1613 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1616 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1617 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1621 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1622 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1624 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1626 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1627 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1629 *pcbEncoded
= bytesNeeded
;
1632 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1633 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1638 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1639 ptr
= *(BYTE
**)pbEncoded
;
1642 *ptr
++ = ASN_PRINTABLESTRING
;
1643 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1645 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1647 if (isprintableW(str
[i
]))
1648 *ptr
++ = (BYTE
)str
[i
];
1652 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1656 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1657 CryptMemFree(*(BYTE
**)pbEncoded
);
1663 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1664 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1668 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1669 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1671 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1673 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1674 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1676 *pcbEncoded
= bytesNeeded
;
1679 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1680 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1685 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1686 ptr
= *(BYTE
**)pbEncoded
;
1689 *ptr
++ = ASN_IA5STRING
;
1690 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1692 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1695 *ptr
++ = (BYTE
)str
[i
];
1699 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1703 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1704 CryptMemFree(*(BYTE
**)pbEncoded
);
1710 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
1711 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1715 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1716 DWORD bytesNeeded
, lenBytes
, strLen
;
1718 /* FIXME: doesn't handle composite characters */
1719 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1721 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
1722 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
1724 *pcbEncoded
= bytesNeeded
;
1727 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1728 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1732 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1733 pbEncoded
= *(BYTE
**)pbEncoded
;
1734 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
1735 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
1736 pbEncoded
+= lenBytes
;
1737 for (i
= 0; i
< strLen
; i
++)
1741 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
1742 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
1749 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1750 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1751 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1757 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1759 switch (value
->dwValueType
)
1761 case CERT_RDN_ANY_TYPE
:
1762 case CERT_RDN_ENCODED_BLOB
:
1763 case CERT_RDN_OCTET_STRING
:
1764 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
1766 case CERT_RDN_NUMERIC_STRING
:
1767 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
1768 pbEncoded
, pcbEncoded
);
1770 case CERT_RDN_PRINTABLE_STRING
:
1771 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
1772 pbEncoded
, pcbEncoded
);
1774 case CERT_RDN_TELETEX_STRING
:
1775 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
1776 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1778 case CERT_RDN_VIDEOTEX_STRING
:
1779 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
1780 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1782 case CERT_RDN_IA5_STRING
:
1783 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
1784 pbEncoded
, pcbEncoded
);
1786 case CERT_RDN_GRAPHIC_STRING
:
1787 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1788 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1790 case CERT_RDN_VISIBLE_STRING
:
1791 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
1792 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1794 case CERT_RDN_GENERAL_STRING
:
1795 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
1796 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1798 case CERT_RDN_UNIVERSAL_STRING
:
1799 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
1800 pbEncoded
, pcbEncoded
);
1802 case CERT_RDN_BMP_STRING
:
1803 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1804 pbEncoded
, pcbEncoded
);
1806 case CERT_RDN_UTF8_STRING
:
1807 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1808 pbEncoded
, pcbEncoded
);
1811 SetLastError(CRYPT_E_ASN1_CHOICE
);
1816 SetLastError(STATUS_ACCESS_VIOLATION
);
1822 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1823 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1824 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1830 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1831 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1833 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1835 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1837 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1838 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
1840 bytesNeeded
+= size
;
1842 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1843 bytesNeeded
+= 1 + lenBytes
;
1847 *pcbEncoded
= bytesNeeded
;
1850 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1851 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1853 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1854 pbEncoded
= *(BYTE
**)pbEncoded
;
1855 *pbEncoded
++ = ASN_SEQUENCEOF
;
1856 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1858 pbEncoded
+= lenBytes
;
1859 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1862 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1863 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
1868 bytesNeeded
-= size
;
1877 SetLastError(STATUS_ACCESS_VIOLATION
);
1884 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1885 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1886 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1888 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1897 else if (*pcbEncoded
< 3)
1900 SetLastError(ERROR_MORE_DATA
);
1906 *pbEncoded
++ = ASN_BOOL
;
1908 *pbEncoded
++ = val
? 0xff : 0;
1911 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1915 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
1916 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1917 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1919 const CERT_ALT_NAME_ENTRY
*entry
=
1920 (const CERT_ALT_NAME_ENTRY
*)pvStructInfo
;
1926 switch (entry
->dwAltNameChoice
)
1928 case CERT_ALT_NAME_RFC822_NAME
:
1929 case CERT_ALT_NAME_DNS_NAME
:
1930 case CERT_ALT_NAME_URL
:
1931 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1932 if (entry
->u
.pwszURL
)
1936 /* Not + 1: don't encode the NULL-terminator */
1937 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1938 for (i
= 0; ret
&& i
< dataLen
; i
++)
1940 if (entry
->u
.pwszURL
[i
] > 0x7f)
1942 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1951 case CERT_ALT_NAME_DIRECTORY_NAME
:
1952 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
1953 dataLen
= entry
->u
.DirectoryName
.cbData
;
1955 case CERT_ALT_NAME_IP_ADDRESS
:
1956 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1957 dataLen
= entry
->u
.IPAddress
.cbData
;
1959 case CERT_ALT_NAME_REGISTERED_ID
:
1961 struct AsnEncodeTagSwappedItem swapped
=
1962 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
1963 CRYPT_AsnEncodeOid
};
1965 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
1968 case CERT_ALT_NAME_OTHER_NAME
:
1969 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
1972 SetLastError(E_INVALIDARG
);
1977 DWORD bytesNeeded
, lenBytes
;
1979 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1980 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1982 *pcbEncoded
= bytesNeeded
;
1983 else if (*pcbEncoded
< bytesNeeded
)
1985 SetLastError(ERROR_MORE_DATA
);
1986 *pcbEncoded
= bytesNeeded
;
1992 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1993 pbEncoded
+= lenBytes
;
1994 switch (entry
->dwAltNameChoice
)
1996 case CERT_ALT_NAME_RFC822_NAME
:
1997 case CERT_ALT_NAME_DNS_NAME
:
1998 case CERT_ALT_NAME_URL
:
2002 for (i
= 0; i
< dataLen
; i
++)
2003 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2006 case CERT_ALT_NAME_DIRECTORY_NAME
:
2007 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2009 case CERT_ALT_NAME_IP_ADDRESS
:
2010 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2014 *pcbEncoded
= bytesNeeded
;
2017 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2021 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2022 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2023 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2029 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2030 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2035 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2040 for (i
= 0; i
< newBlob
.cbData
; i
++)
2041 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2047 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2048 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2049 CryptMemFree(newBlob
.pbData
);
2053 SetLastError(STATUS_ACCESS_VIOLATION
);
2060 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2061 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2062 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2068 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
2069 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
2070 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2071 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2072 struct AsnConstructedItem constructed
= { 0 };
2073 DWORD cItem
= 0, cSwapped
= 0;
2075 if (info
->KeyId
.cbData
)
2077 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2078 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2079 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2080 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2081 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2085 if (info
->CertIssuer
.cbData
)
2087 constructed
.tag
= 1;
2088 constructed
.pvStructInfo
= &info
->CertIssuer
;
2089 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2090 items
[cItem
].pvStructInfo
= &constructed
;
2091 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2094 if (info
->CertSerialNumber
.cbData
)
2096 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2097 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2098 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2099 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2100 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2104 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2105 pEncodePara
, pbEncoded
, pcbEncoded
);
2109 SetLastError(STATUS_ACCESS_VIOLATION
);
2116 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2117 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2118 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2124 const CERT_ALT_NAME_INFO
*info
=
2125 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2126 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2129 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2130 * can't encode an erroneous entry index if it's bigger than this.
2132 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2136 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2137 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2140 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2142 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2143 * the bad character, now set the index of the bad
2146 *pcbEncoded
= (BYTE
)i
<<
2147 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2152 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2153 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2156 *pcbEncoded
= bytesNeeded
;
2161 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2162 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2164 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2165 pbEncoded
= *(BYTE
**)pbEncoded
;
2166 *pbEncoded
++ = ASN_SEQUENCEOF
;
2167 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2168 pbEncoded
+= lenBytes
;
2169 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2171 DWORD len
= dataLen
;
2173 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2174 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, pbEncoded
, &len
);
2187 SetLastError(STATUS_ACCESS_VIOLATION
);
2194 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2195 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2196 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2202 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2203 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2204 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2205 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2206 DWORD cItem
= 0, cSwapped
= 0;
2208 if (info
->KeyId
.cbData
)
2210 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2211 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2212 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2213 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2214 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2218 if (info
->AuthorityCertIssuer
.cAltEntry
)
2220 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2221 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2222 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2223 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2224 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2228 if (info
->AuthorityCertSerialNumber
.cbData
)
2230 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2231 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2232 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2233 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2234 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2238 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2239 pEncodePara
, pbEncoded
, pcbEncoded
);
2243 SetLastError(STATUS_ACCESS_VIOLATION
);
2250 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2251 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2252 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2258 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2259 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2260 struct AsnEncodeSequenceItem items
[3] = {
2261 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2266 if (info
->fPathLenConstraint
)
2268 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2269 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2272 if (info
->cSubtreesConstraint
)
2274 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2275 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2278 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2279 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2283 SetLastError(STATUS_ACCESS_VIOLATION
);
2290 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2291 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2292 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2298 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2299 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2300 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2305 items
[cItem
].pvStructInfo
= &info
->fCA
;
2306 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2309 if (info
->fPathLenConstraint
)
2311 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2312 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2315 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2316 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2320 SetLastError(STATUS_ACCESS_VIOLATION
);
2327 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2328 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2329 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2335 const BLOBHEADER
*hdr
=
2336 (const BLOBHEADER
*)pvStructInfo
;
2338 if (hdr
->bType
!= PUBLICKEYBLOB
)
2340 SetLastError(E_INVALIDARG
);
2345 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2346 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2347 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2348 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2349 struct AsnEncodeSequenceItem items
[] = {
2350 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2351 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2354 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2355 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2361 SetLastError(STATUS_ACCESS_VIOLATION
);
2368 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2369 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2370 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2376 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2377 DWORD bytesNeeded
, lenBytes
;
2379 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2380 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2382 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2383 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2386 *pcbEncoded
= bytesNeeded
;
2391 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2392 pcbEncoded
, bytesNeeded
)))
2394 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2395 pbEncoded
= *(BYTE
**)pbEncoded
;
2396 *pbEncoded
++ = ASN_OCTETSTRING
;
2397 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2398 pbEncoded
+= lenBytes
;
2400 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2406 SetLastError(STATUS_ACCESS_VIOLATION
);
2410 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2414 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2415 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2416 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2422 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2423 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2426 /* yep, MS allows cUnusedBits to be >= 8 */
2427 if (!blob
->cUnusedBits
)
2429 dataBytes
= blob
->cbData
;
2432 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2434 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2435 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2443 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2444 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2447 *pcbEncoded
= bytesNeeded
;
2452 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2453 pcbEncoded
, bytesNeeded
)))
2455 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2456 pbEncoded
= *(BYTE
**)pbEncoded
;
2457 *pbEncoded
++ = ASN_BITSTRING
;
2458 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2459 pbEncoded
+= lenBytes
;
2460 *pbEncoded
++ = unusedBits
;
2463 BYTE mask
= 0xff << unusedBits
;
2467 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2468 pbEncoded
+= dataBytes
- 1;
2470 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2477 SetLastError(STATUS_ACCESS_VIOLATION
);
2484 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2485 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2486 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2492 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2493 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2498 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2503 for (i
= 0; i
< newBlob
.cbData
; i
++)
2504 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2510 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2511 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2512 CryptMemFree(newBlob
.pbData
);
2516 SetLastError(STATUS_ACCESS_VIOLATION
);
2523 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2524 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2525 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2527 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2529 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2530 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2533 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2534 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2535 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2541 DWORD significantBytes
, lenBytes
;
2542 BYTE padByte
= 0, bytesNeeded
;
2544 const CRYPT_INTEGER_BLOB
*blob
=
2545 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2547 significantBytes
= blob
->cbData
;
2548 if (significantBytes
)
2550 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2552 /* negative, lop off leading (little-endian) 0xffs */
2553 for (; significantBytes
> 0 &&
2554 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2556 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2564 /* positive, lop off leading (little-endian) zeroes */
2565 for (; significantBytes
> 0 &&
2566 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2568 if (significantBytes
== 0)
2569 significantBytes
= 1;
2570 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2578 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2580 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2581 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2586 *pcbEncoded
= bytesNeeded
;
2591 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2592 pcbEncoded
, bytesNeeded
)))
2594 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2595 pbEncoded
= *(BYTE
**)pbEncoded
;
2596 *pbEncoded
++ = ASN_INTEGER
;
2599 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2600 pbEncoded
+= lenBytes
;
2601 *pbEncoded
++ = padByte
;
2605 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2606 pbEncoded
+= lenBytes
;
2608 for (; significantBytes
> 0; significantBytes
--)
2609 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2615 SetLastError(STATUS_ACCESS_VIOLATION
);
2622 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
2623 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2624 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2630 DWORD significantBytes
, lenBytes
;
2633 const CRYPT_INTEGER_BLOB
*blob
=
2634 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2636 significantBytes
= blob
->cbData
;
2637 if (significantBytes
)
2639 /* positive, lop off leading (little-endian) zeroes */
2640 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2643 if (significantBytes
== 0)
2644 significantBytes
= 1;
2645 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2649 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2651 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2652 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2657 *pcbEncoded
= bytesNeeded
;
2662 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2663 pcbEncoded
, bytesNeeded
)))
2665 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2666 pbEncoded
= *(BYTE
**)pbEncoded
;
2667 *pbEncoded
++ = ASN_INTEGER
;
2670 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2671 pbEncoded
+= lenBytes
;
2676 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2677 pbEncoded
+= lenBytes
;
2679 for (; significantBytes
> 0; significantBytes
--)
2680 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2686 SetLastError(STATUS_ACCESS_VIOLATION
);
2693 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2694 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2695 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2697 CRYPT_INTEGER_BLOB blob
;
2700 /* Encode as an unsigned integer, then change the tag to enumerated */
2701 blob
.cbData
= sizeof(DWORD
);
2702 blob
.pbData
= (BYTE
*)pvStructInfo
;
2703 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2704 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2705 if (ret
&& pbEncoded
)
2707 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2708 pbEncoded
= *(BYTE
**)pbEncoded
;
2709 pbEncoded
[0] = ASN_ENUMERATED
;
2714 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2715 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2716 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2723 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2724 * temporary buffer because the output buffer is not NULL-terminated.
2727 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2731 *pcbEncoded
= bytesNeeded
;
2736 /* Sanity check the year, this is a two-digit year format */
2737 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2739 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2741 SetLastError(CRYPT_E_BAD_ENCODE
);
2746 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2747 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2749 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2750 pbEncoded
= *(BYTE
**)pbEncoded
;
2751 buf
[0] = ASN_UTCTIME
;
2752 buf
[1] = bytesNeeded
- 2;
2753 snprintf(buf
+ 2, sizeof(buf
) - 2,
2754 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2755 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2756 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2757 sysTime
.wMinute
, sysTime
.wSecond
);
2758 memcpy(pbEncoded
, buf
, bytesNeeded
);
2765 SetLastError(STATUS_ACCESS_VIOLATION
);
2772 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2773 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2774 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2781 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2782 * temporary buffer because the output buffer is not NULL-terminated.
2785 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2789 *pcbEncoded
= bytesNeeded
;
2794 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2797 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2798 pcbEncoded
, bytesNeeded
);
2801 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2802 pbEncoded
= *(BYTE
**)pbEncoded
;
2803 buf
[0] = ASN_GENERALTIME
;
2804 buf
[1] = bytesNeeded
- 2;
2805 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2806 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2807 sysTime
.wMinute
, sysTime
.wSecond
);
2808 memcpy(pbEncoded
, buf
, bytesNeeded
);
2814 SetLastError(STATUS_ACCESS_VIOLATION
);
2821 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2822 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2823 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2831 /* Check the year, if it's in the UTCTime range call that encode func */
2832 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2834 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2835 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2836 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2838 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2839 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2844 SetLastError(STATUS_ACCESS_VIOLATION
);
2851 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2852 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2853 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2859 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2860 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2861 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2863 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2864 dataLen
+= seq
->rgValue
[i
].cbData
;
2865 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2866 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2869 *pcbEncoded
= bytesNeeded
;
2874 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2875 pcbEncoded
, bytesNeeded
)))
2877 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2878 pbEncoded
= *(BYTE
**)pbEncoded
;
2879 *pbEncoded
++ = ASN_SEQUENCEOF
;
2880 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2881 pbEncoded
+= lenBytes
;
2882 for (i
= 0; i
< seq
->cValue
; i
++)
2884 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2885 seq
->rgValue
[i
].cbData
);
2886 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2893 SetLastError(STATUS_ACCESS_VIOLATION
);
2900 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2901 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2904 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2905 struct AsnConstructedItem constructed
= { 0 };
2906 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2907 DWORD cItem
= 0, cSwapped
= 0;
2909 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2911 case CRL_DIST_POINT_NO_NAME
:
2914 case CRL_DIST_POINT_FULL_NAME
:
2915 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2916 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2917 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2918 constructed
.tag
= 0;
2919 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2920 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2921 items
[cItem
].pvStructInfo
= &constructed
;
2922 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2926 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2927 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2933 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2935 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2936 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2937 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2938 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2939 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2943 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2945 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2946 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2947 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2948 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2949 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2954 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2955 pbEncoded
, pcbEncoded
);
2959 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2960 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2961 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2967 const CRL_DIST_POINTS_INFO
*info
=
2968 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2970 if (!info
->cDistPoint
)
2972 SetLastError(E_INVALIDARG
);
2977 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2980 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2984 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2988 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2990 /* Have to propagate index of failing character */
2996 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2997 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3000 *pcbEncoded
= bytesNeeded
;
3005 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3006 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3008 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3009 pbEncoded
= *(BYTE
**)pbEncoded
;
3010 *pbEncoded
++ = ASN_SEQUENCEOF
;
3011 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3012 pbEncoded
+= lenBytes
;
3013 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3015 DWORD len
= dataLen
;
3017 ret
= CRYPT_AsnEncodeDistPoint(
3018 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3032 SetLastError(STATUS_ACCESS_VIOLATION
);
3039 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3040 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3041 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3047 const CERT_ENHKEY_USAGE
*usage
=
3048 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
3049 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3052 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3054 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3055 usage
->rgpszUsageIdentifier
[i
],
3056 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3058 bytesNeeded
+= size
;
3060 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3061 bytesNeeded
+= 1 + lenBytes
;
3065 *pcbEncoded
= bytesNeeded
;
3068 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3069 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3071 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3072 pbEncoded
= *(BYTE
**)pbEncoded
;
3073 *pbEncoded
++ = ASN_SEQUENCEOF
;
3074 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3076 pbEncoded
+= lenBytes
;
3077 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3080 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3081 usage
->rgpszUsageIdentifier
[i
],
3082 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3087 bytesNeeded
-= size
;
3096 SetLastError(STATUS_ACCESS_VIOLATION
);
3103 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3104 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3105 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3111 const CRL_ISSUING_DIST_POINT
*point
=
3112 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3113 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3114 struct AsnConstructedItem constructed
= { 0 };
3115 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3116 DWORD cItem
= 0, cSwapped
= 0;
3119 switch (point
->DistPointName
.dwDistPointNameChoice
)
3121 case CRL_DIST_POINT_NO_NAME
:
3124 case CRL_DIST_POINT_FULL_NAME
:
3125 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3126 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3127 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3128 constructed
.tag
= 0;
3129 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3130 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3131 items
[cItem
].pvStructInfo
= &constructed
;
3132 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3137 SetLastError(E_INVALIDARG
);
3140 if (ret
&& point
->fOnlyContainsUserCerts
)
3142 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3143 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3144 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3145 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3146 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3150 if (ret
&& point
->fOnlyContainsCACerts
)
3152 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3153 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3154 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3155 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3156 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3160 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3162 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3163 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3164 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3165 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3166 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3170 if (ret
&& point
->fIndirectCRL
)
3172 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3173 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3174 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3175 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3176 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3181 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3182 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3186 SetLastError(STATUS_ACCESS_VIOLATION
);
3193 static BOOL WINAPI
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3194 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3195 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3198 const CERT_GENERAL_SUBTREE
*subtree
=
3199 (const CERT_GENERAL_SUBTREE
*)pvStructInfo
;
3200 struct AsnEncodeSequenceItem items
[3] = {
3201 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
3204 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3205 DWORD cItem
= 1, cSwapped
= 0;
3207 if (subtree
->dwMinimum
)
3209 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3210 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
3211 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3212 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3213 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3217 if (subtree
->fMaximum
)
3219 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3220 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
3221 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3222 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3223 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3227 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
3228 pEncodePara
, pbEncoded
, pcbEncoded
);
3232 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
3233 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3234 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3237 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
3239 TRACE("%p\n", pvStructInfo
);
3243 const CERT_NAME_CONSTRAINTS_INFO
*constraints
=
3244 (const CERT_NAME_CONSTRAINTS_INFO
*)pvStructInfo
;
3245 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
3246 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3247 DWORD i
, cItem
= 0, cSwapped
= 0;
3250 if (constraints
->cPermittedSubtree
)
3252 permitted
.rgBlob
= CryptMemAlloc(
3253 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
3254 if (permitted
.rgBlob
)
3256 permitted
.cBlob
= constraints
->cPermittedSubtree
;
3257 memset(permitted
.rgBlob
, 0,
3258 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3259 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
3260 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3261 NULL
, &constraints
->rgPermittedSubtree
[i
],
3262 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3263 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
3264 &permitted
.rgBlob
[i
].cbData
);
3267 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3268 swapped
[cSwapped
].pvStructInfo
= &permitted
;
3269 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3270 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3271 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3279 if (constraints
->cExcludedSubtree
)
3281 excluded
.rgBlob
= CryptMemAlloc(
3282 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
3283 if (excluded
.rgBlob
)
3285 excluded
.cBlob
= constraints
->cExcludedSubtree
;
3286 memset(excluded
.rgBlob
, 0,
3287 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3288 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
3289 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3290 NULL
, &constraints
->rgExcludedSubtree
[i
],
3291 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3292 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
3293 &excluded
.rgBlob
[i
].cbData
);
3296 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3297 swapped
[cSwapped
].pvStructInfo
= &excluded
;
3298 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3299 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3300 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3309 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3310 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3311 for (i
= 0; i
< permitted
.cBlob
; i
++)
3312 LocalFree(permitted
.rgBlob
[i
].pbData
);
3313 for (i
= 0; i
< excluded
.cBlob
; i
++)
3314 LocalFree(excluded
.rgBlob
[i
].pbData
);
3318 SetLastError(STATUS_ACCESS_VIOLATION
);
3321 CryptMemFree(permitted
.rgBlob
);
3322 CryptMemFree(excluded
.rgBlob
);
3323 TRACE("returning %d\n", ret
);
3327 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3328 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3329 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3333 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3334 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3335 struct AsnEncodeSequenceItem items
[] = {
3336 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3337 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3340 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3341 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3346 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3347 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3348 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3352 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3354 SetLastError(E_INVALIDARG
);
3360 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
3362 if (!info
->Issuer
.cbData
)
3363 SetLastError(E_INVALIDARG
);
3366 struct AsnEncodeSequenceItem items
[7] = {
3367 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3368 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3369 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
3372 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3373 DWORD cItem
= 3, cSwapped
= 0;
3375 if (info
->AuthAttrs
.cAttr
)
3377 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3378 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3379 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3380 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3381 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3385 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
3386 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3388 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3389 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3391 if (info
->UnauthAttrs
.cAttr
)
3393 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3394 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
3395 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3396 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3397 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3401 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3402 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3407 SetLastError(STATUS_ACCESS_VIOLATION
);
3413 BOOL
CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
3416 struct AsnEncodeSequenceItem items
[7] = {
3417 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
3419 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
3420 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
3421 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3422 DWORD cItem
= 1, cSwapped
= 0;
3425 if (signedInfo
->cSignerInfo
)
3427 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
3428 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
3429 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_SIGNER_INFO
);
3430 digestAlgorithmsSet
.itemOffset
=
3431 offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
);
3432 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3433 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
3434 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3437 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
3438 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
3440 if (signedInfo
->cCertEncoded
)
3442 certSet
.cItems
= signedInfo
->cCertEncoded
;
3443 certSet
.items
= signedInfo
->rgCertEncoded
;
3444 certSet
.itemSize
= sizeof(CERT_BLOB
);
3445 certSet
.itemOffset
= 0;
3446 certSet
.encode
= CRYPT_CopyEncodedBlob
;
3447 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
3448 swapped
[cSwapped
].pvStructInfo
= &certSet
;
3449 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3450 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3451 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3455 if (signedInfo
->cCrlEncoded
)
3457 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
3458 crlSet
.items
= signedInfo
->rgCrlEncoded
;
3459 crlSet
.itemSize
= sizeof(CRL_BLOB
);
3460 crlSet
.itemOffset
= 0;
3461 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
3462 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
3463 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
3464 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3465 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3466 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3470 if (ret
&& signedInfo
->cSignerInfo
)
3472 signerSet
.cItems
= signedInfo
->cSignerInfo
;
3473 signerSet
.items
= signedInfo
->rgSignerInfo
;
3474 signerSet
.itemSize
= sizeof(CMSG_SIGNER_INFO
);
3475 signerSet
.itemOffset
= 0;
3476 signerSet
.encode
= CRYPT_AsnEncodePKCSSignerInfo
;
3477 items
[cItem
].pvStructInfo
= &signerSet
;
3478 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3482 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
3483 items
, cItem
, 0, NULL
, pvData
, pcbData
);
3488 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
3489 LPCSTR lpszStructType
)
3491 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3493 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3494 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3496 SetLastError(ERROR_FILE_NOT_FOUND
);
3500 if (!HIWORD(lpszStructType
))
3502 switch (LOWORD(lpszStructType
))
3504 case LOWORD(X509_CERT
):
3505 encodeFunc
= CRYPT_AsnEncodeCert
;
3507 case LOWORD(X509_CERT_TO_BE_SIGNED
):
3508 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
3510 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
3511 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
3513 case LOWORD(X509_EXTENSIONS
):
3514 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3516 case LOWORD(X509_NAME_VALUE
):
3517 encodeFunc
= CRYPT_AsnEncodeNameValue
;
3519 case LOWORD(X509_NAME
):
3520 encodeFunc
= CRYPT_AsnEncodeName
;
3522 case LOWORD(X509_PUBLIC_KEY_INFO
):
3523 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
3525 case LOWORD(X509_AUTHORITY_KEY_ID
):
3526 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3528 case LOWORD(X509_ALTERNATE_NAME
):
3529 encodeFunc
= CRYPT_AsnEncodeAltName
;
3531 case LOWORD(X509_BASIC_CONSTRAINTS
):
3532 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3534 case LOWORD(X509_BASIC_CONSTRAINTS2
):
3535 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3537 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
3538 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
3540 case LOWORD(X509_UNICODE_NAME
):
3541 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
3543 case LOWORD(PKCS_CONTENT_INFO
):
3544 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
3546 case LOWORD(PKCS_ATTRIBUTE
):
3547 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
3549 case LOWORD(X509_UNICODE_NAME_VALUE
):
3550 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
3552 case LOWORD(X509_OCTET_STRING
):
3553 encodeFunc
= CRYPT_AsnEncodeOctets
;
3555 case LOWORD(X509_BITS
):
3556 case LOWORD(X509_KEY_USAGE
):
3557 encodeFunc
= CRYPT_AsnEncodeBits
;
3559 case LOWORD(X509_INTEGER
):
3560 encodeFunc
= CRYPT_AsnEncodeInt
;
3562 case LOWORD(X509_MULTI_BYTE_INTEGER
):
3563 encodeFunc
= CRYPT_AsnEncodeInteger
;
3565 case LOWORD(X509_MULTI_BYTE_UINT
):
3566 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
3568 case LOWORD(X509_ENUMERATED
):
3569 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3571 case LOWORD(X509_CHOICE_OF_TIME
):
3572 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
3574 case LOWORD(X509_AUTHORITY_KEY_ID2
):
3575 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3577 case LOWORD(X509_SEQUENCE_OF_ANY
):
3578 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
3580 case LOWORD(PKCS_UTC_TIME
):
3581 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3583 case LOWORD(X509_CRL_DIST_POINTS
):
3584 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3586 case LOWORD(X509_ENHANCED_KEY_USAGE
):
3587 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3589 case LOWORD(PKCS_ATTRIBUTES
):
3590 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3592 case LOWORD(X509_ISSUING_DIST_POINT
):
3593 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3595 case LOWORD(X509_NAME_CONSTRAINTS
):
3596 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
3598 case LOWORD(PKCS7_SIGNER_INFO
):
3599 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
3603 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
3604 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3605 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3606 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3607 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
3608 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3609 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
3610 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3611 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3612 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3613 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3614 encodeFunc
= CRYPT_AsnEncodeBits
;
3615 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3616 encodeFunc
= CRYPT_AsnEncodeOctets
;
3617 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
3618 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3619 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3620 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3621 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
3622 encodeFunc
= CRYPT_AsnEncodeAltName
;
3623 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
3624 encodeFunc
= CRYPT_AsnEncodeAltName
;
3625 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
3626 encodeFunc
= CRYPT_AsnEncodeAltName
;
3627 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
3628 encodeFunc
= CRYPT_AsnEncodeAltName
;
3629 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
3630 encodeFunc
= CRYPT_AsnEncodeAltName
;
3631 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
3632 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3633 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
3634 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3635 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
3636 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3637 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
3638 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
3642 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
3643 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
3645 static HCRYPTOIDFUNCSET set
= NULL
;
3646 CryptEncodeObjectFunc encodeFunc
= NULL
;
3649 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
3650 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3651 (void **)&encodeFunc
, hFunc
);
3655 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
3656 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
3658 static HCRYPTOIDFUNCSET set
= NULL
;
3659 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3662 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
3663 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3664 (void **)&encodeFunc
, hFunc
);
3668 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3669 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3672 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3673 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
3674 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
3676 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
3677 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
3680 if (!pbEncoded
&& !pcbEncoded
)
3682 SetLastError(ERROR_INVALID_PARAMETER
);
3686 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
3689 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
3690 debugstr_a(lpszStructType
));
3691 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
3692 lpszStructType
, &hFunc
);
3693 if (!pCryptEncodeObject
)
3694 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
3695 lpszStructType
, &hFunc
);
3697 if (pCryptEncodeObject
)
3698 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3699 pvStructInfo
, pbEncoded
, pcbEncoded
);
3700 else if (pCryptEncodeObjectEx
)
3701 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
3702 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
3704 CryptFreeOIDFunctionAddress(hFunc
, 0);
3705 TRACE_(crypt
)("returning %d\n", ret
);
3709 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3710 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
3711 void *pvEncoded
, DWORD
*pcbEncoded
)
3714 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3715 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3717 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
3718 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
3719 pvEncoded
, pcbEncoded
);
3721 if (!pvEncoded
&& !pcbEncoded
)
3723 SetLastError(ERROR_INVALID_PARAMETER
);
3727 SetLastError(NOERROR
);
3728 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
3729 *(BYTE
**)pvEncoded
= NULL
;
3730 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
3733 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
3734 debugstr_a(lpszStructType
));
3735 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
3739 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
3740 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
3743 CryptEncodeObjectFunc pCryptEncodeObject
=
3744 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
3746 if (pCryptEncodeObject
)
3748 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3750 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3751 pvStructInfo
, NULL
, pcbEncoded
);
3752 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3753 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
3754 ret
= pCryptEncodeObject(dwCertEncodingType
,
3755 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
3759 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3760 pvStructInfo
, pvEncoded
, pcbEncoded
);
3764 CryptFreeOIDFunctionAddress(hFunc
, 0);
3765 TRACE_(crypt
)("returning %d\n", ret
);
3769 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
3770 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3772 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3773 NULL
, 0, NULL
, pInfo
, pcbInfo
);
3776 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
3777 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3778 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3782 static CHAR oid
[] = szOID_RSA_RSA
;
3784 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
3785 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
3786 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
3788 if (!pszPublicKeyObjId
)
3789 pszPublicKeyObjId
= oid
;
3790 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
3794 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
3797 LPBYTE pubKey
= CryptMemAlloc(keySize
);
3801 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
3805 DWORD encodedLen
= 0;
3807 ret
= CryptEncodeObject(dwCertEncodingType
,
3808 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
3811 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
3812 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
3815 *pcbInfo
= sizeNeeded
;
3816 else if (*pcbInfo
< sizeNeeded
)
3818 SetLastError(ERROR_MORE_DATA
);
3819 *pcbInfo
= sizeNeeded
;
3824 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
3825 sizeof(CERT_PUBLIC_KEY_INFO
);
3826 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
3828 pInfo
->Algorithm
.Parameters
.cbData
= 0;
3829 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
3830 pInfo
->PublicKey
.pbData
=
3831 (BYTE
*)pInfo
->Algorithm
.pszObjId
3832 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
3833 pInfo
->PublicKey
.cbData
= encodedLen
;
3834 pInfo
->PublicKey
.cUnusedBits
= 0;
3835 ret
= CryptEncodeObject(dwCertEncodingType
,
3836 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
3837 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
3841 CryptMemFree(pubKey
);
3846 CryptDestroyKey(key
);
3851 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
3852 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3853 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
3855 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
3856 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
3857 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3859 static HCRYPTOIDFUNCSET set
= NULL
;
3861 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
3862 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3864 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
3865 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
3866 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
3870 SetLastError(ERROR_INVALID_PARAMETER
);
3874 if (pszPublicKeyObjId
)
3877 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
3879 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
3880 0, (void **)&exportFunc
, &hFunc
);
3883 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
3884 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3885 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
3887 CryptFreeOIDFunctionAddress(hFunc
, 0);
3891 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
3892 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
3894 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
3898 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3899 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3900 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3903 DWORD pubKeySize
= 0;
3905 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
3906 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3908 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3909 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
3912 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
3916 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3917 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
3920 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
3922 CryptMemFree(pubKey
);
3930 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3931 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3932 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
3934 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3935 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3936 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3938 static HCRYPTOIDFUNCSET set
= NULL
;
3940 ImportPublicKeyInfoExFunc importFunc
= NULL
;
3941 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3943 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
3944 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3947 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
3948 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
3949 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
3951 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
3952 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
3955 CryptFreeOIDFunctionAddress(hFunc
, 0);