2 * Copyright 2005-2008 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 isn't
21 * implemented, 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
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
38 #define NONAMELESSUNION
44 #include "wine/debug.h"
45 #include "wine/exception.h"
46 #include "crypt32_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
49 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
51 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
54 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
55 * The dwCertEncodingType and lpszStructType are ignored by the built-in
56 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
57 * since it must call functions in external DLLs that follow these signatures.
59 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
60 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
61 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
62 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
63 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
64 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
65 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
66 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
67 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
68 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
69 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
70 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
71 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
72 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
73 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
74 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
75 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
76 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
77 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
78 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
79 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
80 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
81 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
82 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
83 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
84 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
85 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
86 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
87 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
88 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
89 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
90 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
91 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
92 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
93 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
94 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
95 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
96 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
97 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
99 BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
,
100 BYTE
*pbEncoded
, DWORD
*pcbEncoded
, DWORD bytesNeeded
)
104 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
106 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
107 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
109 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
110 if (!*(BYTE
**)pbEncoded
)
113 *pcbEncoded
= bytesNeeded
;
115 else if (bytesNeeded
> *pcbEncoded
)
117 *pcbEncoded
= bytesNeeded
;
118 SetLastError(ERROR_MORE_DATA
);
122 *pcbEncoded
= bytesNeeded
;
126 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA
*pEncodePara
, LPVOID pv
)
128 if (pEncodePara
&& pEncodePara
->pfnFree
)
129 pEncodePara
->pfnFree(pv
);
134 BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
136 DWORD bytesNeeded
, significantBytes
= 0;
144 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
145 temp
<<= 8, significantBytes
--)
147 bytesNeeded
= significantBytes
+ 1;
151 *pcbEncoded
= bytesNeeded
;
154 if (*pcbEncoded
< bytesNeeded
)
156 SetLastError(ERROR_MORE_DATA
);
160 *pbEncoded
= (BYTE
)len
;
165 *pbEncoded
++ = significantBytes
| 0x80;
166 for (i
= 0; i
< significantBytes
; i
++)
168 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
172 *pcbEncoded
= bytesNeeded
;
176 BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
177 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
178 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
181 DWORD i
, dataLen
= 0;
183 TRACE("%p, %d, %08x, %p, %p, %d\n", items
, cItem
, dwFlags
, pEncodePara
,
184 pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
185 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
187 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
188 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
189 NULL
, &items
[i
].size
);
190 /* Some functions propagate their errors through the size */
192 *pcbEncoded
= items
[i
].size
;
193 dataLen
+= items
[i
].size
;
197 DWORD lenBytes
, bytesNeeded
;
199 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
200 bytesNeeded
= 1 + lenBytes
+ dataLen
;
202 *pcbEncoded
= bytesNeeded
;
205 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
206 pcbEncoded
, bytesNeeded
)))
210 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
211 pbEncoded
= *(BYTE
**)pbEncoded
;
213 *out
++ = ASN_SEQUENCE
;
214 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
216 for (i
= 0; ret
&& i
< cItem
; i
++)
218 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
219 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
220 NULL
, out
, &items
[i
].size
);
221 /* Some functions propagate their errors through the size */
223 *pcbEncoded
= items
[i
].size
;
224 out
+= items
[i
].size
;
226 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
227 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
231 TRACE("returning %d (%08x)\n", ret
, GetLastError());
235 BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
236 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
237 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
240 const struct AsnConstructedItem
*item
= pvStructInfo
;
243 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
244 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
246 DWORD dataLen
, bytesNeeded
;
248 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
249 bytesNeeded
= 1 + dataLen
+ len
;
251 *pcbEncoded
= bytesNeeded
;
252 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
253 pbEncoded
, pcbEncoded
, bytesNeeded
)))
257 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
258 pbEncoded
= *(BYTE
**)pbEncoded
;
260 *out
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
261 CRYPT_EncodeLen(len
, out
, &dataLen
);
263 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
264 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
268 /* Some functions propagate their errors through the size */
270 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
271 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
277 /* Some functions propagate their errors through the size */
283 struct AsnEncodeTagSwappedItem
286 const void *pvStructInfo
;
287 CryptEncodeObjectExFunc encodeFunc
;
290 /* Sort of a wacky hack, it encodes something using the struct
291 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
292 * given in the struct AsnEncodeTagSwappedItem.
294 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
295 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
296 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
299 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
301 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
302 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
303 if (ret
&& pbEncoded
)
304 *pbEncoded
= item
->tag
;
308 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
309 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
310 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
312 const DWORD
*ver
= pvStructInfo
;
315 /* CERT_V1 is not encoded */
323 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
325 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
326 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
331 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
332 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
333 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
335 const CRYPT_DER_BLOB
*blob
= pvStructInfo
;
340 *pcbEncoded
= blob
->cbData
;
345 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
346 pcbEncoded
, blob
->cbData
)))
348 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
349 pbEncoded
= *(BYTE
**)pbEncoded
;
351 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
352 *pcbEncoded
= blob
->cbData
;
358 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
359 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
360 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
363 /* This has two filetimes in a row, a NotBefore and a NotAfter */
364 const FILETIME
*timePtr
= pvStructInfo
;
365 struct AsnEncodeSequenceItem items
[] = {
366 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
367 { timePtr
+ 1, CRYPT_AsnEncodeChoiceOfTime
, 0 },
370 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
371 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
376 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
379 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
380 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
381 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
384 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
385 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
386 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
389 struct AsnEncodeSequenceItem items
[2] = {
390 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
391 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
394 if (algo
->Parameters
.cbData
)
395 items
[1].pvStructInfo
= &algo
->Parameters
;
397 items
[1].pvStructInfo
= &nullBlob
;
398 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
399 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
404 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType
,
405 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
406 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
408 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
410 struct AsnEncodeSequenceItem items
[] = {
411 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
412 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
415 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
416 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
421 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
422 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
423 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
429 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
430 struct AsnEncodeSequenceItem items
[] = {
431 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
432 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
435 TRACE("Encoding public key with OID %s\n",
436 debugstr_a(info
->Algorithm
.pszObjId
));
437 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
438 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
443 SetLastError(STATUS_ACCESS_VIOLATION
);
450 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
451 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
452 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
458 const CERT_SIGNED_CONTENT_INFO
*info
= pvStructInfo
;
459 struct AsnEncodeSequenceItem items
[] = {
460 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
461 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
462 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
465 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
466 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
467 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
468 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
473 SetLastError(STATUS_ACCESS_VIOLATION
);
480 BOOL WINAPI
CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType
,
481 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
482 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
485 const CERT_PUBLIC_KEY_INFO
*info
= pvStructInfo
;
486 struct AsnEncodeSequenceItem items
[] = {
487 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
488 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
491 TRACE("Encoding public key with OID %s\n",
492 debugstr_a(info
->Algorithm
.pszObjId
));
493 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
494 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
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
= 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_AsnEncodePubKeyInfoNoNull
, 0 },
522 struct AsnConstructedItem constructed
= { 0 };
523 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
524 DWORD cItem
= 7, cSwapped
= 0;
526 if (info
->IssuerUniqueId
.cbData
)
528 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
529 swapped
[cSwapped
].pvStructInfo
= &info
->IssuerUniqueId
;
530 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
531 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
532 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
536 if (info
->SubjectUniqueId
.cbData
)
538 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
539 swapped
[cSwapped
].pvStructInfo
= &info
->SubjectUniqueId
;
540 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
541 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
542 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
546 if (info
->cExtension
)
549 constructed
.pvStructInfo
= &info
->cExtension
;
550 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
551 items
[cItem
].pvStructInfo
= &constructed
;
552 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
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, %d\n", entry
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
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 bytesNeeded
, dataLen
, lenBytes
, i
;
600 const CRL_INFO
*info
= pvStructInfo
;
601 const CRL_ENTRY
*rgCRLEntry
= info
->rgCRLEntry
;
604 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cCRLEntry
; i
++)
608 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
614 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
615 bytesNeeded
= 1 + lenBytes
+ dataLen
;
617 *pcbEncoded
= bytesNeeded
;
620 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
621 pcbEncoded
, bytesNeeded
)))
625 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
626 pbEncoded
= *(BYTE
**)pbEncoded
;
628 *out
++ = ASN_SEQUENCEOF
;
629 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
631 for (i
= 0; i
< info
->cCRLEntry
; i
++)
633 DWORD size
= dataLen
;
635 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], out
, &size
);
639 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
640 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
647 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
648 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
649 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
651 const DWORD
*ver
= pvStructInfo
;
654 /* CRL_V1 is not encoded */
661 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
662 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
666 /* Like in Windows, this blithely ignores the validity of the passed-in
667 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
668 * decode properly, see CRYPT_AsnDecodeCRLInfo.
670 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
671 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
672 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
678 const CRL_INFO
*info
= pvStructInfo
;
679 struct AsnEncodeSequenceItem items
[7] = {
680 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
681 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
682 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
683 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
686 struct AsnConstructedItem constructed
[1] = { { 0 } };
687 DWORD cItem
= 4, cConstructed
= 0;
689 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
691 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
692 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
697 items
[cItem
].pvStructInfo
= info
;
698 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
701 if (info
->cExtension
)
703 constructed
[cConstructed
].tag
= 0;
704 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
705 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
706 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
707 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
712 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
713 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
717 SetLastError(STATUS_ACCESS_VIOLATION
);
724 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
728 struct AsnEncodeSequenceItem items
[3] = {
729 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
735 TRACE("%p, %p, %d\n", ext
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
739 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
740 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
743 items
[cItem
].pvStructInfo
= &ext
->Value
;
744 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
747 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
748 pbEncoded
, pcbEncoded
);
749 TRACE("returning %d (%08x)\n", ret
, GetLastError());
753 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
754 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
755 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
761 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
762 const CERT_EXTENSIONS
*exts
= pvStructInfo
;
765 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
769 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
775 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
776 bytesNeeded
= 1 + lenBytes
+ dataLen
;
778 *pcbEncoded
= bytesNeeded
;
781 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
782 pbEncoded
, pcbEncoded
, bytesNeeded
)))
786 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
787 pbEncoded
= *(BYTE
**)pbEncoded
;
789 *out
++ = ASN_SEQUENCEOF
;
790 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
792 for (i
= 0; i
< exts
->cExtension
; i
++)
794 DWORD size
= dataLen
;
796 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
801 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
802 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
809 SetLastError(STATUS_ACCESS_VIOLATION
);
816 BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
817 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
818 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
820 LPCSTR pszObjId
= pvStructInfo
;
821 DWORD bytesNeeded
= 0, lenBytes
;
826 TRACE("%s\n", debugstr_a(pszObjId
));
833 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
835 SetLastError(CRYPT_E_ASN1_ERROR
);
839 firstByte
= val1
* 40 + val2
;
840 ptr
= pszObjId
+ firstPos
;
850 /* note I assume each component is at most 32-bits long in base 2 */
851 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
853 if (val1
>= 0x10000000)
855 else if (val1
>= 0x200000)
857 else if (val1
>= 0x4000)
859 else if (val1
>= 0x80)
869 SetLastError(CRYPT_E_ASN1_ERROR
);
873 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
877 bytesNeeded
+= 1 + lenBytes
;
880 if (*pcbEncoded
< bytesNeeded
)
882 SetLastError(ERROR_MORE_DATA
);
887 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
888 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
889 pbEncoded
+= lenBytes
;
895 *pbEncoded
++ = firstByte
;
896 ptr
= pszObjId
+ firstPos
;
899 sscanf(ptr
, "%d%n", &val
, &pos
);
901 unsigned char outBytes
[5];
904 if (val
>= 0x10000000)
906 else if (val
>= 0x200000)
908 else if (val
>= 0x4000)
910 else if (val
>= 0x80)
914 for (i
= numBytes
; i
> 0; i
--)
916 outBytes
[i
- 1] = val
& 0x7f;
919 for (i
= 0; i
< numBytes
- 1; i
++)
920 *pbEncoded
++ = outBytes
[i
] | 0x80;
921 *pbEncoded
++ = outBytes
[i
];
930 *pcbEncoded
= bytesNeeded
;
934 static BOOL
CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE
*value
,
935 BYTE tag
, DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
939 LPCSTR str
= (LPCSTR
)value
->Value
.pbData
;
940 DWORD bytesNeeded
, lenBytes
, encodedLen
;
942 encodedLen
= value
->Value
.cbData
? value
->Value
.cbData
: strlen(str
);
943 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
944 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
946 *pcbEncoded
= bytesNeeded
;
949 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
950 pbEncoded
, pcbEncoded
, bytesNeeded
)))
952 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
953 pbEncoded
= *(BYTE
**)pbEncoded
;
955 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
956 pbEncoded
+= lenBytes
;
957 memcpy(pbEncoded
, str
, encodedLen
);
963 static BOOL
CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE
*value
,
964 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
968 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
969 DWORD bytesNeeded
, lenBytes
, strLen
;
971 if (value
->Value
.cbData
)
972 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
973 else if (value
->Value
.pbData
)
974 strLen
= lstrlenW(str
);
977 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
978 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
980 *pcbEncoded
= bytesNeeded
;
983 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
984 pbEncoded
, pcbEncoded
, bytesNeeded
)))
988 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
989 pbEncoded
= *(BYTE
**)pbEncoded
;
990 *pbEncoded
++ = ASN_BMPSTRING
;
991 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
992 pbEncoded
+= lenBytes
;
993 for (i
= 0; i
< strLen
; i
++)
995 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
996 *pbEncoded
++ = str
[i
] & 0x00ff;
1003 static BOOL
CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE
*value
,
1004 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
1008 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1009 DWORD bytesNeeded
, lenBytes
, encodedLen
, strLen
;
1011 if (value
->Value
.cbData
)
1012 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
1014 strLen
= lstrlenW(str
);
1017 encodedLen
= WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, NULL
, 0, NULL
,
1019 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1020 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1022 *pcbEncoded
= bytesNeeded
;
1025 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1026 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1028 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1029 pbEncoded
= *(BYTE
**)pbEncoded
;
1030 *pbEncoded
++ = ASN_UTF8STRING
;
1031 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1032 pbEncoded
+= lenBytes
;
1033 WideCharToMultiByte(CP_UTF8
, 0, str
, strLen
, (LPSTR
)pbEncoded
,
1034 bytesNeeded
- lenBytes
- 1, NULL
, NULL
);
1040 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1041 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1042 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1048 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1050 switch (value
->dwValueType
)
1052 case CERT_RDN_ANY_TYPE
:
1053 /* explicitly disallowed */
1054 SetLastError(E_INVALIDARG
);
1057 case CERT_RDN_ENCODED_BLOB
:
1058 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
,
1059 &value
->Value
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1061 case CERT_RDN_OCTET_STRING
:
1062 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_OCTETSTRING
,
1063 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1065 case CERT_RDN_NUMERIC_STRING
:
1066 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_NUMERICSTRING
,
1067 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1069 case CERT_RDN_PRINTABLE_STRING
:
1070 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_PRINTABLESTRING
,
1071 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1073 case CERT_RDN_TELETEX_STRING
:
1074 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_T61STRING
,
1075 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1077 case CERT_RDN_VIDEOTEX_STRING
:
1078 ret
= CRYPT_AsnEncodeStringCoerce(value
,
1079 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1081 case CERT_RDN_IA5_STRING
:
1082 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_IA5STRING
,
1083 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1085 case CERT_RDN_GRAPHIC_STRING
:
1086 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GRAPHICSTRING
,
1087 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1089 case CERT_RDN_VISIBLE_STRING
:
1090 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_VISIBLESTRING
,
1091 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1093 case CERT_RDN_GENERAL_STRING
:
1094 ret
= CRYPT_AsnEncodeStringCoerce(value
, ASN_GENERALSTRING
,
1095 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1097 case CERT_RDN_UNIVERSAL_STRING
:
1098 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1099 SetLastError(CRYPT_E_ASN1_CHOICE
);
1102 case CERT_RDN_BMP_STRING
:
1103 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
1104 pbEncoded
, pcbEncoded
);
1106 case CERT_RDN_UTF8_STRING
:
1107 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
1108 pbEncoded
, pcbEncoded
);
1111 SetLastError(CRYPT_E_ASN1_CHOICE
);
1117 SetLastError(STATUS_ACCESS_VIOLATION
);
1124 static BOOL
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1125 const CERT_RDN_ATTR
*attr
, CryptEncodeObjectExFunc nameValueEncodeFunc
,
1126 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1128 DWORD bytesNeeded
= 0, lenBytes
, size
;
1131 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1132 0, NULL
, NULL
, &size
);
1135 bytesNeeded
+= size
;
1136 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1137 * with dwValueType, so "cast" it to get its encoded size
1139 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
, &attr
->dwValueType
,
1140 0, NULL
, NULL
, &size
);
1143 bytesNeeded
+= size
;
1144 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1145 bytesNeeded
+= 1 + lenBytes
;
1148 if (*pcbEncoded
< bytesNeeded
)
1150 SetLastError(ERROR_MORE_DATA
);
1155 *pbEncoded
++ = ASN_SEQUENCE
;
1156 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1158 pbEncoded
+= lenBytes
;
1159 size
= bytesNeeded
- 1 - lenBytes
;
1160 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1161 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1165 size
= bytesNeeded
- 1 - lenBytes
- size
;
1166 ret
= nameValueEncodeFunc(dwCertEncodingType
, NULL
,
1167 &attr
->dwValueType
, 0, NULL
, pbEncoded
, &size
);
1174 *pcbEncoded
= bytesNeeded
;
1178 /* Have to propagate index of failing character */
1185 static int __cdecl
BLOBComp(const void *l
, const void *r
)
1187 const CRYPT_DER_BLOB
*a
= l
, *b
= r
;
1190 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1191 ret
= a
->cbData
- b
->cbData
;
1195 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1197 static BOOL WINAPI
CRYPT_DEREncodeSet(DWORD dwCertEncodingType
,
1198 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1199 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1201 const CRYPT_BLOB_ARRAY
*set
= pvStructInfo
;
1202 DWORD bytesNeeded
= 0, lenBytes
, i
;
1205 for (i
= 0; i
< set
->cBlob
; i
++)
1206 bytesNeeded
+= set
->rgBlob
[i
].cbData
;
1207 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1208 bytesNeeded
+= 1 + lenBytes
;
1211 *pcbEncoded
= bytesNeeded
;
1214 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1215 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1217 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1218 pbEncoded
= *(BYTE
**)pbEncoded
;
1219 qsort(set
->rgBlob
, set
->cBlob
, sizeof(CRYPT_DER_BLOB
), BLOBComp
);
1220 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1221 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1222 pbEncoded
+= lenBytes
;
1223 for (i
= 0; i
< set
->cBlob
; i
++)
1225 memcpy(pbEncoded
, set
->rgBlob
[i
].pbData
, set
->rgBlob
[i
].cbData
);
1226 pbEncoded
+= set
->rgBlob
[i
].cbData
;
1232 struct DERSetDescriptor
1238 CryptEncodeObjectExFunc encode
;
1241 static BOOL WINAPI
CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType
,
1242 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1243 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1245 const struct DERSetDescriptor
*desc
= pvStructInfo
;
1246 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1252 setOf
.rgBlob
= CryptMemAlloc(desc
->cItems
* sizeof(CRYPT_DER_BLOB
));
1257 setOf
.cBlob
= desc
->cItems
;
1258 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1261 for (i
= 0; ret
&& i
< setOf
.cBlob
; i
++)
1263 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1264 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+ desc
->itemOffset
,
1265 0, NULL
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1268 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1269 if (!setOf
.rgBlob
[i
].pbData
)
1272 ret
= desc
->encode(dwCertEncodingType
, lpszStructType
,
1273 (const BYTE
*)desc
->items
+ i
* desc
->itemSize
+
1274 desc
->itemOffset
, 0, NULL
, setOf
.rgBlob
[i
].pbData
,
1275 &setOf
.rgBlob
[i
].cbData
);
1277 /* Some functions propagate their errors through the size */
1279 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1283 DWORD bytesNeeded
= 0, lenBytes
;
1285 for (i
= 0; i
< setOf
.cBlob
; i
++)
1286 bytesNeeded
+= setOf
.rgBlob
[i
].cbData
;
1287 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1288 bytesNeeded
+= 1 + lenBytes
;
1290 *pcbEncoded
= bytesNeeded
;
1291 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1292 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1294 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1295 pbEncoded
= *(BYTE
**)pbEncoded
;
1296 qsort(setOf
.rgBlob
, setOf
.cBlob
, sizeof(CRYPT_DER_BLOB
),
1298 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1299 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
, &lenBytes
);
1300 pbEncoded
+= lenBytes
;
1301 for (i
= 0; i
< setOf
.cBlob
; i
++)
1303 memcpy(pbEncoded
, setOf
.rgBlob
[i
].pbData
,
1304 setOf
.rgBlob
[i
].cbData
);
1305 pbEncoded
+= setOf
.rgBlob
[i
].cbData
;
1309 for (i
= 0; i
< setOf
.cBlob
; i
++)
1310 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1311 CryptMemFree(setOf
.rgBlob
);
1315 static BOOL
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, const CERT_RDN
*rdn
,
1316 CryptEncodeObjectExFunc nameValueEncodeFunc
, BYTE
*pbEncoded
,
1320 CRYPT_BLOB_ARRAY setOf
= { 0, NULL
};
1329 setOf
.rgBlob
= CryptMemAlloc(rdn
->cRDNAttr
*
1330 sizeof(CRYPT_DER_BLOB
));
1335 setOf
.cBlob
= rdn
->cRDNAttr
;
1336 memset(setOf
.rgBlob
, 0, setOf
.cBlob
* sizeof(CRYPT_DER_BLOB
));
1339 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1341 setOf
.rgBlob
[i
].cbData
= 0;
1342 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1343 nameValueEncodeFunc
, NULL
, &setOf
.rgBlob
[i
].cbData
);
1346 setOf
.rgBlob
[i
].pbData
= CryptMemAlloc(setOf
.rgBlob
[i
].cbData
);
1347 if (!setOf
.rgBlob
[i
].pbData
)
1350 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1351 &rdn
->rgRDNAttr
[i
], nameValueEncodeFunc
,
1352 setOf
.rgBlob
[i
].pbData
, &setOf
.rgBlob
[i
].cbData
);
1356 /* Have to propagate index of failing character */
1357 *pcbEncoded
= setOf
.rgBlob
[i
].cbData
;
1361 ret
= CRYPT_DEREncodeSet(X509_ASN_ENCODING
, NULL
, &setOf
, 0, NULL
,
1362 pbEncoded
, pcbEncoded
);
1363 for (i
= 0; i
< setOf
.cBlob
; i
++)
1364 CryptMemFree(setOf
.rgBlob
[i
].pbData
);
1368 SetLastError(STATUS_ACCESS_VIOLATION
);
1372 CryptMemFree(setOf
.rgBlob
);
1376 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
1377 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1378 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
1380 static BOOL WINAPI
CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1381 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1382 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1385 const CERT_NAME_VALUE
*value
= pvStructInfo
;
1388 if (value
->dwValueType
== CERT_RDN_ENCODED_BLOB
)
1389 ret
= CRYPT_CopyEncodedBlob(dwCertEncodingType
, NULL
, &value
->Value
,
1390 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1392 ret
= CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType
, NULL
, value
,
1393 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1397 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType
,
1398 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1399 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1405 const CERT_NAME_INFO
*info
= pvStructInfo
;
1406 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1408 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
1410 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1412 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
1413 CRYPT_AsnEncodeOrCopyUnicodeNameValue
, NULL
, &size
);
1415 bytesNeeded
+= size
;
1419 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1420 bytesNeeded
+= 1 + lenBytes
;
1424 *pcbEncoded
= bytesNeeded
;
1427 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1428 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1432 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1433 pbEncoded
= *(BYTE
**)pbEncoded
;
1435 *out
++ = ASN_SEQUENCEOF
;
1436 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
1438 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1441 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1442 &info
->rgRDN
[i
], CRYPT_AsnEncodeOrCopyUnicodeNameValue
,
1447 bytesNeeded
-= size
;
1452 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1453 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1460 SetLastError(STATUS_ACCESS_VIOLATION
);
1467 static BOOL WINAPI
CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType
,
1468 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1469 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1471 const DWORD
*ver
= pvStructInfo
;
1474 /* CTL_V1 is not encoded */
1481 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
1482 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1486 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1487 * if they are empty and the OID is not empty (otherwise omits them.)
1489 static BOOL WINAPI
CRYPT_AsnEncodeCTLSubjectAlgorithm(
1490 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1491 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1494 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
1496 struct AsnEncodeSequenceItem items
[2] = {
1497 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1503 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
1504 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
1507 if (algo
->Parameters
.cbData
)
1508 items
[cItem
].pvStructInfo
= &algo
->Parameters
;
1510 items
[cItem
].pvStructInfo
= &nullBlob
;
1511 items
[cItem
].encodeFunc
= CRYPT_CopyEncodedBlob
;
1514 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1515 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1519 static BOOL
CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY
*entry
,
1520 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1522 struct AsnEncodeSequenceItem items
[2] = {
1523 { &entry
->SubjectIdentifier
, CRYPT_AsnEncodeOctets
, 0 },
1524 { &entry
->cAttribute
, CRYPT_AsnEncodePKCSAttributes
, 0 },
1528 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
1529 ARRAY_SIZE(items
), 0, NULL
, pbEncoded
, pcbEncoded
);
1539 static BOOL WINAPI
CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType
,
1540 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1541 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1544 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1545 const struct CTLEntries
*entries
= pvStructInfo
;
1548 for (i
= 0, dataLen
= 0; ret
&& i
< entries
->cEntry
; i
++)
1552 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
], NULL
, &size
);
1558 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1559 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1561 *pcbEncoded
= bytesNeeded
;
1564 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1565 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1569 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1570 pbEncoded
= *(BYTE
**)pbEncoded
;
1572 *out
++ = ASN_SEQUENCEOF
;
1573 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1575 for (i
= 0; ret
&& i
< entries
->cEntry
; i
++)
1577 DWORD size
= dataLen
;
1579 ret
= CRYPT_AsnEncodeCTLEntry(&entries
->rgEntry
[i
],
1584 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1585 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1592 static BOOL WINAPI
CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType
,
1593 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1594 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1600 const CTL_INFO
*info
= pvStructInfo
;
1601 struct AsnEncodeSequenceItem items
[9] = {
1602 { &info
->dwVersion
, CRYPT_AsnEncodeCTLVersion
, 0 },
1603 { &info
->SubjectUsage
, CRYPT_AsnEncodeEnhancedKeyUsage
, 0 },
1605 struct AsnConstructedItem constructed
= { 0 };
1608 if (info
->ListIdentifier
.cbData
)
1610 items
[cItem
].pvStructInfo
= &info
->ListIdentifier
;
1611 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1614 if (info
->SequenceNumber
.cbData
)
1616 items
[cItem
].pvStructInfo
= &info
->SequenceNumber
;
1617 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInteger
;
1620 items
[cItem
].pvStructInfo
= &info
->ThisUpdate
;
1621 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1623 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
1625 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
1626 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1629 items
[cItem
].pvStructInfo
= &info
->SubjectAlgorithm
;
1630 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLSubjectAlgorithm
;
1632 if (info
->cCTLEntry
)
1634 items
[cItem
].pvStructInfo
= &info
->cCTLEntry
;
1635 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCTLEntries
;
1638 if (info
->cExtension
)
1640 constructed
.tag
= 0;
1641 constructed
.pvStructInfo
= &info
->cExtension
;
1642 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
1643 items
[cItem
].pvStructInfo
= &constructed
;
1644 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1647 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1648 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1652 SetLastError(STATUS_ACCESS_VIOLATION
);
1658 static BOOL
CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType
,
1659 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1660 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1666 const CRYPT_SMIME_CAPABILITY
*capability
= pvStructInfo
;
1668 if (!capability
->pszObjId
)
1669 SetLastError(E_INVALIDARG
);
1672 struct AsnEncodeSequenceItem items
[] = {
1673 { capability
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1674 { &capability
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
1677 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1678 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
1684 SetLastError(STATUS_ACCESS_VIOLATION
);
1690 static BOOL WINAPI
CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType
,
1691 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1692 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1698 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1699 const CRYPT_SMIME_CAPABILITIES
*capabilities
= pvStructInfo
;
1702 for (i
= 0, dataLen
= 0; ret
&& i
< capabilities
->cCapability
; i
++)
1706 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
, NULL
,
1707 &capabilities
->rgCapability
[i
], 0, NULL
, NULL
, &size
);
1713 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1714 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1716 *pcbEncoded
= bytesNeeded
;
1719 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1720 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1724 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1725 pbEncoded
= *(BYTE
**)pbEncoded
;
1727 *out
++ = ASN_SEQUENCEOF
;
1728 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1730 for (i
= 0; i
< capabilities
->cCapability
; i
++)
1732 DWORD size
= dataLen
;
1734 ret
= CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType
,
1735 NULL
, &capabilities
->rgCapability
[i
], 0, NULL
,
1740 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1741 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1748 SetLastError(STATUS_ACCESS_VIOLATION
);
1754 static BOOL WINAPI
CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType
,
1755 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1756 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1758 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1759 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1762 for (i
= 0, dataLen
= 0; ret
&& i
< noticeRef
->cNoticeNumbers
; i
++)
1766 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1767 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, NULL
, &size
);
1773 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1774 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1776 *pcbEncoded
= bytesNeeded
;
1779 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1780 pcbEncoded
, bytesNeeded
)))
1784 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1785 pbEncoded
= *(BYTE
**)pbEncoded
;
1787 *out
++ = ASN_SEQUENCE
;
1788 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
1790 for (i
= 0; i
< noticeRef
->cNoticeNumbers
; i
++)
1792 DWORD size
= dataLen
;
1794 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
1795 ¬iceRef
->rgNoticeNumbers
[i
], 0, NULL
, out
, &size
);
1799 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
1800 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
1807 static BOOL WINAPI
CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType
,
1808 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1809 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1811 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*noticeRef
= pvStructInfo
;
1813 CERT_NAME_VALUE orgValue
= { CERT_RDN_IA5_STRING
,
1814 { 0, (LPBYTE
)noticeRef
->pszOrganization
} };
1815 struct AsnEncodeSequenceItem items
[] = {
1816 { &orgValue
, CRYPT_AsnEncodeNameValue
, 0 },
1817 { noticeRef
, CRYPT_AsnEncodeNoticeNumbers
, 0 },
1820 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1821 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
1826 static BOOL WINAPI
CRYPT_AsnEncodePolicyQualifierUserNotice(
1827 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1828 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1835 const CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
= pvStructInfo
;
1836 struct AsnEncodeSequenceItem items
[2];
1837 CERT_NAME_VALUE displayTextValue
;
1840 if (notice
->pNoticeReference
)
1842 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNoticeReference
;
1843 items
[cItem
].pvStructInfo
= notice
->pNoticeReference
;
1846 if (notice
->pszDisplayText
)
1848 displayTextValue
.dwValueType
= CERT_RDN_BMP_STRING
;
1849 displayTextValue
.Value
.cbData
= 0;
1850 displayTextValue
.Value
.pbData
= (LPBYTE
)notice
->pszDisplayText
;
1851 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeNameValue
;
1852 items
[cItem
].pvStructInfo
= &displayTextValue
;
1855 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1856 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1860 SetLastError(STATUS_ACCESS_VIOLATION
);
1866 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType
,
1867 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1868 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1874 const CRYPT_ATTRIBUTE
*attr
= pvStructInfo
;
1876 if (!attr
->pszObjId
)
1877 SetLastError(E_INVALIDARG
);
1880 struct AsnEncodeSequenceItem items
[2] = {
1881 { attr
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1882 { &attr
->cValue
, CRYPT_DEREncodeSet
, 0 },
1885 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1886 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
,
1892 SetLastError(STATUS_ACCESS_VIOLATION
);
1898 static BOOL WINAPI
CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType
,
1899 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1900 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1906 const CRYPT_ATTRIBUTES
*attributes
= pvStructInfo
;
1907 struct DERSetDescriptor desc
= { attributes
->cAttr
, attributes
->rgAttr
,
1908 sizeof(CRYPT_ATTRIBUTE
), 0, CRYPT_AsnEncodePKCSAttribute
};
1910 ret
= CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING
, lpszStructType
,
1911 &desc
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1915 SetLastError(STATUS_ACCESS_VIOLATION
);
1921 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1922 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfoInternal(
1923 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
1924 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
1927 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1928 struct AsnEncodeSequenceItem items
[2] = {
1929 { info
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1932 struct AsnConstructedItem constructed
= { 0 };
1935 if (info
->Content
.cbData
)
1937 constructed
.tag
= 0;
1938 constructed
.pvStructInfo
= &info
->Content
;
1939 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
1940 items
[cItem
].pvStructInfo
= &constructed
;
1941 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
1944 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1945 cItem
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1948 BOOL
CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA
*digestedData
,
1949 void *pvData
, DWORD
*pcbData
)
1951 struct AsnEncodeSequenceItem items
[] = {
1952 { &digestedData
->version
, CRYPT_AsnEncodeInt
, 0 },
1953 { &digestedData
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
1955 { &digestedData
->ContentInfo
, CRYPT_AsnEncodePKCSContentInfoInternal
, 0 },
1956 { &digestedData
->hash
, CRYPT_AsnEncodeOctets
, 0 },
1959 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
), 0, NULL
, pvData
, pcbData
);
1962 static BOOL WINAPI
CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType
,
1963 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1964 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1970 const CRYPT_CONTENT_INFO
*info
= pvStructInfo
;
1972 if (!info
->pszObjId
)
1973 SetLastError(E_INVALIDARG
);
1975 ret
= CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType
,
1976 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1981 SetLastError(STATUS_ACCESS_VIOLATION
);
1987 static BOOL
CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE
*value
,
1988 BYTE tag
, DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
1992 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
1993 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1995 if (value
->Value
.cbData
)
1996 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
1998 encodedLen
= lstrlenW(str
);
2001 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2002 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2004 *pcbEncoded
= bytesNeeded
;
2007 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2008 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2012 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2013 pbEncoded
= *(BYTE
**)pbEncoded
;
2015 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
2016 pbEncoded
+= lenBytes
;
2017 for (i
= 0; i
< encodedLen
; i
++)
2018 *pbEncoded
++ = (BYTE
)str
[i
];
2024 static BOOL
CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE
*value
,
2025 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2029 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2030 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2032 if (value
->Value
.cbData
)
2033 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2035 encodedLen
= lstrlenW(str
);
2038 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2039 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2041 *pcbEncoded
= bytesNeeded
;
2044 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2045 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2050 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2051 ptr
= *(BYTE
**)pbEncoded
;
2054 *ptr
++ = ASN_NUMERICSTRING
;
2055 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2057 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2059 if ('0' <= str
[i
] && str
[i
] <= '9')
2060 *ptr
++ = (BYTE
)str
[i
];
2064 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING
);
2068 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2069 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2075 static inline BOOL
isprintableW(WCHAR wc
)
2077 return wc
&& wcschr( L
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?", wc
);
2080 static BOOL
CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE
*value
,
2081 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2085 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2086 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2088 if (value
->Value
.cbData
)
2089 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2091 encodedLen
= lstrlenW(str
);
2094 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2095 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2097 *pcbEncoded
= bytesNeeded
;
2100 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2101 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2106 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2107 ptr
= *(BYTE
**)pbEncoded
;
2110 *ptr
++ = ASN_PRINTABLESTRING
;
2111 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2113 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2115 if (isprintableW(str
[i
]))
2116 *ptr
++ = (BYTE
)str
[i
];
2120 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING
);
2124 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2125 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2131 static BOOL
CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE
*value
,
2132 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2136 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2137 DWORD bytesNeeded
, lenBytes
, encodedLen
;
2139 if (value
->Value
.cbData
)
2140 encodedLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2142 encodedLen
= lstrlenW(str
);
2145 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
2146 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
2148 *pcbEncoded
= bytesNeeded
;
2151 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2152 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2157 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2158 ptr
= *(BYTE
**)pbEncoded
;
2161 *ptr
++ = ASN_IA5STRING
;
2162 CRYPT_EncodeLen(encodedLen
, ptr
, &lenBytes
);
2164 for (i
= 0; ret
&& i
< encodedLen
; i
++)
2167 *ptr
++ = (BYTE
)str
[i
];
2171 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2175 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2176 CRYPT_FreeSpace(pEncodePara
, *(BYTE
**)pbEncoded
);
2182 static BOOL
CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE
*value
,
2183 DWORD dwFlags
, const CRYPT_ENCODE_PARA
*pEncodePara
, BYTE
*pbEncoded
,
2187 LPCWSTR str
= (LPCWSTR
)value
->Value
.pbData
;
2188 DWORD bytesNeeded
, lenBytes
, strLen
;
2190 /* FIXME: doesn't handle composite characters */
2191 if (value
->Value
.cbData
)
2192 strLen
= value
->Value
.cbData
/ sizeof(WCHAR
);
2194 strLen
= lstrlenW(str
);
2197 CRYPT_EncodeLen(strLen
* 4, NULL
, &lenBytes
);
2198 bytesNeeded
= 1 + lenBytes
+ strLen
* 4;
2200 *pcbEncoded
= bytesNeeded
;
2203 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2204 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2208 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2209 pbEncoded
= *(BYTE
**)pbEncoded
;
2210 *pbEncoded
++ = ASN_UNIVERSALSTRING
;
2211 CRYPT_EncodeLen(strLen
* 4, pbEncoded
, &lenBytes
);
2212 pbEncoded
+= lenBytes
;
2213 for (i
= 0; i
< strLen
; i
++)
2217 *pbEncoded
++ = (BYTE
)((str
[i
] & 0xff00) >> 8);
2218 *pbEncoded
++ = (BYTE
)(str
[i
] & 0x00ff);
2225 static BOOL WINAPI
CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType
,
2226 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2227 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2233 const CERT_NAME_VALUE
*value
= pvStructInfo
;
2235 switch (value
->dwValueType
)
2237 case CERT_RDN_ANY_TYPE
:
2238 case CERT_RDN_ENCODED_BLOB
:
2239 case CERT_RDN_OCTET_STRING
:
2240 SetLastError(CRYPT_E_NOT_CHAR_STRING
);
2242 case CERT_RDN_NUMERIC_STRING
:
2243 ret
= CRYPT_AsnEncodeNumericString(value
, dwFlags
, pEncodePara
,
2244 pbEncoded
, pcbEncoded
);
2246 case CERT_RDN_PRINTABLE_STRING
:
2247 ret
= CRYPT_AsnEncodePrintableString(value
, dwFlags
, pEncodePara
,
2248 pbEncoded
, pcbEncoded
);
2250 case CERT_RDN_TELETEX_STRING
:
2251 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_T61STRING
,
2252 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2254 case CERT_RDN_VIDEOTEX_STRING
:
2255 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
,
2256 ASN_VIDEOTEXSTRING
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2258 case CERT_RDN_IA5_STRING
:
2259 ret
= CRYPT_AsnEncodeIA5String(value
, dwFlags
, pEncodePara
,
2260 pbEncoded
, pcbEncoded
);
2262 case CERT_RDN_GRAPHIC_STRING
:
2263 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GRAPHICSTRING
,
2264 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2266 case CERT_RDN_VISIBLE_STRING
:
2267 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_VISIBLESTRING
,
2268 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2270 case CERT_RDN_GENERAL_STRING
:
2271 ret
= CRYPT_AsnEncodeUnicodeStringCoerce(value
, ASN_GENERALSTRING
,
2272 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2274 case CERT_RDN_UNIVERSAL_STRING
:
2275 ret
= CRYPT_AsnEncodeUniversalString(value
, dwFlags
, pEncodePara
,
2276 pbEncoded
, pcbEncoded
);
2278 case CERT_RDN_BMP_STRING
:
2279 ret
= CRYPT_AsnEncodeBMPString(value
, dwFlags
, pEncodePara
,
2280 pbEncoded
, pcbEncoded
);
2282 case CERT_RDN_UTF8_STRING
:
2283 ret
= CRYPT_AsnEncodeUTF8String(value
, dwFlags
, pEncodePara
,
2284 pbEncoded
, pcbEncoded
);
2287 SetLastError(CRYPT_E_ASN1_CHOICE
);
2292 SetLastError(STATUS_ACCESS_VIOLATION
);
2298 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
2299 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2300 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2306 const CERT_NAME_INFO
*info
= pvStructInfo
;
2307 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2309 TRACE("encoding name with %d RDNs\n", info
->cRDN
);
2311 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2313 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
],
2314 CRYPT_AsnEncodeNameValue
, NULL
, &size
);
2316 bytesNeeded
+= size
;
2318 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2319 bytesNeeded
+= 1 + lenBytes
;
2323 *pcbEncoded
= bytesNeeded
;
2326 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2327 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2331 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2332 pbEncoded
= *(BYTE
**)pbEncoded
;
2334 *out
++ = ASN_SEQUENCEOF
;
2335 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2337 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
2340 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
2341 &info
->rgRDN
[i
], CRYPT_AsnEncodeNameValue
, out
, &size
);
2345 bytesNeeded
-= size
;
2348 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2349 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2356 SetLastError(STATUS_ACCESS_VIOLATION
);
2363 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
2364 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2365 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2367 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
2376 else if (*pcbEncoded
< 3)
2379 SetLastError(ERROR_MORE_DATA
);
2385 *pbEncoded
++ = ASN_BOOL
;
2387 *pbEncoded
++ = val
? 0xff : 0;
2390 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2394 static BOOL WINAPI
CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType
,
2395 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2396 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2398 const CERT_ALT_NAME_ENTRY
*entry
= pvStructInfo
;
2404 switch (entry
->dwAltNameChoice
)
2406 case CERT_ALT_NAME_RFC822_NAME
:
2407 case CERT_ALT_NAME_DNS_NAME
:
2408 case CERT_ALT_NAME_URL
:
2409 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2410 if (entry
->u
.pwszURL
)
2414 /* Not + 1: don't encode the NULL-terminator */
2415 dataLen
= lstrlenW(entry
->u
.pwszURL
);
2416 for (i
= 0; ret
&& i
< dataLen
; i
++)
2418 if (entry
->u
.pwszURL
[i
] > 0x7f)
2420 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
2429 case CERT_ALT_NAME_DIRECTORY_NAME
:
2430 tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| (entry
->dwAltNameChoice
- 1);
2431 dataLen
= entry
->u
.DirectoryName
.cbData
;
2433 case CERT_ALT_NAME_IP_ADDRESS
:
2434 tag
= ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
2435 dataLen
= entry
->u
.IPAddress
.cbData
;
2437 case CERT_ALT_NAME_REGISTERED_ID
:
2439 struct AsnEncodeTagSwappedItem swapped
=
2440 { ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1), entry
->u
.pszRegisteredID
,
2441 CRYPT_AsnEncodeOid
};
2443 return CRYPT_AsnEncodeSwapTag(0, NULL
, &swapped
, 0, NULL
, pbEncoded
,
2446 case CERT_ALT_NAME_OTHER_NAME
:
2447 FIXME("name type %d unimplemented\n", entry
->dwAltNameChoice
);
2450 SetLastError(E_INVALIDARG
);
2455 DWORD bytesNeeded
, lenBytes
;
2457 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2458 bytesNeeded
= 1 + dataLen
+ lenBytes
;
2460 *pcbEncoded
= bytesNeeded
;
2461 else if (*pcbEncoded
< bytesNeeded
)
2463 SetLastError(ERROR_MORE_DATA
);
2464 *pcbEncoded
= bytesNeeded
;
2470 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2471 pbEncoded
+= lenBytes
;
2472 switch (entry
->dwAltNameChoice
)
2474 case CERT_ALT_NAME_RFC822_NAME
:
2475 case CERT_ALT_NAME_DNS_NAME
:
2476 case CERT_ALT_NAME_URL
:
2480 for (i
= 0; i
< dataLen
; i
++)
2481 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
2484 case CERT_ALT_NAME_DIRECTORY_NAME
:
2485 memcpy(pbEncoded
, entry
->u
.DirectoryName
.pbData
, dataLen
);
2487 case CERT_ALT_NAME_IP_ADDRESS
:
2488 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
2492 *pcbEncoded
= bytesNeeded
;
2495 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2499 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType
,
2500 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2501 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2507 const CERT_AUTHORITY_KEY_ID_INFO
*info
= pvStructInfo
;
2508 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2509 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2510 struct AsnConstructedItem constructed
= { 0 };
2511 DWORD cItem
= 0, cSwapped
= 0;
2513 if (info
->KeyId
.cbData
)
2515 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2516 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2517 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2518 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2519 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2523 if (info
->CertIssuer
.cbData
)
2525 constructed
.tag
= 1;
2526 constructed
.pvStructInfo
= &info
->CertIssuer
;
2527 constructed
.encodeFunc
= CRYPT_CopyEncodedBlob
;
2528 items
[cItem
].pvStructInfo
= &constructed
;
2529 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2532 if (info
->CertSerialNumber
.cbData
)
2534 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2535 swapped
[cSwapped
].pvStructInfo
= &info
->CertSerialNumber
;
2536 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2537 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2538 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2542 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2543 pEncodePara
, pbEncoded
, pcbEncoded
);
2547 SetLastError(STATUS_ACCESS_VIOLATION
);
2554 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
2555 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2556 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2562 const CERT_ALT_NAME_INFO
*info
= pvStructInfo
;
2563 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2566 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2567 * can't encode an erroneous entry index if it's bigger than this.
2569 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2573 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
, NULL
,
2574 &info
->rgAltEntry
[i
], 0, NULL
, NULL
, &len
);
2577 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2579 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2580 * the bad character, now set the index of the bad
2583 *pcbEncoded
= (BYTE
)i
<<
2584 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
2589 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2590 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2593 *pcbEncoded
= bytesNeeded
;
2598 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2599 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2603 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2604 pbEncoded
= *(BYTE
**)pbEncoded
;
2606 *out
++ = ASN_SEQUENCEOF
;
2607 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2609 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
2611 DWORD len
= dataLen
;
2613 ret
= CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType
,
2614 NULL
, &info
->rgAltEntry
[i
], 0, NULL
, out
, &len
);
2621 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2622 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2629 SetLastError(STATUS_ACCESS_VIOLATION
);
2636 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2637 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2638 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2644 const CERT_AUTHORITY_KEY_ID2_INFO
*info
= pvStructInfo
;
2645 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2646 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2647 DWORD cItem
= 0, cSwapped
= 0;
2649 if (info
->KeyId
.cbData
)
2651 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
2652 swapped
[cSwapped
].pvStructInfo
= &info
->KeyId
;
2653 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
2654 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2655 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2659 if (info
->AuthorityCertIssuer
.cAltEntry
)
2661 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
2662 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertIssuer
;
2663 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2664 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2665 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2669 if (info
->AuthorityCertSerialNumber
.cbData
)
2671 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
2672 swapped
[cSwapped
].pvStructInfo
= &info
->AuthorityCertSerialNumber
;
2673 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInteger
;
2674 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2675 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2679 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, dwFlags
,
2680 pEncodePara
, pbEncoded
, pcbEncoded
);
2684 SetLastError(STATUS_ACCESS_VIOLATION
);
2691 static BOOL
CRYPT_AsnEncodeAccessDescription(
2692 const CERT_ACCESS_DESCRIPTION
*descr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2694 struct AsnEncodeSequenceItem items
[] = {
2695 { descr
->pszAccessMethod
, CRYPT_AsnEncodeOid
, 0 },
2696 { &descr
->AccessLocation
, CRYPT_AsnEncodeAltNameEntry
, 0 },
2699 if (!descr
->pszAccessMethod
)
2701 SetLastError(E_INVALIDARG
);
2704 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
), 0, NULL
, pbEncoded
, pcbEncoded
);
2707 static BOOL WINAPI
CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType
,
2708 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2709 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2715 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2716 const CERT_AUTHORITY_INFO_ACCESS
*info
= pvStructInfo
;
2719 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAccDescr
; i
++)
2723 ret
= CRYPT_AsnEncodeAccessDescription(&info
->rgAccDescr
[i
], NULL
,
2730 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2731 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2733 *pcbEncoded
= bytesNeeded
;
2736 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2737 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2741 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2742 pbEncoded
= *(BYTE
**)pbEncoded
;
2744 *out
++ = ASN_SEQUENCEOF
;
2745 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
2747 for (i
= 0; i
< info
->cAccDescr
; i
++)
2749 DWORD size
= dataLen
;
2751 ret
= CRYPT_AsnEncodeAccessDescription(
2752 &info
->rgAccDescr
[i
], out
, &size
);
2756 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2757 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2764 SetLastError(STATUS_ACCESS_VIOLATION
);
2771 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
2772 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2773 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2779 const CERT_BASIC_CONSTRAINTS_INFO
*info
= pvStructInfo
;
2780 struct AsnEncodeSequenceItem items
[3] = {
2781 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
2786 if (info
->fPathLenConstraint
)
2788 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2789 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2792 if (info
->cSubtreesConstraint
)
2794 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
2795 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2798 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2799 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2803 SetLastError(STATUS_ACCESS_VIOLATION
);
2810 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
2811 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2812 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2818 const CERT_BASIC_CONSTRAINTS2_INFO
*info
= pvStructInfo
;
2819 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
2824 items
[cItem
].pvStructInfo
= &info
->fCA
;
2825 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
2828 if (info
->fPathLenConstraint
)
2830 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
2831 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
2834 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
2835 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2839 SetLastError(STATUS_ACCESS_VIOLATION
);
2846 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType
,
2847 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2848 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2850 const CERT_POLICY_INFO
*info
= pvStructInfo
;
2853 if (!info
->cPolicyQualifier
)
2860 struct AsnEncodeSequenceItem items
[2] = {
2861 { NULL
, CRYPT_AsnEncodeOid
, 0 },
2862 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
2864 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2867 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2869 items
[0].pvStructInfo
=
2870 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2871 items
[1].pvStructInfo
= &info
->rgPolicyQualifier
[i
].Qualifier
;
2872 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2873 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2875 bytesNeeded
+= size
;
2877 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2878 bytesNeeded
+= 1 + lenBytes
;
2882 *pcbEncoded
= bytesNeeded
;
2885 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2886 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2890 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2891 pbEncoded
= *(BYTE
**)pbEncoded
;
2893 *out
++ = ASN_SEQUENCEOF
;
2894 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2896 for (i
= 0; ret
&& i
< info
->cPolicyQualifier
; i
++)
2898 items
[0].pvStructInfo
=
2899 info
->rgPolicyQualifier
[i
].pszPolicyQualifierId
;
2900 items
[1].pvStructInfo
=
2901 &info
->rgPolicyQualifier
[i
].Qualifier
;
2903 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2904 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
2908 bytesNeeded
-= size
;
2911 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2912 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2920 static BOOL
CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType
,
2921 const CERT_POLICY_INFO
*info
, DWORD dwFlags
, BYTE
*pbEncoded
,
2924 struct AsnEncodeSequenceItem items
[2] = {
2925 { info
->pszPolicyIdentifier
, CRYPT_AsnEncodeOid
, 0 },
2926 { info
, CRYPT_AsnEncodeCertPolicyQualifiers
, 0 },
2930 if (!info
->pszPolicyIdentifier
)
2932 SetLastError(E_INVALIDARG
);
2935 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
2939 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType
,
2940 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2941 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2947 const CERT_POLICIES_INFO
*info
= pvStructInfo
;
2948 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2951 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2953 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2954 &info
->rgPolicyInfo
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
2957 bytesNeeded
+= size
;
2959 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2960 bytesNeeded
+= 1 + lenBytes
;
2964 *pcbEncoded
= bytesNeeded
;
2967 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2968 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2972 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2973 pbEncoded
= *(BYTE
**)pbEncoded
;
2975 *out
++ = ASN_SEQUENCEOF
;
2976 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
2978 for (i
= 0; ret
&& i
< info
->cPolicyInfo
; i
++)
2981 ret
= CRYPT_AsnEncodeCertPolicy(dwCertEncodingType
,
2982 &info
->rgPolicyInfo
[i
],
2983 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
2987 bytesNeeded
-= size
;
2990 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
2991 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
2998 SetLastError(STATUS_ACCESS_VIOLATION
);
3004 static BOOL
CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType
,
3005 const CERT_POLICY_MAPPING
*mapping
, DWORD dwFlags
, BYTE
*pbEncoded
,
3008 struct AsnEncodeSequenceItem items
[] = {
3009 { mapping
->pszIssuerDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3010 { mapping
->pszSubjectDomainPolicy
, CRYPT_AsnEncodeOid
, 0 },
3013 if (!mapping
->pszIssuerDomainPolicy
|| !mapping
->pszSubjectDomainPolicy
)
3015 SetLastError(E_INVALIDARG
);
3018 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
), dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3021 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType
,
3022 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3023 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3029 const CERT_POLICY_MAPPINGS_INFO
*info
= pvStructInfo
;
3030 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3033 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3035 ret
= CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType
,
3036 &info
->rgPolicyMapping
[i
], dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
3039 bytesNeeded
+= size
;
3041 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3042 bytesNeeded
+= 1 + lenBytes
;
3046 *pcbEncoded
= bytesNeeded
;
3049 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3050 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3054 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3055 pbEncoded
= *(BYTE
**)pbEncoded
;
3057 *out
++ = ASN_SEQUENCEOF
;
3058 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3060 for (i
= 0; ret
&& i
< info
->cPolicyMapping
; i
++)
3063 ret
= CRYPT_AsnEncodeCertPolicyMapping(
3064 dwCertEncodingType
, &info
->rgPolicyMapping
[i
],
3065 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, out
, &size
);
3069 bytesNeeded
-= size
;
3072 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3073 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3080 SetLastError(STATUS_ACCESS_VIOLATION
);
3086 static BOOL WINAPI
CRYPT_AsnEncodeCertPolicyConstraints(
3087 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
3088 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
3095 const CERT_POLICY_CONSTRAINTS_INFO
*info
= pvStructInfo
;
3096 struct AsnEncodeSequenceItem items
[2];
3097 struct AsnEncodeTagSwappedItem swapped
[2];
3098 DWORD cItem
= 0, cSwapped
= 0;
3100 if (info
->fRequireExplicitPolicy
)
3102 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
3103 swapped
[cSwapped
].pvStructInfo
=
3104 &info
->dwRequireExplicitPolicySkipCerts
;
3105 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3106 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3107 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3111 if (info
->fInhibitPolicyMapping
)
3113 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3114 swapped
[cSwapped
].pvStructInfo
=
3115 &info
->dwInhibitPolicyMappingSkipCerts
;
3116 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
3117 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3118 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3122 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3123 dwFlags
, NULL
, pbEncoded
, pcbEncoded
);
3127 SetLastError(STATUS_ACCESS_VIOLATION
);
3133 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
3134 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3135 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3141 const BLOBHEADER
*hdr
= pvStructInfo
;
3143 if (hdr
->bType
!= PUBLICKEYBLOB
)
3145 SetLastError(E_INVALIDARG
);
3150 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
3151 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
3152 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
3153 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
3154 struct AsnEncodeSequenceItem items
[] = {
3155 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3156 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
3159 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3160 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3165 SetLastError(STATUS_ACCESS_VIOLATION
);
3172 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
3173 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3174 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3180 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
3181 DWORD bytesNeeded
, lenBytes
;
3183 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3184 dwFlags
, pEncodePara
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
3186 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3187 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3190 *pcbEncoded
= bytesNeeded
;
3195 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3196 pcbEncoded
, bytesNeeded
)))
3198 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3199 pbEncoded
= *(BYTE
**)pbEncoded
;
3200 *pbEncoded
++ = ASN_OCTETSTRING
;
3201 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3202 pbEncoded
+= lenBytes
;
3204 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3210 SetLastError(STATUS_ACCESS_VIOLATION
);
3214 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3218 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3219 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3220 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3226 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3227 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3230 /* yep, MS allows cUnusedBits to be >= 8 */
3231 if (!blob
->cUnusedBits
)
3233 dataBytes
= blob
->cbData
;
3236 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3238 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3239 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3247 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3248 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3251 *pcbEncoded
= bytesNeeded
;
3256 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3257 pcbEncoded
, bytesNeeded
)))
3259 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3260 pbEncoded
= *(BYTE
**)pbEncoded
;
3261 *pbEncoded
++ = ASN_BITSTRING
;
3262 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3263 pbEncoded
+= lenBytes
;
3264 *pbEncoded
++ = unusedBits
;
3267 BYTE mask
= 0xff << unusedBits
;
3271 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3272 pbEncoded
+= dataBytes
- 1;
3274 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3281 SetLastError(STATUS_ACCESS_VIOLATION
);
3288 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3289 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3290 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3296 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3297 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3302 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3307 for (i
= 0; i
< newBlob
.cbData
; i
++)
3308 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3314 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3315 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3316 CryptMemFree(newBlob
.pbData
);
3320 SetLastError(STATUS_ACCESS_VIOLATION
);
3327 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3328 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3329 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3331 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3333 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3334 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3337 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3338 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3339 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3345 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3348 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3350 significantBytes
= blob
->cbData
;
3351 if (significantBytes
)
3353 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3355 /* negative, lop off leading (little-endian) 0xffs */
3356 for (; significantBytes
> 0 &&
3357 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3359 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3367 /* positive, lop off leading (little-endian) zeroes */
3368 for (; significantBytes
> 0 &&
3369 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3371 if (significantBytes
== 0)
3372 significantBytes
= 1;
3373 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3381 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3383 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3384 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3389 *pcbEncoded
= bytesNeeded
;
3394 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3395 pcbEncoded
, bytesNeeded
)))
3397 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3398 pbEncoded
= *(BYTE
**)pbEncoded
;
3399 *pbEncoded
++ = ASN_INTEGER
;
3402 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3403 pbEncoded
+= lenBytes
;
3404 *pbEncoded
++ = padByte
;
3408 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3409 pbEncoded
+= lenBytes
;
3411 for (; significantBytes
> 0; significantBytes
--)
3412 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3418 SetLastError(STATUS_ACCESS_VIOLATION
);
3425 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3426 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3427 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3433 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3435 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3437 significantBytes
= blob
->cbData
;
3438 if (significantBytes
)
3440 /* positive, lop off leading (little-endian) zeroes */
3441 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3444 if (significantBytes
== 0)
3445 significantBytes
= 1;
3446 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3450 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3452 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3453 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3458 *pcbEncoded
= bytesNeeded
;
3463 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3464 pcbEncoded
, bytesNeeded
)))
3466 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3467 pbEncoded
= *(BYTE
**)pbEncoded
;
3468 *pbEncoded
++ = ASN_INTEGER
;
3471 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3472 pbEncoded
+= lenBytes
;
3477 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3478 pbEncoded
+= lenBytes
;
3480 for (; significantBytes
> 0; significantBytes
--)
3481 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3487 SetLastError(STATUS_ACCESS_VIOLATION
);
3494 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3495 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3496 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3498 CRYPT_INTEGER_BLOB blob
;
3501 /* Encode as an unsigned integer, then change the tag to enumerated */
3502 blob
.cbData
= sizeof(DWORD
);
3503 blob
.pbData
= (BYTE
*)pvStructInfo
;
3504 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3505 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3506 if (ret
&& pbEncoded
)
3508 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3509 pbEncoded
= *(BYTE
**)pbEncoded
;
3510 pbEncoded
[0] = ASN_ENUMERATED
;
3515 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3516 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3517 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3524 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a
3525 * temporary buffer because the output buffer is not NULL-terminated.
3527 static const DWORD bytesNeeded
= 15;
3532 *pcbEncoded
= bytesNeeded
;
3537 /* Sanity check the year, this is a two-digit year format */
3538 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3539 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3541 SetLastError(CRYPT_E_BAD_ENCODE
);
3546 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3547 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3549 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3550 pbEncoded
= *(BYTE
**)pbEncoded
;
3551 buf
[0] = ASN_UTCTIME
;
3552 buf
[1] = bytesNeeded
- 2;
3553 snprintf(buf
+ 2, sizeof(buf
) - 2,
3554 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3555 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3556 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3557 sysTime
.wMinute
, sysTime
.wSecond
);
3558 memcpy(pbEncoded
, buf
, bytesNeeded
);
3565 SetLastError(STATUS_ACCESS_VIOLATION
);
3572 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3573 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3574 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3581 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a
3582 * temporary buffer because the output buffer is not NULL-terminated.
3584 static const DWORD bytesNeeded
= 17;
3589 *pcbEncoded
= bytesNeeded
;
3594 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3596 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3597 pcbEncoded
, bytesNeeded
);
3600 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3601 pbEncoded
= *(BYTE
**)pbEncoded
;
3602 buf
[0] = ASN_GENERALTIME
;
3603 buf
[1] = bytesNeeded
- 2;
3604 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3605 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3606 sysTime
.wMinute
, sysTime
.wSecond
);
3607 memcpy(pbEncoded
, buf
, bytesNeeded
);
3613 SetLastError(STATUS_ACCESS_VIOLATION
);
3620 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3621 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3622 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3630 /* Check the year, if it's in the UTCTime range call that encode func */
3631 if (!FileTimeToSystemTime(pvStructInfo
, &sysTime
))
3633 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3634 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3635 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3637 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3638 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3643 SetLastError(STATUS_ACCESS_VIOLATION
);
3650 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3651 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3652 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3658 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3659 const CRYPT_SEQUENCE_OF_ANY
*seq
= pvStructInfo
;
3661 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3662 dataLen
+= seq
->rgValue
[i
].cbData
;
3663 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3664 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3667 *pcbEncoded
= bytesNeeded
;
3672 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3673 pcbEncoded
, bytesNeeded
)))
3675 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3676 pbEncoded
= *(BYTE
**)pbEncoded
;
3677 *pbEncoded
++ = ASN_SEQUENCEOF
;
3678 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3679 pbEncoded
+= lenBytes
;
3680 for (i
= 0; i
< seq
->cValue
; i
++)
3682 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3683 seq
->rgValue
[i
].cbData
);
3684 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3691 SetLastError(STATUS_ACCESS_VIOLATION
);
3698 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3699 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3702 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3703 struct AsnConstructedItem constructed
= { 0 };
3704 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3705 DWORD cItem
= 0, cSwapped
= 0;
3707 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3709 case CRL_DIST_POINT_NO_NAME
:
3712 case CRL_DIST_POINT_FULL_NAME
:
3713 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3714 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3715 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3716 constructed
.tag
= 0;
3717 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3718 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3719 items
[cItem
].pvStructInfo
= &constructed
;
3720 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3724 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3725 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3731 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3733 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3734 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3735 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3736 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3737 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3741 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3743 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3744 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3745 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3746 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3747 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3752 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3753 pbEncoded
, pcbEncoded
);
3757 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3758 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3759 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3765 const CRL_DIST_POINTS_INFO
*info
= pvStructInfo
;
3767 if (!info
->cDistPoint
)
3769 SetLastError(E_INVALIDARG
);
3774 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3777 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3781 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3785 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3787 /* Have to propagate index of failing character */
3793 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3794 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3797 *pcbEncoded
= bytesNeeded
;
3802 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3803 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3807 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3808 pbEncoded
= *(BYTE
**)pbEncoded
;
3810 *out
++ = ASN_SEQUENCEOF
;
3811 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
3813 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3815 DWORD len
= dataLen
;
3817 ret
= CRYPT_AsnEncodeDistPoint(
3818 &info
->rgDistPoint
[i
], out
, &len
);
3825 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3826 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3834 SetLastError(STATUS_ACCESS_VIOLATION
);
3841 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3842 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3843 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3849 const CERT_ENHKEY_USAGE
*usage
= pvStructInfo
;
3850 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3853 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3855 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3856 usage
->rgpszUsageIdentifier
[i
],
3857 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3859 bytesNeeded
+= size
;
3861 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3862 bytesNeeded
+= 1 + lenBytes
;
3866 *pcbEncoded
= bytesNeeded
;
3869 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3870 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3874 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3875 pbEncoded
= *(BYTE
**)pbEncoded
;
3877 *out
++ = ASN_SEQUENCEOF
;
3878 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3880 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3883 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3884 usage
->rgpszUsageIdentifier
[i
],
3885 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
3889 bytesNeeded
-= size
;
3892 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3893 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3900 SetLastError(STATUS_ACCESS_VIOLATION
);
3907 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3908 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3909 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3915 const CRL_ISSUING_DIST_POINT
*point
= pvStructInfo
;
3916 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3917 struct AsnConstructedItem constructed
= { 0 };
3918 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3919 DWORD cItem
= 0, cSwapped
= 0;
3922 switch (point
->DistPointName
.dwDistPointNameChoice
)
3924 case CRL_DIST_POINT_NO_NAME
:
3927 case CRL_DIST_POINT_FULL_NAME
:
3928 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3929 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3930 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3931 constructed
.tag
= 0;
3932 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3933 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3934 items
[cItem
].pvStructInfo
= &constructed
;
3935 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3940 SetLastError(E_INVALIDARG
);
3943 if (ret
&& point
->fOnlyContainsUserCerts
)
3945 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3946 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3947 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3948 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3949 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3953 if (ret
&& point
->fOnlyContainsCACerts
)
3955 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
3956 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
3957 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3958 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3959 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3963 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
3965 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
3966 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
3967 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3968 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3969 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3973 if (ret
&& point
->fIndirectCRL
)
3975 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
3976 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
3977 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3978 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3979 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3984 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
3985 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3989 SetLastError(STATUS_ACCESS_VIOLATION
);
3996 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
3997 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3998 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4001 const CERT_GENERAL_SUBTREE
*subtree
= pvStructInfo
;
4002 struct AsnEncodeSequenceItem items
[3] = {
4003 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
4006 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4007 DWORD cItem
= 1, cSwapped
= 0;
4009 if (subtree
->dwMinimum
)
4011 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4012 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
4013 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4014 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4015 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4019 if (subtree
->fMaximum
)
4021 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
4022 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
4023 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4024 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4025 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4029 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
4030 pEncodePara
, pbEncoded
, pcbEncoded
);
4034 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
4035 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4036 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4039 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
4041 TRACE("%p\n", pvStructInfo
);
4045 const CERT_NAME_CONSTRAINTS_INFO
*constraints
= pvStructInfo
;
4046 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
4047 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4048 DWORD i
, cItem
= 0, cSwapped
= 0;
4051 if (constraints
->cPermittedSubtree
)
4053 permitted
.rgBlob
= CryptMemAlloc(
4054 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
4055 if (permitted
.rgBlob
)
4057 permitted
.cBlob
= constraints
->cPermittedSubtree
;
4058 memset(permitted
.rgBlob
, 0,
4059 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4060 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
4061 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4062 NULL
, &constraints
->rgPermittedSubtree
[i
],
4063 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4064 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
4065 &permitted
.rgBlob
[i
].cbData
);
4068 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4069 swapped
[cSwapped
].pvStructInfo
= &permitted
;
4070 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4071 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4072 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4080 if (constraints
->cExcludedSubtree
)
4082 excluded
.rgBlob
= CryptMemAlloc(
4083 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
4084 if (excluded
.rgBlob
)
4086 excluded
.cBlob
= constraints
->cExcludedSubtree
;
4087 memset(excluded
.rgBlob
, 0,
4088 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4089 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
4090 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4091 NULL
, &constraints
->rgExcludedSubtree
[i
],
4092 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4093 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
4094 &excluded
.rgBlob
[i
].cbData
);
4097 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4098 swapped
[cSwapped
].pvStructInfo
= &excluded
;
4099 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4100 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4101 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4110 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4111 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4112 for (i
= 0; i
< permitted
.cBlob
; i
++)
4113 LocalFree(permitted
.rgBlob
[i
].pbData
);
4114 for (i
= 0; i
< excluded
.cBlob
; i
++)
4115 LocalFree(excluded
.rgBlob
[i
].pbData
);
4119 SetLastError(STATUS_ACCESS_VIOLATION
);
4122 CryptMemFree(permitted
.rgBlob
);
4123 CryptMemFree(excluded
.rgBlob
);
4124 TRACE("returning %d\n", ret
);
4128 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
4129 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
4130 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
4134 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
= pvStructInfo
;
4135 struct AsnEncodeSequenceItem items
[] = {
4136 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
4137 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
4140 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4141 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4145 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
4146 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4147 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4151 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4153 SetLastError(E_INVALIDARG
);
4159 const CMSG_SIGNER_INFO
*info
= pvStructInfo
;
4161 if (!info
->Issuer
.cbData
)
4162 SetLastError(E_INVALIDARG
);
4165 struct AsnEncodeSequenceItem items
[7] = {
4166 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4167 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4168 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
4171 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4172 DWORD cItem
= 3, cSwapped
= 0;
4174 if (info
->AuthAttrs
.cAttr
)
4176 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4177 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4178 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4179 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4180 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4184 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4185 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4187 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4188 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4190 if (info
->UnauthAttrs
.cAttr
)
4192 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4193 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4194 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4195 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4196 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4200 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4201 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4206 SetLastError(STATUS_ACCESS_VIOLATION
);
4212 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4213 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4214 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4218 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4220 SetLastError(E_INVALIDARG
);
4226 const CMSG_CMS_SIGNER_INFO
*info
= pvStructInfo
;
4228 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4229 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4230 SetLastError(E_INVALIDARG
);
4231 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4232 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4233 SetLastError(E_INVALIDARG
);
4236 struct AsnEncodeSequenceItem items
[7] = {
4237 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4239 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4240 DWORD cItem
= 1, cSwapped
= 0;
4242 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4244 items
[cItem
].pvStructInfo
=
4245 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4246 items
[cItem
].encodeFunc
=
4247 CRYPT_AsnEncodeIssuerSerialNumber
;
4252 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4253 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4254 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4255 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4256 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4260 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4261 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4263 if (info
->AuthAttrs
.cAttr
)
4265 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4266 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4267 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4268 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4269 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4273 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4274 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4276 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4277 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4279 if (info
->UnauthAttrs
.cAttr
)
4281 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4282 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4283 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4284 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4285 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4289 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4290 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4295 SetLastError(STATUS_ACCESS_VIOLATION
);
4301 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4304 struct AsnEncodeSequenceItem items
[7] = {
4305 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4307 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4308 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4309 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4310 DWORD cItem
= 1, cSwapped
= 0;
4313 if (signedInfo
->cSignerInfo
)
4315 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4316 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4317 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4318 digestAlgorithmsSet
.itemOffset
=
4319 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4320 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4321 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4322 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4325 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4326 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4328 if (signedInfo
->cCertEncoded
)
4330 certSet
.cItems
= signedInfo
->cCertEncoded
;
4331 certSet
.items
= signedInfo
->rgCertEncoded
;
4332 certSet
.itemSize
= sizeof(CERT_BLOB
);
4333 certSet
.itemOffset
= 0;
4334 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4335 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4336 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4337 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4338 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4339 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4343 if (signedInfo
->cCrlEncoded
)
4345 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4346 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4347 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4348 crlSet
.itemOffset
= 0;
4349 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4350 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4351 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4352 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4353 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4354 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4358 if (ret
&& signedInfo
->cSignerInfo
)
4360 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4361 signerSet
.items
= signedInfo
->rgSignerInfo
;
4362 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4363 signerSet
.itemOffset
= 0;
4364 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4365 items
[cItem
].pvStructInfo
= &signerSet
;
4366 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4370 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4371 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4376 static BOOL WINAPI
CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType
,
4377 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4378 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4380 const CMSG_KEY_TRANS_RECIPIENT_INFO
*info
= pvStructInfo
;
4381 struct AsnEncodeSequenceItem items
[] = {
4382 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4383 { &info
->RecipientId
.u
.IssuerSerialNumber
,
4384 CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4385 { &info
->KeyEncryptionAlgorithm
,
4386 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4387 { &info
->EncryptedKey
, CRYPT_AsnEncodeOctets
, 0 },
4390 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4391 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4394 static BOOL WINAPI
CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType
,
4395 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4396 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4398 const CRYPT_ENCRYPTED_CONTENT_INFO
*info
= pvStructInfo
;
4399 struct AsnEncodeTagSwappedItem swapped
= { ASN_CONTEXT
| 0,
4400 &info
->encryptedContent
, CRYPT_AsnEncodeOctets
};
4401 struct AsnEncodeSequenceItem items
[] = {
4402 { info
->contentType
, CRYPT_AsnEncodeOid
, 0 },
4403 { &info
->contentEncryptionAlgorithm
,
4404 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4405 { &swapped
, CRYPT_AsnEncodeSwapTag
, 0 },
4408 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4409 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4412 BOOL
CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA
*envelopedData
,
4413 void *pvData
, DWORD
*pcbData
)
4415 struct DERSetDescriptor recipientInfosSet
= { envelopedData
->cRecipientInfo
,
4416 envelopedData
->rgRecipientInfo
, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
), 0,
4417 CRYPT_AsnEncodeRecipientInfo
};
4418 struct AsnEncodeSequenceItem items
[] = {
4419 { &envelopedData
->version
, CRYPT_AsnEncodeInt
, 0 },
4420 { &recipientInfosSet
, CRYPT_DEREncodeItemsAsSet
, 0 },
4421 { &envelopedData
->encryptedContentInfo
,
4422 CRYPT_AsnEncodeEncryptedContentInfo
, 0 },
4425 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
4426 ARRAY_SIZE(items
), 0, NULL
, pvData
, pcbData
);
4429 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4430 LPCSTR lpszStructType
)
4432 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4434 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4435 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4437 SetLastError(ERROR_FILE_NOT_FOUND
);
4441 if (IS_INTOID(lpszStructType
))
4443 switch (LOWORD(lpszStructType
))
4445 case LOWORD(X509_CERT
):
4446 encodeFunc
= CRYPT_AsnEncodeCert
;
4448 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4449 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4451 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4452 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4454 case LOWORD(X509_EXTENSIONS
):
4455 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4457 case LOWORD(X509_NAME_VALUE
):
4458 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4460 case LOWORD(X509_NAME
):
4461 encodeFunc
= CRYPT_AsnEncodeName
;
4463 case LOWORD(X509_PUBLIC_KEY_INFO
):
4464 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4466 case LOWORD(X509_AUTHORITY_KEY_ID
):
4467 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4469 case LOWORD(X509_ALTERNATE_NAME
):
4470 encodeFunc
= CRYPT_AsnEncodeAltName
;
4472 case LOWORD(X509_BASIC_CONSTRAINTS
):
4473 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4475 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4476 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4478 case LOWORD(X509_CERT_POLICIES
):
4479 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4481 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4482 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4484 case LOWORD(X509_UNICODE_NAME
):
4485 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4487 case LOWORD(PKCS_CONTENT_INFO
):
4488 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4490 case LOWORD(PKCS_ATTRIBUTE
):
4491 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4493 case LOWORD(X509_UNICODE_NAME_VALUE
):
4494 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4496 case LOWORD(X509_OCTET_STRING
):
4497 encodeFunc
= CRYPT_AsnEncodeOctets
;
4499 case LOWORD(X509_BITS
):
4500 case LOWORD(X509_KEY_USAGE
):
4501 encodeFunc
= CRYPT_AsnEncodeBits
;
4503 case LOWORD(X509_INTEGER
):
4504 encodeFunc
= CRYPT_AsnEncodeInt
;
4506 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4507 encodeFunc
= CRYPT_AsnEncodeInteger
;
4509 case LOWORD(X509_MULTI_BYTE_UINT
):
4510 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4512 case LOWORD(X509_ENUMERATED
):
4513 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4515 case LOWORD(X509_CHOICE_OF_TIME
):
4516 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4518 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4519 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4521 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4522 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4524 case LOWORD(X509_SEQUENCE_OF_ANY
):
4525 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4527 case LOWORD(PKCS_UTC_TIME
):
4528 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4530 case LOWORD(X509_CRL_DIST_POINTS
):
4531 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4533 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4534 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4536 case LOWORD(PKCS_CTL
):
4537 encodeFunc
= CRYPT_AsnEncodeCTL
;
4539 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4540 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4542 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4543 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4545 case LOWORD(PKCS_ATTRIBUTES
):
4546 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4548 case LOWORD(X509_ISSUING_DIST_POINT
):
4549 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4551 case LOWORD(X509_NAME_CONSTRAINTS
):
4552 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4554 case LOWORD(X509_POLICY_MAPPINGS
):
4555 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4557 case LOWORD(X509_POLICY_CONSTRAINTS
):
4558 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4560 case LOWORD(PKCS7_SIGNER_INFO
):
4561 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4563 case LOWORD(CMS_SIGNER_INFO
):
4564 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4568 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4569 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4570 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4571 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4572 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4573 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4574 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4575 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4576 else if (!strcmp(lpszStructType
, szOID_LEGACY_POLICY_MAPPINGS
))
4577 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4578 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4579 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4580 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4581 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4582 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4583 encodeFunc
= CRYPT_AsnEncodeBits
;
4584 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4585 encodeFunc
= CRYPT_AsnEncodeOctets
;
4586 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4587 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4588 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4589 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4590 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4591 encodeFunc
= CRYPT_AsnEncodeAltName
;
4592 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4593 encodeFunc
= CRYPT_AsnEncodeAltName
;
4594 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4595 encodeFunc
= CRYPT_AsnEncodeAltName
;
4596 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4597 encodeFunc
= CRYPT_AsnEncodeAltName
;
4598 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4599 encodeFunc
= CRYPT_AsnEncodeAltName
;
4600 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4601 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4602 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4603 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4604 else if (!strcmp(lpszStructType
, szOID_POLICY_MAPPINGS
))
4605 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4606 else if (!strcmp(lpszStructType
, szOID_POLICY_CONSTRAINTS
))
4607 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4608 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4609 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4610 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4611 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4612 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4613 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4614 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4615 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4616 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4617 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4618 else if (!strcmp(lpszStructType
, szOID_CTL
))
4619 encodeFunc
= CRYPT_AsnEncodeCTL
;
4623 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4624 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4626 static HCRYPTOIDFUNCSET set
= NULL
;
4627 CryptEncodeObjectFunc encodeFunc
= NULL
;
4630 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4631 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4632 (void **)&encodeFunc
, hFunc
);
4636 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4637 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4639 static HCRYPTOIDFUNCSET set
= NULL
;
4640 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4643 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4644 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4645 (void **)&encodeFunc
, hFunc
);
4649 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4650 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4653 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4654 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4655 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4657 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4658 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4661 if (!pbEncoded
&& !pcbEncoded
)
4663 SetLastError(ERROR_INVALID_PARAMETER
);
4667 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4670 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4671 debugstr_a(lpszStructType
));
4672 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4673 lpszStructType
, &hFunc
);
4674 if (!pCryptEncodeObject
)
4675 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4676 lpszStructType
, &hFunc
);
4678 if (pCryptEncodeObject
)
4679 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4680 pvStructInfo
, pbEncoded
, pcbEncoded
);
4681 else if (pCryptEncodeObjectEx
)
4682 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4683 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4685 CryptFreeOIDFunctionAddress(hFunc
, 0);
4686 TRACE_(crypt
)("returning %d\n", ret
);
4690 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4691 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4692 void *pvEncoded
, DWORD
*pcbEncoded
)
4695 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4696 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4698 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4699 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4700 pvEncoded
, pcbEncoded
);
4702 if (!pvEncoded
&& !pcbEncoded
)
4704 SetLastError(ERROR_INVALID_PARAMETER
);
4708 SetLastError(NOERROR
);
4709 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
) {
4711 SetLastError(ERROR_INVALID_PARAMETER
);
4714 *(BYTE
**)pvEncoded
= NULL
;
4716 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4719 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4720 debugstr_a(lpszStructType
));
4721 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4725 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4726 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4729 CryptEncodeObjectFunc pCryptEncodeObject
=
4730 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4732 if (pCryptEncodeObject
)
4734 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4736 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4737 pvStructInfo
, NULL
, pcbEncoded
);
4738 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4739 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4740 ret
= pCryptEncodeObject(dwCertEncodingType
,
4741 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4745 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4746 pvStructInfo
, pvEncoded
, pcbEncoded
);
4750 CryptFreeOIDFunctionAddress(hFunc
, 0);
4751 TRACE_(crypt
)("returning %d\n", ret
);
4755 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4756 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4758 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4759 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4762 typedef BOOL (WINAPI
*EncodePublicKeyAndParametersFunc
)(DWORD dwCertEncodingType
,
4763 LPSTR pszPublicKeyObjId
, BYTE
*pbPubKey
, DWORD cbPubKey
, DWORD dwFlags
, void *pvAuxInfo
,
4764 BYTE
**ppPublicKey
, DWORD
*pcbPublicKey
, BYTE
**ppbParams
, DWORD
*pcbParams
);
4766 static BOOL WINAPI
CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4767 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4768 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4772 static CHAR rsa_oid
[] = szOID_RSA_RSA
;
4774 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4775 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4776 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4778 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4782 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4785 PUBLICKEYSTRUC
*pubKey
= CryptMemAlloc(keySize
);
4789 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, (BYTE
*)pubKey
, &keySize
);
4794 if (!pszPublicKeyObjId
)
4796 static HCRYPTOIDFUNCSET set
;
4797 EncodePublicKeyAndParametersFunc encodeFunc
= NULL
;
4798 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4800 pszPublicKeyObjId
= (LPSTR
)CertAlgIdToOID(pubKey
->aiKeyAlg
);
4801 TRACE("public key algid %#x (%s)\n", pubKey
->aiKeyAlg
, debugstr_a(pszPublicKeyObjId
));
4803 if (!set
) /* FIXME: there is no a public macro */
4804 set
= CryptInitOIDFunctionSet("CryptDllEncodePublicKeyAndParameters", 0);
4806 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
, 0, (void **)&encodeFunc
, &hFunc
);
4809 BYTE
*key_data
= NULL
;
4811 BYTE
*params
= NULL
;
4812 DWORD params_size
= 0;
4814 ret
= encodeFunc(dwCertEncodingType
, pszPublicKeyObjId
, (BYTE
*)pubKey
, keySize
,
4815 dwFlags
, pvAuxInfo
, &key_data
, &key_size
, ¶ms
, ¶ms_size
);
4818 DWORD oid_size
= strlen(pszPublicKeyObjId
) + 1;
4819 DWORD size_needed
= sizeof(*pInfo
) + oid_size
+ key_size
+ params_size
;
4822 *pcbInfo
= size_needed
;
4823 else if (*pcbInfo
< size_needed
)
4825 *pcbInfo
= size_needed
;
4826 SetLastError(ERROR_MORE_DATA
);
4831 *pcbInfo
= size_needed
;
4832 pInfo
->Algorithm
.pszObjId
= (char *)(pInfo
+ 1);
4833 lstrcpyA(pInfo
->Algorithm
.pszObjId
, pszPublicKeyObjId
);
4836 pInfo
->Algorithm
.Parameters
.cbData
= params_size
;
4837 pInfo
->Algorithm
.Parameters
.pbData
= (BYTE
*)pInfo
->Algorithm
.pszObjId
+ oid_size
;
4838 memcpy(pInfo
->Algorithm
.Parameters
.pbData
, params
, params_size
);
4842 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4843 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4845 pInfo
->PublicKey
.pbData
= (BYTE
*)pInfo
->Algorithm
.pszObjId
+ oid_size
+ params_size
;
4846 pInfo
->PublicKey
.cbData
= key_size
;
4847 memcpy(pInfo
->PublicKey
.pbData
, key_data
, key_size
);
4848 pInfo
->PublicKey
.cUnusedBits
= 0;
4851 CryptMemFree(key_data
);
4852 CryptMemFree(params
);
4855 CryptMemFree(pubKey
);
4856 CryptFreeOIDFunctionAddress(hFunc
, 0);
4860 /* fallback to RSA */
4861 pszPublicKeyObjId
= rsa_oid
;
4865 ret
= CryptEncodeObject(dwCertEncodingType
,
4866 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4869 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4870 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4873 *pcbInfo
= sizeNeeded
;
4874 else if (*pcbInfo
< sizeNeeded
)
4876 SetLastError(ERROR_MORE_DATA
);
4877 *pcbInfo
= sizeNeeded
;
4882 *pcbInfo
= sizeNeeded
;
4883 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4884 sizeof(CERT_PUBLIC_KEY_INFO
);
4885 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4887 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4888 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4889 pInfo
->PublicKey
.pbData
=
4890 (BYTE
*)pInfo
->Algorithm
.pszObjId
4891 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4892 pInfo
->PublicKey
.cbData
= encodedLen
;
4893 pInfo
->PublicKey
.cUnusedBits
= 0;
4894 ret
= CryptEncodeObject(dwCertEncodingType
,
4895 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4896 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4900 CryptMemFree(pubKey
);
4905 CryptDestroyKey(key
);
4910 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4911 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4912 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4914 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4915 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4916 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4918 static HCRYPTOIDFUNCSET set
= NULL
;
4920 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4921 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4923 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4924 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4925 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4929 SetLastError(ERROR_INVALID_PARAMETER
);
4933 if (pszPublicKeyObjId
)
4936 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4938 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4939 0, (void **)&exportFunc
, &hFunc
);
4942 exportFunc
= CRYPT_ExportPublicKeyInfoEx
;
4943 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4944 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4946 CryptFreeOIDFunctionAddress(hFunc
, 0);
4950 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
4951 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
4953 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
4957 typedef BOOL (WINAPI
*ConvertPublicKeyInfoFunc
)(DWORD dwCertEncodingType
,
4958 PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
, DWORD dwFlags
,
4959 BYTE
**ppbData
, DWORD
*dwDataLen
);
4961 static BOOL WINAPI
CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
4962 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
4963 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
4965 static HCRYPTOIDFUNCSET set
= NULL
;
4966 ConvertPublicKeyInfoFunc convertFunc
= NULL
;
4967 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4972 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
4973 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
4976 set
= CryptInitOIDFunctionSet(CRYPT_OID_CONVERT_PUBLIC_KEY_INFO_FUNC
, 0);
4977 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pInfo
->Algorithm
.pszObjId
,
4978 0, (void **)&convertFunc
, &hFunc
);
4983 ret
= convertFunc(dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, &pubKey
, &pubKeySize
);
4986 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0, phKey
);
4987 CryptMemFree(pubKey
);
4990 CryptFreeOIDFunctionAddress(hFunc
, 0);
4994 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
4995 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
4998 pubKey
= CryptMemAlloc(pubKeySize
);
5002 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5003 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5008 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
5009 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5012 CryptMemFree(pubKey
);
5020 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5021 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5022 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5024 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5025 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5026 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5028 static HCRYPTOIDFUNCSET set
= NULL
;
5030 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5031 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5033 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
5034 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5037 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
5038 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
5039 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
5041 importFunc
= CRYPT_ImportPublicKeyInfoEx
;
5042 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
5045 CryptFreeOIDFunctionAddress(hFunc
, 0);
5049 BOOL WINAPI
CryptImportPublicKeyInfoEx2(DWORD dwCertEncodingType
,
5050 PCERT_PUBLIC_KEY_INFO pInfo
, DWORD dwFlags
, void *pvAuxInfo
,
5051 BCRYPT_KEY_HANDLE
*phKey
)
5053 FIXME_(crypt
)("(%d, %p, %08x, %p, %p): stub\n", dwCertEncodingType
, pInfo
,
5054 dwFlags
, pvAuxInfo
, phKey
);
5055 SetLastError(ERROR_FILE_NOT_FOUND
);