Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenencode.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2005-2008 Juan Lang 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 * 00018 * This file implements ASN.1 DER encoding of a limited set of types. 00019 * It isn't a full ASN.1 implementation. Microsoft implements BER 00020 * encoding of many of the basic types in msasn1.dll, but that interface isn't 00021 * implemented, so I implement them here. 00022 * 00023 * References: 00024 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski 00025 * (available online, look for a PDF copy as the HTML versions tend to have 00026 * translation errors.) 00027 * 00028 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html 00029 * 00030 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject" 00031 */ 00032 00033 #include "config.h" 00034 #include "wine/port.h" 00035 00036 #include <assert.h> 00037 #include <stdarg.h> 00038 #include <stdio.h> 00039 #include <stdlib.h> 00040 00041 #define NONAMELESSUNION 00042 00043 #include "windef.h" 00044 #include "winbase.h" 00045 #include "wincrypt.h" 00046 #include "snmp.h" 00047 #include "wine/debug.h" 00048 #include "wine/exception.h" 00049 #include "wine/unicode.h" 00050 #include "crypt32_private.h" 00051 00052 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn); 00053 WINE_DECLARE_DEBUG_CHANNEL(crypt); 00054 00055 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *, 00056 BYTE *, DWORD *); 00057 00058 /* Prototypes for built-in encoders. They follow the Ex style prototypes. 00059 * The dwCertEncodingType and lpszStructType are ignored by the built-in 00060 * functions, but the parameters are retained to simplify CryptEncodeObjectEx, 00061 * since it must call functions in external DLLs that follow these signatures. 00062 */ 00063 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType, 00064 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00065 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00066 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType, 00067 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00068 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00069 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, 00070 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00071 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00072 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, 00073 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00074 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00075 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType, 00076 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00077 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00078 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, 00079 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00080 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00081 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType, 00082 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00083 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00084 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, 00085 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00086 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00087 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, 00088 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00089 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00090 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, 00091 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00092 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00093 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, 00094 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00095 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00096 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType, 00097 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00098 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00099 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType, 00100 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00101 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 00102 00103 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, 00104 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded) 00105 { 00106 BOOL ret = TRUE; 00107 00108 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00109 { 00110 if (pEncodePara && pEncodePara->pfnAlloc) 00111 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded); 00112 else 00113 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded); 00114 if (!*(BYTE **)pbEncoded) 00115 ret = FALSE; 00116 else 00117 *pcbEncoded = bytesNeeded; 00118 } 00119 else if (bytesNeeded > *pcbEncoded) 00120 { 00121 *pcbEncoded = bytesNeeded; 00122 SetLastError(ERROR_MORE_DATA); 00123 ret = FALSE; 00124 } 00125 else 00126 *pcbEncoded = bytesNeeded; 00127 return ret; 00128 } 00129 00130 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv) 00131 { 00132 if (pEncodePara && pEncodePara->pfnFree) 00133 pEncodePara->pfnFree(pv); 00134 else 00135 LocalFree(pv); 00136 } 00137 00138 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded) 00139 { 00140 DWORD bytesNeeded, significantBytes = 0; 00141 00142 if (len <= 0x7f) 00143 bytesNeeded = 1; 00144 else 00145 { 00146 DWORD temp; 00147 00148 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000); 00149 temp <<= 8, significantBytes--) 00150 ; 00151 bytesNeeded = significantBytes + 1; 00152 } 00153 if (!pbEncoded) 00154 { 00155 *pcbEncoded = bytesNeeded; 00156 return TRUE; 00157 } 00158 if (*pcbEncoded < bytesNeeded) 00159 { 00160 SetLastError(ERROR_MORE_DATA); 00161 return FALSE; 00162 } 00163 if (len <= 0x7f) 00164 *pbEncoded = (BYTE)len; 00165 else 00166 { 00167 DWORD i; 00168 00169 *pbEncoded++ = significantBytes | 0x80; 00170 for (i = 0; i < significantBytes; i++) 00171 { 00172 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff); 00173 len >>= 8; 00174 } 00175 } 00176 *pcbEncoded = bytesNeeded; 00177 return TRUE; 00178 } 00179 00180 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType, 00181 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags, 00182 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00183 { 00184 BOOL ret; 00185 DWORD i, dataLen = 0; 00186 00187 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara, 00188 pbEncoded, pbEncoded ? *pcbEncoded : 0); 00189 for (i = 0, ret = TRUE; ret && i < cItem; i++) 00190 { 00191 ret = items[i].encodeFunc(dwCertEncodingType, NULL, 00192 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, 00193 NULL, &items[i].size); 00194 /* Some functions propagate their errors through the size */ 00195 if (!ret) 00196 *pcbEncoded = items[i].size; 00197 dataLen += items[i].size; 00198 } 00199 if (ret) 00200 { 00201 DWORD lenBytes, bytesNeeded; 00202 00203 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 00204 bytesNeeded = 1 + lenBytes + dataLen; 00205 if (!pbEncoded) 00206 *pcbEncoded = bytesNeeded; 00207 else 00208 { 00209 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 00210 pcbEncoded, bytesNeeded))) 00211 { 00212 BYTE *out; 00213 00214 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00215 pbEncoded = *(BYTE **)pbEncoded; 00216 out = pbEncoded; 00217 *out++ = ASN_SEQUENCE; 00218 CRYPT_EncodeLen(dataLen, out, &lenBytes); 00219 out += lenBytes; 00220 for (i = 0; ret && i < cItem; i++) 00221 { 00222 ret = items[i].encodeFunc(dwCertEncodingType, NULL, 00223 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, 00224 NULL, out, &items[i].size); 00225 /* Some functions propagate their errors through the size */ 00226 if (!ret) 00227 *pcbEncoded = items[i].size; 00228 out += items[i].size; 00229 } 00230 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 00231 CRYPT_FreeSpace(pEncodePara, pbEncoded); 00232 } 00233 } 00234 } 00235 TRACE("returning %d (%08x)\n", ret, GetLastError()); 00236 return ret; 00237 } 00238 00239 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType, 00240 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00241 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00242 { 00243 BOOL ret; 00244 const struct AsnConstructedItem *item = pvStructInfo; 00245 DWORD len; 00246 00247 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 00248 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len))) 00249 { 00250 DWORD dataLen, bytesNeeded; 00251 00252 CRYPT_EncodeLen(len, NULL, &dataLen); 00253 bytesNeeded = 1 + dataLen + len; 00254 if (!pbEncoded) 00255 *pcbEncoded = bytesNeeded; 00256 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 00257 pbEncoded, pcbEncoded, bytesNeeded))) 00258 { 00259 BYTE *out; 00260 00261 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00262 pbEncoded = *(BYTE **)pbEncoded; 00263 out = pbEncoded; 00264 *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag; 00265 CRYPT_EncodeLen(len, out, &dataLen); 00266 out += dataLen; 00267 ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 00268 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, 00269 out, &len); 00270 if (!ret) 00271 { 00272 /* Some functions propagate their errors through the size */ 00273 *pcbEncoded = len; 00274 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00275 CRYPT_FreeSpace(pEncodePara, pbEncoded); 00276 } 00277 } 00278 } 00279 else 00280 { 00281 /* Some functions propagate their errors through the size */ 00282 *pcbEncoded = len; 00283 } 00284 return ret; 00285 } 00286 00287 struct AsnEncodeTagSwappedItem 00288 { 00289 BYTE tag; 00290 const void *pvStructInfo; 00291 CryptEncodeObjectExFunc encodeFunc; 00292 }; 00293 00294 /* Sort of a wacky hack, it encodes something using the struct 00295 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag 00296 * given in the struct AsnEncodeTagSwappedItem. 00297 */ 00298 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType, 00299 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00300 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00301 { 00302 BOOL ret; 00303 const struct AsnEncodeTagSwappedItem *item = pvStructInfo; 00304 00305 ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 00306 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 00307 if (ret && pbEncoded) 00308 *pbEncoded = item->tag; 00309 return ret; 00310 } 00311 00312 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType, 00313 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00314 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00315 { 00316 const DWORD *ver = pvStructInfo; 00317 BOOL ret; 00318 00319 /* CERT_V1 is not encoded */ 00320 if (*ver == CERT_V1) 00321 { 00322 *pcbEncoded = 0; 00323 ret = TRUE; 00324 } 00325 else 00326 { 00327 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt }; 00328 00329 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER, 00330 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 00331 } 00332 return ret; 00333 } 00334 00335 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType, 00336 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00337 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00338 { 00339 const CRYPT_DER_BLOB *blob = pvStructInfo; 00340 BOOL ret; 00341 00342 if (!pbEncoded) 00343 { 00344 *pcbEncoded = blob->cbData; 00345 ret = TRUE; 00346 } 00347 else 00348 { 00349 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 00350 pcbEncoded, blob->cbData))) 00351 { 00352 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00353 pbEncoded = *(BYTE **)pbEncoded; 00354 if (blob->cbData) 00355 memcpy(pbEncoded, blob->pbData, blob->cbData); 00356 *pcbEncoded = blob->cbData; 00357 } 00358 } 00359 return ret; 00360 } 00361 00362 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType, 00363 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00364 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00365 { 00366 BOOL ret; 00367 /* This has two filetimes in a row, a NotBefore and a NotAfter */ 00368 const FILETIME *timePtr = pvStructInfo; 00369 struct AsnEncodeSequenceItem items[] = { 00370 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 }, 00371 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 }, 00372 }; 00373 00374 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 00375 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 00376 pcbEncoded); 00377 return ret; 00378 } 00379 00380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL 00381 * if they are empty. 00382 */ 00383 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams( 00384 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 00385 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 00386 DWORD *pcbEncoded) 00387 { 00388 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 00389 static const BYTE asn1Null[] = { ASN_NULL, 0 }; 00390 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null), 00391 (LPBYTE)asn1Null }; 00392 BOOL ret; 00393 struct AsnEncodeSequenceItem items[2] = { 00394 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, 00395 { NULL, CRYPT_CopyEncodedBlob, 0 }, 00396 }; 00397 00398 if (algo->Parameters.cbData) 00399 items[1].pvStructInfo = &algo->Parameters; 00400 else 00401 items[1].pvStructInfo = &nullBlob; 00402 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 00403 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 00404 pcbEncoded); 00405 return ret; 00406 } 00407 00408 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType, 00409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00411 { 00412 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 00413 BOOL ret; 00414 struct AsnEncodeSequenceItem items[] = { 00415 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, 00416 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 }, 00417 }; 00418 00419 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 00420 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 00421 pcbEncoded); 00422 return ret; 00423 } 00424 00425 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType, 00426 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00427 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00428 { 00429 BOOL ret; 00430 00431 __TRY 00432 { 00433 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo; 00434 struct AsnEncodeSequenceItem items[] = { 00435 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 00436 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 }, 00437 }; 00438 00439 TRACE("Encoding public key with OID %s\n", 00440 debugstr_a(info->Algorithm.pszObjId)); 00441 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 00442 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 00443 pcbEncoded); 00444 } 00445 __EXCEPT_PAGE_FAULT 00446 { 00447 SetLastError(STATUS_ACCESS_VIOLATION); 00448 ret = FALSE; 00449 } 00450 __ENDTRY 00451 return ret; 00452 } 00453 00454 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType, 00455 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00456 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00457 { 00458 BOOL ret; 00459 00460 __TRY 00461 { 00462 const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo; 00463 struct AsnEncodeSequenceItem items[] = { 00464 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 }, 00465 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 00466 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 }, 00467 }; 00468 00469 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG) 00470 items[2].encodeFunc = CRYPT_AsnEncodeBits; 00471 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 00472 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 00473 pcbEncoded); 00474 } 00475 __EXCEPT_PAGE_FAULT 00476 { 00477 SetLastError(STATUS_ACCESS_VIOLATION); 00478 ret = FALSE; 00479 } 00480 __ENDTRY 00481 return ret; 00482 } 00483 00484 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType, 00485 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00486 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00487 { 00488 BOOL ret; 00489 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo; 00490 struct AsnEncodeSequenceItem items[] = { 00491 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 00492 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 }, 00493 }; 00494 00495 TRACE("Encoding public key with OID %s\n", 00496 debugstr_a(info->Algorithm.pszObjId)); 00497 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 00498 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 00499 pcbEncoded); 00500 return ret; 00501 } 00502 00503 /* Like in Windows, this blithely ignores the validity of the passed-in 00504 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not 00505 * decode properly, see CRYPT_AsnDecodeCertInfo. 00506 */ 00507 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType, 00508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00510 { 00511 BOOL ret; 00512 00513 __TRY 00514 { 00515 const CERT_INFO *info = pvStructInfo; 00516 struct AsnEncodeSequenceItem items[10] = { 00517 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 }, 00518 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, 00519 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 00520 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 }, 00521 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 }, 00522 { &info->Subject, CRYPT_CopyEncodedBlob, 0 }, 00523 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 }, 00524 { 0 } 00525 }; 00526 struct AsnConstructedItem constructed = { 0 }; 00527 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 00528 DWORD cItem = 7, cSwapped = 0; 00529 00530 if (info->IssuerUniqueId.cbData) 00531 { 00532 swapped[cSwapped].tag = ASN_CONTEXT | 1; 00533 swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId; 00534 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 00535 items[cItem].pvStructInfo = &swapped[cSwapped]; 00536 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 00537 cSwapped++; 00538 cItem++; 00539 } 00540 if (info->SubjectUniqueId.cbData) 00541 { 00542 swapped[cSwapped].tag = ASN_CONTEXT | 2; 00543 swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId; 00544 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 00545 items[cItem].pvStructInfo = &swapped[cSwapped]; 00546 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 00547 cSwapped++; 00548 cItem++; 00549 } 00550 if (info->cExtension) 00551 { 00552 constructed.tag = 3; 00553 constructed.pvStructInfo = &info->cExtension; 00554 constructed.encodeFunc = CRYPT_AsnEncodeExtensions; 00555 items[cItem].pvStructInfo = &constructed; 00556 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 00557 cItem++; 00558 } 00559 00560 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 00561 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 00562 } 00563 __EXCEPT_PAGE_FAULT 00564 { 00565 SetLastError(STATUS_ACCESS_VIOLATION); 00566 ret = FALSE; 00567 } 00568 __ENDTRY 00569 return ret; 00570 } 00571 00572 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry, 00573 BYTE *pbEncoded, DWORD *pcbEncoded) 00574 { 00575 struct AsnEncodeSequenceItem items[3] = { 00576 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, 00577 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 }, 00578 { 0 } 00579 }; 00580 DWORD cItem = 2; 00581 BOOL ret; 00582 00583 TRACE("%p, %p, %d\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0); 00584 00585 if (entry->cExtension) 00586 { 00587 items[cItem].pvStructInfo = &entry->cExtension; 00588 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions; 00589 cItem++; 00590 } 00591 00592 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, 00593 pbEncoded, pcbEncoded); 00594 00595 TRACE("returning %d (%08x)\n", ret, GetLastError()); 00596 return ret; 00597 } 00598 00599 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType, 00600 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00601 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00602 { 00603 DWORD bytesNeeded, dataLen, lenBytes, i; 00604 const CRL_INFO *info = pvStructInfo; 00605 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry; 00606 BOOL ret = TRUE; 00607 00608 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++) 00609 { 00610 DWORD size; 00611 00612 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size); 00613 if (ret) 00614 dataLen += size; 00615 } 00616 if (ret) 00617 { 00618 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 00619 bytesNeeded = 1 + lenBytes + dataLen; 00620 if (!pbEncoded) 00621 *pcbEncoded = bytesNeeded; 00622 else 00623 { 00624 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 00625 pcbEncoded, bytesNeeded))) 00626 { 00627 BYTE *out; 00628 00629 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00630 pbEncoded = *(BYTE **)pbEncoded; 00631 out = pbEncoded; 00632 *out++ = ASN_SEQUENCEOF; 00633 CRYPT_EncodeLen(dataLen, out, &lenBytes); 00634 out += lenBytes; 00635 for (i = 0; i < info->cCRLEntry; i++) 00636 { 00637 DWORD size = dataLen; 00638 00639 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size); 00640 out += size; 00641 dataLen -= size; 00642 } 00643 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 00644 CRYPT_FreeSpace(pEncodePara, pbEncoded); 00645 } 00646 } 00647 } 00648 return ret; 00649 } 00650 00651 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType, 00652 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00653 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00654 { 00655 const DWORD *ver = pvStructInfo; 00656 BOOL ret; 00657 00658 /* CRL_V1 is not encoded */ 00659 if (*ver == CRL_V1) 00660 { 00661 *pcbEncoded = 0; 00662 ret = TRUE; 00663 } 00664 else 00665 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver, 00666 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 00667 return ret; 00668 } 00669 00670 /* Like in Windows, this blithely ignores the validity of the passed-in 00671 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not 00672 * decode properly, see CRYPT_AsnDecodeCRLInfo. 00673 */ 00674 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType, 00675 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00676 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00677 { 00678 BOOL ret; 00679 00680 __TRY 00681 { 00682 const CRL_INFO *info = pvStructInfo; 00683 struct AsnEncodeSequenceItem items[7] = { 00684 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 }, 00685 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 00686 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 }, 00687 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 }, 00688 { 0 } 00689 }; 00690 struct AsnConstructedItem constructed[1] = { { 0 } }; 00691 DWORD cItem = 4, cConstructed = 0; 00692 00693 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime) 00694 { 00695 items[cItem].pvStructInfo = &info->NextUpdate; 00696 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 00697 cItem++; 00698 } 00699 if (info->cCRLEntry) 00700 { 00701 items[cItem].pvStructInfo = info; 00702 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries; 00703 cItem++; 00704 } 00705 if (info->cExtension) 00706 { 00707 constructed[cConstructed].tag = 0; 00708 constructed[cConstructed].pvStructInfo = &info->cExtension; 00709 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions; 00710 items[cItem].pvStructInfo = &constructed[cConstructed]; 00711 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 00712 cConstructed++; 00713 cItem++; 00714 } 00715 00716 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 00717 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 00718 } 00719 __EXCEPT_PAGE_FAULT 00720 { 00721 SetLastError(STATUS_ACCESS_VIOLATION); 00722 ret = FALSE; 00723 } 00724 __ENDTRY 00725 return ret; 00726 } 00727 00728 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded, 00729 DWORD *pcbEncoded) 00730 { 00731 BOOL ret; 00732 struct AsnEncodeSequenceItem items[3] = { 00733 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 }, 00734 { NULL, NULL, 0 }, 00735 { NULL, NULL, 0 }, 00736 }; 00737 DWORD cItem = 1; 00738 00739 TRACE("%p, %p, %d\n", ext, pbEncoded, pbEncoded ? *pcbEncoded : 0); 00740 00741 if (ext->fCritical) 00742 { 00743 items[cItem].pvStructInfo = &ext->fCritical; 00744 items[cItem].encodeFunc = CRYPT_AsnEncodeBool; 00745 cItem++; 00746 } 00747 items[cItem].pvStructInfo = &ext->Value; 00748 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 00749 cItem++; 00750 00751 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, 00752 pbEncoded, pcbEncoded); 00753 TRACE("returning %d (%08x)\n", ret, GetLastError()); 00754 return ret; 00755 } 00756 00757 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType, 00758 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00759 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00760 { 00761 BOOL ret; 00762 00763 __TRY 00764 { 00765 DWORD bytesNeeded, dataLen, lenBytes, i; 00766 const CERT_EXTENSIONS *exts = pvStructInfo; 00767 00768 ret = TRUE; 00769 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++) 00770 { 00771 DWORD size; 00772 00773 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size); 00774 if (ret) 00775 dataLen += size; 00776 } 00777 if (ret) 00778 { 00779 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 00780 bytesNeeded = 1 + lenBytes + dataLen; 00781 if (!pbEncoded) 00782 *pcbEncoded = bytesNeeded; 00783 else 00784 { 00785 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 00786 pbEncoded, pcbEncoded, bytesNeeded))) 00787 { 00788 BYTE *out; 00789 00790 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00791 pbEncoded = *(BYTE **)pbEncoded; 00792 out = pbEncoded; 00793 *out++ = ASN_SEQUENCEOF; 00794 CRYPT_EncodeLen(dataLen, out, &lenBytes); 00795 out += lenBytes; 00796 for (i = 0; i < exts->cExtension; i++) 00797 { 00798 DWORD size = dataLen; 00799 00800 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], 00801 out, &size); 00802 out += size; 00803 dataLen -= size; 00804 } 00805 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 00806 CRYPT_FreeSpace(pEncodePara, pbEncoded); 00807 } 00808 } 00809 } 00810 } 00811 __EXCEPT_PAGE_FAULT 00812 { 00813 SetLastError(STATUS_ACCESS_VIOLATION); 00814 ret = FALSE; 00815 } 00816 __ENDTRY 00817 return ret; 00818 } 00819 00820 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType, 00821 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 00822 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 00823 { 00824 LPCSTR pszObjId = pvStructInfo; 00825 DWORD bytesNeeded = 0, lenBytes; 00826 BOOL ret = TRUE; 00827 int firstPos = 0; 00828 BYTE firstByte = 0; 00829 00830 TRACE("%s\n", debugstr_a(pszObjId)); 00831 00832 if (pszObjId) 00833 { 00834 const char *ptr; 00835 int val1, val2; 00836 00837 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2) 00838 { 00839 SetLastError(CRYPT_E_ASN1_ERROR); 00840 return FALSE; 00841 } 00842 bytesNeeded++; 00843 firstByte = val1 * 40 + val2; 00844 ptr = pszObjId + firstPos; 00845 if (*ptr == '.') 00846 { 00847 ptr++; 00848 firstPos++; 00849 } 00850 while (ret && *ptr) 00851 { 00852 int pos; 00853 00854 /* note I assume each component is at most 32-bits long in base 2 */ 00855 if (sscanf(ptr, "%d%n", &val1, &pos) == 1) 00856 { 00857 if (val1 >= 0x10000000) 00858 bytesNeeded += 5; 00859 else if (val1 >= 0x200000) 00860 bytesNeeded += 4; 00861 else if (val1 >= 0x4000) 00862 bytesNeeded += 3; 00863 else if (val1 >= 0x80) 00864 bytesNeeded += 2; 00865 else 00866 bytesNeeded += 1; 00867 ptr += pos; 00868 if (*ptr == '.') 00869 ptr++; 00870 } 00871 else 00872 { 00873 SetLastError(CRYPT_E_ASN1_ERROR); 00874 return FALSE; 00875 } 00876 } 00877 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 00878 } 00879 else 00880 lenBytes = 1; 00881 bytesNeeded += 1 + lenBytes; 00882 if (pbEncoded) 00883 { 00884 if (*pcbEncoded < bytesNeeded) 00885 { 00886 SetLastError(ERROR_MORE_DATA); 00887 ret = FALSE; 00888 } 00889 else 00890 { 00891 *pbEncoded++ = ASN_OBJECTIDENTIFIER; 00892 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes); 00893 pbEncoded += lenBytes; 00894 if (pszObjId) 00895 { 00896 const char *ptr; 00897 int val, pos; 00898 00899 *pbEncoded++ = firstByte; 00900 ptr = pszObjId + firstPos; 00901 while (ret && *ptr) 00902 { 00903 sscanf(ptr, "%d%n", &val, &pos); 00904 { 00905 unsigned char outBytes[5]; 00906 int numBytes, i; 00907 00908 if (val >= 0x10000000) 00909 numBytes = 5; 00910 else if (val >= 0x200000) 00911 numBytes = 4; 00912 else if (val >= 0x4000) 00913 numBytes = 3; 00914 else if (val >= 0x80) 00915 numBytes = 2; 00916 else 00917 numBytes = 1; 00918 for (i = numBytes; i > 0; i--) 00919 { 00920 outBytes[i - 1] = val & 0x7f; 00921 val >>= 7; 00922 } 00923 for (i = 0; i < numBytes - 1; i++) 00924 *pbEncoded++ = outBytes[i] | 0x80; 00925 *pbEncoded++ = outBytes[i]; 00926 ptr += pos; 00927 if (*ptr == '.') 00928 ptr++; 00929 } 00930 } 00931 } 00932 } 00933 } 00934 *pcbEncoded = bytesNeeded; 00935 return ret; 00936 } 00937 00938 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value, 00939 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 00940 DWORD *pcbEncoded) 00941 { 00942 BOOL ret = TRUE; 00943 LPCSTR str = (LPCSTR)value->Value.pbData; 00944 DWORD bytesNeeded, lenBytes, encodedLen; 00945 00946 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str); 00947 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 00948 bytesNeeded = 1 + lenBytes + encodedLen; 00949 if (!pbEncoded) 00950 *pcbEncoded = bytesNeeded; 00951 else 00952 { 00953 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 00954 pbEncoded, pcbEncoded, bytesNeeded))) 00955 { 00956 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00957 pbEncoded = *(BYTE **)pbEncoded; 00958 *pbEncoded++ = tag; 00959 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); 00960 pbEncoded += lenBytes; 00961 memcpy(pbEncoded, str, encodedLen); 00962 } 00963 } 00964 return ret; 00965 } 00966 00967 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value, 00968 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 00969 DWORD *pcbEncoded) 00970 { 00971 BOOL ret = TRUE; 00972 LPCWSTR str = (LPCWSTR)value->Value.pbData; 00973 DWORD bytesNeeded, lenBytes, strLen; 00974 00975 if (value->Value.cbData) 00976 strLen = value->Value.cbData / sizeof(WCHAR); 00977 else if (value->Value.pbData) 00978 strLen = lstrlenW(str); 00979 else 00980 strLen = 0; 00981 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes); 00982 bytesNeeded = 1 + lenBytes + strLen * 2; 00983 if (!pbEncoded) 00984 *pcbEncoded = bytesNeeded; 00985 else 00986 { 00987 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 00988 pbEncoded, pcbEncoded, bytesNeeded))) 00989 { 00990 DWORD i; 00991 00992 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 00993 pbEncoded = *(BYTE **)pbEncoded; 00994 *pbEncoded++ = ASN_BMPSTRING; 00995 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes); 00996 pbEncoded += lenBytes; 00997 for (i = 0; i < strLen; i++) 00998 { 00999 *pbEncoded++ = (str[i] & 0xff00) >> 8; 01000 *pbEncoded++ = str[i] & 0x00ff; 01001 } 01002 } 01003 } 01004 return ret; 01005 } 01006 01007 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value, 01008 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 01009 DWORD *pcbEncoded) 01010 { 01011 BOOL ret = TRUE; 01012 LPCWSTR str = (LPCWSTR)value->Value.pbData; 01013 DWORD bytesNeeded, lenBytes, encodedLen, strLen; 01014 01015 if (value->Value.cbData) 01016 strLen = value->Value.cbData / sizeof(WCHAR); 01017 else if (str) 01018 strLen = strlenW(str); 01019 else 01020 strLen = 0; 01021 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL, 01022 NULL); 01023 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 01024 bytesNeeded = 1 + lenBytes + encodedLen; 01025 if (!pbEncoded) 01026 *pcbEncoded = bytesNeeded; 01027 else 01028 { 01029 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 01030 pbEncoded, pcbEncoded, bytesNeeded))) 01031 { 01032 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 01033 pbEncoded = *(BYTE **)pbEncoded; 01034 *pbEncoded++ = ASN_UTF8STRING; 01035 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); 01036 pbEncoded += lenBytes; 01037 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded, 01038 bytesNeeded - lenBytes - 1, NULL, NULL); 01039 } 01040 } 01041 return ret; 01042 } 01043 01044 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType, 01045 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01046 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01047 { 01048 BOOL ret = TRUE; 01049 01050 __TRY 01051 { 01052 const CERT_NAME_VALUE *value = pvStructInfo; 01053 01054 switch (value->dwValueType) 01055 { 01056 case CERT_RDN_ANY_TYPE: 01057 /* explicitly disallowed */ 01058 SetLastError(E_INVALIDARG); 01059 ret = FALSE; 01060 break; 01061 case CERT_RDN_ENCODED_BLOB: 01062 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, 01063 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01064 break; 01065 case CERT_RDN_OCTET_STRING: 01066 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING, 01067 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01068 break; 01069 case CERT_RDN_NUMERIC_STRING: 01070 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING, 01071 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01072 break; 01073 case CERT_RDN_PRINTABLE_STRING: 01074 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING, 01075 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01076 break; 01077 case CERT_RDN_TELETEX_STRING: 01078 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING, 01079 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01080 break; 01081 case CERT_RDN_VIDEOTEX_STRING: 01082 ret = CRYPT_AsnEncodeStringCoerce(value, 01083 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01084 break; 01085 case CERT_RDN_IA5_STRING: 01086 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING, 01087 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01088 break; 01089 case CERT_RDN_GRAPHIC_STRING: 01090 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING, 01091 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01092 break; 01093 case CERT_RDN_VISIBLE_STRING: 01094 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING, 01095 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01096 break; 01097 case CERT_RDN_GENERAL_STRING: 01098 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING, 01099 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01100 break; 01101 case CERT_RDN_UNIVERSAL_STRING: 01102 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n"); 01103 SetLastError(CRYPT_E_ASN1_CHOICE); 01104 ret = FALSE; 01105 break; 01106 case CERT_RDN_BMP_STRING: 01107 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara, 01108 pbEncoded, pcbEncoded); 01109 break; 01110 case CERT_RDN_UTF8_STRING: 01111 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara, 01112 pbEncoded, pcbEncoded); 01113 break; 01114 default: 01115 SetLastError(CRYPT_E_ASN1_CHOICE); 01116 ret = FALSE; 01117 } 01118 } 01119 __EXCEPT_PAGE_FAULT 01120 { 01121 SetLastError(STATUS_ACCESS_VIOLATION); 01122 ret = FALSE; 01123 } 01124 __ENDTRY 01125 return ret; 01126 } 01127 01128 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType, 01129 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc, 01130 BYTE *pbEncoded, DWORD *pcbEncoded) 01131 { 01132 DWORD bytesNeeded = 0, lenBytes, size; 01133 BOOL ret; 01134 01135 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId, 01136 0, NULL, NULL, &size); 01137 if (ret) 01138 { 01139 bytesNeeded += size; 01140 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning 01141 * with dwValueType, so "cast" it to get its encoded size 01142 */ 01143 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType, 01144 0, NULL, NULL, &size); 01145 if (ret) 01146 { 01147 bytesNeeded += size; 01148 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 01149 bytesNeeded += 1 + lenBytes; 01150 if (pbEncoded) 01151 { 01152 if (*pcbEncoded < bytesNeeded) 01153 { 01154 SetLastError(ERROR_MORE_DATA); 01155 ret = FALSE; 01156 } 01157 else 01158 { 01159 *pbEncoded++ = ASN_SEQUENCE; 01160 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, 01161 &lenBytes); 01162 pbEncoded += lenBytes; 01163 size = bytesNeeded - 1 - lenBytes; 01164 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 01165 attr->pszObjId, 0, NULL, pbEncoded, &size); 01166 if (ret) 01167 { 01168 pbEncoded += size; 01169 size = bytesNeeded - 1 - lenBytes - size; 01170 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, 01171 &attr->dwValueType, 0, NULL, pbEncoded, &size); 01172 if (!ret) 01173 *pcbEncoded = size; 01174 } 01175 } 01176 } 01177 if (ret) 01178 *pcbEncoded = bytesNeeded; 01179 } 01180 else 01181 { 01182 /* Have to propagate index of failing character */ 01183 *pcbEncoded = size; 01184 } 01185 } 01186 return ret; 01187 } 01188 01189 static int BLOBComp(const void *l, const void *r) 01190 { 01191 const CRYPT_DER_BLOB *a = l, *b = r; 01192 int ret; 01193 01194 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData)))) 01195 ret = a->cbData - b->cbData; 01196 return ret; 01197 } 01198 01199 /* This encodes a SET OF, which in DER must be lexicographically sorted. 01200 */ 01201 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType, 01202 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01204 { 01205 const CRYPT_BLOB_ARRAY *set = pvStructInfo; 01206 DWORD bytesNeeded = 0, lenBytes, i; 01207 BOOL ret; 01208 01209 for (i = 0; i < set->cBlob; i++) 01210 bytesNeeded += set->rgBlob[i].cbData; 01211 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 01212 bytesNeeded += 1 + lenBytes; 01213 if (!pbEncoded) 01214 { 01215 *pcbEncoded = bytesNeeded; 01216 ret = TRUE; 01217 } 01218 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 01219 pbEncoded, pcbEncoded, bytesNeeded))) 01220 { 01221 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 01222 pbEncoded = *(BYTE **)pbEncoded; 01223 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp); 01224 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF; 01225 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes); 01226 pbEncoded += lenBytes; 01227 for (i = 0; i < set->cBlob; i++) 01228 { 01229 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData); 01230 pbEncoded += set->rgBlob[i].cbData; 01231 } 01232 } 01233 return ret; 01234 } 01235 01236 struct DERSetDescriptor 01237 { 01238 DWORD cItems; 01239 const void *items; 01240 size_t itemSize; 01241 size_t itemOffset; 01242 CryptEncodeObjectExFunc encode; 01243 }; 01244 01245 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType, 01246 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01247 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01248 { 01249 const struct DERSetDescriptor *desc = pvStructInfo; 01250 CRYPT_BLOB_ARRAY setOf = { 0, NULL }; 01251 BOOL ret = TRUE; 01252 DWORD i; 01253 01254 if (desc->cItems) 01255 { 01256 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB)); 01257 if (!setOf.rgBlob) 01258 ret = FALSE; 01259 else 01260 { 01261 setOf.cBlob = desc->cItems; 01262 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB)); 01263 } 01264 } 01265 for (i = 0; ret && i < setOf.cBlob; i++) 01266 { 01267 ret = desc->encode(dwCertEncodingType, lpszStructType, 01268 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset, 01269 0, NULL, NULL, &setOf.rgBlob[i].cbData); 01270 if (ret) 01271 { 01272 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData); 01273 if (!setOf.rgBlob[i].pbData) 01274 ret = FALSE; 01275 else 01276 ret = desc->encode(dwCertEncodingType, lpszStructType, 01277 (const BYTE *)desc->items + i * desc->itemSize + 01278 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData, 01279 &setOf.rgBlob[i].cbData); 01280 } 01281 /* Some functions propagate their errors through the size */ 01282 if (!ret) 01283 *pcbEncoded = setOf.rgBlob[i].cbData; 01284 } 01285 if (ret) 01286 { 01287 DWORD bytesNeeded = 0, lenBytes; 01288 01289 for (i = 0; i < setOf.cBlob; i++) 01290 bytesNeeded += setOf.rgBlob[i].cbData; 01291 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 01292 bytesNeeded += 1 + lenBytes; 01293 if (!pbEncoded) 01294 *pcbEncoded = bytesNeeded; 01295 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 01296 pbEncoded, pcbEncoded, bytesNeeded))) 01297 { 01298 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 01299 pbEncoded = *(BYTE **)pbEncoded; 01300 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB), 01301 BLOBComp); 01302 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF; 01303 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes); 01304 pbEncoded += lenBytes; 01305 for (i = 0; i < setOf.cBlob; i++) 01306 { 01307 memcpy(pbEncoded, setOf.rgBlob[i].pbData, 01308 setOf.rgBlob[i].cbData); 01309 pbEncoded += setOf.rgBlob[i].cbData; 01310 } 01311 } 01312 } 01313 for (i = 0; i < setOf.cBlob; i++) 01314 CryptMemFree(setOf.rgBlob[i].pbData); 01315 CryptMemFree(setOf.rgBlob); 01316 return ret; 01317 } 01318 01319 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn, 01320 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded, 01321 DWORD *pcbEncoded) 01322 { 01323 BOOL ret; 01324 CRYPT_BLOB_ARRAY setOf = { 0, NULL }; 01325 01326 __TRY 01327 { 01328 DWORD i; 01329 01330 ret = TRUE; 01331 if (rdn->cRDNAttr) 01332 { 01333 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr * 01334 sizeof(CRYPT_DER_BLOB)); 01335 if (!setOf.rgBlob) 01336 ret = FALSE; 01337 else 01338 { 01339 setOf.cBlob = rdn->cRDNAttr; 01340 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB)); 01341 } 01342 } 01343 for (i = 0; ret && i < rdn->cRDNAttr; i++) 01344 { 01345 setOf.rgBlob[i].cbData = 0; 01346 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i], 01347 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData); 01348 if (ret) 01349 { 01350 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData); 01351 if (!setOf.rgBlob[i].pbData) 01352 ret = FALSE; 01353 else 01354 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, 01355 &rdn->rgRDNAttr[i], nameValueEncodeFunc, 01356 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData); 01357 } 01358 if (!ret) 01359 { 01360 /* Have to propagate index of failing character */ 01361 *pcbEncoded = setOf.rgBlob[i].cbData; 01362 } 01363 } 01364 if (ret) 01365 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL, 01366 pbEncoded, pcbEncoded); 01367 for (i = 0; i < setOf.cBlob; i++) 01368 CryptMemFree(setOf.rgBlob[i].pbData); 01369 } 01370 __EXCEPT_PAGE_FAULT 01371 { 01372 SetLastError(STATUS_ACCESS_VIOLATION); 01373 ret = FALSE; 01374 } 01375 __ENDTRY 01376 CryptMemFree(setOf.rgBlob); 01377 return ret; 01378 } 01379 01380 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType, 01381 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01382 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 01383 01384 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue( 01385 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 01386 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 01387 DWORD *pcbEncoded) 01388 { 01389 const CERT_NAME_VALUE *value = pvStructInfo; 01390 BOOL ret; 01391 01392 if (value->dwValueType == CERT_RDN_ENCODED_BLOB) 01393 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value, 01394 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01395 else 01396 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value, 01397 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01398 return ret; 01399 } 01400 01401 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType, 01402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01404 { 01405 BOOL ret = TRUE; 01406 01407 __TRY 01408 { 01409 const CERT_NAME_INFO *info = pvStructInfo; 01410 DWORD bytesNeeded = 0, lenBytes, size, i; 01411 01412 TRACE("encoding name with %d RDNs\n", info->cRDN); 01413 ret = TRUE; 01414 for (i = 0; ret && i < info->cRDN; i++) 01415 { 01416 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], 01417 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size); 01418 if (ret) 01419 bytesNeeded += size; 01420 else 01421 *pcbEncoded = size; 01422 } 01423 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 01424 bytesNeeded += 1 + lenBytes; 01425 if (ret) 01426 { 01427 if (!pbEncoded) 01428 *pcbEncoded = bytesNeeded; 01429 else 01430 { 01431 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 01432 pbEncoded, pcbEncoded, bytesNeeded))) 01433 { 01434 BYTE *out; 01435 01436 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 01437 pbEncoded = *(BYTE **)pbEncoded; 01438 out = pbEncoded; 01439 *out++ = ASN_SEQUENCEOF; 01440 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 01441 out += lenBytes; 01442 for (i = 0; ret && i < info->cRDN; i++) 01443 { 01444 size = bytesNeeded; 01445 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, 01446 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue, 01447 out, &size); 01448 if (ret) 01449 { 01450 out += size; 01451 bytesNeeded -= size; 01452 } 01453 else 01454 *pcbEncoded = size; 01455 } 01456 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 01457 CRYPT_FreeSpace(pEncodePara, pbEncoded); 01458 } 01459 } 01460 } 01461 } 01462 __EXCEPT_PAGE_FAULT 01463 { 01464 SetLastError(STATUS_ACCESS_VIOLATION); 01465 ret = FALSE; 01466 } 01467 __ENDTRY 01468 return ret; 01469 } 01470 01471 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType, 01472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01474 { 01475 const DWORD *ver = pvStructInfo; 01476 BOOL ret; 01477 01478 /* CTL_V1 is not encoded */ 01479 if (*ver == CTL_V1) 01480 { 01481 *pcbEncoded = 0; 01482 ret = TRUE; 01483 } 01484 else 01485 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver, 01486 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01487 return ret; 01488 } 01489 01490 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL 01491 * if they are empty and the OID is not empty (otherwise omits them.) 01492 */ 01493 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm( 01494 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 01495 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 01496 DWORD *pcbEncoded) 01497 { 01498 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 01499 BOOL ret; 01500 struct AsnEncodeSequenceItem items[2] = { 01501 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, 01502 }; 01503 DWORD cItem = 1; 01504 01505 if (algo->pszObjId) 01506 { 01507 static const BYTE asn1Null[] = { ASN_NULL, 0 }; 01508 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null), 01509 (LPBYTE)asn1Null }; 01510 01511 if (algo->Parameters.cbData) 01512 items[cItem].pvStructInfo = &algo->Parameters; 01513 else 01514 items[cItem].pvStructInfo = &nullBlob; 01515 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob; 01516 cItem++; 01517 } 01518 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 01519 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01520 return ret; 01521 } 01522 01523 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry, 01524 BYTE *pbEncoded, DWORD *pcbEncoded) 01525 { 01526 struct AsnEncodeSequenceItem items[2] = { 01527 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 }, 01528 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 }, 01529 }; 01530 BOOL ret; 01531 01532 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 01533 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded); 01534 return ret; 01535 } 01536 01537 struct CTLEntries 01538 { 01539 DWORD cEntry; 01540 CTL_ENTRY *rgEntry; 01541 }; 01542 01543 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType, 01544 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01545 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01546 { 01547 BOOL ret; 01548 DWORD bytesNeeded, dataLen, lenBytes, i; 01549 const struct CTLEntries *entries = pvStructInfo; 01550 01551 ret = TRUE; 01552 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++) 01553 { 01554 DWORD size; 01555 01556 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size); 01557 if (ret) 01558 dataLen += size; 01559 } 01560 if (ret) 01561 { 01562 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 01563 bytesNeeded = 1 + lenBytes + dataLen; 01564 if (!pbEncoded) 01565 *pcbEncoded = bytesNeeded; 01566 else 01567 { 01568 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 01569 pbEncoded, pcbEncoded, bytesNeeded))) 01570 { 01571 BYTE *out; 01572 01573 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 01574 pbEncoded = *(BYTE **)pbEncoded; 01575 out = pbEncoded; 01576 *out++ = ASN_SEQUENCEOF; 01577 CRYPT_EncodeLen(dataLen, out, &lenBytes); 01578 out += lenBytes; 01579 for (i = 0; ret && i < entries->cEntry; i++) 01580 { 01581 DWORD size = dataLen; 01582 01583 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], 01584 out, &size); 01585 out += size; 01586 dataLen -= size; 01587 } 01588 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 01589 CRYPT_FreeSpace(pEncodePara, pbEncoded); 01590 } 01591 } 01592 } 01593 return ret; 01594 } 01595 01596 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType, 01597 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01598 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01599 { 01600 BOOL ret = FALSE; 01601 01602 __TRY 01603 { 01604 const CTL_INFO *info = pvStructInfo; 01605 struct AsnEncodeSequenceItem items[9] = { 01606 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 }, 01607 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 }, 01608 }; 01609 struct AsnConstructedItem constructed = { 0 }; 01610 DWORD cItem = 2; 01611 01612 if (info->ListIdentifier.cbData) 01613 { 01614 items[cItem].pvStructInfo = &info->ListIdentifier; 01615 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 01616 cItem++; 01617 } 01618 if (info->SequenceNumber.cbData) 01619 { 01620 items[cItem].pvStructInfo = &info->SequenceNumber; 01621 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger; 01622 cItem++; 01623 } 01624 items[cItem].pvStructInfo = &info->ThisUpdate; 01625 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 01626 cItem++; 01627 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime) 01628 { 01629 items[cItem].pvStructInfo = &info->NextUpdate; 01630 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 01631 cItem++; 01632 } 01633 items[cItem].pvStructInfo = &info->SubjectAlgorithm; 01634 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm; 01635 cItem++; 01636 if (info->cCTLEntry) 01637 { 01638 items[cItem].pvStructInfo = &info->cCTLEntry; 01639 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries; 01640 cItem++; 01641 } 01642 if (info->cExtension) 01643 { 01644 constructed.tag = 0; 01645 constructed.pvStructInfo = &info->cExtension; 01646 constructed.encodeFunc = CRYPT_AsnEncodeExtensions; 01647 items[cItem].pvStructInfo = &constructed; 01648 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 01649 cItem++; 01650 } 01651 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 01652 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01653 } 01654 __EXCEPT_PAGE_FAULT 01655 { 01656 SetLastError(STATUS_ACCESS_VIOLATION); 01657 } 01658 __ENDTRY 01659 return ret; 01660 } 01661 01662 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType, 01663 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01664 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01665 { 01666 BOOL ret = FALSE; 01667 01668 __TRY 01669 { 01670 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo; 01671 01672 if (!capability->pszObjId) 01673 SetLastError(E_INVALIDARG); 01674 else 01675 { 01676 struct AsnEncodeSequenceItem items[] = { 01677 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 }, 01678 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 }, 01679 }; 01680 01681 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 01682 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 01683 pcbEncoded); 01684 } 01685 } 01686 __EXCEPT_PAGE_FAULT 01687 { 01688 SetLastError(STATUS_ACCESS_VIOLATION); 01689 } 01690 __ENDTRY 01691 return ret; 01692 } 01693 01694 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType, 01695 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01696 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01697 { 01698 BOOL ret = FALSE; 01699 01700 __TRY 01701 { 01702 DWORD bytesNeeded, dataLen, lenBytes, i; 01703 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo; 01704 01705 ret = TRUE; 01706 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++) 01707 { 01708 DWORD size; 01709 01710 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL, 01711 &capabilities->rgCapability[i], 0, NULL, NULL, &size); 01712 if (ret) 01713 dataLen += size; 01714 } 01715 if (ret) 01716 { 01717 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 01718 bytesNeeded = 1 + lenBytes + dataLen; 01719 if (!pbEncoded) 01720 *pcbEncoded = bytesNeeded; 01721 else 01722 { 01723 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 01724 pbEncoded, pcbEncoded, bytesNeeded))) 01725 { 01726 BYTE *out; 01727 01728 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 01729 pbEncoded = *(BYTE **)pbEncoded; 01730 out = pbEncoded; 01731 *out++ = ASN_SEQUENCEOF; 01732 CRYPT_EncodeLen(dataLen, out, &lenBytes); 01733 out += lenBytes; 01734 for (i = 0; i < capabilities->cCapability; i++) 01735 { 01736 DWORD size = dataLen; 01737 01738 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, 01739 NULL, &capabilities->rgCapability[i], 0, NULL, 01740 out, &size); 01741 out += size; 01742 dataLen -= size; 01743 } 01744 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 01745 CRYPT_FreeSpace(pEncodePara, pbEncoded); 01746 } 01747 } 01748 } 01749 } 01750 __EXCEPT_PAGE_FAULT 01751 { 01752 SetLastError(STATUS_ACCESS_VIOLATION); 01753 } 01754 __ENDTRY 01755 return ret; 01756 } 01757 01758 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType, 01759 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01760 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01761 { 01762 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo; 01763 DWORD bytesNeeded, dataLen, lenBytes, i; 01764 BOOL ret = TRUE; 01765 01766 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++) 01767 { 01768 DWORD size; 01769 01770 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, 01771 ¬iceRef->rgNoticeNumbers[i], 0, NULL, NULL, &size); 01772 if (ret) 01773 dataLen += size; 01774 } 01775 if (ret) 01776 { 01777 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 01778 bytesNeeded = 1 + lenBytes + dataLen; 01779 if (!pbEncoded) 01780 *pcbEncoded = bytesNeeded; 01781 else 01782 { 01783 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 01784 pcbEncoded, bytesNeeded))) 01785 { 01786 BYTE *out; 01787 01788 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 01789 pbEncoded = *(BYTE **)pbEncoded; 01790 out = pbEncoded; 01791 *out++ = ASN_SEQUENCE; 01792 CRYPT_EncodeLen(dataLen, out, &lenBytes); 01793 out += lenBytes; 01794 for (i = 0; i < noticeRef->cNoticeNumbers; i++) 01795 { 01796 DWORD size = dataLen; 01797 01798 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, 01799 ¬iceRef->rgNoticeNumbers[i], 0, NULL, out, &size); 01800 out += size; 01801 dataLen -= size; 01802 } 01803 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 01804 CRYPT_FreeSpace(pEncodePara, pbEncoded); 01805 } 01806 } 01807 } 01808 return ret; 01809 } 01810 01811 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType, 01812 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01813 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01814 { 01815 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo; 01816 BOOL ret; 01817 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING, 01818 { 0, (LPBYTE)noticeRef->pszOrganization } }; 01819 struct AsnEncodeSequenceItem items[] = { 01820 { &orgValue, CRYPT_AsnEncodeNameValue, 0 }, 01821 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 }, 01822 }; 01823 01824 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 01825 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 01826 pcbEncoded); 01827 return ret; 01828 } 01829 01830 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice( 01831 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 01832 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 01833 DWORD *pcbEncoded) 01834 { 01835 BOOL ret = FALSE; 01836 01837 __TRY 01838 { 01839 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo; 01840 struct AsnEncodeSequenceItem items[2]; 01841 CERT_NAME_VALUE displayTextValue; 01842 DWORD cItem = 0; 01843 01844 if (notice->pNoticeReference) 01845 { 01846 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference; 01847 items[cItem].pvStructInfo = notice->pNoticeReference; 01848 cItem++; 01849 } 01850 if (notice->pszDisplayText) 01851 { 01852 displayTextValue.dwValueType = CERT_RDN_BMP_STRING; 01853 displayTextValue.Value.cbData = 0; 01854 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText; 01855 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue; 01856 items[cItem].pvStructInfo = &displayTextValue; 01857 cItem++; 01858 } 01859 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 01860 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01861 } 01862 __EXCEPT_PAGE_FAULT 01863 { 01864 SetLastError(STATUS_ACCESS_VIOLATION); 01865 } 01866 __ENDTRY 01867 return ret; 01868 } 01869 01870 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType, 01871 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01872 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01873 { 01874 BOOL ret = FALSE; 01875 01876 __TRY 01877 { 01878 const CRYPT_ATTRIBUTE *attr = pvStructInfo; 01879 01880 if (!attr->pszObjId) 01881 SetLastError(E_INVALIDARG); 01882 else 01883 { 01884 struct AsnEncodeSequenceItem items[2] = { 01885 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 }, 01886 { &attr->cValue, CRYPT_DEREncodeSet, 0 }, 01887 }; 01888 01889 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 01890 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 01891 pcbEncoded); 01892 } 01893 } 01894 __EXCEPT_PAGE_FAULT 01895 { 01896 SetLastError(STATUS_ACCESS_VIOLATION); 01897 } 01898 __ENDTRY 01899 return ret; 01900 } 01901 01902 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType, 01903 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01904 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01905 { 01906 BOOL ret = FALSE; 01907 01908 __TRY 01909 { 01910 const CRYPT_ATTRIBUTES *attributes = pvStructInfo; 01911 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr, 01912 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute }; 01913 01914 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType, 01915 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01916 } 01917 __EXCEPT_PAGE_FAULT 01918 { 01919 SetLastError(STATUS_ACCESS_VIOLATION); 01920 } 01921 __ENDTRY 01922 return ret; 01923 } 01924 01925 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */ 01926 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal( 01927 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 01928 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 01929 DWORD *pcbEncoded) 01930 { 01931 const CRYPT_CONTENT_INFO *info = pvStructInfo; 01932 struct AsnEncodeSequenceItem items[2] = { 01933 { info->pszObjId, CRYPT_AsnEncodeOid, 0 }, 01934 { NULL, NULL, 0 }, 01935 }; 01936 struct AsnConstructedItem constructed = { 0 }; 01937 DWORD cItem = 1; 01938 01939 if (info->Content.cbData) 01940 { 01941 constructed.tag = 0; 01942 constructed.pvStructInfo = &info->Content; 01943 constructed.encodeFunc = CRYPT_CopyEncodedBlob; 01944 items[cItem].pvStructInfo = &constructed; 01945 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 01946 cItem++; 01947 } 01948 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 01949 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 01950 } 01951 01952 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData, 01953 void *pvData, DWORD *pcbData) 01954 { 01955 struct AsnEncodeSequenceItem items[] = { 01956 { &digestedData->version, CRYPT_AsnEncodeInt, 0 }, 01957 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 01958 0 }, 01959 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 }, 01960 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 }, 01961 }; 01962 01963 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 01964 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData); 01965 } 01966 01967 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType, 01968 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 01969 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 01970 { 01971 BOOL ret = FALSE; 01972 01973 __TRY 01974 { 01975 const CRYPT_CONTENT_INFO *info = pvStructInfo; 01976 01977 if (!info->pszObjId) 01978 SetLastError(E_INVALIDARG); 01979 else 01980 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType, 01981 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded, 01982 pcbEncoded); 01983 } 01984 __EXCEPT_PAGE_FAULT 01985 { 01986 SetLastError(STATUS_ACCESS_VIOLATION); 01987 } 01988 __ENDTRY 01989 return ret; 01990 } 01991 01992 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value, 01993 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 01994 DWORD *pcbEncoded) 01995 { 01996 BOOL ret = TRUE; 01997 LPCWSTR str = (LPCWSTR)value->Value.pbData; 01998 DWORD bytesNeeded, lenBytes, encodedLen; 01999 02000 if (value->Value.cbData) 02001 encodedLen = value->Value.cbData / sizeof(WCHAR); 02002 else if (str) 02003 encodedLen = strlenW(str); 02004 else 02005 encodedLen = 0; 02006 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 02007 bytesNeeded = 1 + lenBytes + encodedLen; 02008 if (!pbEncoded) 02009 *pcbEncoded = bytesNeeded; 02010 else 02011 { 02012 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02013 pbEncoded, pcbEncoded, bytesNeeded))) 02014 { 02015 DWORD i; 02016 02017 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02018 pbEncoded = *(BYTE **)pbEncoded; 02019 *pbEncoded++ = tag; 02020 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); 02021 pbEncoded += lenBytes; 02022 for (i = 0; i < encodedLen; i++) 02023 *pbEncoded++ = (BYTE)str[i]; 02024 } 02025 } 02026 return ret; 02027 } 02028 02029 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value, 02030 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 02031 DWORD *pcbEncoded) 02032 { 02033 BOOL ret = TRUE; 02034 LPCWSTR str = (LPCWSTR)value->Value.pbData; 02035 DWORD bytesNeeded, lenBytes, encodedLen; 02036 02037 if (value->Value.cbData) 02038 encodedLen = value->Value.cbData / sizeof(WCHAR); 02039 else if (str) 02040 encodedLen = strlenW(str); 02041 else 02042 encodedLen = 0; 02043 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 02044 bytesNeeded = 1 + lenBytes + encodedLen; 02045 if (!pbEncoded) 02046 *pcbEncoded = bytesNeeded; 02047 else 02048 { 02049 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02050 pbEncoded, pcbEncoded, bytesNeeded))) 02051 { 02052 DWORD i; 02053 BYTE *ptr; 02054 02055 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02056 ptr = *(BYTE **)pbEncoded; 02057 else 02058 ptr = pbEncoded; 02059 *ptr++ = ASN_NUMERICSTRING; 02060 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 02061 ptr += lenBytes; 02062 for (i = 0; ret && i < encodedLen; i++) 02063 { 02064 if (isdigitW(str[i])) 02065 *ptr++ = (BYTE)str[i]; 02066 else 02067 { 02068 *pcbEncoded = i; 02069 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING); 02070 ret = FALSE; 02071 } 02072 } 02073 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 02074 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 02075 } 02076 } 02077 return ret; 02078 } 02079 02080 static inline int isprintableW(WCHAR wc) 02081 { 02082 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' || 02083 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' || 02084 wc == '/' || wc == ':' || wc == '=' || wc == '?'; 02085 } 02086 02087 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value, 02088 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 02089 DWORD *pcbEncoded) 02090 { 02091 BOOL ret = TRUE; 02092 LPCWSTR str = (LPCWSTR)value->Value.pbData; 02093 DWORD bytesNeeded, lenBytes, encodedLen; 02094 02095 if (value->Value.cbData) 02096 encodedLen = value->Value.cbData / sizeof(WCHAR); 02097 else if (str) 02098 encodedLen = strlenW(str); 02099 else 02100 encodedLen = 0; 02101 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 02102 bytesNeeded = 1 + lenBytes + encodedLen; 02103 if (!pbEncoded) 02104 *pcbEncoded = bytesNeeded; 02105 else 02106 { 02107 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02108 pbEncoded, pcbEncoded, bytesNeeded))) 02109 { 02110 DWORD i; 02111 BYTE *ptr; 02112 02113 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02114 ptr = *(BYTE **)pbEncoded; 02115 else 02116 ptr = pbEncoded; 02117 *ptr++ = ASN_PRINTABLESTRING; 02118 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 02119 ptr += lenBytes; 02120 for (i = 0; ret && i < encodedLen; i++) 02121 { 02122 if (isprintableW(str[i])) 02123 *ptr++ = (BYTE)str[i]; 02124 else 02125 { 02126 *pcbEncoded = i; 02127 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING); 02128 ret = FALSE; 02129 } 02130 } 02131 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 02132 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 02133 } 02134 } 02135 return ret; 02136 } 02137 02138 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value, 02139 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 02140 DWORD *pcbEncoded) 02141 { 02142 BOOL ret = TRUE; 02143 LPCWSTR str = (LPCWSTR)value->Value.pbData; 02144 DWORD bytesNeeded, lenBytes, encodedLen; 02145 02146 if (value->Value.cbData) 02147 encodedLen = value->Value.cbData / sizeof(WCHAR); 02148 else if (str) 02149 encodedLen = strlenW(str); 02150 else 02151 encodedLen = 0; 02152 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 02153 bytesNeeded = 1 + lenBytes + encodedLen; 02154 if (!pbEncoded) 02155 *pcbEncoded = bytesNeeded; 02156 else 02157 { 02158 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02159 pbEncoded, pcbEncoded, bytesNeeded))) 02160 { 02161 DWORD i; 02162 BYTE *ptr; 02163 02164 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02165 ptr = *(BYTE **)pbEncoded; 02166 else 02167 ptr = pbEncoded; 02168 *ptr++ = ASN_IA5STRING; 02169 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 02170 ptr += lenBytes; 02171 for (i = 0; ret && i < encodedLen; i++) 02172 { 02173 if (str[i] <= 0x7f) 02174 *ptr++ = (BYTE)str[i]; 02175 else 02176 { 02177 *pcbEncoded = i; 02178 SetLastError(CRYPT_E_INVALID_IA5_STRING); 02179 ret = FALSE; 02180 } 02181 } 02182 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 02183 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 02184 } 02185 } 02186 return ret; 02187 } 02188 02189 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value, 02190 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 02191 DWORD *pcbEncoded) 02192 { 02193 BOOL ret = TRUE; 02194 LPCWSTR str = (LPCWSTR)value->Value.pbData; 02195 DWORD bytesNeeded, lenBytes, strLen; 02196 02197 /* FIXME: doesn't handle composite characters */ 02198 if (value->Value.cbData) 02199 strLen = value->Value.cbData / sizeof(WCHAR); 02200 else if (str) 02201 strLen = strlenW(str); 02202 else 02203 strLen = 0; 02204 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes); 02205 bytesNeeded = 1 + lenBytes + strLen * 4; 02206 if (!pbEncoded) 02207 *pcbEncoded = bytesNeeded; 02208 else 02209 { 02210 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02211 pbEncoded, pcbEncoded, bytesNeeded))) 02212 { 02213 DWORD i; 02214 02215 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02216 pbEncoded = *(BYTE **)pbEncoded; 02217 *pbEncoded++ = ASN_UNIVERSALSTRING; 02218 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes); 02219 pbEncoded += lenBytes; 02220 for (i = 0; i < strLen; i++) 02221 { 02222 *pbEncoded++ = 0; 02223 *pbEncoded++ = 0; 02224 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8); 02225 *pbEncoded++ = (BYTE)(str[i] & 0x00ff); 02226 } 02227 } 02228 } 02229 return ret; 02230 } 02231 02232 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType, 02233 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02234 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02235 { 02236 BOOL ret = FALSE; 02237 02238 __TRY 02239 { 02240 const CERT_NAME_VALUE *value = pvStructInfo; 02241 02242 switch (value->dwValueType) 02243 { 02244 case CERT_RDN_ANY_TYPE: 02245 case CERT_RDN_ENCODED_BLOB: 02246 case CERT_RDN_OCTET_STRING: 02247 SetLastError(CRYPT_E_NOT_CHAR_STRING); 02248 break; 02249 case CERT_RDN_NUMERIC_STRING: 02250 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara, 02251 pbEncoded, pcbEncoded); 02252 break; 02253 case CERT_RDN_PRINTABLE_STRING: 02254 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara, 02255 pbEncoded, pcbEncoded); 02256 break; 02257 case CERT_RDN_TELETEX_STRING: 02258 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING, 02259 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 02260 break; 02261 case CERT_RDN_VIDEOTEX_STRING: 02262 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, 02263 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 02264 break; 02265 case CERT_RDN_IA5_STRING: 02266 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara, 02267 pbEncoded, pcbEncoded); 02268 break; 02269 case CERT_RDN_GRAPHIC_STRING: 02270 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING, 02271 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 02272 break; 02273 case CERT_RDN_VISIBLE_STRING: 02274 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING, 02275 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 02276 break; 02277 case CERT_RDN_GENERAL_STRING: 02278 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING, 02279 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 02280 break; 02281 case CERT_RDN_UNIVERSAL_STRING: 02282 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara, 02283 pbEncoded, pcbEncoded); 02284 break; 02285 case CERT_RDN_BMP_STRING: 02286 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara, 02287 pbEncoded, pcbEncoded); 02288 break; 02289 case CERT_RDN_UTF8_STRING: 02290 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara, 02291 pbEncoded, pcbEncoded); 02292 break; 02293 default: 02294 SetLastError(CRYPT_E_ASN1_CHOICE); 02295 } 02296 } 02297 __EXCEPT_PAGE_FAULT 02298 { 02299 SetLastError(STATUS_ACCESS_VIOLATION); 02300 } 02301 __ENDTRY 02302 return ret; 02303 } 02304 02305 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType, 02306 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02307 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02308 { 02309 BOOL ret; 02310 02311 __TRY 02312 { 02313 const CERT_NAME_INFO *info = pvStructInfo; 02314 DWORD bytesNeeded = 0, lenBytes, size, i; 02315 02316 TRACE("encoding name with %d RDNs\n", info->cRDN); 02317 ret = TRUE; 02318 for (i = 0; ret && i < info->cRDN; i++) 02319 { 02320 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], 02321 CRYPT_AsnEncodeNameValue, NULL, &size); 02322 if (ret) 02323 bytesNeeded += size; 02324 } 02325 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 02326 bytesNeeded += 1 + lenBytes; 02327 if (ret) 02328 { 02329 if (!pbEncoded) 02330 *pcbEncoded = bytesNeeded; 02331 else 02332 { 02333 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02334 pbEncoded, pcbEncoded, bytesNeeded))) 02335 { 02336 BYTE *out; 02337 02338 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02339 pbEncoded = *(BYTE **)pbEncoded; 02340 out = pbEncoded; 02341 *out++ = ASN_SEQUENCEOF; 02342 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 02343 out += lenBytes; 02344 for (i = 0; ret && i < info->cRDN; i++) 02345 { 02346 size = bytesNeeded; 02347 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, 02348 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size); 02349 if (ret) 02350 { 02351 out += size; 02352 bytesNeeded -= size; 02353 } 02354 } 02355 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 02356 CRYPT_FreeSpace(pEncodePara, pbEncoded); 02357 } 02358 } 02359 } 02360 } 02361 __EXCEPT_PAGE_FAULT 02362 { 02363 SetLastError(STATUS_ACCESS_VIOLATION); 02364 ret = FALSE; 02365 } 02366 __ENDTRY 02367 return ret; 02368 } 02369 02370 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, 02371 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02372 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02373 { 02374 BOOL val = *(const BOOL *)pvStructInfo, ret; 02375 02376 TRACE("%d\n", val); 02377 02378 if (!pbEncoded) 02379 { 02380 *pcbEncoded = 3; 02381 ret = TRUE; 02382 } 02383 else if (*pcbEncoded < 3) 02384 { 02385 *pcbEncoded = 3; 02386 SetLastError(ERROR_MORE_DATA); 02387 ret = FALSE; 02388 } 02389 else 02390 { 02391 *pcbEncoded = 3; 02392 *pbEncoded++ = ASN_BOOL; 02393 *pbEncoded++ = 1; 02394 *pbEncoded++ = val ? 0xff : 0; 02395 ret = TRUE; 02396 } 02397 TRACE("returning %d (%08x)\n", ret, GetLastError()); 02398 return ret; 02399 } 02400 02401 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType, 02402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02404 { 02405 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo; 02406 BOOL ret; 02407 DWORD dataLen; 02408 BYTE tag; 02409 02410 ret = TRUE; 02411 switch (entry->dwAltNameChoice) 02412 { 02413 case CERT_ALT_NAME_RFC822_NAME: 02414 case CERT_ALT_NAME_DNS_NAME: 02415 case CERT_ALT_NAME_URL: 02416 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1); 02417 if (entry->u.pwszURL) 02418 { 02419 DWORD i; 02420 02421 /* Not + 1: don't encode the NULL-terminator */ 02422 dataLen = lstrlenW(entry->u.pwszURL); 02423 for (i = 0; ret && i < dataLen; i++) 02424 { 02425 if (entry->u.pwszURL[i] > 0x7f) 02426 { 02427 SetLastError(CRYPT_E_INVALID_IA5_STRING); 02428 ret = FALSE; 02429 *pcbEncoded = i; 02430 } 02431 } 02432 } 02433 else 02434 dataLen = 0; 02435 break; 02436 case CERT_ALT_NAME_DIRECTORY_NAME: 02437 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1); 02438 dataLen = entry->u.DirectoryName.cbData; 02439 break; 02440 case CERT_ALT_NAME_IP_ADDRESS: 02441 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1); 02442 dataLen = entry->u.IPAddress.cbData; 02443 break; 02444 case CERT_ALT_NAME_REGISTERED_ID: 02445 { 02446 struct AsnEncodeTagSwappedItem swapped = 02447 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID, 02448 CRYPT_AsnEncodeOid }; 02449 02450 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded, 02451 pcbEncoded); 02452 } 02453 case CERT_ALT_NAME_OTHER_NAME: 02454 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice); 02455 return FALSE; 02456 default: 02457 SetLastError(E_INVALIDARG); 02458 return FALSE; 02459 } 02460 if (ret) 02461 { 02462 DWORD bytesNeeded, lenBytes; 02463 02464 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 02465 bytesNeeded = 1 + dataLen + lenBytes; 02466 if (!pbEncoded) 02467 *pcbEncoded = bytesNeeded; 02468 else if (*pcbEncoded < bytesNeeded) 02469 { 02470 SetLastError(ERROR_MORE_DATA); 02471 *pcbEncoded = bytesNeeded; 02472 ret = FALSE; 02473 } 02474 else 02475 { 02476 *pbEncoded++ = tag; 02477 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 02478 pbEncoded += lenBytes; 02479 switch (entry->dwAltNameChoice) 02480 { 02481 case CERT_ALT_NAME_RFC822_NAME: 02482 case CERT_ALT_NAME_DNS_NAME: 02483 case CERT_ALT_NAME_URL: 02484 { 02485 DWORD i; 02486 02487 for (i = 0; i < dataLen; i++) 02488 *pbEncoded++ = (BYTE)entry->u.pwszURL[i]; 02489 break; 02490 } 02491 case CERT_ALT_NAME_DIRECTORY_NAME: 02492 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen); 02493 break; 02494 case CERT_ALT_NAME_IP_ADDRESS: 02495 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen); 02496 break; 02497 } 02498 if (ret) 02499 *pcbEncoded = bytesNeeded; 02500 } 02501 } 02502 TRACE("returning %d (%08x)\n", ret, GetLastError()); 02503 return ret; 02504 } 02505 02506 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType, 02507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02509 { 02510 BOOL ret; 02511 02512 __TRY 02513 { 02514 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo; 02515 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 02516 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 02517 struct AsnConstructedItem constructed = { 0 }; 02518 DWORD cItem = 0, cSwapped = 0; 02519 02520 if (info->KeyId.cbData) 02521 { 02522 swapped[cSwapped].tag = ASN_CONTEXT | 0; 02523 swapped[cSwapped].pvStructInfo = &info->KeyId; 02524 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 02525 items[cItem].pvStructInfo = &swapped[cSwapped]; 02526 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 02527 cSwapped++; 02528 cItem++; 02529 } 02530 if (info->CertIssuer.cbData) 02531 { 02532 constructed.tag = 1; 02533 constructed.pvStructInfo = &info->CertIssuer; 02534 constructed.encodeFunc = CRYPT_CopyEncodedBlob; 02535 items[cItem].pvStructInfo = &constructed; 02536 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 02537 cItem++; 02538 } 02539 if (info->CertSerialNumber.cbData) 02540 { 02541 swapped[cSwapped].tag = ASN_CONTEXT | 2; 02542 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber; 02543 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger; 02544 items[cItem].pvStructInfo = &swapped[cSwapped]; 02545 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 02546 cSwapped++; 02547 cItem++; 02548 } 02549 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags, 02550 pEncodePara, pbEncoded, pcbEncoded); 02551 } 02552 __EXCEPT_PAGE_FAULT 02553 { 02554 SetLastError(STATUS_ACCESS_VIOLATION); 02555 ret = FALSE; 02556 } 02557 __ENDTRY 02558 return ret; 02559 } 02560 02561 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType, 02562 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02563 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02564 { 02565 BOOL ret; 02566 02567 __TRY 02568 { 02569 const CERT_ALT_NAME_INFO *info = pvStructInfo; 02570 DWORD bytesNeeded, dataLen, lenBytes, i; 02571 02572 ret = TRUE; 02573 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we 02574 * can't encode an erroneous entry index if it's bigger than this. 02575 */ 02576 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++) 02577 { 02578 DWORD len; 02579 02580 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL, 02581 &info->rgAltEntry[i], 0, NULL, NULL, &len); 02582 if (ret) 02583 dataLen += len; 02584 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING) 02585 { 02586 /* CRYPT_AsnEncodeAltNameEntry encoded the index of 02587 * the bad character, now set the index of the bad 02588 * entry 02589 */ 02590 *pcbEncoded = (BYTE)i << 02591 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len; 02592 } 02593 } 02594 if (ret) 02595 { 02596 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 02597 bytesNeeded = 1 + lenBytes + dataLen; 02598 if (!pbEncoded) 02599 { 02600 *pcbEncoded = bytesNeeded; 02601 ret = TRUE; 02602 } 02603 else 02604 { 02605 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02606 pbEncoded, pcbEncoded, bytesNeeded))) 02607 { 02608 BYTE *out; 02609 02610 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02611 pbEncoded = *(BYTE **)pbEncoded; 02612 out = pbEncoded; 02613 *out++ = ASN_SEQUENCEOF; 02614 CRYPT_EncodeLen(dataLen, out, &lenBytes); 02615 out += lenBytes; 02616 for (i = 0; ret && i < info->cAltEntry; i++) 02617 { 02618 DWORD len = dataLen; 02619 02620 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, 02621 NULL, &info->rgAltEntry[i], 0, NULL, out, &len); 02622 if (ret) 02623 { 02624 out += len; 02625 dataLen -= len; 02626 } 02627 } 02628 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 02629 CRYPT_FreeSpace(pEncodePara, pbEncoded); 02630 } 02631 } 02632 } 02633 } 02634 __EXCEPT_PAGE_FAULT 02635 { 02636 SetLastError(STATUS_ACCESS_VIOLATION); 02637 ret = FALSE; 02638 } 02639 __ENDTRY 02640 return ret; 02641 } 02642 02643 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType, 02644 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02645 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02646 { 02647 BOOL ret; 02648 02649 __TRY 02650 { 02651 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo; 02652 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 02653 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 02654 DWORD cItem = 0, cSwapped = 0; 02655 02656 if (info->KeyId.cbData) 02657 { 02658 swapped[cSwapped].tag = ASN_CONTEXT | 0; 02659 swapped[cSwapped].pvStructInfo = &info->KeyId; 02660 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 02661 items[cItem].pvStructInfo = &swapped[cSwapped]; 02662 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 02663 cSwapped++; 02664 cItem++; 02665 } 02666 if (info->AuthorityCertIssuer.cAltEntry) 02667 { 02668 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 02669 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer; 02670 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 02671 items[cItem].pvStructInfo = &swapped[cSwapped]; 02672 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 02673 cSwapped++; 02674 cItem++; 02675 } 02676 if (info->AuthorityCertSerialNumber.cbData) 02677 { 02678 swapped[cSwapped].tag = ASN_CONTEXT | 2; 02679 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber; 02680 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger; 02681 items[cItem].pvStructInfo = &swapped[cSwapped]; 02682 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 02683 cSwapped++; 02684 cItem++; 02685 } 02686 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags, 02687 pEncodePara, pbEncoded, pcbEncoded); 02688 } 02689 __EXCEPT_PAGE_FAULT 02690 { 02691 SetLastError(STATUS_ACCESS_VIOLATION); 02692 ret = FALSE; 02693 } 02694 __ENDTRY 02695 return ret; 02696 } 02697 02698 static BOOL CRYPT_AsnEncodeAccessDescription( 02699 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded) 02700 { 02701 struct AsnEncodeSequenceItem items[] = { 02702 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 }, 02703 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 }, 02704 }; 02705 02706 if (!descr->pszAccessMethod) 02707 { 02708 SetLastError(E_INVALIDARG); 02709 return FALSE; 02710 } 02711 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 02712 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded); 02713 } 02714 02715 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType, 02716 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02717 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02718 { 02719 BOOL ret; 02720 02721 __TRY 02722 { 02723 DWORD bytesNeeded, dataLen, lenBytes, i; 02724 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo; 02725 02726 ret = TRUE; 02727 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++) 02728 { 02729 DWORD size; 02730 02731 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL, 02732 &size); 02733 if (ret) 02734 dataLen += size; 02735 } 02736 if (ret) 02737 { 02738 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 02739 bytesNeeded = 1 + lenBytes + dataLen; 02740 if (!pbEncoded) 02741 *pcbEncoded = bytesNeeded; 02742 else 02743 { 02744 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02745 pbEncoded, pcbEncoded, bytesNeeded))) 02746 { 02747 BYTE *out; 02748 02749 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02750 pbEncoded = *(BYTE **)pbEncoded; 02751 out = pbEncoded; 02752 *out++ = ASN_SEQUENCEOF; 02753 CRYPT_EncodeLen(dataLen, out, &lenBytes); 02754 out += lenBytes; 02755 for (i = 0; i < info->cAccDescr; i++) 02756 { 02757 DWORD size = dataLen; 02758 02759 ret = CRYPT_AsnEncodeAccessDescription( 02760 &info->rgAccDescr[i], out, &size); 02761 out += size; 02762 dataLen -= size; 02763 } 02764 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 02765 CRYPT_FreeSpace(pEncodePara, pbEncoded); 02766 } 02767 } 02768 } 02769 } 02770 __EXCEPT_PAGE_FAULT 02771 { 02772 SetLastError(STATUS_ACCESS_VIOLATION); 02773 ret = FALSE; 02774 } 02775 __ENDTRY 02776 return ret; 02777 } 02778 02779 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType, 02780 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02781 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02782 { 02783 BOOL ret; 02784 02785 __TRY 02786 { 02787 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo; 02788 struct AsnEncodeSequenceItem items[3] = { 02789 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 }, 02790 { 0 } 02791 }; 02792 DWORD cItem = 1; 02793 02794 if (info->fPathLenConstraint) 02795 { 02796 items[cItem].pvStructInfo = &info->dwPathLenConstraint; 02797 items[cItem].encodeFunc = CRYPT_AsnEncodeInt; 02798 cItem++; 02799 } 02800 if (info->cSubtreesConstraint) 02801 { 02802 items[cItem].pvStructInfo = &info->cSubtreesConstraint; 02803 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny; 02804 cItem++; 02805 } 02806 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 02807 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 02808 } 02809 __EXCEPT_PAGE_FAULT 02810 { 02811 SetLastError(STATUS_ACCESS_VIOLATION); 02812 ret = FALSE; 02813 } 02814 __ENDTRY 02815 return ret; 02816 } 02817 02818 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType, 02819 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02820 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02821 { 02822 BOOL ret; 02823 02824 __TRY 02825 { 02826 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo; 02827 struct AsnEncodeSequenceItem items[2] = { { 0 } }; 02828 DWORD cItem = 0; 02829 02830 if (info->fCA) 02831 { 02832 items[cItem].pvStructInfo = &info->fCA; 02833 items[cItem].encodeFunc = CRYPT_AsnEncodeBool; 02834 cItem++; 02835 } 02836 if (info->fPathLenConstraint) 02837 { 02838 items[cItem].pvStructInfo = &info->dwPathLenConstraint; 02839 items[cItem].encodeFunc = CRYPT_AsnEncodeInt; 02840 cItem++; 02841 } 02842 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 02843 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 02844 } 02845 __EXCEPT_PAGE_FAULT 02846 { 02847 SetLastError(STATUS_ACCESS_VIOLATION); 02848 ret = FALSE; 02849 } 02850 __ENDTRY 02851 return ret; 02852 } 02853 02854 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType, 02855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02857 { 02858 const CERT_POLICY_INFO *info = pvStructInfo; 02859 BOOL ret; 02860 02861 if (!info->cPolicyQualifier) 02862 { 02863 *pcbEncoded = 0; 02864 ret = TRUE; 02865 } 02866 else 02867 { 02868 struct AsnEncodeSequenceItem items[2] = { 02869 { NULL, CRYPT_AsnEncodeOid, 0 }, 02870 { NULL, CRYPT_CopyEncodedBlob, 0 }, 02871 }; 02872 DWORD bytesNeeded = 0, lenBytes, size, i; 02873 02874 ret = TRUE; 02875 for (i = 0; ret && i < info->cPolicyQualifier; i++) 02876 { 02877 items[0].pvStructInfo = 02878 info->rgPolicyQualifier[i].pszPolicyQualifierId; 02879 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier; 02880 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 02881 sizeof(items) / sizeof(items[0]), 02882 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size); 02883 if (ret) 02884 bytesNeeded += size; 02885 } 02886 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 02887 bytesNeeded += 1 + lenBytes; 02888 if (ret) 02889 { 02890 if (!pbEncoded) 02891 *pcbEncoded = bytesNeeded; 02892 else 02893 { 02894 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02895 pbEncoded, pcbEncoded, bytesNeeded))) 02896 { 02897 BYTE *out; 02898 02899 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02900 pbEncoded = *(BYTE **)pbEncoded; 02901 out = pbEncoded; 02902 *out++ = ASN_SEQUENCEOF; 02903 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 02904 out += lenBytes; 02905 for (i = 0; ret && i < info->cPolicyQualifier; i++) 02906 { 02907 items[0].pvStructInfo = 02908 info->rgPolicyQualifier[i].pszPolicyQualifierId; 02909 items[1].pvStructInfo = 02910 &info->rgPolicyQualifier[i].Qualifier; 02911 size = bytesNeeded; 02912 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 02913 sizeof(items) / sizeof(items[0]), 02914 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size); 02915 if (ret) 02916 { 02917 out += size; 02918 bytesNeeded -= size; 02919 } 02920 } 02921 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 02922 CRYPT_FreeSpace(pEncodePara, pbEncoded); 02923 } 02924 } 02925 } 02926 } 02927 return ret; 02928 } 02929 02930 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType, 02931 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded, 02932 DWORD *pcbEncoded) 02933 { 02934 struct AsnEncodeSequenceItem items[2] = { 02935 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 }, 02936 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 }, 02937 }; 02938 BOOL ret; 02939 02940 if (!info->pszPolicyIdentifier) 02941 { 02942 SetLastError(E_INVALIDARG); 02943 return FALSE; 02944 } 02945 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 02946 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded); 02947 return ret; 02948 } 02949 02950 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType, 02951 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 02952 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 02953 { 02954 BOOL ret = FALSE; 02955 02956 __TRY 02957 { 02958 const CERT_POLICIES_INFO *info = pvStructInfo; 02959 DWORD bytesNeeded = 0, lenBytes, size, i; 02960 02961 ret = TRUE; 02962 for (i = 0; ret && i < info->cPolicyInfo; i++) 02963 { 02964 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType, 02965 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, 02966 &size); 02967 if (ret) 02968 bytesNeeded += size; 02969 } 02970 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 02971 bytesNeeded += 1 + lenBytes; 02972 if (ret) 02973 { 02974 if (!pbEncoded) 02975 *pcbEncoded = bytesNeeded; 02976 else 02977 { 02978 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 02979 pbEncoded, pcbEncoded, bytesNeeded))) 02980 { 02981 BYTE *out; 02982 02983 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 02984 pbEncoded = *(BYTE **)pbEncoded; 02985 out = pbEncoded; 02986 *out++ = ASN_SEQUENCEOF; 02987 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 02988 out += lenBytes; 02989 for (i = 0; ret && i < info->cPolicyInfo; i++) 02990 { 02991 size = bytesNeeded; 02992 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType, 02993 &info->rgPolicyInfo[i], 02994 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size); 02995 if (ret) 02996 { 02997 out += size; 02998 bytesNeeded -= size; 02999 } 03000 } 03001 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 03002 CRYPT_FreeSpace(pEncodePara, pbEncoded); 03003 } 03004 } 03005 } 03006 } 03007 __EXCEPT_PAGE_FAULT 03008 { 03009 SetLastError(STATUS_ACCESS_VIOLATION); 03010 } 03011 __ENDTRY 03012 return ret; 03013 } 03014 03015 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType, 03016 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded, 03017 DWORD *pcbEncoded) 03018 { 03019 struct AsnEncodeSequenceItem items[] = { 03020 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 }, 03021 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 }, 03022 }; 03023 03024 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy) 03025 { 03026 SetLastError(E_INVALIDARG); 03027 return FALSE; 03028 } 03029 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 03030 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded); 03031 } 03032 03033 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType, 03034 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03035 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03036 { 03037 BOOL ret = FALSE; 03038 03039 __TRY 03040 { 03041 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo; 03042 DWORD bytesNeeded = 0, lenBytes, size, i; 03043 03044 ret = TRUE; 03045 for (i = 0; ret && i < info->cPolicyMapping; i++) 03046 { 03047 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType, 03048 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, 03049 NULL, &size); 03050 if (ret) 03051 bytesNeeded += size; 03052 } 03053 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 03054 bytesNeeded += 1 + lenBytes; 03055 if (ret) 03056 { 03057 if (!pbEncoded) 03058 *pcbEncoded = bytesNeeded; 03059 else 03060 { 03061 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 03062 pbEncoded, pcbEncoded, bytesNeeded))) 03063 { 03064 BYTE *out; 03065 03066 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03067 pbEncoded = *(BYTE **)pbEncoded; 03068 out = pbEncoded; 03069 *out++ = ASN_SEQUENCEOF; 03070 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 03071 out += lenBytes; 03072 for (i = 0; ret && i < info->cPolicyMapping; i++) 03073 { 03074 size = bytesNeeded; 03075 ret = CRYPT_AsnEncodeCertPolicyMapping( 03076 dwCertEncodingType, &info->rgPolicyMapping[i], 03077 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size); 03078 if (ret) 03079 { 03080 out += size; 03081 bytesNeeded -= size; 03082 } 03083 } 03084 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 03085 CRYPT_FreeSpace(pEncodePara, pbEncoded); 03086 } 03087 } 03088 } 03089 } 03090 __EXCEPT_PAGE_FAULT 03091 { 03092 SetLastError(STATUS_ACCESS_VIOLATION); 03093 } 03094 __ENDTRY 03095 return ret; 03096 } 03097 03098 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints( 03099 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 03100 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 03101 DWORD *pcbEncoded) 03102 { 03103 BOOL ret = FALSE; 03104 03105 __TRY 03106 { 03107 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo; 03108 struct AsnEncodeSequenceItem items[2]; 03109 struct AsnEncodeTagSwappedItem swapped[2]; 03110 DWORD cItem = 0, cSwapped = 0; 03111 03112 if (info->fRequireExplicitPolicy) 03113 { 03114 swapped[cSwapped].tag = ASN_CONTEXT | 0; 03115 swapped[cSwapped].pvStructInfo = 03116 &info->dwRequireExplicitPolicySkipCerts; 03117 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 03118 items[cItem].pvStructInfo = &swapped[cSwapped]; 03119 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03120 cSwapped++; 03121 cItem++; 03122 } 03123 if (info->fInhibitPolicyMapping) 03124 { 03125 swapped[cSwapped].tag = ASN_CONTEXT | 1; 03126 swapped[cSwapped].pvStructInfo = 03127 &info->dwInhibitPolicyMappingSkipCerts; 03128 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 03129 items[cItem].pvStructInfo = &swapped[cSwapped]; 03130 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03131 cSwapped++; 03132 cItem++; 03133 } 03134 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 03135 dwFlags, NULL, pbEncoded, pcbEncoded); 03136 } 03137 __EXCEPT_PAGE_FAULT 03138 { 03139 SetLastError(STATUS_ACCESS_VIOLATION); 03140 } 03141 __ENDTRY 03142 return ret; 03143 } 03144 03145 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType, 03146 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03147 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03148 { 03149 BOOL ret; 03150 03151 __TRY 03152 { 03153 const BLOBHEADER *hdr = pvStructInfo; 03154 03155 if (hdr->bType != PUBLICKEYBLOB) 03156 { 03157 SetLastError(E_INVALIDARG); 03158 ret = FALSE; 03159 } 03160 else 03161 { 03162 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *) 03163 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER)); 03164 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8, 03165 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) }; 03166 struct AsnEncodeSequenceItem items[] = { 03167 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 }, 03168 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 }, 03169 }; 03170 03171 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 03172 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 03173 pcbEncoded); 03174 } 03175 } 03176 __EXCEPT_PAGE_FAULT 03177 { 03178 SetLastError(STATUS_ACCESS_VIOLATION); 03179 ret = FALSE; 03180 } 03181 __ENDTRY 03182 return ret; 03183 } 03184 03185 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType, 03186 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03187 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03188 { 03189 BOOL ret; 03190 03191 __TRY 03192 { 03193 const CRYPT_DATA_BLOB *blob = pvStructInfo; 03194 DWORD bytesNeeded, lenBytes; 03195 03196 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData, 03197 dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0); 03198 03199 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes); 03200 bytesNeeded = 1 + lenBytes + blob->cbData; 03201 if (!pbEncoded) 03202 { 03203 *pcbEncoded = bytesNeeded; 03204 ret = TRUE; 03205 } 03206 else 03207 { 03208 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 03209 pcbEncoded, bytesNeeded))) 03210 { 03211 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03212 pbEncoded = *(BYTE **)pbEncoded; 03213 *pbEncoded++ = ASN_OCTETSTRING; 03214 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes); 03215 pbEncoded += lenBytes; 03216 if (blob->cbData) 03217 memcpy(pbEncoded, blob->pbData, blob->cbData); 03218 } 03219 } 03220 } 03221 __EXCEPT_PAGE_FAULT 03222 { 03223 SetLastError(STATUS_ACCESS_VIOLATION); 03224 ret = FALSE; 03225 } 03226 __ENDTRY 03227 TRACE("returning %d (%08x)\n", ret, GetLastError()); 03228 return ret; 03229 } 03230 03231 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, 03232 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03233 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03234 { 03235 BOOL ret; 03236 03237 __TRY 03238 { 03239 const CRYPT_BIT_BLOB *blob = pvStructInfo; 03240 DWORD bytesNeeded, lenBytes, dataBytes; 03241 BYTE unusedBits; 03242 03243 /* yep, MS allows cUnusedBits to be >= 8 */ 03244 if (!blob->cUnusedBits) 03245 { 03246 dataBytes = blob->cbData; 03247 unusedBits = 0; 03248 } 03249 else if (blob->cbData * 8 > blob->cUnusedBits) 03250 { 03251 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1; 03252 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 : 03253 blob->cUnusedBits; 03254 } 03255 else 03256 { 03257 dataBytes = 0; 03258 unusedBits = 0; 03259 } 03260 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes); 03261 bytesNeeded = 1 + lenBytes + dataBytes + 1; 03262 if (!pbEncoded) 03263 { 03264 *pcbEncoded = bytesNeeded; 03265 ret = TRUE; 03266 } 03267 else 03268 { 03269 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 03270 pcbEncoded, bytesNeeded))) 03271 { 03272 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03273 pbEncoded = *(BYTE **)pbEncoded; 03274 *pbEncoded++ = ASN_BITSTRING; 03275 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes); 03276 pbEncoded += lenBytes; 03277 *pbEncoded++ = unusedBits; 03278 if (dataBytes) 03279 { 03280 BYTE mask = 0xff << unusedBits; 03281 03282 if (dataBytes > 1) 03283 { 03284 memcpy(pbEncoded, blob->pbData, dataBytes - 1); 03285 pbEncoded += dataBytes - 1; 03286 } 03287 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask; 03288 } 03289 } 03290 } 03291 } 03292 __EXCEPT_PAGE_FAULT 03293 { 03294 SetLastError(STATUS_ACCESS_VIOLATION); 03295 ret = FALSE; 03296 } 03297 __ENDTRY 03298 return ret; 03299 } 03300 03301 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType, 03302 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03303 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03304 { 03305 BOOL ret; 03306 03307 __TRY 03308 { 03309 const CRYPT_BIT_BLOB *blob = pvStructInfo; 03310 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits }; 03311 03312 ret = TRUE; 03313 if (newBlob.cbData) 03314 { 03315 newBlob.pbData = CryptMemAlloc(newBlob.cbData); 03316 if (newBlob.pbData) 03317 { 03318 DWORD i; 03319 03320 for (i = 0; i < newBlob.cbData; i++) 03321 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i]; 03322 } 03323 else 03324 ret = FALSE; 03325 } 03326 if (ret) 03327 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType, 03328 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 03329 CryptMemFree(newBlob.pbData); 03330 } 03331 __EXCEPT_PAGE_FAULT 03332 { 03333 SetLastError(STATUS_ACCESS_VIOLATION); 03334 ret = FALSE; 03335 } 03336 __ENDTRY 03337 return ret; 03338 } 03339 03340 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, 03341 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03342 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03343 { 03344 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo }; 03345 03346 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER, 03347 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 03348 } 03349 03350 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, 03351 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03352 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03353 { 03354 BOOL ret; 03355 03356 __TRY 03357 { 03358 DWORD significantBytes, lenBytes, bytesNeeded; 03359 BYTE padByte = 0; 03360 BOOL pad = FALSE; 03361 const CRYPT_INTEGER_BLOB *blob = pvStructInfo; 03362 03363 significantBytes = blob->cbData; 03364 if (significantBytes) 03365 { 03366 if (blob->pbData[significantBytes - 1] & 0x80) 03367 { 03368 /* negative, lop off leading (little-endian) 0xffs */ 03369 for (; significantBytes > 0 && 03370 blob->pbData[significantBytes - 1] == 0xff; significantBytes--) 03371 ; 03372 if (blob->pbData[significantBytes - 1] < 0x80) 03373 { 03374 padByte = 0xff; 03375 pad = TRUE; 03376 } 03377 } 03378 else 03379 { 03380 /* positive, lop off leading (little-endian) zeroes */ 03381 for (; significantBytes > 0 && 03382 !blob->pbData[significantBytes - 1]; significantBytes--) 03383 ; 03384 if (significantBytes == 0) 03385 significantBytes = 1; 03386 if (blob->pbData[significantBytes - 1] > 0x7f) 03387 { 03388 padByte = 0; 03389 pad = TRUE; 03390 } 03391 } 03392 } 03393 if (pad) 03394 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); 03395 else 03396 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); 03397 bytesNeeded = 1 + lenBytes + significantBytes; 03398 if (pad) 03399 bytesNeeded++; 03400 if (!pbEncoded) 03401 { 03402 *pcbEncoded = bytesNeeded; 03403 ret = TRUE; 03404 } 03405 else 03406 { 03407 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 03408 pcbEncoded, bytesNeeded))) 03409 { 03410 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03411 pbEncoded = *(BYTE **)pbEncoded; 03412 *pbEncoded++ = ASN_INTEGER; 03413 if (pad) 03414 { 03415 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); 03416 pbEncoded += lenBytes; 03417 *pbEncoded++ = padByte; 03418 } 03419 else 03420 { 03421 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); 03422 pbEncoded += lenBytes; 03423 } 03424 for (; significantBytes > 0; significantBytes--) 03425 *(pbEncoded++) = blob->pbData[significantBytes - 1]; 03426 } 03427 } 03428 } 03429 __EXCEPT_PAGE_FAULT 03430 { 03431 SetLastError(STATUS_ACCESS_VIOLATION); 03432 ret = FALSE; 03433 } 03434 __ENDTRY 03435 return ret; 03436 } 03437 03438 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, 03439 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03440 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03441 { 03442 BOOL ret; 03443 03444 __TRY 03445 { 03446 DWORD significantBytes, lenBytes, bytesNeeded; 03447 BOOL pad = FALSE; 03448 const CRYPT_INTEGER_BLOB *blob = pvStructInfo; 03449 03450 significantBytes = blob->cbData; 03451 if (significantBytes) 03452 { 03453 /* positive, lop off leading (little-endian) zeroes */ 03454 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1]; 03455 significantBytes--) 03456 ; 03457 if (significantBytes == 0) 03458 significantBytes = 1; 03459 if (blob->pbData[significantBytes - 1] > 0x7f) 03460 pad = TRUE; 03461 } 03462 if (pad) 03463 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); 03464 else 03465 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); 03466 bytesNeeded = 1 + lenBytes + significantBytes; 03467 if (pad) 03468 bytesNeeded++; 03469 if (!pbEncoded) 03470 { 03471 *pcbEncoded = bytesNeeded; 03472 ret = TRUE; 03473 } 03474 else 03475 { 03476 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 03477 pcbEncoded, bytesNeeded))) 03478 { 03479 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03480 pbEncoded = *(BYTE **)pbEncoded; 03481 *pbEncoded++ = ASN_INTEGER; 03482 if (pad) 03483 { 03484 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); 03485 pbEncoded += lenBytes; 03486 *pbEncoded++ = 0; 03487 } 03488 else 03489 { 03490 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); 03491 pbEncoded += lenBytes; 03492 } 03493 for (; significantBytes > 0; significantBytes--) 03494 *(pbEncoded++) = blob->pbData[significantBytes - 1]; 03495 } 03496 } 03497 } 03498 __EXCEPT_PAGE_FAULT 03499 { 03500 SetLastError(STATUS_ACCESS_VIOLATION); 03501 ret = FALSE; 03502 } 03503 __ENDTRY 03504 return ret; 03505 } 03506 03507 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType, 03508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03510 { 03511 CRYPT_INTEGER_BLOB blob; 03512 BOOL ret; 03513 03514 /* Encode as an unsigned integer, then change the tag to enumerated */ 03515 blob.cbData = sizeof(DWORD); 03516 blob.pbData = (BYTE *)pvStructInfo; 03517 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType, 03518 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 03519 if (ret && pbEncoded) 03520 { 03521 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03522 pbEncoded = *(BYTE **)pbEncoded; 03523 pbEncoded[0] = ASN_ENUMERATED; 03524 } 03525 return ret; 03526 } 03527 03528 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType, 03529 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03530 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03531 { 03532 BOOL ret; 03533 03534 __TRY 03535 { 03536 SYSTEMTIME sysTime; 03537 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a 03538 * temporary buffer because the output buffer is not NULL-terminated. 03539 */ 03540 char buf[16]; 03541 static const DWORD bytesNeeded = sizeof(buf) - 1; 03542 03543 if (!pbEncoded) 03544 { 03545 *pcbEncoded = bytesNeeded; 03546 ret = TRUE; 03547 } 03548 else 03549 { 03550 /* Sanity check the year, this is a two-digit year format */ 03551 ret = FileTimeToSystemTime(pvStructInfo, &sysTime); 03552 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050)) 03553 { 03554 SetLastError(CRYPT_E_BAD_ENCODE); 03555 ret = FALSE; 03556 } 03557 if (ret) 03558 { 03559 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 03560 pbEncoded, pcbEncoded, bytesNeeded))) 03561 { 03562 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03563 pbEncoded = *(BYTE **)pbEncoded; 03564 buf[0] = ASN_UTCTIME; 03565 buf[1] = bytesNeeded - 2; 03566 snprintf(buf + 2, sizeof(buf) - 2, 03567 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ? 03568 sysTime.wYear - 2000 : sysTime.wYear - 1900, 03569 sysTime.wMonth, sysTime.wDay, sysTime.wHour, 03570 sysTime.wMinute, sysTime.wSecond); 03571 memcpy(pbEncoded, buf, bytesNeeded); 03572 } 03573 } 03574 } 03575 } 03576 __EXCEPT_PAGE_FAULT 03577 { 03578 SetLastError(STATUS_ACCESS_VIOLATION); 03579 ret = FALSE; 03580 } 03581 __ENDTRY 03582 return ret; 03583 } 03584 03585 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType, 03586 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03587 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03588 { 03589 BOOL ret; 03590 03591 __TRY 03592 { 03593 SYSTEMTIME sysTime; 03594 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a 03595 * temporary buffer because the output buffer is not NULL-terminated. 03596 */ 03597 char buf[18]; 03598 static const DWORD bytesNeeded = sizeof(buf) - 1; 03599 03600 if (!pbEncoded) 03601 { 03602 *pcbEncoded = bytesNeeded; 03603 ret = TRUE; 03604 } 03605 else 03606 { 03607 ret = FileTimeToSystemTime(pvStructInfo, &sysTime); 03608 if (ret) 03609 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 03610 pcbEncoded, bytesNeeded); 03611 if (ret) 03612 { 03613 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03614 pbEncoded = *(BYTE **)pbEncoded; 03615 buf[0] = ASN_GENERALTIME; 03616 buf[1] = bytesNeeded - 2; 03617 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ", 03618 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, 03619 sysTime.wMinute, sysTime.wSecond); 03620 memcpy(pbEncoded, buf, bytesNeeded); 03621 } 03622 } 03623 } 03624 __EXCEPT_PAGE_FAULT 03625 { 03626 SetLastError(STATUS_ACCESS_VIOLATION); 03627 ret = FALSE; 03628 } 03629 __ENDTRY 03630 return ret; 03631 } 03632 03633 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, 03634 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03635 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03636 { 03637 BOOL ret; 03638 03639 __TRY 03640 { 03641 SYSTEMTIME sysTime; 03642 03643 /* Check the year, if it's in the UTCTime range call that encode func */ 03644 if (!FileTimeToSystemTime(pvStructInfo, &sysTime)) 03645 return FALSE; 03646 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050) 03647 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType, 03648 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 03649 else 03650 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType, 03651 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded, 03652 pcbEncoded); 03653 } 03654 __EXCEPT_PAGE_FAULT 03655 { 03656 SetLastError(STATUS_ACCESS_VIOLATION); 03657 ret = FALSE; 03658 } 03659 __ENDTRY 03660 return ret; 03661 } 03662 03663 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, 03664 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03665 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03666 { 03667 BOOL ret; 03668 03669 __TRY 03670 { 03671 DWORD bytesNeeded, dataLen, lenBytes, i; 03672 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo; 03673 03674 for (i = 0, dataLen = 0; i < seq->cValue; i++) 03675 dataLen += seq->rgValue[i].cbData; 03676 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 03677 bytesNeeded = 1 + lenBytes + dataLen; 03678 if (!pbEncoded) 03679 { 03680 *pcbEncoded = bytesNeeded; 03681 ret = TRUE; 03682 } 03683 else 03684 { 03685 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 03686 pcbEncoded, bytesNeeded))) 03687 { 03688 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03689 pbEncoded = *(BYTE **)pbEncoded; 03690 *pbEncoded++ = ASN_SEQUENCEOF; 03691 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 03692 pbEncoded += lenBytes; 03693 for (i = 0; i < seq->cValue; i++) 03694 { 03695 memcpy(pbEncoded, seq->rgValue[i].pbData, 03696 seq->rgValue[i].cbData); 03697 pbEncoded += seq->rgValue[i].cbData; 03698 } 03699 } 03700 } 03701 } 03702 __EXCEPT_PAGE_FAULT 03703 { 03704 SetLastError(STATUS_ACCESS_VIOLATION); 03705 ret = FALSE; 03706 } 03707 __ENDTRY 03708 return ret; 03709 } 03710 03711 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint, 03712 BYTE *pbEncoded, DWORD *pcbEncoded) 03713 { 03714 BOOL ret = TRUE; 03715 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 03716 struct AsnConstructedItem constructed = { 0 }; 03717 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 03718 DWORD cItem = 0, cSwapped = 0; 03719 03720 switch (distPoint->DistPointName.dwDistPointNameChoice) 03721 { 03722 case CRL_DIST_POINT_NO_NAME: 03723 /* do nothing */ 03724 break; 03725 case CRL_DIST_POINT_FULL_NAME: 03726 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 03727 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName; 03728 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 03729 constructed.tag = 0; 03730 constructed.pvStructInfo = &swapped[cSwapped]; 03731 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag; 03732 items[cItem].pvStructInfo = &constructed; 03733 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 03734 cSwapped++; 03735 cItem++; 03736 break; 03737 case CRL_DIST_POINT_ISSUER_RDN_NAME: 03738 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n"); 03739 ret = FALSE; 03740 break; 03741 default: 03742 ret = FALSE; 03743 } 03744 if (ret && distPoint->ReasonFlags.cbData) 03745 { 03746 swapped[cSwapped].tag = ASN_CONTEXT | 1; 03747 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags; 03748 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 03749 items[cItem].pvStructInfo = &swapped[cSwapped]; 03750 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03751 cSwapped++; 03752 cItem++; 03753 } 03754 if (ret && distPoint->CRLIssuer.cAltEntry) 03755 { 03756 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2; 03757 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer; 03758 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 03759 items[cItem].pvStructInfo = &swapped[cSwapped]; 03760 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03761 cSwapped++; 03762 cItem++; 03763 } 03764 if (ret) 03765 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, 03766 pbEncoded, pcbEncoded); 03767 return ret; 03768 } 03769 03770 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType, 03771 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03772 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03773 { 03774 BOOL ret; 03775 03776 __TRY 03777 { 03778 const CRL_DIST_POINTS_INFO *info = pvStructInfo; 03779 03780 if (!info->cDistPoint) 03781 { 03782 SetLastError(E_INVALIDARG); 03783 ret = FALSE; 03784 } 03785 else 03786 { 03787 DWORD bytesNeeded, dataLen, lenBytes, i; 03788 03789 ret = TRUE; 03790 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++) 03791 { 03792 DWORD len; 03793 03794 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL, 03795 &len); 03796 if (ret) 03797 dataLen += len; 03798 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING) 03799 { 03800 /* Have to propagate index of failing character */ 03801 *pcbEncoded = len; 03802 } 03803 } 03804 if (ret) 03805 { 03806 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 03807 bytesNeeded = 1 + lenBytes + dataLen; 03808 if (!pbEncoded) 03809 { 03810 *pcbEncoded = bytesNeeded; 03811 ret = TRUE; 03812 } 03813 else 03814 { 03815 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 03816 pbEncoded, pcbEncoded, bytesNeeded))) 03817 { 03818 BYTE *out; 03819 03820 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03821 pbEncoded = *(BYTE **)pbEncoded; 03822 out = pbEncoded; 03823 *out++ = ASN_SEQUENCEOF; 03824 CRYPT_EncodeLen(dataLen, out, &lenBytes); 03825 out += lenBytes; 03826 for (i = 0; ret && i < info->cDistPoint; i++) 03827 { 03828 DWORD len = dataLen; 03829 03830 ret = CRYPT_AsnEncodeDistPoint( 03831 &info->rgDistPoint[i], out, &len); 03832 if (ret) 03833 { 03834 out += len; 03835 dataLen -= len; 03836 } 03837 } 03838 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 03839 CRYPT_FreeSpace(pEncodePara, pbEncoded); 03840 } 03841 } 03842 } 03843 } 03844 } 03845 __EXCEPT_PAGE_FAULT 03846 { 03847 SetLastError(STATUS_ACCESS_VIOLATION); 03848 ret = FALSE; 03849 } 03850 __ENDTRY 03851 return ret; 03852 } 03853 03854 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType, 03855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03857 { 03858 BOOL ret; 03859 03860 __TRY 03861 { 03862 const CERT_ENHKEY_USAGE *usage = pvStructInfo; 03863 DWORD bytesNeeded = 0, lenBytes, size, i; 03864 03865 ret = TRUE; 03866 for (i = 0; ret && i < usage->cUsageIdentifier; i++) 03867 { 03868 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 03869 usage->rgpszUsageIdentifier[i], 03870 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size); 03871 if (ret) 03872 bytesNeeded += size; 03873 } 03874 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 03875 bytesNeeded += 1 + lenBytes; 03876 if (ret) 03877 { 03878 if (!pbEncoded) 03879 *pcbEncoded = bytesNeeded; 03880 else 03881 { 03882 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 03883 pbEncoded, pcbEncoded, bytesNeeded))) 03884 { 03885 BYTE *out; 03886 03887 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 03888 pbEncoded = *(BYTE **)pbEncoded; 03889 out = pbEncoded; 03890 *out++ = ASN_SEQUENCEOF; 03891 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 03892 out += lenBytes; 03893 for (i = 0; ret && i < usage->cUsageIdentifier; i++) 03894 { 03895 size = bytesNeeded; 03896 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 03897 usage->rgpszUsageIdentifier[i], 03898 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size); 03899 if (ret) 03900 { 03901 out += size; 03902 bytesNeeded -= size; 03903 } 03904 } 03905 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 03906 CRYPT_FreeSpace(pEncodePara, pbEncoded); 03907 } 03908 } 03909 } 03910 } 03911 __EXCEPT_PAGE_FAULT 03912 { 03913 SetLastError(STATUS_ACCESS_VIOLATION); 03914 ret = FALSE; 03915 } 03916 __ENDTRY 03917 return ret; 03918 } 03919 03920 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType, 03921 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 03922 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 03923 { 03924 BOOL ret; 03925 03926 __TRY 03927 { 03928 const CRL_ISSUING_DIST_POINT *point = pvStructInfo; 03929 struct AsnEncodeSequenceItem items[6] = { { 0 } }; 03930 struct AsnConstructedItem constructed = { 0 }; 03931 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } }; 03932 DWORD cItem = 0, cSwapped = 0; 03933 03934 ret = TRUE; 03935 switch (point->DistPointName.dwDistPointNameChoice) 03936 { 03937 case CRL_DIST_POINT_NO_NAME: 03938 /* do nothing */ 03939 break; 03940 case CRL_DIST_POINT_FULL_NAME: 03941 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 03942 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName; 03943 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 03944 constructed.tag = 0; 03945 constructed.pvStructInfo = &swapped[cSwapped]; 03946 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag; 03947 items[cItem].pvStructInfo = &constructed; 03948 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 03949 cSwapped++; 03950 cItem++; 03951 break; 03952 default: 03953 SetLastError(E_INVALIDARG); 03954 ret = FALSE; 03955 } 03956 if (ret && point->fOnlyContainsUserCerts) 03957 { 03958 swapped[cSwapped].tag = ASN_CONTEXT | 1; 03959 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts; 03960 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 03961 items[cItem].pvStructInfo = &swapped[cSwapped]; 03962 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03963 cSwapped++; 03964 cItem++; 03965 } 03966 if (ret && point->fOnlyContainsCACerts) 03967 { 03968 swapped[cSwapped].tag = ASN_CONTEXT | 2; 03969 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts; 03970 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 03971 items[cItem].pvStructInfo = &swapped[cSwapped]; 03972 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03973 cSwapped++; 03974 cItem++; 03975 } 03976 if (ret && point->OnlySomeReasonFlags.cbData) 03977 { 03978 swapped[cSwapped].tag = ASN_CONTEXT | 3; 03979 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags; 03980 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 03981 items[cItem].pvStructInfo = &swapped[cSwapped]; 03982 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03983 cSwapped++; 03984 cItem++; 03985 } 03986 if (ret && point->fIndirectCRL) 03987 { 03988 swapped[cSwapped].tag = ASN_CONTEXT | 4; 03989 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL; 03990 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 03991 items[cItem].pvStructInfo = &swapped[cSwapped]; 03992 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 03993 cSwapped++; 03994 cItem++; 03995 } 03996 if (ret) 03997 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 03998 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 03999 } 04000 __EXCEPT_PAGE_FAULT 04001 { 04002 SetLastError(STATUS_ACCESS_VIOLATION); 04003 ret = FALSE; 04004 } 04005 __ENDTRY 04006 return ret; 04007 } 04008 04009 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType, 04010 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 04011 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 04012 { 04013 BOOL ret; 04014 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo; 04015 struct AsnEncodeSequenceItem items[3] = { 04016 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 }, 04017 { 0 } 04018 }; 04019 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 04020 DWORD cItem = 1, cSwapped = 0; 04021 04022 if (subtree->dwMinimum) 04023 { 04024 swapped[cSwapped].tag = ASN_CONTEXT | 0; 04025 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum; 04026 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 04027 items[cItem].pvStructInfo = &swapped[cSwapped]; 04028 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04029 cSwapped++; 04030 cItem++; 04031 } 04032 if (subtree->fMaximum) 04033 { 04034 swapped[cSwapped].tag = ASN_CONTEXT | 1; 04035 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum; 04036 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 04037 items[cItem].pvStructInfo = &swapped[cSwapped]; 04038 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04039 cSwapped++; 04040 cItem++; 04041 } 04042 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags, 04043 pEncodePara, pbEncoded, pcbEncoded); 04044 return ret; 04045 } 04046 04047 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType, 04048 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 04049 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 04050 { 04051 BOOL ret = FALSE; 04052 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL }; 04053 04054 TRACE("%p\n", pvStructInfo); 04055 04056 __TRY 04057 { 04058 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo; 04059 struct AsnEncodeSequenceItem items[2] = { { 0 } }; 04060 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 04061 DWORD i, cItem = 0, cSwapped = 0; 04062 04063 ret = TRUE; 04064 if (constraints->cPermittedSubtree) 04065 { 04066 permitted.rgBlob = CryptMemAlloc( 04067 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB)); 04068 if (permitted.rgBlob) 04069 { 04070 permitted.cBlob = constraints->cPermittedSubtree; 04071 memset(permitted.rgBlob, 0, 04072 permitted.cBlob * sizeof(CRYPT_DER_BLOB)); 04073 for (i = 0; ret && i < permitted.cBlob; i++) 04074 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType, 04075 NULL, &constraints->rgPermittedSubtree[i], 04076 CRYPT_ENCODE_ALLOC_FLAG, NULL, 04077 (BYTE *)&permitted.rgBlob[i].pbData, 04078 &permitted.rgBlob[i].cbData); 04079 if (ret) 04080 { 04081 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 04082 swapped[cSwapped].pvStructInfo = &permitted; 04083 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet; 04084 items[cItem].pvStructInfo = &swapped[cSwapped]; 04085 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04086 cSwapped++; 04087 cItem++; 04088 } 04089 } 04090 else 04091 ret = FALSE; 04092 } 04093 if (constraints->cExcludedSubtree) 04094 { 04095 excluded.rgBlob = CryptMemAlloc( 04096 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB)); 04097 if (excluded.rgBlob) 04098 { 04099 excluded.cBlob = constraints->cExcludedSubtree; 04100 memset(excluded.rgBlob, 0, 04101 excluded.cBlob * sizeof(CRYPT_DER_BLOB)); 04102 for (i = 0; ret && i < excluded.cBlob; i++) 04103 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType, 04104 NULL, &constraints->rgExcludedSubtree[i], 04105 CRYPT_ENCODE_ALLOC_FLAG, NULL, 04106 (BYTE *)&excluded.rgBlob[i].pbData, 04107 &excluded.rgBlob[i].cbData); 04108 if (ret) 04109 { 04110 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 04111 swapped[cSwapped].pvStructInfo = &excluded; 04112 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet; 04113 items[cItem].pvStructInfo = &swapped[cSwapped]; 04114 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04115 cSwapped++; 04116 cItem++; 04117 } 04118 } 04119 else 04120 ret = FALSE; 04121 } 04122 if (ret) 04123 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 04124 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 04125 for (i = 0; i < permitted.cBlob; i++) 04126 LocalFree(permitted.rgBlob[i].pbData); 04127 for (i = 0; i < excluded.cBlob; i++) 04128 LocalFree(excluded.rgBlob[i].pbData); 04129 } 04130 __EXCEPT_PAGE_FAULT 04131 { 04132 SetLastError(STATUS_ACCESS_VIOLATION); 04133 } 04134 __ENDTRY 04135 CryptMemFree(permitted.rgBlob); 04136 CryptMemFree(excluded.rgBlob); 04137 TRACE("returning %d\n", ret); 04138 return ret; 04139 } 04140 04141 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber( 04142 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 04143 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 04144 DWORD *pcbEncoded) 04145 { 04146 BOOL ret; 04147 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo; 04148 struct AsnEncodeSequenceItem items[] = { 04149 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 }, 04150 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, 04151 }; 04152 04153 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 04154 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 04155 pcbEncoded); 04156 return ret; 04157 } 04158 04159 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType, 04160 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 04161 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 04162 { 04163 BOOL ret = FALSE; 04164 04165 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING)) 04166 { 04167 SetLastError(E_INVALIDARG); 04168 return FALSE; 04169 } 04170 04171 __TRY 04172 { 04173 const CMSG_SIGNER_INFO *info = pvStructInfo; 04174 04175 if (!info->Issuer.cbData) 04176 SetLastError(E_INVALIDARG); 04177 else 04178 { 04179 struct AsnEncodeSequenceItem items[7] = { 04180 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 04181 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 }, 04182 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 04183 0 }, 04184 }; 04185 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 04186 DWORD cItem = 3, cSwapped = 0; 04187 04188 if (info->AuthAttrs.cAttr) 04189 { 04190 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 04191 swapped[cSwapped].pvStructInfo = &info->AuthAttrs; 04192 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 04193 items[cItem].pvStructInfo = &swapped[cSwapped]; 04194 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04195 cSwapped++; 04196 cItem++; 04197 } 04198 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; 04199 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 04200 cItem++; 04201 items[cItem].pvStructInfo = &info->EncryptedHash; 04202 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 04203 cItem++; 04204 if (info->UnauthAttrs.cAttr) 04205 { 04206 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 04207 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; 04208 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 04209 items[cItem].pvStructInfo = &swapped[cSwapped]; 04210 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04211 cSwapped++; 04212 cItem++; 04213 } 04214 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 04215 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 04216 } 04217 } 04218 __EXCEPT_PAGE_FAULT 04219 { 04220 SetLastError(STATUS_ACCESS_VIOLATION); 04221 } 04222 __ENDTRY 04223 return ret; 04224 } 04225 04226 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType, 04227 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 04228 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 04229 { 04230 BOOL ret = FALSE; 04231 04232 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING)) 04233 { 04234 SetLastError(E_INVALIDARG); 04235 return FALSE; 04236 } 04237 04238 __TRY 04239 { 04240 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo; 04241 04242 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER && 04243 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER) 04244 SetLastError(E_INVALIDARG); 04245 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER && 04246 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData) 04247 SetLastError(E_INVALIDARG); 04248 else 04249 { 04250 struct AsnEncodeSequenceItem items[7] = { 04251 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 04252 }; 04253 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 04254 DWORD cItem = 1, cSwapped = 0; 04255 04256 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 04257 { 04258 items[cItem].pvStructInfo = 04259 &info->SignerId.u.IssuerSerialNumber.Issuer; 04260 items[cItem].encodeFunc = 04261 CRYPT_AsnEncodeIssuerSerialNumber; 04262 cItem++; 04263 } 04264 else 04265 { 04266 swapped[cSwapped].tag = ASN_CONTEXT | 0; 04267 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId; 04268 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 04269 items[cItem].pvStructInfo = &swapped[cSwapped]; 04270 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04271 cSwapped++; 04272 cItem++; 04273 } 04274 items[cItem].pvStructInfo = &info->HashAlgorithm; 04275 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 04276 cItem++; 04277 if (info->AuthAttrs.cAttr) 04278 { 04279 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 04280 swapped[cSwapped].pvStructInfo = &info->AuthAttrs; 04281 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 04282 items[cItem].pvStructInfo = &swapped[cSwapped]; 04283 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04284 cSwapped++; 04285 cItem++; 04286 } 04287 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; 04288 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 04289 cItem++; 04290 items[cItem].pvStructInfo = &info->EncryptedHash; 04291 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 04292 cItem++; 04293 if (info->UnauthAttrs.cAttr) 04294 { 04295 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 04296 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; 04297 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 04298 items[cItem].pvStructInfo = &swapped[cSwapped]; 04299 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04300 cSwapped++; 04301 cItem++; 04302 } 04303 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 04304 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 04305 } 04306 } 04307 __EXCEPT_PAGE_FAULT 04308 { 04309 SetLastError(STATUS_ACCESS_VIOLATION); 04310 } 04311 __ENDTRY 04312 return ret; 04313 } 04314 04315 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData, 04316 DWORD *pcbData) 04317 { 04318 struct AsnEncodeSequenceItem items[7] = { 04319 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 }, 04320 }; 04321 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 }; 04322 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 }; 04323 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 04324 DWORD cItem = 1, cSwapped = 0; 04325 BOOL ret = TRUE; 04326 04327 if (signedInfo->cSignerInfo) 04328 { 04329 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo; 04330 digestAlgorithmsSet.items = signedInfo->rgSignerInfo; 04331 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO); 04332 digestAlgorithmsSet.itemOffset = 04333 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm); 04334 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 04335 items[cItem].pvStructInfo = &digestAlgorithmsSet; 04336 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet; 04337 cItem++; 04338 } 04339 items[cItem].pvStructInfo = &signedInfo->content; 04340 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal; 04341 cItem++; 04342 if (signedInfo->cCertEncoded) 04343 { 04344 certSet.cItems = signedInfo->cCertEncoded; 04345 certSet.items = signedInfo->rgCertEncoded; 04346 certSet.itemSize = sizeof(CERT_BLOB); 04347 certSet.itemOffset = 0; 04348 certSet.encode = CRYPT_CopyEncodedBlob; 04349 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0; 04350 swapped[cSwapped].pvStructInfo = &certSet; 04351 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet; 04352 items[cItem].pvStructInfo = &swapped[cSwapped]; 04353 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04354 cSwapped++; 04355 cItem++; 04356 } 04357 if (signedInfo->cCrlEncoded) 04358 { 04359 crlSet.cItems = signedInfo->cCrlEncoded; 04360 crlSet.items = signedInfo->rgCrlEncoded; 04361 crlSet.itemSize = sizeof(CRL_BLOB); 04362 crlSet.itemOffset = 0; 04363 crlSet.encode = CRYPT_CopyEncodedBlob; 04364 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1; 04365 swapped[cSwapped].pvStructInfo = &crlSet; 04366 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet; 04367 items[cItem].pvStructInfo = &swapped[cSwapped]; 04368 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 04369 cSwapped++; 04370 cItem++; 04371 } 04372 if (ret && signedInfo->cSignerInfo) 04373 { 04374 signerSet.cItems = signedInfo->cSignerInfo; 04375 signerSet.items = signedInfo->rgSignerInfo; 04376 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO); 04377 signerSet.itemOffset = 0; 04378 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo; 04379 items[cItem].pvStructInfo = &signerSet; 04380 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet; 04381 cItem++; 04382 } 04383 if (ret) 04384 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 04385 items, cItem, 0, NULL, pvData, pcbData); 04386 04387 return ret; 04388 } 04389 04390 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType, 04391 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 04392 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 04393 { 04394 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo; 04395 struct AsnEncodeSequenceItem items[] = { 04396 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 04397 { &info->RecipientId.u.IssuerSerialNumber, 04398 CRYPT_AsnEncodeIssuerSerialNumber, 0 }, 04399 { &info->KeyEncryptionAlgorithm, 04400 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 04401 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 }, 04402 }; 04403 04404 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 04405 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 04406 pcbEncoded); 04407 } 04408 04409 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType, 04410 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 04411 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 04412 { 04413 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo; 04414 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0, 04415 &info->encryptedContent, CRYPT_AsnEncodeOctets }; 04416 struct AsnEncodeSequenceItem items[] = { 04417 { info->contentType, CRYPT_AsnEncodeOid, 0 }, 04418 { &info->contentEncryptionAlgorithm, 04419 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 04420 { &swapped, CRYPT_AsnEncodeSwapTag, 0 }, 04421 }; 04422 04423 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 04424 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 04425 pcbEncoded); 04426 } 04427 04428 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData, 04429 void *pvData, DWORD *pcbData) 04430 { 04431 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo, 04432 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0, 04433 CRYPT_AsnEncodeRecipientInfo }; 04434 struct AsnEncodeSequenceItem items[] = { 04435 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 }, 04436 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 }, 04437 { &envelopedData->encryptedContentInfo, 04438 CRYPT_AsnEncodeEncryptedContentInfo, 0 }, 04439 }; 04440 04441 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 04442 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData); 04443 } 04444 04445 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType, 04446 LPCSTR lpszStructType) 04447 { 04448 CryptEncodeObjectExFunc encodeFunc = NULL; 04449 04450 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING 04451 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING) 04452 { 04453 SetLastError(ERROR_FILE_NOT_FOUND); 04454 return NULL; 04455 } 04456 04457 if (IS_INTOID(lpszStructType)) 04458 { 04459 switch (LOWORD(lpszStructType)) 04460 { 04461 case LOWORD(X509_CERT): 04462 encodeFunc = CRYPT_AsnEncodeCert; 04463 break; 04464 case LOWORD(X509_CERT_TO_BE_SIGNED): 04465 encodeFunc = CRYPT_AsnEncodeCertInfo; 04466 break; 04467 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED): 04468 encodeFunc = CRYPT_AsnEncodeCRLInfo; 04469 break; 04470 case LOWORD(X509_EXTENSIONS): 04471 encodeFunc = CRYPT_AsnEncodeExtensions; 04472 break; 04473 case LOWORD(X509_NAME_VALUE): 04474 encodeFunc = CRYPT_AsnEncodeNameValue; 04475 break; 04476 case LOWORD(X509_NAME): 04477 encodeFunc = CRYPT_AsnEncodeName; 04478 break; 04479 case LOWORD(X509_PUBLIC_KEY_INFO): 04480 encodeFunc = CRYPT_AsnEncodePubKeyInfo; 04481 break; 04482 case LOWORD(X509_AUTHORITY_KEY_ID): 04483 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId; 04484 break; 04485 case LOWORD(X509_ALTERNATE_NAME): 04486 encodeFunc = CRYPT_AsnEncodeAltName; 04487 break; 04488 case LOWORD(X509_BASIC_CONSTRAINTS): 04489 encodeFunc = CRYPT_AsnEncodeBasicConstraints; 04490 break; 04491 case LOWORD(X509_BASIC_CONSTRAINTS2): 04492 encodeFunc = CRYPT_AsnEncodeBasicConstraints2; 04493 break; 04494 case LOWORD(X509_CERT_POLICIES): 04495 encodeFunc = CRYPT_AsnEncodeCertPolicies; 04496 break; 04497 case LOWORD(RSA_CSP_PUBLICKEYBLOB): 04498 encodeFunc = CRYPT_AsnEncodeRsaPubKey; 04499 break; 04500 case LOWORD(X509_UNICODE_NAME): 04501 encodeFunc = CRYPT_AsnEncodeUnicodeName; 04502 break; 04503 case LOWORD(PKCS_CONTENT_INFO): 04504 encodeFunc = CRYPT_AsnEncodePKCSContentInfo; 04505 break; 04506 case LOWORD(PKCS_ATTRIBUTE): 04507 encodeFunc = CRYPT_AsnEncodePKCSAttribute; 04508 break; 04509 case LOWORD(X509_UNICODE_NAME_VALUE): 04510 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue; 04511 break; 04512 case LOWORD(X509_OCTET_STRING): 04513 encodeFunc = CRYPT_AsnEncodeOctets; 04514 break; 04515 case LOWORD(X509_BITS): 04516 case LOWORD(X509_KEY_USAGE): 04517 encodeFunc = CRYPT_AsnEncodeBits; 04518 break; 04519 case LOWORD(X509_INTEGER): 04520 encodeFunc = CRYPT_AsnEncodeInt; 04521 break; 04522 case LOWORD(X509_MULTI_BYTE_INTEGER): 04523 encodeFunc = CRYPT_AsnEncodeInteger; 04524 break; 04525 case LOWORD(X509_MULTI_BYTE_UINT): 04526 encodeFunc = CRYPT_AsnEncodeUnsignedInteger; 04527 break; 04528 case LOWORD(X509_ENUMERATED): 04529 encodeFunc = CRYPT_AsnEncodeEnumerated; 04530 break; 04531 case LOWORD(X509_CHOICE_OF_TIME): 04532 encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 04533 break; 04534 case LOWORD(X509_AUTHORITY_KEY_ID2): 04535 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2; 04536 break; 04537 case LOWORD(X509_AUTHORITY_INFO_ACCESS): 04538 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess; 04539 break; 04540 case LOWORD(X509_SEQUENCE_OF_ANY): 04541 encodeFunc = CRYPT_AsnEncodeSequenceOfAny; 04542 break; 04543 case LOWORD(PKCS_UTC_TIME): 04544 encodeFunc = CRYPT_AsnEncodeUtcTime; 04545 break; 04546 case LOWORD(X509_CRL_DIST_POINTS): 04547 encodeFunc = CRYPT_AsnEncodeCRLDistPoints; 04548 break; 04549 case LOWORD(X509_ENHANCED_KEY_USAGE): 04550 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage; 04551 break; 04552 case LOWORD(PKCS_CTL): 04553 encodeFunc = CRYPT_AsnEncodeCTL; 04554 break; 04555 case LOWORD(PKCS_SMIME_CAPABILITIES): 04556 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities; 04557 break; 04558 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE): 04559 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice; 04560 break; 04561 case LOWORD(PKCS_ATTRIBUTES): 04562 encodeFunc = CRYPT_AsnEncodePKCSAttributes; 04563 break; 04564 case LOWORD(X509_ISSUING_DIST_POINT): 04565 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint; 04566 break; 04567 case LOWORD(X509_NAME_CONSTRAINTS): 04568 encodeFunc = CRYPT_AsnEncodeNameConstraints; 04569 break; 04570 case LOWORD(X509_POLICY_MAPPINGS): 04571 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 04572 break; 04573 case LOWORD(X509_POLICY_CONSTRAINTS): 04574 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints; 04575 break; 04576 case LOWORD(PKCS7_SIGNER_INFO): 04577 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo; 04578 break; 04579 case LOWORD(CMS_SIGNER_INFO): 04580 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo; 04581 break; 04582 } 04583 } 04584 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS)) 04585 encodeFunc = CRYPT_AsnEncodeExtensions; 04586 else if (!strcmp(lpszStructType, szOID_RSA_signingTime)) 04587 encodeFunc = CRYPT_AsnEncodeUtcTime; 04588 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities)) 04589 encodeFunc = CRYPT_AsnEncodeUtcTime; 04590 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER)) 04591 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId; 04592 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS)) 04593 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 04594 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2)) 04595 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2; 04596 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE)) 04597 encodeFunc = CRYPT_AsnEncodeEnumerated; 04598 else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) 04599 encodeFunc = CRYPT_AsnEncodeBits; 04600 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER)) 04601 encodeFunc = CRYPT_AsnEncodeOctets; 04602 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS)) 04603 encodeFunc = CRYPT_AsnEncodeBasicConstraints; 04604 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) 04605 encodeFunc = CRYPT_AsnEncodeBasicConstraints2; 04606 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) 04607 encodeFunc = CRYPT_AsnEncodeAltName; 04608 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) 04609 encodeFunc = CRYPT_AsnEncodeAltName; 04610 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION)) 04611 encodeFunc = CRYPT_AsnEncodeAltName; 04612 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) 04613 encodeFunc = CRYPT_AsnEncodeAltName; 04614 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) 04615 encodeFunc = CRYPT_AsnEncodeAltName; 04616 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS)) 04617 encodeFunc = CRYPT_AsnEncodeCRLDistPoints; 04618 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES)) 04619 encodeFunc = CRYPT_AsnEncodeCertPolicies; 04620 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS)) 04621 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 04622 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS)) 04623 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints; 04624 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE)) 04625 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage; 04626 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT)) 04627 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint; 04628 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS)) 04629 encodeFunc = CRYPT_AsnEncodeNameConstraints; 04630 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS)) 04631 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess; 04632 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) 04633 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice; 04634 else if (!strcmp(lpszStructType, szOID_CTL)) 04635 encodeFunc = CRYPT_AsnEncodeCTL; 04636 return encodeFunc; 04637 } 04638 04639 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType, 04640 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) 04641 { 04642 static HCRYPTOIDFUNCSET set = NULL; 04643 CryptEncodeObjectFunc encodeFunc = NULL; 04644 04645 if (!set) 04646 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0); 04647 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, 04648 (void **)&encodeFunc, hFunc); 04649 return encodeFunc; 04650 } 04651 04652 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType, 04653 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) 04654 { 04655 static HCRYPTOIDFUNCSET set = NULL; 04656 CryptEncodeObjectExFunc encodeFunc = NULL; 04657 04658 if (!set) 04659 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0); 04660 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, 04661 (void **)&encodeFunc, hFunc); 04662 return encodeFunc; 04663 } 04664 04665 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType, 04666 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded) 04667 { 04668 BOOL ret = FALSE; 04669 HCRYPTOIDFUNCADDR hFunc = NULL; 04670 CryptEncodeObjectFunc pCryptEncodeObject = NULL; 04671 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL; 04672 04673 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 04674 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, 04675 pcbEncoded); 04676 04677 if (!pbEncoded && !pcbEncoded) 04678 { 04679 SetLastError(ERROR_INVALID_PARAMETER); 04680 return FALSE; 04681 } 04682 04683 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType, 04684 lpszStructType))) 04685 { 04686 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", 04687 debugstr_a(lpszStructType)); 04688 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType, 04689 lpszStructType, &hFunc); 04690 if (!pCryptEncodeObject) 04691 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType, 04692 lpszStructType, &hFunc); 04693 } 04694 if (pCryptEncodeObject) 04695 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 04696 pvStructInfo, pbEncoded, pcbEncoded); 04697 else if (pCryptEncodeObjectEx) 04698 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType, 04699 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded); 04700 if (hFunc) 04701 CryptFreeOIDFunctionAddress(hFunc, 0); 04702 TRACE_(crypt)("returning %d\n", ret); 04703 return ret; 04704 } 04705 04706 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, 04707 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, 04708 void *pvEncoded, DWORD *pcbEncoded) 04709 { 04710 BOOL ret = FALSE; 04711 HCRYPTOIDFUNCADDR hFunc = NULL; 04712 CryptEncodeObjectExFunc encodeFunc = NULL; 04713 04714 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType, 04715 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara, 04716 pvEncoded, pcbEncoded); 04717 04718 if (!pvEncoded && !pcbEncoded) 04719 { 04720 SetLastError(ERROR_INVALID_PARAMETER); 04721 return FALSE; 04722 } 04723 04724 SetLastError(NOERROR); 04725 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) { 04726 if (!pvEncoded) { 04727 SetLastError(ERROR_INVALID_PARAMETER); 04728 return FALSE; 04729 } 04730 *(BYTE **)pvEncoded = NULL; 04731 } 04732 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType); 04733 if (!encodeFunc) 04734 { 04735 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", 04736 debugstr_a(lpszStructType)); 04737 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType, 04738 &hFunc); 04739 } 04740 if (encodeFunc) 04741 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo, 04742 dwFlags, pEncodePara, pvEncoded, pcbEncoded); 04743 else 04744 { 04745 CryptEncodeObjectFunc pCryptEncodeObject = 04746 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc); 04747 04748 if (pCryptEncodeObject) 04749 { 04750 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 04751 { 04752 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 04753 pvStructInfo, NULL, pcbEncoded); 04754 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 04755 pvEncoded, pcbEncoded, *pcbEncoded))) 04756 ret = pCryptEncodeObject(dwCertEncodingType, 04757 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded, 04758 pcbEncoded); 04759 } 04760 else 04761 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 04762 pvStructInfo, pvEncoded, pcbEncoded); 04763 } 04764 } 04765 if (hFunc) 04766 CryptFreeOIDFunctionAddress(hFunc, 0); 04767 TRACE_(crypt)("returning %d\n", ret); 04768 return ret; 04769 } 04770 04771 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX, 04772 LPCWSTR szPassword, DWORD dwFlags) 04773 { 04774 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags); 04775 } 04776 04777 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX, 04778 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags) 04779 { 04780 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword, 04781 pvReserved, dwFlags); 04782 return FALSE; 04783 } 04784 04785 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec, 04786 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 04787 { 04788 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType, 04789 NULL, 0, NULL, pInfo, pcbInfo); 04790 } 04791 04792 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 04793 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, 04794 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 04795 { 04796 BOOL ret; 04797 HCRYPTKEY key; 04798 static CHAR oid[] = szOID_RSA_RSA; 04799 04800 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv, 04801 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, 04802 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0); 04803 04804 if (!pszPublicKeyObjId) 04805 pszPublicKeyObjId = oid; 04806 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key))) 04807 { 04808 DWORD keySize = 0; 04809 04810 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize); 04811 if (ret) 04812 { 04813 LPBYTE pubKey = CryptMemAlloc(keySize); 04814 04815 if (pubKey) 04816 { 04817 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey, 04818 &keySize); 04819 if (ret) 04820 { 04821 DWORD encodedLen = 0; 04822 04823 ret = CryptEncodeObject(dwCertEncodingType, 04824 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen); 04825 if (ret) 04826 { 04827 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) + 04828 strlen(pszPublicKeyObjId) + 1 + encodedLen; 04829 04830 if (!pInfo) 04831 *pcbInfo = sizeNeeded; 04832 else if (*pcbInfo < sizeNeeded) 04833 { 04834 SetLastError(ERROR_MORE_DATA); 04835 *pcbInfo = sizeNeeded; 04836 ret = FALSE; 04837 } 04838 else 04839 { 04840 *pcbInfo = sizeNeeded; 04841 pInfo->Algorithm.pszObjId = (char *)pInfo + 04842 sizeof(CERT_PUBLIC_KEY_INFO); 04843 lstrcpyA(pInfo->Algorithm.pszObjId, 04844 pszPublicKeyObjId); 04845 pInfo->Algorithm.Parameters.cbData = 0; 04846 pInfo->Algorithm.Parameters.pbData = NULL; 04847 pInfo->PublicKey.pbData = 04848 (BYTE *)pInfo->Algorithm.pszObjId 04849 + lstrlenA(pInfo->Algorithm.pszObjId) + 1; 04850 pInfo->PublicKey.cbData = encodedLen; 04851 pInfo->PublicKey.cUnusedBits = 0; 04852 ret = CryptEncodeObject(dwCertEncodingType, 04853 RSA_CSP_PUBLICKEYBLOB, pubKey, 04854 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData); 04855 } 04856 } 04857 } 04858 CryptMemFree(pubKey); 04859 } 04860 else 04861 ret = FALSE; 04862 } 04863 CryptDestroyKey(key); 04864 } 04865 return ret; 04866 } 04867 04868 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 04869 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, 04870 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo); 04871 04872 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec, 04873 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags, 04874 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 04875 { 04876 static HCRYPTOIDFUNCSET set = NULL; 04877 BOOL ret; 04878 ExportPublicKeyInfoExFunc exportFunc = NULL; 04879 HCRYPTOIDFUNCADDR hFunc = NULL; 04880 04881 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv, 04882 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, 04883 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0); 04884 04885 if (!hCryptProv) 04886 { 04887 SetLastError(ERROR_INVALID_PARAMETER); 04888 return FALSE; 04889 } 04890 04891 if (pszPublicKeyObjId) 04892 { 04893 if (!set) 04894 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC, 04895 0); 04896 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId, 04897 0, (void **)&exportFunc, &hFunc); 04898 } 04899 if (!exportFunc) 04900 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx; 04901 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType, 04902 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo); 04903 if (hFunc) 04904 CryptFreeOIDFunctionAddress(hFunc, 0); 04905 return ret; 04906 } 04907 04908 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv, 04909 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) 04910 { 04911 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo, 04912 0, 0, NULL, phKey); 04913 } 04914 04915 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv, 04916 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 04917 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) 04918 { 04919 BOOL ret; 04920 DWORD pubKeySize = 0; 04921 04922 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv, 04923 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); 04924 04925 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 04926 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize); 04927 if (ret) 04928 { 04929 LPBYTE pubKey = CryptMemAlloc(pubKeySize); 04930 04931 if (pubKey) 04932 { 04933 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 04934 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey, 04935 &pubKeySize); 04936 if (ret) 04937 { 04938 if(aiKeyAlg) 04939 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg; 04940 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, 04941 phKey); 04942 } 04943 CryptMemFree(pubKey); 04944 } 04945 else 04946 ret = FALSE; 04947 } 04948 return ret; 04949 } 04950 04951 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv, 04952 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 04953 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey); 04954 04955 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv, 04956 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 04957 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) 04958 { 04959 static HCRYPTOIDFUNCSET set = NULL; 04960 BOOL ret; 04961 ImportPublicKeyInfoExFunc importFunc = NULL; 04962 HCRYPTOIDFUNCADDR hFunc = NULL; 04963 04964 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv, 04965 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); 04966 04967 if (!set) 04968 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0); 04969 CryptGetOIDFunctionAddress(set, dwCertEncodingType, 04970 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc); 04971 if (!importFunc) 04972 importFunc = CRYPT_ImportRsaPublicKeyInfoEx; 04973 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, 04974 pvAuxInfo, phKey); 04975 if (hFunc) 04976 CryptFreeOIDFunctionAddress(hFunc, 0); 04977 return ret; 04978 } Generated on Sun May 27 2012 04:23:14 for ReactOS by
1.7.6.1
|