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
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
54 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
56 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
57 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
59 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
60 * The dwCertEncodingType and lpszStructType are ignored by the built-in
61 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
62 * since it must call functions in external DLLs that follow these signatures.
64 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
65 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
66 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
67 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
68 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
69 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
70 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
71 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
72 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
73 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
74 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
75 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
76 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
77 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
78 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
79 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
80 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
81 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
82 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
83 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
84 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
85 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
86 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
87 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
88 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
89 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
90 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
91 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
92 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
93 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
94 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
95 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
96 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
97 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
98 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
99 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
101 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
102 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
104 static HCRYPTOIDFUNCSET set
= NULL
;
106 HCRYPTOIDFUNCADDR hFunc
;
107 CryptEncodeObjectFunc pCryptEncodeObject
;
109 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
110 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
113 if (!pbEncoded
&& !pcbEncoded
)
115 SetLastError(ERROR_INVALID_PARAMETER
);
119 /* Try registered DLL first.. */
121 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
122 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
123 (void **)&pCryptEncodeObject
, &hFunc
);
124 if (pCryptEncodeObject
)
126 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
127 pvStructInfo
, pbEncoded
, pcbEncoded
);
128 CryptFreeOIDFunctionAddress(hFunc
, 0);
132 /* If not, use CryptEncodeObjectEx */
133 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
134 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
139 /* Helper function to check *pcbEncoded, set it to the required size, and
140 * optionally to allocate memory. Assumes pbEncoded is not NULL.
141 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
142 * pointer to the newly allocated memory.
144 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
145 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
150 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
152 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
153 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
155 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
156 if (!*(BYTE
**)pbEncoded
)
159 *pcbEncoded
= bytesNeeded
;
161 else if (bytesNeeded
> *pcbEncoded
)
163 *pcbEncoded
= bytesNeeded
;
164 SetLastError(ERROR_MORE_DATA
);
168 *pcbEncoded
= bytesNeeded
;
172 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
174 DWORD bytesNeeded
, significantBytes
= 0;
182 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
183 temp
<<= 8, significantBytes
--)
185 bytesNeeded
= significantBytes
+ 1;
189 *pcbEncoded
= bytesNeeded
;
192 if (*pcbEncoded
< bytesNeeded
)
194 SetLastError(ERROR_MORE_DATA
);
198 *pbEncoded
= (BYTE
)len
;
203 *pbEncoded
++ = significantBytes
| 0x80;
204 for (i
= 0; i
< significantBytes
; i
++)
206 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
210 *pcbEncoded
= bytesNeeded
;
214 struct AsnEncodeSequenceItem
216 const void *pvStructInfo
;
217 CryptEncodeObjectExFunc encodeFunc
;
218 DWORD size
; /* used during encoding, not for your use */
221 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
222 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
223 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
226 DWORD i
, dataLen
= 0;
228 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
229 pbEncoded
, *pcbEncoded
);
230 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
232 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
233 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
234 NULL
, &items
[i
].size
);
235 /* Some functions propagate their errors through the size */
237 *pcbEncoded
= items
[i
].size
;
238 dataLen
+= items
[i
].size
;
242 DWORD lenBytes
, bytesNeeded
;
244 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
245 bytesNeeded
= 1 + lenBytes
+ dataLen
;
247 *pcbEncoded
= bytesNeeded
;
250 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
251 pcbEncoded
, bytesNeeded
)))
253 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
254 pbEncoded
= *(BYTE
**)pbEncoded
;
255 *pbEncoded
++ = ASN_SEQUENCE
;
256 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
257 pbEncoded
+= lenBytes
;
258 for (i
= 0; ret
&& i
< cItem
; i
++)
260 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
261 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
262 NULL
, pbEncoded
, &items
[i
].size
);
263 /* Some functions propagate their errors through the size */
265 *pcbEncoded
= items
[i
].size
;
266 pbEncoded
+= items
[i
].size
;
271 TRACE("returning %d (%08x)\n", ret
, GetLastError());
275 struct AsnConstructedItem
278 const void *pvStructInfo
;
279 CryptEncodeObjectExFunc encodeFunc
;
282 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
283 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
284 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
287 const struct AsnConstructedItem
*item
=
288 (const struct AsnConstructedItem
*)pvStructInfo
;
291 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
292 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
294 DWORD dataLen
, bytesNeeded
;
296 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
297 bytesNeeded
= 1 + dataLen
+ len
;
299 *pcbEncoded
= bytesNeeded
;
300 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
301 pbEncoded
, pcbEncoded
, bytesNeeded
)))
303 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
304 pbEncoded
= *(BYTE
**)pbEncoded
;
305 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
306 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
307 pbEncoded
+= dataLen
;
308 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
309 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
313 /* Some functions propagate their errors through the size */
320 /* Some functions propagate their errors through the size */
326 struct AsnEncodeTagSwappedItem
329 const void *pvStructInfo
;
330 CryptEncodeObjectExFunc encodeFunc
;
333 /* Sort of a wacky hack, it encodes something using the struct
334 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
335 * given in the struct AsnEncodeTagSwappedItem.
337 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
338 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
339 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
342 const struct AsnEncodeTagSwappedItem
*item
=
343 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
345 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
346 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
347 if (ret
&& pbEncoded
)
348 *pbEncoded
= item
->tag
;
352 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
353 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
354 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
356 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
359 /* CERT_V1 is not encoded */
367 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
369 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
370 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
375 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
376 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
377 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
379 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
384 *pcbEncoded
= blob
->cbData
;
389 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
390 pcbEncoded
, blob
->cbData
)))
392 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
393 pbEncoded
= *(BYTE
**)pbEncoded
;
395 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
396 *pcbEncoded
= blob
->cbData
;
403 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
404 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
405 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
408 /* This has two filetimes in a row, a NotBefore and a NotAfter */
409 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
410 struct AsnEncodeSequenceItem items
[] = {
411 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
412 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
415 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
416 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
421 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
422 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
423 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
426 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
427 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
429 struct AsnEncodeSequenceItem items
[] = {
430 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
431 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
434 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
435 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
440 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
441 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
442 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
448 const CERT_PUBLIC_KEY_INFO
*info
=
449 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
450 struct AsnEncodeSequenceItem items
[] = {
451 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
452 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
455 TRACE("Encoding public key with OID %s\n",
456 debugstr_a(info
->Algorithm
.pszObjId
));
457 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
458 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
463 SetLastError(STATUS_ACCESS_VIOLATION
);
470 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
471 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
472 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
478 const CERT_SIGNED_CONTENT_INFO
*info
=
479 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
480 struct AsnEncodeSequenceItem items
[] = {
481 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
482 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
483 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
486 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
487 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
488 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
489 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
494 SetLastError(STATUS_ACCESS_VIOLATION
);
501 /* Like in Windows, this blithely ignores the validity of the passed-in
502 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
503 * decode properly, see CRYPT_AsnDecodeCertInfo.
505 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
506 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
507 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
513 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
514 struct AsnEncodeSequenceItem items
[10] = {
515 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
516 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
517 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
518 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
519 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
520 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
521 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
524 struct AsnConstructedItem constructed
[3] = { { 0 } };
525 DWORD cItem
= 7, cConstructed
= 0;
527 if (info
->IssuerUniqueId
.cbData
)
529 constructed
[cConstructed
].tag
= 1;
530 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
531 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
532 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
533 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
537 if (info
->SubjectUniqueId
.cbData
)
539 constructed
[cConstructed
].tag
= 2;
540 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
541 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
542 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
543 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
547 if (info
->cExtension
)
549 constructed
[cConstructed
].tag
= 3;
550 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
551 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
552 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
553 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
558 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
559 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
563 SetLastError(STATUS_ACCESS_VIOLATION
);
570 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
571 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
573 struct AsnEncodeSequenceItem items
[3] = {
574 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
575 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
581 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
583 if (entry
->cExtension
)
585 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
586 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
590 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
591 pbEncoded
, pcbEncoded
);
593 TRACE("returning %d (%08x)\n", ret
, GetLastError());
597 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
598 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
599 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
601 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
602 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
603 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
604 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
607 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
611 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
615 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
616 bytesNeeded
= 1 + lenBytes
+ dataLen
;
618 *pcbEncoded
= bytesNeeded
;
621 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
622 pcbEncoded
, bytesNeeded
)))
624 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
625 pbEncoded
= *(BYTE
**)pbEncoded
;
626 *pbEncoded
++ = ASN_SEQUENCEOF
;
627 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
628 pbEncoded
+= lenBytes
;
629 for (i
= 0; i
< cCRLEntry
; i
++)
631 DWORD size
= dataLen
;
633 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
642 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
643 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
644 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
646 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
649 /* CRL_V1 is not encoded */
656 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
657 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
661 /* Like in Windows, this blithely ignores the validity of the passed-in
662 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
663 * decode properly, see CRYPT_AsnDecodeCRLInfo.
665 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
666 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
667 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
673 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
674 struct AsnEncodeSequenceItem items
[7] = {
675 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
676 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
677 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
678 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
681 struct AsnConstructedItem constructed
[1] = { { 0 } };
682 DWORD cItem
= 4, cConstructed
= 0;
684 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
686 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
687 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
692 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
693 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
696 if (info
->cExtension
)
698 constructed
[cConstructed
].tag
= 0;
699 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
700 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
701 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
702 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
707 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
708 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
712 SetLastError(STATUS_ACCESS_VIOLATION
);
719 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
723 struct AsnEncodeSequenceItem items
[3] = {
724 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
730 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
734 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
735 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
738 items
[cItem
].pvStructInfo
= &ext
->Value
;
739 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
742 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
743 pbEncoded
, pcbEncoded
);
744 TRACE("returning %d (%08x)\n", ret
, GetLastError());
748 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
749 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
750 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
756 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
757 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
760 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
764 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
768 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
769 bytesNeeded
= 1 + lenBytes
+ dataLen
;
771 *pcbEncoded
= bytesNeeded
;
774 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
775 pcbEncoded
, bytesNeeded
)))
777 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
778 pbEncoded
= *(BYTE
**)pbEncoded
;
779 *pbEncoded
++ = ASN_SEQUENCEOF
;
780 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
781 pbEncoded
+= lenBytes
;
782 for (i
= 0; i
< exts
->cExtension
; i
++)
784 DWORD size
= dataLen
;
786 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
796 SetLastError(STATUS_ACCESS_VIOLATION
);
803 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
804 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
805 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
807 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
808 DWORD bytesNeeded
= 0, lenBytes
;
813 TRACE("%s\n", debugstr_a(pszObjId
));
820 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
822 SetLastError(CRYPT_E_ASN1_ERROR
);
826 firstByte
= val1
* 40 + val2
;
827 ptr
= pszObjId
+ firstPos
;
832 /* note I assume each component is at most 32-bits long in base 2 */
833 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
835 if (val1
>= 0x10000000)
837 else if (val1
>= 0x200000)
839 else if (val1
>= 0x4000)
841 else if (val1
>= 0x80)
851 SetLastError(CRYPT_E_ASN1_ERROR
);
855 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
859 bytesNeeded
+= 1 + lenBytes
;
862 if (*pcbEncoded
< bytesNeeded
)
864 SetLastError(ERROR_MORE_DATA
);
869 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
870 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
871 pbEncoded
+= lenBytes
;
877 *pbEncoded
++ = firstByte
;
878 ptr
= pszObjId
+ firstPos
;
881 sscanf(ptr
, "%d%n", &val
, &pos
);
883 unsigned char outBytes
[5];
886 if (val
>= 0x10000000)
888 else if (val
>= 0x200000)
890 else if (val
>= 0x4000)
892 else if (val
>= 0x80)
896 for (i
= numBytes
; i
> 0; i
--)
898 outBytes
[i
- 1] = val
& 0x7f;
901 for (i
= 0; i
< numBytes
- 1; i
++)
902 *pbEncoded
++ = outBytes
[i
] | 0x80;
903 *pbEncoded
++ = outBytes
[i
];
912 *pcbEncoded
= bytesNeeded
;
916 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
917 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
921 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
922 DWORD bytesNeeded
, lenBytes
, encodedLen
;
924 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: lstrlenA(str
);
925 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
926 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
928 *pcbEncoded
= bytesNeeded
;
931 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
932 pbEncoded
, pcbEncoded
, bytesNeeded
)))
934 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
935 pbEncoded
= *(BYTE
**)pbEncoded
;
937 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
938 pbEncoded
+= lenBytes
;
939 memcpy(pbEncoded
, str
, encodedLen
);
945 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
946 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
950 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
951 DWORD bytesNeeded
, lenBytes
, strLen
;
953 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
955 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
956 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
958 *pcbEncoded
= bytesNeeded
;
961 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
962 pbEncoded
, pcbEncoded
, bytesNeeded
)))
966 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
967 pbEncoded
= *(BYTE
**)pbEncoded
;
968 *pbEncoded
++ = ASN_BMPSTRING
;
969 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
970 pbEncoded
+= lenBytes
;
971 for (i
= 0; i
< strLen
; i
++)
973 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
974 *pbEncoded
++ = str
[i
] & 0x00ff;
981 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
982 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
986 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
987 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
989 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
991 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
993 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
994 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
996 *pcbEncoded
= bytesNeeded
;
999 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1000 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1002 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1003 pbEncoded
= *(BYTE
**)pbEncoded
;
1004 *pbEncoded
++ = ASN_UTF8STRING
;
1005 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1006 pbEncoded
+= lenBytes
;
1007 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
1008 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
1014 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1015 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1016 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1022 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1024 switch (value
->dwValueType
)
1026 case CERT_RDN_ANY_TYPE
:
1027 /* explicitly disallowed */
1028 SetLastError(E_INVALIDARG
);
1031 case CERT_RDN_ENCODED_BLOB
:
1032 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1033 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1035 case CERT_RDN_OCTET_STRING
:
1036 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1037 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1039 case CERT_RDN_NUMERIC_STRING
:
1040 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1041 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1043 case CERT_RDN_PRINTABLE_STRING
:
1044 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1045 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1047 case CERT_RDN_TELETEX_STRING
:
1048 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1049 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1051 case CERT_RDN_VIDEOTEX_STRING
:
1052 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1053 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1055 case CERT_RDN_IA5_STRING
:
1056 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1057 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1059 case CERT_RDN_GRAPHIC_STRING
:
1060 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1061 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1063 case CERT_RDN_VISIBLE_STRING
:
1064 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1065 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1067 case CERT_RDN_GENERAL_STRING
:
1068 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1069 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1071 case CERT_RDN_UNIVERSAL_STRING
:
1072 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1073 SetLastError(CRYPT_E_ASN1_CHOICE
);
1076 case CERT_RDN_BMP_STRING
:
1077 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1078 pbEncoded
, pcbEncoded
);
1080 case CERT_RDN_UTF8_STRING
:
1081 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1082 pbEncoded
, pcbEncoded
);
1085 SetLastError(CRYPT_E_ASN1_CHOICE
);
1091 SetLastError(STATUS_ACCESS_VIOLATION
);
1098 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1099 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1100 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1102 DWORD bytesNeeded
= 0, lenBytes
, size
;
1105 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1106 0, NULL
, NULL
, &size
);
1109 bytesNeeded
+= size
;
1110 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1111 * with dwValueType, so "cast" it to get its encoded size
1113 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1114 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1117 bytesNeeded
+= size
;
1118 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1119 bytesNeeded
+= 1 + lenBytes
;
1122 if (*pcbEncoded
< bytesNeeded
)
1124 SetLastError(ERROR_MORE_DATA
);
1129 *pbEncoded
++ = ASN_SEQUENCE
;
1130 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1132 pbEncoded
+= lenBytes
;
1133 size
= bytesNeeded
- 1 - lenBytes
;
1134 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1135 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1139 size
= bytesNeeded
- 1 - lenBytes
- size
;
1140 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1141 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1142 0, NULL
, pbEncoded
, &size
);
1149 *pcbEncoded
= bytesNeeded
;
1153 /* Have to propagate index of failing character */
1160 static int BLOBComp(const void *l
, const void *r
)
1162 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1165 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1166 ret
= a
->cbData
- b
->cbData
;
1170 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1172 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1173 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1177 CRYPT_DER_BLOB
*blobs
= NULL
;
1181 DWORD bytesNeeded
= 0, lenBytes
, i
;
1187 blobs
= CryptMemAlloc(rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1191 memset(blobs
, 0, rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1193 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1195 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1196 nameValueEncodeFunc
, NULL
, &blobs
[i
].cbData
);
1198 bytesNeeded
+= blobs
[i
].cbData
;
1201 /* Have to propagate index of failing character */
1202 *pcbEncoded
= blobs
[i
].cbData
;
1207 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1208 bytesNeeded
+= 1 + lenBytes
;
1211 if (*pcbEncoded
< bytesNeeded
)
1213 SetLastError(ERROR_MORE_DATA
);
1218 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1220 blobs
[i
].pbData
= CryptMemAlloc(blobs
[i
].cbData
);
1221 if (!blobs
[i
].pbData
)
1225 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1226 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1227 blobs
[i
].pbData
, &blobs
[i
].cbData
);
1229 *pcbEncoded
= blobs
[i
].cbData
;
1234 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1236 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1237 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1239 pbEncoded
+= lenBytes
;
1240 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1242 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1243 pbEncoded
+= blobs
[i
].cbData
;
1249 *pcbEncoded
= bytesNeeded
;
1253 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1254 CryptMemFree(blobs
[i
].pbData
);
1259 SetLastError(STATUS_ACCESS_VIOLATION
);
1263 CryptMemFree(blobs
);
1267 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1268 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1269 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1271 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1272 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1273 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1276 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1279 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1280 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1281 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1283 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1284 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1288 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1289 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1290 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1296 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1297 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1299 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1301 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1303 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1304 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1306 bytesNeeded
+= size
;
1310 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1311 bytesNeeded
+= 1 + lenBytes
;
1315 *pcbEncoded
= bytesNeeded
;
1318 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1319 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1321 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1322 pbEncoded
= *(BYTE
**)pbEncoded
;
1323 *pbEncoded
++ = ASN_SEQUENCEOF
;
1324 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1326 pbEncoded
+= lenBytes
;
1327 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1330 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1331 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1336 bytesNeeded
-= size
;
1347 SetLastError(STATUS_ACCESS_VIOLATION
);
1354 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1355 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1359 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1360 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1362 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1364 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1365 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1367 *pcbEncoded
= bytesNeeded
;
1370 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1371 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1375 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1376 pbEncoded
= *(BYTE
**)pbEncoded
;
1378 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1379 pbEncoded
+= lenBytes
;
1380 for (i
= 0; i
< encodedLen
; i
++)
1381 *pbEncoded
++ = (BYTE
)str
[i
];
1387 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1388 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1392 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1393 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1395 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1397 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1398 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1400 *pcbEncoded
= bytesNeeded
;
1403 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1404 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1408 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1409 pbEncoded
= *(BYTE
**)pbEncoded
;
1410 *pbEncoded
++ = ASN_NUMERICSTRING
;
1411 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1412 pbEncoded
+= lenBytes
;
1413 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1415 if (isdigitW(str
[i
]))
1416 *pbEncoded
++ = (BYTE
)str
[i
];
1420 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1429 static inline int isprintableW(WCHAR wc
)
1431 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1432 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1433 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1436 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1437 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1441 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1442 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1444 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1446 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1447 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1449 *pcbEncoded
= bytesNeeded
;
1452 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1453 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1457 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1458 pbEncoded
= *(BYTE
**)pbEncoded
;
1459 *pbEncoded
++ = ASN_PRINTABLESTRING
;
1460 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1461 pbEncoded
+= lenBytes
;
1462 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1464 if (isprintableW(str
[i
]))
1465 *pbEncoded
++ = (BYTE
)str
[i
];
1469 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1478 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1479 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1483 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1484 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1486 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1488 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1489 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1491 *pcbEncoded
= bytesNeeded
;
1494 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1495 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1499 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1500 pbEncoded
= *(BYTE
**)pbEncoded
;
1501 *pbEncoded
++ = ASN_IA5STRING
;
1502 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1503 pbEncoded
+= lenBytes
;
1504 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1507 *pbEncoded
++ = (BYTE
)str
[i
];
1511 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1520 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
1521 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1525 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1526 DWORD bytesNeeded
, lenBytes
, strLen
;
1528 /* FIXME: doesn't handle composite characters */
1529 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1531 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
1532 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
1534 *pcbEncoded
= bytesNeeded
;
1537 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1538 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1542 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1543 pbEncoded
= *(BYTE
**)pbEncoded
;
1544 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
1545 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
1546 pbEncoded
+= lenBytes
;
1547 for (i
= 0; i
< strLen
; i
++)
1551 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
1552 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
1559 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1560 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1561 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1567 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1569 switch (value
->dwValueType
)
1571 case CERT_RDN_ANY_TYPE
:
1572 case CERT_RDN_ENCODED_BLOB
:
1573 case CERT_RDN_OCTET_STRING
:
1574 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
1576 case CERT_RDN_NUMERIC_STRING
:
1577 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
1578 pbEncoded
, pcbEncoded
);
1580 case CERT_RDN_PRINTABLE_STRING
:
1581 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
1582 pbEncoded
, pcbEncoded
);
1584 case CERT_RDN_TELETEX_STRING
:
1585 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
1586 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1588 case CERT_RDN_VIDEOTEX_STRING
:
1589 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
1590 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1592 case CERT_RDN_IA5_STRING
:
1593 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
1594 pbEncoded
, pcbEncoded
);
1596 case CERT_RDN_GRAPHIC_STRING
:
1597 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1598 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1600 case CERT_RDN_VISIBLE_STRING
:
1601 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
1602 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1604 case CERT_RDN_GENERAL_STRING
:
1605 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
1606 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1608 case CERT_RDN_UNIVERSAL_STRING
:
1609 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
1610 pbEncoded
, pcbEncoded
);
1612 case CERT_RDN_BMP_STRING
:
1613 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1614 pbEncoded
, pcbEncoded
);
1616 case CERT_RDN_UTF8_STRING
:
1617 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1618 pbEncoded
, pcbEncoded
);
1621 SetLastError(CRYPT_E_ASN1_CHOICE
);
1626 SetLastError(STATUS_ACCESS_VIOLATION
);
1632 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1633 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1634 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1640 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1641 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1643 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1645 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1647 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1648 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
1650 bytesNeeded
+= size
;
1652 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1653 bytesNeeded
+= 1 + lenBytes
;
1657 *pcbEncoded
= bytesNeeded
;
1660 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1661 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1663 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1664 pbEncoded
= *(BYTE
**)pbEncoded
;
1665 *pbEncoded
++ = ASN_SEQUENCEOF
;
1666 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1668 pbEncoded
+= lenBytes
;
1669 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1672 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1673 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
1678 bytesNeeded
-= size
;
1687 SetLastError(STATUS_ACCESS_VIOLATION
);
1694 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1695 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1696 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1698 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1707 else if (*pcbEncoded
< 3)
1710 SetLastError(ERROR_MORE_DATA
);
1716 *pbEncoded
++ = ASN_BOOL
;
1718 *pbEncoded
++ = val
? 0xff : 0;
1721 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1725 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1726 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1732 switch (entry
->dwAltNameChoice
)
1734 case CERT_ALT_NAME_RFC822_NAME
:
1735 case CERT_ALT_NAME_DNS_NAME
:
1736 case CERT_ALT_NAME_URL
:
1737 if (entry
->u
.pwszURL
)
1741 /* Not + 1: don't encode the NULL-terminator */
1742 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1743 for (i
= 0; ret
&& i
< dataLen
; i
++)
1745 if (entry
->u
.pwszURL
[i
] > 0x7f)
1747 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1756 case CERT_ALT_NAME_IP_ADDRESS
:
1757 dataLen
= entry
->u
.IPAddress
.cbData
;
1759 case CERT_ALT_NAME_REGISTERED_ID
:
1760 /* FIXME: encode OID */
1761 case CERT_ALT_NAME_OTHER_NAME
:
1762 case CERT_ALT_NAME_DIRECTORY_NAME
:
1763 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
1766 SetLastError(E_INVALIDARG
);
1771 DWORD bytesNeeded
, lenBytes
;
1773 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1774 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1776 *pcbEncoded
= bytesNeeded
;
1777 else if (*pcbEncoded
< bytesNeeded
)
1779 SetLastError(ERROR_MORE_DATA
);
1780 *pcbEncoded
= bytesNeeded
;
1785 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1786 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1787 pbEncoded
+= lenBytes
;
1788 switch (entry
->dwAltNameChoice
)
1790 case CERT_ALT_NAME_RFC822_NAME
:
1791 case CERT_ALT_NAME_DNS_NAME
:
1792 case CERT_ALT_NAME_URL
:
1796 for (i
= 0; i
< dataLen
; i
++)
1797 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1800 case CERT_ALT_NAME_IP_ADDRESS
:
1801 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1805 *pcbEncoded
= bytesNeeded
;
1808 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1812 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
1813 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1814 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1820 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
1821 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
1822 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
1823 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
1824 struct AsnConstructedItem constructed
= { 0 };
1825 DWORD cItem
= 0, cSwapped
= 0;
1827 if (info
->KeyId
.cbData
)
1829 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
1830 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
1831 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1832 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
1833 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
1837 if (info
->CertIssuer
.cbData
)
1839 constructed
.tag
= 1;
1840 constructed
.pvStructInfo
= &info
->CertIssuer
;
1841 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1842 items
[cItem
].pvStructInfo
= &constructed
;
1843 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1846 if (info
->CertSerialNumber
.cbData
)
1848 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
1849 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
1850 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1851 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
1852 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
1856 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
1857 pEncodePara
, pbEncoded
, pcbEncoded
);
1861 SetLastError(STATUS_ACCESS_VIOLATION
);
1868 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1869 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1870 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1876 const CERT_ALT_NAME_INFO
*info
=
1877 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1878 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1881 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1882 * can't encode an erroneous entry index if it's bigger than this.
1884 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1888 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1892 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1894 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1895 * the bad character, now set the index of the bad
1898 *pcbEncoded
= (BYTE
)i
<<
1899 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1904 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1905 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1908 *pcbEncoded
= bytesNeeded
;
1913 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1914 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1916 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1917 pbEncoded
= *(BYTE
**)pbEncoded
;
1918 *pbEncoded
++ = ASN_SEQUENCEOF
;
1919 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1920 pbEncoded
+= lenBytes
;
1921 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1923 DWORD len
= dataLen
;
1925 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1939 SetLastError(STATUS_ACCESS_VIOLATION
);
1946 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
1947 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1948 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1954 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
1955 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
1956 struct AsnEncodeSequenceItem items
[3] = {
1957 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
1962 if (info
->fPathLenConstraint
)
1964 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1965 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1968 if (info
->cSubtreesConstraint
)
1970 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
1971 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
1974 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1975 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1979 SetLastError(STATUS_ACCESS_VIOLATION
);
1986 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1987 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1988 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1994 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1995 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1996 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2001 items
[cItem
].pvStructInfo
= &info
->fCA
;
2002 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2005 if (info
->fPathLenConstraint
)
2007 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2008 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2011 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2012 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2016 SetLastError(STATUS_ACCESS_VIOLATION
);
2023 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2024 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2025 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2031 const BLOBHEADER
*hdr
=
2032 (const BLOBHEADER
*)pvStructInfo
;
2034 if (hdr
->bType
!= PUBLICKEYBLOB
)
2036 SetLastError(E_INVALIDARG
);
2041 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2042 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2043 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2044 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2045 struct AsnEncodeSequenceItem items
[] = {
2046 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2047 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2050 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2051 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2057 SetLastError(STATUS_ACCESS_VIOLATION
);
2064 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2065 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2066 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2072 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2073 DWORD bytesNeeded
, lenBytes
;
2075 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2076 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2078 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2079 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2082 *pcbEncoded
= bytesNeeded
;
2087 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2088 pcbEncoded
, bytesNeeded
)))
2090 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2091 pbEncoded
= *(BYTE
**)pbEncoded
;
2092 *pbEncoded
++ = ASN_OCTETSTRING
;
2093 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2094 pbEncoded
+= lenBytes
;
2096 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2102 SetLastError(STATUS_ACCESS_VIOLATION
);
2106 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2110 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2111 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2112 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2118 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2119 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2122 /* yep, MS allows cUnusedBits to be >= 8 */
2123 if (!blob
->cUnusedBits
)
2125 dataBytes
= blob
->cbData
;
2128 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2130 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2131 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2139 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2140 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2143 *pcbEncoded
= bytesNeeded
;
2148 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2149 pcbEncoded
, bytesNeeded
)))
2151 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2152 pbEncoded
= *(BYTE
**)pbEncoded
;
2153 *pbEncoded
++ = ASN_BITSTRING
;
2154 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2155 pbEncoded
+= lenBytes
;
2156 *pbEncoded
++ = unusedBits
;
2159 BYTE mask
= 0xff << unusedBits
;
2163 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2164 pbEncoded
+= dataBytes
- 1;
2166 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2173 SetLastError(STATUS_ACCESS_VIOLATION
);
2180 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2181 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2182 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2188 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2189 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2194 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2199 for (i
= 0; i
< newBlob
.cbData
; i
++)
2200 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2206 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2207 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2208 CryptMemFree(newBlob
.pbData
);
2212 SetLastError(STATUS_ACCESS_VIOLATION
);
2219 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2220 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2221 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2223 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2225 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2226 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2229 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2230 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2231 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2237 DWORD significantBytes
, lenBytes
;
2238 BYTE padByte
= 0, bytesNeeded
;
2240 const CRYPT_INTEGER_BLOB
*blob
=
2241 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2243 significantBytes
= blob
->cbData
;
2244 if (significantBytes
)
2246 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2248 /* negative, lop off leading (little-endian) 0xffs */
2249 for (; significantBytes
> 0 &&
2250 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2252 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2260 /* positive, lop off leading (little-endian) zeroes */
2261 for (; significantBytes
> 0 &&
2262 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2264 if (significantBytes
== 0)
2265 significantBytes
= 1;
2266 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2274 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2276 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2277 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2282 *pcbEncoded
= bytesNeeded
;
2287 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2288 pcbEncoded
, bytesNeeded
)))
2290 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2291 pbEncoded
= *(BYTE
**)pbEncoded
;
2292 *pbEncoded
++ = ASN_INTEGER
;
2295 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2296 pbEncoded
+= lenBytes
;
2297 *pbEncoded
++ = padByte
;
2301 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2302 pbEncoded
+= lenBytes
;
2304 for (; significantBytes
> 0; significantBytes
--)
2305 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2311 SetLastError(STATUS_ACCESS_VIOLATION
);
2318 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
2319 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2320 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2326 DWORD significantBytes
, lenBytes
;
2329 const CRYPT_INTEGER_BLOB
*blob
=
2330 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2332 significantBytes
= blob
->cbData
;
2333 if (significantBytes
)
2335 /* positive, lop off leading (little-endian) zeroes */
2336 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2339 if (significantBytes
== 0)
2340 significantBytes
= 1;
2341 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2345 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2347 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2348 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2353 *pcbEncoded
= bytesNeeded
;
2358 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2359 pcbEncoded
, bytesNeeded
)))
2361 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2362 pbEncoded
= *(BYTE
**)pbEncoded
;
2363 *pbEncoded
++ = ASN_INTEGER
;
2366 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2367 pbEncoded
+= lenBytes
;
2372 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2373 pbEncoded
+= lenBytes
;
2375 for (; significantBytes
> 0; significantBytes
--)
2376 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2382 SetLastError(STATUS_ACCESS_VIOLATION
);
2389 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2390 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2391 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2393 CRYPT_INTEGER_BLOB blob
;
2396 /* Encode as an unsigned integer, then change the tag to enumerated */
2397 blob
.cbData
= sizeof(DWORD
);
2398 blob
.pbData
= (BYTE
*)pvStructInfo
;
2399 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2400 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2401 if (ret
&& pbEncoded
)
2403 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2404 pbEncoded
= *(BYTE
**)pbEncoded
;
2405 pbEncoded
[0] = ASN_ENUMERATED
;
2410 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2411 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2412 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2419 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2420 * temporary buffer because the output buffer is not NULL-terminated.
2423 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2427 *pcbEncoded
= bytesNeeded
;
2432 /* Sanity check the year, this is a two-digit year format */
2433 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2435 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2437 SetLastError(CRYPT_E_BAD_ENCODE
);
2442 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2443 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2445 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2446 pbEncoded
= *(BYTE
**)pbEncoded
;
2447 buf
[0] = ASN_UTCTIME
;
2448 buf
[1] = bytesNeeded
- 2;
2449 snprintf(buf
+ 2, sizeof(buf
) - 2,
2450 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2451 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2452 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2453 sysTime
.wMinute
, sysTime
.wSecond
);
2454 memcpy(pbEncoded
, buf
, bytesNeeded
);
2461 SetLastError(STATUS_ACCESS_VIOLATION
);
2468 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2469 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2470 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2477 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2478 * temporary buffer because the output buffer is not NULL-terminated.
2481 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2485 *pcbEncoded
= bytesNeeded
;
2490 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2493 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2494 pcbEncoded
, bytesNeeded
);
2497 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2498 pbEncoded
= *(BYTE
**)pbEncoded
;
2499 buf
[0] = ASN_GENERALTIME
;
2500 buf
[1] = bytesNeeded
- 2;
2501 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2502 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2503 sysTime
.wMinute
, sysTime
.wSecond
);
2504 memcpy(pbEncoded
, buf
, bytesNeeded
);
2510 SetLastError(STATUS_ACCESS_VIOLATION
);
2517 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2518 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2519 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2527 /* Check the year, if it's in the UTCTime range call that encode func */
2528 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2530 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2531 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2532 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2534 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2535 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2540 SetLastError(STATUS_ACCESS_VIOLATION
);
2547 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2548 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2549 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2555 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2556 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2557 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2559 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2560 dataLen
+= seq
->rgValue
[i
].cbData
;
2561 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2562 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2565 *pcbEncoded
= bytesNeeded
;
2570 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2571 pcbEncoded
, bytesNeeded
)))
2573 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2574 pbEncoded
= *(BYTE
**)pbEncoded
;
2575 *pbEncoded
++ = ASN_SEQUENCEOF
;
2576 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2577 pbEncoded
+= lenBytes
;
2578 for (i
= 0; i
< seq
->cValue
; i
++)
2580 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2581 seq
->rgValue
[i
].cbData
);
2582 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2589 SetLastError(STATUS_ACCESS_VIOLATION
);
2596 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2597 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2600 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2601 struct AsnConstructedItem constructed
= { 0 };
2602 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2603 DWORD cItem
= 0, cSwapped
= 0;
2605 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2607 case CRL_DIST_POINT_NO_NAME
:
2610 case CRL_DIST_POINT_FULL_NAME
:
2611 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2612 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2613 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2614 constructed
.tag
= 0;
2615 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2616 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2617 items
[cItem
].pvStructInfo
= &constructed
;
2618 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2622 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2623 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2629 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2631 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2632 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2633 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2634 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2635 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2639 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2641 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2642 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2643 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2644 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2645 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2650 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2651 pbEncoded
, pcbEncoded
);
2655 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2656 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2657 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2663 const CRL_DIST_POINTS_INFO
*info
=
2664 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2666 if (!info
->cDistPoint
)
2668 SetLastError(E_INVALIDARG
);
2673 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2676 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2680 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2684 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2686 /* Have to propagate index of failing character */
2692 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2693 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2696 *pcbEncoded
= bytesNeeded
;
2701 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2702 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2704 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2705 pbEncoded
= *(BYTE
**)pbEncoded
;
2706 *pbEncoded
++ = ASN_SEQUENCEOF
;
2707 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2708 pbEncoded
+= lenBytes
;
2709 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2711 DWORD len
= dataLen
;
2713 ret
= CRYPT_AsnEncodeDistPoint(
2714 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
2728 SetLastError(STATUS_ACCESS_VIOLATION
);
2735 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
2736 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2737 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2743 const CERT_ENHKEY_USAGE
*usage
=
2744 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
2745 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2748 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2750 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2751 usage
->rgpszUsageIdentifier
[i
],
2752 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2754 bytesNeeded
+= size
;
2756 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2757 bytesNeeded
+= 1 + lenBytes
;
2761 *pcbEncoded
= bytesNeeded
;
2764 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2765 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2767 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2768 pbEncoded
= *(BYTE
**)pbEncoded
;
2769 *pbEncoded
++ = ASN_SEQUENCEOF
;
2770 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2772 pbEncoded
+= lenBytes
;
2773 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2776 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2777 usage
->rgpszUsageIdentifier
[i
],
2778 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2783 bytesNeeded
-= size
;
2792 SetLastError(STATUS_ACCESS_VIOLATION
);
2799 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
2800 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2801 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2807 const CRL_ISSUING_DIST_POINT
*point
=
2808 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
2809 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
2810 struct AsnConstructedItem constructed
= { 0 };
2811 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
2812 DWORD cItem
= 0, cSwapped
= 0;
2815 switch (point
->DistPointName
.dwDistPointNameChoice
)
2817 case CRL_DIST_POINT_NO_NAME
:
2820 case CRL_DIST_POINT_FULL_NAME
:
2821 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2822 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
2823 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2824 constructed
.tag
= 0;
2825 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2826 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2827 items
[cItem
].pvStructInfo
= &constructed
;
2828 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2833 SetLastError(E_INVALIDARG
);
2836 if (ret
&& point
->fOnlyContainsUserCerts
)
2838 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2839 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
2840 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
2841 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2842 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2846 if (ret
&& point
->fOnlyContainsCACerts
)
2848 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2849 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
2850 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
2851 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2852 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2856 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
2858 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
2859 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
2860 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2861 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2862 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2866 if (ret
&& point
->fIndirectCRL
)
2868 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
2869 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
2870 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
2871 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2872 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2877 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2878 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2882 SetLastError(STATUS_ACCESS_VIOLATION
);
2889 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2890 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2891 void *pvEncoded
, DWORD
*pcbEncoded
)
2893 static HCRYPTOIDFUNCSET set
= NULL
;
2895 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2896 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2898 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
2899 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2900 pvEncoded
, pcbEncoded
);
2902 if (!pvEncoded
&& !pcbEncoded
)
2904 SetLastError(ERROR_INVALID_PARAMETER
);
2907 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2908 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2910 SetLastError(ERROR_FILE_NOT_FOUND
);
2914 SetLastError(NOERROR
);
2915 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2916 *(BYTE
**)pvEncoded
= NULL
;
2917 if (!HIWORD(lpszStructType
))
2919 switch (LOWORD(lpszStructType
))
2921 case (WORD
)X509_CERT
:
2922 encodeFunc
= CRYPT_AsnEncodeCert
;
2924 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2925 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2927 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2928 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2930 case (WORD
)X509_EXTENSIONS
:
2931 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2933 case (WORD
)X509_NAME_VALUE
:
2934 encodeFunc
= CRYPT_AsnEncodeNameValue
;
2936 case (WORD
)X509_NAME
:
2937 encodeFunc
= CRYPT_AsnEncodeName
;
2939 case (WORD
)X509_PUBLIC_KEY_INFO
:
2940 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2942 case (WORD
)X509_AUTHORITY_KEY_ID
:
2943 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
2945 case (WORD
)X509_ALTERNATE_NAME
:
2946 encodeFunc
= CRYPT_AsnEncodeAltName
;
2948 case (WORD
)X509_BASIC_CONSTRAINTS
:
2949 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
2951 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2952 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2954 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2955 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2957 case (WORD
)X509_UNICODE_NAME
:
2958 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
2960 case (WORD
)X509_UNICODE_NAME_VALUE
:
2961 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
2963 case (WORD
)X509_OCTET_STRING
:
2964 encodeFunc
= CRYPT_AsnEncodeOctets
;
2966 case (WORD
)X509_BITS
:
2967 case (WORD
)X509_KEY_USAGE
:
2968 encodeFunc
= CRYPT_AsnEncodeBits
;
2970 case (WORD
)X509_INTEGER
:
2971 encodeFunc
= CRYPT_AsnEncodeInt
;
2973 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2974 encodeFunc
= CRYPT_AsnEncodeInteger
;
2976 case (WORD
)X509_MULTI_BYTE_UINT
:
2977 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2979 case (WORD
)X509_ENUMERATED
:
2980 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2982 case (WORD
)X509_CHOICE_OF_TIME
:
2983 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2985 case (WORD
)X509_SEQUENCE_OF_ANY
:
2986 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2988 case (WORD
)PKCS_UTC_TIME
:
2989 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2991 case (WORD
)X509_CRL_DIST_POINTS
:
2992 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
2994 case (WORD
)X509_ENHANCED_KEY_USAGE
:
2995 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
2997 case (WORD
)X509_ISSUING_DIST_POINT
:
2998 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3001 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
3004 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
3005 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3006 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3007 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3008 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
3009 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3010 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3011 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3012 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3013 encodeFunc
= CRYPT_AsnEncodeBits
;
3014 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3015 encodeFunc
= CRYPT_AsnEncodeOctets
;
3016 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
3017 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3018 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3019 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3020 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
3021 encodeFunc
= CRYPT_AsnEncodeAltName
;
3022 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
3023 encodeFunc
= CRYPT_AsnEncodeAltName
;
3024 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
3025 encodeFunc
= CRYPT_AsnEncodeAltName
;
3026 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
3027 encodeFunc
= CRYPT_AsnEncodeAltName
;
3028 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
3029 encodeFunc
= CRYPT_AsnEncodeAltName
;
3030 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
3031 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3032 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
3033 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3034 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
3035 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3037 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3038 debugstr_a(lpszStructType
));
3042 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
3043 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3044 (void **)&encodeFunc
, &hFunc
);
3047 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
3048 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
3050 SetLastError(ERROR_FILE_NOT_FOUND
);
3052 CryptFreeOIDFunctionAddress(hFunc
, 0);
3056 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
3057 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3059 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3060 NULL
, 0, NULL
, pInfo
, pcbInfo
);
3063 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3064 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3065 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3069 static CHAR oid
[] = szOID_RSA_RSA
;
3071 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3072 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3075 if (!pszPublicKeyObjId
)
3076 pszPublicKeyObjId
= oid
;
3077 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
3081 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
3084 LPBYTE pubKey
= CryptMemAlloc(keySize
);
3088 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
3092 DWORD encodedLen
= 0;
3094 ret
= CryptEncodeObject(dwCertEncodingType
,
3095 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
3098 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
3099 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
3102 *pcbInfo
= sizeNeeded
;
3103 else if (*pcbInfo
< sizeNeeded
)
3105 SetLastError(ERROR_MORE_DATA
);
3106 *pcbInfo
= sizeNeeded
;
3111 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
3112 sizeof(CERT_PUBLIC_KEY_INFO
);
3113 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
3115 pInfo
->Algorithm
.Parameters
.cbData
= 0;
3116 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
3117 pInfo
->PublicKey
.pbData
=
3118 (BYTE
*)pInfo
->Algorithm
.pszObjId
3119 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
3120 pInfo
->PublicKey
.cbData
= encodedLen
;
3121 pInfo
->PublicKey
.cUnusedBits
= 0;
3122 ret
= CryptEncodeObject(dwCertEncodingType
,
3123 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
3124 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
3128 CryptMemFree(pubKey
);
3133 CryptDestroyKey(key
);
3138 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3139 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3140 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
3142 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
3143 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
3144 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3146 static HCRYPTOIDFUNCSET set
= NULL
;
3148 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
3149 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3151 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3152 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3157 SetLastError(ERROR_INVALID_PARAMETER
);
3161 if (pszPublicKeyObjId
)
3164 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
3166 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
3167 0, (void **)&exportFunc
, &hFunc
);
3170 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
3171 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3172 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
3174 CryptFreeOIDFunctionAddress(hFunc
, 0);
3178 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
3179 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
3181 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
3185 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3186 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3187 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3190 DWORD pubKeySize
= 0;
3192 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3193 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3195 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3196 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
3199 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
3203 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3204 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
3207 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
3209 CryptMemFree(pubKey
);
3217 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3218 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3219 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
3221 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3222 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3223 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3225 static HCRYPTOIDFUNCSET set
= NULL
;
3227 ImportPublicKeyInfoExFunc importFunc
= NULL
;
3228 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3230 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3231 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3234 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
3235 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
3236 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
3238 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
3239 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
3242 CryptFreeOIDFunctionAddress(hFunc
, 0);