2 * Copyright 2005 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 is
21 * undocumented, 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
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "wine/unicode.h"
48 #include "crypt32_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
51 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
53 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
56 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
57 * The dwCertEncodingType and lpszStructType are ignored by the built-in
58 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
59 * since it must call functions in external DLLs that follow these signatures.
61 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
62 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
63 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
64 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
65 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
66 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
67 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
68 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
69 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
70 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
71 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
72 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
73 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
74 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
75 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
76 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
77 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
78 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
79 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
80 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
81 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
82 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
83 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
84 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
85 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
86 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
87 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
88 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
89 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
90 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
91 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
92 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
93 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
95 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
96 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
100 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
102 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
103 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
105 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
106 if (!*(BYTE
**)pbEncoded
)
109 *pcbEncoded
= bytesNeeded
;
111 else if (bytesNeeded
> *pcbEncoded
)
113 *pcbEncoded
= bytesNeeded
;
114 SetLastError(ERROR_MORE_DATA
);
118 *pcbEncoded
= bytesNeeded
;
122 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
124 DWORD bytesNeeded
, significantBytes
= 0;
132 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
133 temp
<<= 8, significantBytes
--)
135 bytesNeeded
= significantBytes
+ 1;
139 *pcbEncoded
= bytesNeeded
;
142 if (*pcbEncoded
< bytesNeeded
)
144 SetLastError(ERROR_MORE_DATA
);
148 *pbEncoded
= (BYTE
)len
;
153 *pbEncoded
++ = significantBytes
| 0x80;
154 for (i
= 0; i
< significantBytes
; i
++)
156 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
160 *pcbEncoded
= bytesNeeded
;
164 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
165 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
166 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
169 DWORD i
, dataLen
= 0;
171 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
172 pbEncoded
, *pcbEncoded
);
173 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
175 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
176 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
177 NULL
, &items
[i
].size
);
178 /* Some functions propagate their errors through the size */
180 *pcbEncoded
= items
[i
].size
;
181 dataLen
+= items
[i
].size
;
185 DWORD lenBytes
, bytesNeeded
;
187 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
188 bytesNeeded
= 1 + lenBytes
+ dataLen
;
190 *pcbEncoded
= bytesNeeded
;
193 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
194 pcbEncoded
, bytesNeeded
)))
196 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
197 pbEncoded
= *(BYTE
**)pbEncoded
;
198 *pbEncoded
++ = ASN_SEQUENCE
;
199 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
200 pbEncoded
+= lenBytes
;
201 for (i
= 0; ret
&& i
< cItem
; i
++)
203 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
204 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
205 NULL
, pbEncoded
, &items
[i
].size
);
206 /* Some functions propagate their errors through the size */
208 *pcbEncoded
= items
[i
].size
;
209 pbEncoded
+= items
[i
].size
;
214 TRACE("returning %d (%08x)\n", ret
, GetLastError());
218 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
219 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
220 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
223 const struct AsnConstructedItem
*item
=
224 (const struct AsnConstructedItem
*)pvStructInfo
;
227 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
228 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
230 DWORD dataLen
, bytesNeeded
;
232 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
233 bytesNeeded
= 1 + dataLen
+ len
;
235 *pcbEncoded
= bytesNeeded
;
236 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
237 pbEncoded
, pcbEncoded
, bytesNeeded
)))
239 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
240 pbEncoded
= *(BYTE
**)pbEncoded
;
241 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
242 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
243 pbEncoded
+= dataLen
;
244 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
245 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
249 /* Some functions propagate their errors through the size */
256 /* Some functions propagate their errors through the size */
262 struct AsnEncodeTagSwappedItem
265 const void *pvStructInfo
;
266 CryptEncodeObjectExFunc encodeFunc
;
269 /* Sort of a wacky hack, it encodes something using the struct
270 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
271 * given in the struct AsnEncodeTagSwappedItem.
273 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
274 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
275 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
278 const struct AsnEncodeTagSwappedItem
*item
=
279 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
281 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
282 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
283 if (ret
&& pbEncoded
)
284 *pbEncoded
= item
->tag
;
288 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
289 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
290 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
292 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
295 /* CERT_V1 is not encoded */
303 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
305 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
306 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
311 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
312 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
313 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
315 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
320 *pcbEncoded
= blob
->cbData
;
325 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
326 pcbEncoded
, blob
->cbData
)))
328 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
329 pbEncoded
= *(BYTE
**)pbEncoded
;
331 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
332 *pcbEncoded
= blob
->cbData
;
339 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
340 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
341 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
344 /* This has two filetimes in a row, a NotBefore and a NotAfter */
345 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
346 struct AsnEncodeSequenceItem items
[] = {
347 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
348 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
351 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
352 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
357 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
360 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
361 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
362 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
365 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
366 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
367 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
368 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
371 struct AsnEncodeSequenceItem items
[2] = {
372 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
373 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
376 if (algo
->Parameters
.cbData
)
377 items
[1].pvStructInfo
= &algo
->Parameters
;
379 items
[1].pvStructInfo
= &nullBlob
;
380 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
381 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
386 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
387 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
388 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
390 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
391 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
393 struct AsnEncodeSequenceItem items
[] = {
394 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
395 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
398 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
399 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
404 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
405 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
406 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
412 const CERT_PUBLIC_KEY_INFO
*info
=
413 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
414 struct AsnEncodeSequenceItem items
[] = {
415 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
416 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
419 TRACE("Encoding public key with OID %s\n",
420 debugstr_a(info
->Algorithm
.pszObjId
));
421 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
422 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
427 SetLastError(STATUS_ACCESS_VIOLATION
);
434 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
435 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
436 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
442 const CERT_SIGNED_CONTENT_INFO
*info
=
443 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
444 struct AsnEncodeSequenceItem items
[] = {
445 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
446 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
447 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
450 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
451 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
452 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
453 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
458 SetLastError(STATUS_ACCESS_VIOLATION
);
465 /* Like in Windows, this blithely ignores the validity of the passed-in
466 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
467 * decode properly, see CRYPT_AsnDecodeCertInfo.
469 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
470 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
471 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
477 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
478 struct AsnEncodeSequenceItem items
[10] = {
479 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
480 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
481 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
482 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
483 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
484 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
485 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
488 struct AsnConstructedItem constructed
[3] = { { 0 } };
489 DWORD cItem
= 7, cConstructed
= 0;
491 if (info
->IssuerUniqueId
.cbData
)
493 constructed
[cConstructed
].tag
= 1;
494 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
495 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
496 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
497 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
501 if (info
->SubjectUniqueId
.cbData
)
503 constructed
[cConstructed
].tag
= 2;
504 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
505 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
506 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
507 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
511 if (info
->cExtension
)
513 constructed
[cConstructed
].tag
= 3;
514 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
515 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
516 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
517 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
522 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
523 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
527 SetLastError(STATUS_ACCESS_VIOLATION
);
534 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
535 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
537 struct AsnEncodeSequenceItem items
[3] = {
538 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
539 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
545 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
547 if (entry
->cExtension
)
549 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
550 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
554 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
555 pbEncoded
, pcbEncoded
);
557 TRACE("returning %d (%08x)\n", ret
, GetLastError());
561 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
562 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
563 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
565 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
566 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
567 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
568 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
571 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
575 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
579 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
580 bytesNeeded
= 1 + lenBytes
+ dataLen
;
582 *pcbEncoded
= bytesNeeded
;
585 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
586 pcbEncoded
, bytesNeeded
)))
588 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
589 pbEncoded
= *(BYTE
**)pbEncoded
;
590 *pbEncoded
++ = ASN_SEQUENCEOF
;
591 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
592 pbEncoded
+= lenBytes
;
593 for (i
= 0; i
< cCRLEntry
; i
++)
595 DWORD size
= dataLen
;
597 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
606 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
607 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
608 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
610 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
613 /* CRL_V1 is not encoded */
620 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
621 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
625 /* Like in Windows, this blithely ignores the validity of the passed-in
626 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
627 * decode properly, see CRYPT_AsnDecodeCRLInfo.
629 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
630 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
631 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
637 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
638 struct AsnEncodeSequenceItem items
[7] = {
639 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
640 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
641 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
642 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
645 struct AsnConstructedItem constructed
[1] = { { 0 } };
646 DWORD cItem
= 4, cConstructed
= 0;
648 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
650 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
651 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
656 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
657 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
660 if (info
->cExtension
)
662 constructed
[cConstructed
].tag
= 0;
663 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
664 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
665 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
666 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
671 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
672 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
676 SetLastError(STATUS_ACCESS_VIOLATION
);
683 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
687 struct AsnEncodeSequenceItem items
[3] = {
688 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
694 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
698 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
699 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
702 items
[cItem
].pvStructInfo
= &ext
->Value
;
703 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
706 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
707 pbEncoded
, pcbEncoded
);
708 TRACE("returning %d (%08x)\n", ret
, GetLastError());
712 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
713 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
714 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
720 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
721 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
724 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
728 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
732 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
733 bytesNeeded
= 1 + lenBytes
+ dataLen
;
735 *pcbEncoded
= bytesNeeded
;
738 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
739 pcbEncoded
, bytesNeeded
)))
741 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
742 pbEncoded
= *(BYTE
**)pbEncoded
;
743 *pbEncoded
++ = ASN_SEQUENCEOF
;
744 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
745 pbEncoded
+= lenBytes
;
746 for (i
= 0; i
< exts
->cExtension
; i
++)
748 DWORD size
= dataLen
;
750 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
760 SetLastError(STATUS_ACCESS_VIOLATION
);
767 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
768 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
769 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
771 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
772 DWORD bytesNeeded
= 0, lenBytes
;
777 TRACE("%s\n", debugstr_a(pszObjId
));
784 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
786 SetLastError(CRYPT_E_ASN1_ERROR
);
790 firstByte
= val1
* 40 + val2
;
791 ptr
= pszObjId
+ firstPos
;
796 /* note I assume each component is at most 32-bits long in base 2 */
797 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
799 if (val1
>= 0x10000000)
801 else if (val1
>= 0x200000)
803 else if (val1
>= 0x4000)
805 else if (val1
>= 0x80)
815 SetLastError(CRYPT_E_ASN1_ERROR
);
819 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
823 bytesNeeded
+= 1 + lenBytes
;
826 if (*pcbEncoded
< bytesNeeded
)
828 SetLastError(ERROR_MORE_DATA
);
833 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
834 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
835 pbEncoded
+= lenBytes
;
841 *pbEncoded
++ = firstByte
;
842 ptr
= pszObjId
+ firstPos
;
845 sscanf(ptr
, "%d%n", &val
, &pos
);
847 unsigned char outBytes
[5];
850 if (val
>= 0x10000000)
852 else if (val
>= 0x200000)
854 else if (val
>= 0x4000)
856 else if (val
>= 0x80)
860 for (i
= numBytes
; i
> 0; i
--)
862 outBytes
[i
- 1] = val
& 0x7f;
865 for (i
= 0; i
< numBytes
- 1; i
++)
866 *pbEncoded
++ = outBytes
[i
] | 0x80;
867 *pbEncoded
++ = outBytes
[i
];
876 *pcbEncoded
= bytesNeeded
;
880 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
881 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
885 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
886 DWORD bytesNeeded
, lenBytes
, encodedLen
;
888 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: lstrlenA(str
);
889 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
890 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
892 *pcbEncoded
= bytesNeeded
;
895 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
896 pbEncoded
, pcbEncoded
, bytesNeeded
)))
898 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
899 pbEncoded
= *(BYTE
**)pbEncoded
;
901 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
902 pbEncoded
+= lenBytes
;
903 memcpy(pbEncoded
, str
, encodedLen
);
909 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
910 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
914 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
915 DWORD bytesNeeded
, lenBytes
, strLen
;
917 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
919 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
920 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
922 *pcbEncoded
= bytesNeeded
;
925 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
926 pbEncoded
, pcbEncoded
, bytesNeeded
)))
930 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
931 pbEncoded
= *(BYTE
**)pbEncoded
;
932 *pbEncoded
++ = ASN_BMPSTRING
;
933 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
934 pbEncoded
+= lenBytes
;
935 for (i
= 0; i
< strLen
; i
++)
937 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
938 *pbEncoded
++ = str
[i
] & 0x00ff;
945 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
946 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
950 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
951 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
953 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
955 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
957 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
958 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
960 *pcbEncoded
= bytesNeeded
;
963 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
964 pbEncoded
, pcbEncoded
, bytesNeeded
)))
966 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
967 pbEncoded
= *(BYTE
**)pbEncoded
;
968 *pbEncoded
++ = ASN_UTF8STRING
;
969 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
970 pbEncoded
+= lenBytes
;
971 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
972 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
978 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
979 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
980 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
986 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
988 switch (value
->dwValueType
)
990 case CERT_RDN_ANY_TYPE
:
991 /* explicitly disallowed */
992 SetLastError(E_INVALIDARG
);
995 case CERT_RDN_ENCODED_BLOB
:
996 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
997 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
999 case CERT_RDN_OCTET_STRING
:
1000 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1001 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1003 case CERT_RDN_NUMERIC_STRING
:
1004 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1005 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1007 case CERT_RDN_PRINTABLE_STRING
:
1008 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1009 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1011 case CERT_RDN_TELETEX_STRING
:
1012 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1013 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1015 case CERT_RDN_VIDEOTEX_STRING
:
1016 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1017 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1019 case CERT_RDN_IA5_STRING
:
1020 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1021 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1023 case CERT_RDN_GRAPHIC_STRING
:
1024 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1025 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1027 case CERT_RDN_VISIBLE_STRING
:
1028 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1029 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1031 case CERT_RDN_GENERAL_STRING
:
1032 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1033 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1035 case CERT_RDN_UNIVERSAL_STRING
:
1036 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1037 SetLastError(CRYPT_E_ASN1_CHOICE
);
1040 case CERT_RDN_BMP_STRING
:
1041 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1042 pbEncoded
, pcbEncoded
);
1044 case CERT_RDN_UTF8_STRING
:
1045 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1046 pbEncoded
, pcbEncoded
);
1049 SetLastError(CRYPT_E_ASN1_CHOICE
);
1055 SetLastError(STATUS_ACCESS_VIOLATION
);
1062 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1063 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1064 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1066 DWORD bytesNeeded
= 0, lenBytes
, size
;
1069 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1070 0, NULL
, NULL
, &size
);
1073 bytesNeeded
+= size
;
1074 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1075 * with dwValueType, so "cast" it to get its encoded size
1077 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1078 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1081 bytesNeeded
+= size
;
1082 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1083 bytesNeeded
+= 1 + lenBytes
;
1086 if (*pcbEncoded
< bytesNeeded
)
1088 SetLastError(ERROR_MORE_DATA
);
1093 *pbEncoded
++ = ASN_SEQUENCE
;
1094 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1096 pbEncoded
+= lenBytes
;
1097 size
= bytesNeeded
- 1 - lenBytes
;
1098 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1099 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1103 size
= bytesNeeded
- 1 - lenBytes
- size
;
1104 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1105 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1106 0, NULL
, pbEncoded
, &size
);
1113 *pcbEncoded
= bytesNeeded
;
1117 /* Have to propagate index of failing character */
1124 static int BLOBComp(const void *l
, const void *r
)
1126 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1129 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1130 ret
= a
->cbData
- b
->cbData
;
1134 typedef struct _CRYPT_SET_OF
{
1136 PCRYPT_DER_BLOB rgValue
;
1139 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1141 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1142 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1143 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1145 const CRYPT_SET_OF
*set
= (const CRYPT_SET_OF
*)pvStructInfo
;
1146 DWORD bytesNeeded
= 0, lenBytes
, i
;
1149 for (i
= 0; i
< set
->cValue
; i
++)
1150 bytesNeeded
+= set
->rgValue
[i
].cbData
;
1151 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1152 bytesNeeded
+= 1 + lenBytes
;
1155 *pcbEncoded
= bytesNeeded
;
1158 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1159 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1161 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1162 pbEncoded
= *(BYTE
**)pbEncoded
;
1163 qsort(set
->rgValue
, set
->cValue
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1164 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1165 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1166 pbEncoded
+= lenBytes
;
1167 for (i
= 0; ret
&& i
< set
->cValue
; i
++)
1169 memcpy(pbEncoded
, set
->rgValue
[i
].pbData
, set
->rgValue
[i
].cbData
);
1170 pbEncoded
+= set
->rgValue
[i
].cbData
;
1176 struct DERSetDescriptor
1182 CryptEncodeObjectExFunc encode
;
1185 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1186 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1187 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1189 const struct DERSetDescriptor
*desc
=
1190 (const struct DERSetDescriptor
*)pvStructInfo
;
1191 CRYPT_SET_OF setOf
= { 0, NULL
};
1197 setOf
.rgValue
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1202 setOf
.cValue
= desc
->cItems
;
1203 memset(setOf
.rgValue
, 0, setOf
.cValue
* sizeof(CRYPT_DER_BLOB
));
1206 for (i
= 0; ret
&& i
< setOf
.cValue
; i
++)
1208 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1209 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1210 0, NULL
, NULL
, &setOf
.rgValue
[i
].cbData
);
1213 setOf
.rgValue
[i
].pbData
= CryptMemAlloc(setOf
.rgValue
[i
].cbData
);
1214 if (!setOf
.rgValue
[i
].pbData
)
1217 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1218 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1219 desc
->itemOffset
, 0, NULL
, setOf
.rgValue
[i
].pbData
,
1220 &setOf
.rgValue
[i
].cbData
);
1222 /* Some functions propagate their errors through the size */
1224 *pcbEncoded
= setOf
.rgValue
[i
].cbData
;
1228 DWORD bytesNeeded
= 0, lenBytes
;
1231 for (i
= 0; i
< setOf
.cValue
; i
++)
1232 bytesNeeded
+= setOf
.rgValue
[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
.rgValue
, setOf
.cValue
, 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
.cValue
; i
++)
1249 memcpy(pbEncoded
, setOf
.rgValue
[i
].pbData
,
1250 setOf
.rgValue
[i
].cbData
);
1251 pbEncoded
+= setOf
.rgValue
[i
].cbData
;
1255 for (i
= 0; i
< setOf
.cValue
; i
++)
1256 CryptMemFree(setOf
.rgValue
[i
].pbData
);
1257 CryptMemFree(setOf
.rgValue
);
1261 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1262 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1266 CRYPT_SET_OF setOf
= { 0, NULL
};
1275 setOf
.cValue
= rdn
->cRDNAttr
;
1276 setOf
.rgValue
= CryptMemAlloc(rdn
->cRDNAttr
*
1277 sizeof(CRYPT_DER_BLOB
));
1281 memset(setOf
.rgValue
, 0, setOf
.cValue
* sizeof(CRYPT_DER_BLOB
));
1283 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1285 setOf
.rgValue
[i
].cbData
= 0;
1286 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1287 nameValueEncodeFunc
, NULL
, &setOf
.rgValue
[i
].cbData
);
1290 setOf
.rgValue
[i
].pbData
=
1291 CryptMemAlloc(setOf
.rgValue
[i
].cbData
);
1292 if (!setOf
.rgValue
[i
].pbData
)
1295 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1296 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1297 setOf
.rgValue
[i
].pbData
, &setOf
.rgValue
[i
].cbData
);
1301 /* Have to propagate index of failing character */
1302 *pcbEncoded
= setOf
.rgValue
[i
].cbData
;
1306 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1307 pbEncoded
, pcbEncoded
);
1308 for (i
= 0; i
< setOf
.cValue
; i
++)
1309 CryptMemFree(setOf
.rgValue
[i
].pbData
);
1313 SetLastError(STATUS_ACCESS_VIOLATION
);
1317 CryptMemFree(setOf
.rgValue
);
1321 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1322 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1323 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1325 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1326 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1327 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1330 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1333 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1334 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1335 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1337 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1338 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1342 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1343 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1344 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1350 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1351 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1353 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1355 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1357 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1358 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1360 bytesNeeded
+= size
;
1364 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1365 bytesNeeded
+= 1 + lenBytes
;
1369 *pcbEncoded
= bytesNeeded
;
1372 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1373 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1375 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1376 pbEncoded
= *(BYTE
**)pbEncoded
;
1377 *pbEncoded
++ = ASN_SEQUENCEOF
;
1378 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1380 pbEncoded
+= lenBytes
;
1381 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1384 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1385 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1390 bytesNeeded
-= size
;
1401 SetLastError(STATUS_ACCESS_VIOLATION
);
1408 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1409 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1410 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1416 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1418 if (!attr
->pszObjId
)
1419 SetLastError(E_INVALIDARG
);
1422 struct AsnEncodeSequenceItem items
[2] = {
1423 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1424 { &attr
->cValue
, CRYPT_DEREncodeSet
, 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_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1441 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1442 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1448 const CRYPT_ATTRIBUTES
*attributes
=
1449 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1450 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1451 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1453 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1454 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1458 SetLastError(STATUS_ACCESS_VIOLATION
);
1464 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1465 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1466 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1467 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1470 const CRYPT_CONTENT_INFO
*info
= (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1471 struct AsnEncodeSequenceItem items
[2] = {
1472 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1475 struct AsnConstructedItem constructed
= { 0 };
1478 if (info
->Content
.cbData
)
1480 constructed
.tag
= 0;
1481 constructed
.pvStructInfo
= &info
->Content
;
1482 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1483 items
[cItem
].pvStructInfo
= &constructed
;
1484 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1487 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1488 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1491 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1492 void *pvData
, DWORD
*pcbData
)
1494 struct AsnEncodeSequenceItem items
[] = {
1495 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1496 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1498 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1499 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1502 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1503 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1506 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1507 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1508 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1514 const CRYPT_CONTENT_INFO
*info
=
1515 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1517 if (!info
->pszObjId
)
1518 SetLastError(E_INVALIDARG
);
1520 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1521 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1526 SetLastError(STATUS_ACCESS_VIOLATION
);
1532 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1533 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1537 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1538 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1540 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1542 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1543 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1545 *pcbEncoded
= bytesNeeded
;
1548 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1549 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1553 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1554 pbEncoded
= *(BYTE
**)pbEncoded
;
1556 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1557 pbEncoded
+= lenBytes
;
1558 for (i
= 0; i
< encodedLen
; i
++)
1559 *pbEncoded
++ = (BYTE
)str
[i
];
1565 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1566 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1570 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1571 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1573 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1575 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1576 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1578 *pcbEncoded
= bytesNeeded
;
1581 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1582 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1586 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1587 pbEncoded
= *(BYTE
**)pbEncoded
;
1588 *pbEncoded
++ = ASN_NUMERICSTRING
;
1589 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1590 pbEncoded
+= lenBytes
;
1591 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1593 if (isdigitW(str
[i
]))
1594 *pbEncoded
++ = (BYTE
)str
[i
];
1598 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1607 static inline int isprintableW(WCHAR wc
)
1609 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1610 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1611 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1614 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1615 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1619 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1620 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1622 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1624 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1625 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1627 *pcbEncoded
= bytesNeeded
;
1630 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1631 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1635 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1636 pbEncoded
= *(BYTE
**)pbEncoded
;
1637 *pbEncoded
++ = ASN_PRINTABLESTRING
;
1638 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1639 pbEncoded
+= lenBytes
;
1640 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1642 if (isprintableW(str
[i
]))
1643 *pbEncoded
++ = (BYTE
)str
[i
];
1647 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1656 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1657 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1661 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1662 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1664 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1666 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1667 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1669 *pcbEncoded
= bytesNeeded
;
1672 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1673 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1677 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1678 pbEncoded
= *(BYTE
**)pbEncoded
;
1679 *pbEncoded
++ = ASN_IA5STRING
;
1680 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1681 pbEncoded
+= lenBytes
;
1682 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1685 *pbEncoded
++ = (BYTE
)str
[i
];
1689 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1698 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
1699 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1703 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1704 DWORD bytesNeeded
, lenBytes
, strLen
;
1706 /* FIXME: doesn't handle composite characters */
1707 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1709 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
1710 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
1712 *pcbEncoded
= bytesNeeded
;
1715 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1716 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1720 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1721 pbEncoded
= *(BYTE
**)pbEncoded
;
1722 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
1723 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
1724 pbEncoded
+= lenBytes
;
1725 for (i
= 0; i
< strLen
; i
++)
1729 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
1730 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
1737 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1738 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1739 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1745 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1747 switch (value
->dwValueType
)
1749 case CERT_RDN_ANY_TYPE
:
1750 case CERT_RDN_ENCODED_BLOB
:
1751 case CERT_RDN_OCTET_STRING
:
1752 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
1754 case CERT_RDN_NUMERIC_STRING
:
1755 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
1756 pbEncoded
, pcbEncoded
);
1758 case CERT_RDN_PRINTABLE_STRING
:
1759 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
1760 pbEncoded
, pcbEncoded
);
1762 case CERT_RDN_TELETEX_STRING
:
1763 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
1764 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1766 case CERT_RDN_VIDEOTEX_STRING
:
1767 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
1768 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1770 case CERT_RDN_IA5_STRING
:
1771 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
1772 pbEncoded
, pcbEncoded
);
1774 case CERT_RDN_GRAPHIC_STRING
:
1775 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1776 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1778 case CERT_RDN_VISIBLE_STRING
:
1779 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
1780 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1782 case CERT_RDN_GENERAL_STRING
:
1783 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
1784 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1786 case CERT_RDN_UNIVERSAL_STRING
:
1787 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
1788 pbEncoded
, pcbEncoded
);
1790 case CERT_RDN_BMP_STRING
:
1791 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1792 pbEncoded
, pcbEncoded
);
1794 case CERT_RDN_UTF8_STRING
:
1795 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1796 pbEncoded
, pcbEncoded
);
1799 SetLastError(CRYPT_E_ASN1_CHOICE
);
1804 SetLastError(STATUS_ACCESS_VIOLATION
);
1810 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1811 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1812 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1818 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1819 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1821 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1823 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1825 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1826 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
1828 bytesNeeded
+= size
;
1830 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1831 bytesNeeded
+= 1 + lenBytes
;
1835 *pcbEncoded
= bytesNeeded
;
1838 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1839 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1841 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1842 pbEncoded
= *(BYTE
**)pbEncoded
;
1843 *pbEncoded
++ = ASN_SEQUENCEOF
;
1844 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1846 pbEncoded
+= lenBytes
;
1847 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1850 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1851 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
1856 bytesNeeded
-= size
;
1865 SetLastError(STATUS_ACCESS_VIOLATION
);
1872 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1873 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1874 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1876 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1885 else if (*pcbEncoded
< 3)
1888 SetLastError(ERROR_MORE_DATA
);
1894 *pbEncoded
++ = ASN_BOOL
;
1896 *pbEncoded
++ = val
? 0xff : 0;
1899 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1903 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1904 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1911 switch (entry
->dwAltNameChoice
)
1913 case CERT_ALT_NAME_RFC822_NAME
:
1914 case CERT_ALT_NAME_DNS_NAME
:
1915 case CERT_ALT_NAME_URL
:
1916 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1917 if (entry
->u
.pwszURL
)
1921 /* Not + 1: don't encode the NULL-terminator */
1922 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1923 for (i
= 0; ret
&& i
< dataLen
; i
++)
1925 if (entry
->u
.pwszURL
[i
] > 0x7f)
1927 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1936 case CERT_ALT_NAME_DIRECTORY_NAME
:
1937 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
1938 dataLen
= entry
->u
.DirectoryName
.cbData
;
1940 case CERT_ALT_NAME_IP_ADDRESS
:
1941 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1942 dataLen
= entry
->u
.IPAddress
.cbData
;
1944 case CERT_ALT_NAME_REGISTERED_ID
:
1946 struct AsnEncodeTagSwappedItem swapped
=
1947 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
1948 CRYPT_AsnEncodeOid
};
1950 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
1953 case CERT_ALT_NAME_OTHER_NAME
:
1954 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
1957 SetLastError(E_INVALIDARG
);
1962 DWORD bytesNeeded
, lenBytes
;
1964 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1965 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1967 *pcbEncoded
= bytesNeeded
;
1968 else if (*pcbEncoded
< bytesNeeded
)
1970 SetLastError(ERROR_MORE_DATA
);
1971 *pcbEncoded
= bytesNeeded
;
1977 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1978 pbEncoded
+= lenBytes
;
1979 switch (entry
->dwAltNameChoice
)
1981 case CERT_ALT_NAME_RFC822_NAME
:
1982 case CERT_ALT_NAME_DNS_NAME
:
1983 case CERT_ALT_NAME_URL
:
1987 for (i
= 0; i
< dataLen
; i
++)
1988 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1991 case CERT_ALT_NAME_DIRECTORY_NAME
:
1992 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
1994 case CERT_ALT_NAME_IP_ADDRESS
:
1995 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1999 *pcbEncoded
= bytesNeeded
;
2002 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2006 static BOOL WINAPI
CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2007 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2008 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2014 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2015 CRYPT_DATA_BLOB newBlob
= { blob
->cbData
, NULL
};
2020 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2025 for (i
= 0; i
< newBlob
.cbData
; i
++)
2026 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2032 ret
= CRYPT_AsnEncodeInteger(dwCertEncodingType
, lpszStructType
,
2033 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2034 CryptMemFree(newBlob
.pbData
);
2038 SetLastError(STATUS_ACCESS_VIOLATION
);
2045 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2046 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2047 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2053 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
2054 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
2055 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2056 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2057 struct AsnConstructedItem constructed
= { 0 };
2058 DWORD cItem
= 0, cSwapped
= 0;
2060 if (info
->KeyId
.cbData
)
2062 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2063 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2064 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2065 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2066 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2070 if (info
->CertIssuer
.cbData
)
2072 constructed
.tag
= 1;
2073 constructed
.pvStructInfo
= &info
->CertIssuer
;
2074 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2075 items
[cItem
].pvStructInfo
= &constructed
;
2076 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2079 if (info
->CertSerialNumber
.cbData
)
2081 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2082 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2083 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2084 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2085 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2089 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2090 pEncodePara
, pbEncoded
, pcbEncoded
);
2094 SetLastError(STATUS_ACCESS_VIOLATION
);
2101 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2102 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2103 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2109 const CERT_ALT_NAME_INFO
*info
=
2110 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2111 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2114 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2115 * can't encode an erroneous entry index if it's bigger than this.
2117 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2121 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
2125 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2127 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2128 * the bad character, now set the index of the bad
2131 *pcbEncoded
= (BYTE
)i
<<
2132 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2137 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2138 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2141 *pcbEncoded
= bytesNeeded
;
2146 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2147 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2149 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2150 pbEncoded
= *(BYTE
**)pbEncoded
;
2151 *pbEncoded
++ = ASN_SEQUENCEOF
;
2152 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2153 pbEncoded
+= lenBytes
;
2154 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2156 DWORD len
= dataLen
;
2158 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
2172 SetLastError(STATUS_ACCESS_VIOLATION
);
2179 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2180 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2181 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2187 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2188 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2189 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2190 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2191 DWORD cItem
= 0, cSwapped
= 0;
2193 if (info
->KeyId
.cbData
)
2195 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2196 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2197 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeIntegerSwapBytes
;
2198 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2199 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2203 if (info
->AuthorityCertIssuer
.cAltEntry
)
2205 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2206 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2207 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2208 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2209 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2213 if (info
->AuthorityCertSerialNumber
.cbData
)
2215 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2216 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2217 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2218 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2219 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2223 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2224 pEncodePara
, pbEncoded
, pcbEncoded
);
2228 SetLastError(STATUS_ACCESS_VIOLATION
);
2235 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2236 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2237 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2243 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2244 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2245 struct AsnEncodeSequenceItem items
[3] = {
2246 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2251 if (info
->fPathLenConstraint
)
2253 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2254 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2257 if (info
->cSubtreesConstraint
)
2259 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2260 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2263 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2264 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2268 SetLastError(STATUS_ACCESS_VIOLATION
);
2275 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2276 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2277 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2283 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2284 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2285 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2290 items
[cItem
].pvStructInfo
= &info
->fCA
;
2291 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2294 if (info
->fPathLenConstraint
)
2296 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2297 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2300 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2301 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2305 SetLastError(STATUS_ACCESS_VIOLATION
);
2312 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2313 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2314 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2320 const BLOBHEADER
*hdr
=
2321 (const BLOBHEADER
*)pvStructInfo
;
2323 if (hdr
->bType
!= PUBLICKEYBLOB
)
2325 SetLastError(E_INVALIDARG
);
2330 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2331 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2332 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2333 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2334 struct AsnEncodeSequenceItem items
[] = {
2335 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2336 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2339 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2340 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2346 SetLastError(STATUS_ACCESS_VIOLATION
);
2353 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2354 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2355 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2361 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2362 DWORD bytesNeeded
, lenBytes
;
2364 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2365 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2367 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2368 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2371 *pcbEncoded
= bytesNeeded
;
2376 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2377 pcbEncoded
, bytesNeeded
)))
2379 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2380 pbEncoded
= *(BYTE
**)pbEncoded
;
2381 *pbEncoded
++ = ASN_OCTETSTRING
;
2382 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2383 pbEncoded
+= lenBytes
;
2385 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2391 SetLastError(STATUS_ACCESS_VIOLATION
);
2395 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2399 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2400 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2401 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2407 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2408 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2411 /* yep, MS allows cUnusedBits to be >= 8 */
2412 if (!blob
->cUnusedBits
)
2414 dataBytes
= blob
->cbData
;
2417 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2419 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2420 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2428 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2429 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2432 *pcbEncoded
= bytesNeeded
;
2437 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2438 pcbEncoded
, bytesNeeded
)))
2440 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2441 pbEncoded
= *(BYTE
**)pbEncoded
;
2442 *pbEncoded
++ = ASN_BITSTRING
;
2443 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2444 pbEncoded
+= lenBytes
;
2445 *pbEncoded
++ = unusedBits
;
2448 BYTE mask
= 0xff << unusedBits
;
2452 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2453 pbEncoded
+= dataBytes
- 1;
2455 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2462 SetLastError(STATUS_ACCESS_VIOLATION
);
2469 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2470 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2471 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2477 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2478 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2483 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2488 for (i
= 0; i
< newBlob
.cbData
; i
++)
2489 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2495 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2496 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2497 CryptMemFree(newBlob
.pbData
);
2501 SetLastError(STATUS_ACCESS_VIOLATION
);
2508 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2509 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2510 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2512 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2514 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2515 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2518 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2519 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2520 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2526 DWORD significantBytes
, lenBytes
;
2527 BYTE padByte
= 0, bytesNeeded
;
2529 const CRYPT_INTEGER_BLOB
*blob
=
2530 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2532 significantBytes
= blob
->cbData
;
2533 if (significantBytes
)
2535 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2537 /* negative, lop off leading (little-endian) 0xffs */
2538 for (; significantBytes
> 0 &&
2539 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2541 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2549 /* positive, lop off leading (little-endian) zeroes */
2550 for (; significantBytes
> 0 &&
2551 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2553 if (significantBytes
== 0)
2554 significantBytes
= 1;
2555 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2563 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2565 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2566 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2571 *pcbEncoded
= bytesNeeded
;
2576 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2577 pcbEncoded
, bytesNeeded
)))
2579 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2580 pbEncoded
= *(BYTE
**)pbEncoded
;
2581 *pbEncoded
++ = ASN_INTEGER
;
2584 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2585 pbEncoded
+= lenBytes
;
2586 *pbEncoded
++ = padByte
;
2590 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2591 pbEncoded
+= lenBytes
;
2593 for (; significantBytes
> 0; significantBytes
--)
2594 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2600 SetLastError(STATUS_ACCESS_VIOLATION
);
2607 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
2608 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2609 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2615 DWORD significantBytes
, lenBytes
;
2618 const CRYPT_INTEGER_BLOB
*blob
=
2619 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2621 significantBytes
= blob
->cbData
;
2622 if (significantBytes
)
2624 /* positive, lop off leading (little-endian) zeroes */
2625 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2628 if (significantBytes
== 0)
2629 significantBytes
= 1;
2630 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2634 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2636 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2637 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2642 *pcbEncoded
= bytesNeeded
;
2647 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2648 pcbEncoded
, bytesNeeded
)))
2650 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2651 pbEncoded
= *(BYTE
**)pbEncoded
;
2652 *pbEncoded
++ = ASN_INTEGER
;
2655 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2656 pbEncoded
+= lenBytes
;
2661 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2662 pbEncoded
+= lenBytes
;
2664 for (; significantBytes
> 0; significantBytes
--)
2665 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2671 SetLastError(STATUS_ACCESS_VIOLATION
);
2678 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2679 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2680 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2682 CRYPT_INTEGER_BLOB blob
;
2685 /* Encode as an unsigned integer, then change the tag to enumerated */
2686 blob
.cbData
= sizeof(DWORD
);
2687 blob
.pbData
= (BYTE
*)pvStructInfo
;
2688 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2689 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2690 if (ret
&& pbEncoded
)
2692 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2693 pbEncoded
= *(BYTE
**)pbEncoded
;
2694 pbEncoded
[0] = ASN_ENUMERATED
;
2699 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2700 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2701 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2708 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2709 * temporary buffer because the output buffer is not NULL-terminated.
2712 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2716 *pcbEncoded
= bytesNeeded
;
2721 /* Sanity check the year, this is a two-digit year format */
2722 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2724 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2726 SetLastError(CRYPT_E_BAD_ENCODE
);
2731 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2732 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2734 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2735 pbEncoded
= *(BYTE
**)pbEncoded
;
2736 buf
[0] = ASN_UTCTIME
;
2737 buf
[1] = bytesNeeded
- 2;
2738 snprintf(buf
+ 2, sizeof(buf
) - 2,
2739 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2740 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2741 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2742 sysTime
.wMinute
, sysTime
.wSecond
);
2743 memcpy(pbEncoded
, buf
, bytesNeeded
);
2750 SetLastError(STATUS_ACCESS_VIOLATION
);
2757 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2758 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2759 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2766 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2767 * temporary buffer because the output buffer is not NULL-terminated.
2770 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2774 *pcbEncoded
= bytesNeeded
;
2779 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2782 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2783 pcbEncoded
, bytesNeeded
);
2786 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2787 pbEncoded
= *(BYTE
**)pbEncoded
;
2788 buf
[0] = ASN_GENERALTIME
;
2789 buf
[1] = bytesNeeded
- 2;
2790 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2791 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2792 sysTime
.wMinute
, sysTime
.wSecond
);
2793 memcpy(pbEncoded
, buf
, bytesNeeded
);
2799 SetLastError(STATUS_ACCESS_VIOLATION
);
2806 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2807 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2808 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2816 /* Check the year, if it's in the UTCTime range call that encode func */
2817 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2819 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2820 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2821 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2823 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2824 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2829 SetLastError(STATUS_ACCESS_VIOLATION
);
2836 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2837 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2838 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2844 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2845 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2846 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2848 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2849 dataLen
+= seq
->rgValue
[i
].cbData
;
2850 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2851 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2854 *pcbEncoded
= bytesNeeded
;
2859 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2860 pcbEncoded
, bytesNeeded
)))
2862 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2863 pbEncoded
= *(BYTE
**)pbEncoded
;
2864 *pbEncoded
++ = ASN_SEQUENCEOF
;
2865 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2866 pbEncoded
+= lenBytes
;
2867 for (i
= 0; i
< seq
->cValue
; i
++)
2869 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2870 seq
->rgValue
[i
].cbData
);
2871 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2878 SetLastError(STATUS_ACCESS_VIOLATION
);
2885 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2886 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2889 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2890 struct AsnConstructedItem constructed
= { 0 };
2891 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2892 DWORD cItem
= 0, cSwapped
= 0;
2894 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2896 case CRL_DIST_POINT_NO_NAME
:
2899 case CRL_DIST_POINT_FULL_NAME
:
2900 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2901 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2902 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2903 constructed
.tag
= 0;
2904 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2905 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2906 items
[cItem
].pvStructInfo
= &constructed
;
2907 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2911 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2912 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2918 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2920 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2921 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2922 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2923 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2924 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2928 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2930 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2931 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2932 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2933 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2934 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2939 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2940 pbEncoded
, pcbEncoded
);
2944 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2945 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2946 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2952 const CRL_DIST_POINTS_INFO
*info
=
2953 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2955 if (!info
->cDistPoint
)
2957 SetLastError(E_INVALIDARG
);
2962 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2965 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2969 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2973 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2975 /* Have to propagate index of failing character */
2981 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2982 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2985 *pcbEncoded
= bytesNeeded
;
2990 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2991 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2993 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2994 pbEncoded
= *(BYTE
**)pbEncoded
;
2995 *pbEncoded
++ = ASN_SEQUENCEOF
;
2996 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2997 pbEncoded
+= lenBytes
;
2998 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3000 DWORD len
= dataLen
;
3002 ret
= CRYPT_AsnEncodeDistPoint(
3003 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3017 SetLastError(STATUS_ACCESS_VIOLATION
);
3024 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3025 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3026 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3032 const CERT_ENHKEY_USAGE
*usage
=
3033 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
3034 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3037 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3039 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3040 usage
->rgpszUsageIdentifier
[i
],
3041 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3043 bytesNeeded
+= size
;
3045 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3046 bytesNeeded
+= 1 + lenBytes
;
3050 *pcbEncoded
= bytesNeeded
;
3053 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3054 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3056 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3057 pbEncoded
= *(BYTE
**)pbEncoded
;
3058 *pbEncoded
++ = ASN_SEQUENCEOF
;
3059 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3061 pbEncoded
+= lenBytes
;
3062 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3065 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3066 usage
->rgpszUsageIdentifier
[i
],
3067 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3072 bytesNeeded
-= size
;
3081 SetLastError(STATUS_ACCESS_VIOLATION
);
3088 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3089 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3090 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3096 const CRL_ISSUING_DIST_POINT
*point
=
3097 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3098 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3099 struct AsnConstructedItem constructed
= { 0 };
3100 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3101 DWORD cItem
= 0, cSwapped
= 0;
3104 switch (point
->DistPointName
.dwDistPointNameChoice
)
3106 case CRL_DIST_POINT_NO_NAME
:
3109 case CRL_DIST_POINT_FULL_NAME
:
3110 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3111 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3112 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3113 constructed
.tag
= 0;
3114 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3115 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3116 items
[cItem
].pvStructInfo
= &constructed
;
3117 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3122 SetLastError(E_INVALIDARG
);
3125 if (ret
&& point
->fOnlyContainsUserCerts
)
3127 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3128 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3129 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3130 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3131 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3135 if (ret
&& point
->fOnlyContainsCACerts
)
3137 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3138 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3139 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3140 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3141 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3145 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3147 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3148 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3149 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3150 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3151 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3155 if (ret
&& point
->fIndirectCRL
)
3157 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3158 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3159 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3160 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3161 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3166 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3167 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3171 SetLastError(STATUS_ACCESS_VIOLATION
);
3178 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3179 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3180 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3184 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3185 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3186 struct AsnEncodeSequenceItem items
[] = {
3187 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3188 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3191 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3192 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3197 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3198 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3199 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3203 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3205 SetLastError(E_INVALIDARG
);
3211 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
3213 if (!info
->Issuer
.cbData
)
3214 SetLastError(E_INVALIDARG
);
3217 struct AsnEncodeSequenceItem items
[7] = {
3218 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3219 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3220 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
3223 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3224 DWORD cItem
= 3, cSwapped
= 0;
3226 if (info
->AuthAttrs
.cAttr
)
3228 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3229 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3230 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3231 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3232 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3236 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
3237 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3239 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3240 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3242 if (info
->UnauthAttrs
.cAttr
)
3244 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3245 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
3246 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3247 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3248 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3252 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3253 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3258 SetLastError(STATUS_ACCESS_VIOLATION
);
3264 BOOL
CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
3267 struct AsnEncodeSequenceItem items
[7] = {
3268 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
3270 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
3271 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
3272 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3273 DWORD cItem
= 1, cSwapped
= 0;
3276 if (signedInfo
->cSignerInfo
)
3278 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
3279 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
3280 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_SIGNER_INFO
);
3281 digestAlgorithmsSet
.itemOffset
=
3282 offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
);
3283 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3284 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
3285 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3288 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
3289 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
3291 if (signedInfo
->cCertEncoded
)
3293 certSet
.cItems
= signedInfo
->cCertEncoded
;
3294 certSet
.items
= signedInfo
->rgCertEncoded
;
3295 certSet
.itemSize
= sizeof(CERT_BLOB
);
3296 certSet
.itemOffset
= 0;
3297 certSet
.encode
= CRYPT_CopyEncodedBlob
;
3298 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
3299 swapped
[cSwapped
].pvStructInfo
= &certSet
;
3300 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3301 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3302 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3306 if (signedInfo
->cCrlEncoded
)
3308 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
3309 crlSet
.items
= signedInfo
->rgCrlEncoded
;
3310 crlSet
.itemSize
= sizeof(CRL_BLOB
);
3311 crlSet
.itemOffset
= 0;
3312 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
3313 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
3314 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
3315 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3316 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3317 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3321 if (ret
&& signedInfo
->cSignerInfo
)
3323 signerSet
.cItems
= signedInfo
->cSignerInfo
;
3324 signerSet
.items
= signedInfo
->rgSignerInfo
;
3325 signerSet
.itemSize
= sizeof(CMSG_SIGNER_INFO
);
3326 signerSet
.itemOffset
= 0;
3327 signerSet
.encode
= CRYPT_AsnEncodePKCSSignerInfo
;
3328 items
[cItem
].pvStructInfo
= &signerSet
;
3329 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3333 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
3334 items
, cItem
, 0, NULL
, pvData
, pcbData
);
3339 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
3340 LPCSTR lpszStructType
)
3342 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3344 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3345 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3347 SetLastError(ERROR_FILE_NOT_FOUND
);
3351 if (!HIWORD(lpszStructType
))
3353 switch (LOWORD(lpszStructType
))
3355 case (WORD
)X509_CERT
:
3356 encodeFunc
= CRYPT_AsnEncodeCert
;
3358 case (WORD
)X509_CERT_TO_BE_SIGNED
:
3359 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
3361 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
3362 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
3364 case (WORD
)X509_EXTENSIONS
:
3365 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3367 case (WORD
)X509_NAME_VALUE
:
3368 encodeFunc
= CRYPT_AsnEncodeNameValue
;
3370 case (WORD
)X509_NAME
:
3371 encodeFunc
= CRYPT_AsnEncodeName
;
3373 case (WORD
)X509_PUBLIC_KEY_INFO
:
3374 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
3376 case (WORD
)X509_AUTHORITY_KEY_ID
:
3377 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3379 case (WORD
)X509_ALTERNATE_NAME
:
3380 encodeFunc
= CRYPT_AsnEncodeAltName
;
3382 case (WORD
)X509_BASIC_CONSTRAINTS
:
3383 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3385 case (WORD
)X509_BASIC_CONSTRAINTS2
:
3386 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3388 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
3389 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
3391 case (WORD
)X509_UNICODE_NAME
:
3392 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
3394 case (WORD
)PKCS_CONTENT_INFO
:
3395 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
3397 case (WORD
)PKCS_ATTRIBUTE
:
3398 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
3400 case (WORD
)X509_UNICODE_NAME_VALUE
:
3401 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
3403 case (WORD
)X509_OCTET_STRING
:
3404 encodeFunc
= CRYPT_AsnEncodeOctets
;
3406 case (WORD
)X509_BITS
:
3407 case (WORD
)X509_KEY_USAGE
:
3408 encodeFunc
= CRYPT_AsnEncodeBits
;
3410 case (WORD
)X509_INTEGER
:
3411 encodeFunc
= CRYPT_AsnEncodeInt
;
3413 case (WORD
)X509_MULTI_BYTE_INTEGER
:
3414 encodeFunc
= CRYPT_AsnEncodeInteger
;
3416 case (WORD
)X509_MULTI_BYTE_UINT
:
3417 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
3419 case (WORD
)X509_ENUMERATED
:
3420 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3422 case (WORD
)X509_CHOICE_OF_TIME
:
3423 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
3425 case (WORD
)X509_AUTHORITY_KEY_ID2
:
3426 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3428 case (WORD
)X509_SEQUENCE_OF_ANY
:
3429 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
3431 case (WORD
)PKCS_UTC_TIME
:
3432 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3434 case (WORD
)X509_CRL_DIST_POINTS
:
3435 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3437 case (WORD
)X509_ENHANCED_KEY_USAGE
:
3438 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3440 case (WORD
)PKCS_ATTRIBUTES
:
3441 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3443 case (WORD
)X509_ISSUING_DIST_POINT
:
3444 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3446 case (WORD
)PKCS7_SIGNER_INFO
:
3447 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
3451 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
3452 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3453 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3454 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3455 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
3456 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3457 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
3458 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3459 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3460 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3461 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3462 encodeFunc
= CRYPT_AsnEncodeBits
;
3463 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3464 encodeFunc
= CRYPT_AsnEncodeOctets
;
3465 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
3466 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3467 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3468 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3469 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
3470 encodeFunc
= CRYPT_AsnEncodeAltName
;
3471 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
3472 encodeFunc
= CRYPT_AsnEncodeAltName
;
3473 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
3474 encodeFunc
= CRYPT_AsnEncodeAltName
;
3475 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
3476 encodeFunc
= CRYPT_AsnEncodeAltName
;
3477 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
3478 encodeFunc
= CRYPT_AsnEncodeAltName
;
3479 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
3480 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3481 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
3482 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3483 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
3484 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3488 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
3489 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
3491 static HCRYPTOIDFUNCSET set
= NULL
;
3492 CryptEncodeObjectFunc encodeFunc
= NULL
;
3495 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
3496 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3497 (void **)&encodeFunc
, hFunc
);
3501 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
3502 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
3504 static HCRYPTOIDFUNCSET set
= NULL
;
3505 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3508 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
3509 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3510 (void **)&encodeFunc
, hFunc
);
3514 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3515 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3518 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3519 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
3520 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
3522 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
3523 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
3526 if (!pbEncoded
&& !pcbEncoded
)
3528 SetLastError(ERROR_INVALID_PARAMETER
);
3532 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
3535 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
3536 debugstr_a(lpszStructType
));
3537 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
3538 lpszStructType
, &hFunc
);
3539 if (!pCryptEncodeObject
)
3540 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
3541 lpszStructType
, &hFunc
);
3543 if (pCryptEncodeObject
)
3544 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3545 pvStructInfo
, pbEncoded
, pcbEncoded
);
3546 else if (pCryptEncodeObjectEx
)
3547 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
3548 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
3550 CryptFreeOIDFunctionAddress(hFunc
, 0);
3551 TRACE_(crypt
)("returning %d\n", ret
);
3555 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3556 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
3557 void *pvEncoded
, DWORD
*pcbEncoded
)
3560 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3561 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3563 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
3564 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
3565 pvEncoded
, pcbEncoded
);
3567 if (!pvEncoded
&& !pcbEncoded
)
3569 SetLastError(ERROR_INVALID_PARAMETER
);
3573 SetLastError(NOERROR
);
3574 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
3575 *(BYTE
**)pvEncoded
= NULL
;
3576 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
3579 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
3580 debugstr_a(lpszStructType
));
3581 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
3585 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
3586 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
3589 CryptEncodeObjectFunc pCryptEncodeObject
=
3590 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
3592 if (pCryptEncodeObject
)
3594 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3596 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3597 pvStructInfo
, NULL
, pcbEncoded
);
3598 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3599 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
3600 ret
= pCryptEncodeObject(dwCertEncodingType
,
3601 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
3605 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
3606 pvStructInfo
, pvEncoded
, pcbEncoded
);
3610 CryptFreeOIDFunctionAddress(hFunc
, 0);
3611 TRACE_(crypt
)("returning %d\n", ret
);
3615 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
3616 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3618 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3619 NULL
, 0, NULL
, pInfo
, pcbInfo
);
3622 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
3623 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3624 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3628 static CHAR oid
[] = szOID_RSA_RSA
;
3630 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3631 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3634 if (!pszPublicKeyObjId
)
3635 pszPublicKeyObjId
= oid
;
3636 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
3640 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
3643 LPBYTE pubKey
= CryptMemAlloc(keySize
);
3647 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
3651 DWORD encodedLen
= 0;
3653 ret
= CryptEncodeObject(dwCertEncodingType
,
3654 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
3657 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
3658 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
3661 *pcbInfo
= sizeNeeded
;
3662 else if (*pcbInfo
< sizeNeeded
)
3664 SetLastError(ERROR_MORE_DATA
);
3665 *pcbInfo
= sizeNeeded
;
3670 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
3671 sizeof(CERT_PUBLIC_KEY_INFO
);
3672 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
3674 pInfo
->Algorithm
.Parameters
.cbData
= 0;
3675 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
3676 pInfo
->PublicKey
.pbData
=
3677 (BYTE
*)pInfo
->Algorithm
.pszObjId
3678 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
3679 pInfo
->PublicKey
.cbData
= encodedLen
;
3680 pInfo
->PublicKey
.cUnusedBits
= 0;
3681 ret
= CryptEncodeObject(dwCertEncodingType
,
3682 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
3683 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
3687 CryptMemFree(pubKey
);
3692 CryptDestroyKey(key
);
3697 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
3698 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3699 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
3701 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
3702 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
3703 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3705 static HCRYPTOIDFUNCSET set
= NULL
;
3707 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
3708 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3710 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
,
3711 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
3712 pvAuxInfo
, pInfo
, pcbInfo
);
3716 SetLastError(ERROR_INVALID_PARAMETER
);
3720 if (pszPublicKeyObjId
)
3723 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
3725 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
3726 0, (void **)&exportFunc
, &hFunc
);
3729 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
3730 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3731 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
3733 CryptFreeOIDFunctionAddress(hFunc
, 0);
3737 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
3738 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
3740 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
3744 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3745 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3746 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3749 DWORD pubKeySize
= 0;
3751 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3752 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3754 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3755 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
3758 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
3762 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3763 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
3766 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
3768 CryptMemFree(pubKey
);
3776 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3777 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3778 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
3780 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3781 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3782 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3784 static HCRYPTOIDFUNCSET set
= NULL
;
3786 ImportPublicKeyInfoExFunc importFunc
= NULL
;
3787 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3789 TRACE_(crypt
)("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3790 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3793 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
3794 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
3795 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
3797 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
3798 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
3801 CryptFreeOIDFunctionAddress(hFunc
, 0);