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(crypt
);
52 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
61 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
62 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
63 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
94 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
95 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
97 static HCRYPTOIDFUNCSET set
= NULL
;
99 HCRYPTOIDFUNCADDR hFunc
;
100 CryptEncodeObjectFunc pCryptEncodeObject
;
102 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
103 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
106 if (!pbEncoded
&& !pcbEncoded
)
108 SetLastError(ERROR_INVALID_PARAMETER
);
112 /* Try registered DLL first.. */
114 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
115 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
116 (void **)&pCryptEncodeObject
, &hFunc
);
117 if (pCryptEncodeObject
)
119 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
120 pvStructInfo
, pbEncoded
, pcbEncoded
);
121 CryptFreeOIDFunctionAddress(hFunc
, 0);
125 /* If not, use CryptEncodeObjectEx */
126 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
127 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
132 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
133 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
137 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
139 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
140 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
142 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
143 if (!*(BYTE
**)pbEncoded
)
146 *pcbEncoded
= bytesNeeded
;
148 else if (bytesNeeded
> *pcbEncoded
)
150 *pcbEncoded
= bytesNeeded
;
151 SetLastError(ERROR_MORE_DATA
);
155 *pcbEncoded
= bytesNeeded
;
159 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
161 DWORD bytesNeeded
, significantBytes
= 0;
169 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
170 temp
<<= 8, significantBytes
--)
172 bytesNeeded
= significantBytes
+ 1;
176 *pcbEncoded
= bytesNeeded
;
179 if (*pcbEncoded
< bytesNeeded
)
181 SetLastError(ERROR_MORE_DATA
);
185 *pbEncoded
= (BYTE
)len
;
190 *pbEncoded
++ = significantBytes
| 0x80;
191 for (i
= 0; i
< significantBytes
; i
++)
193 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
197 *pcbEncoded
= bytesNeeded
;
201 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
202 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
203 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
206 DWORD i
, dataLen
= 0;
208 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
209 pbEncoded
, *pcbEncoded
);
210 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
212 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
213 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
214 NULL
, &items
[i
].size
);
215 /* Some functions propagate their errors through the size */
217 *pcbEncoded
= items
[i
].size
;
218 dataLen
+= items
[i
].size
;
222 DWORD lenBytes
, bytesNeeded
;
224 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
225 bytesNeeded
= 1 + lenBytes
+ dataLen
;
227 *pcbEncoded
= bytesNeeded
;
230 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
231 pcbEncoded
, bytesNeeded
)))
233 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
234 pbEncoded
= *(BYTE
**)pbEncoded
;
235 *pbEncoded
++ = ASN_SEQUENCE
;
236 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
237 pbEncoded
+= lenBytes
;
238 for (i
= 0; ret
&& i
< cItem
; i
++)
240 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
241 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
242 NULL
, pbEncoded
, &items
[i
].size
);
243 /* Some functions propagate their errors through the size */
245 *pcbEncoded
= items
[i
].size
;
246 pbEncoded
+= items
[i
].size
;
251 TRACE("returning %d (%08x)\n", ret
, GetLastError());
255 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
256 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
257 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
260 const struct AsnConstructedItem
*item
=
261 (const struct AsnConstructedItem
*)pvStructInfo
;
264 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
265 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
267 DWORD dataLen
, bytesNeeded
;
269 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
270 bytesNeeded
= 1 + dataLen
+ len
;
272 *pcbEncoded
= bytesNeeded
;
273 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
274 pbEncoded
, pcbEncoded
, bytesNeeded
)))
276 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
277 pbEncoded
= *(BYTE
**)pbEncoded
;
278 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
279 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
280 pbEncoded
+= dataLen
;
281 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
282 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
286 /* Some functions propagate their errors through the size */
293 /* Some functions propagate their errors through the size */
299 struct AsnEncodeTagSwappedItem
302 const void *pvStructInfo
;
303 CryptEncodeObjectExFunc encodeFunc
;
306 /* Sort of a wacky hack, it encodes something using the struct
307 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
308 * given in the struct AsnEncodeTagSwappedItem.
310 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
311 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
312 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
315 const struct AsnEncodeTagSwappedItem
*item
=
316 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
318 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
319 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
320 if (ret
&& pbEncoded
)
321 *pbEncoded
= item
->tag
;
325 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
326 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
327 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
329 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
332 /* CERT_V1 is not encoded */
340 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
342 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
343 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
348 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
349 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
350 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
352 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
357 *pcbEncoded
= blob
->cbData
;
362 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
363 pcbEncoded
, blob
->cbData
)))
365 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
366 pbEncoded
= *(BYTE
**)pbEncoded
;
368 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
369 *pcbEncoded
= blob
->cbData
;
376 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
377 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
378 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
381 /* This has two filetimes in a row, a NotBefore and a NotAfter */
382 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
383 struct AsnEncodeSequenceItem items
[] = {
384 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
385 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
388 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
389 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
394 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
397 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
398 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
399 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
402 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
403 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
404 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
405 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
408 struct AsnEncodeSequenceItem items
[2] = {
409 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
410 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
413 if (algo
->Parameters
.cbData
)
414 items
[1].pvStructInfo
= &algo
->Parameters
;
416 items
[1].pvStructInfo
= &nullBlob
;
417 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
418 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
423 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
424 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
425 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
427 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
428 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
430 struct AsnEncodeSequenceItem items
[] = {
431 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
432 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
435 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
436 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
441 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
442 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
443 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
449 const CERT_PUBLIC_KEY_INFO
*info
=
450 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
451 struct AsnEncodeSequenceItem items
[] = {
452 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
453 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
456 TRACE("Encoding public key with OID %s\n",
457 debugstr_a(info
->Algorithm
.pszObjId
));
458 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
459 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
464 SetLastError(STATUS_ACCESS_VIOLATION
);
471 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
472 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
473 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
479 const CERT_SIGNED_CONTENT_INFO
*info
=
480 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
481 struct AsnEncodeSequenceItem items
[] = {
482 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
483 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
484 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
487 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
488 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
489 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
490 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
495 SetLastError(STATUS_ACCESS_VIOLATION
);
502 /* Like in Windows, this blithely ignores the validity of the passed-in
503 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
504 * decode properly, see CRYPT_AsnDecodeCertInfo.
506 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
507 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
508 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
514 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
515 struct AsnEncodeSequenceItem items
[10] = {
516 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
517 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
518 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
519 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
520 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
521 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
522 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
525 struct AsnConstructedItem constructed
[3] = { { 0 } };
526 DWORD cItem
= 7, cConstructed
= 0;
528 if (info
->IssuerUniqueId
.cbData
)
530 constructed
[cConstructed
].tag
= 1;
531 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
532 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
533 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
534 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
538 if (info
->SubjectUniqueId
.cbData
)
540 constructed
[cConstructed
].tag
= 2;
541 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
542 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
543 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
544 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
548 if (info
->cExtension
)
550 constructed
[cConstructed
].tag
= 3;
551 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
552 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
553 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
554 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
559 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
560 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
564 SetLastError(STATUS_ACCESS_VIOLATION
);
571 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
572 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
574 struct AsnEncodeSequenceItem items
[3] = {
575 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
576 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
582 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
584 if (entry
->cExtension
)
586 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
587 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
591 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
592 pbEncoded
, pcbEncoded
);
594 TRACE("returning %d (%08x)\n", ret
, GetLastError());
598 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
599 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
600 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
602 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
603 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
604 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
605 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
608 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
612 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
616 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
617 bytesNeeded
= 1 + lenBytes
+ dataLen
;
619 *pcbEncoded
= bytesNeeded
;
622 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
623 pcbEncoded
, bytesNeeded
)))
625 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
626 pbEncoded
= *(BYTE
**)pbEncoded
;
627 *pbEncoded
++ = ASN_SEQUENCEOF
;
628 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
629 pbEncoded
+= lenBytes
;
630 for (i
= 0; i
< cCRLEntry
; i
++)
632 DWORD size
= dataLen
;
634 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
643 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
644 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
645 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
647 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
650 /* CRL_V1 is not encoded */
657 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
658 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
662 /* Like in Windows, this blithely ignores the validity of the passed-in
663 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
664 * decode properly, see CRYPT_AsnDecodeCRLInfo.
666 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
667 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
668 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
674 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
675 struct AsnEncodeSequenceItem items
[7] = {
676 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
677 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
678 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
679 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
682 struct AsnConstructedItem constructed
[1] = { { 0 } };
683 DWORD cItem
= 4, cConstructed
= 0;
685 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
687 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
688 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
693 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
694 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
697 if (info
->cExtension
)
699 constructed
[cConstructed
].tag
= 0;
700 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
701 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
702 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
703 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
708 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
709 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
713 SetLastError(STATUS_ACCESS_VIOLATION
);
720 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
724 struct AsnEncodeSequenceItem items
[3] = {
725 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
731 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
735 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
736 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
739 items
[cItem
].pvStructInfo
= &ext
->Value
;
740 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
743 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
744 pbEncoded
, pcbEncoded
);
745 TRACE("returning %d (%08x)\n", ret
, GetLastError());
749 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
750 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
751 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
757 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
758 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
761 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
765 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
769 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
770 bytesNeeded
= 1 + lenBytes
+ dataLen
;
772 *pcbEncoded
= bytesNeeded
;
775 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
776 pcbEncoded
, bytesNeeded
)))
778 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
779 pbEncoded
= *(BYTE
**)pbEncoded
;
780 *pbEncoded
++ = ASN_SEQUENCEOF
;
781 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
782 pbEncoded
+= lenBytes
;
783 for (i
= 0; i
< exts
->cExtension
; i
++)
785 DWORD size
= dataLen
;
787 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
797 SetLastError(STATUS_ACCESS_VIOLATION
);
804 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
805 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
806 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
808 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
809 DWORD bytesNeeded
= 0, lenBytes
;
814 TRACE("%s\n", debugstr_a(pszObjId
));
821 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
823 SetLastError(CRYPT_E_ASN1_ERROR
);
827 firstByte
= val1
* 40 + val2
;
828 ptr
= pszObjId
+ firstPos
;
833 /* note I assume each component is at most 32-bits long in base 2 */
834 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
836 if (val1
>= 0x10000000)
838 else if (val1
>= 0x200000)
840 else if (val1
>= 0x4000)
842 else if (val1
>= 0x80)
852 SetLastError(CRYPT_E_ASN1_ERROR
);
856 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
860 bytesNeeded
+= 1 + lenBytes
;
863 if (*pcbEncoded
< bytesNeeded
)
865 SetLastError(ERROR_MORE_DATA
);
870 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
871 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
872 pbEncoded
+= lenBytes
;
878 *pbEncoded
++ = firstByte
;
879 ptr
= pszObjId
+ firstPos
;
882 sscanf(ptr
, "%d%n", &val
, &pos
);
884 unsigned char outBytes
[5];
887 if (val
>= 0x10000000)
889 else if (val
>= 0x200000)
891 else if (val
>= 0x4000)
893 else if (val
>= 0x80)
897 for (i
= numBytes
; i
> 0; i
--)
899 outBytes
[i
- 1] = val
& 0x7f;
902 for (i
= 0; i
< numBytes
- 1; i
++)
903 *pbEncoded
++ = outBytes
[i
] | 0x80;
904 *pbEncoded
++ = outBytes
[i
];
913 *pcbEncoded
= bytesNeeded
;
917 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
918 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
922 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
923 DWORD bytesNeeded
, lenBytes
, encodedLen
;
925 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: lstrlenA(str
);
926 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
927 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
929 *pcbEncoded
= bytesNeeded
;
932 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
933 pbEncoded
, pcbEncoded
, bytesNeeded
)))
935 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
936 pbEncoded
= *(BYTE
**)pbEncoded
;
938 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
939 pbEncoded
+= lenBytes
;
940 memcpy(pbEncoded
, str
, encodedLen
);
946 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
947 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
951 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
952 DWORD bytesNeeded
, lenBytes
, strLen
;
954 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
956 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
957 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
959 *pcbEncoded
= bytesNeeded
;
962 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
963 pbEncoded
, pcbEncoded
, bytesNeeded
)))
967 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
968 pbEncoded
= *(BYTE
**)pbEncoded
;
969 *pbEncoded
++ = ASN_BMPSTRING
;
970 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
971 pbEncoded
+= lenBytes
;
972 for (i
= 0; i
< strLen
; i
++)
974 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
975 *pbEncoded
++ = str
[i
] & 0x00ff;
982 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
983 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
987 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
988 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
990 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
992 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
994 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
995 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
997 *pcbEncoded
= bytesNeeded
;
1000 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1001 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1003 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1004 pbEncoded
= *(BYTE
**)pbEncoded
;
1005 *pbEncoded
++ = ASN_UTF8STRING
;
1006 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1007 pbEncoded
+= lenBytes
;
1008 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
1009 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
1015 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1016 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1017 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1023 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1025 switch (value
->dwValueType
)
1027 case CERT_RDN_ANY_TYPE
:
1028 /* explicitly disallowed */
1029 SetLastError(E_INVALIDARG
);
1032 case CERT_RDN_ENCODED_BLOB
:
1033 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1034 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1036 case CERT_RDN_OCTET_STRING
:
1037 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1038 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1040 case CERT_RDN_NUMERIC_STRING
:
1041 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1042 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1044 case CERT_RDN_PRINTABLE_STRING
:
1045 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1046 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1048 case CERT_RDN_TELETEX_STRING
:
1049 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1050 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1052 case CERT_RDN_VIDEOTEX_STRING
:
1053 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1054 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1056 case CERT_RDN_IA5_STRING
:
1057 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1058 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1060 case CERT_RDN_GRAPHIC_STRING
:
1061 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1062 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1064 case CERT_RDN_VISIBLE_STRING
:
1065 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1066 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1068 case CERT_RDN_GENERAL_STRING
:
1069 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1070 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1072 case CERT_RDN_UNIVERSAL_STRING
:
1073 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1074 SetLastError(CRYPT_E_ASN1_CHOICE
);
1077 case CERT_RDN_BMP_STRING
:
1078 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1079 pbEncoded
, pcbEncoded
);
1081 case CERT_RDN_UTF8_STRING
:
1082 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1083 pbEncoded
, pcbEncoded
);
1086 SetLastError(CRYPT_E_ASN1_CHOICE
);
1092 SetLastError(STATUS_ACCESS_VIOLATION
);
1099 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1100 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1101 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1103 DWORD bytesNeeded
= 0, lenBytes
, size
;
1106 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1107 0, NULL
, NULL
, &size
);
1110 bytesNeeded
+= size
;
1111 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1112 * with dwValueType, so "cast" it to get its encoded size
1114 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1115 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1118 bytesNeeded
+= size
;
1119 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1120 bytesNeeded
+= 1 + lenBytes
;
1123 if (*pcbEncoded
< bytesNeeded
)
1125 SetLastError(ERROR_MORE_DATA
);
1130 *pbEncoded
++ = ASN_SEQUENCE
;
1131 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1133 pbEncoded
+= lenBytes
;
1134 size
= bytesNeeded
- 1 - lenBytes
;
1135 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1136 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1140 size
= bytesNeeded
- 1 - lenBytes
- size
;
1141 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1142 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1143 0, NULL
, pbEncoded
, &size
);
1150 *pcbEncoded
= bytesNeeded
;
1154 /* Have to propagate index of failing character */
1161 static int BLOBComp(const void *l
, const void *r
)
1163 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1166 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1167 ret
= a
->cbData
- b
->cbData
;
1171 typedef struct _CRYPT_SET_OF
{
1173 PCRYPT_DER_BLOB rgValue
;
1176 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1178 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1179 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1180 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1182 const CRYPT_SET_OF
*set
= (const CRYPT_SET_OF
*)pvStructInfo
;
1183 DWORD bytesNeeded
= 0, lenBytes
, i
;
1186 for (i
= 0; i
< set
->cValue
; i
++)
1187 bytesNeeded
+= set
->rgValue
[i
].cbData
;
1188 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1189 bytesNeeded
+= 1 + lenBytes
;
1192 *pcbEncoded
= bytesNeeded
;
1195 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1196 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1198 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1199 pbEncoded
= *(BYTE
**)pbEncoded
;
1200 qsort(set
->rgValue
, set
->cValue
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1201 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1202 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1203 pbEncoded
+= lenBytes
;
1204 for (i
= 0; ret
&& i
< set
->cValue
; i
++)
1206 memcpy(pbEncoded
, set
->rgValue
[i
].pbData
, set
->rgValue
[i
].cbData
);
1207 pbEncoded
+= set
->rgValue
[i
].cbData
;
1213 struct DERSetDescriptor
1219 CryptEncodeObjectExFunc encode
;
1222 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1223 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1224 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1226 const struct DERSetDescriptor
*desc
=
1227 (const struct DERSetDescriptor
*)pvStructInfo
;
1228 CRYPT_SET_OF setOf
= { 0, NULL
};
1234 setOf
.rgValue
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1239 setOf
.cValue
= desc
->cItems
;
1240 memset(setOf
.rgValue
, 0, setOf
.cValue
* sizeof(CRYPT_DER_BLOB
));
1243 for (i
= 0; ret
&& i
< setOf
.cValue
; i
++)
1245 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1246 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1247 0, NULL
, NULL
, &setOf
.rgValue
[i
].cbData
);
1250 setOf
.rgValue
[i
].pbData
= CryptMemAlloc(setOf
.rgValue
[i
].cbData
);
1251 if (!setOf
.rgValue
[i
].pbData
)
1254 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1255 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1256 desc
->itemOffset
, 0, NULL
, setOf
.rgValue
[i
].pbData
,
1257 &setOf
.rgValue
[i
].cbData
);
1259 /* Some functions propagate their errors through the size */
1261 *pcbEncoded
= setOf
.rgValue
[i
].cbData
;
1265 DWORD bytesNeeded
= 0, lenBytes
;
1268 for (i
= 0; i
< setOf
.cValue
; i
++)
1269 bytesNeeded
+= setOf
.rgValue
[i
].cbData
;
1270 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1271 bytesNeeded
+= 1 + lenBytes
;
1273 *pcbEncoded
= bytesNeeded
;
1274 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1275 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1277 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1278 pbEncoded
= *(BYTE
**)pbEncoded
;
1279 qsort(setOf
.rgValue
, setOf
.cValue
, sizeof(CRYPT_DER_BLOB
),
1281 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1282 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1283 pbEncoded
+= lenBytes
;
1284 for (i
= 0; i
< setOf
.cValue
; i
++)
1286 memcpy(pbEncoded
, setOf
.rgValue
[i
].pbData
,
1287 setOf
.rgValue
[i
].cbData
);
1288 pbEncoded
+= setOf
.rgValue
[i
].cbData
;
1292 for (i
= 0; i
< setOf
.cValue
; i
++)
1293 CryptMemFree(setOf
.rgValue
[i
].pbData
);
1294 CryptMemFree(setOf
.rgValue
);
1298 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1299 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1303 CRYPT_SET_OF setOf
= { 0, NULL
};
1312 setOf
.cValue
= rdn
->cRDNAttr
;
1313 setOf
.rgValue
= CryptMemAlloc(rdn
->cRDNAttr
*
1314 sizeof(CRYPT_DER_BLOB
));
1318 memset(setOf
.rgValue
, 0, setOf
.cValue
* sizeof(CRYPT_DER_BLOB
));
1320 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1322 setOf
.rgValue
[i
].cbData
= 0;
1323 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1324 nameValueEncodeFunc
, NULL
, &setOf
.rgValue
[i
].cbData
);
1327 setOf
.rgValue
[i
].pbData
=
1328 CryptMemAlloc(setOf
.rgValue
[i
].cbData
);
1329 if (!setOf
.rgValue
[i
].pbData
)
1332 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1333 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1334 setOf
.rgValue
[i
].pbData
, &setOf
.rgValue
[i
].cbData
);
1338 /* Have to propagate index of failing character */
1339 *pcbEncoded
= setOf
.rgValue
[i
].cbData
;
1343 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1344 pbEncoded
, pcbEncoded
);
1345 for (i
= 0; i
< setOf
.cValue
; i
++)
1346 CryptMemFree(setOf
.rgValue
[i
].pbData
);
1350 SetLastError(STATUS_ACCESS_VIOLATION
);
1354 CryptMemFree(setOf
.rgValue
);
1358 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1359 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1360 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1362 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1363 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1364 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1367 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1370 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1371 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1372 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1374 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1375 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1379 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1380 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1381 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1387 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1388 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1390 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1392 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1394 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1395 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1397 bytesNeeded
+= size
;
1401 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1402 bytesNeeded
+= 1 + lenBytes
;
1406 *pcbEncoded
= bytesNeeded
;
1409 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1410 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1412 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1413 pbEncoded
= *(BYTE
**)pbEncoded
;
1414 *pbEncoded
++ = ASN_SEQUENCEOF
;
1415 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1417 pbEncoded
+= lenBytes
;
1418 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1421 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1422 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1427 bytesNeeded
-= size
;
1438 SetLastError(STATUS_ACCESS_VIOLATION
);
1445 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1446 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1447 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1453 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1455 if (!attr
->pszObjId
)
1456 SetLastError(E_INVALIDARG
);
1459 struct AsnEncodeSequenceItem items
[2] = {
1460 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1461 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1464 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1465 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1471 SetLastError(STATUS_ACCESS_VIOLATION
);
1477 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1478 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1479 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1485 const CRYPT_ATTRIBUTES
*attributes
=
1486 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1487 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1488 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1490 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1491 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1495 SetLastError(STATUS_ACCESS_VIOLATION
);
1501 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1502 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1503 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1504 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1507 const CRYPT_CONTENT_INFO
*info
= (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1508 struct AsnEncodeSequenceItem items
[2] = {
1509 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1512 struct AsnConstructedItem constructed
= { 0 };
1515 if (info
->Content
.cbData
)
1517 constructed
.tag
= 0;
1518 constructed
.pvStructInfo
= &info
->Content
;
1519 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1520 items
[cItem
].pvStructInfo
= &constructed
;
1521 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1524 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1525 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1528 BOOL
CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA
*digestedData
,
1529 void *pvData
, DWORD
*pcbData
)
1531 struct AsnEncodeSequenceItem items
[] = {
1532 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1533 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1535 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1536 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1539 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1540 sizeof(items
) / sizeof(items
[0]), 0, NULL
, pvData
, pcbData
);
1543 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1544 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1545 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1551 const CRYPT_CONTENT_INFO
*info
=
1552 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1554 if (!info
->pszObjId
)
1555 SetLastError(E_INVALIDARG
);
1557 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1558 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1563 SetLastError(STATUS_ACCESS_VIOLATION
);
1569 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1570 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1574 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1575 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1577 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1579 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1580 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1582 *pcbEncoded
= bytesNeeded
;
1585 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1586 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1590 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1591 pbEncoded
= *(BYTE
**)pbEncoded
;
1593 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1594 pbEncoded
+= lenBytes
;
1595 for (i
= 0; i
< encodedLen
; i
++)
1596 *pbEncoded
++ = (BYTE
)str
[i
];
1602 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1603 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1607 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1608 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1610 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1612 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1613 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1615 *pcbEncoded
= bytesNeeded
;
1618 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1619 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1623 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1624 pbEncoded
= *(BYTE
**)pbEncoded
;
1625 *pbEncoded
++ = ASN_NUMERICSTRING
;
1626 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1627 pbEncoded
+= lenBytes
;
1628 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1630 if (isdigitW(str
[i
]))
1631 *pbEncoded
++ = (BYTE
)str
[i
];
1635 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1644 static inline int isprintableW(WCHAR wc
)
1646 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1647 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1648 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1651 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1652 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1656 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1657 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1659 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1661 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1662 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1664 *pcbEncoded
= bytesNeeded
;
1667 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1668 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1672 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1673 pbEncoded
= *(BYTE
**)pbEncoded
;
1674 *pbEncoded
++ = ASN_PRINTABLESTRING
;
1675 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1676 pbEncoded
+= lenBytes
;
1677 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1679 if (isprintableW(str
[i
]))
1680 *pbEncoded
++ = (BYTE
)str
[i
];
1684 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1693 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1694 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1698 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1699 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1701 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1703 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1704 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1706 *pcbEncoded
= bytesNeeded
;
1709 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1710 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1714 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1715 pbEncoded
= *(BYTE
**)pbEncoded
;
1716 *pbEncoded
++ = ASN_IA5STRING
;
1717 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1718 pbEncoded
+= lenBytes
;
1719 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1722 *pbEncoded
++ = (BYTE
)str
[i
];
1726 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1735 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
1736 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1740 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1741 DWORD bytesNeeded
, lenBytes
, strLen
;
1743 /* FIXME: doesn't handle composite characters */
1744 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1746 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
1747 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
1749 *pcbEncoded
= bytesNeeded
;
1752 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1753 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1757 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1758 pbEncoded
= *(BYTE
**)pbEncoded
;
1759 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
1760 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
1761 pbEncoded
+= lenBytes
;
1762 for (i
= 0; i
< strLen
; i
++)
1766 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
1767 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
1774 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1775 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1776 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1782 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1784 switch (value
->dwValueType
)
1786 case CERT_RDN_ANY_TYPE
:
1787 case CERT_RDN_ENCODED_BLOB
:
1788 case CERT_RDN_OCTET_STRING
:
1789 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
1791 case CERT_RDN_NUMERIC_STRING
:
1792 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
1793 pbEncoded
, pcbEncoded
);
1795 case CERT_RDN_PRINTABLE_STRING
:
1796 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
1797 pbEncoded
, pcbEncoded
);
1799 case CERT_RDN_TELETEX_STRING
:
1800 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
1801 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1803 case CERT_RDN_VIDEOTEX_STRING
:
1804 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
1805 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1807 case CERT_RDN_IA5_STRING
:
1808 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
1809 pbEncoded
, pcbEncoded
);
1811 case CERT_RDN_GRAPHIC_STRING
:
1812 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1813 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1815 case CERT_RDN_VISIBLE_STRING
:
1816 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
1817 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1819 case CERT_RDN_GENERAL_STRING
:
1820 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
1821 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1823 case CERT_RDN_UNIVERSAL_STRING
:
1824 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
1825 pbEncoded
, pcbEncoded
);
1827 case CERT_RDN_BMP_STRING
:
1828 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1829 pbEncoded
, pcbEncoded
);
1831 case CERT_RDN_UTF8_STRING
:
1832 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1833 pbEncoded
, pcbEncoded
);
1836 SetLastError(CRYPT_E_ASN1_CHOICE
);
1841 SetLastError(STATUS_ACCESS_VIOLATION
);
1847 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1848 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1849 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1855 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1856 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1858 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1860 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1862 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1863 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
1865 bytesNeeded
+= size
;
1867 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1868 bytesNeeded
+= 1 + lenBytes
;
1872 *pcbEncoded
= bytesNeeded
;
1875 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1876 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1878 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1879 pbEncoded
= *(BYTE
**)pbEncoded
;
1880 *pbEncoded
++ = ASN_SEQUENCEOF
;
1881 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1883 pbEncoded
+= lenBytes
;
1884 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1887 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1888 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
1893 bytesNeeded
-= size
;
1902 SetLastError(STATUS_ACCESS_VIOLATION
);
1909 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1910 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1911 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1913 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1922 else if (*pcbEncoded
< 3)
1925 SetLastError(ERROR_MORE_DATA
);
1931 *pbEncoded
++ = ASN_BOOL
;
1933 *pbEncoded
++ = val
? 0xff : 0;
1936 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1940 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1941 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1948 switch (entry
->dwAltNameChoice
)
1950 case CERT_ALT_NAME_RFC822_NAME
:
1951 case CERT_ALT_NAME_DNS_NAME
:
1952 case CERT_ALT_NAME_URL
:
1953 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1954 if (entry
->u
.pwszURL
)
1958 /* Not + 1: don't encode the NULL-terminator */
1959 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1960 for (i
= 0; ret
&& i
< dataLen
; i
++)
1962 if (entry
->u
.pwszURL
[i
] > 0x7f)
1964 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1973 case CERT_ALT_NAME_DIRECTORY_NAME
:
1974 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
1975 dataLen
= entry
->u
.DirectoryName
.cbData
;
1977 case CERT_ALT_NAME_IP_ADDRESS
:
1978 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1979 dataLen
= entry
->u
.IPAddress
.cbData
;
1981 case CERT_ALT_NAME_REGISTERED_ID
:
1983 struct AsnEncodeTagSwappedItem swapped
=
1984 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
1985 CRYPT_AsnEncodeOid
};
1987 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
1990 case CERT_ALT_NAME_OTHER_NAME
:
1991 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
1994 SetLastError(E_INVALIDARG
);
1999 DWORD bytesNeeded
, lenBytes
;
2001 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2002 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2004 *pcbEncoded
= bytesNeeded
;
2005 else if (*pcbEncoded
< bytesNeeded
)
2007 SetLastError(ERROR_MORE_DATA
);
2008 *pcbEncoded
= bytesNeeded
;
2014 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2015 pbEncoded
+= lenBytes
;
2016 switch (entry
->dwAltNameChoice
)
2018 case CERT_ALT_NAME_RFC822_NAME
:
2019 case CERT_ALT_NAME_DNS_NAME
:
2020 case CERT_ALT_NAME_URL
:
2024 for (i
= 0; i
< dataLen
; i
++)
2025 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2028 case CERT_ALT_NAME_DIRECTORY_NAME
:
2029 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2031 case CERT_ALT_NAME_IP_ADDRESS
:
2032 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2036 *pcbEncoded
= bytesNeeded
;
2039 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2043 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2044 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2045 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2051 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
2052 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
2053 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2054 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2055 struct AsnConstructedItem constructed
= { 0 };
2056 DWORD cItem
= 0, cSwapped
= 0;
2058 if (info
->KeyId
.cbData
)
2060 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2061 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2062 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2063 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2064 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2068 if (info
->CertIssuer
.cbData
)
2070 constructed
.tag
= 1;
2071 constructed
.pvStructInfo
= &info
->CertIssuer
;
2072 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2073 items
[cItem
].pvStructInfo
= &constructed
;
2074 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2077 if (info
->CertSerialNumber
.cbData
)
2079 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2080 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2081 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2082 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2083 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2087 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2088 pEncodePara
, pbEncoded
, pcbEncoded
);
2092 SetLastError(STATUS_ACCESS_VIOLATION
);
2099 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2100 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2101 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2107 const CERT_ALT_NAME_INFO
*info
=
2108 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2109 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2112 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2113 * can't encode an erroneous entry index if it's bigger than this.
2115 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2119 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
2123 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2125 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2126 * the bad character, now set the index of the bad
2129 *pcbEncoded
= (BYTE
)i
<<
2130 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2135 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2136 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2139 *pcbEncoded
= bytesNeeded
;
2144 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2145 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2147 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2148 pbEncoded
= *(BYTE
**)pbEncoded
;
2149 *pbEncoded
++ = ASN_SEQUENCEOF
;
2150 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2151 pbEncoded
+= lenBytes
;
2152 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2154 DWORD len
= dataLen
;
2156 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
2170 SetLastError(STATUS_ACCESS_VIOLATION
);
2177 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2178 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2179 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2185 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2186 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2187 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2188 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2189 DWORD cItem
= 0, cSwapped
= 0;
2191 if (info
->KeyId
.cbData
)
2193 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2194 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2195 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2196 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2197 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2201 if (info
->AuthorityCertIssuer
.cAltEntry
)
2203 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2204 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2205 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2206 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2207 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2211 if (info
->AuthorityCertSerialNumber
.cbData
)
2213 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2214 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2215 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2216 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2217 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2221 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2222 pEncodePara
, pbEncoded
, pcbEncoded
);
2226 SetLastError(STATUS_ACCESS_VIOLATION
);
2233 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2234 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2235 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2241 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2242 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2243 struct AsnEncodeSequenceItem items
[3] = {
2244 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2249 if (info
->fPathLenConstraint
)
2251 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2252 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2255 if (info
->cSubtreesConstraint
)
2257 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2258 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2261 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2262 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2266 SetLastError(STATUS_ACCESS_VIOLATION
);
2273 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2274 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2275 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2281 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2282 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2283 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2288 items
[cItem
].pvStructInfo
= &info
->fCA
;
2289 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2292 if (info
->fPathLenConstraint
)
2294 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2295 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2298 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2299 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2303 SetLastError(STATUS_ACCESS_VIOLATION
);
2310 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2311 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2312 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2318 const BLOBHEADER
*hdr
=
2319 (const BLOBHEADER
*)pvStructInfo
;
2321 if (hdr
->bType
!= PUBLICKEYBLOB
)
2323 SetLastError(E_INVALIDARG
);
2328 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2329 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2330 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2331 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2332 struct AsnEncodeSequenceItem items
[] = {
2333 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2334 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2337 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2338 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2344 SetLastError(STATUS_ACCESS_VIOLATION
);
2351 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2352 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2353 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2359 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2360 DWORD bytesNeeded
, lenBytes
;
2362 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2363 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2365 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2366 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2369 *pcbEncoded
= bytesNeeded
;
2374 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2375 pcbEncoded
, bytesNeeded
)))
2377 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2378 pbEncoded
= *(BYTE
**)pbEncoded
;
2379 *pbEncoded
++ = ASN_OCTETSTRING
;
2380 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2381 pbEncoded
+= lenBytes
;
2383 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2389 SetLastError(STATUS_ACCESS_VIOLATION
);
2393 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2397 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2398 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2399 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2405 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2406 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2409 /* yep, MS allows cUnusedBits to be >= 8 */
2410 if (!blob
->cUnusedBits
)
2412 dataBytes
= blob
->cbData
;
2415 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2417 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2418 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2426 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2427 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2430 *pcbEncoded
= bytesNeeded
;
2435 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2436 pcbEncoded
, bytesNeeded
)))
2438 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2439 pbEncoded
= *(BYTE
**)pbEncoded
;
2440 *pbEncoded
++ = ASN_BITSTRING
;
2441 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2442 pbEncoded
+= lenBytes
;
2443 *pbEncoded
++ = unusedBits
;
2446 BYTE mask
= 0xff << unusedBits
;
2450 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2451 pbEncoded
+= dataBytes
- 1;
2453 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2460 SetLastError(STATUS_ACCESS_VIOLATION
);
2467 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2468 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2469 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2475 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2476 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2481 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2486 for (i
= 0; i
< newBlob
.cbData
; i
++)
2487 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2493 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2494 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2495 CryptMemFree(newBlob
.pbData
);
2499 SetLastError(STATUS_ACCESS_VIOLATION
);
2506 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2507 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2508 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2510 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2512 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2513 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2516 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2517 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2518 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2524 DWORD significantBytes
, lenBytes
;
2525 BYTE padByte
= 0, bytesNeeded
;
2527 const CRYPT_INTEGER_BLOB
*blob
=
2528 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2530 significantBytes
= blob
->cbData
;
2531 if (significantBytes
)
2533 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2535 /* negative, lop off leading (little-endian) 0xffs */
2536 for (; significantBytes
> 0 &&
2537 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2539 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2547 /* positive, lop off leading (little-endian) zeroes */
2548 for (; significantBytes
> 0 &&
2549 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2551 if (significantBytes
== 0)
2552 significantBytes
= 1;
2553 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2561 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2563 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2564 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2569 *pcbEncoded
= bytesNeeded
;
2574 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2575 pcbEncoded
, bytesNeeded
)))
2577 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2578 pbEncoded
= *(BYTE
**)pbEncoded
;
2579 *pbEncoded
++ = ASN_INTEGER
;
2582 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2583 pbEncoded
+= lenBytes
;
2584 *pbEncoded
++ = padByte
;
2588 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2589 pbEncoded
+= lenBytes
;
2591 for (; significantBytes
> 0; significantBytes
--)
2592 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2598 SetLastError(STATUS_ACCESS_VIOLATION
);
2605 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
2606 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2607 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2613 DWORD significantBytes
, lenBytes
;
2616 const CRYPT_INTEGER_BLOB
*blob
=
2617 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2619 significantBytes
= blob
->cbData
;
2620 if (significantBytes
)
2622 /* positive, lop off leading (little-endian) zeroes */
2623 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2626 if (significantBytes
== 0)
2627 significantBytes
= 1;
2628 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2632 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2634 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2635 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2640 *pcbEncoded
= bytesNeeded
;
2645 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2646 pcbEncoded
, bytesNeeded
)))
2648 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2649 pbEncoded
= *(BYTE
**)pbEncoded
;
2650 *pbEncoded
++ = ASN_INTEGER
;
2653 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2654 pbEncoded
+= lenBytes
;
2659 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2660 pbEncoded
+= lenBytes
;
2662 for (; significantBytes
> 0; significantBytes
--)
2663 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2669 SetLastError(STATUS_ACCESS_VIOLATION
);
2676 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2677 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2678 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2680 CRYPT_INTEGER_BLOB blob
;
2683 /* Encode as an unsigned integer, then change the tag to enumerated */
2684 blob
.cbData
= sizeof(DWORD
);
2685 blob
.pbData
= (BYTE
*)pvStructInfo
;
2686 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2687 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2688 if (ret
&& pbEncoded
)
2690 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2691 pbEncoded
= *(BYTE
**)pbEncoded
;
2692 pbEncoded
[0] = ASN_ENUMERATED
;
2697 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2698 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2699 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2706 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2707 * temporary buffer because the output buffer is not NULL-terminated.
2710 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2714 *pcbEncoded
= bytesNeeded
;
2719 /* Sanity check the year, this is a two-digit year format */
2720 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2722 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2724 SetLastError(CRYPT_E_BAD_ENCODE
);
2729 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2730 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2732 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2733 pbEncoded
= *(BYTE
**)pbEncoded
;
2734 buf
[0] = ASN_UTCTIME
;
2735 buf
[1] = bytesNeeded
- 2;
2736 snprintf(buf
+ 2, sizeof(buf
) - 2,
2737 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2738 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2739 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2740 sysTime
.wMinute
, sysTime
.wSecond
);
2741 memcpy(pbEncoded
, buf
, bytesNeeded
);
2748 SetLastError(STATUS_ACCESS_VIOLATION
);
2755 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2756 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2757 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2764 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2765 * temporary buffer because the output buffer is not NULL-terminated.
2768 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2772 *pcbEncoded
= bytesNeeded
;
2777 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2780 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2781 pcbEncoded
, bytesNeeded
);
2784 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2785 pbEncoded
= *(BYTE
**)pbEncoded
;
2786 buf
[0] = ASN_GENERALTIME
;
2787 buf
[1] = bytesNeeded
- 2;
2788 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2789 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2790 sysTime
.wMinute
, sysTime
.wSecond
);
2791 memcpy(pbEncoded
, buf
, bytesNeeded
);
2797 SetLastError(STATUS_ACCESS_VIOLATION
);
2804 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2805 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2806 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2814 /* Check the year, if it's in the UTCTime range call that encode func */
2815 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2817 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2818 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2819 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2821 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2822 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2827 SetLastError(STATUS_ACCESS_VIOLATION
);
2834 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2835 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2836 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2842 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2843 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2844 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2846 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2847 dataLen
+= seq
->rgValue
[i
].cbData
;
2848 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2849 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2852 *pcbEncoded
= bytesNeeded
;
2857 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2858 pcbEncoded
, bytesNeeded
)))
2860 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2861 pbEncoded
= *(BYTE
**)pbEncoded
;
2862 *pbEncoded
++ = ASN_SEQUENCEOF
;
2863 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2864 pbEncoded
+= lenBytes
;
2865 for (i
= 0; i
< seq
->cValue
; i
++)
2867 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2868 seq
->rgValue
[i
].cbData
);
2869 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2876 SetLastError(STATUS_ACCESS_VIOLATION
);
2883 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2884 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2887 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2888 struct AsnConstructedItem constructed
= { 0 };
2889 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2890 DWORD cItem
= 0, cSwapped
= 0;
2892 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2894 case CRL_DIST_POINT_NO_NAME
:
2897 case CRL_DIST_POINT_FULL_NAME
:
2898 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2899 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2900 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2901 constructed
.tag
= 0;
2902 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2903 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2904 items
[cItem
].pvStructInfo
= &constructed
;
2905 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2909 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2910 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2916 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2918 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2919 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2920 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2921 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2922 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2926 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2928 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2929 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2930 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2931 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2932 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2937 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2938 pbEncoded
, pcbEncoded
);
2942 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2943 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2944 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2950 const CRL_DIST_POINTS_INFO
*info
=
2951 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2953 if (!info
->cDistPoint
)
2955 SetLastError(E_INVALIDARG
);
2960 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2963 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2967 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2971 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2973 /* Have to propagate index of failing character */
2979 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2980 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2983 *pcbEncoded
= bytesNeeded
;
2988 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2989 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2991 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2992 pbEncoded
= *(BYTE
**)pbEncoded
;
2993 *pbEncoded
++ = ASN_SEQUENCEOF
;
2994 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2995 pbEncoded
+= lenBytes
;
2996 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2998 DWORD len
= dataLen
;
3000 ret
= CRYPT_AsnEncodeDistPoint(
3001 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
3015 SetLastError(STATUS_ACCESS_VIOLATION
);
3022 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3023 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3024 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3030 const CERT_ENHKEY_USAGE
*usage
=
3031 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
3032 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3035 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3037 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3038 usage
->rgpszUsageIdentifier
[i
],
3039 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3041 bytesNeeded
+= size
;
3043 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3044 bytesNeeded
+= 1 + lenBytes
;
3048 *pcbEncoded
= bytesNeeded
;
3051 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3052 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3054 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3055 pbEncoded
= *(BYTE
**)pbEncoded
;
3056 *pbEncoded
++ = ASN_SEQUENCEOF
;
3057 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
3059 pbEncoded
+= lenBytes
;
3060 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3063 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3064 usage
->rgpszUsageIdentifier
[i
],
3065 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
3070 bytesNeeded
-= size
;
3079 SetLastError(STATUS_ACCESS_VIOLATION
);
3086 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3087 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3088 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3094 const CRL_ISSUING_DIST_POINT
*point
=
3095 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3096 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3097 struct AsnConstructedItem constructed
= { 0 };
3098 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3099 DWORD cItem
= 0, cSwapped
= 0;
3102 switch (point
->DistPointName
.dwDistPointNameChoice
)
3104 case CRL_DIST_POINT_NO_NAME
:
3107 case CRL_DIST_POINT_FULL_NAME
:
3108 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3109 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3110 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3111 constructed
.tag
= 0;
3112 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3113 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3114 items
[cItem
].pvStructInfo
= &constructed
;
3115 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3120 SetLastError(E_INVALIDARG
);
3123 if (ret
&& point
->fOnlyContainsUserCerts
)
3125 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3126 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3127 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3128 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3129 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3133 if (ret
&& point
->fOnlyContainsCACerts
)
3135 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3136 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3137 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3138 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3139 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3143 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3145 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3146 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3147 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3148 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3149 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3153 if (ret
&& point
->fIndirectCRL
)
3155 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3156 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3157 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3158 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3159 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3164 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3165 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3169 SetLastError(STATUS_ACCESS_VIOLATION
);
3176 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3177 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3178 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3182 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3183 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3184 struct AsnEncodeSequenceItem items
[] = {
3185 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3186 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3189 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3190 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3195 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3196 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3197 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3201 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3203 SetLastError(E_INVALIDARG
);
3209 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
3211 if (!info
->Issuer
.cbData
)
3212 SetLastError(E_INVALIDARG
);
3215 struct AsnEncodeSequenceItem items
[7] = {
3216 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3217 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3218 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
3221 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3222 DWORD cItem
= 3, cSwapped
= 0;
3224 if (info
->AuthAttrs
.cAttr
)
3226 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3227 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
3228 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3229 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3230 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3234 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
3235 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3237 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3238 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3240 if (info
->UnauthAttrs
.cAttr
)
3242 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
3243 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
3244 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3245 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3246 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3250 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3251 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3256 SetLastError(STATUS_ACCESS_VIOLATION
);
3262 BOOL
CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
3265 struct AsnEncodeSequenceItem items
[7] = {
3266 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
3268 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
3269 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
3270 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
3271 DWORD cItem
= 1, cSwapped
= 0;
3274 if (signedInfo
->cSignerInfo
)
3276 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
3277 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
3278 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_SIGNER_INFO
);
3279 digestAlgorithmsSet
.itemOffset
=
3280 offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
);
3281 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
3282 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
3283 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3286 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
3287 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
3289 if (signedInfo
->cCertEncoded
)
3291 certSet
.cItems
= signedInfo
->cCertEncoded
;
3292 certSet
.items
= signedInfo
->rgCertEncoded
;
3293 certSet
.itemSize
= sizeof(CERT_BLOB
);
3294 certSet
.itemOffset
= 0;
3295 certSet
.encode
= CRYPT_CopyEncodedBlob
;
3296 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
3297 swapped
[cSwapped
].pvStructInfo
= &certSet
;
3298 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3299 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3300 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3304 if (signedInfo
->cCrlEncoded
)
3306 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
3307 crlSet
.items
= signedInfo
->rgCrlEncoded
;
3308 crlSet
.itemSize
= sizeof(CRL_BLOB
);
3309 crlSet
.itemOffset
= 0;
3310 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
3311 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
3312 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
3313 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3314 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3315 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3319 if (ret
&& signedInfo
->cSignerInfo
)
3321 signerSet
.cItems
= signedInfo
->cSignerInfo
;
3322 signerSet
.items
= signedInfo
->rgSignerInfo
;
3323 signerSet
.itemSize
= sizeof(CMSG_SIGNER_INFO
);
3324 signerSet
.itemOffset
= 0;
3325 signerSet
.encode
= CRYPT_AsnEncodePKCSSignerInfo
;
3326 items
[cItem
].pvStructInfo
= &signerSet
;
3327 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
3331 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
3332 items
, cItem
, 0, NULL
, pvData
, pcbData
);
3337 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3338 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
3339 void *pvEncoded
, DWORD
*pcbEncoded
)
3341 static HCRYPTOIDFUNCSET set
= NULL
;
3343 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3344 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3346 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
3347 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
3348 pvEncoded
, pcbEncoded
);
3350 if (!pvEncoded
&& !pcbEncoded
)
3352 SetLastError(ERROR_INVALID_PARAMETER
);
3355 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3356 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3358 SetLastError(ERROR_FILE_NOT_FOUND
);
3362 SetLastError(NOERROR
);
3363 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
3364 *(BYTE
**)pvEncoded
= NULL
;
3365 if (!HIWORD(lpszStructType
))
3367 switch (LOWORD(lpszStructType
))
3369 case (WORD
)X509_CERT
:
3370 encodeFunc
= CRYPT_AsnEncodeCert
;
3372 case (WORD
)X509_CERT_TO_BE_SIGNED
:
3373 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
3375 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
3376 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
3378 case (WORD
)X509_EXTENSIONS
:
3379 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3381 case (WORD
)X509_NAME_VALUE
:
3382 encodeFunc
= CRYPT_AsnEncodeNameValue
;
3384 case (WORD
)X509_NAME
:
3385 encodeFunc
= CRYPT_AsnEncodeName
;
3387 case (WORD
)X509_PUBLIC_KEY_INFO
:
3388 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
3390 case (WORD
)X509_AUTHORITY_KEY_ID
:
3391 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3393 case (WORD
)X509_ALTERNATE_NAME
:
3394 encodeFunc
= CRYPT_AsnEncodeAltName
;
3396 case (WORD
)X509_BASIC_CONSTRAINTS
:
3397 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3399 case (WORD
)X509_BASIC_CONSTRAINTS2
:
3400 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3402 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
3403 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
3405 case (WORD
)X509_UNICODE_NAME
:
3406 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
3408 case (WORD
)PKCS_CONTENT_INFO
:
3409 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
3411 case (WORD
)PKCS_ATTRIBUTE
:
3412 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
3414 case (WORD
)X509_UNICODE_NAME_VALUE
:
3415 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
3417 case (WORD
)X509_OCTET_STRING
:
3418 encodeFunc
= CRYPT_AsnEncodeOctets
;
3420 case (WORD
)X509_BITS
:
3421 case (WORD
)X509_KEY_USAGE
:
3422 encodeFunc
= CRYPT_AsnEncodeBits
;
3424 case (WORD
)X509_INTEGER
:
3425 encodeFunc
= CRYPT_AsnEncodeInt
;
3427 case (WORD
)X509_MULTI_BYTE_INTEGER
:
3428 encodeFunc
= CRYPT_AsnEncodeInteger
;
3430 case (WORD
)X509_MULTI_BYTE_UINT
:
3431 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
3433 case (WORD
)X509_ENUMERATED
:
3434 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3436 case (WORD
)X509_CHOICE_OF_TIME
:
3437 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
3439 case (WORD
)X509_AUTHORITY_KEY_ID2
:
3440 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3442 case (WORD
)X509_SEQUENCE_OF_ANY
:
3443 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
3445 case (WORD
)PKCS_UTC_TIME
:
3446 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3448 case (WORD
)X509_CRL_DIST_POINTS
:
3449 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3451 case (WORD
)X509_ENHANCED_KEY_USAGE
:
3452 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3454 case (WORD
)PKCS_ATTRIBUTES
:
3455 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3457 case (WORD
)X509_ISSUING_DIST_POINT
:
3458 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3460 case (WORD
)PKCS7_SIGNER_INFO
:
3461 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
3464 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
3467 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
3468 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3469 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3470 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3471 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
3472 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3473 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
3474 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3475 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3476 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3477 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3478 encodeFunc
= CRYPT_AsnEncodeBits
;
3479 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3480 encodeFunc
= CRYPT_AsnEncodeOctets
;
3481 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
3482 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3483 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3484 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3485 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
3486 encodeFunc
= CRYPT_AsnEncodeAltName
;
3487 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
3488 encodeFunc
= CRYPT_AsnEncodeAltName
;
3489 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
3490 encodeFunc
= CRYPT_AsnEncodeAltName
;
3491 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
3492 encodeFunc
= CRYPT_AsnEncodeAltName
;
3493 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
3494 encodeFunc
= CRYPT_AsnEncodeAltName
;
3495 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
3496 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3497 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
3498 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3499 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
3500 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3502 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3503 debugstr_a(lpszStructType
));
3507 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
3508 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3509 (void **)&encodeFunc
, &hFunc
);
3512 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
3513 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
3515 SetLastError(ERROR_FILE_NOT_FOUND
);
3517 CryptFreeOIDFunctionAddress(hFunc
, 0);
3521 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
3522 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3524 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3525 NULL
, 0, NULL
, pInfo
, pcbInfo
);
3528 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
3529 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3530 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3534 static CHAR oid
[] = szOID_RSA_RSA
;
3536 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3537 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3540 if (!pszPublicKeyObjId
)
3541 pszPublicKeyObjId
= oid
;
3542 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
3546 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
3549 LPBYTE pubKey
= CryptMemAlloc(keySize
);
3553 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
3557 DWORD encodedLen
= 0;
3559 ret
= CryptEncodeObject(dwCertEncodingType
,
3560 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
3563 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
3564 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
3567 *pcbInfo
= sizeNeeded
;
3568 else if (*pcbInfo
< sizeNeeded
)
3570 SetLastError(ERROR_MORE_DATA
);
3571 *pcbInfo
= sizeNeeded
;
3576 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
3577 sizeof(CERT_PUBLIC_KEY_INFO
);
3578 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
3580 pInfo
->Algorithm
.Parameters
.cbData
= 0;
3581 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
3582 pInfo
->PublicKey
.pbData
=
3583 (BYTE
*)pInfo
->Algorithm
.pszObjId
3584 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
3585 pInfo
->PublicKey
.cbData
= encodedLen
;
3586 pInfo
->PublicKey
.cUnusedBits
= 0;
3587 ret
= CryptEncodeObject(dwCertEncodingType
,
3588 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
3589 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
3593 CryptMemFree(pubKey
);
3598 CryptDestroyKey(key
);
3603 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
3604 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3605 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
3607 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
3608 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
3609 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3611 static HCRYPTOIDFUNCSET set
= NULL
;
3613 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
3614 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3616 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3617 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3622 SetLastError(ERROR_INVALID_PARAMETER
);
3626 if (pszPublicKeyObjId
)
3629 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
3631 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
3632 0, (void **)&exportFunc
, &hFunc
);
3635 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
3636 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3637 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
3639 CryptFreeOIDFunctionAddress(hFunc
, 0);
3643 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
3644 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
3646 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
3650 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3651 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3652 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3655 DWORD pubKeySize
= 0;
3657 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3658 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3660 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3661 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
3664 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
3668 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3669 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
3672 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
3674 CryptMemFree(pubKey
);
3682 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3683 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3684 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
3686 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3687 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3688 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3690 static HCRYPTOIDFUNCSET set
= NULL
;
3692 ImportPublicKeyInfoExFunc importFunc
= NULL
;
3693 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3695 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3696 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3699 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
3700 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
3701 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
3703 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
3704 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
3707 CryptFreeOIDFunctionAddress(hFunc
, 0);