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 "crypt32_private.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
53 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
55 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
56 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
64 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
65 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
66 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
67 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
68 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
69 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
70 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
71 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
72 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
73 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
74 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
75 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
77 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
78 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
93 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
95 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
96 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
97 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
98 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
100 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
101 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
103 static HCRYPTOIDFUNCSET set
= NULL
;
105 HCRYPTOIDFUNCADDR hFunc
;
106 CryptEncodeObjectFunc pCryptEncodeObject
;
108 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
109 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
112 if (!pbEncoded
&& !pcbEncoded
)
114 SetLastError(ERROR_INVALID_PARAMETER
);
118 /* Try registered DLL first.. */
120 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
121 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
122 (void **)&pCryptEncodeObject
, &hFunc
);
123 if (pCryptEncodeObject
)
125 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
126 pvStructInfo
, pbEncoded
, pcbEncoded
);
127 CryptFreeOIDFunctionAddress(hFunc
, 0);
131 /* If not, use CryptEncodeObjectEx */
132 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
133 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
138 /* Helper function to check *pcbEncoded, set it to the required size, and
139 * optionally to allocate memory. Assumes pbEncoded is not NULL.
140 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
141 * pointer to the newly allocated memory.
143 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
144 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
149 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
151 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
152 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
154 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
155 if (!*(BYTE
**)pbEncoded
)
158 *pcbEncoded
= bytesNeeded
;
160 else if (bytesNeeded
> *pcbEncoded
)
162 *pcbEncoded
= bytesNeeded
;
163 SetLastError(ERROR_MORE_DATA
);
169 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
171 DWORD bytesNeeded
, significantBytes
= 0;
179 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
180 temp
<<= 8, significantBytes
--)
182 bytesNeeded
= significantBytes
+ 1;
186 *pcbEncoded
= bytesNeeded
;
189 if (*pcbEncoded
< bytesNeeded
)
191 SetLastError(ERROR_MORE_DATA
);
195 *pbEncoded
= (BYTE
)len
;
200 *pbEncoded
++ = significantBytes
| 0x80;
201 for (i
= 0; i
< significantBytes
; i
++)
203 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
207 *pcbEncoded
= bytesNeeded
;
211 struct AsnEncodeSequenceItem
213 const void *pvStructInfo
;
214 CryptEncodeObjectExFunc encodeFunc
;
215 DWORD size
; /* used during encoding, not for your use */
218 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
219 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
220 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
223 DWORD i
, dataLen
= 0;
225 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
226 pbEncoded
, *pcbEncoded
);
227 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
229 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
230 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
231 NULL
, &items
[i
].size
);
232 /* Some functions propagate their errors through the size */
234 *pcbEncoded
= items
[i
].size
;
235 dataLen
+= items
[i
].size
;
239 DWORD lenBytes
, bytesNeeded
;
241 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
242 bytesNeeded
= 1 + lenBytes
+ dataLen
;
244 *pcbEncoded
= bytesNeeded
;
247 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
248 pcbEncoded
, bytesNeeded
)))
250 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
251 pbEncoded
= *(BYTE
**)pbEncoded
;
252 *pbEncoded
++ = ASN_SEQUENCE
;
253 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
254 pbEncoded
+= lenBytes
;
255 for (i
= 0; ret
&& i
< cItem
; i
++)
257 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
258 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
259 NULL
, pbEncoded
, &items
[i
].size
);
260 /* Some functions propagate their errors through the size */
262 *pcbEncoded
= items
[i
].size
;
263 pbEncoded
+= items
[i
].size
;
268 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
272 struct AsnConstructedItem
275 const void *pvStructInfo
;
276 CryptEncodeObjectExFunc encodeFunc
;
279 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
280 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
281 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
284 const struct AsnConstructedItem
*item
=
285 (const struct AsnConstructedItem
*)pvStructInfo
;
288 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
289 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
291 DWORD dataLen
, bytesNeeded
;
293 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
294 bytesNeeded
= 1 + dataLen
+ len
;
296 *pcbEncoded
= bytesNeeded
;
297 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
298 pbEncoded
, pcbEncoded
, bytesNeeded
)))
300 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
301 pbEncoded
= *(BYTE
**)pbEncoded
;
302 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
303 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
304 pbEncoded
+= dataLen
;
305 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
306 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
310 /* Some functions propagate their errors through the size */
317 /* Some functions propagate their errors through the size */
323 struct AsnEncodeTagSwappedItem
326 const void *pvStructInfo
;
327 CryptEncodeObjectExFunc encodeFunc
;
330 /* Sort of a wacky hack, it encodes something using the struct
331 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
332 * given in the struct AsnEncodeTagSwappedItem.
334 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
335 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
336 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
339 const struct AsnEncodeTagSwappedItem
*item
=
340 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
342 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
343 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
344 if (ret
&& pbEncoded
)
345 *pbEncoded
= item
->tag
;
349 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
350 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
351 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
353 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
356 /* CERT_V1 is not encoded */
364 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
366 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
367 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
372 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
373 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
374 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
376 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
381 *pcbEncoded
= blob
->cbData
;
384 else if (*pcbEncoded
< blob
->cbData
)
386 *pcbEncoded
= blob
->cbData
;
387 SetLastError(ERROR_MORE_DATA
);
393 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
394 *pcbEncoded
= blob
->cbData
;
400 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
401 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
402 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
405 /* This has two filetimes in a row, a NotBefore and a NotAfter */
406 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
407 struct AsnEncodeSequenceItem items
[] = {
408 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
409 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
412 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
413 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
418 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
419 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
420 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
423 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
424 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
426 struct AsnEncodeSequenceItem items
[] = {
427 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
428 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
431 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
432 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
437 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
438 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
439 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
445 const CERT_PUBLIC_KEY_INFO
*info
=
446 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
447 struct AsnEncodeSequenceItem items
[] = {
448 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
449 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
452 TRACE("Encoding public key with OID %s\n",
453 debugstr_a(info
->Algorithm
.pszObjId
));
454 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
455 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
460 SetLastError(STATUS_ACCESS_VIOLATION
);
467 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
468 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
469 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
475 const CERT_SIGNED_CONTENT_INFO
*info
=
476 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
477 struct AsnEncodeSequenceItem items
[] = {
478 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
479 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
480 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
483 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
484 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
485 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
486 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
491 SetLastError(STATUS_ACCESS_VIOLATION
);
498 /* Like in Windows, this blithely ignores the validity of the passed-in
499 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
500 * decode properly, see CRYPT_AsnDecodeCertInfo.
502 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
503 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
504 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
510 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
511 struct AsnEncodeSequenceItem items
[10] = {
512 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
513 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
514 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
515 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
516 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
517 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
518 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
521 struct AsnConstructedItem constructed
[3] = { { 0 } };
522 DWORD cItem
= 7, cConstructed
= 0;
524 if (info
->IssuerUniqueId
.cbData
)
526 constructed
[cConstructed
].tag
= 1;
527 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
528 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
529 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
530 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
534 if (info
->SubjectUniqueId
.cbData
)
536 constructed
[cConstructed
].tag
= 2;
537 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
538 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
539 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
540 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
544 if (info
->cExtension
)
546 constructed
[cConstructed
].tag
= 3;
547 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
548 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
549 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
550 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
555 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
556 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
560 SetLastError(STATUS_ACCESS_VIOLATION
);
567 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
568 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
570 struct AsnEncodeSequenceItem items
[3] = {
571 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
572 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
578 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
580 if (entry
->cExtension
)
582 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
583 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
587 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
588 pbEncoded
, pcbEncoded
);
590 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
594 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
595 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
596 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
598 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
599 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
600 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
601 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
604 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
608 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
612 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
613 bytesNeeded
= 1 + lenBytes
+ dataLen
;
615 *pcbEncoded
= bytesNeeded
;
618 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
619 pcbEncoded
, bytesNeeded
)))
621 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
622 pbEncoded
= *(BYTE
**)pbEncoded
;
623 *pbEncoded
++ = ASN_SEQUENCEOF
;
624 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
625 pbEncoded
+= lenBytes
;
626 for (i
= 0; i
< cCRLEntry
; i
++)
628 DWORD size
= dataLen
;
630 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
639 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
640 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
641 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
643 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
646 /* CRL_V1 is not encoded */
653 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
654 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
658 /* Like in Windows, this blithely ignores the validity of the passed-in
659 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
660 * decode properly, see CRYPT_AsnDecodeCRLInfo.
662 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
663 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
664 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
670 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
671 struct AsnEncodeSequenceItem items
[7] = {
672 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
673 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
674 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
675 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
680 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
682 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
683 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
688 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
689 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
692 if (info
->cExtension
)
694 items
[cItem
].pvStructInfo
= &info
->cExtension
;
695 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
699 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
700 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
704 SetLastError(STATUS_ACCESS_VIOLATION
);
711 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
715 struct AsnEncodeSequenceItem items
[3] = {
716 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
722 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
726 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
727 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
730 items
[cItem
].pvStructInfo
= &ext
->Value
;
731 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
734 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
735 pbEncoded
, pcbEncoded
);
736 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
740 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
741 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
742 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
748 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
749 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
752 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
756 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
760 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
761 bytesNeeded
= 1 + lenBytes
+ dataLen
;
763 *pcbEncoded
= bytesNeeded
;
766 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
767 pcbEncoded
, bytesNeeded
)))
769 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
770 pbEncoded
= *(BYTE
**)pbEncoded
;
771 *pbEncoded
++ = ASN_SEQUENCEOF
;
772 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
773 pbEncoded
+= lenBytes
;
774 for (i
= 0; i
< exts
->cExtension
; i
++)
776 DWORD size
= dataLen
;
778 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
788 SetLastError(STATUS_ACCESS_VIOLATION
);
795 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
796 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
797 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
799 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
800 DWORD bytesNeeded
= 0, lenBytes
;
805 TRACE("%s\n", debugstr_a(pszObjId
));
812 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
814 SetLastError(CRYPT_E_ASN1_ERROR
);
818 firstByte
= val1
* 40 + val2
;
819 ptr
= pszObjId
+ firstPos
;
824 /* note I assume each component is at most 32-bits long in base 2 */
825 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
827 if (val1
>= 0x10000000)
829 else if (val1
>= 0x200000)
831 else if (val1
>= 0x4000)
833 else if (val1
>= 0x80)
843 SetLastError(CRYPT_E_ASN1_ERROR
);
847 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
851 bytesNeeded
+= 1 + lenBytes
;
854 if (*pcbEncoded
< bytesNeeded
)
856 SetLastError(ERROR_MORE_DATA
);
861 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
862 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
863 pbEncoded
+= lenBytes
;
869 *pbEncoded
++ = firstByte
;
870 ptr
= pszObjId
+ firstPos
;
873 sscanf(ptr
, "%d%n", &val
, &pos
);
875 unsigned char outBytes
[5];
878 if (val
>= 0x10000000)
880 else if (val
>= 0x200000)
882 else if (val
>= 0x4000)
884 else if (val
>= 0x80)
888 for (i
= numBytes
; i
> 0; i
--)
890 outBytes
[i
- 1] = val
& 0x7f;
893 for (i
= 0; i
< numBytes
- 1; i
++)
894 *pbEncoded
++ = outBytes
[i
] | 0x80;
895 *pbEncoded
++ = outBytes
[i
];
904 *pcbEncoded
= bytesNeeded
;
908 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
909 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
912 DWORD bytesNeeded
, lenBytes
, encodedLen
;
915 switch (value
->dwValueType
)
917 case CERT_RDN_NUMERIC_STRING
:
918 tag
= ASN_NUMERICSTRING
;
919 encodedLen
= value
->Value
.cbData
;
921 case CERT_RDN_PRINTABLE_STRING
:
922 tag
= ASN_PRINTABLESTRING
;
923 encodedLen
= value
->Value
.cbData
;
925 case CERT_RDN_IA5_STRING
:
927 encodedLen
= value
->Value
.cbData
;
929 case CERT_RDN_ANY_TYPE
:
930 /* explicitly disallowed */
931 SetLastError(E_INVALIDARG
);
934 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
937 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
938 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
941 if (*pcbEncoded
< bytesNeeded
)
943 SetLastError(ERROR_MORE_DATA
);
949 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
950 pbEncoded
+= lenBytes
;
951 switch (value
->dwValueType
)
953 case CERT_RDN_NUMERIC_STRING
:
954 case CERT_RDN_PRINTABLE_STRING
:
955 case CERT_RDN_IA5_STRING
:
956 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
960 *pcbEncoded
= bytesNeeded
;
964 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
965 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
967 DWORD bytesNeeded
= 0, lenBytes
, size
;
970 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
971 0, NULL
, NULL
, &size
);
975 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
976 * with dwValueType, so "cast" it to get its encoded size
978 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
979 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
983 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
984 bytesNeeded
+= 1 + lenBytes
;
987 if (*pcbEncoded
< bytesNeeded
)
989 SetLastError(ERROR_MORE_DATA
);
994 *pbEncoded
++ = ASN_SEQUENCE
;
995 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
997 pbEncoded
+= lenBytes
;
998 size
= bytesNeeded
- 1 - lenBytes
;
999 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1000 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1004 size
= bytesNeeded
- 1 - lenBytes
- size
;
1005 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1006 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1011 *pcbEncoded
= bytesNeeded
;
1017 static int BLOBComp(const void *l
, const void *r
)
1019 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1022 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1023 ret
= a
->cbData
- b
->cbData
;
1027 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1029 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1030 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1033 CRYPT_DER_BLOB
*blobs
= NULL
;
1037 DWORD bytesNeeded
= 0, lenBytes
, i
;
1043 blobs
= CryptMemAlloc(rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1047 memset(blobs
, 0, rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1049 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1051 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1052 NULL
, &blobs
[i
].cbData
);
1054 bytesNeeded
+= blobs
[i
].cbData
;
1058 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1059 bytesNeeded
+= 1 + lenBytes
;
1062 if (*pcbEncoded
< bytesNeeded
)
1064 SetLastError(ERROR_MORE_DATA
);
1069 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1071 blobs
[i
].pbData
= CryptMemAlloc(blobs
[i
].cbData
);
1072 if (!blobs
[i
].pbData
)
1075 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1076 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1081 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1083 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1084 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1086 pbEncoded
+= lenBytes
;
1087 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1089 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1090 pbEncoded
+= blobs
[i
].cbData
;
1095 *pcbEncoded
= bytesNeeded
;
1099 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1100 CryptMemFree(blobs
[i
].pbData
);
1105 SetLastError(STATUS_ACCESS_VIOLATION
);
1109 CryptMemFree(blobs
);
1113 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1114 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1115 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1121 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1122 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1124 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1126 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1128 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1131 bytesNeeded
+= size
;
1133 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1134 bytesNeeded
+= 1 + lenBytes
;
1138 *pcbEncoded
= bytesNeeded
;
1141 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1142 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1144 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1145 pbEncoded
= *(BYTE
**)pbEncoded
;
1146 *pbEncoded
++ = ASN_SEQUENCEOF
;
1147 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1149 pbEncoded
+= lenBytes
;
1150 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1153 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1154 &info
->rgRDN
[i
], pbEncoded
, &size
);
1158 bytesNeeded
-= size
;
1167 SetLastError(STATUS_ACCESS_VIOLATION
);
1174 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1175 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1176 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1178 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1187 else if (*pcbEncoded
< 3)
1190 SetLastError(ERROR_MORE_DATA
);
1196 *pbEncoded
++ = ASN_BOOL
;
1198 *pbEncoded
++ = val
? 0xff : 0;
1201 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1205 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1206 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1212 switch (entry
->dwAltNameChoice
)
1214 case CERT_ALT_NAME_RFC822_NAME
:
1215 case CERT_ALT_NAME_DNS_NAME
:
1216 case CERT_ALT_NAME_URL
:
1217 if (entry
->u
.pwszURL
)
1221 /* Not + 1: don't encode the NULL-terminator */
1222 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1223 for (i
= 0; ret
&& i
< dataLen
; i
++)
1225 if (entry
->u
.pwszURL
[i
] > 0x7f)
1227 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1236 case CERT_ALT_NAME_IP_ADDRESS
:
1237 dataLen
= entry
->u
.IPAddress
.cbData
;
1239 case CERT_ALT_NAME_REGISTERED_ID
:
1240 /* FIXME: encode OID */
1241 case CERT_ALT_NAME_OTHER_NAME
:
1242 case CERT_ALT_NAME_DIRECTORY_NAME
:
1243 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1246 SetLastError(E_INVALIDARG
);
1251 DWORD bytesNeeded
, lenBytes
;
1253 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1254 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1256 *pcbEncoded
= bytesNeeded
;
1257 else if (*pcbEncoded
< bytesNeeded
)
1259 SetLastError(ERROR_MORE_DATA
);
1260 *pcbEncoded
= bytesNeeded
;
1265 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1266 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1267 pbEncoded
+= lenBytes
;
1268 switch (entry
->dwAltNameChoice
)
1270 case CERT_ALT_NAME_RFC822_NAME
:
1271 case CERT_ALT_NAME_DNS_NAME
:
1272 case CERT_ALT_NAME_URL
:
1276 for (i
= 0; i
< dataLen
; i
++)
1277 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1280 case CERT_ALT_NAME_IP_ADDRESS
:
1281 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1285 *pcbEncoded
= bytesNeeded
;
1288 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1292 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1293 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1294 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1300 const CERT_ALT_NAME_INFO
*info
=
1301 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1302 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1305 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1306 * can't encode an erroneous entry index if it's bigger than this.
1308 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1312 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1316 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1318 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1319 * the bad character, now set the index of the bad
1322 *pcbEncoded
= (BYTE
)i
<<
1323 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1328 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1329 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1332 *pcbEncoded
= bytesNeeded
;
1337 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1338 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1340 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1341 pbEncoded
= *(BYTE
**)pbEncoded
;
1342 *pbEncoded
++ = ASN_SEQUENCEOF
;
1343 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1344 pbEncoded
+= lenBytes
;
1345 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1347 DWORD len
= dataLen
;
1349 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1363 SetLastError(STATUS_ACCESS_VIOLATION
);
1370 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
1371 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1372 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1378 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
1379 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
1380 struct AsnEncodeSequenceItem items
[3] = {
1381 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
1386 if (info
->fPathLenConstraint
)
1388 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1389 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1392 if (info
->cSubtreesConstraint
)
1394 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
1395 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
1398 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1399 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1403 SetLastError(STATUS_ACCESS_VIOLATION
);
1410 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1411 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1412 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1418 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1419 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1420 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1425 items
[cItem
].pvStructInfo
= &info
->fCA
;
1426 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1429 if (info
->fPathLenConstraint
)
1431 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1432 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1435 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1436 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1440 SetLastError(STATUS_ACCESS_VIOLATION
);
1447 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1448 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1449 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1455 const BLOBHEADER
*hdr
=
1456 (const BLOBHEADER
*)pvStructInfo
;
1458 if (hdr
->bType
!= PUBLICKEYBLOB
)
1460 SetLastError(E_INVALIDARG
);
1465 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1466 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1467 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1468 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1469 struct AsnEncodeSequenceItem items
[] = {
1470 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
1471 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1474 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1475 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1481 SetLastError(STATUS_ACCESS_VIOLATION
);
1488 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1489 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1490 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1496 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1497 DWORD bytesNeeded
, lenBytes
;
1499 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1500 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1502 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1503 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1506 *pcbEncoded
= bytesNeeded
;
1511 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1512 pcbEncoded
, bytesNeeded
)))
1514 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1515 pbEncoded
= *(BYTE
**)pbEncoded
;
1516 *pbEncoded
++ = ASN_OCTETSTRING
;
1517 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1518 pbEncoded
+= lenBytes
;
1520 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1526 SetLastError(STATUS_ACCESS_VIOLATION
);
1530 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1534 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1535 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1536 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1542 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1543 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1546 /* yep, MS allows cUnusedBits to be >= 8 */
1547 if (!blob
->cUnusedBits
)
1549 dataBytes
= blob
->cbData
;
1552 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1554 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1555 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1563 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1564 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1567 *pcbEncoded
= bytesNeeded
;
1572 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1573 pcbEncoded
, bytesNeeded
)))
1575 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1576 pbEncoded
= *(BYTE
**)pbEncoded
;
1577 *pbEncoded
++ = ASN_BITSTRING
;
1578 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1579 pbEncoded
+= lenBytes
;
1580 *pbEncoded
++ = unusedBits
;
1583 BYTE mask
= 0xff << unusedBits
;
1587 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1588 pbEncoded
+= dataBytes
- 1;
1590 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1597 SetLastError(STATUS_ACCESS_VIOLATION
);
1604 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1605 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1606 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1612 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1613 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1618 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
1623 for (i
= 0; i
< newBlob
.cbData
; i
++)
1624 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1630 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1631 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1632 CryptMemFree(newBlob
.pbData
);
1636 SetLastError(STATUS_ACCESS_VIOLATION
);
1643 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1644 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1645 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1647 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1649 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1650 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1653 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1654 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1655 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1661 DWORD significantBytes
, lenBytes
;
1662 BYTE padByte
= 0, bytesNeeded
;
1664 const CRYPT_INTEGER_BLOB
*blob
=
1665 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1667 significantBytes
= blob
->cbData
;
1668 if (significantBytes
)
1670 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1672 /* negative, lop off leading (little-endian) 0xffs */
1673 for (; significantBytes
> 0 &&
1674 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1676 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1684 /* positive, lop off leading (little-endian) zeroes */
1685 for (; significantBytes
> 0 &&
1686 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1688 if (significantBytes
== 0)
1689 significantBytes
= 1;
1690 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1698 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1700 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1701 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1706 *pcbEncoded
= bytesNeeded
;
1711 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1712 pcbEncoded
, bytesNeeded
)))
1714 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1715 pbEncoded
= *(BYTE
**)pbEncoded
;
1716 *pbEncoded
++ = ASN_INTEGER
;
1719 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1720 pbEncoded
+= lenBytes
;
1721 *pbEncoded
++ = padByte
;
1725 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1726 pbEncoded
+= lenBytes
;
1728 for (; significantBytes
> 0; significantBytes
--)
1729 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1735 SetLastError(STATUS_ACCESS_VIOLATION
);
1742 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1743 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1744 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1750 DWORD significantBytes
, lenBytes
;
1753 const CRYPT_INTEGER_BLOB
*blob
=
1754 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1756 significantBytes
= blob
->cbData
;
1757 if (significantBytes
)
1759 /* positive, lop off leading (little-endian) zeroes */
1760 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
1763 if (significantBytes
== 0)
1764 significantBytes
= 1;
1765 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1769 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1771 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1772 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1777 *pcbEncoded
= bytesNeeded
;
1782 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1783 pcbEncoded
, bytesNeeded
)))
1785 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1786 pbEncoded
= *(BYTE
**)pbEncoded
;
1787 *pbEncoded
++ = ASN_INTEGER
;
1790 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1791 pbEncoded
+= lenBytes
;
1796 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1797 pbEncoded
+= lenBytes
;
1799 for (; significantBytes
> 0; significantBytes
--)
1800 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1806 SetLastError(STATUS_ACCESS_VIOLATION
);
1813 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
1814 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1815 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1817 CRYPT_INTEGER_BLOB blob
;
1820 /* Encode as an unsigned integer, then change the tag to enumerated */
1821 blob
.cbData
= sizeof(DWORD
);
1822 blob
.pbData
= (BYTE
*)pvStructInfo
;
1823 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
1824 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1825 if (ret
&& pbEncoded
)
1827 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1828 pbEncoded
= *(BYTE
**)pbEncoded
;
1829 pbEncoded
[0] = ASN_ENUMERATED
;
1834 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
1835 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1836 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1843 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
1844 * temporary buffer because the output buffer is not NULL-terminated.
1847 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1851 *pcbEncoded
= bytesNeeded
;
1856 /* Sanity check the year, this is a two-digit year format */
1857 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1859 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
1861 SetLastError(CRYPT_E_BAD_ENCODE
);
1866 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1867 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1869 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1870 pbEncoded
= *(BYTE
**)pbEncoded
;
1871 buf
[0] = ASN_UTCTIME
;
1872 buf
[1] = bytesNeeded
- 2;
1873 snprintf(buf
+ 2, sizeof(buf
) - 2,
1874 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
1875 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
1876 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
1877 sysTime
.wMinute
, sysTime
.wSecond
);
1878 memcpy(pbEncoded
, buf
, bytesNeeded
);
1885 SetLastError(STATUS_ACCESS_VIOLATION
);
1892 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
1893 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1894 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1901 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
1902 * temporary buffer because the output buffer is not NULL-terminated.
1905 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1909 *pcbEncoded
= bytesNeeded
;
1914 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1917 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1918 pcbEncoded
, bytesNeeded
);
1921 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1922 pbEncoded
= *(BYTE
**)pbEncoded
;
1923 buf
[0] = ASN_GENERALTIME
;
1924 buf
[1] = bytesNeeded
- 2;
1925 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
1926 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
1927 sysTime
.wMinute
, sysTime
.wSecond
);
1928 memcpy(pbEncoded
, buf
, bytesNeeded
);
1934 SetLastError(STATUS_ACCESS_VIOLATION
);
1941 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
1942 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1943 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1951 /* Check the year, if it's in the UTCTime range call that encode func */
1952 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
1954 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
1955 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
1956 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1958 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
1959 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1964 SetLastError(STATUS_ACCESS_VIOLATION
);
1971 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
1972 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1973 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1979 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1980 const CRYPT_SEQUENCE_OF_ANY
*seq
=
1981 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
1983 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
1984 dataLen
+= seq
->rgValue
[i
].cbData
;
1985 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1986 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1989 *pcbEncoded
= bytesNeeded
;
1994 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1995 pcbEncoded
, bytesNeeded
)))
1997 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1998 pbEncoded
= *(BYTE
**)pbEncoded
;
1999 *pbEncoded
++ = ASN_SEQUENCEOF
;
2000 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2001 pbEncoded
+= lenBytes
;
2002 for (i
= 0; i
< seq
->cValue
; i
++)
2004 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2005 seq
->rgValue
[i
].cbData
);
2006 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2013 SetLastError(STATUS_ACCESS_VIOLATION
);
2020 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2021 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2024 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2025 struct AsnConstructedItem constructed
= { 0 };
2026 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2027 DWORD cItem
= 0, cSwapped
= 0;
2029 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2031 case CRL_DIST_POINT_NO_NAME
:
2034 case CRL_DIST_POINT_FULL_NAME
:
2035 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2036 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2037 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2038 constructed
.tag
= 0;
2039 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2040 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2041 items
[cItem
].pvStructInfo
= &constructed
;
2042 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2046 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2047 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2053 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2055 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2056 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2057 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2058 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2059 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2063 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2065 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2066 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2067 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2068 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2069 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2074 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2075 pbEncoded
, pcbEncoded
);
2079 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2080 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2081 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2087 const CRL_DIST_POINTS_INFO
*info
=
2088 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2090 if (!info
->cDistPoint
)
2092 SetLastError(E_INVALIDARG
);
2097 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2100 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2104 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2108 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2110 /* Have to propagate index of failing character */
2116 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2117 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2120 *pcbEncoded
= bytesNeeded
;
2125 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2126 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2128 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2129 pbEncoded
= *(BYTE
**)pbEncoded
;
2130 *pbEncoded
++ = ASN_SEQUENCEOF
;
2131 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2132 pbEncoded
+= lenBytes
;
2133 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2135 DWORD len
= dataLen
;
2137 ret
= CRYPT_AsnEncodeDistPoint(
2138 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
2152 SetLastError(STATUS_ACCESS_VIOLATION
);
2159 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
2160 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2161 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2167 const CERT_ENHKEY_USAGE
*usage
=
2168 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
2169 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2172 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2174 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2175 usage
->rgpszUsageIdentifier
[i
],
2176 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2178 bytesNeeded
+= size
;
2180 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2181 bytesNeeded
+= 1 + lenBytes
;
2185 *pcbEncoded
= bytesNeeded
;
2188 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2189 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2191 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2192 pbEncoded
= *(BYTE
**)pbEncoded
;
2193 *pbEncoded
++ = ASN_SEQUENCEOF
;
2194 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2196 pbEncoded
+= lenBytes
;
2197 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2200 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2201 usage
->rgpszUsageIdentifier
[i
],
2202 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2207 bytesNeeded
-= size
;
2216 SetLastError(STATUS_ACCESS_VIOLATION
);
2223 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2224 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2225 void *pvEncoded
, DWORD
*pcbEncoded
)
2227 static HCRYPTOIDFUNCSET set
= NULL
;
2229 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2230 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2232 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2233 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2234 pvEncoded
, pcbEncoded
);
2236 if (!pvEncoded
&& !pcbEncoded
)
2238 SetLastError(ERROR_INVALID_PARAMETER
);
2241 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2242 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2244 SetLastError(ERROR_FILE_NOT_FOUND
);
2248 SetLastError(NOERROR
);
2249 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2250 *(BYTE
**)pvEncoded
= NULL
;
2251 if (!HIWORD(lpszStructType
))
2253 switch (LOWORD(lpszStructType
))
2255 case (WORD
)X509_CERT
:
2256 encodeFunc
= CRYPT_AsnEncodeCert
;
2258 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2259 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2261 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2262 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2264 case (WORD
)X509_EXTENSIONS
:
2265 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2267 case (WORD
)X509_NAME
:
2268 encodeFunc
= CRYPT_AsnEncodeName
;
2270 case (WORD
)X509_PUBLIC_KEY_INFO
:
2271 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2273 case (WORD
)X509_ALTERNATE_NAME
:
2274 encodeFunc
= CRYPT_AsnEncodeAltName
;
2276 case (WORD
)X509_BASIC_CONSTRAINTS
:
2277 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
2279 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2280 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2282 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2283 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2285 case (WORD
)X509_OCTET_STRING
:
2286 encodeFunc
= CRYPT_AsnEncodeOctets
;
2288 case (WORD
)X509_BITS
:
2289 case (WORD
)X509_KEY_USAGE
:
2290 encodeFunc
= CRYPT_AsnEncodeBits
;
2292 case (WORD
)X509_INTEGER
:
2293 encodeFunc
= CRYPT_AsnEncodeInt
;
2295 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2296 encodeFunc
= CRYPT_AsnEncodeInteger
;
2298 case (WORD
)X509_MULTI_BYTE_UINT
:
2299 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2301 case (WORD
)X509_ENUMERATED
:
2302 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2304 case (WORD
)X509_CHOICE_OF_TIME
:
2305 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2307 case (WORD
)X509_SEQUENCE_OF_ANY
:
2308 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2310 case (WORD
)PKCS_UTC_TIME
:
2311 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2313 case (WORD
)X509_CRL_DIST_POINTS
:
2314 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
2316 case (WORD
)X509_ENHANCED_KEY_USAGE
:
2317 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
2320 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2323 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2324 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2325 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2326 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2327 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2328 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2329 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2330 encodeFunc
= CRYPT_AsnEncodeBits
;
2331 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2332 encodeFunc
= CRYPT_AsnEncodeOctets
;
2333 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
2334 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
2335 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2336 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2337 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2338 encodeFunc
= CRYPT_AsnEncodeAltName
;
2339 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2340 encodeFunc
= CRYPT_AsnEncodeAltName
;
2341 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2342 encodeFunc
= CRYPT_AsnEncodeAltName
;
2343 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2344 encodeFunc
= CRYPT_AsnEncodeAltName
;
2345 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2346 encodeFunc
= CRYPT_AsnEncodeAltName
;
2347 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2348 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
2349 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2350 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
2352 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2353 debugstr_a(lpszStructType
));
2357 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
2358 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2359 (void **)&encodeFunc
, &hFunc
);
2362 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2363 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2365 SetLastError(ERROR_FILE_NOT_FOUND
);
2367 CryptFreeOIDFunctionAddress(hFunc
, 0);
2371 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
2372 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
2374 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
2375 NULL
, 0, NULL
, pInfo
, pcbInfo
);
2378 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
2379 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
2380 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
2385 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
2386 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
2389 if (!pszPublicKeyObjId
)
2390 pszPublicKeyObjId
= szOID_RSA_RSA
;
2391 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
2395 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
2398 LPBYTE pubKey
= CryptMemAlloc(keySize
);
2402 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
2406 DWORD encodedLen
= 0;
2408 ret
= CryptEncodeObject(dwCertEncodingType
,
2409 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
2412 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
2413 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
2416 *pcbInfo
= sizeNeeded
;
2417 else if (*pcbInfo
< sizeNeeded
)
2419 SetLastError(ERROR_MORE_DATA
);
2420 *pcbInfo
= sizeNeeded
;
2425 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
2426 sizeof(CERT_PUBLIC_KEY_INFO
);
2427 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
2429 pInfo
->Algorithm
.Parameters
.cbData
= 0;
2430 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
2431 pInfo
->PublicKey
.pbData
=
2432 (BYTE
*)pInfo
->Algorithm
.pszObjId
2433 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
2434 pInfo
->PublicKey
.cbData
= encodedLen
;
2435 pInfo
->PublicKey
.cUnusedBits
= 0;
2436 ret
= CryptEncodeObject(dwCertEncodingType
,
2437 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
2438 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
2442 CryptMemFree(pubKey
);
2447 CryptDestroyKey(key
);
2452 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
2453 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
2454 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
2456 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
2457 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
2458 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
2460 static HCRYPTOIDFUNCSET set
= NULL
;
2462 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
2463 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2465 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
2466 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
2471 SetLastError(ERROR_INVALID_PARAMETER
);
2475 if (pszPublicKeyObjId
)
2478 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
2480 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
2481 0, (void **)&exportFunc
, &hFunc
);
2484 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
2485 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
2486 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
2488 CryptFreeOIDFunctionAddress(hFunc
, 0);
2492 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
2493 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
2495 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
2499 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
2500 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
2501 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
2504 DWORD pubKeySize
= 0;
2506 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
2507 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
2509 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
2510 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
2513 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
2517 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
2518 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
2521 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
2523 CryptMemFree(pubKey
);
2531 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
2532 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
2533 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
2535 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
2536 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
2537 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
2539 static HCRYPTOIDFUNCSET set
= NULL
;
2541 ImportPublicKeyInfoExFunc importFunc
= NULL
;
2542 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2544 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
2545 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
2548 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
2549 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
2550 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
2552 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
2553 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
2556 CryptFreeOIDFunctionAddress(hFunc
, 0);