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 *,
54 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
55 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
57 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
58 * The dwCertEncodingType and lpszStructType are ignored by the built-in
59 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
60 * since it must call functions in external DLLs that follow these signatures.
62 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
63 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
64 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
65 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
66 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
67 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
68 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
69 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
70 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
71 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
72 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
73 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
74 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
75 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
76 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
77 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
78 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
79 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
80 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
81 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
82 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
83 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
84 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
85 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
86 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
87 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
88 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
89 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
90 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
91 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
92 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
93 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
94 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
95 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
96 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
97 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
99 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
100 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
102 static HCRYPTOIDFUNCSET set
= NULL
;
104 HCRYPTOIDFUNCADDR hFunc
;
105 CryptEncodeObjectFunc pCryptEncodeObject
;
107 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
108 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
111 if (!pbEncoded
&& !pcbEncoded
)
113 SetLastError(ERROR_INVALID_PARAMETER
);
117 /* Try registered DLL first.. */
119 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
120 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
121 (void **)&pCryptEncodeObject
, &hFunc
);
122 if (pCryptEncodeObject
)
124 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
125 pvStructInfo
, pbEncoded
, pcbEncoded
);
126 CryptFreeOIDFunctionAddress(hFunc
, 0);
130 /* If not, use CryptEncodeObjectEx */
131 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
132 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
137 /* Helper function to check *pcbEncoded, set it to the required size, and
138 * optionally to allocate memory. Assumes pbEncoded is not NULL.
139 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
140 * pointer to the newly allocated memory.
142 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
143 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
148 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
150 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
151 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
153 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
154 if (!*(BYTE
**)pbEncoded
)
157 *pcbEncoded
= bytesNeeded
;
159 else if (bytesNeeded
> *pcbEncoded
)
161 *pcbEncoded
= bytesNeeded
;
162 SetLastError(ERROR_MORE_DATA
);
166 *pcbEncoded
= bytesNeeded
;
170 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
172 DWORD bytesNeeded
, significantBytes
= 0;
180 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
181 temp
<<= 8, significantBytes
--)
183 bytesNeeded
= significantBytes
+ 1;
187 *pcbEncoded
= bytesNeeded
;
190 if (*pcbEncoded
< bytesNeeded
)
192 SetLastError(ERROR_MORE_DATA
);
196 *pbEncoded
= (BYTE
)len
;
201 *pbEncoded
++ = significantBytes
| 0x80;
202 for (i
= 0; i
< significantBytes
; i
++)
204 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
208 *pcbEncoded
= bytesNeeded
;
212 struct AsnEncodeSequenceItem
214 const void *pvStructInfo
;
215 CryptEncodeObjectExFunc encodeFunc
;
216 DWORD size
; /* used during encoding, not for your use */
219 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
220 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
221 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
224 DWORD i
, dataLen
= 0;
226 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
227 pbEncoded
, *pcbEncoded
);
228 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
230 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
231 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
232 NULL
, &items
[i
].size
);
233 /* Some functions propagate their errors through the size */
235 *pcbEncoded
= items
[i
].size
;
236 dataLen
+= items
[i
].size
;
240 DWORD lenBytes
, bytesNeeded
;
242 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
243 bytesNeeded
= 1 + lenBytes
+ dataLen
;
245 *pcbEncoded
= bytesNeeded
;
248 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
249 pcbEncoded
, bytesNeeded
)))
251 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
252 pbEncoded
= *(BYTE
**)pbEncoded
;
253 *pbEncoded
++ = ASN_SEQUENCE
;
254 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
255 pbEncoded
+= lenBytes
;
256 for (i
= 0; ret
&& i
< cItem
; i
++)
258 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
259 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
260 NULL
, pbEncoded
, &items
[i
].size
);
261 /* Some functions propagate their errors through the size */
263 *pcbEncoded
= items
[i
].size
;
264 pbEncoded
+= items
[i
].size
;
269 TRACE("returning %d (%08x)\n", ret
, GetLastError());
273 struct AsnConstructedItem
276 const void *pvStructInfo
;
277 CryptEncodeObjectExFunc encodeFunc
;
280 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
281 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
282 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
285 const struct AsnConstructedItem
*item
=
286 (const struct AsnConstructedItem
*)pvStructInfo
;
289 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
290 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
292 DWORD dataLen
, bytesNeeded
;
294 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
295 bytesNeeded
= 1 + dataLen
+ len
;
297 *pcbEncoded
= bytesNeeded
;
298 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
299 pbEncoded
, pcbEncoded
, bytesNeeded
)))
301 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
302 pbEncoded
= *(BYTE
**)pbEncoded
;
303 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
304 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
305 pbEncoded
+= dataLen
;
306 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
307 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
311 /* Some functions propagate their errors through the size */
318 /* Some functions propagate their errors through the size */
324 struct AsnEncodeTagSwappedItem
327 const void *pvStructInfo
;
328 CryptEncodeObjectExFunc encodeFunc
;
331 /* Sort of a wacky hack, it encodes something using the struct
332 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
333 * given in the struct AsnEncodeTagSwappedItem.
335 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
336 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
337 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
340 const struct AsnEncodeTagSwappedItem
*item
=
341 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
343 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
344 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
345 if (ret
&& pbEncoded
)
346 *pbEncoded
= item
->tag
;
350 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
351 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
352 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
354 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
357 /* CERT_V1 is not encoded */
365 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
367 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
368 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
373 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
374 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
375 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
377 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
382 *pcbEncoded
= blob
->cbData
;
387 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
388 pcbEncoded
, blob
->cbData
)))
390 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
391 pbEncoded
= *(BYTE
**)pbEncoded
;
393 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
394 *pcbEncoded
= blob
->cbData
;
401 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
402 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
403 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
406 /* This has two filetimes in a row, a NotBefore and a NotAfter */
407 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
408 struct AsnEncodeSequenceItem items
[] = {
409 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
410 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
413 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
414 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
419 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
420 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
421 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
424 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
425 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
427 struct AsnEncodeSequenceItem items
[] = {
428 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
429 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
432 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
433 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
438 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
439 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
440 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
446 const CERT_PUBLIC_KEY_INFO
*info
=
447 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
448 struct AsnEncodeSequenceItem items
[] = {
449 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
450 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
453 TRACE("Encoding public key with OID %s\n",
454 debugstr_a(info
->Algorithm
.pszObjId
));
455 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
456 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
461 SetLastError(STATUS_ACCESS_VIOLATION
);
468 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
469 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
470 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
476 const CERT_SIGNED_CONTENT_INFO
*info
=
477 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
478 struct AsnEncodeSequenceItem items
[] = {
479 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
480 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
481 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
484 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
485 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
486 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
487 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
492 SetLastError(STATUS_ACCESS_VIOLATION
);
499 /* Like in Windows, this blithely ignores the validity of the passed-in
500 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
501 * decode properly, see CRYPT_AsnDecodeCertInfo.
503 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
504 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
505 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
511 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
512 struct AsnEncodeSequenceItem items
[10] = {
513 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
514 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
515 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
516 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
517 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
518 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
519 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
522 struct AsnConstructedItem constructed
[3] = { { 0 } };
523 DWORD cItem
= 7, cConstructed
= 0;
525 if (info
->IssuerUniqueId
.cbData
)
527 constructed
[cConstructed
].tag
= 1;
528 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
529 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
530 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
531 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
535 if (info
->SubjectUniqueId
.cbData
)
537 constructed
[cConstructed
].tag
= 2;
538 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
539 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
540 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
541 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
545 if (info
->cExtension
)
547 constructed
[cConstructed
].tag
= 3;
548 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
549 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
550 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
551 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
556 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
557 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
561 SetLastError(STATUS_ACCESS_VIOLATION
);
568 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
569 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
571 struct AsnEncodeSequenceItem items
[3] = {
572 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
573 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
579 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
581 if (entry
->cExtension
)
583 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
584 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
588 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
589 pbEncoded
, pcbEncoded
);
591 TRACE("returning %d (%08x)\n", ret
, GetLastError());
595 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
596 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
597 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
599 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
600 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
601 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
*const *)
602 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
605 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
609 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
613 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
614 bytesNeeded
= 1 + lenBytes
+ dataLen
;
616 *pcbEncoded
= bytesNeeded
;
619 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
620 pcbEncoded
, bytesNeeded
)))
622 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
623 pbEncoded
= *(BYTE
**)pbEncoded
;
624 *pbEncoded
++ = ASN_SEQUENCEOF
;
625 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
626 pbEncoded
+= lenBytes
;
627 for (i
= 0; i
< cCRLEntry
; i
++)
629 DWORD size
= dataLen
;
631 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
640 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
641 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
642 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
644 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
647 /* CRL_V1 is not encoded */
654 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
655 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
659 /* Like in Windows, this blithely ignores the validity of the passed-in
660 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
661 * decode properly, see CRYPT_AsnDecodeCRLInfo.
663 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
664 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
665 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
671 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
672 struct AsnEncodeSequenceItem items
[7] = {
673 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
674 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
675 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
676 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
679 struct AsnConstructedItem constructed
[1] = { { 0 } };
680 DWORD cItem
= 4, cConstructed
= 0;
682 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
684 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
685 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
690 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
691 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
694 if (info
->cExtension
)
696 constructed
[cConstructed
].tag
= 0;
697 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
698 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
699 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
700 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
705 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
706 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
710 SetLastError(STATUS_ACCESS_VIOLATION
);
717 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
721 struct AsnEncodeSequenceItem items
[3] = {
722 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
728 TRACE("%p, %p, %d\n", ext
, pbEncoded
, *pcbEncoded
);
732 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
733 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
736 items
[cItem
].pvStructInfo
= &ext
->Value
;
737 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
740 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
741 pbEncoded
, pcbEncoded
);
742 TRACE("returning %d (%08x)\n", ret
, GetLastError());
746 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
747 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
748 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
754 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
755 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
758 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
762 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
766 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
767 bytesNeeded
= 1 + lenBytes
+ dataLen
;
769 *pcbEncoded
= bytesNeeded
;
772 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
773 pcbEncoded
, bytesNeeded
)))
775 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
776 pbEncoded
= *(BYTE
**)pbEncoded
;
777 *pbEncoded
++ = ASN_SEQUENCEOF
;
778 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
779 pbEncoded
+= lenBytes
;
780 for (i
= 0; i
< exts
->cExtension
; i
++)
782 DWORD size
= dataLen
;
784 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
794 SetLastError(STATUS_ACCESS_VIOLATION
);
801 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
802 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
803 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
805 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
806 DWORD bytesNeeded
= 0, lenBytes
;
811 TRACE("%s\n", debugstr_a(pszObjId
));
818 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
820 SetLastError(CRYPT_E_ASN1_ERROR
);
824 firstByte
= val1
* 40 + val2
;
825 ptr
= pszObjId
+ firstPos
;
830 /* note I assume each component is at most 32-bits long in base 2 */
831 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
833 if (val1
>= 0x10000000)
835 else if (val1
>= 0x200000)
837 else if (val1
>= 0x4000)
839 else if (val1
>= 0x80)
849 SetLastError(CRYPT_E_ASN1_ERROR
);
853 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
857 bytesNeeded
+= 1 + lenBytes
;
860 if (*pcbEncoded
< bytesNeeded
)
862 SetLastError(ERROR_MORE_DATA
);
867 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
868 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
869 pbEncoded
+= lenBytes
;
875 *pbEncoded
++ = firstByte
;
876 ptr
= pszObjId
+ firstPos
;
879 sscanf(ptr
, "%d%n", &val
, &pos
);
881 unsigned char outBytes
[5];
884 if (val
>= 0x10000000)
886 else if (val
>= 0x200000)
888 else if (val
>= 0x4000)
890 else if (val
>= 0x80)
894 for (i
= numBytes
; i
> 0; i
--)
896 outBytes
[i
- 1] = val
& 0x7f;
899 for (i
= 0; i
< numBytes
- 1; i
++)
900 *pbEncoded
++ = outBytes
[i
] | 0x80;
901 *pbEncoded
++ = outBytes
[i
];
910 *pcbEncoded
= bytesNeeded
;
914 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
915 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
919 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
920 DWORD bytesNeeded
, lenBytes
, encodedLen
;
922 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: lstrlenA(str
);
923 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
924 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
926 *pcbEncoded
= bytesNeeded
;
929 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
930 pbEncoded
, pcbEncoded
, bytesNeeded
)))
932 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
933 pbEncoded
= *(BYTE
**)pbEncoded
;
935 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
936 pbEncoded
+= lenBytes
;
937 memcpy(pbEncoded
, str
, encodedLen
);
943 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
944 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
948 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
949 DWORD bytesNeeded
, lenBytes
, strLen
;
951 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
953 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
954 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
956 *pcbEncoded
= bytesNeeded
;
959 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
960 pbEncoded
, pcbEncoded
, bytesNeeded
)))
964 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
965 pbEncoded
= *(BYTE
**)pbEncoded
;
966 *pbEncoded
++ = ASN_BMPSTRING
;
967 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
968 pbEncoded
+= lenBytes
;
969 for (i
= 0; i
< strLen
; i
++)
971 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
972 *pbEncoded
++ = str
[i
] & 0x00ff;
979 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
980 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
984 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
985 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
987 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
989 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
991 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
992 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
994 *pcbEncoded
= bytesNeeded
;
997 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
998 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1000 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1001 pbEncoded
= *(BYTE
**)pbEncoded
;
1002 *pbEncoded
++ = ASN_UTF8STRING
;
1003 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1004 pbEncoded
+= lenBytes
;
1005 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
1006 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
1012 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1013 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1014 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1020 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1022 switch (value
->dwValueType
)
1024 case CERT_RDN_ANY_TYPE
:
1025 /* explicitly disallowed */
1026 SetLastError(E_INVALIDARG
);
1029 case CERT_RDN_ENCODED_BLOB
:
1030 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1031 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1033 case CERT_RDN_OCTET_STRING
:
1034 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1035 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1037 case CERT_RDN_NUMERIC_STRING
:
1038 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1039 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1041 case CERT_RDN_PRINTABLE_STRING
:
1042 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1043 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1045 case CERT_RDN_TELETEX_STRING
:
1046 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1047 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1049 case CERT_RDN_VIDEOTEX_STRING
:
1050 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1051 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1053 case CERT_RDN_IA5_STRING
:
1054 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1055 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1057 case CERT_RDN_GRAPHIC_STRING
:
1058 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1059 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1061 case CERT_RDN_VISIBLE_STRING
:
1062 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1063 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1065 case CERT_RDN_GENERAL_STRING
:
1066 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1067 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1069 case CERT_RDN_UNIVERSAL_STRING
:
1070 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1071 SetLastError(CRYPT_E_ASN1_CHOICE
);
1074 case CERT_RDN_BMP_STRING
:
1075 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1076 pbEncoded
, pcbEncoded
);
1078 case CERT_RDN_UTF8_STRING
:
1079 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1080 pbEncoded
, pcbEncoded
);
1083 SetLastError(CRYPT_E_ASN1_CHOICE
);
1089 SetLastError(STATUS_ACCESS_VIOLATION
);
1096 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1097 CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1098 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1100 DWORD bytesNeeded
= 0, lenBytes
, size
;
1103 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1104 0, NULL
, NULL
, &size
);
1107 bytesNeeded
+= size
;
1108 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1109 * with dwValueType, so "cast" it to get its encoded size
1111 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1112 (CERT_NAME_VALUE
*)&attr
->dwValueType
, 0, NULL
, NULL
, &size
);
1115 bytesNeeded
+= size
;
1116 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1117 bytesNeeded
+= 1 + lenBytes
;
1120 if (*pcbEncoded
< bytesNeeded
)
1122 SetLastError(ERROR_MORE_DATA
);
1127 *pbEncoded
++ = ASN_SEQUENCE
;
1128 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1130 pbEncoded
+= lenBytes
;
1131 size
= bytesNeeded
- 1 - lenBytes
;
1132 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1133 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1137 size
= bytesNeeded
- 1 - lenBytes
- size
;
1138 ret
= nameValueEncodeFunc(dwCertEncodingType
,
1139 NULL
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1140 0, NULL
, pbEncoded
, &size
);
1147 *pcbEncoded
= bytesNeeded
;
1151 /* Have to propagate index of failing character */
1158 static int BLOBComp(const void *l
, const void *r
)
1160 const CRYPT_DER_BLOB
*a
= (const CRYPT_DER_BLOB
*)l
, *b
= (const CRYPT_DER_BLOB
*)r
;
1163 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1164 ret
= a
->cbData
- b
->cbData
;
1168 typedef struct _CRYPT_SET_OF
{
1170 PCRYPT_DER_BLOB rgValue
;
1173 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1175 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1176 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1177 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1179 CRYPT_SET_OF
*set
= (CRYPT_SET_OF
*)pvStructInfo
;
1180 DWORD bytesNeeded
= 0, lenBytes
, i
;
1183 for (i
= 0; i
< set
->cValue
; i
++)
1184 bytesNeeded
+= set
->rgValue
[i
].cbData
;
1185 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1186 bytesNeeded
+= 1 + lenBytes
;
1189 if (*pcbEncoded
< bytesNeeded
)
1191 *pcbEncoded
= bytesNeeded
;
1192 SetLastError(ERROR_MORE_DATA
);
1197 *pcbEncoded
= bytesNeeded
;
1198 qsort(set
->rgValue
, set
->cValue
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1199 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1200 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1201 pbEncoded
+= lenBytes
;
1202 for (i
= 0; ret
&& i
< set
->cValue
; i
++)
1204 memcpy(pbEncoded
, set
->rgValue
[i
].pbData
,
1205 set
->rgValue
[i
].cbData
);
1206 pbEncoded
+= set
->rgValue
[i
].cbData
;
1212 *pcbEncoded
= bytesNeeded
;
1218 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1219 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1223 CRYPT_SET_OF setOf
= { 0, NULL
};
1232 setOf
.cValue
= rdn
->cRDNAttr
;
1233 setOf
.rgValue
= CryptMemAlloc(rdn
->cRDNAttr
*
1234 sizeof(CRYPT_DER_BLOB
));
1238 memset(setOf
.rgValue
, 0, setOf
.cValue
* sizeof(CRYPT_DER_BLOB
));
1240 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1242 setOf
.rgValue
[i
].cbData
= 0;
1243 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1244 nameValueEncodeFunc
, NULL
, &setOf
.rgValue
[i
].cbData
);
1247 setOf
.rgValue
[i
].pbData
=
1248 CryptMemAlloc(setOf
.rgValue
[i
].cbData
);
1249 if (!setOf
.rgValue
[i
].pbData
)
1252 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1253 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1254 setOf
.rgValue
[i
].pbData
, &setOf
.rgValue
[i
].cbData
);
1258 /* Have to propagate index of failing character */
1259 *pcbEncoded
= setOf
.rgValue
[i
].cbData
;
1263 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1264 pbEncoded
, pcbEncoded
);
1265 for (i
= 0; i
< setOf
.cValue
; i
++)
1266 CryptMemFree(setOf
.rgValue
[i
].pbData
);
1270 SetLastError(STATUS_ACCESS_VIOLATION
);
1274 CryptMemFree(setOf
.rgValue
);
1278 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1279 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1280 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1282 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1283 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1284 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1287 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1290 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1291 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1292 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1294 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1295 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1299 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1300 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1301 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1307 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1308 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1310 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1312 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1314 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1315 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1317 bytesNeeded
+= size
;
1321 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1322 bytesNeeded
+= 1 + lenBytes
;
1326 *pcbEncoded
= bytesNeeded
;
1329 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1330 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1332 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1333 pbEncoded
= *(BYTE
**)pbEncoded
;
1334 *pbEncoded
++ = ASN_SEQUENCEOF
;
1335 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1337 pbEncoded
+= lenBytes
;
1338 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1341 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1342 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1347 bytesNeeded
-= size
;
1358 SetLastError(STATUS_ACCESS_VIOLATION
);
1365 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1366 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1367 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1373 const CRYPT_CONTENT_INFO
*info
=
1374 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1376 if (!info
->pszObjId
)
1377 SetLastError(E_INVALIDARG
);
1380 struct AsnEncodeSequenceItem items
[2] = {
1381 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1384 struct AsnConstructedItem constructed
= { 0 };
1387 if (info
->Content
.cbData
)
1389 constructed
.tag
= 0;
1390 constructed
.pvStructInfo
= &info
->Content
;
1391 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1392 items
[cItem
].pvStructInfo
= &constructed
;
1393 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1396 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1397 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1403 SetLastError(STATUS_ACCESS_VIOLATION
);
1409 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1410 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1414 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1415 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1417 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1419 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1420 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1422 *pcbEncoded
= bytesNeeded
;
1425 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1426 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1430 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1431 pbEncoded
= *(BYTE
**)pbEncoded
;
1433 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1434 pbEncoded
+= lenBytes
;
1435 for (i
= 0; i
< encodedLen
; i
++)
1436 *pbEncoded
++ = (BYTE
)str
[i
];
1442 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1443 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1447 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1448 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1450 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1452 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1453 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1455 *pcbEncoded
= bytesNeeded
;
1458 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1459 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1463 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1464 pbEncoded
= *(BYTE
**)pbEncoded
;
1465 *pbEncoded
++ = ASN_NUMERICSTRING
;
1466 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1467 pbEncoded
+= lenBytes
;
1468 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1470 if (isdigitW(str
[i
]))
1471 *pbEncoded
++ = (BYTE
)str
[i
];
1475 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1484 static inline int isprintableW(WCHAR wc
)
1486 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1487 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1488 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1491 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1492 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1496 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1497 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1499 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1501 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1502 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1504 *pcbEncoded
= bytesNeeded
;
1507 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1508 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1512 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1513 pbEncoded
= *(BYTE
**)pbEncoded
;
1514 *pbEncoded
++ = ASN_PRINTABLESTRING
;
1515 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1516 pbEncoded
+= lenBytes
;
1517 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1519 if (isprintableW(str
[i
]))
1520 *pbEncoded
++ = (BYTE
)str
[i
];
1524 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1533 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1534 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1538 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1539 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1541 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1543 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1544 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1546 *pcbEncoded
= bytesNeeded
;
1549 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1550 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1554 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1555 pbEncoded
= *(BYTE
**)pbEncoded
;
1556 *pbEncoded
++ = ASN_IA5STRING
;
1557 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1558 pbEncoded
+= lenBytes
;
1559 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1562 *pbEncoded
++ = (BYTE
)str
[i
];
1566 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1575 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
1576 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1580 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1581 DWORD bytesNeeded
, lenBytes
, strLen
;
1583 /* FIXME: doesn't handle composite characters */
1584 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1586 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
1587 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
1589 *pcbEncoded
= bytesNeeded
;
1592 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1593 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1597 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1598 pbEncoded
= *(BYTE
**)pbEncoded
;
1599 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
1600 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
1601 pbEncoded
+= lenBytes
;
1602 for (i
= 0; i
< strLen
; i
++)
1606 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
1607 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
1614 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1615 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1616 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1622 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1624 switch (value
->dwValueType
)
1626 case CERT_RDN_ANY_TYPE
:
1627 case CERT_RDN_ENCODED_BLOB
:
1628 case CERT_RDN_OCTET_STRING
:
1629 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
1631 case CERT_RDN_NUMERIC_STRING
:
1632 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
1633 pbEncoded
, pcbEncoded
);
1635 case CERT_RDN_PRINTABLE_STRING
:
1636 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
1637 pbEncoded
, pcbEncoded
);
1639 case CERT_RDN_TELETEX_STRING
:
1640 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
1641 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1643 case CERT_RDN_VIDEOTEX_STRING
:
1644 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
1645 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1647 case CERT_RDN_IA5_STRING
:
1648 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
1649 pbEncoded
, pcbEncoded
);
1651 case CERT_RDN_GRAPHIC_STRING
:
1652 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1653 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1655 case CERT_RDN_VISIBLE_STRING
:
1656 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
1657 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1659 case CERT_RDN_GENERAL_STRING
:
1660 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
1661 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1663 case CERT_RDN_UNIVERSAL_STRING
:
1664 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
1665 pbEncoded
, pcbEncoded
);
1667 case CERT_RDN_BMP_STRING
:
1668 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1669 pbEncoded
, pcbEncoded
);
1671 case CERT_RDN_UTF8_STRING
:
1672 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1673 pbEncoded
, pcbEncoded
);
1676 SetLastError(CRYPT_E_ASN1_CHOICE
);
1681 SetLastError(STATUS_ACCESS_VIOLATION
);
1687 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1688 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1689 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1695 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1696 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1698 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1700 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1702 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1703 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
1705 bytesNeeded
+= size
;
1707 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1708 bytesNeeded
+= 1 + lenBytes
;
1712 *pcbEncoded
= bytesNeeded
;
1715 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1716 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1718 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1719 pbEncoded
= *(BYTE
**)pbEncoded
;
1720 *pbEncoded
++ = ASN_SEQUENCEOF
;
1721 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1723 pbEncoded
+= lenBytes
;
1724 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1727 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1728 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
1733 bytesNeeded
-= size
;
1742 SetLastError(STATUS_ACCESS_VIOLATION
);
1749 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1750 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1751 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1753 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1762 else if (*pcbEncoded
< 3)
1765 SetLastError(ERROR_MORE_DATA
);
1771 *pbEncoded
++ = ASN_BOOL
;
1773 *pbEncoded
++ = val
? 0xff : 0;
1776 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1780 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1781 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1787 switch (entry
->dwAltNameChoice
)
1789 case CERT_ALT_NAME_RFC822_NAME
:
1790 case CERT_ALT_NAME_DNS_NAME
:
1791 case CERT_ALT_NAME_URL
:
1792 if (entry
->u
.pwszURL
)
1796 /* Not + 1: don't encode the NULL-terminator */
1797 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1798 for (i
= 0; ret
&& i
< dataLen
; i
++)
1800 if (entry
->u
.pwszURL
[i
] > 0x7f)
1802 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1811 case CERT_ALT_NAME_IP_ADDRESS
:
1812 dataLen
= entry
->u
.IPAddress
.cbData
;
1814 case CERT_ALT_NAME_REGISTERED_ID
:
1815 /* FIXME: encode OID */
1816 case CERT_ALT_NAME_OTHER_NAME
:
1817 case CERT_ALT_NAME_DIRECTORY_NAME
:
1818 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
1821 SetLastError(E_INVALIDARG
);
1826 DWORD bytesNeeded
, lenBytes
;
1828 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1829 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1831 *pcbEncoded
= bytesNeeded
;
1832 else if (*pcbEncoded
< bytesNeeded
)
1834 SetLastError(ERROR_MORE_DATA
);
1835 *pcbEncoded
= bytesNeeded
;
1840 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1841 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1842 pbEncoded
+= lenBytes
;
1843 switch (entry
->dwAltNameChoice
)
1845 case CERT_ALT_NAME_RFC822_NAME
:
1846 case CERT_ALT_NAME_DNS_NAME
:
1847 case CERT_ALT_NAME_URL
:
1851 for (i
= 0; i
< dataLen
; i
++)
1852 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1855 case CERT_ALT_NAME_IP_ADDRESS
:
1856 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1860 *pcbEncoded
= bytesNeeded
;
1863 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1867 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
1868 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1869 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1875 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
1876 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
1877 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
1878 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
1879 struct AsnConstructedItem constructed
= { 0 };
1880 DWORD cItem
= 0, cSwapped
= 0;
1882 if (info
->KeyId
.cbData
)
1884 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
1885 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
1886 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1887 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
1888 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
1892 if (info
->CertIssuer
.cbData
)
1894 constructed
.tag
= 1;
1895 constructed
.pvStructInfo
= &info
->CertIssuer
;
1896 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1897 items
[cItem
].pvStructInfo
= &constructed
;
1898 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1901 if (info
->CertSerialNumber
.cbData
)
1903 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
1904 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
1905 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1906 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
1907 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
1911 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
1912 pEncodePara
, pbEncoded
, pcbEncoded
);
1916 SetLastError(STATUS_ACCESS_VIOLATION
);
1923 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1924 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1925 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1931 const CERT_ALT_NAME_INFO
*info
=
1932 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1933 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1936 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1937 * can't encode an erroneous entry index if it's bigger than this.
1939 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1943 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1947 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1949 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1950 * the bad character, now set the index of the bad
1953 *pcbEncoded
= (BYTE
)i
<<
1954 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1959 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1960 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1963 *pcbEncoded
= bytesNeeded
;
1968 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1969 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1971 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1972 pbEncoded
= *(BYTE
**)pbEncoded
;
1973 *pbEncoded
++ = ASN_SEQUENCEOF
;
1974 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1975 pbEncoded
+= lenBytes
;
1976 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1978 DWORD len
= dataLen
;
1980 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1994 SetLastError(STATUS_ACCESS_VIOLATION
);
2001 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2002 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2003 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2009 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2010 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2011 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2012 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2013 DWORD cItem
= 0, cSwapped
= 0;
2015 if (info
->KeyId
.cbData
)
2017 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2018 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2019 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2020 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2021 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2025 if (info
->AuthorityCertIssuer
.cAltEntry
)
2027 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2028 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2029 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2030 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2031 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2035 if (info
->AuthorityCertSerialNumber
.cbData
)
2037 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2038 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2039 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2040 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2041 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2045 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2046 pEncodePara
, pbEncoded
, pcbEncoded
);
2050 SetLastError(STATUS_ACCESS_VIOLATION
);
2057 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2058 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2059 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2065 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2066 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2067 struct AsnEncodeSequenceItem items
[3] = {
2068 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2073 if (info
->fPathLenConstraint
)
2075 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2076 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2079 if (info
->cSubtreesConstraint
)
2081 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2082 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2085 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2086 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2090 SetLastError(STATUS_ACCESS_VIOLATION
);
2097 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2098 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2099 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2105 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2106 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2107 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2112 items
[cItem
].pvStructInfo
= &info
->fCA
;
2113 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2116 if (info
->fPathLenConstraint
)
2118 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2119 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2122 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2123 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2127 SetLastError(STATUS_ACCESS_VIOLATION
);
2134 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2135 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2136 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2142 const BLOBHEADER
*hdr
=
2143 (const BLOBHEADER
*)pvStructInfo
;
2145 if (hdr
->bType
!= PUBLICKEYBLOB
)
2147 SetLastError(E_INVALIDARG
);
2152 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2153 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2154 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2155 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2156 struct AsnEncodeSequenceItem items
[] = {
2157 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2158 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2161 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2162 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2168 SetLastError(STATUS_ACCESS_VIOLATION
);
2175 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2176 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2177 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2183 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2184 DWORD bytesNeeded
, lenBytes
;
2186 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2187 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2189 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2190 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2193 *pcbEncoded
= bytesNeeded
;
2198 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2199 pcbEncoded
, bytesNeeded
)))
2201 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2202 pbEncoded
= *(BYTE
**)pbEncoded
;
2203 *pbEncoded
++ = ASN_OCTETSTRING
;
2204 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2205 pbEncoded
+= lenBytes
;
2207 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2213 SetLastError(STATUS_ACCESS_VIOLATION
);
2217 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2221 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2222 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2223 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2229 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2230 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2233 /* yep, MS allows cUnusedBits to be >= 8 */
2234 if (!blob
->cUnusedBits
)
2236 dataBytes
= blob
->cbData
;
2239 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2241 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2242 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2250 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2251 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2254 *pcbEncoded
= bytesNeeded
;
2259 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2260 pcbEncoded
, bytesNeeded
)))
2262 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2263 pbEncoded
= *(BYTE
**)pbEncoded
;
2264 *pbEncoded
++ = ASN_BITSTRING
;
2265 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2266 pbEncoded
+= lenBytes
;
2267 *pbEncoded
++ = unusedBits
;
2270 BYTE mask
= 0xff << unusedBits
;
2274 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2275 pbEncoded
+= dataBytes
- 1;
2277 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2284 SetLastError(STATUS_ACCESS_VIOLATION
);
2291 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2292 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2293 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2299 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2300 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2305 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2310 for (i
= 0; i
< newBlob
.cbData
; i
++)
2311 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2317 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2318 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2319 CryptMemFree(newBlob
.pbData
);
2323 SetLastError(STATUS_ACCESS_VIOLATION
);
2330 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2331 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2332 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2334 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2336 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2337 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2340 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2341 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2342 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2348 DWORD significantBytes
, lenBytes
;
2349 BYTE padByte
= 0, bytesNeeded
;
2351 const CRYPT_INTEGER_BLOB
*blob
=
2352 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2354 significantBytes
= blob
->cbData
;
2355 if (significantBytes
)
2357 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2359 /* negative, lop off leading (little-endian) 0xffs */
2360 for (; significantBytes
> 0 &&
2361 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2363 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2371 /* positive, lop off leading (little-endian) zeroes */
2372 for (; significantBytes
> 0 &&
2373 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2375 if (significantBytes
== 0)
2376 significantBytes
= 1;
2377 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2385 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2387 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2388 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2393 *pcbEncoded
= bytesNeeded
;
2398 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2399 pcbEncoded
, bytesNeeded
)))
2401 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2402 pbEncoded
= *(BYTE
**)pbEncoded
;
2403 *pbEncoded
++ = ASN_INTEGER
;
2406 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2407 pbEncoded
+= lenBytes
;
2408 *pbEncoded
++ = padByte
;
2412 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2413 pbEncoded
+= lenBytes
;
2415 for (; significantBytes
> 0; significantBytes
--)
2416 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2422 SetLastError(STATUS_ACCESS_VIOLATION
);
2429 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
2430 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2431 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2437 DWORD significantBytes
, lenBytes
;
2440 const CRYPT_INTEGER_BLOB
*blob
=
2441 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2443 significantBytes
= blob
->cbData
;
2444 if (significantBytes
)
2446 /* positive, lop off leading (little-endian) zeroes */
2447 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2450 if (significantBytes
== 0)
2451 significantBytes
= 1;
2452 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2456 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2458 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2459 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2464 *pcbEncoded
= bytesNeeded
;
2469 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2470 pcbEncoded
, bytesNeeded
)))
2472 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2473 pbEncoded
= *(BYTE
**)pbEncoded
;
2474 *pbEncoded
++ = ASN_INTEGER
;
2477 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2478 pbEncoded
+= lenBytes
;
2483 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2484 pbEncoded
+= lenBytes
;
2486 for (; significantBytes
> 0; significantBytes
--)
2487 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2493 SetLastError(STATUS_ACCESS_VIOLATION
);
2500 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2501 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2502 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2504 CRYPT_INTEGER_BLOB blob
;
2507 /* Encode as an unsigned integer, then change the tag to enumerated */
2508 blob
.cbData
= sizeof(DWORD
);
2509 blob
.pbData
= (BYTE
*)pvStructInfo
;
2510 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2511 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2512 if (ret
&& pbEncoded
)
2514 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2515 pbEncoded
= *(BYTE
**)pbEncoded
;
2516 pbEncoded
[0] = ASN_ENUMERATED
;
2521 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2522 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2523 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2530 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2531 * temporary buffer because the output buffer is not NULL-terminated.
2534 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2538 *pcbEncoded
= bytesNeeded
;
2543 /* Sanity check the year, this is a two-digit year format */
2544 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2546 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2548 SetLastError(CRYPT_E_BAD_ENCODE
);
2553 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2554 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2556 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2557 pbEncoded
= *(BYTE
**)pbEncoded
;
2558 buf
[0] = ASN_UTCTIME
;
2559 buf
[1] = bytesNeeded
- 2;
2560 snprintf(buf
+ 2, sizeof(buf
) - 2,
2561 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2562 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2563 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2564 sysTime
.wMinute
, sysTime
.wSecond
);
2565 memcpy(pbEncoded
, buf
, bytesNeeded
);
2572 SetLastError(STATUS_ACCESS_VIOLATION
);
2579 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2580 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2581 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2588 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2589 * temporary buffer because the output buffer is not NULL-terminated.
2592 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2596 *pcbEncoded
= bytesNeeded
;
2601 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2604 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2605 pcbEncoded
, bytesNeeded
);
2608 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2609 pbEncoded
= *(BYTE
**)pbEncoded
;
2610 buf
[0] = ASN_GENERALTIME
;
2611 buf
[1] = bytesNeeded
- 2;
2612 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2613 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2614 sysTime
.wMinute
, sysTime
.wSecond
);
2615 memcpy(pbEncoded
, buf
, bytesNeeded
);
2621 SetLastError(STATUS_ACCESS_VIOLATION
);
2628 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2629 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2630 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2638 /* Check the year, if it's in the UTCTime range call that encode func */
2639 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2641 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2642 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2643 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2645 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2646 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2651 SetLastError(STATUS_ACCESS_VIOLATION
);
2658 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2659 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2660 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2666 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2667 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2668 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2670 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2671 dataLen
+= seq
->rgValue
[i
].cbData
;
2672 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2673 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2676 *pcbEncoded
= bytesNeeded
;
2681 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2682 pcbEncoded
, bytesNeeded
)))
2684 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2685 pbEncoded
= *(BYTE
**)pbEncoded
;
2686 *pbEncoded
++ = ASN_SEQUENCEOF
;
2687 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2688 pbEncoded
+= lenBytes
;
2689 for (i
= 0; i
< seq
->cValue
; i
++)
2691 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2692 seq
->rgValue
[i
].cbData
);
2693 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2700 SetLastError(STATUS_ACCESS_VIOLATION
);
2707 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2708 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2711 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2712 struct AsnConstructedItem constructed
= { 0 };
2713 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2714 DWORD cItem
= 0, cSwapped
= 0;
2716 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2718 case CRL_DIST_POINT_NO_NAME
:
2721 case CRL_DIST_POINT_FULL_NAME
:
2722 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2723 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2724 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2725 constructed
.tag
= 0;
2726 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2727 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2728 items
[cItem
].pvStructInfo
= &constructed
;
2729 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2733 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2734 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2740 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2742 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2743 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2744 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2745 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2746 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2750 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2752 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2753 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2754 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2755 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2756 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2761 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2762 pbEncoded
, pcbEncoded
);
2766 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2767 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2768 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2774 const CRL_DIST_POINTS_INFO
*info
=
2775 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2777 if (!info
->cDistPoint
)
2779 SetLastError(E_INVALIDARG
);
2784 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2787 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2791 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2795 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2797 /* Have to propagate index of failing character */
2803 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2804 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2807 *pcbEncoded
= bytesNeeded
;
2812 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2813 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2815 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2816 pbEncoded
= *(BYTE
**)pbEncoded
;
2817 *pbEncoded
++ = ASN_SEQUENCEOF
;
2818 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2819 pbEncoded
+= lenBytes
;
2820 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2822 DWORD len
= dataLen
;
2824 ret
= CRYPT_AsnEncodeDistPoint(
2825 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
2839 SetLastError(STATUS_ACCESS_VIOLATION
);
2846 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
2847 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2848 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2854 const CERT_ENHKEY_USAGE
*usage
=
2855 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
2856 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2859 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2861 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2862 usage
->rgpszUsageIdentifier
[i
],
2863 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2865 bytesNeeded
+= size
;
2867 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2868 bytesNeeded
+= 1 + lenBytes
;
2872 *pcbEncoded
= bytesNeeded
;
2875 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2876 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2878 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2879 pbEncoded
= *(BYTE
**)pbEncoded
;
2880 *pbEncoded
++ = ASN_SEQUENCEOF
;
2881 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2883 pbEncoded
+= lenBytes
;
2884 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2887 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2888 usage
->rgpszUsageIdentifier
[i
],
2889 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2894 bytesNeeded
-= size
;
2903 SetLastError(STATUS_ACCESS_VIOLATION
);
2910 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
2911 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2912 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2918 const CRL_ISSUING_DIST_POINT
*point
=
2919 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
2920 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
2921 struct AsnConstructedItem constructed
= { 0 };
2922 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
2923 DWORD cItem
= 0, cSwapped
= 0;
2926 switch (point
->DistPointName
.dwDistPointNameChoice
)
2928 case CRL_DIST_POINT_NO_NAME
:
2931 case CRL_DIST_POINT_FULL_NAME
:
2932 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2933 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
2934 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2935 constructed
.tag
= 0;
2936 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2937 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2938 items
[cItem
].pvStructInfo
= &constructed
;
2939 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2944 SetLastError(E_INVALIDARG
);
2947 if (ret
&& point
->fOnlyContainsUserCerts
)
2949 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2950 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
2951 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
2952 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2953 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2957 if (ret
&& point
->fOnlyContainsCACerts
)
2959 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2960 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
2961 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
2962 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2963 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2967 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
2969 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
2970 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
2971 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2972 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2973 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2977 if (ret
&& point
->fIndirectCRL
)
2979 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
2980 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
2981 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
2982 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2983 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2988 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2989 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2993 SetLastError(STATUS_ACCESS_VIOLATION
);
3000 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3001 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
3002 void *pvEncoded
, DWORD
*pcbEncoded
)
3004 static HCRYPTOIDFUNCSET set
= NULL
;
3006 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3007 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3009 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
3010 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
3011 pvEncoded
, pcbEncoded
);
3013 if (!pvEncoded
&& !pcbEncoded
)
3015 SetLastError(ERROR_INVALID_PARAMETER
);
3018 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3019 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3021 SetLastError(ERROR_FILE_NOT_FOUND
);
3025 SetLastError(NOERROR
);
3026 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
3027 *(BYTE
**)pvEncoded
= NULL
;
3028 if (!HIWORD(lpszStructType
))
3030 switch (LOWORD(lpszStructType
))
3032 case (WORD
)X509_CERT
:
3033 encodeFunc
= CRYPT_AsnEncodeCert
;
3035 case (WORD
)X509_CERT_TO_BE_SIGNED
:
3036 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
3038 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
3039 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
3041 case (WORD
)X509_EXTENSIONS
:
3042 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3044 case (WORD
)X509_NAME_VALUE
:
3045 encodeFunc
= CRYPT_AsnEncodeNameValue
;
3047 case (WORD
)X509_NAME
:
3048 encodeFunc
= CRYPT_AsnEncodeName
;
3050 case (WORD
)X509_PUBLIC_KEY_INFO
:
3051 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
3053 case (WORD
)X509_AUTHORITY_KEY_ID
:
3054 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3056 case (WORD
)X509_ALTERNATE_NAME
:
3057 encodeFunc
= CRYPT_AsnEncodeAltName
;
3059 case (WORD
)X509_BASIC_CONSTRAINTS
:
3060 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3062 case (WORD
)X509_BASIC_CONSTRAINTS2
:
3063 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3065 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
3066 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
3068 case (WORD
)X509_UNICODE_NAME
:
3069 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
3071 case (WORD
)PKCS_CONTENT_INFO
:
3072 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
3074 case (WORD
)X509_UNICODE_NAME_VALUE
:
3075 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
3077 case (WORD
)X509_OCTET_STRING
:
3078 encodeFunc
= CRYPT_AsnEncodeOctets
;
3080 case (WORD
)X509_BITS
:
3081 case (WORD
)X509_KEY_USAGE
:
3082 encodeFunc
= CRYPT_AsnEncodeBits
;
3084 case (WORD
)X509_INTEGER
:
3085 encodeFunc
= CRYPT_AsnEncodeInt
;
3087 case (WORD
)X509_MULTI_BYTE_INTEGER
:
3088 encodeFunc
= CRYPT_AsnEncodeInteger
;
3090 case (WORD
)X509_MULTI_BYTE_UINT
:
3091 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
3093 case (WORD
)X509_ENUMERATED
:
3094 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3096 case (WORD
)X509_CHOICE_OF_TIME
:
3097 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
3099 case (WORD
)X509_AUTHORITY_KEY_ID2
:
3100 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3102 case (WORD
)X509_SEQUENCE_OF_ANY
:
3103 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
3105 case (WORD
)PKCS_UTC_TIME
:
3106 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3108 case (WORD
)X509_CRL_DIST_POINTS
:
3109 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3111 case (WORD
)X509_ENHANCED_KEY_USAGE
:
3112 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3114 case (WORD
)X509_ISSUING_DIST_POINT
:
3115 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3118 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
3121 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
3122 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3123 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3124 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3125 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
3126 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3127 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
3128 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3129 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3130 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3131 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3132 encodeFunc
= CRYPT_AsnEncodeBits
;
3133 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3134 encodeFunc
= CRYPT_AsnEncodeOctets
;
3135 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
3136 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3137 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3138 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3139 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
3140 encodeFunc
= CRYPT_AsnEncodeAltName
;
3141 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
3142 encodeFunc
= CRYPT_AsnEncodeAltName
;
3143 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
3144 encodeFunc
= CRYPT_AsnEncodeAltName
;
3145 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
3146 encodeFunc
= CRYPT_AsnEncodeAltName
;
3147 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
3148 encodeFunc
= CRYPT_AsnEncodeAltName
;
3149 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
3150 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3151 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
3152 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3153 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
3154 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3156 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3157 debugstr_a(lpszStructType
));
3161 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
3162 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3163 (void **)&encodeFunc
, &hFunc
);
3166 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
3167 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
3169 SetLastError(ERROR_FILE_NOT_FOUND
);
3171 CryptFreeOIDFunctionAddress(hFunc
, 0);
3175 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
3176 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3178 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3179 NULL
, 0, NULL
, pInfo
, pcbInfo
);
3182 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3183 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3184 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3188 static CHAR oid
[] = szOID_RSA_RSA
;
3190 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3191 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3194 if (!pszPublicKeyObjId
)
3195 pszPublicKeyObjId
= oid
;
3196 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
3200 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
3203 LPBYTE pubKey
= CryptMemAlloc(keySize
);
3207 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
3211 DWORD encodedLen
= 0;
3213 ret
= CryptEncodeObject(dwCertEncodingType
,
3214 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
3217 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
3218 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
3221 *pcbInfo
= sizeNeeded
;
3222 else if (*pcbInfo
< sizeNeeded
)
3224 SetLastError(ERROR_MORE_DATA
);
3225 *pcbInfo
= sizeNeeded
;
3230 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
3231 sizeof(CERT_PUBLIC_KEY_INFO
);
3232 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
3234 pInfo
->Algorithm
.Parameters
.cbData
= 0;
3235 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
3236 pInfo
->PublicKey
.pbData
=
3237 (BYTE
*)pInfo
->Algorithm
.pszObjId
3238 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
3239 pInfo
->PublicKey
.cbData
= encodedLen
;
3240 pInfo
->PublicKey
.cUnusedBits
= 0;
3241 ret
= CryptEncodeObject(dwCertEncodingType
,
3242 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
3243 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
3247 CryptMemFree(pubKey
);
3252 CryptDestroyKey(key
);
3257 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3258 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3259 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
3261 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
3262 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
3263 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3265 static HCRYPTOIDFUNCSET set
= NULL
;
3267 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
3268 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3270 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3271 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3276 SetLastError(ERROR_INVALID_PARAMETER
);
3280 if (pszPublicKeyObjId
)
3283 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
3285 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
3286 0, (void **)&exportFunc
, &hFunc
);
3289 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
3290 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3291 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
3293 CryptFreeOIDFunctionAddress(hFunc
, 0);
3297 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
3298 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
3300 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
3304 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3305 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3306 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3309 DWORD pubKeySize
= 0;
3311 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3312 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3314 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3315 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
3318 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
3322 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3323 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
3326 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
3328 CryptMemFree(pubKey
);
3336 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3337 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3338 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
3340 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3341 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3342 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3344 static HCRYPTOIDFUNCSET set
= NULL
;
3346 ImportPublicKeyInfoExFunc importFunc
= NULL
;
3347 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3349 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3350 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3353 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
3354 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
3355 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
3357 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
3358 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
3361 CryptFreeOIDFunctionAddress(hFunc
, 0);