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 const CRYPT_SET_OF
*set
= (const 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 *pcbEncoded
= bytesNeeded
;
1192 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1193 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1195 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1196 pbEncoded
= *(BYTE
**)pbEncoded
;
1197 qsort(set
->rgValue
, set
->cValue
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1198 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1199 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1200 pbEncoded
+= lenBytes
;
1201 for (i
= 0; ret
&& i
< set
->cValue
; i
++)
1203 memcpy(pbEncoded
, set
->rgValue
[i
].pbData
, set
->rgValue
[i
].cbData
);
1204 pbEncoded
+= set
->rgValue
[i
].cbData
;
1210 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1211 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1215 CRYPT_SET_OF setOf
= { 0, NULL
};
1224 setOf
.cValue
= rdn
->cRDNAttr
;
1225 setOf
.rgValue
= CryptMemAlloc(rdn
->cRDNAttr
*
1226 sizeof(CRYPT_DER_BLOB
));
1230 memset(setOf
.rgValue
, 0, setOf
.cValue
* sizeof(CRYPT_DER_BLOB
));
1232 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1234 setOf
.rgValue
[i
].cbData
= 0;
1235 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1236 nameValueEncodeFunc
, NULL
, &setOf
.rgValue
[i
].cbData
);
1239 setOf
.rgValue
[i
].pbData
=
1240 CryptMemAlloc(setOf
.rgValue
[i
].cbData
);
1241 if (!setOf
.rgValue
[i
].pbData
)
1244 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1245 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1246 setOf
.rgValue
[i
].pbData
, &setOf
.rgValue
[i
].cbData
);
1250 /* Have to propagate index of failing character */
1251 *pcbEncoded
= setOf
.rgValue
[i
].cbData
;
1255 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1256 pbEncoded
, pcbEncoded
);
1257 for (i
= 0; i
< setOf
.cValue
; i
++)
1258 CryptMemFree(setOf
.rgValue
[i
].pbData
);
1262 SetLastError(STATUS_ACCESS_VIOLATION
);
1266 CryptMemFree(setOf
.rgValue
);
1270 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1271 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1272 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1274 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1275 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1276 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1279 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1282 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1283 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1284 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1286 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1287 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1291 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1292 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1293 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1299 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1300 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1302 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1304 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1306 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1307 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1309 bytesNeeded
+= size
;
1313 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1314 bytesNeeded
+= 1 + lenBytes
;
1318 *pcbEncoded
= bytesNeeded
;
1321 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1322 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1324 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1325 pbEncoded
= *(BYTE
**)pbEncoded
;
1326 *pbEncoded
++ = ASN_SEQUENCEOF
;
1327 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1329 pbEncoded
+= lenBytes
;
1330 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1333 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1334 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1339 bytesNeeded
-= size
;
1350 SetLastError(STATUS_ACCESS_VIOLATION
);
1357 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1358 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1359 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1365 const CRYPT_ATTRIBUTE
*attr
= (const CRYPT_ATTRIBUTE
*)pvStructInfo
;
1367 if (!attr
->pszObjId
)
1368 SetLastError(E_INVALIDARG
);
1371 struct AsnEncodeSequenceItem items
[2] = {
1372 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1373 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1376 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1377 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1383 SetLastError(STATUS_ACCESS_VIOLATION
);
1389 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1390 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1391 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1394 CRYPT_SET_OF setOf
= { 0, NULL
};
1399 const CRYPT_ATTRIBUTES
*attributes
=
1400 (const CRYPT_ATTRIBUTES
*)pvStructInfo
;
1403 if (attributes
->cAttr
)
1405 setOf
.cValue
= attributes
->cAttr
;
1406 setOf
.rgValue
= CryptMemAlloc(attributes
->cAttr
*
1407 sizeof(CRYPT_DER_BLOB
));
1411 memset(setOf
.rgValue
, 0, setOf
.cValue
* sizeof(CRYPT_DER_BLOB
));
1413 for (i
= 0; ret
&& i
< attributes
->cAttr
; i
++)
1415 ret
= CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType
, NULL
,
1416 &attributes
->rgAttr
[i
], 0, NULL
, NULL
, &setOf
.rgValue
[i
].cbData
);
1419 setOf
.rgValue
[i
].pbData
=
1420 CryptMemAlloc(setOf
.rgValue
[i
].cbData
);
1421 if (!setOf
.rgValue
[i
].pbData
)
1425 ret
= CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType
, NULL
,
1426 &attributes
->rgAttr
[i
], 0, NULL
, setOf
.rgValue
[i
].pbData
,
1427 &setOf
.rgValue
[i
].cbData
);
1432 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, dwFlags
,
1433 pEncodePara
, pbEncoded
, pcbEncoded
);
1434 for (i
= 0; i
< setOf
.cValue
; i
++)
1435 CryptMemFree(setOf
.rgValue
[i
].pbData
);
1439 SetLastError(STATUS_ACCESS_VIOLATION
);
1442 CryptMemFree(setOf
.rgValue
);
1446 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1447 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1448 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1454 const CRYPT_CONTENT_INFO
*info
=
1455 (const CRYPT_CONTENT_INFO
*)pvStructInfo
;
1457 if (!info
->pszObjId
)
1458 SetLastError(E_INVALIDARG
);
1461 struct AsnEncodeSequenceItem items
[2] = {
1462 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1465 struct AsnConstructedItem constructed
= { 0 };
1468 if (info
->Content
.cbData
)
1470 constructed
.tag
= 0;
1471 constructed
.pvStructInfo
= &info
->Content
;
1472 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1473 items
[cItem
].pvStructInfo
= &constructed
;
1474 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1477 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1478 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1484 SetLastError(STATUS_ACCESS_VIOLATION
);
1490 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1491 BYTE tag
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1495 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1496 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1498 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1500 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1501 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1503 *pcbEncoded
= bytesNeeded
;
1506 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1507 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1511 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1512 pbEncoded
= *(BYTE
**)pbEncoded
;
1514 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1515 pbEncoded
+= lenBytes
;
1516 for (i
= 0; i
< encodedLen
; i
++)
1517 *pbEncoded
++ = (BYTE
)str
[i
];
1523 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
1524 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1528 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1529 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1531 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1533 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1534 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1536 *pcbEncoded
= bytesNeeded
;
1539 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1540 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1544 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1545 pbEncoded
= *(BYTE
**)pbEncoded
;
1546 *pbEncoded
++ = ASN_NUMERICSTRING
;
1547 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1548 pbEncoded
+= lenBytes
;
1549 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1551 if (isdigitW(str
[i
]))
1552 *pbEncoded
++ = (BYTE
)str
[i
];
1556 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
1565 static inline int isprintableW(WCHAR wc
)
1567 return isalnumW(wc
) || isspaceW(wc
) || wc
== '\'' || wc
== '(' ||
1568 wc
== ')' || wc
== '+' || wc
== ',' || wc
== '-' || wc
== '.' ||
1569 wc
== '/' || wc
== ':' || wc
== '=' || wc
== '?';
1572 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
1573 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1577 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1578 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1580 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1582 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1583 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1585 *pcbEncoded
= bytesNeeded
;
1588 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1589 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1593 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1594 pbEncoded
= *(BYTE
**)pbEncoded
;
1595 *pbEncoded
++ = ASN_PRINTABLESTRING
;
1596 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1597 pbEncoded
+= lenBytes
;
1598 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1600 if (isprintableW(str
[i
]))
1601 *pbEncoded
++ = (BYTE
)str
[i
];
1605 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
1614 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
1615 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1619 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1620 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1622 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1624 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1625 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1627 *pcbEncoded
= bytesNeeded
;
1630 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1631 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1635 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1636 pbEncoded
= *(BYTE
**)pbEncoded
;
1637 *pbEncoded
++ = ASN_IA5STRING
;
1638 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1639 pbEncoded
+= lenBytes
;
1640 for (i
= 0; ret
&& i
< encodedLen
; i
++)
1643 *pbEncoded
++ = (BYTE
)str
[i
];
1647 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1656 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
1657 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1661 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1662 DWORD bytesNeeded
, lenBytes
, strLen
;
1664 /* FIXME: doesn't handle composite characters */
1665 strLen
= value
->Value
.cbData
? value
->Value
.cbData
/ sizeof(WCHAR
) :
1667 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
1668 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
1670 *pcbEncoded
= bytesNeeded
;
1673 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1674 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1678 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1679 pbEncoded
= *(BYTE
**)pbEncoded
;
1680 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
1681 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
1682 pbEncoded
+= lenBytes
;
1683 for (i
= 0; i
< strLen
; i
++)
1687 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
1688 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
1695 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1696 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1697 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1703 const CERT_NAME_VALUE
*value
= (const CERT_NAME_VALUE
*)pvStructInfo
;
1705 switch (value
->dwValueType
)
1707 case CERT_RDN_ANY_TYPE
:
1708 case CERT_RDN_ENCODED_BLOB
:
1709 case CERT_RDN_OCTET_STRING
:
1710 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
1712 case CERT_RDN_NUMERIC_STRING
:
1713 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
1714 pbEncoded
, pcbEncoded
);
1716 case CERT_RDN_PRINTABLE_STRING
:
1717 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
1718 pbEncoded
, pcbEncoded
);
1720 case CERT_RDN_TELETEX_STRING
:
1721 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
1722 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1724 case CERT_RDN_VIDEOTEX_STRING
:
1725 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
1726 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1728 case CERT_RDN_IA5_STRING
:
1729 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
1730 pbEncoded
, pcbEncoded
);
1732 case CERT_RDN_GRAPHIC_STRING
:
1733 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1734 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1736 case CERT_RDN_VISIBLE_STRING
:
1737 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
1738 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1740 case CERT_RDN_GENERAL_STRING
:
1741 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
1742 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1744 case CERT_RDN_UNIVERSAL_STRING
:
1745 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
1746 pbEncoded
, pcbEncoded
);
1748 case CERT_RDN_BMP_STRING
:
1749 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1750 pbEncoded
, pcbEncoded
);
1752 case CERT_RDN_UTF8_STRING
:
1753 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1754 pbEncoded
, pcbEncoded
);
1757 SetLastError(CRYPT_E_ASN1_CHOICE
);
1762 SetLastError(STATUS_ACCESS_VIOLATION
);
1768 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1769 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1770 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1776 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1777 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1779 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1781 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1783 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1784 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
1786 bytesNeeded
+= size
;
1788 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1789 bytesNeeded
+= 1 + lenBytes
;
1793 *pcbEncoded
= bytesNeeded
;
1796 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1797 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1799 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1800 pbEncoded
= *(BYTE
**)pbEncoded
;
1801 *pbEncoded
++ = ASN_SEQUENCEOF
;
1802 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1804 pbEncoded
+= lenBytes
;
1805 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1808 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1809 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, pbEncoded
,
1814 bytesNeeded
-= size
;
1823 SetLastError(STATUS_ACCESS_VIOLATION
);
1830 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1831 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1832 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1834 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1843 else if (*pcbEncoded
< 3)
1846 SetLastError(ERROR_MORE_DATA
);
1852 *pbEncoded
++ = ASN_BOOL
;
1854 *pbEncoded
++ = val
? 0xff : 0;
1857 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1861 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1862 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1868 switch (entry
->dwAltNameChoice
)
1870 case CERT_ALT_NAME_RFC822_NAME
:
1871 case CERT_ALT_NAME_DNS_NAME
:
1872 case CERT_ALT_NAME_URL
:
1873 if (entry
->u
.pwszURL
)
1877 /* Not + 1: don't encode the NULL-terminator */
1878 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1879 for (i
= 0; ret
&& i
< dataLen
; i
++)
1881 if (entry
->u
.pwszURL
[i
] > 0x7f)
1883 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1892 case CERT_ALT_NAME_IP_ADDRESS
:
1893 dataLen
= entry
->u
.IPAddress
.cbData
;
1895 case CERT_ALT_NAME_REGISTERED_ID
:
1896 /* FIXME: encode OID */
1897 case CERT_ALT_NAME_OTHER_NAME
:
1898 case CERT_ALT_NAME_DIRECTORY_NAME
:
1899 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
1902 SetLastError(E_INVALIDARG
);
1907 DWORD bytesNeeded
, lenBytes
;
1909 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1910 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1912 *pcbEncoded
= bytesNeeded
;
1913 else if (*pcbEncoded
< bytesNeeded
)
1915 SetLastError(ERROR_MORE_DATA
);
1916 *pcbEncoded
= bytesNeeded
;
1921 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1922 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1923 pbEncoded
+= lenBytes
;
1924 switch (entry
->dwAltNameChoice
)
1926 case CERT_ALT_NAME_RFC822_NAME
:
1927 case CERT_ALT_NAME_DNS_NAME
:
1928 case CERT_ALT_NAME_URL
:
1932 for (i
= 0; i
< dataLen
; i
++)
1933 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1936 case CERT_ALT_NAME_IP_ADDRESS
:
1937 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1941 *pcbEncoded
= bytesNeeded
;
1944 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1948 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
1949 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1950 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1956 const CERT_AUTHORITY_KEY_ID_INFO
*info
=
1957 (const CERT_AUTHORITY_KEY_ID_INFO
*)pvStructInfo
;
1958 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
1959 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
1960 struct AsnConstructedItem constructed
= { 0 };
1961 DWORD cItem
= 0, cSwapped
= 0;
1963 if (info
->KeyId
.cbData
)
1965 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
1966 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
1967 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1968 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
1969 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
1973 if (info
->CertIssuer
.cbData
)
1975 constructed
.tag
= 1;
1976 constructed
.pvStructInfo
= &info
->CertIssuer
;
1977 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1978 items
[cItem
].pvStructInfo
= &constructed
;
1979 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1982 if (info
->CertSerialNumber
.cbData
)
1984 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
1985 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
1986 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1987 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
1988 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
1992 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
1993 pEncodePara
, pbEncoded
, pcbEncoded
);
1997 SetLastError(STATUS_ACCESS_VIOLATION
);
2004 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2005 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2006 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2012 const CERT_ALT_NAME_INFO
*info
=
2013 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
2014 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2017 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2018 * can't encode an erroneous entry index if it's bigger than this.
2020 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2024 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
2028 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2030 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2031 * the bad character, now set the index of the bad
2034 *pcbEncoded
= (BYTE
)i
<<
2035 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2040 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2041 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2044 *pcbEncoded
= bytesNeeded
;
2049 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2050 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2052 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2053 pbEncoded
= *(BYTE
**)pbEncoded
;
2054 *pbEncoded
++ = ASN_SEQUENCEOF
;
2055 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2056 pbEncoded
+= lenBytes
;
2057 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2059 DWORD len
= dataLen
;
2061 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
2075 SetLastError(STATUS_ACCESS_VIOLATION
);
2082 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2083 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2084 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2090 const CERT_AUTHORITY_KEY_ID2_INFO
*info
=
2091 (const CERT_AUTHORITY_KEY_ID2_INFO
*)pvStructInfo
;
2092 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2093 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2094 DWORD cItem
= 0, cSwapped
= 0;
2096 if (info
->KeyId
.cbData
)
2098 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2099 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2100 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2101 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2102 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2106 if (info
->AuthorityCertIssuer
.cAltEntry
)
2108 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2109 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2110 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2111 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2112 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2116 if (info
->AuthorityCertSerialNumber
.cbData
)
2118 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2119 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2120 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2121 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2122 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2126 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2127 pEncodePara
, pbEncoded
, pcbEncoded
);
2131 SetLastError(STATUS_ACCESS_VIOLATION
);
2138 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2139 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2140 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2146 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
2147 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
2148 struct AsnEncodeSequenceItem items
[3] = {
2149 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2154 if (info
->fPathLenConstraint
)
2156 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2157 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2160 if (info
->cSubtreesConstraint
)
2162 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2163 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2166 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2167 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2171 SetLastError(STATUS_ACCESS_VIOLATION
);
2178 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2179 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2180 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2186 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
2187 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
2188 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2193 items
[cItem
].pvStructInfo
= &info
->fCA
;
2194 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2197 if (info
->fPathLenConstraint
)
2199 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2200 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2203 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2204 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2208 SetLastError(STATUS_ACCESS_VIOLATION
);
2215 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
2216 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2217 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2223 const BLOBHEADER
*hdr
=
2224 (const BLOBHEADER
*)pvStructInfo
;
2226 if (hdr
->bType
!= PUBLICKEYBLOB
)
2228 SetLastError(E_INVALIDARG
);
2233 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
2234 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
2235 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
2236 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
2237 struct AsnEncodeSequenceItem items
[] = {
2238 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
2239 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
2242 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
2243 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
2249 SetLastError(STATUS_ACCESS_VIOLATION
);
2256 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
2257 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2258 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2264 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
2265 DWORD bytesNeeded
, lenBytes
;
2267 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
2268 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
2270 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
2271 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
2274 *pcbEncoded
= bytesNeeded
;
2279 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2280 pcbEncoded
, bytesNeeded
)))
2282 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2283 pbEncoded
= *(BYTE
**)pbEncoded
;
2284 *pbEncoded
++ = ASN_OCTETSTRING
;
2285 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
2286 pbEncoded
+= lenBytes
;
2288 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
2294 SetLastError(STATUS_ACCESS_VIOLATION
);
2298 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2302 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
2303 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2304 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2310 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2311 DWORD bytesNeeded
, lenBytes
, dataBytes
;
2314 /* yep, MS allows cUnusedBits to be >= 8 */
2315 if (!blob
->cUnusedBits
)
2317 dataBytes
= blob
->cbData
;
2320 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
2322 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
2323 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
2331 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
2332 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
2335 *pcbEncoded
= bytesNeeded
;
2340 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2341 pcbEncoded
, bytesNeeded
)))
2343 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2344 pbEncoded
= *(BYTE
**)pbEncoded
;
2345 *pbEncoded
++ = ASN_BITSTRING
;
2346 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
2347 pbEncoded
+= lenBytes
;
2348 *pbEncoded
++ = unusedBits
;
2351 BYTE mask
= 0xff << unusedBits
;
2355 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
2356 pbEncoded
+= dataBytes
- 1;
2358 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
2365 SetLastError(STATUS_ACCESS_VIOLATION
);
2372 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
2373 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2374 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2380 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
2381 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
2386 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
2391 for (i
= 0; i
< newBlob
.cbData
; i
++)
2392 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
2398 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
2399 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2400 CryptMemFree(newBlob
.pbData
);
2404 SetLastError(STATUS_ACCESS_VIOLATION
);
2411 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
2412 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2413 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2415 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
2417 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
2418 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2421 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
2422 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2423 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2429 DWORD significantBytes
, lenBytes
;
2430 BYTE padByte
= 0, bytesNeeded
;
2432 const CRYPT_INTEGER_BLOB
*blob
=
2433 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2435 significantBytes
= blob
->cbData
;
2436 if (significantBytes
)
2438 if (blob
->pbData
[significantBytes
- 1] & 0x80)
2440 /* negative, lop off leading (little-endian) 0xffs */
2441 for (; significantBytes
> 0 &&
2442 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
2444 if (blob
->pbData
[significantBytes
- 1] < 0x80)
2452 /* positive, lop off leading (little-endian) zeroes */
2453 for (; significantBytes
> 0 &&
2454 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
2456 if (significantBytes
== 0)
2457 significantBytes
= 1;
2458 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2466 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2468 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2469 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2474 *pcbEncoded
= bytesNeeded
;
2479 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2480 pcbEncoded
, bytesNeeded
)))
2482 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2483 pbEncoded
= *(BYTE
**)pbEncoded
;
2484 *pbEncoded
++ = ASN_INTEGER
;
2487 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2488 pbEncoded
+= lenBytes
;
2489 *pbEncoded
++ = padByte
;
2493 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2494 pbEncoded
+= lenBytes
;
2496 for (; significantBytes
> 0; significantBytes
--)
2497 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2503 SetLastError(STATUS_ACCESS_VIOLATION
);
2510 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
2511 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2512 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2518 DWORD significantBytes
, lenBytes
;
2521 const CRYPT_INTEGER_BLOB
*blob
=
2522 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2524 significantBytes
= blob
->cbData
;
2525 if (significantBytes
)
2527 /* positive, lop off leading (little-endian) zeroes */
2528 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2531 if (significantBytes
== 0)
2532 significantBytes
= 1;
2533 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2537 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2539 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2540 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2545 *pcbEncoded
= bytesNeeded
;
2550 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2551 pcbEncoded
, bytesNeeded
)))
2553 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2554 pbEncoded
= *(BYTE
**)pbEncoded
;
2555 *pbEncoded
++ = ASN_INTEGER
;
2558 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2559 pbEncoded
+= lenBytes
;
2564 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2565 pbEncoded
+= lenBytes
;
2567 for (; significantBytes
> 0; significantBytes
--)
2568 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2574 SetLastError(STATUS_ACCESS_VIOLATION
);
2581 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2582 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2583 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2585 CRYPT_INTEGER_BLOB blob
;
2588 /* Encode as an unsigned integer, then change the tag to enumerated */
2589 blob
.cbData
= sizeof(DWORD
);
2590 blob
.pbData
= (BYTE
*)pvStructInfo
;
2591 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2592 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2593 if (ret
&& pbEncoded
)
2595 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2596 pbEncoded
= *(BYTE
**)pbEncoded
;
2597 pbEncoded
[0] = ASN_ENUMERATED
;
2602 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2603 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2604 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2611 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2612 * temporary buffer because the output buffer is not NULL-terminated.
2615 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2619 *pcbEncoded
= bytesNeeded
;
2624 /* Sanity check the year, this is a two-digit year format */
2625 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2627 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2629 SetLastError(CRYPT_E_BAD_ENCODE
);
2634 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2635 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2637 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2638 pbEncoded
= *(BYTE
**)pbEncoded
;
2639 buf
[0] = ASN_UTCTIME
;
2640 buf
[1] = bytesNeeded
- 2;
2641 snprintf(buf
+ 2, sizeof(buf
) - 2,
2642 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2643 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2644 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2645 sysTime
.wMinute
, sysTime
.wSecond
);
2646 memcpy(pbEncoded
, buf
, bytesNeeded
);
2653 SetLastError(STATUS_ACCESS_VIOLATION
);
2660 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2661 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2662 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2669 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2670 * temporary buffer because the output buffer is not NULL-terminated.
2673 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2677 *pcbEncoded
= bytesNeeded
;
2682 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2685 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2686 pcbEncoded
, bytesNeeded
);
2689 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2690 pbEncoded
= *(BYTE
**)pbEncoded
;
2691 buf
[0] = ASN_GENERALTIME
;
2692 buf
[1] = bytesNeeded
- 2;
2693 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2694 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2695 sysTime
.wMinute
, sysTime
.wSecond
);
2696 memcpy(pbEncoded
, buf
, bytesNeeded
);
2702 SetLastError(STATUS_ACCESS_VIOLATION
);
2709 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2710 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2711 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2719 /* Check the year, if it's in the UTCTime range call that encode func */
2720 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2722 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2723 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2724 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2726 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2727 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2732 SetLastError(STATUS_ACCESS_VIOLATION
);
2739 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2740 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2741 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2747 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2748 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2749 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2751 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2752 dataLen
+= seq
->rgValue
[i
].cbData
;
2753 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2754 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2757 *pcbEncoded
= bytesNeeded
;
2762 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2763 pcbEncoded
, bytesNeeded
)))
2765 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2766 pbEncoded
= *(BYTE
**)pbEncoded
;
2767 *pbEncoded
++ = ASN_SEQUENCEOF
;
2768 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2769 pbEncoded
+= lenBytes
;
2770 for (i
= 0; i
< seq
->cValue
; i
++)
2772 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2773 seq
->rgValue
[i
].cbData
);
2774 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2781 SetLastError(STATUS_ACCESS_VIOLATION
);
2788 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2789 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2792 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2793 struct AsnConstructedItem constructed
= { 0 };
2794 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2795 DWORD cItem
= 0, cSwapped
= 0;
2797 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2799 case CRL_DIST_POINT_NO_NAME
:
2802 case CRL_DIST_POINT_FULL_NAME
:
2803 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2804 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2805 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2806 constructed
.tag
= 0;
2807 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2808 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2809 items
[cItem
].pvStructInfo
= &constructed
;
2810 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2814 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2815 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2821 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2823 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2824 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2825 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2826 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2827 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2831 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2833 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2834 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2835 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2836 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2837 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2842 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2843 pbEncoded
, pcbEncoded
);
2847 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2848 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2849 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2855 const CRL_DIST_POINTS_INFO
*info
=
2856 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2858 if (!info
->cDistPoint
)
2860 SetLastError(E_INVALIDARG
);
2865 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2868 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2872 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2876 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2878 /* Have to propagate index of failing character */
2884 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2885 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2888 *pcbEncoded
= bytesNeeded
;
2893 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2894 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2896 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2897 pbEncoded
= *(BYTE
**)pbEncoded
;
2898 *pbEncoded
++ = ASN_SEQUENCEOF
;
2899 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2900 pbEncoded
+= lenBytes
;
2901 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2903 DWORD len
= dataLen
;
2905 ret
= CRYPT_AsnEncodeDistPoint(
2906 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
2920 SetLastError(STATUS_ACCESS_VIOLATION
);
2927 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
2928 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2929 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2935 const CERT_ENHKEY_USAGE
*usage
=
2936 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
2937 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2940 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2942 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2943 usage
->rgpszUsageIdentifier
[i
],
2944 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2946 bytesNeeded
+= size
;
2948 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2949 bytesNeeded
+= 1 + lenBytes
;
2953 *pcbEncoded
= bytesNeeded
;
2956 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2957 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2959 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2960 pbEncoded
= *(BYTE
**)pbEncoded
;
2961 *pbEncoded
++ = ASN_SEQUENCEOF
;
2962 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2964 pbEncoded
+= lenBytes
;
2965 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2968 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2969 usage
->rgpszUsageIdentifier
[i
],
2970 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2975 bytesNeeded
-= size
;
2984 SetLastError(STATUS_ACCESS_VIOLATION
);
2991 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
2992 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2993 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2999 const CRL_ISSUING_DIST_POINT
*point
=
3000 (const CRL_ISSUING_DIST_POINT
*)pvStructInfo
;
3001 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3002 struct AsnConstructedItem constructed
= { 0 };
3003 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3004 DWORD cItem
= 0, cSwapped
= 0;
3007 switch (point
->DistPointName
.dwDistPointNameChoice
)
3009 case CRL_DIST_POINT_NO_NAME
:
3012 case CRL_DIST_POINT_FULL_NAME
:
3013 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3014 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3015 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3016 constructed
.tag
= 0;
3017 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3018 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3019 items
[cItem
].pvStructInfo
= &constructed
;
3020 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3025 SetLastError(E_INVALIDARG
);
3028 if (ret
&& point
->fOnlyContainsUserCerts
)
3030 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3031 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3032 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3033 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3034 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3038 if (ret
&& point
->fOnlyContainsCACerts
)
3040 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3041 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3042 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3043 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3044 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3048 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3050 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3051 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3052 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3053 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3054 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3058 if (ret
&& point
->fIndirectCRL
)
3060 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3061 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3062 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3063 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3064 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3069 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3070 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3074 SetLastError(STATUS_ACCESS_VIOLATION
);
3081 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
3082 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3083 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3087 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3088 (const CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3089 struct AsnEncodeSequenceItem items
[] = {
3090 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
3091 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
3094 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3095 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
3100 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
3101 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3102 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3106 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
3108 SetLastError(E_INVALIDARG
);
3114 const CMSG_SIGNER_INFO
*info
= (const CMSG_SIGNER_INFO
*)pvStructInfo
;
3116 if (!info
->Issuer
.cbData
)
3117 SetLastError(E_INVALIDARG
);
3120 struct AsnEncodeSequenceItem items
[7] = {
3121 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
3122 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
3123 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
3124 { &info
->HashEncryptionAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
3128 if (info
->AuthAttrs
.cAttr
)
3130 items
[cItem
].pvStructInfo
= &info
->AuthAttrs
;
3131 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3134 if (info
->UnauthAttrs
.cAttr
)
3136 items
[cItem
].pvStructInfo
= &info
->UnauthAttrs
;
3137 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3140 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
3141 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
3143 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3144 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3149 SetLastError(STATUS_ACCESS_VIOLATION
);
3155 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3156 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
3157 void *pvEncoded
, DWORD
*pcbEncoded
)
3159 static HCRYPTOIDFUNCSET set
= NULL
;
3161 CryptEncodeObjectExFunc encodeFunc
= NULL
;
3162 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3164 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
3165 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
3166 pvEncoded
, pcbEncoded
);
3168 if (!pvEncoded
&& !pcbEncoded
)
3170 SetLastError(ERROR_INVALID_PARAMETER
);
3173 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3174 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3176 SetLastError(ERROR_FILE_NOT_FOUND
);
3180 SetLastError(NOERROR
);
3181 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
3182 *(BYTE
**)pvEncoded
= NULL
;
3183 if (!HIWORD(lpszStructType
))
3185 switch (LOWORD(lpszStructType
))
3187 case (WORD
)X509_CERT
:
3188 encodeFunc
= CRYPT_AsnEncodeCert
;
3190 case (WORD
)X509_CERT_TO_BE_SIGNED
:
3191 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
3193 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
3194 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
3196 case (WORD
)X509_EXTENSIONS
:
3197 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3199 case (WORD
)X509_NAME_VALUE
:
3200 encodeFunc
= CRYPT_AsnEncodeNameValue
;
3202 case (WORD
)X509_NAME
:
3203 encodeFunc
= CRYPT_AsnEncodeName
;
3205 case (WORD
)X509_PUBLIC_KEY_INFO
:
3206 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
3208 case (WORD
)X509_AUTHORITY_KEY_ID
:
3209 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3211 case (WORD
)X509_ALTERNATE_NAME
:
3212 encodeFunc
= CRYPT_AsnEncodeAltName
;
3214 case (WORD
)X509_BASIC_CONSTRAINTS
:
3215 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3217 case (WORD
)X509_BASIC_CONSTRAINTS2
:
3218 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3220 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
3221 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
3223 case (WORD
)X509_UNICODE_NAME
:
3224 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
3226 case (WORD
)PKCS_CONTENT_INFO
:
3227 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
3229 case (WORD
)PKCS_ATTRIBUTE
:
3230 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
3232 case (WORD
)X509_UNICODE_NAME_VALUE
:
3233 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
3235 case (WORD
)X509_OCTET_STRING
:
3236 encodeFunc
= CRYPT_AsnEncodeOctets
;
3238 case (WORD
)X509_BITS
:
3239 case (WORD
)X509_KEY_USAGE
:
3240 encodeFunc
= CRYPT_AsnEncodeBits
;
3242 case (WORD
)X509_INTEGER
:
3243 encodeFunc
= CRYPT_AsnEncodeInt
;
3245 case (WORD
)X509_MULTI_BYTE_INTEGER
:
3246 encodeFunc
= CRYPT_AsnEncodeInteger
;
3248 case (WORD
)X509_MULTI_BYTE_UINT
:
3249 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
3251 case (WORD
)X509_ENUMERATED
:
3252 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3254 case (WORD
)X509_CHOICE_OF_TIME
:
3255 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
3257 case (WORD
)X509_AUTHORITY_KEY_ID2
:
3258 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3260 case (WORD
)X509_SEQUENCE_OF_ANY
:
3261 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
3263 case (WORD
)PKCS_UTC_TIME
:
3264 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3266 case (WORD
)X509_CRL_DIST_POINTS
:
3267 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3269 case (WORD
)X509_ENHANCED_KEY_USAGE
:
3270 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3272 case (WORD
)PKCS_ATTRIBUTES
:
3273 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
3275 case (WORD
)X509_ISSUING_DIST_POINT
:
3276 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3278 case (WORD
)PKCS7_SIGNER_INFO
:
3279 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
3282 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
3285 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
3286 encodeFunc
= CRYPT_AsnEncodeExtensions
;
3287 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3288 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
3289 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
3290 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
3291 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
3292 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
3293 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3294 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
3295 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3296 encodeFunc
= CRYPT_AsnEncodeBits
;
3297 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3298 encodeFunc
= CRYPT_AsnEncodeOctets
;
3299 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
3300 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
3301 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3302 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
3303 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
3304 encodeFunc
= CRYPT_AsnEncodeAltName
;
3305 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
3306 encodeFunc
= CRYPT_AsnEncodeAltName
;
3307 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
3308 encodeFunc
= CRYPT_AsnEncodeAltName
;
3309 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
3310 encodeFunc
= CRYPT_AsnEncodeAltName
;
3311 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
3312 encodeFunc
= CRYPT_AsnEncodeAltName
;
3313 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
3314 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
3315 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
3316 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
3317 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
3318 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
3320 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3321 debugstr_a(lpszStructType
));
3325 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
3326 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
3327 (void **)&encodeFunc
, &hFunc
);
3330 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
3331 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
3333 SetLastError(ERROR_FILE_NOT_FOUND
);
3335 CryptFreeOIDFunctionAddress(hFunc
, 0);
3339 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
3340 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3342 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3343 NULL
, 0, NULL
, pInfo
, pcbInfo
);
3346 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3347 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3348 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3352 static CHAR oid
[] = szOID_RSA_RSA
;
3354 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3355 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3358 if (!pszPublicKeyObjId
)
3359 pszPublicKeyObjId
= oid
;
3360 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
3364 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
3367 LPBYTE pubKey
= CryptMemAlloc(keySize
);
3371 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
3375 DWORD encodedLen
= 0;
3377 ret
= CryptEncodeObject(dwCertEncodingType
,
3378 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
3381 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
3382 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
3385 *pcbInfo
= sizeNeeded
;
3386 else if (*pcbInfo
< sizeNeeded
)
3388 SetLastError(ERROR_MORE_DATA
);
3389 *pcbInfo
= sizeNeeded
;
3394 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
3395 sizeof(CERT_PUBLIC_KEY_INFO
);
3396 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
3398 pInfo
->Algorithm
.Parameters
.cbData
= 0;
3399 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
3400 pInfo
->PublicKey
.pbData
=
3401 (BYTE
*)pInfo
->Algorithm
.pszObjId
3402 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
3403 pInfo
->PublicKey
.cbData
= encodedLen
;
3404 pInfo
->PublicKey
.cUnusedBits
= 0;
3405 ret
= CryptEncodeObject(dwCertEncodingType
,
3406 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
3407 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
3411 CryptMemFree(pubKey
);
3416 CryptDestroyKey(key
);
3421 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3422 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
3423 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
3425 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
3426 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
3427 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
3429 static HCRYPTOIDFUNCSET set
= NULL
;
3431 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
3432 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3434 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
3435 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
3440 SetLastError(ERROR_INVALID_PARAMETER
);
3444 if (pszPublicKeyObjId
)
3447 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
3449 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
3450 0, (void **)&exportFunc
, &hFunc
);
3453 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
3454 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
3455 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
3457 CryptFreeOIDFunctionAddress(hFunc
, 0);
3461 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
3462 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
3464 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
3468 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3469 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3470 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3473 DWORD pubKeySize
= 0;
3475 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3476 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3478 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3479 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
3482 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
3486 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
3487 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
3490 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
3492 CryptMemFree(pubKey
);
3500 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
3501 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3502 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
3504 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
3505 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
3506 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
3508 static HCRYPTOIDFUNCSET set
= NULL
;
3510 ImportPublicKeyInfoExFunc importFunc
= NULL
;
3511 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3513 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv
,
3514 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
3517 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
3518 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
3519 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
3521 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
3522 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
3525 CryptFreeOIDFunctionAddress(hFunc
, 0);