1 /* 2 * Copyright 2005-2008 Juan Lang 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 * 18 * This file implements ASN.1 DER encoding of a limited set of types. 19 * It isn't a full ASN.1 implementation. Microsoft implements BER 20 * encoding of many of the basic types in msasn1.dll, but that interface isn't 21 * implemented, so I implement them here. 22 * 23 * References: 24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski 25 * (available online, look for a PDF copy as the HTML versions tend to have 26 * translation errors.) 27 * 28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html 29 * 30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject" 31 */ 32 33 #include "config.h" 34 #include "wine/port.h" 35 36 #include <assert.h> 37 #include <stdarg.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 41 #define NONAMELESSUNION 42 43 #include "windef.h" 44 #include "winbase.h" 45 #include "wincrypt.h" 46 #include "snmp.h" 47 #include "wine/debug.h" 48 #include "wine/exception.h" 49 #include "wine/unicode.h" 50 #include "crypt32_private.h" 51 52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn); 53 WINE_DECLARE_DEBUG_CHANNEL(crypt); 54 55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *, 56 BYTE *, DWORD *); 57 58 /* Prototypes for built-in encoders. They follow the Ex style prototypes. 59 * The dwCertEncodingType and lpszStructType are ignored by the built-in 60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx, 61 * since it must call functions in external DLLs that follow these signatures. 62 */ 63 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType, 64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 66 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType, 67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 69 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, 70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 72 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, 73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 75 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType, 76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 78 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, 79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 81 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType, 82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 84 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, 85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 87 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, 88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 90 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, 91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 93 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, 94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 96 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType, 97 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 98 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 99 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType, 100 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 101 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 102 103 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, 104 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded) 105 { 106 BOOL ret = TRUE; 107 108 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 109 { 110 if (pEncodePara && pEncodePara->pfnAlloc) 111 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded); 112 else 113 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded); 114 if (!*(BYTE **)pbEncoded) 115 ret = FALSE; 116 else 117 *pcbEncoded = bytesNeeded; 118 } 119 else if (bytesNeeded > *pcbEncoded) 120 { 121 *pcbEncoded = bytesNeeded; 122 SetLastError(ERROR_MORE_DATA); 123 ret = FALSE; 124 } 125 else 126 *pcbEncoded = bytesNeeded; 127 return ret; 128 } 129 130 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv) 131 { 132 if (pEncodePara && pEncodePara->pfnFree) 133 pEncodePara->pfnFree(pv); 134 else 135 LocalFree(pv); 136 } 137 138 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded) 139 { 140 DWORD bytesNeeded, significantBytes = 0; 141 142 if (len <= 0x7f) 143 bytesNeeded = 1; 144 else 145 { 146 DWORD temp; 147 148 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000); 149 temp <<= 8, significantBytes--) 150 ; 151 bytesNeeded = significantBytes + 1; 152 } 153 if (!pbEncoded) 154 { 155 *pcbEncoded = bytesNeeded; 156 return TRUE; 157 } 158 if (*pcbEncoded < bytesNeeded) 159 { 160 SetLastError(ERROR_MORE_DATA); 161 return FALSE; 162 } 163 if (len <= 0x7f) 164 *pbEncoded = (BYTE)len; 165 else 166 { 167 DWORD i; 168 169 *pbEncoded++ = significantBytes | 0x80; 170 for (i = 0; i < significantBytes; i++) 171 { 172 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff); 173 len >>= 8; 174 } 175 } 176 *pcbEncoded = bytesNeeded; 177 return TRUE; 178 } 179 180 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType, 181 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags, 182 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 183 { 184 BOOL ret; 185 DWORD i, dataLen = 0; 186 187 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara, 188 pbEncoded, pbEncoded ? *pcbEncoded : 0); 189 for (i = 0, ret = TRUE; ret && i < cItem; i++) 190 { 191 ret = items[i].encodeFunc(dwCertEncodingType, NULL, 192 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, 193 NULL, &items[i].size); 194 /* Some functions propagate their errors through the size */ 195 if (!ret) 196 *pcbEncoded = items[i].size; 197 dataLen += items[i].size; 198 } 199 if (ret) 200 { 201 DWORD lenBytes, bytesNeeded; 202 203 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 204 bytesNeeded = 1 + lenBytes + dataLen; 205 if (!pbEncoded) 206 *pcbEncoded = bytesNeeded; 207 else 208 { 209 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 210 pcbEncoded, bytesNeeded))) 211 { 212 BYTE *out; 213 214 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 215 pbEncoded = *(BYTE **)pbEncoded; 216 out = pbEncoded; 217 *out++ = ASN_SEQUENCE; 218 CRYPT_EncodeLen(dataLen, out, &lenBytes); 219 out += lenBytes; 220 for (i = 0; ret && i < cItem; i++) 221 { 222 ret = items[i].encodeFunc(dwCertEncodingType, NULL, 223 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, 224 NULL, out, &items[i].size); 225 /* Some functions propagate their errors through the size */ 226 if (!ret) 227 *pcbEncoded = items[i].size; 228 out += items[i].size; 229 } 230 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 231 CRYPT_FreeSpace(pEncodePara, pbEncoded); 232 } 233 } 234 } 235 TRACE("returning %d (%08x)\n", ret, GetLastError()); 236 return ret; 237 } 238 239 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType, 240 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 241 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 242 { 243 BOOL ret; 244 const struct AsnConstructedItem *item = pvStructInfo; 245 DWORD len; 246 247 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 248 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len))) 249 { 250 DWORD dataLen, bytesNeeded; 251 252 CRYPT_EncodeLen(len, NULL, &dataLen); 253 bytesNeeded = 1 + dataLen + len; 254 if (!pbEncoded) 255 *pcbEncoded = bytesNeeded; 256 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 257 pbEncoded, pcbEncoded, bytesNeeded))) 258 { 259 BYTE *out; 260 261 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 262 pbEncoded = *(BYTE **)pbEncoded; 263 out = pbEncoded; 264 *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag; 265 CRYPT_EncodeLen(len, out, &dataLen); 266 out += dataLen; 267 ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 268 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, 269 out, &len); 270 if (!ret) 271 { 272 /* Some functions propagate their errors through the size */ 273 *pcbEncoded = len; 274 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 275 CRYPT_FreeSpace(pEncodePara, pbEncoded); 276 } 277 } 278 } 279 else 280 { 281 /* Some functions propagate their errors through the size */ 282 *pcbEncoded = len; 283 } 284 return ret; 285 } 286 287 struct AsnEncodeTagSwappedItem 288 { 289 BYTE tag; 290 const void *pvStructInfo; 291 CryptEncodeObjectExFunc encodeFunc; 292 }; 293 294 /* Sort of a wacky hack, it encodes something using the struct 295 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag 296 * given in the struct AsnEncodeTagSwappedItem. 297 */ 298 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType, 299 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 300 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 301 { 302 BOOL ret; 303 const struct AsnEncodeTagSwappedItem *item = pvStructInfo; 304 305 ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 306 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 307 if (ret && pbEncoded) 308 *pbEncoded = item->tag; 309 return ret; 310 } 311 312 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType, 313 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 314 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 315 { 316 const DWORD *ver = pvStructInfo; 317 BOOL ret; 318 319 /* CERT_V1 is not encoded */ 320 if (*ver == CERT_V1) 321 { 322 *pcbEncoded = 0; 323 ret = TRUE; 324 } 325 else 326 { 327 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt }; 328 329 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER, 330 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 331 } 332 return ret; 333 } 334 335 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType, 336 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 337 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 338 { 339 const CRYPT_DER_BLOB *blob = pvStructInfo; 340 BOOL ret; 341 342 if (!pbEncoded) 343 { 344 *pcbEncoded = blob->cbData; 345 ret = TRUE; 346 } 347 else 348 { 349 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 350 pcbEncoded, blob->cbData))) 351 { 352 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 353 pbEncoded = *(BYTE **)pbEncoded; 354 if (blob->cbData) 355 memcpy(pbEncoded, blob->pbData, blob->cbData); 356 *pcbEncoded = blob->cbData; 357 } 358 } 359 return ret; 360 } 361 362 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType, 363 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 364 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 365 { 366 BOOL ret; 367 /* This has two filetimes in a row, a NotBefore and a NotAfter */ 368 const FILETIME *timePtr = pvStructInfo; 369 struct AsnEncodeSequenceItem items[] = { 370 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 }, 371 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 }, 372 }; 373 374 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 375 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 376 pcbEncoded); 377 return ret; 378 } 379 380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL 381 * if they are empty. 382 */ 383 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams( 384 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 385 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 386 DWORD *pcbEncoded) 387 { 388 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 389 static const BYTE asn1Null[] = { ASN_NULL, 0 }; 390 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null), 391 (LPBYTE)asn1Null }; 392 BOOL ret; 393 struct AsnEncodeSequenceItem items[2] = { 394 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, 395 { NULL, CRYPT_CopyEncodedBlob, 0 }, 396 }; 397 398 if (algo->Parameters.cbData) 399 items[1].pvStructInfo = &algo->Parameters; 400 else 401 items[1].pvStructInfo = &nullBlob; 402 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 403 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 404 pcbEncoded); 405 return ret; 406 } 407 408 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType, 409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 411 { 412 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 413 BOOL ret; 414 struct AsnEncodeSequenceItem items[] = { 415 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, 416 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 }, 417 }; 418 419 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 420 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 421 pcbEncoded); 422 return ret; 423 } 424 425 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType, 426 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 427 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 428 { 429 BOOL ret; 430 431 __TRY 432 { 433 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo; 434 struct AsnEncodeSequenceItem items[] = { 435 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 436 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 }, 437 }; 438 439 TRACE("Encoding public key with OID %s\n", 440 debugstr_a(info->Algorithm.pszObjId)); 441 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 442 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 443 pcbEncoded); 444 } 445 __EXCEPT_PAGE_FAULT 446 { 447 SetLastError(STATUS_ACCESS_VIOLATION); 448 ret = FALSE; 449 } 450 __ENDTRY 451 return ret; 452 } 453 454 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType, 455 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 456 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 457 { 458 BOOL ret; 459 460 __TRY 461 { 462 const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo; 463 struct AsnEncodeSequenceItem items[] = { 464 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 }, 465 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 466 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 }, 467 }; 468 469 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG) 470 items[2].encodeFunc = CRYPT_AsnEncodeBits; 471 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 472 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 473 pcbEncoded); 474 } 475 __EXCEPT_PAGE_FAULT 476 { 477 SetLastError(STATUS_ACCESS_VIOLATION); 478 ret = FALSE; 479 } 480 __ENDTRY 481 return ret; 482 } 483 484 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType, 485 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 486 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 487 { 488 BOOL ret; 489 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo; 490 struct AsnEncodeSequenceItem items[] = { 491 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 492 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 }, 493 }; 494 495 TRACE("Encoding public key with OID %s\n", 496 debugstr_a(info->Algorithm.pszObjId)); 497 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 498 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 499 pcbEncoded); 500 return ret; 501 } 502 503 /* Like in Windows, this blithely ignores the validity of the passed-in 504 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not 505 * decode properly, see CRYPT_AsnDecodeCertInfo. 506 */ 507 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType, 508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 510 { 511 BOOL ret; 512 513 __TRY 514 { 515 const CERT_INFO *info = pvStructInfo; 516 struct AsnEncodeSequenceItem items[10] = { 517 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 }, 518 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, 519 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 520 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 }, 521 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 }, 522 { &info->Subject, CRYPT_CopyEncodedBlob, 0 }, 523 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 }, 524 { 0 } 525 }; 526 struct AsnConstructedItem constructed = { 0 }; 527 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 528 DWORD cItem = 7, cSwapped = 0; 529 530 if (info->IssuerUniqueId.cbData) 531 { 532 swapped[cSwapped].tag = ASN_CONTEXT | 1; 533 swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId; 534 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 535 items[cItem].pvStructInfo = &swapped[cSwapped]; 536 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 537 cSwapped++; 538 cItem++; 539 } 540 if (info->SubjectUniqueId.cbData) 541 { 542 swapped[cSwapped].tag = ASN_CONTEXT | 2; 543 swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId; 544 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 545 items[cItem].pvStructInfo = &swapped[cSwapped]; 546 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 547 cSwapped++; 548 cItem++; 549 } 550 if (info->cExtension) 551 { 552 constructed.tag = 3; 553 constructed.pvStructInfo = &info->cExtension; 554 constructed.encodeFunc = CRYPT_AsnEncodeExtensions; 555 items[cItem].pvStructInfo = &constructed; 556 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 557 cItem++; 558 } 559 560 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 561 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 562 } 563 __EXCEPT_PAGE_FAULT 564 { 565 SetLastError(STATUS_ACCESS_VIOLATION); 566 ret = FALSE; 567 } 568 __ENDTRY 569 return ret; 570 } 571 572 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry, 573 BYTE *pbEncoded, DWORD *pcbEncoded) 574 { 575 struct AsnEncodeSequenceItem items[3] = { 576 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, 577 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 }, 578 { 0 } 579 }; 580 DWORD cItem = 2; 581 BOOL ret; 582 583 TRACE("%p, %p, %d\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0); 584 585 if (entry->cExtension) 586 { 587 items[cItem].pvStructInfo = &entry->cExtension; 588 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions; 589 cItem++; 590 } 591 592 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, 593 pbEncoded, pcbEncoded); 594 595 TRACE("returning %d (%08x)\n", ret, GetLastError()); 596 return ret; 597 } 598 599 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType, 600 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 601 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 602 { 603 DWORD bytesNeeded, dataLen, lenBytes, i; 604 const CRL_INFO *info = pvStructInfo; 605 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry; 606 BOOL ret = TRUE; 607 608 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++) 609 { 610 DWORD size; 611 612 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size); 613 if (ret) 614 dataLen += size; 615 } 616 if (ret) 617 { 618 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 619 bytesNeeded = 1 + lenBytes + dataLen; 620 if (!pbEncoded) 621 *pcbEncoded = bytesNeeded; 622 else 623 { 624 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 625 pcbEncoded, bytesNeeded))) 626 { 627 BYTE *out; 628 629 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 630 pbEncoded = *(BYTE **)pbEncoded; 631 out = pbEncoded; 632 *out++ = ASN_SEQUENCEOF; 633 CRYPT_EncodeLen(dataLen, out, &lenBytes); 634 out += lenBytes; 635 for (i = 0; i < info->cCRLEntry; i++) 636 { 637 DWORD size = dataLen; 638 639 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size); 640 out += size; 641 dataLen -= size; 642 } 643 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 644 CRYPT_FreeSpace(pEncodePara, pbEncoded); 645 } 646 } 647 } 648 return ret; 649 } 650 651 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType, 652 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 653 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 654 { 655 const DWORD *ver = pvStructInfo; 656 BOOL ret; 657 658 /* CRL_V1 is not encoded */ 659 if (*ver == CRL_V1) 660 { 661 *pcbEncoded = 0; 662 ret = TRUE; 663 } 664 else 665 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver, 666 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 667 return ret; 668 } 669 670 /* Like in Windows, this blithely ignores the validity of the passed-in 671 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not 672 * decode properly, see CRYPT_AsnDecodeCRLInfo. 673 */ 674 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType, 675 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 676 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 677 { 678 BOOL ret; 679 680 __TRY 681 { 682 const CRL_INFO *info = pvStructInfo; 683 struct AsnEncodeSequenceItem items[7] = { 684 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 }, 685 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, 686 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 }, 687 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 }, 688 { 0 } 689 }; 690 struct AsnConstructedItem constructed[1] = { { 0 } }; 691 DWORD cItem = 4, cConstructed = 0; 692 693 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime) 694 { 695 items[cItem].pvStructInfo = &info->NextUpdate; 696 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 697 cItem++; 698 } 699 if (info->cCRLEntry) 700 { 701 items[cItem].pvStructInfo = info; 702 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries; 703 cItem++; 704 } 705 if (info->cExtension) 706 { 707 constructed[cConstructed].tag = 0; 708 constructed[cConstructed].pvStructInfo = &info->cExtension; 709 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions; 710 items[cItem].pvStructInfo = &constructed[cConstructed]; 711 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 712 cConstructed++; 713 cItem++; 714 } 715 716 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 717 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 718 } 719 __EXCEPT_PAGE_FAULT 720 { 721 SetLastError(STATUS_ACCESS_VIOLATION); 722 ret = FALSE; 723 } 724 __ENDTRY 725 return ret; 726 } 727 728 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded, 729 DWORD *pcbEncoded) 730 { 731 BOOL ret; 732 struct AsnEncodeSequenceItem items[3] = { 733 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 }, 734 { NULL, NULL, 0 }, 735 { NULL, NULL, 0 }, 736 }; 737 DWORD cItem = 1; 738 739 TRACE("%p, %p, %d\n", ext, pbEncoded, pbEncoded ? *pcbEncoded : 0); 740 741 if (ext->fCritical) 742 { 743 items[cItem].pvStructInfo = &ext->fCritical; 744 items[cItem].encodeFunc = CRYPT_AsnEncodeBool; 745 cItem++; 746 } 747 items[cItem].pvStructInfo = &ext->Value; 748 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 749 cItem++; 750 751 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, 752 pbEncoded, pcbEncoded); 753 TRACE("returning %d (%08x)\n", ret, GetLastError()); 754 return ret; 755 } 756 757 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType, 758 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 759 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 760 { 761 BOOL ret; 762 763 __TRY 764 { 765 DWORD bytesNeeded, dataLen, lenBytes, i; 766 const CERT_EXTENSIONS *exts = pvStructInfo; 767 768 ret = TRUE; 769 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++) 770 { 771 DWORD size; 772 773 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size); 774 if (ret) 775 dataLen += size; 776 } 777 if (ret) 778 { 779 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 780 bytesNeeded = 1 + lenBytes + dataLen; 781 if (!pbEncoded) 782 *pcbEncoded = bytesNeeded; 783 else 784 { 785 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 786 pbEncoded, pcbEncoded, bytesNeeded))) 787 { 788 BYTE *out; 789 790 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 791 pbEncoded = *(BYTE **)pbEncoded; 792 out = pbEncoded; 793 *out++ = ASN_SEQUENCEOF; 794 CRYPT_EncodeLen(dataLen, out, &lenBytes); 795 out += lenBytes; 796 for (i = 0; i < exts->cExtension; i++) 797 { 798 DWORD size = dataLen; 799 800 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], 801 out, &size); 802 out += size; 803 dataLen -= size; 804 } 805 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 806 CRYPT_FreeSpace(pEncodePara, pbEncoded); 807 } 808 } 809 } 810 } 811 __EXCEPT_PAGE_FAULT 812 { 813 SetLastError(STATUS_ACCESS_VIOLATION); 814 ret = FALSE; 815 } 816 __ENDTRY 817 return ret; 818 } 819 820 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType, 821 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 822 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 823 { 824 LPCSTR pszObjId = pvStructInfo; 825 DWORD bytesNeeded = 0, lenBytes; 826 BOOL ret = TRUE; 827 int firstPos = 0; 828 BYTE firstByte = 0; 829 830 TRACE("%s\n", debugstr_a(pszObjId)); 831 832 if (pszObjId) 833 { 834 const char *ptr; 835 int val1, val2; 836 837 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2) 838 { 839 SetLastError(CRYPT_E_ASN1_ERROR); 840 return FALSE; 841 } 842 bytesNeeded++; 843 firstByte = val1 * 40 + val2; 844 ptr = pszObjId + firstPos; 845 if (*ptr == '.') 846 { 847 ptr++; 848 firstPos++; 849 } 850 while (ret && *ptr) 851 { 852 int pos; 853 854 /* note I assume each component is at most 32-bits long in base 2 */ 855 if (sscanf(ptr, "%d%n", &val1, &pos) == 1) 856 { 857 if (val1 >= 0x10000000) 858 bytesNeeded += 5; 859 else if (val1 >= 0x200000) 860 bytesNeeded += 4; 861 else if (val1 >= 0x4000) 862 bytesNeeded += 3; 863 else if (val1 >= 0x80) 864 bytesNeeded += 2; 865 else 866 bytesNeeded += 1; 867 ptr += pos; 868 if (*ptr == '.') 869 ptr++; 870 } 871 else 872 { 873 SetLastError(CRYPT_E_ASN1_ERROR); 874 return FALSE; 875 } 876 } 877 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 878 } 879 else 880 lenBytes = 1; 881 bytesNeeded += 1 + lenBytes; 882 if (pbEncoded) 883 { 884 if (*pcbEncoded < bytesNeeded) 885 { 886 SetLastError(ERROR_MORE_DATA); 887 ret = FALSE; 888 } 889 else 890 { 891 *pbEncoded++ = ASN_OBJECTIDENTIFIER; 892 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes); 893 pbEncoded += lenBytes; 894 if (pszObjId) 895 { 896 const char *ptr; 897 int val, pos; 898 899 *pbEncoded++ = firstByte; 900 ptr = pszObjId + firstPos; 901 while (ret && *ptr) 902 { 903 sscanf(ptr, "%d%n", &val, &pos); 904 { 905 unsigned char outBytes[5]; 906 int numBytes, i; 907 908 if (val >= 0x10000000) 909 numBytes = 5; 910 else if (val >= 0x200000) 911 numBytes = 4; 912 else if (val >= 0x4000) 913 numBytes = 3; 914 else if (val >= 0x80) 915 numBytes = 2; 916 else 917 numBytes = 1; 918 for (i = numBytes; i > 0; i--) 919 { 920 outBytes[i - 1] = val & 0x7f; 921 val >>= 7; 922 } 923 for (i = 0; i < numBytes - 1; i++) 924 *pbEncoded++ = outBytes[i] | 0x80; 925 *pbEncoded++ = outBytes[i]; 926 ptr += pos; 927 if (*ptr == '.') 928 ptr++; 929 } 930 } 931 } 932 } 933 } 934 *pcbEncoded = bytesNeeded; 935 return ret; 936 } 937 938 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value, 939 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 940 DWORD *pcbEncoded) 941 { 942 BOOL ret = TRUE; 943 LPCSTR str = (LPCSTR)value->Value.pbData; 944 DWORD bytesNeeded, lenBytes, encodedLen; 945 946 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str); 947 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 948 bytesNeeded = 1 + lenBytes + encodedLen; 949 if (!pbEncoded) 950 *pcbEncoded = bytesNeeded; 951 else 952 { 953 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 954 pbEncoded, pcbEncoded, bytesNeeded))) 955 { 956 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 957 pbEncoded = *(BYTE **)pbEncoded; 958 *pbEncoded++ = tag; 959 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); 960 pbEncoded += lenBytes; 961 memcpy(pbEncoded, str, encodedLen); 962 } 963 } 964 return ret; 965 } 966 967 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value, 968 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 969 DWORD *pcbEncoded) 970 { 971 BOOL ret = TRUE; 972 LPCWSTR str = (LPCWSTR)value->Value.pbData; 973 DWORD bytesNeeded, lenBytes, strLen; 974 975 if (value->Value.cbData) 976 strLen = value->Value.cbData / sizeof(WCHAR); 977 else if (value->Value.pbData) 978 strLen = lstrlenW(str); 979 else 980 strLen = 0; 981 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes); 982 bytesNeeded = 1 + lenBytes + strLen * 2; 983 if (!pbEncoded) 984 *pcbEncoded = bytesNeeded; 985 else 986 { 987 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 988 pbEncoded, pcbEncoded, bytesNeeded))) 989 { 990 DWORD i; 991 992 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 993 pbEncoded = *(BYTE **)pbEncoded; 994 *pbEncoded++ = ASN_BMPSTRING; 995 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes); 996 pbEncoded += lenBytes; 997 for (i = 0; i < strLen; i++) 998 { 999 *pbEncoded++ = (str[i] & 0xff00) >> 8; 1000 *pbEncoded++ = str[i] & 0x00ff; 1001 } 1002 } 1003 } 1004 return ret; 1005 } 1006 1007 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value, 1008 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 1009 DWORD *pcbEncoded) 1010 { 1011 BOOL ret = TRUE; 1012 LPCWSTR str = (LPCWSTR)value->Value.pbData; 1013 DWORD bytesNeeded, lenBytes, encodedLen, strLen; 1014 1015 if (value->Value.cbData) 1016 strLen = value->Value.cbData / sizeof(WCHAR); 1017 else if (str) 1018 strLen = strlenW(str); 1019 else 1020 strLen = 0; 1021 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL, 1022 NULL); 1023 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 1024 bytesNeeded = 1 + lenBytes + encodedLen; 1025 if (!pbEncoded) 1026 *pcbEncoded = bytesNeeded; 1027 else 1028 { 1029 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 1030 pbEncoded, pcbEncoded, bytesNeeded))) 1031 { 1032 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 1033 pbEncoded = *(BYTE **)pbEncoded; 1034 *pbEncoded++ = ASN_UTF8STRING; 1035 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); 1036 pbEncoded += lenBytes; 1037 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded, 1038 bytesNeeded - lenBytes - 1, NULL, NULL); 1039 } 1040 } 1041 return ret; 1042 } 1043 1044 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType, 1045 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1046 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1047 { 1048 BOOL ret = TRUE; 1049 1050 __TRY 1051 { 1052 const CERT_NAME_VALUE *value = pvStructInfo; 1053 1054 switch (value->dwValueType) 1055 { 1056 case CERT_RDN_ANY_TYPE: 1057 /* explicitly disallowed */ 1058 SetLastError(E_INVALIDARG); 1059 ret = FALSE; 1060 break; 1061 case CERT_RDN_ENCODED_BLOB: 1062 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, 1063 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1064 break; 1065 case CERT_RDN_OCTET_STRING: 1066 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING, 1067 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1068 break; 1069 case CERT_RDN_NUMERIC_STRING: 1070 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING, 1071 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1072 break; 1073 case CERT_RDN_PRINTABLE_STRING: 1074 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING, 1075 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1076 break; 1077 case CERT_RDN_TELETEX_STRING: 1078 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING, 1079 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1080 break; 1081 case CERT_RDN_VIDEOTEX_STRING: 1082 ret = CRYPT_AsnEncodeStringCoerce(value, 1083 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1084 break; 1085 case CERT_RDN_IA5_STRING: 1086 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING, 1087 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1088 break; 1089 case CERT_RDN_GRAPHIC_STRING: 1090 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING, 1091 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1092 break; 1093 case CERT_RDN_VISIBLE_STRING: 1094 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING, 1095 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1096 break; 1097 case CERT_RDN_GENERAL_STRING: 1098 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING, 1099 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1100 break; 1101 case CERT_RDN_UNIVERSAL_STRING: 1102 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n"); 1103 SetLastError(CRYPT_E_ASN1_CHOICE); 1104 ret = FALSE; 1105 break; 1106 case CERT_RDN_BMP_STRING: 1107 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara, 1108 pbEncoded, pcbEncoded); 1109 break; 1110 case CERT_RDN_UTF8_STRING: 1111 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara, 1112 pbEncoded, pcbEncoded); 1113 break; 1114 default: 1115 SetLastError(CRYPT_E_ASN1_CHOICE); 1116 ret = FALSE; 1117 } 1118 } 1119 __EXCEPT_PAGE_FAULT 1120 { 1121 SetLastError(STATUS_ACCESS_VIOLATION); 1122 ret = FALSE; 1123 } 1124 __ENDTRY 1125 return ret; 1126 } 1127 1128 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType, 1129 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc, 1130 BYTE *pbEncoded, DWORD *pcbEncoded) 1131 { 1132 DWORD bytesNeeded = 0, lenBytes, size; 1133 BOOL ret; 1134 1135 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId, 1136 0, NULL, NULL, &size); 1137 if (ret) 1138 { 1139 bytesNeeded += size; 1140 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning 1141 * with dwValueType, so "cast" it to get its encoded size 1142 */ 1143 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType, 1144 0, NULL, NULL, &size); 1145 if (ret) 1146 { 1147 bytesNeeded += size; 1148 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 1149 bytesNeeded += 1 + lenBytes; 1150 if (pbEncoded) 1151 { 1152 if (*pcbEncoded < bytesNeeded) 1153 { 1154 SetLastError(ERROR_MORE_DATA); 1155 ret = FALSE; 1156 } 1157 else 1158 { 1159 *pbEncoded++ = ASN_SEQUENCE; 1160 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, 1161 &lenBytes); 1162 pbEncoded += lenBytes; 1163 size = bytesNeeded - 1 - lenBytes; 1164 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 1165 attr->pszObjId, 0, NULL, pbEncoded, &size); 1166 if (ret) 1167 { 1168 pbEncoded += size; 1169 size = bytesNeeded - 1 - lenBytes - size; 1170 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, 1171 &attr->dwValueType, 0, NULL, pbEncoded, &size); 1172 if (!ret) 1173 *pcbEncoded = size; 1174 } 1175 } 1176 } 1177 if (ret) 1178 *pcbEncoded = bytesNeeded; 1179 } 1180 else 1181 { 1182 /* Have to propagate index of failing character */ 1183 *pcbEncoded = size; 1184 } 1185 } 1186 return ret; 1187 } 1188 1189 static int BLOBComp(const void *l, const void *r) 1190 { 1191 const CRYPT_DER_BLOB *a = l, *b = r; 1192 int ret; 1193 1194 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData)))) 1195 ret = a->cbData - b->cbData; 1196 return ret; 1197 } 1198 1199 /* This encodes a SET OF, which in DER must be lexicographically sorted. 1200 */ 1201 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType, 1202 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1204 { 1205 const CRYPT_BLOB_ARRAY *set = pvStructInfo; 1206 DWORD bytesNeeded = 0, lenBytes, i; 1207 BOOL ret; 1208 1209 for (i = 0; i < set->cBlob; i++) 1210 bytesNeeded += set->rgBlob[i].cbData; 1211 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 1212 bytesNeeded += 1 + lenBytes; 1213 if (!pbEncoded) 1214 { 1215 *pcbEncoded = bytesNeeded; 1216 ret = TRUE; 1217 } 1218 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 1219 pbEncoded, pcbEncoded, bytesNeeded))) 1220 { 1221 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 1222 pbEncoded = *(BYTE **)pbEncoded; 1223 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp); 1224 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF; 1225 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes); 1226 pbEncoded += lenBytes; 1227 for (i = 0; i < set->cBlob; i++) 1228 { 1229 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData); 1230 pbEncoded += set->rgBlob[i].cbData; 1231 } 1232 } 1233 return ret; 1234 } 1235 1236 struct DERSetDescriptor 1237 { 1238 DWORD cItems; 1239 const void *items; 1240 size_t itemSize; 1241 size_t itemOffset; 1242 CryptEncodeObjectExFunc encode; 1243 }; 1244 1245 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType, 1246 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1247 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1248 { 1249 const struct DERSetDescriptor *desc = pvStructInfo; 1250 CRYPT_BLOB_ARRAY setOf = { 0, NULL }; 1251 BOOL ret = TRUE; 1252 DWORD i; 1253 1254 if (desc->cItems) 1255 { 1256 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB)); 1257 if (!setOf.rgBlob) 1258 ret = FALSE; 1259 else 1260 { 1261 setOf.cBlob = desc->cItems; 1262 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB)); 1263 } 1264 } 1265 for (i = 0; ret && i < setOf.cBlob; i++) 1266 { 1267 ret = desc->encode(dwCertEncodingType, lpszStructType, 1268 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset, 1269 0, NULL, NULL, &setOf.rgBlob[i].cbData); 1270 if (ret) 1271 { 1272 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData); 1273 if (!setOf.rgBlob[i].pbData) 1274 ret = FALSE; 1275 else 1276 ret = desc->encode(dwCertEncodingType, lpszStructType, 1277 (const BYTE *)desc->items + i * desc->itemSize + 1278 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData, 1279 &setOf.rgBlob[i].cbData); 1280 } 1281 /* Some functions propagate their errors through the size */ 1282 if (!ret) 1283 *pcbEncoded = setOf.rgBlob[i].cbData; 1284 } 1285 if (ret) 1286 { 1287 DWORD bytesNeeded = 0, lenBytes; 1288 1289 for (i = 0; i < setOf.cBlob; i++) 1290 bytesNeeded += setOf.rgBlob[i].cbData; 1291 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 1292 bytesNeeded += 1 + lenBytes; 1293 if (!pbEncoded) 1294 *pcbEncoded = bytesNeeded; 1295 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 1296 pbEncoded, pcbEncoded, bytesNeeded))) 1297 { 1298 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 1299 pbEncoded = *(BYTE **)pbEncoded; 1300 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB), 1301 BLOBComp); 1302 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF; 1303 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes); 1304 pbEncoded += lenBytes; 1305 for (i = 0; i < setOf.cBlob; i++) 1306 { 1307 memcpy(pbEncoded, setOf.rgBlob[i].pbData, 1308 setOf.rgBlob[i].cbData); 1309 pbEncoded += setOf.rgBlob[i].cbData; 1310 } 1311 } 1312 } 1313 for (i = 0; i < setOf.cBlob; i++) 1314 CryptMemFree(setOf.rgBlob[i].pbData); 1315 CryptMemFree(setOf.rgBlob); 1316 return ret; 1317 } 1318 1319 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn, 1320 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded, 1321 DWORD *pcbEncoded) 1322 { 1323 BOOL ret; 1324 CRYPT_BLOB_ARRAY setOf = { 0, NULL }; 1325 1326 __TRY 1327 { 1328 DWORD i; 1329 1330 ret = TRUE; 1331 if (rdn->cRDNAttr) 1332 { 1333 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr * 1334 sizeof(CRYPT_DER_BLOB)); 1335 if (!setOf.rgBlob) 1336 ret = FALSE; 1337 else 1338 { 1339 setOf.cBlob = rdn->cRDNAttr; 1340 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB)); 1341 } 1342 } 1343 for (i = 0; ret && i < rdn->cRDNAttr; i++) 1344 { 1345 setOf.rgBlob[i].cbData = 0; 1346 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i], 1347 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData); 1348 if (ret) 1349 { 1350 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData); 1351 if (!setOf.rgBlob[i].pbData) 1352 ret = FALSE; 1353 else 1354 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, 1355 &rdn->rgRDNAttr[i], nameValueEncodeFunc, 1356 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData); 1357 } 1358 if (!ret) 1359 { 1360 /* Have to propagate index of failing character */ 1361 *pcbEncoded = setOf.rgBlob[i].cbData; 1362 } 1363 } 1364 if (ret) 1365 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL, 1366 pbEncoded, pcbEncoded); 1367 for (i = 0; i < setOf.cBlob; i++) 1368 CryptMemFree(setOf.rgBlob[i].pbData); 1369 } 1370 __EXCEPT_PAGE_FAULT 1371 { 1372 SetLastError(STATUS_ACCESS_VIOLATION); 1373 ret = FALSE; 1374 } 1375 __ENDTRY 1376 CryptMemFree(setOf.rgBlob); 1377 return ret; 1378 } 1379 1380 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType, 1381 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1382 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); 1383 1384 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue( 1385 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 1386 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 1387 DWORD *pcbEncoded) 1388 { 1389 const CERT_NAME_VALUE *value = pvStructInfo; 1390 BOOL ret; 1391 1392 if (value->dwValueType == CERT_RDN_ENCODED_BLOB) 1393 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value, 1394 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1395 else 1396 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value, 1397 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1398 return ret; 1399 } 1400 1401 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType, 1402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1404 { 1405 BOOL ret = TRUE; 1406 1407 __TRY 1408 { 1409 const CERT_NAME_INFO *info = pvStructInfo; 1410 DWORD bytesNeeded = 0, lenBytes, size, i; 1411 1412 TRACE("encoding name with %d RDNs\n", info->cRDN); 1413 ret = TRUE; 1414 for (i = 0; ret && i < info->cRDN; i++) 1415 { 1416 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], 1417 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size); 1418 if (ret) 1419 bytesNeeded += size; 1420 else 1421 *pcbEncoded = size; 1422 } 1423 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 1424 bytesNeeded += 1 + lenBytes; 1425 if (ret) 1426 { 1427 if (!pbEncoded) 1428 *pcbEncoded = bytesNeeded; 1429 else 1430 { 1431 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 1432 pbEncoded, pcbEncoded, bytesNeeded))) 1433 { 1434 BYTE *out; 1435 1436 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 1437 pbEncoded = *(BYTE **)pbEncoded; 1438 out = pbEncoded; 1439 *out++ = ASN_SEQUENCEOF; 1440 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 1441 out += lenBytes; 1442 for (i = 0; ret && i < info->cRDN; i++) 1443 { 1444 size = bytesNeeded; 1445 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, 1446 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue, 1447 out, &size); 1448 if (ret) 1449 { 1450 out += size; 1451 bytesNeeded -= size; 1452 } 1453 else 1454 *pcbEncoded = size; 1455 } 1456 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 1457 CRYPT_FreeSpace(pEncodePara, pbEncoded); 1458 } 1459 } 1460 } 1461 } 1462 __EXCEPT_PAGE_FAULT 1463 { 1464 SetLastError(STATUS_ACCESS_VIOLATION); 1465 ret = FALSE; 1466 } 1467 __ENDTRY 1468 return ret; 1469 } 1470 1471 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType, 1472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1474 { 1475 const DWORD *ver = pvStructInfo; 1476 BOOL ret; 1477 1478 /* CTL_V1 is not encoded */ 1479 if (*ver == CTL_V1) 1480 { 1481 *pcbEncoded = 0; 1482 ret = TRUE; 1483 } 1484 else 1485 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver, 1486 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1487 return ret; 1488 } 1489 1490 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL 1491 * if they are empty and the OID is not empty (otherwise omits them.) 1492 */ 1493 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm( 1494 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 1495 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 1496 DWORD *pcbEncoded) 1497 { 1498 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 1499 BOOL ret; 1500 struct AsnEncodeSequenceItem items[2] = { 1501 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, 1502 }; 1503 DWORD cItem = 1; 1504 1505 if (algo->pszObjId) 1506 { 1507 static const BYTE asn1Null[] = { ASN_NULL, 0 }; 1508 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null), 1509 (LPBYTE)asn1Null }; 1510 1511 if (algo->Parameters.cbData) 1512 items[cItem].pvStructInfo = &algo->Parameters; 1513 else 1514 items[cItem].pvStructInfo = &nullBlob; 1515 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob; 1516 cItem++; 1517 } 1518 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 1519 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1520 return ret; 1521 } 1522 1523 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry, 1524 BYTE *pbEncoded, DWORD *pcbEncoded) 1525 { 1526 struct AsnEncodeSequenceItem items[2] = { 1527 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 }, 1528 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 }, 1529 }; 1530 BOOL ret; 1531 1532 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 1533 ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded); 1534 return ret; 1535 } 1536 1537 struct CTLEntries 1538 { 1539 DWORD cEntry; 1540 CTL_ENTRY *rgEntry; 1541 }; 1542 1543 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType, 1544 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1545 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1546 { 1547 BOOL ret; 1548 DWORD bytesNeeded, dataLen, lenBytes, i; 1549 const struct CTLEntries *entries = pvStructInfo; 1550 1551 ret = TRUE; 1552 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++) 1553 { 1554 DWORD size; 1555 1556 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size); 1557 if (ret) 1558 dataLen += size; 1559 } 1560 if (ret) 1561 { 1562 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 1563 bytesNeeded = 1 + lenBytes + dataLen; 1564 if (!pbEncoded) 1565 *pcbEncoded = bytesNeeded; 1566 else 1567 { 1568 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 1569 pbEncoded, pcbEncoded, bytesNeeded))) 1570 { 1571 BYTE *out; 1572 1573 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 1574 pbEncoded = *(BYTE **)pbEncoded; 1575 out = pbEncoded; 1576 *out++ = ASN_SEQUENCEOF; 1577 CRYPT_EncodeLen(dataLen, out, &lenBytes); 1578 out += lenBytes; 1579 for (i = 0; ret && i < entries->cEntry; i++) 1580 { 1581 DWORD size = dataLen; 1582 1583 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], 1584 out, &size); 1585 out += size; 1586 dataLen -= size; 1587 } 1588 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 1589 CRYPT_FreeSpace(pEncodePara, pbEncoded); 1590 } 1591 } 1592 } 1593 return ret; 1594 } 1595 1596 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType, 1597 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1598 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1599 { 1600 BOOL ret = FALSE; 1601 1602 __TRY 1603 { 1604 const CTL_INFO *info = pvStructInfo; 1605 struct AsnEncodeSequenceItem items[9] = { 1606 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 }, 1607 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 }, 1608 }; 1609 struct AsnConstructedItem constructed = { 0 }; 1610 DWORD cItem = 2; 1611 1612 if (info->ListIdentifier.cbData) 1613 { 1614 items[cItem].pvStructInfo = &info->ListIdentifier; 1615 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 1616 cItem++; 1617 } 1618 if (info->SequenceNumber.cbData) 1619 { 1620 items[cItem].pvStructInfo = &info->SequenceNumber; 1621 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger; 1622 cItem++; 1623 } 1624 items[cItem].pvStructInfo = &info->ThisUpdate; 1625 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 1626 cItem++; 1627 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime) 1628 { 1629 items[cItem].pvStructInfo = &info->NextUpdate; 1630 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 1631 cItem++; 1632 } 1633 items[cItem].pvStructInfo = &info->SubjectAlgorithm; 1634 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm; 1635 cItem++; 1636 if (info->cCTLEntry) 1637 { 1638 items[cItem].pvStructInfo = &info->cCTLEntry; 1639 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries; 1640 cItem++; 1641 } 1642 if (info->cExtension) 1643 { 1644 constructed.tag = 0; 1645 constructed.pvStructInfo = &info->cExtension; 1646 constructed.encodeFunc = CRYPT_AsnEncodeExtensions; 1647 items[cItem].pvStructInfo = &constructed; 1648 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 1649 cItem++; 1650 } 1651 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 1652 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1653 } 1654 __EXCEPT_PAGE_FAULT 1655 { 1656 SetLastError(STATUS_ACCESS_VIOLATION); 1657 } 1658 __ENDTRY 1659 return ret; 1660 } 1661 1662 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType, 1663 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1664 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1665 { 1666 BOOL ret = FALSE; 1667 1668 __TRY 1669 { 1670 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo; 1671 1672 if (!capability->pszObjId) 1673 SetLastError(E_INVALIDARG); 1674 else 1675 { 1676 struct AsnEncodeSequenceItem items[] = { 1677 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 }, 1678 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 }, 1679 }; 1680 1681 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 1682 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 1683 pcbEncoded); 1684 } 1685 } 1686 __EXCEPT_PAGE_FAULT 1687 { 1688 SetLastError(STATUS_ACCESS_VIOLATION); 1689 } 1690 __ENDTRY 1691 return ret; 1692 } 1693 1694 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType, 1695 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1696 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1697 { 1698 BOOL ret = FALSE; 1699 1700 __TRY 1701 { 1702 DWORD bytesNeeded, dataLen, lenBytes, i; 1703 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo; 1704 1705 ret = TRUE; 1706 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++) 1707 { 1708 DWORD size; 1709 1710 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL, 1711 &capabilities->rgCapability[i], 0, NULL, NULL, &size); 1712 if (ret) 1713 dataLen += size; 1714 } 1715 if (ret) 1716 { 1717 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 1718 bytesNeeded = 1 + lenBytes + dataLen; 1719 if (!pbEncoded) 1720 *pcbEncoded = bytesNeeded; 1721 else 1722 { 1723 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 1724 pbEncoded, pcbEncoded, bytesNeeded))) 1725 { 1726 BYTE *out; 1727 1728 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 1729 pbEncoded = *(BYTE **)pbEncoded; 1730 out = pbEncoded; 1731 *out++ = ASN_SEQUENCEOF; 1732 CRYPT_EncodeLen(dataLen, out, &lenBytes); 1733 out += lenBytes; 1734 for (i = 0; i < capabilities->cCapability; i++) 1735 { 1736 DWORD size = dataLen; 1737 1738 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, 1739 NULL, &capabilities->rgCapability[i], 0, NULL, 1740 out, &size); 1741 out += size; 1742 dataLen -= size; 1743 } 1744 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 1745 CRYPT_FreeSpace(pEncodePara, pbEncoded); 1746 } 1747 } 1748 } 1749 } 1750 __EXCEPT_PAGE_FAULT 1751 { 1752 SetLastError(STATUS_ACCESS_VIOLATION); 1753 } 1754 __ENDTRY 1755 return ret; 1756 } 1757 1758 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType, 1759 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1760 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1761 { 1762 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo; 1763 DWORD bytesNeeded, dataLen, lenBytes, i; 1764 BOOL ret = TRUE; 1765 1766 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++) 1767 { 1768 DWORD size; 1769 1770 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, 1771 ¬iceRef->rgNoticeNumbers[i], 0, NULL, NULL, &size); 1772 if (ret) 1773 dataLen += size; 1774 } 1775 if (ret) 1776 { 1777 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 1778 bytesNeeded = 1 + lenBytes + dataLen; 1779 if (!pbEncoded) 1780 *pcbEncoded = bytesNeeded; 1781 else 1782 { 1783 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 1784 pcbEncoded, bytesNeeded))) 1785 { 1786 BYTE *out; 1787 1788 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 1789 pbEncoded = *(BYTE **)pbEncoded; 1790 out = pbEncoded; 1791 *out++ = ASN_SEQUENCE; 1792 CRYPT_EncodeLen(dataLen, out, &lenBytes); 1793 out += lenBytes; 1794 for (i = 0; i < noticeRef->cNoticeNumbers; i++) 1795 { 1796 DWORD size = dataLen; 1797 1798 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, 1799 ¬iceRef->rgNoticeNumbers[i], 0, NULL, out, &size); 1800 out += size; 1801 dataLen -= size; 1802 } 1803 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 1804 CRYPT_FreeSpace(pEncodePara, pbEncoded); 1805 } 1806 } 1807 } 1808 return ret; 1809 } 1810 1811 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType, 1812 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1813 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1814 { 1815 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo; 1816 BOOL ret; 1817 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING, 1818 { 0, (LPBYTE)noticeRef->pszOrganization } }; 1819 struct AsnEncodeSequenceItem items[] = { 1820 { &orgValue, CRYPT_AsnEncodeNameValue, 0 }, 1821 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 }, 1822 }; 1823 1824 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 1825 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 1826 pcbEncoded); 1827 return ret; 1828 } 1829 1830 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice( 1831 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 1832 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 1833 DWORD *pcbEncoded) 1834 { 1835 BOOL ret = FALSE; 1836 1837 __TRY 1838 { 1839 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo; 1840 struct AsnEncodeSequenceItem items[2]; 1841 CERT_NAME_VALUE displayTextValue; 1842 DWORD cItem = 0; 1843 1844 if (notice->pNoticeReference) 1845 { 1846 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference; 1847 items[cItem].pvStructInfo = notice->pNoticeReference; 1848 cItem++; 1849 } 1850 if (notice->pszDisplayText) 1851 { 1852 displayTextValue.dwValueType = CERT_RDN_BMP_STRING; 1853 displayTextValue.Value.cbData = 0; 1854 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText; 1855 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue; 1856 items[cItem].pvStructInfo = &displayTextValue; 1857 cItem++; 1858 } 1859 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 1860 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1861 } 1862 __EXCEPT_PAGE_FAULT 1863 { 1864 SetLastError(STATUS_ACCESS_VIOLATION); 1865 } 1866 __ENDTRY 1867 return ret; 1868 } 1869 1870 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType, 1871 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1872 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1873 { 1874 BOOL ret = FALSE; 1875 1876 __TRY 1877 { 1878 const CRYPT_ATTRIBUTE *attr = pvStructInfo; 1879 1880 if (!attr->pszObjId) 1881 SetLastError(E_INVALIDARG); 1882 else 1883 { 1884 struct AsnEncodeSequenceItem items[2] = { 1885 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 }, 1886 { &attr->cValue, CRYPT_DEREncodeSet, 0 }, 1887 }; 1888 1889 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 1890 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, 1891 pcbEncoded); 1892 } 1893 } 1894 __EXCEPT_PAGE_FAULT 1895 { 1896 SetLastError(STATUS_ACCESS_VIOLATION); 1897 } 1898 __ENDTRY 1899 return ret; 1900 } 1901 1902 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType, 1903 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1904 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1905 { 1906 BOOL ret = FALSE; 1907 1908 __TRY 1909 { 1910 const CRYPT_ATTRIBUTES *attributes = pvStructInfo; 1911 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr, 1912 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute }; 1913 1914 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType, 1915 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1916 } 1917 __EXCEPT_PAGE_FAULT 1918 { 1919 SetLastError(STATUS_ACCESS_VIOLATION); 1920 } 1921 __ENDTRY 1922 return ret; 1923 } 1924 1925 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */ 1926 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal( 1927 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 1928 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 1929 DWORD *pcbEncoded) 1930 { 1931 const CRYPT_CONTENT_INFO *info = pvStructInfo; 1932 struct AsnEncodeSequenceItem items[2] = { 1933 { info->pszObjId, CRYPT_AsnEncodeOid, 0 }, 1934 { NULL, NULL, 0 }, 1935 }; 1936 struct AsnConstructedItem constructed = { 0 }; 1937 DWORD cItem = 1; 1938 1939 if (info->Content.cbData) 1940 { 1941 constructed.tag = 0; 1942 constructed.pvStructInfo = &info->Content; 1943 constructed.encodeFunc = CRYPT_CopyEncodedBlob; 1944 items[cItem].pvStructInfo = &constructed; 1945 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 1946 cItem++; 1947 } 1948 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 1949 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 1950 } 1951 1952 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData, 1953 void *pvData, DWORD *pcbData) 1954 { 1955 struct AsnEncodeSequenceItem items[] = { 1956 { &digestedData->version, CRYPT_AsnEncodeInt, 0 }, 1957 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 1958 0 }, 1959 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 }, 1960 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 }, 1961 }; 1962 1963 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pvData, pcbData); 1964 } 1965 1966 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType, 1967 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1968 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1969 { 1970 BOOL ret = FALSE; 1971 1972 __TRY 1973 { 1974 const CRYPT_CONTENT_INFO *info = pvStructInfo; 1975 1976 if (!info->pszObjId) 1977 SetLastError(E_INVALIDARG); 1978 else 1979 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType, 1980 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded, 1981 pcbEncoded); 1982 } 1983 __EXCEPT_PAGE_FAULT 1984 { 1985 SetLastError(STATUS_ACCESS_VIOLATION); 1986 } 1987 __ENDTRY 1988 return ret; 1989 } 1990 1991 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value, 1992 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 1993 DWORD *pcbEncoded) 1994 { 1995 BOOL ret = TRUE; 1996 LPCWSTR str = (LPCWSTR)value->Value.pbData; 1997 DWORD bytesNeeded, lenBytes, encodedLen; 1998 1999 if (value->Value.cbData) 2000 encodedLen = value->Value.cbData / sizeof(WCHAR); 2001 else if (str) 2002 encodedLen = strlenW(str); 2003 else 2004 encodedLen = 0; 2005 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2006 bytesNeeded = 1 + lenBytes + encodedLen; 2007 if (!pbEncoded) 2008 *pcbEncoded = bytesNeeded; 2009 else 2010 { 2011 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2012 pbEncoded, pcbEncoded, bytesNeeded))) 2013 { 2014 DWORD i; 2015 2016 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2017 pbEncoded = *(BYTE **)pbEncoded; 2018 *pbEncoded++ = tag; 2019 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); 2020 pbEncoded += lenBytes; 2021 for (i = 0; i < encodedLen; i++) 2022 *pbEncoded++ = (BYTE)str[i]; 2023 } 2024 } 2025 return ret; 2026 } 2027 2028 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value, 2029 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2030 DWORD *pcbEncoded) 2031 { 2032 BOOL ret = TRUE; 2033 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2034 DWORD bytesNeeded, lenBytes, encodedLen; 2035 2036 if (value->Value.cbData) 2037 encodedLen = value->Value.cbData / sizeof(WCHAR); 2038 else if (str) 2039 encodedLen = strlenW(str); 2040 else 2041 encodedLen = 0; 2042 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2043 bytesNeeded = 1 + lenBytes + encodedLen; 2044 if (!pbEncoded) 2045 *pcbEncoded = bytesNeeded; 2046 else 2047 { 2048 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2049 pbEncoded, pcbEncoded, bytesNeeded))) 2050 { 2051 DWORD i; 2052 BYTE *ptr; 2053 2054 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2055 ptr = *(BYTE **)pbEncoded; 2056 else 2057 ptr = pbEncoded; 2058 *ptr++ = ASN_NUMERICSTRING; 2059 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 2060 ptr += lenBytes; 2061 for (i = 0; ret && i < encodedLen; i++) 2062 { 2063 if (isdigitW(str[i])) 2064 *ptr++ = (BYTE)str[i]; 2065 else 2066 { 2067 *pcbEncoded = i; 2068 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING); 2069 ret = FALSE; 2070 } 2071 } 2072 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2073 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 2074 } 2075 } 2076 return ret; 2077 } 2078 2079 static inline BOOL isprintableW(WCHAR wc) 2080 { 2081 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' || 2082 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' || 2083 wc == '/' || wc == ':' || wc == '=' || wc == '?'; 2084 } 2085 2086 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value, 2087 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2088 DWORD *pcbEncoded) 2089 { 2090 BOOL ret = TRUE; 2091 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2092 DWORD bytesNeeded, lenBytes, encodedLen; 2093 2094 if (value->Value.cbData) 2095 encodedLen = value->Value.cbData / sizeof(WCHAR); 2096 else if (str) 2097 encodedLen = strlenW(str); 2098 else 2099 encodedLen = 0; 2100 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2101 bytesNeeded = 1 + lenBytes + encodedLen; 2102 if (!pbEncoded) 2103 *pcbEncoded = bytesNeeded; 2104 else 2105 { 2106 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2107 pbEncoded, pcbEncoded, bytesNeeded))) 2108 { 2109 DWORD i; 2110 BYTE *ptr; 2111 2112 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2113 ptr = *(BYTE **)pbEncoded; 2114 else 2115 ptr = pbEncoded; 2116 *ptr++ = ASN_PRINTABLESTRING; 2117 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 2118 ptr += lenBytes; 2119 for (i = 0; ret && i < encodedLen; i++) 2120 { 2121 if (isprintableW(str[i])) 2122 *ptr++ = (BYTE)str[i]; 2123 else 2124 { 2125 *pcbEncoded = i; 2126 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING); 2127 ret = FALSE; 2128 } 2129 } 2130 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2131 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 2132 } 2133 } 2134 return ret; 2135 } 2136 2137 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value, 2138 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2139 DWORD *pcbEncoded) 2140 { 2141 BOOL ret = TRUE; 2142 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2143 DWORD bytesNeeded, lenBytes, encodedLen; 2144 2145 if (value->Value.cbData) 2146 encodedLen = value->Value.cbData / sizeof(WCHAR); 2147 else if (str) 2148 encodedLen = strlenW(str); 2149 else 2150 encodedLen = 0; 2151 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2152 bytesNeeded = 1 + lenBytes + encodedLen; 2153 if (!pbEncoded) 2154 *pcbEncoded = bytesNeeded; 2155 else 2156 { 2157 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2158 pbEncoded, pcbEncoded, bytesNeeded))) 2159 { 2160 DWORD i; 2161 BYTE *ptr; 2162 2163 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2164 ptr = *(BYTE **)pbEncoded; 2165 else 2166 ptr = pbEncoded; 2167 *ptr++ = ASN_IA5STRING; 2168 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 2169 ptr += lenBytes; 2170 for (i = 0; ret && i < encodedLen; i++) 2171 { 2172 if (str[i] <= 0x7f) 2173 *ptr++ = (BYTE)str[i]; 2174 else 2175 { 2176 *pcbEncoded = i; 2177 SetLastError(CRYPT_E_INVALID_IA5_STRING); 2178 ret = FALSE; 2179 } 2180 } 2181 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2182 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 2183 } 2184 } 2185 return ret; 2186 } 2187 2188 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value, 2189 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2190 DWORD *pcbEncoded) 2191 { 2192 BOOL ret = TRUE; 2193 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2194 DWORD bytesNeeded, lenBytes, strLen; 2195 2196 /* FIXME: doesn't handle composite characters */ 2197 if (value->Value.cbData) 2198 strLen = value->Value.cbData / sizeof(WCHAR); 2199 else if (str) 2200 strLen = strlenW(str); 2201 else 2202 strLen = 0; 2203 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes); 2204 bytesNeeded = 1 + lenBytes + strLen * 4; 2205 if (!pbEncoded) 2206 *pcbEncoded = bytesNeeded; 2207 else 2208 { 2209 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2210 pbEncoded, pcbEncoded, bytesNeeded))) 2211 { 2212 DWORD i; 2213 2214 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2215 pbEncoded = *(BYTE **)pbEncoded; 2216 *pbEncoded++ = ASN_UNIVERSALSTRING; 2217 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes); 2218 pbEncoded += lenBytes; 2219 for (i = 0; i < strLen; i++) 2220 { 2221 *pbEncoded++ = 0; 2222 *pbEncoded++ = 0; 2223 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8); 2224 *pbEncoded++ = (BYTE)(str[i] & 0x00ff); 2225 } 2226 } 2227 } 2228 return ret; 2229 } 2230 2231 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType, 2232 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2233 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2234 { 2235 BOOL ret = FALSE; 2236 2237 __TRY 2238 { 2239 const CERT_NAME_VALUE *value = pvStructInfo; 2240 2241 switch (value->dwValueType) 2242 { 2243 case CERT_RDN_ANY_TYPE: 2244 case CERT_RDN_ENCODED_BLOB: 2245 case CERT_RDN_OCTET_STRING: 2246 SetLastError(CRYPT_E_NOT_CHAR_STRING); 2247 break; 2248 case CERT_RDN_NUMERIC_STRING: 2249 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara, 2250 pbEncoded, pcbEncoded); 2251 break; 2252 case CERT_RDN_PRINTABLE_STRING: 2253 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara, 2254 pbEncoded, pcbEncoded); 2255 break; 2256 case CERT_RDN_TELETEX_STRING: 2257 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING, 2258 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2259 break; 2260 case CERT_RDN_VIDEOTEX_STRING: 2261 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, 2262 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2263 break; 2264 case CERT_RDN_IA5_STRING: 2265 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara, 2266 pbEncoded, pcbEncoded); 2267 break; 2268 case CERT_RDN_GRAPHIC_STRING: 2269 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING, 2270 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2271 break; 2272 case CERT_RDN_VISIBLE_STRING: 2273 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING, 2274 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2275 break; 2276 case CERT_RDN_GENERAL_STRING: 2277 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING, 2278 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2279 break; 2280 case CERT_RDN_UNIVERSAL_STRING: 2281 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara, 2282 pbEncoded, pcbEncoded); 2283 break; 2284 case CERT_RDN_BMP_STRING: 2285 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara, 2286 pbEncoded, pcbEncoded); 2287 break; 2288 case CERT_RDN_UTF8_STRING: 2289 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara, 2290 pbEncoded, pcbEncoded); 2291 break; 2292 default: 2293 SetLastError(CRYPT_E_ASN1_CHOICE); 2294 } 2295 } 2296 __EXCEPT_PAGE_FAULT 2297 { 2298 SetLastError(STATUS_ACCESS_VIOLATION); 2299 } 2300 __ENDTRY 2301 return ret; 2302 } 2303 2304 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType, 2305 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2306 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2307 { 2308 BOOL ret; 2309 2310 __TRY 2311 { 2312 const CERT_NAME_INFO *info = pvStructInfo; 2313 DWORD bytesNeeded = 0, lenBytes, size, i; 2314 2315 TRACE("encoding name with %d RDNs\n", info->cRDN); 2316 ret = TRUE; 2317 for (i = 0; ret && i < info->cRDN; i++) 2318 { 2319 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], 2320 CRYPT_AsnEncodeNameValue, NULL, &size); 2321 if (ret) 2322 bytesNeeded += size; 2323 } 2324 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 2325 bytesNeeded += 1 + lenBytes; 2326 if (ret) 2327 { 2328 if (!pbEncoded) 2329 *pcbEncoded = bytesNeeded; 2330 else 2331 { 2332 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2333 pbEncoded, pcbEncoded, bytesNeeded))) 2334 { 2335 BYTE *out; 2336 2337 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2338 pbEncoded = *(BYTE **)pbEncoded; 2339 out = pbEncoded; 2340 *out++ = ASN_SEQUENCEOF; 2341 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 2342 out += lenBytes; 2343 for (i = 0; ret && i < info->cRDN; i++) 2344 { 2345 size = bytesNeeded; 2346 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, 2347 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size); 2348 if (ret) 2349 { 2350 out += size; 2351 bytesNeeded -= size; 2352 } 2353 } 2354 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2355 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2356 } 2357 } 2358 } 2359 } 2360 __EXCEPT_PAGE_FAULT 2361 { 2362 SetLastError(STATUS_ACCESS_VIOLATION); 2363 ret = FALSE; 2364 } 2365 __ENDTRY 2366 return ret; 2367 } 2368 2369 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, 2370 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2371 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2372 { 2373 BOOL val = *(const BOOL *)pvStructInfo, ret; 2374 2375 TRACE("%d\n", val); 2376 2377 if (!pbEncoded) 2378 { 2379 *pcbEncoded = 3; 2380 ret = TRUE; 2381 } 2382 else if (*pcbEncoded < 3) 2383 { 2384 *pcbEncoded = 3; 2385 SetLastError(ERROR_MORE_DATA); 2386 ret = FALSE; 2387 } 2388 else 2389 { 2390 *pcbEncoded = 3; 2391 *pbEncoded++ = ASN_BOOL; 2392 *pbEncoded++ = 1; 2393 *pbEncoded++ = val ? 0xff : 0; 2394 ret = TRUE; 2395 } 2396 TRACE("returning %d (%08x)\n", ret, GetLastError()); 2397 return ret; 2398 } 2399 2400 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType, 2401 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2402 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2403 { 2404 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo; 2405 BOOL ret; 2406 DWORD dataLen; 2407 BYTE tag; 2408 2409 ret = TRUE; 2410 switch (entry->dwAltNameChoice) 2411 { 2412 case CERT_ALT_NAME_RFC822_NAME: 2413 case CERT_ALT_NAME_DNS_NAME: 2414 case CERT_ALT_NAME_URL: 2415 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1); 2416 if (entry->u.pwszURL) 2417 { 2418 DWORD i; 2419 2420 /* Not + 1: don't encode the NULL-terminator */ 2421 dataLen = lstrlenW(entry->u.pwszURL); 2422 for (i = 0; ret && i < dataLen; i++) 2423 { 2424 if (entry->u.pwszURL[i] > 0x7f) 2425 { 2426 SetLastError(CRYPT_E_INVALID_IA5_STRING); 2427 ret = FALSE; 2428 *pcbEncoded = i; 2429 } 2430 } 2431 } 2432 else 2433 dataLen = 0; 2434 break; 2435 case CERT_ALT_NAME_DIRECTORY_NAME: 2436 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1); 2437 dataLen = entry->u.DirectoryName.cbData; 2438 break; 2439 case CERT_ALT_NAME_IP_ADDRESS: 2440 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1); 2441 dataLen = entry->u.IPAddress.cbData; 2442 break; 2443 case CERT_ALT_NAME_REGISTERED_ID: 2444 { 2445 struct AsnEncodeTagSwappedItem swapped = 2446 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID, 2447 CRYPT_AsnEncodeOid }; 2448 2449 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded, 2450 pcbEncoded); 2451 } 2452 case CERT_ALT_NAME_OTHER_NAME: 2453 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice); 2454 return FALSE; 2455 default: 2456 SetLastError(E_INVALIDARG); 2457 return FALSE; 2458 } 2459 if (ret) 2460 { 2461 DWORD bytesNeeded, lenBytes; 2462 2463 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 2464 bytesNeeded = 1 + dataLen + lenBytes; 2465 if (!pbEncoded) 2466 *pcbEncoded = bytesNeeded; 2467 else if (*pcbEncoded < bytesNeeded) 2468 { 2469 SetLastError(ERROR_MORE_DATA); 2470 *pcbEncoded = bytesNeeded; 2471 ret = FALSE; 2472 } 2473 else 2474 { 2475 *pbEncoded++ = tag; 2476 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 2477 pbEncoded += lenBytes; 2478 switch (entry->dwAltNameChoice) 2479 { 2480 case CERT_ALT_NAME_RFC822_NAME: 2481 case CERT_ALT_NAME_DNS_NAME: 2482 case CERT_ALT_NAME_URL: 2483 { 2484 DWORD i; 2485 2486 for (i = 0; i < dataLen; i++) 2487 *pbEncoded++ = (BYTE)entry->u.pwszURL[i]; 2488 break; 2489 } 2490 case CERT_ALT_NAME_DIRECTORY_NAME: 2491 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen); 2492 break; 2493 case CERT_ALT_NAME_IP_ADDRESS: 2494 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen); 2495 break; 2496 } 2497 if (ret) 2498 *pcbEncoded = bytesNeeded; 2499 } 2500 } 2501 TRACE("returning %d (%08x)\n", ret, GetLastError()); 2502 return ret; 2503 } 2504 2505 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType, 2506 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2507 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2508 { 2509 BOOL ret; 2510 2511 __TRY 2512 { 2513 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo; 2514 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 2515 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 2516 struct AsnConstructedItem constructed = { 0 }; 2517 DWORD cItem = 0, cSwapped = 0; 2518 2519 if (info->KeyId.cbData) 2520 { 2521 swapped[cSwapped].tag = ASN_CONTEXT | 0; 2522 swapped[cSwapped].pvStructInfo = &info->KeyId; 2523 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 2524 items[cItem].pvStructInfo = &swapped[cSwapped]; 2525 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2526 cSwapped++; 2527 cItem++; 2528 } 2529 if (info->CertIssuer.cbData) 2530 { 2531 constructed.tag = 1; 2532 constructed.pvStructInfo = &info->CertIssuer; 2533 constructed.encodeFunc = CRYPT_CopyEncodedBlob; 2534 items[cItem].pvStructInfo = &constructed; 2535 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 2536 cItem++; 2537 } 2538 if (info->CertSerialNumber.cbData) 2539 { 2540 swapped[cSwapped].tag = ASN_CONTEXT | 2; 2541 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber; 2542 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger; 2543 items[cItem].pvStructInfo = &swapped[cSwapped]; 2544 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2545 cSwapped++; 2546 cItem++; 2547 } 2548 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags, 2549 pEncodePara, pbEncoded, pcbEncoded); 2550 } 2551 __EXCEPT_PAGE_FAULT 2552 { 2553 SetLastError(STATUS_ACCESS_VIOLATION); 2554 ret = FALSE; 2555 } 2556 __ENDTRY 2557 return ret; 2558 } 2559 2560 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType, 2561 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2562 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2563 { 2564 BOOL ret; 2565 2566 __TRY 2567 { 2568 const CERT_ALT_NAME_INFO *info = pvStructInfo; 2569 DWORD bytesNeeded, dataLen, lenBytes, i; 2570 2571 ret = TRUE; 2572 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we 2573 * can't encode an erroneous entry index if it's bigger than this. 2574 */ 2575 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++) 2576 { 2577 DWORD len; 2578 2579 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL, 2580 &info->rgAltEntry[i], 0, NULL, NULL, &len); 2581 if (ret) 2582 dataLen += len; 2583 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING) 2584 { 2585 /* CRYPT_AsnEncodeAltNameEntry encoded the index of 2586 * the bad character, now set the index of the bad 2587 * entry 2588 */ 2589 *pcbEncoded = (BYTE)i << 2590 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len; 2591 } 2592 } 2593 if (ret) 2594 { 2595 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 2596 bytesNeeded = 1 + lenBytes + dataLen; 2597 if (!pbEncoded) 2598 { 2599 *pcbEncoded = bytesNeeded; 2600 ret = TRUE; 2601 } 2602 else 2603 { 2604 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2605 pbEncoded, pcbEncoded, bytesNeeded))) 2606 { 2607 BYTE *out; 2608 2609 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2610 pbEncoded = *(BYTE **)pbEncoded; 2611 out = pbEncoded; 2612 *out++ = ASN_SEQUENCEOF; 2613 CRYPT_EncodeLen(dataLen, out, &lenBytes); 2614 out += lenBytes; 2615 for (i = 0; ret && i < info->cAltEntry; i++) 2616 { 2617 DWORD len = dataLen; 2618 2619 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, 2620 NULL, &info->rgAltEntry[i], 0, NULL, out, &len); 2621 if (ret) 2622 { 2623 out += len; 2624 dataLen -= len; 2625 } 2626 } 2627 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2628 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2629 } 2630 } 2631 } 2632 } 2633 __EXCEPT_PAGE_FAULT 2634 { 2635 SetLastError(STATUS_ACCESS_VIOLATION); 2636 ret = FALSE; 2637 } 2638 __ENDTRY 2639 return ret; 2640 } 2641 2642 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType, 2643 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2644 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2645 { 2646 BOOL ret; 2647 2648 __TRY 2649 { 2650 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo; 2651 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 2652 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 2653 DWORD cItem = 0, cSwapped = 0; 2654 2655 if (info->KeyId.cbData) 2656 { 2657 swapped[cSwapped].tag = ASN_CONTEXT | 0; 2658 swapped[cSwapped].pvStructInfo = &info->KeyId; 2659 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 2660 items[cItem].pvStructInfo = &swapped[cSwapped]; 2661 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2662 cSwapped++; 2663 cItem++; 2664 } 2665 if (info->AuthorityCertIssuer.cAltEntry) 2666 { 2667 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 2668 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer; 2669 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 2670 items[cItem].pvStructInfo = &swapped[cSwapped]; 2671 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2672 cSwapped++; 2673 cItem++; 2674 } 2675 if (info->AuthorityCertSerialNumber.cbData) 2676 { 2677 swapped[cSwapped].tag = ASN_CONTEXT | 2; 2678 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber; 2679 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger; 2680 items[cItem].pvStructInfo = &swapped[cSwapped]; 2681 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2682 cSwapped++; 2683 cItem++; 2684 } 2685 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags, 2686 pEncodePara, pbEncoded, pcbEncoded); 2687 } 2688 __EXCEPT_PAGE_FAULT 2689 { 2690 SetLastError(STATUS_ACCESS_VIOLATION); 2691 ret = FALSE; 2692 } 2693 __ENDTRY 2694 return ret; 2695 } 2696 2697 static BOOL CRYPT_AsnEncodeAccessDescription( 2698 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded) 2699 { 2700 struct AsnEncodeSequenceItem items[] = { 2701 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 }, 2702 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 }, 2703 }; 2704 2705 if (!descr->pszAccessMethod) 2706 { 2707 SetLastError(E_INVALIDARG); 2708 return FALSE; 2709 } 2710 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded); 2711 } 2712 2713 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType, 2714 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2715 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2716 { 2717 BOOL ret; 2718 2719 __TRY 2720 { 2721 DWORD bytesNeeded, dataLen, lenBytes, i; 2722 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo; 2723 2724 ret = TRUE; 2725 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++) 2726 { 2727 DWORD size; 2728 2729 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL, 2730 &size); 2731 if (ret) 2732 dataLen += size; 2733 } 2734 if (ret) 2735 { 2736 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 2737 bytesNeeded = 1 + lenBytes + dataLen; 2738 if (!pbEncoded) 2739 *pcbEncoded = bytesNeeded; 2740 else 2741 { 2742 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2743 pbEncoded, pcbEncoded, bytesNeeded))) 2744 { 2745 BYTE *out; 2746 2747 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2748 pbEncoded = *(BYTE **)pbEncoded; 2749 out = pbEncoded; 2750 *out++ = ASN_SEQUENCEOF; 2751 CRYPT_EncodeLen(dataLen, out, &lenBytes); 2752 out += lenBytes; 2753 for (i = 0; i < info->cAccDescr; i++) 2754 { 2755 DWORD size = dataLen; 2756 2757 ret = CRYPT_AsnEncodeAccessDescription( 2758 &info->rgAccDescr[i], out, &size); 2759 out += size; 2760 dataLen -= size; 2761 } 2762 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2763 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2764 } 2765 } 2766 } 2767 } 2768 __EXCEPT_PAGE_FAULT 2769 { 2770 SetLastError(STATUS_ACCESS_VIOLATION); 2771 ret = FALSE; 2772 } 2773 __ENDTRY 2774 return ret; 2775 } 2776 2777 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType, 2778 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2779 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2780 { 2781 BOOL ret; 2782 2783 __TRY 2784 { 2785 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo; 2786 struct AsnEncodeSequenceItem items[3] = { 2787 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 }, 2788 { 0 } 2789 }; 2790 DWORD cItem = 1; 2791 2792 if (info->fPathLenConstraint) 2793 { 2794 items[cItem].pvStructInfo = &info->dwPathLenConstraint; 2795 items[cItem].encodeFunc = CRYPT_AsnEncodeInt; 2796 cItem++; 2797 } 2798 if (info->cSubtreesConstraint) 2799 { 2800 items[cItem].pvStructInfo = &info->cSubtreesConstraint; 2801 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny; 2802 cItem++; 2803 } 2804 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 2805 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2806 } 2807 __EXCEPT_PAGE_FAULT 2808 { 2809 SetLastError(STATUS_ACCESS_VIOLATION); 2810 ret = FALSE; 2811 } 2812 __ENDTRY 2813 return ret; 2814 } 2815 2816 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType, 2817 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2818 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2819 { 2820 BOOL ret; 2821 2822 __TRY 2823 { 2824 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo; 2825 struct AsnEncodeSequenceItem items[2] = { { 0 } }; 2826 DWORD cItem = 0; 2827 2828 if (info->fCA) 2829 { 2830 items[cItem].pvStructInfo = &info->fCA; 2831 items[cItem].encodeFunc = CRYPT_AsnEncodeBool; 2832 cItem++; 2833 } 2834 if (info->fPathLenConstraint) 2835 { 2836 items[cItem].pvStructInfo = &info->dwPathLenConstraint; 2837 items[cItem].encodeFunc = CRYPT_AsnEncodeInt; 2838 cItem++; 2839 } 2840 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 2841 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2842 } 2843 __EXCEPT_PAGE_FAULT 2844 { 2845 SetLastError(STATUS_ACCESS_VIOLATION); 2846 ret = FALSE; 2847 } 2848 __ENDTRY 2849 return ret; 2850 } 2851 2852 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType, 2853 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2854 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2855 { 2856 const CERT_POLICY_INFO *info = pvStructInfo; 2857 BOOL ret; 2858 2859 if (!info->cPolicyQualifier) 2860 { 2861 *pcbEncoded = 0; 2862 ret = TRUE; 2863 } 2864 else 2865 { 2866 struct AsnEncodeSequenceItem items[2] = { 2867 { NULL, CRYPT_AsnEncodeOid, 0 }, 2868 { NULL, CRYPT_CopyEncodedBlob, 0 }, 2869 }; 2870 DWORD bytesNeeded = 0, lenBytes, size, i; 2871 2872 ret = TRUE; 2873 for (i = 0; ret && i < info->cPolicyQualifier; i++) 2874 { 2875 items[0].pvStructInfo = 2876 info->rgPolicyQualifier[i].pszPolicyQualifierId; 2877 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier; 2878 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), 2879 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size); 2880 if (ret) 2881 bytesNeeded += size; 2882 } 2883 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 2884 bytesNeeded += 1 + lenBytes; 2885 if (ret) 2886 { 2887 if (!pbEncoded) 2888 *pcbEncoded = bytesNeeded; 2889 else 2890 { 2891 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2892 pbEncoded, pcbEncoded, bytesNeeded))) 2893 { 2894 BYTE *out; 2895 2896 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2897 pbEncoded = *(BYTE **)pbEncoded; 2898 out = pbEncoded; 2899 *out++ = ASN_SEQUENCEOF; 2900 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 2901 out += lenBytes; 2902 for (i = 0; ret && i < info->cPolicyQualifier; i++) 2903 { 2904 items[0].pvStructInfo = 2905 info->rgPolicyQualifier[i].pszPolicyQualifierId; 2906 items[1].pvStructInfo = 2907 &info->rgPolicyQualifier[i].Qualifier; 2908 size = bytesNeeded; 2909 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), 2910 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size); 2911 if (ret) 2912 { 2913 out += size; 2914 bytesNeeded -= size; 2915 } 2916 } 2917 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2918 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2919 } 2920 } 2921 } 2922 } 2923 return ret; 2924 } 2925 2926 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType, 2927 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded, 2928 DWORD *pcbEncoded) 2929 { 2930 struct AsnEncodeSequenceItem items[2] = { 2931 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 }, 2932 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 }, 2933 }; 2934 BOOL ret; 2935 2936 if (!info->pszPolicyIdentifier) 2937 { 2938 SetLastError(E_INVALIDARG); 2939 return FALSE; 2940 } 2941 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded); 2942 return ret; 2943 } 2944 2945 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType, 2946 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2947 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2948 { 2949 BOOL ret = FALSE; 2950 2951 __TRY 2952 { 2953 const CERT_POLICIES_INFO *info = pvStructInfo; 2954 DWORD bytesNeeded = 0, lenBytes, size, i; 2955 2956 ret = TRUE; 2957 for (i = 0; ret && i < info->cPolicyInfo; i++) 2958 { 2959 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType, 2960 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, 2961 &size); 2962 if (ret) 2963 bytesNeeded += size; 2964 } 2965 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 2966 bytesNeeded += 1 + lenBytes; 2967 if (ret) 2968 { 2969 if (!pbEncoded) 2970 *pcbEncoded = bytesNeeded; 2971 else 2972 { 2973 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2974 pbEncoded, pcbEncoded, bytesNeeded))) 2975 { 2976 BYTE *out; 2977 2978 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2979 pbEncoded = *(BYTE **)pbEncoded; 2980 out = pbEncoded; 2981 *out++ = ASN_SEQUENCEOF; 2982 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 2983 out += lenBytes; 2984 for (i = 0; ret && i < info->cPolicyInfo; i++) 2985 { 2986 size = bytesNeeded; 2987 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType, 2988 &info->rgPolicyInfo[i], 2989 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size); 2990 if (ret) 2991 { 2992 out += size; 2993 bytesNeeded -= size; 2994 } 2995 } 2996 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2997 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2998 } 2999 } 3000 } 3001 } 3002 __EXCEPT_PAGE_FAULT 3003 { 3004 SetLastError(STATUS_ACCESS_VIOLATION); 3005 } 3006 __ENDTRY 3007 return ret; 3008 } 3009 3010 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType, 3011 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded, 3012 DWORD *pcbEncoded) 3013 { 3014 struct AsnEncodeSequenceItem items[] = { 3015 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 }, 3016 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 }, 3017 }; 3018 3019 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy) 3020 { 3021 SetLastError(E_INVALIDARG); 3022 return FALSE; 3023 } 3024 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded); 3025 } 3026 3027 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType, 3028 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3029 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3030 { 3031 BOOL ret = FALSE; 3032 3033 __TRY 3034 { 3035 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo; 3036 DWORD bytesNeeded = 0, lenBytes, size, i; 3037 3038 ret = TRUE; 3039 for (i = 0; ret && i < info->cPolicyMapping; i++) 3040 { 3041 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType, 3042 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, 3043 NULL, &size); 3044 if (ret) 3045 bytesNeeded += size; 3046 } 3047 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 3048 bytesNeeded += 1 + lenBytes; 3049 if (ret) 3050 { 3051 if (!pbEncoded) 3052 *pcbEncoded = bytesNeeded; 3053 else 3054 { 3055 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3056 pbEncoded, pcbEncoded, bytesNeeded))) 3057 { 3058 BYTE *out; 3059 3060 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3061 pbEncoded = *(BYTE **)pbEncoded; 3062 out = pbEncoded; 3063 *out++ = ASN_SEQUENCEOF; 3064 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 3065 out += lenBytes; 3066 for (i = 0; ret && i < info->cPolicyMapping; i++) 3067 { 3068 size = bytesNeeded; 3069 ret = CRYPT_AsnEncodeCertPolicyMapping( 3070 dwCertEncodingType, &info->rgPolicyMapping[i], 3071 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size); 3072 if (ret) 3073 { 3074 out += size; 3075 bytesNeeded -= size; 3076 } 3077 } 3078 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 3079 CRYPT_FreeSpace(pEncodePara, pbEncoded); 3080 } 3081 } 3082 } 3083 } 3084 __EXCEPT_PAGE_FAULT 3085 { 3086 SetLastError(STATUS_ACCESS_VIOLATION); 3087 } 3088 __ENDTRY 3089 return ret; 3090 } 3091 3092 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints( 3093 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 3094 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 3095 DWORD *pcbEncoded) 3096 { 3097 BOOL ret = FALSE; 3098 3099 __TRY 3100 { 3101 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo; 3102 struct AsnEncodeSequenceItem items[2]; 3103 struct AsnEncodeTagSwappedItem swapped[2]; 3104 DWORD cItem = 0, cSwapped = 0; 3105 3106 if (info->fRequireExplicitPolicy) 3107 { 3108 swapped[cSwapped].tag = ASN_CONTEXT | 0; 3109 swapped[cSwapped].pvStructInfo = 3110 &info->dwRequireExplicitPolicySkipCerts; 3111 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 3112 items[cItem].pvStructInfo = &swapped[cSwapped]; 3113 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3114 cSwapped++; 3115 cItem++; 3116 } 3117 if (info->fInhibitPolicyMapping) 3118 { 3119 swapped[cSwapped].tag = ASN_CONTEXT | 1; 3120 swapped[cSwapped].pvStructInfo = 3121 &info->dwInhibitPolicyMappingSkipCerts; 3122 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 3123 items[cItem].pvStructInfo = &swapped[cSwapped]; 3124 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3125 cSwapped++; 3126 cItem++; 3127 } 3128 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 3129 dwFlags, NULL, pbEncoded, pcbEncoded); 3130 } 3131 __EXCEPT_PAGE_FAULT 3132 { 3133 SetLastError(STATUS_ACCESS_VIOLATION); 3134 } 3135 __ENDTRY 3136 return ret; 3137 } 3138 3139 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType, 3140 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3141 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3142 { 3143 BOOL ret; 3144 3145 __TRY 3146 { 3147 const BLOBHEADER *hdr = pvStructInfo; 3148 3149 if (hdr->bType != PUBLICKEYBLOB) 3150 { 3151 SetLastError(E_INVALIDARG); 3152 ret = FALSE; 3153 } 3154 else 3155 { 3156 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *) 3157 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER)); 3158 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8, 3159 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) }; 3160 struct AsnEncodeSequenceItem items[] = { 3161 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 }, 3162 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 }, 3163 }; 3164 3165 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 3166 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3167 } 3168 } 3169 __EXCEPT_PAGE_FAULT 3170 { 3171 SetLastError(STATUS_ACCESS_VIOLATION); 3172 ret = FALSE; 3173 } 3174 __ENDTRY 3175 return ret; 3176 } 3177 3178 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType, 3179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3181 { 3182 BOOL ret; 3183 3184 __TRY 3185 { 3186 const CRYPT_DATA_BLOB *blob = pvStructInfo; 3187 DWORD bytesNeeded, lenBytes; 3188 3189 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData, 3190 dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0); 3191 3192 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes); 3193 bytesNeeded = 1 + lenBytes + blob->cbData; 3194 if (!pbEncoded) 3195 { 3196 *pcbEncoded = bytesNeeded; 3197 ret = TRUE; 3198 } 3199 else 3200 { 3201 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3202 pcbEncoded, bytesNeeded))) 3203 { 3204 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3205 pbEncoded = *(BYTE **)pbEncoded; 3206 *pbEncoded++ = ASN_OCTETSTRING; 3207 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes); 3208 pbEncoded += lenBytes; 3209 if (blob->cbData) 3210 memcpy(pbEncoded, blob->pbData, blob->cbData); 3211 } 3212 } 3213 } 3214 __EXCEPT_PAGE_FAULT 3215 { 3216 SetLastError(STATUS_ACCESS_VIOLATION); 3217 ret = FALSE; 3218 } 3219 __ENDTRY 3220 TRACE("returning %d (%08x)\n", ret, GetLastError()); 3221 return ret; 3222 } 3223 3224 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, 3225 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3226 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3227 { 3228 BOOL ret; 3229 3230 __TRY 3231 { 3232 const CRYPT_BIT_BLOB *blob = pvStructInfo; 3233 DWORD bytesNeeded, lenBytes, dataBytes; 3234 BYTE unusedBits; 3235 3236 /* yep, MS allows cUnusedBits to be >= 8 */ 3237 if (!blob->cUnusedBits) 3238 { 3239 dataBytes = blob->cbData; 3240 unusedBits = 0; 3241 } 3242 else if (blob->cbData * 8 > blob->cUnusedBits) 3243 { 3244 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1; 3245 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 : 3246 blob->cUnusedBits; 3247 } 3248 else 3249 { 3250 dataBytes = 0; 3251 unusedBits = 0; 3252 } 3253 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes); 3254 bytesNeeded = 1 + lenBytes + dataBytes + 1; 3255 if (!pbEncoded) 3256 { 3257 *pcbEncoded = bytesNeeded; 3258 ret = TRUE; 3259 } 3260 else 3261 { 3262 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3263 pcbEncoded, bytesNeeded))) 3264 { 3265 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3266 pbEncoded = *(BYTE **)pbEncoded; 3267 *pbEncoded++ = ASN_BITSTRING; 3268 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes); 3269 pbEncoded += lenBytes; 3270 *pbEncoded++ = unusedBits; 3271 if (dataBytes) 3272 { 3273 BYTE mask = 0xff << unusedBits; 3274 3275 if (dataBytes > 1) 3276 { 3277 memcpy(pbEncoded, blob->pbData, dataBytes - 1); 3278 pbEncoded += dataBytes - 1; 3279 } 3280 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask; 3281 } 3282 } 3283 } 3284 } 3285 __EXCEPT_PAGE_FAULT 3286 { 3287 SetLastError(STATUS_ACCESS_VIOLATION); 3288 ret = FALSE; 3289 } 3290 __ENDTRY 3291 return ret; 3292 } 3293 3294 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType, 3295 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3296 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3297 { 3298 BOOL ret; 3299 3300 __TRY 3301 { 3302 const CRYPT_BIT_BLOB *blob = pvStructInfo; 3303 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits }; 3304 3305 ret = TRUE; 3306 if (newBlob.cbData) 3307 { 3308 newBlob.pbData = CryptMemAlloc(newBlob.cbData); 3309 if (newBlob.pbData) 3310 { 3311 DWORD i; 3312 3313 for (i = 0; i < newBlob.cbData; i++) 3314 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i]; 3315 } 3316 else 3317 ret = FALSE; 3318 } 3319 if (ret) 3320 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType, 3321 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3322 CryptMemFree(newBlob.pbData); 3323 } 3324 __EXCEPT_PAGE_FAULT 3325 { 3326 SetLastError(STATUS_ACCESS_VIOLATION); 3327 ret = FALSE; 3328 } 3329 __ENDTRY 3330 return ret; 3331 } 3332 3333 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, 3334 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3335 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3336 { 3337 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo }; 3338 3339 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER, 3340 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3341 } 3342 3343 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, 3344 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3345 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3346 { 3347 BOOL ret; 3348 3349 __TRY 3350 { 3351 DWORD significantBytes, lenBytes, bytesNeeded; 3352 BYTE padByte = 0; 3353 BOOL pad = FALSE; 3354 const CRYPT_INTEGER_BLOB *blob = pvStructInfo; 3355 3356 significantBytes = blob->cbData; 3357 if (significantBytes) 3358 { 3359 if (blob->pbData[significantBytes - 1] & 0x80) 3360 { 3361 /* negative, lop off leading (little-endian) 0xffs */ 3362 for (; significantBytes > 0 && 3363 blob->pbData[significantBytes - 1] == 0xff; significantBytes--) 3364 ; 3365 if (blob->pbData[significantBytes - 1] < 0x80) 3366 { 3367 padByte = 0xff; 3368 pad = TRUE; 3369 } 3370 } 3371 else 3372 { 3373 /* positive, lop off leading (little-endian) zeroes */ 3374 for (; significantBytes > 0 && 3375 !blob->pbData[significantBytes - 1]; significantBytes--) 3376 ; 3377 if (significantBytes == 0) 3378 significantBytes = 1; 3379 if (blob->pbData[significantBytes - 1] > 0x7f) 3380 { 3381 padByte = 0; 3382 pad = TRUE; 3383 } 3384 } 3385 } 3386 if (pad) 3387 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); 3388 else 3389 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); 3390 bytesNeeded = 1 + lenBytes + significantBytes; 3391 if (pad) 3392 bytesNeeded++; 3393 if (!pbEncoded) 3394 { 3395 *pcbEncoded = bytesNeeded; 3396 ret = TRUE; 3397 } 3398 else 3399 { 3400 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3401 pcbEncoded, bytesNeeded))) 3402 { 3403 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3404 pbEncoded = *(BYTE **)pbEncoded; 3405 *pbEncoded++ = ASN_INTEGER; 3406 if (pad) 3407 { 3408 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); 3409 pbEncoded += lenBytes; 3410 *pbEncoded++ = padByte; 3411 } 3412 else 3413 { 3414 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); 3415 pbEncoded += lenBytes; 3416 } 3417 for (; significantBytes > 0; significantBytes--) 3418 *(pbEncoded++) = blob->pbData[significantBytes - 1]; 3419 } 3420 } 3421 } 3422 __EXCEPT_PAGE_FAULT 3423 { 3424 SetLastError(STATUS_ACCESS_VIOLATION); 3425 ret = FALSE; 3426 } 3427 __ENDTRY 3428 return ret; 3429 } 3430 3431 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, 3432 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3433 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3434 { 3435 BOOL ret; 3436 3437 __TRY 3438 { 3439 DWORD significantBytes, lenBytes, bytesNeeded; 3440 BOOL pad = FALSE; 3441 const CRYPT_INTEGER_BLOB *blob = pvStructInfo; 3442 3443 significantBytes = blob->cbData; 3444 if (significantBytes) 3445 { 3446 /* positive, lop off leading (little-endian) zeroes */ 3447 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1]; 3448 significantBytes--) 3449 ; 3450 if (significantBytes == 0) 3451 significantBytes = 1; 3452 if (blob->pbData[significantBytes - 1] > 0x7f) 3453 pad = TRUE; 3454 } 3455 if (pad) 3456 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); 3457 else 3458 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); 3459 bytesNeeded = 1 + lenBytes + significantBytes; 3460 if (pad) 3461 bytesNeeded++; 3462 if (!pbEncoded) 3463 { 3464 *pcbEncoded = bytesNeeded; 3465 ret = TRUE; 3466 } 3467 else 3468 { 3469 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3470 pcbEncoded, bytesNeeded))) 3471 { 3472 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3473 pbEncoded = *(BYTE **)pbEncoded; 3474 *pbEncoded++ = ASN_INTEGER; 3475 if (pad) 3476 { 3477 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); 3478 pbEncoded += lenBytes; 3479 *pbEncoded++ = 0; 3480 } 3481 else 3482 { 3483 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); 3484 pbEncoded += lenBytes; 3485 } 3486 for (; significantBytes > 0; significantBytes--) 3487 *(pbEncoded++) = blob->pbData[significantBytes - 1]; 3488 } 3489 } 3490 } 3491 __EXCEPT_PAGE_FAULT 3492 { 3493 SetLastError(STATUS_ACCESS_VIOLATION); 3494 ret = FALSE; 3495 } 3496 __ENDTRY 3497 return ret; 3498 } 3499 3500 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType, 3501 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3502 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3503 { 3504 CRYPT_INTEGER_BLOB blob; 3505 BOOL ret; 3506 3507 /* Encode as an unsigned integer, then change the tag to enumerated */ 3508 blob.cbData = sizeof(DWORD); 3509 blob.pbData = (BYTE *)pvStructInfo; 3510 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType, 3511 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3512 if (ret && pbEncoded) 3513 { 3514 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3515 pbEncoded = *(BYTE **)pbEncoded; 3516 pbEncoded[0] = ASN_ENUMERATED; 3517 } 3518 return ret; 3519 } 3520 3521 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType, 3522 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3523 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3524 { 3525 BOOL ret; 3526 3527 __TRY 3528 { 3529 SYSTEMTIME sysTime; 3530 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a 3531 * temporary buffer because the output buffer is not NULL-terminated. 3532 */ 3533 static const DWORD bytesNeeded = 15; 3534 char buf[40]; 3535 3536 if (!pbEncoded) 3537 { 3538 *pcbEncoded = bytesNeeded; 3539 ret = TRUE; 3540 } 3541 else 3542 { 3543 /* Sanity check the year, this is a two-digit year format */ 3544 ret = FileTimeToSystemTime(pvStructInfo, &sysTime); 3545 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050)) 3546 { 3547 SetLastError(CRYPT_E_BAD_ENCODE); 3548 ret = FALSE; 3549 } 3550 if (ret) 3551 { 3552 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3553 pbEncoded, pcbEncoded, bytesNeeded))) 3554 { 3555 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3556 pbEncoded = *(BYTE **)pbEncoded; 3557 buf[0] = ASN_UTCTIME; 3558 buf[1] = bytesNeeded - 2; 3559 snprintf(buf + 2, sizeof(buf) - 2, 3560 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ? 3561 sysTime.wYear - 2000 : sysTime.wYear - 1900, 3562 sysTime.wMonth, sysTime.wDay, sysTime.wHour, 3563 sysTime.wMinute, sysTime.wSecond); 3564 memcpy(pbEncoded, buf, bytesNeeded); 3565 } 3566 } 3567 } 3568 } 3569 __EXCEPT_PAGE_FAULT 3570 { 3571 SetLastError(STATUS_ACCESS_VIOLATION); 3572 ret = FALSE; 3573 } 3574 __ENDTRY 3575 return ret; 3576 } 3577 3578 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType, 3579 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3580 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3581 { 3582 BOOL ret; 3583 3584 __TRY 3585 { 3586 SYSTEMTIME sysTime; 3587 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a 3588 * temporary buffer because the output buffer is not NULL-terminated. 3589 */ 3590 static const DWORD bytesNeeded = 17; 3591 char buf[40]; 3592 3593 if (!pbEncoded) 3594 { 3595 *pcbEncoded = bytesNeeded; 3596 ret = TRUE; 3597 } 3598 else 3599 { 3600 ret = FileTimeToSystemTime(pvStructInfo, &sysTime); 3601 if (ret) 3602 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3603 pcbEncoded, bytesNeeded); 3604 if (ret) 3605 { 3606 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3607 pbEncoded = *(BYTE **)pbEncoded; 3608 buf[0] = ASN_GENERALTIME; 3609 buf[1] = bytesNeeded - 2; 3610 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ", 3611 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, 3612 sysTime.wMinute, sysTime.wSecond); 3613 memcpy(pbEncoded, buf, bytesNeeded); 3614 } 3615 } 3616 } 3617 __EXCEPT_PAGE_FAULT 3618 { 3619 SetLastError(STATUS_ACCESS_VIOLATION); 3620 ret = FALSE; 3621 } 3622 __ENDTRY 3623 return ret; 3624 } 3625 3626 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, 3627 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3628 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3629 { 3630 BOOL ret; 3631 3632 __TRY 3633 { 3634 SYSTEMTIME sysTime; 3635 3636 /* Check the year, if it's in the UTCTime range call that encode func */ 3637 if (!FileTimeToSystemTime(pvStructInfo, &sysTime)) 3638 return FALSE; 3639 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050) 3640 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType, 3641 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3642 else 3643 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType, 3644 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded, 3645 pcbEncoded); 3646 } 3647 __EXCEPT_PAGE_FAULT 3648 { 3649 SetLastError(STATUS_ACCESS_VIOLATION); 3650 ret = FALSE; 3651 } 3652 __ENDTRY 3653 return ret; 3654 } 3655 3656 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, 3657 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3658 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3659 { 3660 BOOL ret; 3661 3662 __TRY 3663 { 3664 DWORD bytesNeeded, dataLen, lenBytes, i; 3665 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo; 3666 3667 for (i = 0, dataLen = 0; i < seq->cValue; i++) 3668 dataLen += seq->rgValue[i].cbData; 3669 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 3670 bytesNeeded = 1 + lenBytes + dataLen; 3671 if (!pbEncoded) 3672 { 3673 *pcbEncoded = bytesNeeded; 3674 ret = TRUE; 3675 } 3676 else 3677 { 3678 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3679 pcbEncoded, bytesNeeded))) 3680 { 3681 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3682 pbEncoded = *(BYTE **)pbEncoded; 3683 *pbEncoded++ = ASN_SEQUENCEOF; 3684 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 3685 pbEncoded += lenBytes; 3686 for (i = 0; i < seq->cValue; i++) 3687 { 3688 memcpy(pbEncoded, seq->rgValue[i].pbData, 3689 seq->rgValue[i].cbData); 3690 pbEncoded += seq->rgValue[i].cbData; 3691 } 3692 } 3693 } 3694 } 3695 __EXCEPT_PAGE_FAULT 3696 { 3697 SetLastError(STATUS_ACCESS_VIOLATION); 3698 ret = FALSE; 3699 } 3700 __ENDTRY 3701 return ret; 3702 } 3703 3704 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint, 3705 BYTE *pbEncoded, DWORD *pcbEncoded) 3706 { 3707 BOOL ret = TRUE; 3708 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 3709 struct AsnConstructedItem constructed = { 0 }; 3710 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 3711 DWORD cItem = 0, cSwapped = 0; 3712 3713 switch (distPoint->DistPointName.dwDistPointNameChoice) 3714 { 3715 case CRL_DIST_POINT_NO_NAME: 3716 /* do nothing */ 3717 break; 3718 case CRL_DIST_POINT_FULL_NAME: 3719 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 3720 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName; 3721 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 3722 constructed.tag = 0; 3723 constructed.pvStructInfo = &swapped[cSwapped]; 3724 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag; 3725 items[cItem].pvStructInfo = &constructed; 3726 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 3727 cSwapped++; 3728 cItem++; 3729 break; 3730 case CRL_DIST_POINT_ISSUER_RDN_NAME: 3731 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n"); 3732 ret = FALSE; 3733 break; 3734 default: 3735 ret = FALSE; 3736 } 3737 if (ret && distPoint->ReasonFlags.cbData) 3738 { 3739 swapped[cSwapped].tag = ASN_CONTEXT | 1; 3740 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags; 3741 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 3742 items[cItem].pvStructInfo = &swapped[cSwapped]; 3743 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3744 cSwapped++; 3745 cItem++; 3746 } 3747 if (ret && distPoint->CRLIssuer.cAltEntry) 3748 { 3749 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2; 3750 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer; 3751 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 3752 items[cItem].pvStructInfo = &swapped[cSwapped]; 3753 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3754 cSwapped++; 3755 cItem++; 3756 } 3757 if (ret) 3758 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, 3759 pbEncoded, pcbEncoded); 3760 return ret; 3761 } 3762 3763 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType, 3764 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3765 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3766 { 3767 BOOL ret; 3768 3769 __TRY 3770 { 3771 const CRL_DIST_POINTS_INFO *info = pvStructInfo; 3772 3773 if (!info->cDistPoint) 3774 { 3775 SetLastError(E_INVALIDARG); 3776 ret = FALSE; 3777 } 3778 else 3779 { 3780 DWORD bytesNeeded, dataLen, lenBytes, i; 3781 3782 ret = TRUE; 3783 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++) 3784 { 3785 DWORD len; 3786 3787 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL, 3788 &len); 3789 if (ret) 3790 dataLen += len; 3791 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING) 3792 { 3793 /* Have to propagate index of failing character */ 3794 *pcbEncoded = len; 3795 } 3796 } 3797 if (ret) 3798 { 3799 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 3800 bytesNeeded = 1 + lenBytes + dataLen; 3801 if (!pbEncoded) 3802 { 3803 *pcbEncoded = bytesNeeded; 3804 ret = TRUE; 3805 } 3806 else 3807 { 3808 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3809 pbEncoded, pcbEncoded, bytesNeeded))) 3810 { 3811 BYTE *out; 3812 3813 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3814 pbEncoded = *(BYTE **)pbEncoded; 3815 out = pbEncoded; 3816 *out++ = ASN_SEQUENCEOF; 3817 CRYPT_EncodeLen(dataLen, out, &lenBytes); 3818 out += lenBytes; 3819 for (i = 0; ret && i < info->cDistPoint; i++) 3820 { 3821 DWORD len = dataLen; 3822 3823 ret = CRYPT_AsnEncodeDistPoint( 3824 &info->rgDistPoint[i], out, &len); 3825 if (ret) 3826 { 3827 out += len; 3828 dataLen -= len; 3829 } 3830 } 3831 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 3832 CRYPT_FreeSpace(pEncodePara, pbEncoded); 3833 } 3834 } 3835 } 3836 } 3837 } 3838 __EXCEPT_PAGE_FAULT 3839 { 3840 SetLastError(STATUS_ACCESS_VIOLATION); 3841 ret = FALSE; 3842 } 3843 __ENDTRY 3844 return ret; 3845 } 3846 3847 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType, 3848 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3849 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3850 { 3851 BOOL ret; 3852 3853 __TRY 3854 { 3855 const CERT_ENHKEY_USAGE *usage = pvStructInfo; 3856 DWORD bytesNeeded = 0, lenBytes, size, i; 3857 3858 ret = TRUE; 3859 for (i = 0; ret && i < usage->cUsageIdentifier; i++) 3860 { 3861 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 3862 usage->rgpszUsageIdentifier[i], 3863 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size); 3864 if (ret) 3865 bytesNeeded += size; 3866 } 3867 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 3868 bytesNeeded += 1 + lenBytes; 3869 if (ret) 3870 { 3871 if (!pbEncoded) 3872 *pcbEncoded = bytesNeeded; 3873 else 3874 { 3875 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3876 pbEncoded, pcbEncoded, bytesNeeded))) 3877 { 3878 BYTE *out; 3879 3880 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3881 pbEncoded = *(BYTE **)pbEncoded; 3882 out = pbEncoded; 3883 *out++ = ASN_SEQUENCEOF; 3884 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 3885 out += lenBytes; 3886 for (i = 0; ret && i < usage->cUsageIdentifier; i++) 3887 { 3888 size = bytesNeeded; 3889 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 3890 usage->rgpszUsageIdentifier[i], 3891 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size); 3892 if (ret) 3893 { 3894 out += size; 3895 bytesNeeded -= size; 3896 } 3897 } 3898 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 3899 CRYPT_FreeSpace(pEncodePara, pbEncoded); 3900 } 3901 } 3902 } 3903 } 3904 __EXCEPT_PAGE_FAULT 3905 { 3906 SetLastError(STATUS_ACCESS_VIOLATION); 3907 ret = FALSE; 3908 } 3909 __ENDTRY 3910 return ret; 3911 } 3912 3913 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType, 3914 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3915 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3916 { 3917 BOOL ret; 3918 3919 __TRY 3920 { 3921 const CRL_ISSUING_DIST_POINT *point = pvStructInfo; 3922 struct AsnEncodeSequenceItem items[6] = { { 0 } }; 3923 struct AsnConstructedItem constructed = { 0 }; 3924 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } }; 3925 DWORD cItem = 0, cSwapped = 0; 3926 3927 ret = TRUE; 3928 switch (point->DistPointName.dwDistPointNameChoice) 3929 { 3930 case CRL_DIST_POINT_NO_NAME: 3931 /* do nothing */ 3932 break; 3933 case CRL_DIST_POINT_FULL_NAME: 3934 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 3935 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName; 3936 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 3937 constructed.tag = 0; 3938 constructed.pvStructInfo = &swapped[cSwapped]; 3939 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag; 3940 items[cItem].pvStructInfo = &constructed; 3941 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 3942 cSwapped++; 3943 cItem++; 3944 break; 3945 default: 3946 SetLastError(E_INVALIDARG); 3947 ret = FALSE; 3948 } 3949 if (ret && point->fOnlyContainsUserCerts) 3950 { 3951 swapped[cSwapped].tag = ASN_CONTEXT | 1; 3952 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts; 3953 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 3954 items[cItem].pvStructInfo = &swapped[cSwapped]; 3955 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3956 cSwapped++; 3957 cItem++; 3958 } 3959 if (ret && point->fOnlyContainsCACerts) 3960 { 3961 swapped[cSwapped].tag = ASN_CONTEXT | 2; 3962 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts; 3963 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 3964 items[cItem].pvStructInfo = &swapped[cSwapped]; 3965 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3966 cSwapped++; 3967 cItem++; 3968 } 3969 if (ret && point->OnlySomeReasonFlags.cbData) 3970 { 3971 swapped[cSwapped].tag = ASN_CONTEXT | 3; 3972 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags; 3973 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 3974 items[cItem].pvStructInfo = &swapped[cSwapped]; 3975 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3976 cSwapped++; 3977 cItem++; 3978 } 3979 if (ret && point->fIndirectCRL) 3980 { 3981 swapped[cSwapped].tag = ASN_CONTEXT | 4; 3982 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL; 3983 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 3984 items[cItem].pvStructInfo = &swapped[cSwapped]; 3985 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3986 cSwapped++; 3987 cItem++; 3988 } 3989 if (ret) 3990 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 3991 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3992 } 3993 __EXCEPT_PAGE_FAULT 3994 { 3995 SetLastError(STATUS_ACCESS_VIOLATION); 3996 ret = FALSE; 3997 } 3998 __ENDTRY 3999 return ret; 4000 } 4001 4002 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType, 4003 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4004 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4005 { 4006 BOOL ret; 4007 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo; 4008 struct AsnEncodeSequenceItem items[3] = { 4009 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 }, 4010 { 0 } 4011 }; 4012 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4013 DWORD cItem = 1, cSwapped = 0; 4014 4015 if (subtree->dwMinimum) 4016 { 4017 swapped[cSwapped].tag = ASN_CONTEXT | 0; 4018 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum; 4019 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 4020 items[cItem].pvStructInfo = &swapped[cSwapped]; 4021 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4022 cSwapped++; 4023 cItem++; 4024 } 4025 if (subtree->fMaximum) 4026 { 4027 swapped[cSwapped].tag = ASN_CONTEXT | 1; 4028 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum; 4029 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 4030 items[cItem].pvStructInfo = &swapped[cSwapped]; 4031 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4032 cSwapped++; 4033 cItem++; 4034 } 4035 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags, 4036 pEncodePara, pbEncoded, pcbEncoded); 4037 return ret; 4038 } 4039 4040 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType, 4041 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4042 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4043 { 4044 BOOL ret = FALSE; 4045 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL }; 4046 4047 TRACE("%p\n", pvStructInfo); 4048 4049 __TRY 4050 { 4051 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo; 4052 struct AsnEncodeSequenceItem items[2] = { { 0 } }; 4053 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4054 DWORD i, cItem = 0, cSwapped = 0; 4055 4056 ret = TRUE; 4057 if (constraints->cPermittedSubtree) 4058 { 4059 permitted.rgBlob = CryptMemAlloc( 4060 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB)); 4061 if (permitted.rgBlob) 4062 { 4063 permitted.cBlob = constraints->cPermittedSubtree; 4064 memset(permitted.rgBlob, 0, 4065 permitted.cBlob * sizeof(CRYPT_DER_BLOB)); 4066 for (i = 0; ret && i < permitted.cBlob; i++) 4067 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType, 4068 NULL, &constraints->rgPermittedSubtree[i], 4069 CRYPT_ENCODE_ALLOC_FLAG, NULL, 4070 (BYTE *)&permitted.rgBlob[i].pbData, 4071 &permitted.rgBlob[i].cbData); 4072 if (ret) 4073 { 4074 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 4075 swapped[cSwapped].pvStructInfo = &permitted; 4076 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet; 4077 items[cItem].pvStructInfo = &swapped[cSwapped]; 4078 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4079 cSwapped++; 4080 cItem++; 4081 } 4082 } 4083 else 4084 ret = FALSE; 4085 } 4086 if (constraints->cExcludedSubtree) 4087 { 4088 excluded.rgBlob = CryptMemAlloc( 4089 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB)); 4090 if (excluded.rgBlob) 4091 { 4092 excluded.cBlob = constraints->cExcludedSubtree; 4093 memset(excluded.rgBlob, 0, 4094 excluded.cBlob * sizeof(CRYPT_DER_BLOB)); 4095 for (i = 0; ret && i < excluded.cBlob; i++) 4096 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType, 4097 NULL, &constraints->rgExcludedSubtree[i], 4098 CRYPT_ENCODE_ALLOC_FLAG, NULL, 4099 (BYTE *)&excluded.rgBlob[i].pbData, 4100 &excluded.rgBlob[i].cbData); 4101 if (ret) 4102 { 4103 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 4104 swapped[cSwapped].pvStructInfo = &excluded; 4105 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet; 4106 items[cItem].pvStructInfo = &swapped[cSwapped]; 4107 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4108 cSwapped++; 4109 cItem++; 4110 } 4111 } 4112 else 4113 ret = FALSE; 4114 } 4115 if (ret) 4116 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 4117 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4118 for (i = 0; i < permitted.cBlob; i++) 4119 LocalFree(permitted.rgBlob[i].pbData); 4120 for (i = 0; i < excluded.cBlob; i++) 4121 LocalFree(excluded.rgBlob[i].pbData); 4122 } 4123 __EXCEPT_PAGE_FAULT 4124 { 4125 SetLastError(STATUS_ACCESS_VIOLATION); 4126 } 4127 __ENDTRY 4128 CryptMemFree(permitted.rgBlob); 4129 CryptMemFree(excluded.rgBlob); 4130 TRACE("returning %d\n", ret); 4131 return ret; 4132 } 4133 4134 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber( 4135 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 4136 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 4137 DWORD *pcbEncoded) 4138 { 4139 BOOL ret; 4140 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo; 4141 struct AsnEncodeSequenceItem items[] = { 4142 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 }, 4143 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, 4144 }; 4145 4146 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 4147 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4148 return ret; 4149 } 4150 4151 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType, 4152 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4153 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4154 { 4155 BOOL ret = FALSE; 4156 4157 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING)) 4158 { 4159 SetLastError(E_INVALIDARG); 4160 return FALSE; 4161 } 4162 4163 __TRY 4164 { 4165 const CMSG_SIGNER_INFO *info = pvStructInfo; 4166 4167 if (!info->Issuer.cbData) 4168 SetLastError(E_INVALIDARG); 4169 else 4170 { 4171 struct AsnEncodeSequenceItem items[7] = { 4172 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 4173 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 }, 4174 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 4175 0 }, 4176 }; 4177 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4178 DWORD cItem = 3, cSwapped = 0; 4179 4180 if (info->AuthAttrs.cAttr) 4181 { 4182 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 4183 swapped[cSwapped].pvStructInfo = &info->AuthAttrs; 4184 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4185 items[cItem].pvStructInfo = &swapped[cSwapped]; 4186 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4187 cSwapped++; 4188 cItem++; 4189 } 4190 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; 4191 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4192 cItem++; 4193 items[cItem].pvStructInfo = &info->EncryptedHash; 4194 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 4195 cItem++; 4196 if (info->UnauthAttrs.cAttr) 4197 { 4198 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 4199 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; 4200 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4201 items[cItem].pvStructInfo = &swapped[cSwapped]; 4202 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4203 cSwapped++; 4204 cItem++; 4205 } 4206 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 4207 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4208 } 4209 } 4210 __EXCEPT_PAGE_FAULT 4211 { 4212 SetLastError(STATUS_ACCESS_VIOLATION); 4213 } 4214 __ENDTRY 4215 return ret; 4216 } 4217 4218 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType, 4219 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4220 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4221 { 4222 BOOL ret = FALSE; 4223 4224 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING)) 4225 { 4226 SetLastError(E_INVALIDARG); 4227 return FALSE; 4228 } 4229 4230 __TRY 4231 { 4232 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo; 4233 4234 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER && 4235 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER) 4236 SetLastError(E_INVALIDARG); 4237 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER && 4238 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData) 4239 SetLastError(E_INVALIDARG); 4240 else 4241 { 4242 struct AsnEncodeSequenceItem items[7] = { 4243 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 4244 }; 4245 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 4246 DWORD cItem = 1, cSwapped = 0; 4247 4248 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 4249 { 4250 items[cItem].pvStructInfo = 4251 &info->SignerId.u.IssuerSerialNumber.Issuer; 4252 items[cItem].encodeFunc = 4253 CRYPT_AsnEncodeIssuerSerialNumber; 4254 cItem++; 4255 } 4256 else 4257 { 4258 swapped[cSwapped].tag = ASN_CONTEXT | 0; 4259 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId; 4260 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 4261 items[cItem].pvStructInfo = &swapped[cSwapped]; 4262 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4263 cSwapped++; 4264 cItem++; 4265 } 4266 items[cItem].pvStructInfo = &info->HashAlgorithm; 4267 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4268 cItem++; 4269 if (info->AuthAttrs.cAttr) 4270 { 4271 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 4272 swapped[cSwapped].pvStructInfo = &info->AuthAttrs; 4273 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4274 items[cItem].pvStructInfo = &swapped[cSwapped]; 4275 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4276 cSwapped++; 4277 cItem++; 4278 } 4279 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; 4280 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4281 cItem++; 4282 items[cItem].pvStructInfo = &info->EncryptedHash; 4283 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 4284 cItem++; 4285 if (info->UnauthAttrs.cAttr) 4286 { 4287 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 4288 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; 4289 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4290 items[cItem].pvStructInfo = &swapped[cSwapped]; 4291 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4292 cSwapped++; 4293 cItem++; 4294 } 4295 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 4296 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4297 } 4298 } 4299 __EXCEPT_PAGE_FAULT 4300 { 4301 SetLastError(STATUS_ACCESS_VIOLATION); 4302 } 4303 __ENDTRY 4304 return ret; 4305 } 4306 4307 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData, 4308 DWORD *pcbData) 4309 { 4310 struct AsnEncodeSequenceItem items[7] = { 4311 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 }, 4312 }; 4313 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 }; 4314 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 }; 4315 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4316 DWORD cItem = 1, cSwapped = 0; 4317 BOOL ret = TRUE; 4318 4319 if (signedInfo->cSignerInfo) 4320 { 4321 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo; 4322 digestAlgorithmsSet.items = signedInfo->rgSignerInfo; 4323 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO); 4324 digestAlgorithmsSet.itemOffset = 4325 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm); 4326 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4327 items[cItem].pvStructInfo = &digestAlgorithmsSet; 4328 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4329 cItem++; 4330 } 4331 items[cItem].pvStructInfo = &signedInfo->content; 4332 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal; 4333 cItem++; 4334 if (signedInfo->cCertEncoded) 4335 { 4336 certSet.cItems = signedInfo->cCertEncoded; 4337 certSet.items = signedInfo->rgCertEncoded; 4338 certSet.itemSize = sizeof(CERT_BLOB); 4339 certSet.itemOffset = 0; 4340 certSet.encode = CRYPT_CopyEncodedBlob; 4341 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0; 4342 swapped[cSwapped].pvStructInfo = &certSet; 4343 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4344 items[cItem].pvStructInfo = &swapped[cSwapped]; 4345 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4346 cSwapped++; 4347 cItem++; 4348 } 4349 if (signedInfo->cCrlEncoded) 4350 { 4351 crlSet.cItems = signedInfo->cCrlEncoded; 4352 crlSet.items = signedInfo->rgCrlEncoded; 4353 crlSet.itemSize = sizeof(CRL_BLOB); 4354 crlSet.itemOffset = 0; 4355 crlSet.encode = CRYPT_CopyEncodedBlob; 4356 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1; 4357 swapped[cSwapped].pvStructInfo = &crlSet; 4358 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4359 items[cItem].pvStructInfo = &swapped[cSwapped]; 4360 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4361 cSwapped++; 4362 cItem++; 4363 } 4364 if (ret && signedInfo->cSignerInfo) 4365 { 4366 signerSet.cItems = signedInfo->cSignerInfo; 4367 signerSet.items = signedInfo->rgSignerInfo; 4368 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO); 4369 signerSet.itemOffset = 0; 4370 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo; 4371 items[cItem].pvStructInfo = &signerSet; 4372 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4373 cItem++; 4374 } 4375 if (ret) 4376 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 4377 items, cItem, 0, NULL, pvData, pcbData); 4378 4379 return ret; 4380 } 4381 4382 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType, 4383 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4384 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4385 { 4386 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo; 4387 struct AsnEncodeSequenceItem items[] = { 4388 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 4389 { &info->RecipientId.u.IssuerSerialNumber, 4390 CRYPT_AsnEncodeIssuerSerialNumber, 0 }, 4391 { &info->KeyEncryptionAlgorithm, 4392 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 4393 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 }, 4394 }; 4395 4396 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 4397 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4398 } 4399 4400 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType, 4401 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4402 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4403 { 4404 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo; 4405 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0, 4406 &info->encryptedContent, CRYPT_AsnEncodeOctets }; 4407 struct AsnEncodeSequenceItem items[] = { 4408 { info->contentType, CRYPT_AsnEncodeOid, 0 }, 4409 { &info->contentEncryptionAlgorithm, 4410 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 4411 { &swapped, CRYPT_AsnEncodeSwapTag, 0 }, 4412 }; 4413 4414 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 4415 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4416 } 4417 4418 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData, 4419 void *pvData, DWORD *pcbData) 4420 { 4421 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo, 4422 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0, 4423 CRYPT_AsnEncodeRecipientInfo }; 4424 struct AsnEncodeSequenceItem items[] = { 4425 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 }, 4426 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 }, 4427 { &envelopedData->encryptedContentInfo, 4428 CRYPT_AsnEncodeEncryptedContentInfo, 0 }, 4429 }; 4430 4431 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 4432 ARRAY_SIZE(items), 0, NULL, pvData, pcbData); 4433 } 4434 4435 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType, 4436 LPCSTR lpszStructType) 4437 { 4438 CryptEncodeObjectExFunc encodeFunc = NULL; 4439 4440 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING 4441 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING) 4442 { 4443 SetLastError(ERROR_FILE_NOT_FOUND); 4444 return NULL; 4445 } 4446 4447 if (IS_INTOID(lpszStructType)) 4448 { 4449 switch (LOWORD(lpszStructType)) 4450 { 4451 case LOWORD(X509_CERT): 4452 encodeFunc = CRYPT_AsnEncodeCert; 4453 break; 4454 case LOWORD(X509_CERT_TO_BE_SIGNED): 4455 encodeFunc = CRYPT_AsnEncodeCertInfo; 4456 break; 4457 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED): 4458 encodeFunc = CRYPT_AsnEncodeCRLInfo; 4459 break; 4460 case LOWORD(X509_EXTENSIONS): 4461 encodeFunc = CRYPT_AsnEncodeExtensions; 4462 break; 4463 case LOWORD(X509_NAME_VALUE): 4464 encodeFunc = CRYPT_AsnEncodeNameValue; 4465 break; 4466 case LOWORD(X509_NAME): 4467 encodeFunc = CRYPT_AsnEncodeName; 4468 break; 4469 case LOWORD(X509_PUBLIC_KEY_INFO): 4470 encodeFunc = CRYPT_AsnEncodePubKeyInfo; 4471 break; 4472 case LOWORD(X509_AUTHORITY_KEY_ID): 4473 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId; 4474 break; 4475 case LOWORD(X509_ALTERNATE_NAME): 4476 encodeFunc = CRYPT_AsnEncodeAltName; 4477 break; 4478 case LOWORD(X509_BASIC_CONSTRAINTS): 4479 encodeFunc = CRYPT_AsnEncodeBasicConstraints; 4480 break; 4481 case LOWORD(X509_BASIC_CONSTRAINTS2): 4482 encodeFunc = CRYPT_AsnEncodeBasicConstraints2; 4483 break; 4484 case LOWORD(X509_CERT_POLICIES): 4485 encodeFunc = CRYPT_AsnEncodeCertPolicies; 4486 break; 4487 case LOWORD(RSA_CSP_PUBLICKEYBLOB): 4488 encodeFunc = CRYPT_AsnEncodeRsaPubKey; 4489 break; 4490 case LOWORD(X509_UNICODE_NAME): 4491 encodeFunc = CRYPT_AsnEncodeUnicodeName; 4492 break; 4493 case LOWORD(PKCS_CONTENT_INFO): 4494 encodeFunc = CRYPT_AsnEncodePKCSContentInfo; 4495 break; 4496 case LOWORD(PKCS_ATTRIBUTE): 4497 encodeFunc = CRYPT_AsnEncodePKCSAttribute; 4498 break; 4499 case LOWORD(X509_UNICODE_NAME_VALUE): 4500 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue; 4501 break; 4502 case LOWORD(X509_OCTET_STRING): 4503 encodeFunc = CRYPT_AsnEncodeOctets; 4504 break; 4505 case LOWORD(X509_BITS): 4506 case LOWORD(X509_KEY_USAGE): 4507 encodeFunc = CRYPT_AsnEncodeBits; 4508 break; 4509 case LOWORD(X509_INTEGER): 4510 encodeFunc = CRYPT_AsnEncodeInt; 4511 break; 4512 case LOWORD(X509_MULTI_BYTE_INTEGER): 4513 encodeFunc = CRYPT_AsnEncodeInteger; 4514 break; 4515 case LOWORD(X509_MULTI_BYTE_UINT): 4516 encodeFunc = CRYPT_AsnEncodeUnsignedInteger; 4517 break; 4518 case LOWORD(X509_ENUMERATED): 4519 encodeFunc = CRYPT_AsnEncodeEnumerated; 4520 break; 4521 case LOWORD(X509_CHOICE_OF_TIME): 4522 encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 4523 break; 4524 case LOWORD(X509_AUTHORITY_KEY_ID2): 4525 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2; 4526 break; 4527 case LOWORD(X509_AUTHORITY_INFO_ACCESS): 4528 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess; 4529 break; 4530 case LOWORD(X509_SEQUENCE_OF_ANY): 4531 encodeFunc = CRYPT_AsnEncodeSequenceOfAny; 4532 break; 4533 case LOWORD(PKCS_UTC_TIME): 4534 encodeFunc = CRYPT_AsnEncodeUtcTime; 4535 break; 4536 case LOWORD(X509_CRL_DIST_POINTS): 4537 encodeFunc = CRYPT_AsnEncodeCRLDistPoints; 4538 break; 4539 case LOWORD(X509_ENHANCED_KEY_USAGE): 4540 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage; 4541 break; 4542 case LOWORD(PKCS_CTL): 4543 encodeFunc = CRYPT_AsnEncodeCTL; 4544 break; 4545 case LOWORD(PKCS_SMIME_CAPABILITIES): 4546 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities; 4547 break; 4548 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE): 4549 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice; 4550 break; 4551 case LOWORD(PKCS_ATTRIBUTES): 4552 encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4553 break; 4554 case LOWORD(X509_ISSUING_DIST_POINT): 4555 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint; 4556 break; 4557 case LOWORD(X509_NAME_CONSTRAINTS): 4558 encodeFunc = CRYPT_AsnEncodeNameConstraints; 4559 break; 4560 case LOWORD(X509_POLICY_MAPPINGS): 4561 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 4562 break; 4563 case LOWORD(X509_POLICY_CONSTRAINTS): 4564 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints; 4565 break; 4566 case LOWORD(PKCS7_SIGNER_INFO): 4567 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo; 4568 break; 4569 case LOWORD(CMS_SIGNER_INFO): 4570 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo; 4571 break; 4572 } 4573 } 4574 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS)) 4575 encodeFunc = CRYPT_AsnEncodeExtensions; 4576 else if (!strcmp(lpszStructType, szOID_RSA_signingTime)) 4577 encodeFunc = CRYPT_AsnEncodeUtcTime; 4578 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities)) 4579 encodeFunc = CRYPT_AsnEncodeUtcTime; 4580 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER)) 4581 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId; 4582 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS)) 4583 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 4584 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2)) 4585 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2; 4586 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE)) 4587 encodeFunc = CRYPT_AsnEncodeEnumerated; 4588 else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) 4589 encodeFunc = CRYPT_AsnEncodeBits; 4590 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER)) 4591 encodeFunc = CRYPT_AsnEncodeOctets; 4592 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS)) 4593 encodeFunc = CRYPT_AsnEncodeBasicConstraints; 4594 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) 4595 encodeFunc = CRYPT_AsnEncodeBasicConstraints2; 4596 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) 4597 encodeFunc = CRYPT_AsnEncodeAltName; 4598 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) 4599 encodeFunc = CRYPT_AsnEncodeAltName; 4600 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION)) 4601 encodeFunc = CRYPT_AsnEncodeAltName; 4602 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) 4603 encodeFunc = CRYPT_AsnEncodeAltName; 4604 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) 4605 encodeFunc = CRYPT_AsnEncodeAltName; 4606 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS)) 4607 encodeFunc = CRYPT_AsnEncodeCRLDistPoints; 4608 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES)) 4609 encodeFunc = CRYPT_AsnEncodeCertPolicies; 4610 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS)) 4611 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 4612 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS)) 4613 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints; 4614 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE)) 4615 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage; 4616 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT)) 4617 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint; 4618 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS)) 4619 encodeFunc = CRYPT_AsnEncodeNameConstraints; 4620 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS)) 4621 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess; 4622 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) 4623 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice; 4624 else if (!strcmp(lpszStructType, szOID_CTL)) 4625 encodeFunc = CRYPT_AsnEncodeCTL; 4626 return encodeFunc; 4627 } 4628 4629 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType, 4630 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) 4631 { 4632 static HCRYPTOIDFUNCSET set = NULL; 4633 CryptEncodeObjectFunc encodeFunc = NULL; 4634 4635 if (!set) 4636 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0); 4637 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, 4638 (void **)&encodeFunc, hFunc); 4639 return encodeFunc; 4640 } 4641 4642 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType, 4643 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) 4644 { 4645 static HCRYPTOIDFUNCSET set = NULL; 4646 CryptEncodeObjectExFunc encodeFunc = NULL; 4647 4648 if (!set) 4649 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0); 4650 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, 4651 (void **)&encodeFunc, hFunc); 4652 return encodeFunc; 4653 } 4654 4655 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType, 4656 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded) 4657 { 4658 BOOL ret = FALSE; 4659 HCRYPTOIDFUNCADDR hFunc = NULL; 4660 CryptEncodeObjectFunc pCryptEncodeObject = NULL; 4661 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL; 4662 4663 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 4664 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, 4665 pcbEncoded); 4666 4667 if (!pbEncoded && !pcbEncoded) 4668 { 4669 SetLastError(ERROR_INVALID_PARAMETER); 4670 return FALSE; 4671 } 4672 4673 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType, 4674 lpszStructType))) 4675 { 4676 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", 4677 debugstr_a(lpszStructType)); 4678 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType, 4679 lpszStructType, &hFunc); 4680 if (!pCryptEncodeObject) 4681 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType, 4682 lpszStructType, &hFunc); 4683 } 4684 if (pCryptEncodeObject) 4685 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 4686 pvStructInfo, pbEncoded, pcbEncoded); 4687 else if (pCryptEncodeObjectEx) 4688 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType, 4689 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded); 4690 if (hFunc) 4691 CryptFreeOIDFunctionAddress(hFunc, 0); 4692 TRACE_(crypt)("returning %d\n", ret); 4693 return ret; 4694 } 4695 4696 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, 4697 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, 4698 void *pvEncoded, DWORD *pcbEncoded) 4699 { 4700 BOOL ret = FALSE; 4701 HCRYPTOIDFUNCADDR hFunc = NULL; 4702 CryptEncodeObjectExFunc encodeFunc = NULL; 4703 4704 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType, 4705 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara, 4706 pvEncoded, pcbEncoded); 4707 4708 if (!pvEncoded && !pcbEncoded) 4709 { 4710 SetLastError(ERROR_INVALID_PARAMETER); 4711 return FALSE; 4712 } 4713 4714 SetLastError(NOERROR); 4715 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) { 4716 if (!pvEncoded) { 4717 SetLastError(ERROR_INVALID_PARAMETER); 4718 return FALSE; 4719 } 4720 *(BYTE **)pvEncoded = NULL; 4721 } 4722 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType); 4723 if (!encodeFunc) 4724 { 4725 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", 4726 debugstr_a(lpszStructType)); 4727 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType, 4728 &hFunc); 4729 } 4730 if (encodeFunc) 4731 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo, 4732 dwFlags, pEncodePara, pvEncoded, pcbEncoded); 4733 else 4734 { 4735 CryptEncodeObjectFunc pCryptEncodeObject = 4736 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc); 4737 4738 if (pCryptEncodeObject) 4739 { 4740 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 4741 { 4742 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 4743 pvStructInfo, NULL, pcbEncoded); 4744 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 4745 pvEncoded, pcbEncoded, *pcbEncoded))) 4746 ret = pCryptEncodeObject(dwCertEncodingType, 4747 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded, 4748 pcbEncoded); 4749 } 4750 else 4751 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 4752 pvStructInfo, pvEncoded, pcbEncoded); 4753 } 4754 } 4755 if (hFunc) 4756 CryptFreeOIDFunctionAddress(hFunc, 0); 4757 TRACE_(crypt)("returning %d\n", ret); 4758 return ret; 4759 } 4760 4761 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX, 4762 LPCWSTR szPassword, DWORD dwFlags) 4763 { 4764 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags); 4765 } 4766 4767 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX, 4768 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags) 4769 { 4770 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword, 4771 pvReserved, dwFlags); 4772 return FALSE; 4773 } 4774 4775 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec, 4776 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 4777 { 4778 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType, 4779 NULL, 0, NULL, pInfo, pcbInfo); 4780 } 4781 4782 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 4783 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, 4784 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 4785 { 4786 BOOL ret; 4787 HCRYPTKEY key; 4788 static CHAR oid[] = szOID_RSA_RSA; 4789 4790 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv, 4791 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, 4792 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0); 4793 4794 if (!pszPublicKeyObjId) 4795 pszPublicKeyObjId = oid; 4796 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key))) 4797 { 4798 DWORD keySize = 0; 4799 4800 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize); 4801 if (ret) 4802 { 4803 LPBYTE pubKey = CryptMemAlloc(keySize); 4804 4805 if (pubKey) 4806 { 4807 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey, 4808 &keySize); 4809 if (ret) 4810 { 4811 DWORD encodedLen = 0; 4812 4813 ret = CryptEncodeObject(dwCertEncodingType, 4814 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen); 4815 if (ret) 4816 { 4817 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) + 4818 strlen(pszPublicKeyObjId) + 1 + encodedLen; 4819 4820 if (!pInfo) 4821 *pcbInfo = sizeNeeded; 4822 else if (*pcbInfo < sizeNeeded) 4823 { 4824 SetLastError(ERROR_MORE_DATA); 4825 *pcbInfo = sizeNeeded; 4826 ret = FALSE; 4827 } 4828 else 4829 { 4830 *pcbInfo = sizeNeeded; 4831 pInfo->Algorithm.pszObjId = (char *)pInfo + 4832 sizeof(CERT_PUBLIC_KEY_INFO); 4833 lstrcpyA(pInfo->Algorithm.pszObjId, 4834 pszPublicKeyObjId); 4835 pInfo->Algorithm.Parameters.cbData = 0; 4836 pInfo->Algorithm.Parameters.pbData = NULL; 4837 pInfo->PublicKey.pbData = 4838 (BYTE *)pInfo->Algorithm.pszObjId 4839 + lstrlenA(pInfo->Algorithm.pszObjId) + 1; 4840 pInfo->PublicKey.cbData = encodedLen; 4841 pInfo->PublicKey.cUnusedBits = 0; 4842 ret = CryptEncodeObject(dwCertEncodingType, 4843 RSA_CSP_PUBLICKEYBLOB, pubKey, 4844 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData); 4845 } 4846 } 4847 } 4848 CryptMemFree(pubKey); 4849 } 4850 else 4851 ret = FALSE; 4852 } 4853 CryptDestroyKey(key); 4854 } 4855 return ret; 4856 } 4857 4858 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 4859 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, 4860 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo); 4861 4862 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec, 4863 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags, 4864 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 4865 { 4866 static HCRYPTOIDFUNCSET set = NULL; 4867 BOOL ret; 4868 ExportPublicKeyInfoExFunc exportFunc = NULL; 4869 HCRYPTOIDFUNCADDR hFunc = NULL; 4870 4871 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv, 4872 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, 4873 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0); 4874 4875 if (!hCryptProv) 4876 { 4877 SetLastError(ERROR_INVALID_PARAMETER); 4878 return FALSE; 4879 } 4880 4881 if (pszPublicKeyObjId) 4882 { 4883 if (!set) 4884 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC, 4885 0); 4886 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId, 4887 0, (void **)&exportFunc, &hFunc); 4888 } 4889 if (!exportFunc) 4890 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx; 4891 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType, 4892 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo); 4893 if (hFunc) 4894 CryptFreeOIDFunctionAddress(hFunc, 0); 4895 return ret; 4896 } 4897 4898 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv, 4899 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) 4900 { 4901 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo, 4902 0, 0, NULL, phKey); 4903 } 4904 4905 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv, 4906 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 4907 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) 4908 { 4909 BOOL ret; 4910 DWORD pubKeySize = 0; 4911 4912 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv, 4913 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); 4914 4915 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 4916 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize); 4917 if (ret) 4918 { 4919 LPBYTE pubKey = CryptMemAlloc(pubKeySize); 4920 4921 if (pubKey) 4922 { 4923 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 4924 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey, 4925 &pubKeySize); 4926 if (ret) 4927 { 4928 if(aiKeyAlg) 4929 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg; 4930 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, 4931 phKey); 4932 } 4933 CryptMemFree(pubKey); 4934 } 4935 else 4936 ret = FALSE; 4937 } 4938 return ret; 4939 } 4940 4941 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv, 4942 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 4943 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey); 4944 4945 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv, 4946 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 4947 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) 4948 { 4949 static HCRYPTOIDFUNCSET set = NULL; 4950 BOOL ret; 4951 ImportPublicKeyInfoExFunc importFunc = NULL; 4952 HCRYPTOIDFUNCADDR hFunc = NULL; 4953 4954 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv, 4955 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); 4956 4957 if (!set) 4958 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0); 4959 CryptGetOIDFunctionAddress(set, dwCertEncodingType, 4960 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc); 4961 if (!importFunc) 4962 importFunc = CRYPT_ImportRsaPublicKeyInfoEx; 4963 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, 4964 pvAuxInfo, phKey); 4965 if (hFunc) 4966 CryptFreeOIDFunctionAddress(hFunc, 0); 4967 return ret; 4968 } 4969