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_Bcrypt(DWORD dwCertEncodingType
,
3134 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3135 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3141 const BCRYPT_RSAKEY_BLOB
*hdr
= pvStructInfo
;
3143 BYTE
*pubexp
= (BYTE
*)pvStructInfo
+ sizeof(BCRYPT_RSAKEY_BLOB
);
3144 BYTE
*modulus
= (BYTE
*)pvStructInfo
+ sizeof(BCRYPT_RSAKEY_BLOB
) + hdr
->cbPublicExp
;
3145 BYTE
*pubexp_be
= CryptMemAlloc(hdr
->cbPublicExp
);
3146 BYTE
*modulus_be
= CryptMemAlloc(hdr
->cbModulus
);
3147 CRYPT_INTEGER_BLOB pubexp_int
= { hdr
->cbPublicExp
, pubexp_be
};
3148 CRYPT_INTEGER_BLOB modulus_int
= { hdr
->cbModulus
, modulus_be
};
3150 struct AsnEncodeSequenceItem items
[] = {
3151 { &modulus_int
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3152 { &pubexp_int
, CRYPT_AsnEncodeInteger
, 0 },
3155 /* CNG_RSA_PUBLIC_KEY_BLOB stores the exponent and modulus
3156 * in big-endian format, so we need to convert them
3157 * to little-endian format before encoding
3159 CRYPT_CopyReversed(pubexp_be
, pubexp
, hdr
->cbPublicExp
);
3160 CRYPT_CopyReversed(modulus_be
, modulus
, hdr
->cbModulus
);
3162 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3163 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3165 CryptMemFree(pubexp_be
);
3166 CryptMemFree(modulus_be
);
3170 SetLastError(STATUS_ACCESS_VIOLATION
);
3179 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
3180 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3181 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3187 const BLOBHEADER
*hdr
= pvStructInfo
;
3189 if (hdr
->bType
!= PUBLICKEYBLOB
)
3191 SetLastError(E_INVALIDARG
);
3196 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
3197 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
3198 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
3199 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
3200 struct AsnEncodeSequenceItem items
[] = {
3201 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
3202 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
3205 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
3206 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3211 SetLastError(STATUS_ACCESS_VIOLATION
);
3218 BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
3219 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3220 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3226 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
3227 DWORD bytesNeeded
, lenBytes
;
3229 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob
->cbData
, blob
->pbData
,
3230 dwFlags
, pEncodePara
, pbEncoded
, pbEncoded
? *pcbEncoded
: 0);
3232 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
3233 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
3236 *pcbEncoded
= bytesNeeded
;
3241 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3242 pcbEncoded
, bytesNeeded
)))
3244 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3245 pbEncoded
= *(BYTE
**)pbEncoded
;
3246 *pbEncoded
++ = ASN_OCTETSTRING
;
3247 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
3248 pbEncoded
+= lenBytes
;
3250 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
3256 SetLastError(STATUS_ACCESS_VIOLATION
);
3260 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3264 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
3265 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3266 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3272 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3273 DWORD bytesNeeded
, lenBytes
, dataBytes
;
3276 /* yep, MS allows cUnusedBits to be >= 8 */
3277 if (!blob
->cUnusedBits
)
3279 dataBytes
= blob
->cbData
;
3282 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
3284 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
3285 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
3293 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
3294 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
3297 *pcbEncoded
= bytesNeeded
;
3302 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3303 pcbEncoded
, bytesNeeded
)))
3305 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3306 pbEncoded
= *(BYTE
**)pbEncoded
;
3307 *pbEncoded
++ = ASN_BITSTRING
;
3308 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
3309 pbEncoded
+= lenBytes
;
3310 *pbEncoded
++ = unusedBits
;
3313 BYTE mask
= 0xff << unusedBits
;
3317 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
3318 pbEncoded
+= dataBytes
- 1;
3320 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
3327 SetLastError(STATUS_ACCESS_VIOLATION
);
3334 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
3335 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3336 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3342 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
3343 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
3348 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
3353 for (i
= 0; i
< newBlob
.cbData
; i
++)
3354 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
3360 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
3361 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3362 CryptMemFree(newBlob
.pbData
);
3366 SetLastError(STATUS_ACCESS_VIOLATION
);
3373 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
3374 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3375 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3377 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
3379 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
3380 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3383 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
3384 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3385 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3391 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3394 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3396 significantBytes
= blob
->cbData
;
3397 if (significantBytes
)
3399 if (blob
->pbData
[significantBytes
- 1] & 0x80)
3401 /* negative, lop off leading (little-endian) 0xffs */
3402 for (; significantBytes
> 0 &&
3403 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
3405 if (blob
->pbData
[significantBytes
- 1] < 0x80)
3413 /* positive, lop off leading (little-endian) zeroes */
3414 for (; significantBytes
> 0 &&
3415 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
3417 if (significantBytes
== 0)
3418 significantBytes
= 1;
3419 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3427 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3429 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3430 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3435 *pcbEncoded
= bytesNeeded
;
3440 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3441 pcbEncoded
, bytesNeeded
)))
3443 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3444 pbEncoded
= *(BYTE
**)pbEncoded
;
3445 *pbEncoded
++ = ASN_INTEGER
;
3448 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3449 pbEncoded
+= lenBytes
;
3450 *pbEncoded
++ = padByte
;
3454 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3455 pbEncoded
+= lenBytes
;
3457 for (; significantBytes
> 0; significantBytes
--)
3458 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3464 SetLastError(STATUS_ACCESS_VIOLATION
);
3471 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
3472 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3473 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3479 DWORD significantBytes
, lenBytes
, bytesNeeded
;
3481 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
3483 significantBytes
= blob
->cbData
;
3484 if (significantBytes
)
3486 /* positive, lop off leading (little-endian) zeroes */
3487 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
3490 if (significantBytes
== 0)
3491 significantBytes
= 1;
3492 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
3496 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
3498 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
3499 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
3504 *pcbEncoded
= bytesNeeded
;
3509 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3510 pcbEncoded
, bytesNeeded
)))
3512 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3513 pbEncoded
= *(BYTE
**)pbEncoded
;
3514 *pbEncoded
++ = ASN_INTEGER
;
3517 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
3518 pbEncoded
+= lenBytes
;
3523 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
3524 pbEncoded
+= lenBytes
;
3526 for (; significantBytes
> 0; significantBytes
--)
3527 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
3533 SetLastError(STATUS_ACCESS_VIOLATION
);
3540 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
3541 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3542 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3544 CRYPT_INTEGER_BLOB blob
;
3547 /* Encode as an unsigned integer, then change the tag to enumerated */
3548 blob
.cbData
= sizeof(DWORD
);
3549 blob
.pbData
= (BYTE
*)pvStructInfo
;
3550 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
3551 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3552 if (ret
&& pbEncoded
)
3554 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3555 pbEncoded
= *(BYTE
**)pbEncoded
;
3556 pbEncoded
[0] = ASN_ENUMERATED
;
3561 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
3562 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3563 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3570 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a
3571 * temporary buffer because the output buffer is not NULL-terminated.
3573 static const DWORD bytesNeeded
= 15;
3578 *pcbEncoded
= bytesNeeded
;
3583 /* Sanity check the year, this is a two-digit year format */
3584 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3585 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
3587 SetLastError(CRYPT_E_BAD_ENCODE
);
3592 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3593 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3595 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3596 pbEncoded
= *(BYTE
**)pbEncoded
;
3597 buf
[0] = ASN_UTCTIME
;
3598 buf
[1] = bytesNeeded
- 2;
3599 snprintf(buf
+ 2, sizeof(buf
) - 2,
3600 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
3601 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
3602 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3603 sysTime
.wMinute
, sysTime
.wSecond
);
3604 memcpy(pbEncoded
, buf
, bytesNeeded
);
3611 SetLastError(STATUS_ACCESS_VIOLATION
);
3618 static BOOL
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
3619 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3620 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3627 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a
3628 * temporary buffer because the output buffer is not NULL-terminated.
3630 static const DWORD bytesNeeded
= 17;
3635 *pcbEncoded
= bytesNeeded
;
3640 ret
= FileTimeToSystemTime(pvStructInfo
, &sysTime
);
3642 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3643 pcbEncoded
, bytesNeeded
);
3646 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3647 pbEncoded
= *(BYTE
**)pbEncoded
;
3648 buf
[0] = ASN_GENERALTIME
;
3649 buf
[1] = bytesNeeded
- 2;
3650 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
3651 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
3652 sysTime
.wMinute
, sysTime
.wSecond
);
3653 memcpy(pbEncoded
, buf
, bytesNeeded
);
3659 SetLastError(STATUS_ACCESS_VIOLATION
);
3666 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
3667 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3668 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3676 /* Check the year, if it's in the UTCTime range call that encode func */
3677 if (!FileTimeToSystemTime(pvStructInfo
, &sysTime
))
3679 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
3680 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
3681 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
3683 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
3684 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
3689 SetLastError(STATUS_ACCESS_VIOLATION
);
3696 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
3697 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3698 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3704 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3705 const CRYPT_SEQUENCE_OF_ANY
*seq
= pvStructInfo
;
3707 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
3708 dataLen
+= seq
->rgValue
[i
].cbData
;
3709 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3710 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3713 *pcbEncoded
= bytesNeeded
;
3718 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
3719 pcbEncoded
, bytesNeeded
)))
3721 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3722 pbEncoded
= *(BYTE
**)pbEncoded
;
3723 *pbEncoded
++ = ASN_SEQUENCEOF
;
3724 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
3725 pbEncoded
+= lenBytes
;
3726 for (i
= 0; i
< seq
->cValue
; i
++)
3728 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
3729 seq
->rgValue
[i
].cbData
);
3730 pbEncoded
+= seq
->rgValue
[i
].cbData
;
3737 SetLastError(STATUS_ACCESS_VIOLATION
);
3744 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
3745 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3748 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
3749 struct AsnConstructedItem constructed
= { 0 };
3750 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
3751 DWORD cItem
= 0, cSwapped
= 0;
3753 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
3755 case CRL_DIST_POINT_NO_NAME
:
3758 case CRL_DIST_POINT_FULL_NAME
:
3759 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3760 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
3761 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3762 constructed
.tag
= 0;
3763 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3764 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3765 items
[cItem
].pvStructInfo
= &constructed
;
3766 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3770 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
3771 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3777 if (ret
&& distPoint
->ReasonFlags
.cbData
)
3779 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3780 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
3781 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
3782 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3783 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3787 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
3789 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
3790 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
3791 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3792 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3793 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3798 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
3799 pbEncoded
, pcbEncoded
);
3803 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
3804 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3805 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3811 const CRL_DIST_POINTS_INFO
*info
= pvStructInfo
;
3813 if (!info
->cDistPoint
)
3815 SetLastError(E_INVALIDARG
);
3820 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
3823 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3827 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
3831 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
3833 /* Have to propagate index of failing character */
3839 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
3840 bytesNeeded
= 1 + lenBytes
+ dataLen
;
3843 *pcbEncoded
= bytesNeeded
;
3848 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3849 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3853 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3854 pbEncoded
= *(BYTE
**)pbEncoded
;
3856 *out
++ = ASN_SEQUENCEOF
;
3857 CRYPT_EncodeLen(dataLen
, out
, &lenBytes
);
3859 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
3861 DWORD len
= dataLen
;
3863 ret
= CRYPT_AsnEncodeDistPoint(
3864 &info
->rgDistPoint
[i
], out
, &len
);
3871 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3872 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3880 SetLastError(STATUS_ACCESS_VIOLATION
);
3887 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3888 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3889 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3895 const CERT_ENHKEY_USAGE
*usage
= pvStructInfo
;
3896 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
3899 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3901 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3902 usage
->rgpszUsageIdentifier
[i
],
3903 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
3905 bytesNeeded
+= size
;
3907 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
3908 bytesNeeded
+= 1 + lenBytes
;
3912 *pcbEncoded
= bytesNeeded
;
3915 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
3916 pbEncoded
, pcbEncoded
, bytesNeeded
)))
3920 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
3921 pbEncoded
= *(BYTE
**)pbEncoded
;
3923 *out
++ = ASN_SEQUENCEOF
;
3924 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, out
, &lenBytes
);
3926 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
3929 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
3930 usage
->rgpszUsageIdentifier
[i
],
3931 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, out
, &size
);
3935 bytesNeeded
-= size
;
3938 if (!ret
&& (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
))
3939 CRYPT_FreeSpace(pEncodePara
, pbEncoded
);
3946 SetLastError(STATUS_ACCESS_VIOLATION
);
3953 static BOOL WINAPI
CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType
,
3954 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
3955 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
3961 const CRL_ISSUING_DIST_POINT
*point
= pvStructInfo
;
3962 struct AsnEncodeSequenceItem items
[6] = { { 0 } };
3963 struct AsnConstructedItem constructed
= { 0 };
3964 struct AsnEncodeTagSwappedItem swapped
[5] = { { 0 } };
3965 DWORD cItem
= 0, cSwapped
= 0;
3968 switch (point
->DistPointName
.dwDistPointNameChoice
)
3970 case CRL_DIST_POINT_NO_NAME
:
3973 case CRL_DIST_POINT_FULL_NAME
:
3974 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
3975 swapped
[cSwapped
].pvStructInfo
= &point
->DistPointName
.u
.FullName
;
3976 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
3977 constructed
.tag
= 0;
3978 constructed
.pvStructInfo
= &swapped
[cSwapped
];
3979 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3980 items
[cItem
].pvStructInfo
= &constructed
;
3981 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
3986 SetLastError(E_INVALIDARG
);
3989 if (ret
&& point
->fOnlyContainsUserCerts
)
3991 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
3992 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsUserCerts
;
3993 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
3994 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
3995 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
3999 if (ret
&& point
->fOnlyContainsCACerts
)
4001 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 2;
4002 swapped
[cSwapped
].pvStructInfo
= &point
->fOnlyContainsCACerts
;
4003 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
4004 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4005 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4009 if (ret
&& point
->OnlySomeReasonFlags
.cbData
)
4011 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 3;
4012 swapped
[cSwapped
].pvStructInfo
= &point
->OnlySomeReasonFlags
;
4013 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
4014 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4015 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4019 if (ret
&& point
->fIndirectCRL
)
4021 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 4;
4022 swapped
[cSwapped
].pvStructInfo
= &point
->fIndirectCRL
;
4023 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBool
;
4024 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4025 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4030 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4031 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4035 SetLastError(STATUS_ACCESS_VIOLATION
);
4042 static BOOL
CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType
,
4043 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4044 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4047 const CERT_GENERAL_SUBTREE
*subtree
= pvStructInfo
;
4048 struct AsnEncodeSequenceItem items
[3] = {
4049 { &subtree
->Base
, CRYPT_AsnEncodeAltNameEntry
, 0 },
4052 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4053 DWORD cItem
= 1, cSwapped
= 0;
4055 if (subtree
->dwMinimum
)
4057 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4058 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMinimum
;
4059 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4060 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4061 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4065 if (subtree
->fMaximum
)
4067 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
4068 swapped
[cSwapped
].pvStructInfo
= &subtree
->dwMaximum
;
4069 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeInt
;
4070 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4071 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4075 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
, dwFlags
,
4076 pEncodePara
, pbEncoded
, pcbEncoded
);
4080 static BOOL WINAPI
CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType
,
4081 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4082 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4085 CRYPT_BLOB_ARRAY permitted
= { 0, NULL
}, excluded
= { 0, NULL
};
4087 TRACE("%p\n", pvStructInfo
);
4091 const CERT_NAME_CONSTRAINTS_INFO
*constraints
= pvStructInfo
;
4092 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
4093 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4094 DWORD i
, cItem
= 0, cSwapped
= 0;
4097 if (constraints
->cPermittedSubtree
)
4099 permitted
.rgBlob
= CryptMemAlloc(
4100 constraints
->cPermittedSubtree
* sizeof(CRYPT_DER_BLOB
));
4101 if (permitted
.rgBlob
)
4103 permitted
.cBlob
= constraints
->cPermittedSubtree
;
4104 memset(permitted
.rgBlob
, 0,
4105 permitted
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4106 for (i
= 0; ret
&& i
< permitted
.cBlob
; i
++)
4107 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4108 NULL
, &constraints
->rgPermittedSubtree
[i
],
4109 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4110 (BYTE
*)&permitted
.rgBlob
[i
].pbData
,
4111 &permitted
.rgBlob
[i
].cbData
);
4114 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4115 swapped
[cSwapped
].pvStructInfo
= &permitted
;
4116 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4117 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4118 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4126 if (constraints
->cExcludedSubtree
)
4128 excluded
.rgBlob
= CryptMemAlloc(
4129 constraints
->cExcludedSubtree
* sizeof(CRYPT_DER_BLOB
));
4130 if (excluded
.rgBlob
)
4132 excluded
.cBlob
= constraints
->cExcludedSubtree
;
4133 memset(excluded
.rgBlob
, 0,
4134 excluded
.cBlob
* sizeof(CRYPT_DER_BLOB
));
4135 for (i
= 0; ret
&& i
< excluded
.cBlob
; i
++)
4136 ret
= CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType
,
4137 NULL
, &constraints
->rgExcludedSubtree
[i
],
4138 CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
4139 (BYTE
*)&excluded
.rgBlob
[i
].pbData
,
4140 &excluded
.rgBlob
[i
].cbData
);
4143 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4144 swapped
[cSwapped
].pvStructInfo
= &excluded
;
4145 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeSet
;
4146 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4147 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4156 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4157 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4158 for (i
= 0; i
< permitted
.cBlob
; i
++)
4159 LocalFree(permitted
.rgBlob
[i
].pbData
);
4160 for (i
= 0; i
< excluded
.cBlob
; i
++)
4161 LocalFree(excluded
.rgBlob
[i
].pbData
);
4165 SetLastError(STATUS_ACCESS_VIOLATION
);
4168 CryptMemFree(permitted
.rgBlob
);
4169 CryptMemFree(excluded
.rgBlob
);
4170 TRACE("returning %d\n", ret
);
4174 static BOOL WINAPI
CRYPT_AsnEncodeIssuerSerialNumber(
4175 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
4176 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
4180 const CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
= pvStructInfo
;
4181 struct AsnEncodeSequenceItem items
[] = {
4182 { &issuerSerial
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
4183 { &issuerSerial
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
4186 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4187 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4191 static BOOL WINAPI
CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType
,
4192 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4193 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4197 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4199 SetLastError(E_INVALIDARG
);
4205 const CMSG_SIGNER_INFO
*info
= pvStructInfo
;
4207 if (!info
->Issuer
.cbData
)
4208 SetLastError(E_INVALIDARG
);
4211 struct AsnEncodeSequenceItem items
[7] = {
4212 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4213 { &info
->Issuer
, CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4214 { &info
->HashAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
,
4217 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4218 DWORD cItem
= 3, cSwapped
= 0;
4220 if (info
->AuthAttrs
.cAttr
)
4222 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4223 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4224 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4225 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4226 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4230 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4231 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4233 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4234 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4236 if (info
->UnauthAttrs
.cAttr
)
4238 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4239 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4240 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4241 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4242 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4246 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4247 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4252 SetLastError(STATUS_ACCESS_VIOLATION
);
4258 static BOOL WINAPI
CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType
,
4259 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4260 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4264 if (!(dwCertEncodingType
& PKCS_7_ASN_ENCODING
))
4266 SetLastError(E_INVALIDARG
);
4272 const CMSG_CMS_SIGNER_INFO
*info
= pvStructInfo
;
4274 if (info
->SignerId
.dwIdChoice
!= CERT_ID_ISSUER_SERIAL_NUMBER
&&
4275 info
->SignerId
.dwIdChoice
!= CERT_ID_KEY_IDENTIFIER
)
4276 SetLastError(E_INVALIDARG
);
4277 else if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
&&
4278 !info
->SignerId
.u
.IssuerSerialNumber
.Issuer
.cbData
)
4279 SetLastError(E_INVALIDARG
);
4282 struct AsnEncodeSequenceItem items
[7] = {
4283 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4285 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
4286 DWORD cItem
= 1, cSwapped
= 0;
4288 if (info
->SignerId
.dwIdChoice
== CERT_ID_ISSUER_SERIAL_NUMBER
)
4290 items
[cItem
].pvStructInfo
=
4291 &info
->SignerId
.u
.IssuerSerialNumber
.Issuer
;
4292 items
[cItem
].encodeFunc
=
4293 CRYPT_AsnEncodeIssuerSerialNumber
;
4298 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 0;
4299 swapped
[cSwapped
].pvStructInfo
= &info
->SignerId
.u
.KeyId
;
4300 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4301 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4302 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4306 items
[cItem
].pvStructInfo
= &info
->HashAlgorithm
;
4307 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4309 if (info
->AuthAttrs
.cAttr
)
4311 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
4312 swapped
[cSwapped
].pvStructInfo
= &info
->AuthAttrs
;
4313 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4314 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4315 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4319 items
[cItem
].pvStructInfo
= &info
->HashEncryptionAlgorithm
;
4320 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4322 items
[cItem
].pvStructInfo
= &info
->EncryptedHash
;
4323 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
4325 if (info
->UnauthAttrs
.cAttr
)
4327 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1;
4328 swapped
[cSwapped
].pvStructInfo
= &info
->UnauthAttrs
;
4329 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4330 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4331 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4335 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
4336 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4341 SetLastError(STATUS_ACCESS_VIOLATION
);
4347 BOOL
CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO
*signedInfo
, void *pvData
,
4350 struct AsnEncodeSequenceItem items
[7] = {
4351 { &signedInfo
->version
, CRYPT_AsnEncodeInt
, 0 },
4353 struct DERSetDescriptor digestAlgorithmsSet
= { 0 }, certSet
= { 0 };
4354 struct DERSetDescriptor crlSet
= { 0 }, signerSet
= { 0 };
4355 struct AsnEncodeTagSwappedItem swapped
[2] = { { 0 } };
4356 DWORD cItem
= 1, cSwapped
= 0;
4359 if (signedInfo
->cSignerInfo
)
4361 digestAlgorithmsSet
.cItems
= signedInfo
->cSignerInfo
;
4362 digestAlgorithmsSet
.items
= signedInfo
->rgSignerInfo
;
4363 digestAlgorithmsSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4364 digestAlgorithmsSet
.itemOffset
=
4365 offsetof(CMSG_CMS_SIGNER_INFO
, HashAlgorithm
);
4366 digestAlgorithmsSet
.encode
= CRYPT_AsnEncodeAlgorithmIdWithNullParams
;
4367 items
[cItem
].pvStructInfo
= &digestAlgorithmsSet
;
4368 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4371 items
[cItem
].pvStructInfo
= &signedInfo
->content
;
4372 items
[cItem
].encodeFunc
= CRYPT_AsnEncodePKCSContentInfoInternal
;
4374 if (signedInfo
->cCertEncoded
)
4376 certSet
.cItems
= signedInfo
->cCertEncoded
;
4377 certSet
.items
= signedInfo
->rgCertEncoded
;
4378 certSet
.itemSize
= sizeof(CERT_BLOB
);
4379 certSet
.itemOffset
= 0;
4380 certSet
.encode
= CRYPT_CopyEncodedBlob
;
4381 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0;
4382 swapped
[cSwapped
].pvStructInfo
= &certSet
;
4383 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4384 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4385 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4389 if (signedInfo
->cCrlEncoded
)
4391 crlSet
.cItems
= signedInfo
->cCrlEncoded
;
4392 crlSet
.items
= signedInfo
->rgCrlEncoded
;
4393 crlSet
.itemSize
= sizeof(CRL_BLOB
);
4394 crlSet
.itemOffset
= 0;
4395 crlSet
.encode
= CRYPT_CopyEncodedBlob
;
4396 swapped
[cSwapped
].tag
= ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
4397 swapped
[cSwapped
].pvStructInfo
= &crlSet
;
4398 swapped
[cSwapped
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4399 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
4400 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
4404 if (ret
&& signedInfo
->cSignerInfo
)
4406 signerSet
.cItems
= signedInfo
->cSignerInfo
;
4407 signerSet
.items
= signedInfo
->rgSignerInfo
;
4408 signerSet
.itemSize
= sizeof(CMSG_CMS_SIGNER_INFO
);
4409 signerSet
.itemOffset
= 0;
4410 signerSet
.encode
= CRYPT_AsnEncodeCMSSignerInfo
;
4411 items
[cItem
].pvStructInfo
= &signerSet
;
4412 items
[cItem
].encodeFunc
= CRYPT_DEREncodeItemsAsSet
;
4416 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
4417 items
, cItem
, 0, NULL
, pvData
, pcbData
);
4422 static BOOL WINAPI
CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType
,
4423 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4424 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4426 const CMSG_KEY_TRANS_RECIPIENT_INFO
*info
= pvStructInfo
;
4427 struct AsnEncodeSequenceItem items
[] = {
4428 { &info
->dwVersion
, CRYPT_AsnEncodeInt
, 0 },
4429 { &info
->RecipientId
.u
.IssuerSerialNumber
,
4430 CRYPT_AsnEncodeIssuerSerialNumber
, 0 },
4431 { &info
->KeyEncryptionAlgorithm
,
4432 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4433 { &info
->EncryptedKey
, CRYPT_AsnEncodeOctets
, 0 },
4436 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4437 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4440 static BOOL WINAPI
CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType
,
4441 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
4442 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4444 const CRYPT_ENCRYPTED_CONTENT_INFO
*info
= pvStructInfo
;
4445 struct AsnEncodeTagSwappedItem swapped
= { ASN_CONTEXT
| 0,
4446 &info
->encryptedContent
, CRYPT_AsnEncodeOctets
};
4447 struct AsnEncodeSequenceItem items
[] = {
4448 { info
->contentType
, CRYPT_AsnEncodeOid
, 0 },
4449 { &info
->contentEncryptionAlgorithm
,
4450 CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
4451 { &swapped
, CRYPT_AsnEncodeSwapTag
, 0 },
4454 return CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
4455 ARRAY_SIZE(items
), dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
4458 BOOL
CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA
*envelopedData
,
4459 void *pvData
, DWORD
*pcbData
)
4461 struct DERSetDescriptor recipientInfosSet
= { envelopedData
->cRecipientInfo
,
4462 envelopedData
->rgRecipientInfo
, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO
), 0,
4463 CRYPT_AsnEncodeRecipientInfo
};
4464 struct AsnEncodeSequenceItem items
[] = {
4465 { &envelopedData
->version
, CRYPT_AsnEncodeInt
, 0 },
4466 { &recipientInfosSet
, CRYPT_DEREncodeItemsAsSet
, 0 },
4467 { &envelopedData
->encryptedContentInfo
,
4468 CRYPT_AsnEncodeEncryptedContentInfo
, 0 },
4471 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
,
4472 ARRAY_SIZE(items
), 0, NULL
, pvData
, pcbData
);
4475 static CryptEncodeObjectExFunc
CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType
,
4476 LPCSTR lpszStructType
)
4478 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4480 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4481 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4483 SetLastError(ERROR_FILE_NOT_FOUND
);
4487 if (IS_INTOID(lpszStructType
))
4489 switch (LOWORD(lpszStructType
))
4491 case LOWORD(X509_CERT
):
4492 encodeFunc
= CRYPT_AsnEncodeCert
;
4494 case LOWORD(X509_CERT_TO_BE_SIGNED
):
4495 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
4497 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED
):
4498 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
4500 case LOWORD(X509_EXTENSIONS
):
4501 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4503 case LOWORD(X509_NAME_VALUE
):
4504 encodeFunc
= CRYPT_AsnEncodeNameValue
;
4506 case LOWORD(X509_NAME
):
4507 encodeFunc
= CRYPT_AsnEncodeName
;
4509 case LOWORD(X509_PUBLIC_KEY_INFO
):
4510 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
4512 case LOWORD(X509_AUTHORITY_KEY_ID
):
4513 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4515 case LOWORD(X509_ALTERNATE_NAME
):
4516 encodeFunc
= CRYPT_AsnEncodeAltName
;
4518 case LOWORD(X509_BASIC_CONSTRAINTS
):
4519 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4521 case LOWORD(X509_BASIC_CONSTRAINTS2
):
4522 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4524 case LOWORD(X509_CERT_POLICIES
):
4525 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4527 case LOWORD(RSA_CSP_PUBLICKEYBLOB
):
4528 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
4530 case LOWORD(X509_UNICODE_NAME
):
4531 encodeFunc
= CRYPT_AsnEncodeUnicodeName
;
4533 case LOWORD(PKCS_CONTENT_INFO
):
4534 encodeFunc
= CRYPT_AsnEncodePKCSContentInfo
;
4536 case LOWORD(PKCS_ATTRIBUTE
):
4537 encodeFunc
= CRYPT_AsnEncodePKCSAttribute
;
4539 case LOWORD(X509_UNICODE_NAME_VALUE
):
4540 encodeFunc
= CRYPT_AsnEncodeUnicodeNameValue
;
4542 case LOWORD(X509_OCTET_STRING
):
4543 encodeFunc
= CRYPT_AsnEncodeOctets
;
4545 case LOWORD(X509_BITS
):
4546 case LOWORD(X509_KEY_USAGE
):
4547 encodeFunc
= CRYPT_AsnEncodeBits
;
4549 case LOWORD(X509_INTEGER
):
4550 encodeFunc
= CRYPT_AsnEncodeInt
;
4552 case LOWORD(X509_MULTI_BYTE_INTEGER
):
4553 encodeFunc
= CRYPT_AsnEncodeInteger
;
4555 case LOWORD(X509_MULTI_BYTE_UINT
):
4556 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
4558 case LOWORD(X509_ENUMERATED
):
4559 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4561 case LOWORD(X509_CHOICE_OF_TIME
):
4562 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
4564 case LOWORD(X509_AUTHORITY_KEY_ID2
):
4565 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4567 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
4568 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4570 case LOWORD(X509_SEQUENCE_OF_ANY
):
4571 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
4573 case LOWORD(PKCS_UTC_TIME
):
4574 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4576 case LOWORD(X509_CRL_DIST_POINTS
):
4577 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4579 case LOWORD(X509_ENHANCED_KEY_USAGE
):
4580 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4582 case LOWORD(PKCS_CTL
):
4583 encodeFunc
= CRYPT_AsnEncodeCTL
;
4585 case LOWORD(PKCS_SMIME_CAPABILITIES
):
4586 encodeFunc
= CRYPT_AsnEncodeSMIMECapabilities
;
4588 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE
):
4589 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4591 case LOWORD(PKCS_ATTRIBUTES
):
4592 encodeFunc
= CRYPT_AsnEncodePKCSAttributes
;
4594 case LOWORD(X509_ISSUING_DIST_POINT
):
4595 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4597 case LOWORD(X509_NAME_CONSTRAINTS
):
4598 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4600 case LOWORD(X509_POLICY_MAPPINGS
):
4601 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4603 case LOWORD(X509_POLICY_CONSTRAINTS
):
4604 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4606 case LOWORD(PKCS7_SIGNER_INFO
):
4607 encodeFunc
= CRYPT_AsnEncodePKCSSignerInfo
;
4609 case LOWORD(CMS_SIGNER_INFO
):
4610 encodeFunc
= CRYPT_AsnEncodeCMSSignerInfo
;
4612 case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB
):
4613 encodeFunc
= CRYPT_AsnEncodeRsaPubKey_Bcrypt
;
4616 FIXME("Unimplemented encoder for lpszStructType OID %d\n", LOWORD(lpszStructType
));
4619 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4620 encodeFunc
= CRYPT_AsnEncodeExtensions
;
4621 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4622 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4623 else if (!strcmp(lpszStructType
, szOID_RSA_SMIMECapabilities
))
4624 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
4625 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4626 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId
;
4627 else if (!strcmp(lpszStructType
, szOID_LEGACY_POLICY_MAPPINGS
))
4628 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4629 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4630 encodeFunc
= CRYPT_AsnEncodeAuthorityKeyId2
;
4631 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4632 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
4633 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4634 encodeFunc
= CRYPT_AsnEncodeBits
;
4635 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4636 encodeFunc
= CRYPT_AsnEncodeOctets
;
4637 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4638 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
4639 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4640 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
4641 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4642 encodeFunc
= CRYPT_AsnEncodeAltName
;
4643 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4644 encodeFunc
= CRYPT_AsnEncodeAltName
;
4645 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4646 encodeFunc
= CRYPT_AsnEncodeAltName
;
4647 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4648 encodeFunc
= CRYPT_AsnEncodeAltName
;
4649 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4650 encodeFunc
= CRYPT_AsnEncodeAltName
;
4651 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4652 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
4653 else if (!strcmp(lpszStructType
, szOID_CERT_POLICIES
))
4654 encodeFunc
= CRYPT_AsnEncodeCertPolicies
;
4655 else if (!strcmp(lpszStructType
, szOID_POLICY_MAPPINGS
))
4656 encodeFunc
= CRYPT_AsnEncodeCertPolicyMappings
;
4657 else if (!strcmp(lpszStructType
, szOID_POLICY_CONSTRAINTS
))
4658 encodeFunc
= CRYPT_AsnEncodeCertPolicyConstraints
;
4659 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4660 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
4661 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4662 encodeFunc
= CRYPT_AsnEncodeIssuingDistPoint
;
4663 else if (!strcmp(lpszStructType
, szOID_NAME_CONSTRAINTS
))
4664 encodeFunc
= CRYPT_AsnEncodeNameConstraints
;
4665 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
4666 encodeFunc
= CRYPT_AsnEncodeAuthorityInfoAccess
;
4667 else if (!strcmp(lpszStructType
, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
4668 encodeFunc
= CRYPT_AsnEncodePolicyQualifierUserNotice
;
4669 else if (!strcmp(lpszStructType
, szOID_CTL
))
4670 encodeFunc
= CRYPT_AsnEncodeCTL
;
4672 FIXME("Unsupported encoder for lpszStructType %s\n", lpszStructType
);
4676 static CryptEncodeObjectFunc
CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType
,
4677 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4679 static HCRYPTOIDFUNCSET set
= NULL
;
4680 CryptEncodeObjectFunc encodeFunc
= NULL
;
4683 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
4684 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4685 (void **)&encodeFunc
, hFunc
);
4689 static CryptEncodeObjectExFunc
CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType
,
4690 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4692 static HCRYPTOIDFUNCSET set
= NULL
;
4693 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4696 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
4697 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4698 (void **)&encodeFunc
, hFunc
);
4702 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4703 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
4706 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4707 CryptEncodeObjectFunc pCryptEncodeObject
= NULL
;
4708 CryptEncodeObjectExFunc pCryptEncodeObjectEx
= NULL
;
4710 TRACE_(crypt
)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
4711 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
4714 if (!pbEncoded
&& !pcbEncoded
)
4716 SetLastError(ERROR_INVALID_PARAMETER
);
4720 if (!(pCryptEncodeObjectEx
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
,
4723 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4724 debugstr_a(lpszStructType
));
4725 pCryptEncodeObject
= CRYPT_LoadEncoderFunc(dwCertEncodingType
,
4726 lpszStructType
, &hFunc
);
4727 if (!pCryptEncodeObject
)
4728 pCryptEncodeObjectEx
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
,
4729 lpszStructType
, &hFunc
);
4731 if (pCryptEncodeObject
)
4732 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4733 pvStructInfo
, pbEncoded
, pcbEncoded
);
4734 else if (pCryptEncodeObjectEx
)
4735 ret
= pCryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
4736 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
4738 CryptFreeOIDFunctionAddress(hFunc
, 0);
4739 TRACE_(crypt
)("returning %d\n", ret
);
4743 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4744 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
4745 void *pvEncoded
, DWORD
*pcbEncoded
)
4748 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4749 CryptEncodeObjectExFunc encodeFunc
= NULL
;
4751 TRACE_(crypt
)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType
,
4752 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
4753 pvEncoded
, pcbEncoded
);
4755 if (!pvEncoded
&& !pcbEncoded
)
4757 SetLastError(ERROR_INVALID_PARAMETER
);
4761 SetLastError(NOERROR
);
4762 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
) {
4764 SetLastError(ERROR_INVALID_PARAMETER
);
4767 *(BYTE
**)pvEncoded
= NULL
;
4769 encodeFunc
= CRYPT_GetBuiltinEncoder(dwCertEncodingType
, lpszStructType
);
4772 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4773 debugstr_a(lpszStructType
));
4774 encodeFunc
= CRYPT_LoadEncoderExFunc(dwCertEncodingType
, lpszStructType
,
4778 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
4779 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
4782 CryptEncodeObjectFunc pCryptEncodeObject
=
4783 CRYPT_LoadEncoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4785 if (pCryptEncodeObject
)
4787 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
4789 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4790 pvStructInfo
, NULL
, pcbEncoded
);
4791 if (ret
&& (ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
4792 pvEncoded
, pcbEncoded
, *pcbEncoded
)))
4793 ret
= pCryptEncodeObject(dwCertEncodingType
,
4794 lpszStructType
, pvStructInfo
, *(BYTE
**)pvEncoded
,
4798 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
4799 pvStructInfo
, pvEncoded
, pcbEncoded
);
4803 CryptFreeOIDFunctionAddress(hFunc
, 0);
4804 TRACE_(crypt
)("returning %d\n", ret
);
4808 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4809 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4811 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4812 NULL
, 0, NULL
, pInfo
, pcbInfo
);
4815 typedef BOOL (WINAPI
*EncodePublicKeyAndParametersFunc
)(DWORD dwCertEncodingType
,
4816 LPSTR pszPublicKeyObjId
, BYTE
*pbPubKey
, DWORD cbPubKey
, DWORD dwFlags
, void *pvAuxInfo
,
4817 BYTE
**ppPublicKey
, DWORD
*pcbPublicKey
, BYTE
**ppbParams
, DWORD
*pcbParams
);
4819 static BOOL WINAPI
CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4820 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4821 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4825 static CHAR rsa_oid
[] = szOID_RSA_RSA
;
4827 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4828 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4829 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4831 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
4835 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
4838 PUBLICKEYSTRUC
*pubKey
= CryptMemAlloc(keySize
);
4842 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, (BYTE
*)pubKey
, &keySize
);
4847 if (!pszPublicKeyObjId
)
4849 static HCRYPTOIDFUNCSET set
;
4850 EncodePublicKeyAndParametersFunc encodeFunc
= NULL
;
4851 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4853 pszPublicKeyObjId
= (LPSTR
)CertAlgIdToOID(pubKey
->aiKeyAlg
);
4854 TRACE("public key algid %#x (%s)\n", pubKey
->aiKeyAlg
, debugstr_a(pszPublicKeyObjId
));
4856 if (!set
) /* FIXME: there is no a public macro */
4857 set
= CryptInitOIDFunctionSet("CryptDllEncodePublicKeyAndParameters", 0);
4859 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
, 0, (void **)&encodeFunc
, &hFunc
);
4862 BYTE
*key_data
= NULL
;
4864 BYTE
*params
= NULL
;
4865 DWORD params_size
= 0;
4867 ret
= encodeFunc(dwCertEncodingType
, pszPublicKeyObjId
, (BYTE
*)pubKey
, keySize
,
4868 dwFlags
, pvAuxInfo
, &key_data
, &key_size
, ¶ms
, ¶ms_size
);
4871 DWORD oid_size
= strlen(pszPublicKeyObjId
) + 1;
4872 DWORD size_needed
= sizeof(*pInfo
) + oid_size
+ key_size
+ params_size
;
4875 *pcbInfo
= size_needed
;
4876 else if (*pcbInfo
< size_needed
)
4878 *pcbInfo
= size_needed
;
4879 SetLastError(ERROR_MORE_DATA
);
4884 *pcbInfo
= size_needed
;
4885 pInfo
->Algorithm
.pszObjId
= (char *)(pInfo
+ 1);
4886 lstrcpyA(pInfo
->Algorithm
.pszObjId
, pszPublicKeyObjId
);
4889 pInfo
->Algorithm
.Parameters
.cbData
= params_size
;
4890 pInfo
->Algorithm
.Parameters
.pbData
= (BYTE
*)pInfo
->Algorithm
.pszObjId
+ oid_size
;
4891 memcpy(pInfo
->Algorithm
.Parameters
.pbData
, params
, params_size
);
4895 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4896 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4898 pInfo
->PublicKey
.pbData
= (BYTE
*)pInfo
->Algorithm
.pszObjId
+ oid_size
+ params_size
;
4899 pInfo
->PublicKey
.cbData
= key_size
;
4900 memcpy(pInfo
->PublicKey
.pbData
, key_data
, key_size
);
4901 pInfo
->PublicKey
.cUnusedBits
= 0;
4904 CryptMemFree(key_data
);
4905 CryptMemFree(params
);
4908 CryptMemFree(pubKey
);
4909 CryptFreeOIDFunctionAddress(hFunc
, 0);
4913 /* fallback to RSA */
4914 pszPublicKeyObjId
= rsa_oid
;
4918 ret
= CryptEncodeObject(dwCertEncodingType
,
4919 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
4922 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
4923 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
4926 *pcbInfo
= sizeNeeded
;
4927 else if (*pcbInfo
< sizeNeeded
)
4929 SetLastError(ERROR_MORE_DATA
);
4930 *pcbInfo
= sizeNeeded
;
4935 *pcbInfo
= sizeNeeded
;
4936 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
4937 sizeof(CERT_PUBLIC_KEY_INFO
);
4938 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
4940 pInfo
->Algorithm
.Parameters
.cbData
= 0;
4941 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
4942 pInfo
->PublicKey
.pbData
=
4943 (BYTE
*)pInfo
->Algorithm
.pszObjId
4944 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
4945 pInfo
->PublicKey
.cbData
= encodedLen
;
4946 pInfo
->PublicKey
.cUnusedBits
= 0;
4947 ret
= CryptEncodeObject(dwCertEncodingType
,
4948 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
4949 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
4953 CryptMemFree(pubKey
);
4958 CryptDestroyKey(key
);
4963 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
,
4964 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
4965 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
4967 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv
, DWORD dwKeySpec
,
4968 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
4969 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
4971 static HCRYPTOIDFUNCSET set
= NULL
;
4973 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
4974 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4976 TRACE_(crypt
)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv
,
4977 dwKeySpec
, dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
,
4978 pvAuxInfo
, pInfo
, pInfo
? *pcbInfo
: 0);
4982 SetLastError(ERROR_INVALID_PARAMETER
);
4986 if (pszPublicKeyObjId
)
4989 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
4991 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
4992 0, (void **)&exportFunc
, &hFunc
);
4995 exportFunc
= CRYPT_ExportPublicKeyInfoEx
;
4996 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
4997 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
4999 CryptFreeOIDFunctionAddress(hFunc
, 0);
5003 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5004 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5006 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5010 typedef BOOL (WINAPI
*ConvertPublicKeyInfoFunc
)(DWORD dwCertEncodingType
,
5011 PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
, DWORD dwFlags
,
5012 BYTE
**ppbData
, DWORD
*dwDataLen
);
5014 static BOOL WINAPI
CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5015 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5016 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5018 static HCRYPTOIDFUNCSET set
= NULL
;
5019 ConvertPublicKeyInfoFunc convertFunc
= NULL
;
5020 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5025 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
5026 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5029 set
= CryptInitOIDFunctionSet(CRYPT_OID_CONVERT_PUBLIC_KEY_INFO_FUNC
, 0);
5030 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pInfo
->Algorithm
.pszObjId
,
5031 0, (void **)&convertFunc
, &hFunc
);
5036 ret
= convertFunc(dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, &pubKey
, &pubKeySize
);
5039 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0, phKey
);
5040 CryptMemFree(pubKey
);
5043 CryptFreeOIDFunctionAddress(hFunc
, 0);
5047 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5048 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5051 pubKey
= CryptMemAlloc(pubKeySize
);
5055 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5056 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5061 ((BLOBHEADER
*)pubKey
)->aiKeyAlg
= aiKeyAlg
;
5062 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5065 CryptMemFree(pubKey
);
5073 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5074 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5075 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5077 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5078 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5079 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5081 static HCRYPTOIDFUNCSET set
= NULL
;
5083 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5084 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5086 TRACE_(crypt
)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv
,
5087 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5090 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
5091 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
5092 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
5094 importFunc
= CRYPT_ImportPublicKeyInfoEx
;
5095 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
5098 CryptFreeOIDFunctionAddress(hFunc
, 0);
5102 BOOL WINAPI
CryptImportPublicKeyInfoEx2(DWORD dwCertEncodingType
,
5103 PCERT_PUBLIC_KEY_INFO pInfo
, DWORD dwFlags
, void *pvAuxInfo
,
5104 BCRYPT_KEY_HANDLE
*phKey
)
5106 TRACE_(crypt
)("(%d, %p, %08x, %p, %p)\n", dwCertEncodingType
, pInfo
,
5107 dwFlags
, pvAuxInfo
, phKey
);
5110 FIXME("flags %#x ignored\n", dwFlags
);
5112 return CNG_ImportPubKey(pInfo
, phKey
);