2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
34 #include "wine/port.h"
41 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
55 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
93 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
95 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
97 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
98 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
102 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
104 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
105 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
107 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
108 if (!*(BYTE
**)pbEncoded
)
111 *pcbEncoded
= bytesNeeded
;
113 else if (bytesNeeded
> *pcbEncoded
)
115 *pcbEncoded
= bytesNeeded
;
116 SetLastError(ERROR_MORE_DATA
);
120 *pcbEncoded
= bytesNeeded
;
124 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
126 DWORD bytesNeeded
, significantBytes
= 0;
134 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
135 temp
<<= 8, significantBytes
--)
137 bytesNeeded
= significantBytes
+ 1;
141 *pcbEncoded
= bytesNeeded
;
144 if (*pcbEncoded
< bytesNeeded
)
146 SetLastError(ERROR_MORE_DATA
);
150 *pbEncoded
= (BYTE
)len
;
155 *pbEncoded
++ = significantBytes
| 0x80;
156 for (i
= 0; i
< significantBytes
; i
++)
158 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
162 *pcbEncoded
= bytesNeeded
;
166 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
167 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
168 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
171 DWORD i
, dataLen
= 0;
173 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
174 pbEncoded
, *pcbEncoded
);
175 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
177 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
178 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
179 NULL
, &items
[i
].size
);
180 /* Some functions propagate their errors through the size */
182 *pcbEncoded
= items
[i
].size
;
183 dataLen
+= items
[i
].size
;
187 DWORD lenBytes
, bytesNeeded
;
189 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
190 bytesNeeded
= 1 + lenBytes
+ dataLen
;
192 *pcbEncoded
= bytesNeeded
;
195 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
196 pcbEncoded
, bytesNeeded
)))
198 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
199 pbEncoded
= *(BYTE
**)pbEncoded
;
200 *pbEncoded
++ = ASN_SEQUENCE
;
201 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
202 pbEncoded
+= lenBytes
;
203 for (i
= 0; ret
&& i
< cItem
; i
++)
205 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
206 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
207 NULL
, pbEncoded
, &items
[i
].size
);
208 /* Some functions propagate their errors through the size */
210 *pcbEncoded
= items
[i
].size
;
211 pbEncoded
+= items
[i
].size
;
216 TRACE("returning %d (%08x)\n", ret
, GetLastError());
220 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
221 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
222 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
225 const struct AsnConstructedItem
*item
=
226 (const struct AsnConstructedItem
*)pvStructInfo
;
229 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
230 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
232 DWORD dataLen
, bytesNeeded
;
234 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
235 bytesNeeded
= 1 + dataLen
+ len
;
237 *pcbEncoded
= bytesNeeded
;
238 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
239 pbEncoded
, pcbEncoded
, bytesNeeded
)))
241 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
242 pbEncoded
= *(BYTE
**)pbEncoded
;
243 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
244 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
245 pbEncoded
+= dataLen
;
246 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
247 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
251 /* Some functions propagate their errors through the size */
258 /* Some functions propagate their errors through the size */
264 struct AsnEncodeTagSwappedItem
267 const void *pvStructInfo
;
268 CryptEncodeObjectExFunc encodeFunc
;
271 /* Sort of a wacky hack, it encodes something using the struct
272 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
273 * given in the struct AsnEncodeTagSwappedItem.
275 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
276 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
277 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
280 const struct AsnEncodeTagSwappedItem
*item
=
281 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
283 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
284 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
285 if (ret
&& pbEncoded
)
286 *pbEncoded
= item
->tag
;
290 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
291 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
292 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
294 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
297 /* CERT_V1 is not encoded */
305 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
307 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
308 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
313 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
314 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
315 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
317 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
322 *pcbEncoded
= blob
->cbData
;
327 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
328 pcbEncoded
, blob
->cbData
)))
330 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
331 pbEncoded
= *(BYTE
**)pbEncoded
;
333 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
334 *pcbEncoded
= blob
->cbData
;
341 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
342 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
343 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
346 /* This has two filetimes in a row, a NotBefore and a NotAfter */
347 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
348 struct AsnEncodeSequenceItem items
[] = {
349 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
350 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
353 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
354 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
359 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
362 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
363 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
364 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
367 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
368 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
369 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
370 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
373 struct AsnEncodeSequenceItem items
[2] = {
374 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
375 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
378 if (algo
->Parameters
.cbData
)
379 items
[1].pvStructInfo
= &algo
->Parameters
;
381 items
[1].pvStructInfo
= &nullBlob
;
382 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
383 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
388 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
389 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
390 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
392 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
393 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
395 struct AsnEncodeSequenceItem items
[] = {
396 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
397 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
400 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
401 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
406 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
407 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
408 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
414 const CERT_PUBLIC_KEY_INFO
*info
=
415 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
416 struct AsnEncodeSequenceItem items
[] = {
417 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
418 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
421 TRACE("Encoding public key with OID %s\n",
422 debugstr_a(info
->Algorithm
.pszObjId
));
423 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
424 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
429 SetLastError(STATUS_ACCESS_VIOLATION
);
436 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
437 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
438 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
444 const CERT_SIGNED_CONTENT_INFO
*info
=
445 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
446 struct AsnEncodeSequenceItem items
[] = {
447 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
448 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
449 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
452 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
453 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
454 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
455 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
460 SetLastError(STATUS_ACCESS_VIOLATION
);
467 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
472 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
473 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
479 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
480 struct AsnEncodeSequenceItem items
[10] = {
481 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
482 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
483 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
484 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
485 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
486 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
487 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
490 struct AsnConstructedItem constructed
[3] = { { 0 } };
491 DWORD cItem
= 7, cConstructed
= 0;
493 if (info
->IssuerUniqueId
.cbData
)
495 constructed
[cConstructed
].tag
= 1;
496 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
497 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
498 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
499 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
503 if (info
->SubjectUniqueId
.cbData
)
505 constructed
[cConstructed
].tag
= 2;
506 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
507 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
508 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
509 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
513 if (info
->cExtension
)
515 constructed
[cConstructed
].tag
= 3;
516 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
517 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
518 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
519 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
524 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
525 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
529 SetLastError(STATUS_ACCESS_VIOLATION
);
536 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
537 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
539 struct AsnEncodeSequenceItem items
[3] = {
540 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
541 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
547 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
549 if (entry
->cExtension
)
551 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
552 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
556 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
557 pbEncoded
, pcbEncoded
);
559 TRACE("returning %d (%08x)\n", ret
, GetLastError());
563 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
564 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
565 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
567 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
568 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
569 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
570 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
573 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
577 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
581 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
582 bytesNeeded
= 1 + lenBytes
+ dataLen
;
584 *pcbEncoded
= bytesNeeded
;
587 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
588 pcbEncoded
, bytesNeeded
)))
590 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
591 pbEncoded
= *(BYTE
**)pbEncoded
;
592 *pbEncoded
++ = ASN_SEQUENCEOF
;
593 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
594 pbEncoded
+= lenBytes
;
595 for (i
= 0; i
< cCRLEntry
; i
++)
597 DWORD size
= dataLen
;
599 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
608 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
609 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
610 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
612 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
615 /* CRL_V1 is not encoded */
622 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
623 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
627 /* Like in Windows, this blithely ignores the validity of the passed-in
628 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
629 * decode properly, see CRYPT_AsnDecodeCRLInfo.
631 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
632 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
633 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
639 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
640 struct AsnEncodeSequenceItem items
[7] = {
641 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
642 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
643 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
644 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
647 struct AsnConstructedItem constructed
[1] = { { 0 } };
648 DWORD cItem
= 4, cConstructed
= 0;
650 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
652 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
653 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
658 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
659 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
662 if (info
->cExtension
)
664 constructed
[cConstructed
].tag
= 0;
665 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
666 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
667 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
668 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
673 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
674 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
678 SetLastError(STATUS_ACCESS_VIOLATION
);
685 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
689 struct AsnEncodeSequenceItem items
[3] = {
690 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
696 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
700 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
701 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
704 items
[cItem
].pvStructInfo
= &ext
->Value
;
705 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
708 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
709 pbEncoded
, pcbEncoded
);
710 TRACE("returning %d (%08x)\n", ret
, GetLastError());
714 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
715 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
716 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
722 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
723 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
726 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
730 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
734 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
735 bytesNeeded
= 1 + lenBytes
+ dataLen
;
737 *pcbEncoded
= bytesNeeded
;
740 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
741 pcbEncoded
, bytesNeeded
)))
743 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
744 pbEncoded
= *(BYTE
**)pbEncoded
;
745 *pbEncoded
++ = ASN_SEQUENCEOF
;
746 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
747 pbEncoded
+= lenBytes
;
748 for (i
= 0; i
< exts
->cExtension
; i
++)
750 DWORD size
= dataLen
;
752 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
762 SetLastError(STATUS_ACCESS_VIOLATION
);
769 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
770 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
771 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
773 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
774 DWORD bytesNeeded
= 0, lenBytes
;
779 TRACE("%s\n", debugstr_a(pszObjId
));
786 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
788 SetLastError(CRYPT_E_ASN1_ERROR
);
792 firstByte
= val1
* 40 + val2
;
793 ptr
= pszObjId
+ firstPos
;
798 /* note I assume each component is at most 32-bits long in base 2 */
799 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
801 if (val1
>= 0x10000000)
803 else if (val1
>= 0x200000)
805 else if (val1
>= 0x4000)
807 else if (val1
>= 0x80)
817 SetLastError(CRYPT_E_ASN1_ERROR
);
821 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
825 bytesNeeded
+= 1 + lenBytes
;
828 if (*pcbEncoded
< bytesNeeded
)
830 SetLastError(ERROR_MORE_DATA
);
835 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
836 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
837 pbEncoded
+= lenBytes
;
843 *pbEncoded
++ = firstByte
;
844 ptr
= pszObjId
+ firstPos
;
847 sscanf(ptr
, "%d%n", &val
, &pos
);
849 unsigned char outBytes
[5];
852 if (val
>= 0x10000000)
854 else if (val
>= 0x200000)
856 else if (val
>= 0x4000)
858 else if (val
>= 0x80)
862 for (i
= numBytes
; i
> 0; i
--)
864 outBytes
[i
- 1] = val
& 0x7f;
867 for (i
= 0; i
< numBytes
- 1; i
++)
868 *pbEncoded
++ = outBytes
[i
] | 0x80;
869 *pbEncoded
++ = outBytes
[i
];
878 *pcbEncoded
= bytesNeeded
;
882 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
883 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
887 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
888 DWORD bytesNeeded
, lenBytes
, encodedLen
;
890 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: lstrlenA(str
);
891 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
892 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
894 *pcbEncoded
= bytesNeeded
;
897 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
898 pbEncoded
, pcbEncoded
, bytesNeeded
)))
900 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
901 pbEncoded
= *(BYTE
**)pbEncoded
;
903 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
904 pbEncoded
+= lenBytes
;
905 memcpy(pbEncoded
, str
, encodedLen
);
911 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
912 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
916 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
917 DWORD bytesNeeded
, lenBytes
, strLen
;
919 if (value
->Value
.cbData
)
920 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
921 else if (value
->Value
.pbData
)
922 strLen
= lstrlenW(str
);
925 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
926 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
928 *pcbEncoded
= bytesNeeded
;
931 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
932 pbEncoded
, pcbEncoded
, bytesNeeded
)))
936 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
937 pbEncoded
= *(BYTE
**)pbEncoded
;
938 *pbEncoded
++ = ASN_BMPSTRING
;
939 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
940 pbEncoded
+= lenBytes
;
941 for (i
= 0; i
< strLen
; i
++)
943 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
944 *pbEncoded
++ = str
[i
] & 0x00ff;
951 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
952 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
956 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
957 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
959 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
961 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
963 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
964 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
966 *pcbEncoded
= bytesNeeded
;
969 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
970 pbEncoded
, pcbEncoded
, bytesNeeded
)))
972 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
973 pbEncoded
= *(BYTE
**)pbEncoded
;
974 *pbEncoded
++ = ASN_UTF8STRING
;
975 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
976 pbEncoded
+= lenBytes
;
977 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
978 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
984 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
985 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
986 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
992 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
994 switch (value
->dwValueType
)
996 case CERT_RDN_ANY_TYPE
:
997 /* explicitly disallowed */
998 SetLastError(E_INVALIDARG
);
1001 case CERT_RDN_ENCODED_BLOB
:
1002 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1003 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1005 case CERT_RDN_OCTET_STRING
:
1006 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1007 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1009 case CERT_RDN_NUMERIC_STRING
:
1010 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1011 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1013 case CERT_RDN_PRINTABLE_STRING
:
1014 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1015 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1017 case CERT_RDN_TELETEX_STRING
:
1018 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1019 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1021 case CERT_RDN_VIDEOTEX_STRING
:
1022 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1023 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1025 case CERT_RDN_IA5_STRING
:
1026 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1027 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1029 case CERT_RDN_GRAPHIC_STRING
:
1030 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1031 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1033 case CERT_RDN_VISIBLE_STRING
:
1034 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1035 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1037 case CERT_RDN_GENERAL_STRING
:
1038 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1039 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1041 case CERT_RDN_UNIVERSAL_STRING
:
1042 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1043 SetLastError(CRYPT_E_ASN1_CHOICE
);
1046 case CERT_RDN_BMP_STRING
:
1047 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1048 pbEncoded
, pcbEncoded
);
1050 case CERT_RDN_UTF8_STRING
:
1051 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1052 pbEncoded
, pcbEncoded
);
1055 SetLastError(CRYPT_E_ASN1_CHOICE
);
1061 SetLastError(STATUS_ACCESS_VIOLATION
);
1068 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1069 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1070 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1072 DWORD bytesNeeded
= 0, lenBytes
, size
;
1075 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1076 0, NULL
, NULL
, &size
);
1079 bytesNeeded
+= size
;
1080 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1081 * with dwValueType, so "cast" it to get its encoded size
1083 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1084 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1087 bytesNeeded
+= size
;
1088 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1089 bytesNeeded
+= 1 + lenBytes
;
1092 if (*pcbEncoded
< bytesNeeded
)
1094 SetLastError(ERROR_MORE_DATA
);
1099 *pbEncoded
++ = ASN_SEQUENCE
;
1100 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1102 pbEncoded
+= lenBytes
;
1103 size
= bytesNeeded
- 1 - lenBytes
;
1104 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1105 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1109 size
= bytesNeeded
- 1 - lenBytes
- size
;
1110 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1111 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1112 0, NULL
, pbEncoded
, &size
);
1119 *pcbEncoded
= bytesNeeded
;
1123 /* Have to propagate index of failing character */
1130 static int BLOBComp(const void *l
, const void *r
)
1132 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1135 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1136 ret
= a
->cbData
- b
->cbData
;
1140 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1142 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1143 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1144 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1146 const CRYPT_BLOB_ARRAY
*set
= (const CRYPT_BLOB_ARRAY
*)pvStructInfo
;
1147 DWORD bytesNeeded
= 0, lenBytes
, i
;
1150 for (i
= 0; i
< set
->cBlob
; i
++)
1151 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1152 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1153 bytesNeeded
+= 1 + lenBytes
;
1156 *pcbEncoded
= bytesNeeded
;
1159 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1160 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1162 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1163 pbEncoded
= *(BYTE
**)pbEncoded
;
1164 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1165 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1166 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1167 pbEncoded
+= lenBytes
;
1168 for (i
= 0; ret
&& i
< set
->cBlob
; i
++)
1170 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1171 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1177 struct DERSetDescriptor
1183 CryptEncodeObjectExFunc encode
;
1186 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1187 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1188 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1190 const struct DERSetDescriptor
*desc
=
1191 (const struct DERSetDescriptor
*)pvStructInfo
;
1192 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1198 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1203 setOf
.cBlob
= desc
->cItems
;
1204 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1207 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1209 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1210 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1211 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1214 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1215 if (!setOf
.rgBlob
[i
].pbData
)
1218 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1219 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1220 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1221 &setOf
.rgBlob
[i
].cbData
);
1223 /* Some functions propagate their errors through the size */
1225 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1229 DWORD bytesNeeded
= 0, lenBytes
;
1231 for (i
= 0; i
< setOf
.cBlob
; i
++)
1232 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1233 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1234 bytesNeeded
+= 1 + lenBytes
;
1236 *pcbEncoded
= bytesNeeded
;
1237 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1238 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1240 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1241 pbEncoded
= *(BYTE
**)pbEncoded
;
1242 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1244 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1245 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1246 pbEncoded
+= lenBytes
;
1247 for (i
= 0; i
< setOf
.cBlob
; i
++)
1249 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1250 setOf
.rgBlob
[i
].cbData
);
1251 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1255 for (i
= 0; i
< setOf
.cBlob
; i
++)
1256 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1257 CryptMemFree(setOf
.rgBlob
);
1261 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1262 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1266 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1275 setOf
.cBlob
= rdn
->cRDNAttr
;
1276 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1277 sizeof(CRYPT_DER_BLOB
));
1281 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1283 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1285 setOf
.rgBlob
[i
].cbData
= 0;
1286 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1287 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1290 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1291 if (!setOf
.rgBlob
[i
].pbData
)
1294 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1295 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1296 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1300 /* Have to propagate index of failing character */
1301 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1305 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1306 pbEncoded
, pcbEncoded
);
1307 for (i
= 0; i
< setOf
.cBlob
; i
++)
1308 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1312 SetLastError(STATUS_ACCESS_VIOLATION
);
1316 CryptMemFree(setOf
.rgBlob
);
1320 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1321 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1322 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1324 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1325 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1326 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1329 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1332 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1333 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1334 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1336 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1337 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1341 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1342 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1343 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1349 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1350 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1352 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1354 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1356 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1357 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1359 bytesNeeded
+= size
;
1363 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1364 bytesNeeded
+= 1 + lenBytes
;
1368 *pcbEncoded
= bytesNeeded
;
1371 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1372 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1374 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1375 pbEncoded
= *(BYTE
**)pbEncoded
;
1376 *pbEncoded
++ = ASN_SEQUENCEOF
;
1377 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1379 pbEncoded
+= lenBytes
;
1380 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1383 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1384 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1389 bytesNeeded
-= size
;
1400 SetLastError(STATUS_ACCESS_VIOLATION
);
1407 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1408 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1409 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1415 const CRYPT_SMIME_CAPABILITY
*capability
=
1416 (const CRYPT_SMIME_CAPABILITY
*)pvStructInfo
;
1418 if (!capability
->pszObjId
)
1419 SetLastError(E_INVALIDARG
);
1422 struct AsnEncodeSequenceItem items
[] = {
1423 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1424 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1427 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1428 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1434 SetLastError(STATUS_ACCESS_VIOLATION
);
1440 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1441 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1442 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1448 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1449 const CRYPT_SMIME_CAPABILITIES
*capabilities
=
1450 (const CRYPT_SMIME_CAPABILITIES
*)pvStructInfo
;
1453 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1457 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1458 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1462 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1463 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1465 *pcbEncoded
= bytesNeeded
;
1468 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1469 pcbEncoded
, bytesNeeded
)))
1471 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1472 pbEncoded
= *(BYTE
**)pbEncoded
;
1473 *pbEncoded
++ = ASN_SEQUENCEOF
;
1474 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1475 pbEncoded
+= lenBytes
;
1476 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1478 DWORD size
= dataLen
;
1480 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1481 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
, pbEncoded
,
1491 SetLastError(STATUS_ACCESS_VIOLATION
);
1497 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1498 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1499 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1505 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1507 if (!attr
->pszObjId
)
1508 SetLastError(E_INVALIDARG
);
1511 struct AsnEncodeSequenceItem items
[2] = {
1512 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1513 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1516 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1517 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1523 SetLastError(STATUS_ACCESS_VIOLATION
);
1529 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1530 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1531 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1537 const CRYPT_ATTRIBUTES
*attributes
=
1538 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1539 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1540 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1542 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1543 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1547 SetLastError(STATUS_ACCESS_VIOLATION
);
1553 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1554 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1555 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1556 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1559 const CRYPT_CONTENT_INFO
*info
= (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1560 struct AsnEncodeSequenceItem items
[2] = {
1561 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1564 struct AsnConstructedItem constructed
= { 0 };
1567 if (info
->Content
.cbData
)
1569 constructed
.tag
= 0;
1570 constructed
.pvStructInfo
= &info
->Content
;
1571 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1572 items
[cItem
].pvStructInfo
= &constructed
;
1573 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1576 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1577 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1580 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1581 void *pvData
, DWORD
*pcbData
)
1583 struct AsnEncodeSequenceItem items
[] = {
1584 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1585 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1587 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1588 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1591 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1592 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1595 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1596 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1597 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1603 const CRYPT_CONTENT_INFO
*info
=
1604 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1606 if (!info
->pszObjId
)
1607 SetLastError(E_INVALIDARG
);
1609 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1610 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1615 SetLastError(STATUS_ACCESS_VIOLATION
);
1621 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1622 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1626 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1627 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1629 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1631 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1632 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1634 *pcbEncoded
= bytesNeeded
;
1637 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1638 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1642 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1643 pbEncoded
= *(BYTE
**)pbEncoded
;
1645 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1646 pbEncoded
+= lenBytes
;
1647 for (i
= 0; i
< encodedLen
; i
++)
1648 *pbEncoded
++ = (BYTE
)str
[i
];
1654 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara
, LPVOID pv
)
1656 if (pEncodePara
&& pEncodePara
->pfnFree
)
1657 pEncodePara
->pfnFree(pv
);
1662 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1663 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1667 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1668 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1670 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1672 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1673 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1675 *pcbEncoded
= bytesNeeded
;
1678 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1679 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1684 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1685 ptr
= *(BYTE
**)pbEncoded
;
1688 *ptr
++ = ASN_NUMERICSTRING
;
1689 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1691 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1693 if (isdigitW(str
[i
]))
1694 *ptr
++ = (BYTE
)str
[i
];
1698 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1702 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1703 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
1709 static inline int isprintableW(WCHAR wc
)
1711 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1712 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1713 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1716 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1717 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1721 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1722 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1724 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1726 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1727 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1729 *pcbEncoded
= bytesNeeded
;
1732 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1733 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1738 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1739 ptr
= *(BYTE
**)pbEncoded
;
1742 *ptr
++ = ASN_PRINTABLESTRING
;
1743 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1745 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1747 if (isprintableW(str
[i
]))
1748 *ptr
++ = (BYTE
)str
[i
];
1752 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1756 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1757 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
1763 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1764 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1768 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1769 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1771 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1773 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1774 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1776 *pcbEncoded
= bytesNeeded
;
1779 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1780 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1785 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1786 ptr
= *(BYTE
**)pbEncoded
;
1789 *ptr
++ = ASN_IA5STRING
;
1790 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
1792 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1795 *ptr
++ = (BYTE
)str
[i
];
1799 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1803 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1804 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
1810 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
1811 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1815 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1816 DWORD bytesNeeded
, lenBytes
, strLen
;
1818 /* FIXME: doesn't handle composite characters */
1819 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1821 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
1822 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
1824 *pcbEncoded
= bytesNeeded
;
1827 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1828 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1832 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1833 pbEncoded
= *(BYTE
**)pbEncoded
;
1834 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
1835 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
1836 pbEncoded
+= lenBytes
;
1837 for (i
= 0; i
< strLen
; i
++)
1841 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
1842 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
1849 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1850 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1851 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1857 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1859 switch (value
->dwValueType
)
1861 case CERT_RDN_ANY_TYPE
:
1862 case CERT_RDN_ENCODED_BLOB
:
1863 case CERT_RDN_OCTET_STRING
:
1864 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
1866 case CERT_RDN_NUMERIC_STRING
:
1867 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
1868 pbEncoded
, pcbEncoded
);
1870 case CERT_RDN_PRINTABLE_STRING
:
1871 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
1872 pbEncoded
, pcbEncoded
);
1874 case CERT_RDN_TELETEX_STRING
:
1875 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
1876 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1878 case CERT_RDN_VIDEOTEX_STRING
:
1879 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
1880 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1882 case CERT_RDN_IA5_STRING
:
1883 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
1884 pbEncoded
, pcbEncoded
);
1886 case CERT_RDN_GRAPHIC_STRING
:
1887 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1888 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1890 case CERT_RDN_VISIBLE_STRING
:
1891 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
1892 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1894 case CERT_RDN_GENERAL_STRING
:
1895 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
1896 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1898 case CERT_RDN_UNIVERSAL_STRING
:
1899 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
1900 pbEncoded
, pcbEncoded
);
1902 case CERT_RDN_BMP_STRING
:
1903 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1904 pbEncoded
, pcbEncoded
);
1906 case CERT_RDN_UTF8_STRING
:
1907 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1908 pbEncoded
, pcbEncoded
);
1911 SetLastError(CRYPT_E_ASN1_CHOICE
);
1916 SetLastError(STATUS_ACCESS_VIOLATION
);
1922 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1923 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1924 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1930 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1931 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1933 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1935 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1937 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1938 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
1940 bytesNeeded
+= size
;
1942 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1943 bytesNeeded
+= 1 + lenBytes
;
1947 *pcbEncoded
= bytesNeeded
;
1950 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1951 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1953 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1954 pbEncoded
= *(BYTE
**)pbEncoded
;
1955 *pbEncoded
++ = ASN_SEQUENCEOF
;
1956 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1958 pbEncoded
+= lenBytes
;
1959 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1962 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1963 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
1968 bytesNeeded
-= size
;
1977 SetLastError(STATUS_ACCESS_VIOLATION
);
1984 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1985 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1986 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1988 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1997 else if (*pcbEncoded
< 3)
2000 SetLastError(ERROR_MORE_DATA
);
2006 *pbEncoded
++ = ASN_BOOL
;
2008 *pbEncoded
++ = val
? 0xff : 0;
2011 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2015 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2016 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2017 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2019 const CERT_ALT_NAME_ENTRY
*entry
=
2020 (const CERT_ALT_NAME_ENTRY
*)pvStructInfo
;
2026 switch (entry
->dwAltNameChoice
)
2028 case CERT_ALT_NAME_RFC822_NAME
:
2029 case CERT_ALT_NAME_DNS_NAME
:
2030 case CERT_ALT_NAME_URL
:
2031 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2032 if (entry
->u
.pwszURL
)
2036 /* Not + 1: don't encode the NULL-terminator */
2037 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2038 for (i
= 0; ret
&& i
< dataLen
; i
++)
2040 if (entry
->u
.pwszURL
[i
] > 0x7f)
2042 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2051 case CERT_ALT_NAME_DIRECTORY_NAME
:
2052 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2053 dataLen
= entry
->u
.DirectoryName
.cbData
;
2055 case CERT_ALT_NAME_IP_ADDRESS
:
2056 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2057 dataLen
= entry
->u
.IPAddress
.cbData
;
2059 case CERT_ALT_NAME_REGISTERED_ID
:
2061 struct AsnEncodeTagSwappedItem swapped
=
2062 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2063 CRYPT_AsnEncodeOid
};
2065 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2068 case CERT_ALT_NAME_OTHER_NAME
:
2069 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2072 SetLastError(E_INVALIDARG
);
2077 DWORD bytesNeeded
, lenBytes
;
2079 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2080 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2082 *pcbEncoded
= bytesNeeded
;
2083 else if (*pcbEncoded
< bytesNeeded
)
2085 SetLastError(ERROR_MORE_DATA
);
2086 *pcbEncoded
= bytesNeeded
;
2092 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2093 pbEncoded
+= lenBytes
;
2094 switch (entry
->dwAltNameChoice
)
2096 case CERT_ALT_NAME_RFC822_NAME
:
2097 case CERT_ALT_NAME_DNS_NAME
:
2098 case CERT_ALT_NAME_URL
:
2102 for (i
= 0; i
< dataLen
; i
++)
2103 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2106 case CERT_ALT_NAME_DIRECTORY_NAME
:
2107 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2109 case CERT_ALT_NAME_IP_ADDRESS
:
2110 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2114 *pcbEncoded
= bytesNeeded
;
2117 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2121 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2122 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2123 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2129 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2130 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2135 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2140 for (i
= 0; i
< newBlob
.cbData
; i
++)
2141 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2147 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2148 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2149 CryptMemFree(newBlob
.pbData
);
2153 SetLastError(STATUS_ACCESS_VIOLATION
);
2160 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2161 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2162 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2168 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
2169 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
2170 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2171 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2172 struct AsnConstructedItem constructed
= { 0 };
2173 DWORD cItem
= 0, cSwapped
= 0;
2175 if (info
->KeyId
.cbData
)
2177 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2178 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2179 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2180 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2181 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2185 if (info
->CertIssuer
.cbData
)
2187 constructed
.tag
= 1;
2188 constructed
.pvStructInfo
= &info
->CertIssuer
;
2189 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2190 items
[cItem
].pvStructInfo
= &constructed
;
2191 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2194 if (info
->CertSerialNumber
.cbData
)
2196 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2197 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2198 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2199 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2200 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2204 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2205 pEncodePara
, pbEncoded
, pcbEncoded
);
2209 SetLastError(STATUS_ACCESS_VIOLATION
);
2216 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2217 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2218 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2224 const CERT_ALT_NAME_INFO
*info
=
2225 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2226 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2229 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2230 * can't encode an erroneous entry index if it's bigger than this.
2232 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2236 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2237 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2240 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2242 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2243 * the bad character, now set the index of the bad
2246 *pcbEncoded
= (BYTE
)i
<<
2247 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2252 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2253 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2256 *pcbEncoded
= bytesNeeded
;
2261 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2262 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2264 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2265 pbEncoded
= *(BYTE
**)pbEncoded
;
2266 *pbEncoded
++ = ASN_SEQUENCEOF
;
2267 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2268 pbEncoded
+= lenBytes
;
2269 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2271 DWORD len
= dataLen
;
2273 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2274 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, pbEncoded
, &len
);
2287 SetLastError(STATUS_ACCESS_VIOLATION
);
2294 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2295 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2296 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2302 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2303 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2304 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2305 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2306 DWORD cItem
= 0, cSwapped
= 0;
2308 if (info
->KeyId
.cbData
)
2310 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2311 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2312 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2313 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2314 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2318 if (info
->AuthorityCertIssuer
.cAltEntry
)
2320 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2321 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2322 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2323 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2324 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2328 if (info
->AuthorityCertSerialNumber
.cbData
)
2330 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2331 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2332 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2333 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2334 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2338 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2339 pEncodePara
, pbEncoded
, pcbEncoded
);
2343 SetLastError(STATUS_ACCESS_VIOLATION
);
2350 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2351 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2352 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2358 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2359 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2360 struct AsnEncodeSequenceItem items
[3] = {
2361 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2366 if (info
->fPathLenConstraint
)
2368 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2369 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2372 if (info
->cSubtreesConstraint
)
2374 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2375 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2378 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2379 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2383 SetLastError(STATUS_ACCESS_VIOLATION
);
2390 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2391 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2392 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2398 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2399 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2400 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2405 items
[cItem
].pvStructInfo
= &info
->fCA
;
2406 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2409 if (info
->fPathLenConstraint
)
2411 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2412 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2415 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2416 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2420 SetLastError(STATUS_ACCESS_VIOLATION
);
2427 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2428 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2429 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2435 const BLOBHEADER
*hdr
=
2436 (const BLOBHEADER
*)pvStructInfo
;
2438 if (hdr
->bType
!= PUBLICKEYBLOB
)
2440 SetLastError(E_INVALIDARG
);
2445 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2446 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2447 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2448 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2449 struct AsnEncodeSequenceItem items
[] = {
2450 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2451 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2454 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2455 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2461 SetLastError(STATUS_ACCESS_VIOLATION
);
2468 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2469 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2470 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2476 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2477 DWORD bytesNeeded
, lenBytes
;
2479 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2480 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2482 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2483 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2486 *pcbEncoded
= bytesNeeded
;
2491 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2492 pcbEncoded
, bytesNeeded
)))
2494 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2495 pbEncoded
= *(BYTE
**)pbEncoded
;
2496 *pbEncoded
++ = ASN_OCTETSTRING
;
2497 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2498 pbEncoded
+= lenBytes
;
2500 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2506 SetLastError(STATUS_ACCESS_VIOLATION
);
2510 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2514 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2515 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2516 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2522 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2523 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2526 /* yep, MS allows cUnusedBits to be >= 8 */
2527 if (!blob
->cUnusedBits
)
2529 dataBytes
= blob
->cbData
;
2532 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2534 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2535 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2543 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2544 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2547 *pcbEncoded
= bytesNeeded
;
2552 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2553 pcbEncoded
, bytesNeeded
)))
2555 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2556 pbEncoded
= *(BYTE
**)pbEncoded
;
2557 *pbEncoded
++ = ASN_BITSTRING
;
2558 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2559 pbEncoded
+= lenBytes
;
2560 *pbEncoded
++ = unusedBits
;
2563 BYTE mask
= 0xff << unusedBits
;
2567 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2568 pbEncoded
+= dataBytes
- 1;
2570 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2577 SetLastError(STATUS_ACCESS_VIOLATION
);
2584 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2585 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2586 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2592 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2593 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2598 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2603 for (i
= 0; i
< newBlob
.cbData
; i
++)
2604 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2610 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2611 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2612 CryptMemFree(newBlob
.pbData
);
2616 SetLastError(STATUS_ACCESS_VIOLATION
);
2623 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2624 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2625 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2627 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2629 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2630 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2633 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2634 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2635 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2641 DWORD significantBytes
, lenBytes
, bytesNeeded
;
2644 const CRYPT_INTEGER_BLOB
*blob
=
2645 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2647 significantBytes
= blob
->cbData
;
2648 if (significantBytes
)
2650 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2652 /* negative, lop off leading (little-endian) 0xffs */
2653 for (; significantBytes
> 0 &&
2654 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2656 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2664 /* positive, lop off leading (little-endian) zeroes */
2665 for (; significantBytes
> 0 &&
2666 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2668 if (significantBytes
== 0)
2669 significantBytes
= 1;
2670 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2678 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2680 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2681 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2686 *pcbEncoded
= bytesNeeded
;
2691 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2692 pcbEncoded
, bytesNeeded
)))
2694 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2695 pbEncoded
= *(BYTE
**)pbEncoded
;
2696 *pbEncoded
++ = ASN_INTEGER
;
2699 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2700 pbEncoded
+= lenBytes
;
2701 *pbEncoded
++ = padByte
;
2705 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2706 pbEncoded
+= lenBytes
;
2708 for (; significantBytes
> 0; significantBytes
--)
2709 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2715 SetLastError(STATUS_ACCESS_VIOLATION
);
2722 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
2723 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2724 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2730 DWORD significantBytes
, lenBytes
, bytesNeeded
;
2732 const CRYPT_INTEGER_BLOB
*blob
=
2733 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2735 significantBytes
= blob
->cbData
;
2736 if (significantBytes
)
2738 /* positive, lop off leading (little-endian) zeroes */
2739 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2742 if (significantBytes
== 0)
2743 significantBytes
= 1;
2744 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2748 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2750 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2751 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2756 *pcbEncoded
= bytesNeeded
;
2761 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2762 pcbEncoded
, bytesNeeded
)))
2764 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2765 pbEncoded
= *(BYTE
**)pbEncoded
;
2766 *pbEncoded
++ = ASN_INTEGER
;
2769 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2770 pbEncoded
+= lenBytes
;
2775 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2776 pbEncoded
+= lenBytes
;
2778 for (; significantBytes
> 0; significantBytes
--)
2779 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2785 SetLastError(STATUS_ACCESS_VIOLATION
);
2792 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2793 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2794 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2796 CRYPT_INTEGER_BLOB blob
;
2799 /* Encode as an unsigned integer, then change the tag to enumerated */
2800 blob
.cbData
= sizeof(DWORD
);
2801 blob
.pbData
= (BYTE
*)pvStructInfo
;
2802 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2803 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2804 if (ret
&& pbEncoded
)
2806 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2807 pbEncoded
= *(BYTE
**)pbEncoded
;
2808 pbEncoded
[0] = ASN_ENUMERATED
;
2813 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2814 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2815 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2822 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2823 * temporary buffer because the output buffer is not NULL-terminated.
2826 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2830 *pcbEncoded
= bytesNeeded
;
2835 /* Sanity check the year, this is a two-digit year format */
2836 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2838 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2840 SetLastError(CRYPT_E_BAD_ENCODE
);
2845 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2846 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2848 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2849 pbEncoded
= *(BYTE
**)pbEncoded
;
2850 buf
[0] = ASN_UTCTIME
;
2851 buf
[1] = bytesNeeded
- 2;
2852 snprintf(buf
+ 2, sizeof(buf
) - 2,
2853 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2854 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2855 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2856 sysTime
.wMinute
, sysTime
.wSecond
);
2857 memcpy(pbEncoded
, buf
, bytesNeeded
);
2864 SetLastError(STATUS_ACCESS_VIOLATION
);
2871 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2872 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2873 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2880 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2881 * temporary buffer because the output buffer is not NULL-terminated.
2884 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2888 *pcbEncoded
= bytesNeeded
;
2893 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2896 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2897 pcbEncoded
, bytesNeeded
);
2900 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2901 pbEncoded
= *(BYTE
**)pbEncoded
;
2902 buf
[0] = ASN_GENERALTIME
;
2903 buf
[1] = bytesNeeded
- 2;
2904 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2905 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2906 sysTime
.wMinute
, sysTime
.wSecond
);
2907 memcpy(pbEncoded
, buf
, bytesNeeded
);
2913 SetLastError(STATUS_ACCESS_VIOLATION
);
2920 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2921 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2922 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2930 /* Check the year, if it's in the UTCTime range call that encode func */
2931 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2933 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2934 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2935 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2937 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2938 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2943 SetLastError(STATUS_ACCESS_VIOLATION
);
2950 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2951 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2952 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2958 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2959 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2960 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2962 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2963 dataLen
+= seq
->rgValue
[i
].cbData
;
2964 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2965 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2968 *pcbEncoded
= bytesNeeded
;
2973 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2974 pcbEncoded
, bytesNeeded
)))
2976 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2977 pbEncoded
= *(BYTE
**)pbEncoded
;
2978 *pbEncoded
++ = ASN_SEQUENCEOF
;
2979 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2980 pbEncoded
+= lenBytes
;
2981 for (i
= 0; i
< seq
->cValue
; i
++)
2983 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2984 seq
->rgValue
[i
].cbData
);
2985 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2992 SetLastError(STATUS_ACCESS_VIOLATION
);
2999 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3000 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3003 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3004 struct AsnConstructedItem constructed
= { 0 };
3005 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3006 DWORD cItem
= 0, cSwapped
= 0;
3008 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3010 case CRL_DIST_POINT_NO_NAME
:
3013 case CRL_DIST_POINT_FULL_NAME
:
3014 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3015 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3016 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3017 constructed
.tag
= 0;
3018 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3019 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3020 items
[cItem
].pvStructInfo
= &constructed
;
3021 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3025 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3026 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3032 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3034 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3035 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3036 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3037 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3038 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3042 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3044 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3045 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3046 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3047 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3048 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3053 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3054 pbEncoded
, pcbEncoded
);
3058 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3059 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3060 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3066 const CRL_DIST_POINTS_INFO
*info
=
3067 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
3069 if (!info
->cDistPoint
)
3071 SetLastError(E_INVALIDARG
);
3076 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3079 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3083 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3087 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3089 /* Have to propagate index of failing character */
3095 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3096 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3099 *pcbEncoded
= bytesNeeded
;
3104 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3105 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3107 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3108 pbEncoded
= *(BYTE
**)pbEncoded
;
3109 *pbEncoded
++ = ASN_SEQUENCEOF
;
3110 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3111 pbEncoded
+= lenBytes
;
3112 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3114 DWORD len
= dataLen
;
3116 ret
= CRYPT_AsnEncodeDistPoint(
3117 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3131 SetLastError(STATUS_ACCESS_VIOLATION
);
3138 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3139 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3140 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3146 const CERT_ENHKEY_USAGE
*usage
=
3147 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
3148 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3151 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3153 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3154 usage
->rgpszUsageIdentifier
[i
],
3155 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3157 bytesNeeded
+= size
;
3159 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3160 bytesNeeded
+= 1 + lenBytes
;
3164 *pcbEncoded
= bytesNeeded
;
3167 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3168 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3170 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3171 pbEncoded
= *(BYTE
**)pbEncoded
;
3172 *pbEncoded
++ = ASN_SEQUENCEOF
;
3173 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3175 pbEncoded
+= lenBytes
;
3176 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3179 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3180 usage
->rgpszUsageIdentifier
[i
],
3181 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3186 bytesNeeded
-= size
;
3195 SetLastError(STATUS_ACCESS_VIOLATION
);
3202 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3203 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3204 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3210 const CRL_ISSUING_DIST_POINT
*point
=
3211 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3212 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3213 struct AsnConstructedItem constructed
= { 0 };
3214 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3215 DWORD cItem
= 0, cSwapped
= 0;
3218 switch (point
->DistPointName
.dwDistPointNameChoice
)
3220 case CRL_DIST_POINT_NO_NAME
:
3223 case CRL_DIST_POINT_FULL_NAME
:
3224 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3225 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3226 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3227 constructed
.tag
= 0;
3228 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3229 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3230 items
[cItem
].pvStructInfo
= &constructed
;
3231 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3236 SetLastError(E_INVALIDARG
);
3239 if (ret
&& point
->fOnlyContainsUserCerts
)
3241 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3242 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3243 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3244 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3245 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3249 if (ret
&& point
->fOnlyContainsCACerts
)
3251 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3252 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3253 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3254 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3255 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3259 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3261 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3262 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3263 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3264 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3265 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3269 if (ret
&& point
->fIndirectCRL
)
3271 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3272 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3273 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3274 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3275 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3280 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3281 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3285 SetLastError(STATUS_ACCESS_VIOLATION
);
3292 static BOOL WINAPI
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3293 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3294 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3297 const CERT_GENERAL_SUBTREE
*subtree
=
3298 (const CERT_GENERAL_SUBTREE
*)pvStructInfo
;
3299 struct AsnEncodeSequenceItem items
[3] = {
3300 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
3303 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3304 DWORD cItem
= 1, cSwapped
= 0;
3306 if (subtree
->dwMinimum
)
3308 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3309 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
3310 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3311 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3312 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3316 if (subtree
->fMaximum
)
3318 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3319 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
3320 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3321 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3322 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3326 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
3327 pEncodePara
, pbEncoded
, pcbEncoded
);
3331 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
3332 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3333 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3336 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
3338 TRACE("%p\n", pvStructInfo
);
3342 const CERT_NAME_CONSTRAINTS_INFO
*constraints
=
3343 (const CERT_NAME_CONSTRAINTS_INFO
*)pvStructInfo
;
3344 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
3345 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3346 DWORD i
, cItem
= 0, cSwapped
= 0;
3349 if (constraints
->cPermittedSubtree
)
3351 permitted
.rgBlob
= CryptMemAlloc(
3352 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
3353 if (permitted
.rgBlob
)
3355 permitted
.cBlob
= constraints
->cPermittedSubtree
;
3356 memset(permitted
.rgBlob
, 0,
3357 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3358 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
3359 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3360 NULL
, &constraints
->rgPermittedSubtree
[i
],
3361 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3362 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
3363 &permitted
.rgBlob
[i
].cbData
);
3366 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3367 swapped
[cSwapped
].pvStructInfo
= &permitted
;
3368 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3369 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3370 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3378 if (constraints
->cExcludedSubtree
)
3380 excluded
.rgBlob
= CryptMemAlloc(
3381 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
3382 if (excluded
.rgBlob
)
3384 excluded
.cBlob
= constraints
->cExcludedSubtree
;
3385 memset(excluded
.rgBlob
, 0,
3386 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
3387 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
3388 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
3389 NULL
, &constraints
->rgExcludedSubtree
[i
],
3390 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
3391 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
3392 &excluded
.rgBlob
[i
].cbData
);
3395 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3396 swapped
[cSwapped
].pvStructInfo
= &excluded
;
3397 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
3398 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3399 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3408 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3409 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3410 for (i
= 0; i
< permitted
.cBlob
; i
++)
3411 LocalFree(permitted
.rgBlob
[i
].pbData
);
3412 for (i
= 0; i
< excluded
.cBlob
; i
++)
3413 LocalFree(excluded
.rgBlob
[i
].pbData
);
3417 SetLastError(STATUS_ACCESS_VIOLATION
);
3420 CryptMemFree(permitted
.rgBlob
);
3421 CryptMemFree(excluded
.rgBlob
);
3422 TRACE("returning %d\n", ret
);
3426 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3427 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3428 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3432 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3433 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3434 struct AsnEncodeSequenceItem items
[] = {
3435 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3436 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3439 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3440 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3445 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3446 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3447 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3451 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3453 SetLastError(E_INVALIDARG
);
3459 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
3461 if (!info
->Issuer
.cbData
)
3462 SetLastError(E_INVALIDARG
);
3465 struct AsnEncodeSequenceItem items
[7] = {
3466 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3467 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3468 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
3471 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3472 DWORD cItem
= 3, cSwapped
= 0;
3474 if (info
->AuthAttrs
.cAttr
)
3476 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3477 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3478 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3479 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3480 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3484 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
3485 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3487 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3488 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3490 if (info
->UnauthAttrs
.cAttr
)
3492 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3493 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
3494 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3495 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3496 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3500 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3501 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3506 SetLastError(STATUS_ACCESS_VIOLATION
);
3512 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
3513 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3514 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3518 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3520 SetLastError(E_INVALIDARG
);
3526 const CMSG_CMS_SIGNER_INFO
*info
= (const CMSG_CMS_SIGNER_INFO
*)pvStructInfo
;
3528 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
3529 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
3530 SetLastError(E_INVALIDARG
);
3531 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
3532 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
3533 SetLastError(E_INVALIDARG
);
3536 struct AsnEncodeSequenceItem items
[7] = {
3537 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3539 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3540 DWORD cItem
= 1, cSwapped
= 0;
3542 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
3544 items
[cItem
].pvStructInfo
=
3545 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
3546 items
[cItem
].encodeFunc
=
3547 CRYPT_AsnEncodeIssuerSerialNumber
;
3552 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3553 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
3554 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3555 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3556 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3560 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
3561 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3563 if (info
->AuthAttrs
.cAttr
)
3565 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3566 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3567 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3568 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3569 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3573 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
3574 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3576 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3577 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3579 if (info
->UnauthAttrs
.cAttr
)
3581 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3582 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
3583 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3584 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3585 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3589 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3590 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3595 SetLastError(STATUS_ACCESS_VIOLATION
);
3601 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
3604 struct AsnEncodeSequenceItem items
[7] = {
3605 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
3607 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
3608 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
3609 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3610 DWORD cItem
= 1, cSwapped
= 0;
3613 if (signedInfo
->cSignerInfo
)
3615 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
3616 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
3617 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
3618 digestAlgorithmsSet
.itemOffset
=
3619 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
3620 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3621 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
3622 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3625 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
3626 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
3628 if (signedInfo
->cCertEncoded
)
3630 certSet
.cItems
= signedInfo
->cCertEncoded
;
3631 certSet
.items
= signedInfo
->rgCertEncoded
;
3632 certSet
.itemSize
= sizeof(CERT_BLOB
);
3633 certSet
.itemOffset
= 0;
3634 certSet
.encode
= CRYPT_CopyEncodedBlob
;
3635 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
3636 swapped
[cSwapped
].pvStructInfo
= &certSet
;
3637 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3638 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3639 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3643 if (signedInfo
->cCrlEncoded
)
3645 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
3646 crlSet
.items
= signedInfo
->rgCrlEncoded
;
3647 crlSet
.itemSize
= sizeof(CRL_BLOB
);
3648 crlSet
.itemOffset
= 0;
3649 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
3650 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
3651 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
3652 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3653 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3654 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3658 if (ret
&& signedInfo
->cSignerInfo
)
3660 signerSet
.cItems
= signedInfo
->cSignerInfo
;
3661 signerSet
.items
= signedInfo
->rgSignerInfo
;
3662 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
3663 signerSet
.itemOffset
= 0;
3664 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
3665 items
[cItem
].pvStructInfo
= &signerSet
;
3666 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3670 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
3671 items
, cItem
, 0, NULL
, pvData
, pcbData
);
3676 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
3677 LPCSTR lpszStructType
)
3679 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3681 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3682 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3684 SetLastError(ERROR_FILE_NOT_FOUND
);
3688 if (!HIWORD(lpszStructType
))
3690 switch (LOWORD(lpszStructType
))
3692 case LOWORD(X509_CERT
):
3693 encodeFunc
= CRYPT_AsnEncodeCert
;
3695 case LOWORD(X509_CERT_TO_BE_SIGNED
):
3696 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
3698 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
3699 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
3701 case LOWORD(X509_EXTENSIONS
):
3702 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3704 case LOWORD(X509_NAME_VALUE
):
3705 encodeFunc
= CRYPT_AsnEncodeNameValue
;
3707 case LOWORD(X509_NAME
):
3708 encodeFunc
= CRYPT_AsnEncodeName
;
3710 case LOWORD(X509_PUBLIC_KEY_INFO
):
3711 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
3713 case LOWORD(X509_AUTHORITY_KEY_ID
):
3714 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3716 case LOWORD(X509_ALTERNATE_NAME
):
3717 encodeFunc
= CRYPT_AsnEncodeAltName
;
3719 case LOWORD(X509_BASIC_CONSTRAINTS
):
3720 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3722 case LOWORD(X509_BASIC_CONSTRAINTS2
):
3723 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3725 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
3726 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
3728 case LOWORD(X509_UNICODE_NAME
):
3729 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
3731 case LOWORD(PKCS_CONTENT_INFO
):
3732 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
3734 case LOWORD(PKCS_ATTRIBUTE
):
3735 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
3737 case LOWORD(X509_UNICODE_NAME_VALUE
):
3738 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
3740 case LOWORD(X509_OCTET_STRING
):
3741 encodeFunc
= CRYPT_AsnEncodeOctets
;
3743 case LOWORD(X509_BITS
):
3744 case LOWORD(X509_KEY_USAGE
):
3745 encodeFunc
= CRYPT_AsnEncodeBits
;
3747 case LOWORD(X509_INTEGER
):
3748 encodeFunc
= CRYPT_AsnEncodeInt
;
3750 case LOWORD(X509_MULTI_BYTE_INTEGER
):
3751 encodeFunc
= CRYPT_AsnEncodeInteger
;
3753 case LOWORD(X509_MULTI_BYTE_UINT
):
3754 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
3756 case LOWORD(X509_ENUMERATED
):
3757 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3759 case LOWORD(X509_CHOICE_OF_TIME
):
3760 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
3762 case LOWORD(X509_AUTHORITY_KEY_ID2
):
3763 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3765 case LOWORD(X509_SEQUENCE_OF_ANY
):
3766 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
3768 case LOWORD(PKCS_UTC_TIME
):
3769 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3771 case LOWORD(X509_CRL_DIST_POINTS
):
3772 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3774 case LOWORD(X509_ENHANCED_KEY_USAGE
):
3775 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3777 case LOWORD(PKCS_SMIME_CAPABILITIES
):
3778 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
3780 case LOWORD(PKCS_ATTRIBUTES
):
3781 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3783 case LOWORD(X509_ISSUING_DIST_POINT
):
3784 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3786 case LOWORD(X509_NAME_CONSTRAINTS
):
3787 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
3789 case LOWORD(PKCS7_SIGNER_INFO
):
3790 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
3792 case LOWORD(CMS_SIGNER_INFO
):
3793 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
3797 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
3798 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3799 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3800 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3801 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
3802 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3803 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
3804 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3805 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
3806 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3807 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3808 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3809 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3810 encodeFunc
= CRYPT_AsnEncodeBits
;
3811 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3812 encodeFunc
= CRYPT_AsnEncodeOctets
;
3813 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
3814 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3815 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3816 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3817 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
3818 encodeFunc
= CRYPT_AsnEncodeAltName
;
3819 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
3820 encodeFunc
= CRYPT_AsnEncodeAltName
;
3821 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
3822 encodeFunc
= CRYPT_AsnEncodeAltName
;
3823 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
3824 encodeFunc
= CRYPT_AsnEncodeAltName
;
3825 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
3826 encodeFunc
= CRYPT_AsnEncodeAltName
;
3827 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
3828 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3829 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
3830 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3831 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
3832 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3833 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
3834 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
3838 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
3839 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
3841 static HCRYPTOIDFUNCSET set
= NULL
;
3842 CryptEncodeObjectFunc encodeFunc
= NULL
;
3845 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
3846 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3847 (void **)&encodeFunc
, hFunc
);
3851 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
3852 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
3854 static HCRYPTOIDFUNCSET set
= NULL
;
3855 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3858 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
3859 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3860 (void **)&encodeFunc
, hFunc
);
3864 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3865 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3868 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3869 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
3870 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
3872 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
3873 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
3876 if (!pbEncoded
&& !pcbEncoded
)
3878 SetLastError(ERROR_INVALID_PARAMETER
);
3882 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
3885 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
3886 debugstr_a(lpszStructType
));
3887 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
3888 lpszStructType
, &hFunc
);
3889 if (!pCryptEncodeObject
)
3890 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
3891 lpszStructType
, &hFunc
);
3893 if (pCryptEncodeObject
)
3894 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3895 pvStructInfo
, pbEncoded
, pcbEncoded
);
3896 else if (pCryptEncodeObjectEx
)
3897 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
3898 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
3900 CryptFreeOIDFunctionAddress(hFunc
, 0);
3901 TRACE_(crypt
)("returning %d\n", ret
);
3905 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3906 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
3907 void *pvEncoded
, DWORD
*pcbEncoded
)
3910 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3911 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3913 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
3914 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
3915 pvEncoded
, pcbEncoded
);
3917 if (!pvEncoded
&& !pcbEncoded
)
3919 SetLastError(ERROR_INVALID_PARAMETER
);
3923 SetLastError(NOERROR
);
3924 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
3925 *(BYTE
**)pvEncoded
= NULL
;
3926 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
3929 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
3930 debugstr_a(lpszStructType
));
3931 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
3935 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
3936 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
3939 CryptEncodeObjectFunc pCryptEncodeObject
=
3940 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
3942 if (pCryptEncodeObject
)
3944 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3946 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3947 pvStructInfo
, NULL
, pcbEncoded
);
3948 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3949 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
3950 ret
= pCryptEncodeObject(dwCertEncodingType
,
3951 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
3955 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3956 pvStructInfo
, pvEncoded
, pcbEncoded
);
3960 CryptFreeOIDFunctionAddress(hFunc
, 0);
3961 TRACE_(crypt
)("returning %d\n", ret
);
3965 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
3966 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3968 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3969 NULL
, 0, NULL
, pInfo
, pcbInfo
);
3972 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
3973 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3974 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3978 static CHAR oid
[] = szOID_RSA_RSA
;
3980 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
3981 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
3982 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
3984 if (!pszPublicKeyObjId
)
3985 pszPublicKeyObjId
= oid
;
3986 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
3990 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
3993 LPBYTE pubKey
= CryptMemAlloc(keySize
);
3997 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
4001 DWORD encodedLen
= 0;
4003 ret
= CryptEncodeObject(dwCertEncodingType
,
4004 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4007 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4008 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4011 *pcbInfo
= sizeNeeded
;
4012 else if (*pcbInfo
< sizeNeeded
)
4014 SetLastError(ERROR_MORE_DATA
);
4015 *pcbInfo
= sizeNeeded
;
4020 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4021 sizeof(CERT_PUBLIC_KEY_INFO
);
4022 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4024 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4025 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4026 pInfo
->PublicKey
.pbData
=
4027 (BYTE
*)pInfo
->Algorithm
.pszObjId
4028 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4029 pInfo
->PublicKey
.cbData
= encodedLen
;
4030 pInfo
->PublicKey
.cUnusedBits
= 0;
4031 ret
= CryptEncodeObject(dwCertEncodingType
,
4032 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4033 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4037 CryptMemFree(pubKey
);
4042 CryptDestroyKey(key
);
4047 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4048 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4049 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4051 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4052 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4053 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4055 static HCRYPTOIDFUNCSET set
= NULL
;
4057 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4058 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4060 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4061 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4062 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4066 SetLastError(ERROR_INVALID_PARAMETER
);
4070 if (pszPublicKeyObjId
)
4073 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4075 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4076 0, (void **)&exportFunc
, &hFunc
);
4079 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
4080 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4081 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4083 CryptFreeOIDFunctionAddress(hFunc
, 0);
4087 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4088 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4090 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4094 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4095 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4096 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4099 DWORD pubKeySize
= 0;
4101 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4102 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4104 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4105 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4108 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
4112 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4113 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
4118 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
4119 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
4122 CryptMemFree(pubKey
);
4130 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
4131 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4132 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
4134 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4135 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4136 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4138 static HCRYPTOIDFUNCSET set
= NULL
;
4140 ImportPublicKeyInfoExFunc importFunc
= NULL
;
4141 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4143 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4144 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4147 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
4148 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
4149 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
4151 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
4152 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
4155 CryptFreeOIDFunctionAddress(hFunc
, 0);