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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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 sizeof(items) / sizeof(items[0]), 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, 1964 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData); 1965 } 1966 1967 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType, 1968 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 1969 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 1970 { 1971 BOOL ret = FALSE; 1972 1973 __TRY 1974 { 1975 const CRYPT_CONTENT_INFO *info = pvStructInfo; 1976 1977 if (!info->pszObjId) 1978 SetLastError(E_INVALIDARG); 1979 else 1980 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType, 1981 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded, 1982 pcbEncoded); 1983 } 1984 __EXCEPT_PAGE_FAULT 1985 { 1986 SetLastError(STATUS_ACCESS_VIOLATION); 1987 } 1988 __ENDTRY 1989 return ret; 1990 } 1991 1992 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value, 1993 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 1994 DWORD *pcbEncoded) 1995 { 1996 BOOL ret = TRUE; 1997 LPCWSTR str = (LPCWSTR)value->Value.pbData; 1998 DWORD bytesNeeded, lenBytes, encodedLen; 1999 2000 if (value->Value.cbData) 2001 encodedLen = value->Value.cbData / sizeof(WCHAR); 2002 else if (str) 2003 encodedLen = strlenW(str); 2004 else 2005 encodedLen = 0; 2006 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2007 bytesNeeded = 1 + lenBytes + encodedLen; 2008 if (!pbEncoded) 2009 *pcbEncoded = bytesNeeded; 2010 else 2011 { 2012 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2013 pbEncoded, pcbEncoded, bytesNeeded))) 2014 { 2015 DWORD i; 2016 2017 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2018 pbEncoded = *(BYTE **)pbEncoded; 2019 *pbEncoded++ = tag; 2020 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); 2021 pbEncoded += lenBytes; 2022 for (i = 0; i < encodedLen; i++) 2023 *pbEncoded++ = (BYTE)str[i]; 2024 } 2025 } 2026 return ret; 2027 } 2028 2029 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value, 2030 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2031 DWORD *pcbEncoded) 2032 { 2033 BOOL ret = TRUE; 2034 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2035 DWORD bytesNeeded, lenBytes, encodedLen; 2036 2037 if (value->Value.cbData) 2038 encodedLen = value->Value.cbData / sizeof(WCHAR); 2039 else if (str) 2040 encodedLen = strlenW(str); 2041 else 2042 encodedLen = 0; 2043 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2044 bytesNeeded = 1 + lenBytes + encodedLen; 2045 if (!pbEncoded) 2046 *pcbEncoded = bytesNeeded; 2047 else 2048 { 2049 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2050 pbEncoded, pcbEncoded, bytesNeeded))) 2051 { 2052 DWORD i; 2053 BYTE *ptr; 2054 2055 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2056 ptr = *(BYTE **)pbEncoded; 2057 else 2058 ptr = pbEncoded; 2059 *ptr++ = ASN_NUMERICSTRING; 2060 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 2061 ptr += lenBytes; 2062 for (i = 0; ret && i < encodedLen; i++) 2063 { 2064 if (isdigitW(str[i])) 2065 *ptr++ = (BYTE)str[i]; 2066 else 2067 { 2068 *pcbEncoded = i; 2069 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING); 2070 ret = FALSE; 2071 } 2072 } 2073 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2074 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 2075 } 2076 } 2077 return ret; 2078 } 2079 2080 static inline BOOL isprintableW(WCHAR wc) 2081 { 2082 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' || 2083 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' || 2084 wc == '/' || wc == ':' || wc == '=' || wc == '?'; 2085 } 2086 2087 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value, 2088 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2089 DWORD *pcbEncoded) 2090 { 2091 BOOL ret = TRUE; 2092 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2093 DWORD bytesNeeded, lenBytes, encodedLen; 2094 2095 if (value->Value.cbData) 2096 encodedLen = value->Value.cbData / sizeof(WCHAR); 2097 else if (str) 2098 encodedLen = strlenW(str); 2099 else 2100 encodedLen = 0; 2101 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2102 bytesNeeded = 1 + lenBytes + encodedLen; 2103 if (!pbEncoded) 2104 *pcbEncoded = bytesNeeded; 2105 else 2106 { 2107 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2108 pbEncoded, pcbEncoded, bytesNeeded))) 2109 { 2110 DWORD i; 2111 BYTE *ptr; 2112 2113 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2114 ptr = *(BYTE **)pbEncoded; 2115 else 2116 ptr = pbEncoded; 2117 *ptr++ = ASN_PRINTABLESTRING; 2118 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 2119 ptr += lenBytes; 2120 for (i = 0; ret && i < encodedLen; i++) 2121 { 2122 if (isprintableW(str[i])) 2123 *ptr++ = (BYTE)str[i]; 2124 else 2125 { 2126 *pcbEncoded = i; 2127 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING); 2128 ret = FALSE; 2129 } 2130 } 2131 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2132 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 2133 } 2134 } 2135 return ret; 2136 } 2137 2138 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value, 2139 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2140 DWORD *pcbEncoded) 2141 { 2142 BOOL ret = TRUE; 2143 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2144 DWORD bytesNeeded, lenBytes, encodedLen; 2145 2146 if (value->Value.cbData) 2147 encodedLen = value->Value.cbData / sizeof(WCHAR); 2148 else if (str) 2149 encodedLen = strlenW(str); 2150 else 2151 encodedLen = 0; 2152 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); 2153 bytesNeeded = 1 + lenBytes + encodedLen; 2154 if (!pbEncoded) 2155 *pcbEncoded = bytesNeeded; 2156 else 2157 { 2158 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2159 pbEncoded, pcbEncoded, bytesNeeded))) 2160 { 2161 DWORD i; 2162 BYTE *ptr; 2163 2164 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2165 ptr = *(BYTE **)pbEncoded; 2166 else 2167 ptr = pbEncoded; 2168 *ptr++ = ASN_IA5STRING; 2169 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes); 2170 ptr += lenBytes; 2171 for (i = 0; ret && i < encodedLen; i++) 2172 { 2173 if (str[i] <= 0x7f) 2174 *ptr++ = (BYTE)str[i]; 2175 else 2176 { 2177 *pcbEncoded = i; 2178 SetLastError(CRYPT_E_INVALID_IA5_STRING); 2179 ret = FALSE; 2180 } 2181 } 2182 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2183 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded); 2184 } 2185 } 2186 return ret; 2187 } 2188 2189 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value, 2190 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded, 2191 DWORD *pcbEncoded) 2192 { 2193 BOOL ret = TRUE; 2194 LPCWSTR str = (LPCWSTR)value->Value.pbData; 2195 DWORD bytesNeeded, lenBytes, strLen; 2196 2197 /* FIXME: doesn't handle composite characters */ 2198 if (value->Value.cbData) 2199 strLen = value->Value.cbData / sizeof(WCHAR); 2200 else if (str) 2201 strLen = strlenW(str); 2202 else 2203 strLen = 0; 2204 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes); 2205 bytesNeeded = 1 + lenBytes + strLen * 4; 2206 if (!pbEncoded) 2207 *pcbEncoded = bytesNeeded; 2208 else 2209 { 2210 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2211 pbEncoded, pcbEncoded, bytesNeeded))) 2212 { 2213 DWORD i; 2214 2215 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2216 pbEncoded = *(BYTE **)pbEncoded; 2217 *pbEncoded++ = ASN_UNIVERSALSTRING; 2218 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes); 2219 pbEncoded += lenBytes; 2220 for (i = 0; i < strLen; i++) 2221 { 2222 *pbEncoded++ = 0; 2223 *pbEncoded++ = 0; 2224 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8); 2225 *pbEncoded++ = (BYTE)(str[i] & 0x00ff); 2226 } 2227 } 2228 } 2229 return ret; 2230 } 2231 2232 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType, 2233 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2234 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2235 { 2236 BOOL ret = FALSE; 2237 2238 __TRY 2239 { 2240 const CERT_NAME_VALUE *value = pvStructInfo; 2241 2242 switch (value->dwValueType) 2243 { 2244 case CERT_RDN_ANY_TYPE: 2245 case CERT_RDN_ENCODED_BLOB: 2246 case CERT_RDN_OCTET_STRING: 2247 SetLastError(CRYPT_E_NOT_CHAR_STRING); 2248 break; 2249 case CERT_RDN_NUMERIC_STRING: 2250 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara, 2251 pbEncoded, pcbEncoded); 2252 break; 2253 case CERT_RDN_PRINTABLE_STRING: 2254 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara, 2255 pbEncoded, pcbEncoded); 2256 break; 2257 case CERT_RDN_TELETEX_STRING: 2258 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING, 2259 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2260 break; 2261 case CERT_RDN_VIDEOTEX_STRING: 2262 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, 2263 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2264 break; 2265 case CERT_RDN_IA5_STRING: 2266 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara, 2267 pbEncoded, pcbEncoded); 2268 break; 2269 case CERT_RDN_GRAPHIC_STRING: 2270 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING, 2271 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2272 break; 2273 case CERT_RDN_VISIBLE_STRING: 2274 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING, 2275 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2276 break; 2277 case CERT_RDN_GENERAL_STRING: 2278 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING, 2279 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2280 break; 2281 case CERT_RDN_UNIVERSAL_STRING: 2282 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara, 2283 pbEncoded, pcbEncoded); 2284 break; 2285 case CERT_RDN_BMP_STRING: 2286 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara, 2287 pbEncoded, pcbEncoded); 2288 break; 2289 case CERT_RDN_UTF8_STRING: 2290 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara, 2291 pbEncoded, pcbEncoded); 2292 break; 2293 default: 2294 SetLastError(CRYPT_E_ASN1_CHOICE); 2295 } 2296 } 2297 __EXCEPT_PAGE_FAULT 2298 { 2299 SetLastError(STATUS_ACCESS_VIOLATION); 2300 } 2301 __ENDTRY 2302 return ret; 2303 } 2304 2305 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType, 2306 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2307 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2308 { 2309 BOOL ret; 2310 2311 __TRY 2312 { 2313 const CERT_NAME_INFO *info = pvStructInfo; 2314 DWORD bytesNeeded = 0, lenBytes, size, i; 2315 2316 TRACE("encoding name with %d RDNs\n", info->cRDN); 2317 ret = TRUE; 2318 for (i = 0; ret && i < info->cRDN; i++) 2319 { 2320 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], 2321 CRYPT_AsnEncodeNameValue, NULL, &size); 2322 if (ret) 2323 bytesNeeded += size; 2324 } 2325 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 2326 bytesNeeded += 1 + lenBytes; 2327 if (ret) 2328 { 2329 if (!pbEncoded) 2330 *pcbEncoded = bytesNeeded; 2331 else 2332 { 2333 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2334 pbEncoded, pcbEncoded, bytesNeeded))) 2335 { 2336 BYTE *out; 2337 2338 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2339 pbEncoded = *(BYTE **)pbEncoded; 2340 out = pbEncoded; 2341 *out++ = ASN_SEQUENCEOF; 2342 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 2343 out += lenBytes; 2344 for (i = 0; ret && i < info->cRDN; i++) 2345 { 2346 size = bytesNeeded; 2347 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, 2348 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size); 2349 if (ret) 2350 { 2351 out += size; 2352 bytesNeeded -= size; 2353 } 2354 } 2355 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2356 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2357 } 2358 } 2359 } 2360 } 2361 __EXCEPT_PAGE_FAULT 2362 { 2363 SetLastError(STATUS_ACCESS_VIOLATION); 2364 ret = FALSE; 2365 } 2366 __ENDTRY 2367 return ret; 2368 } 2369 2370 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, 2371 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2372 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2373 { 2374 BOOL val = *(const BOOL *)pvStructInfo, ret; 2375 2376 TRACE("%d\n", val); 2377 2378 if (!pbEncoded) 2379 { 2380 *pcbEncoded = 3; 2381 ret = TRUE; 2382 } 2383 else if (*pcbEncoded < 3) 2384 { 2385 *pcbEncoded = 3; 2386 SetLastError(ERROR_MORE_DATA); 2387 ret = FALSE; 2388 } 2389 else 2390 { 2391 *pcbEncoded = 3; 2392 *pbEncoded++ = ASN_BOOL; 2393 *pbEncoded++ = 1; 2394 *pbEncoded++ = val ? 0xff : 0; 2395 ret = TRUE; 2396 } 2397 TRACE("returning %d (%08x)\n", ret, GetLastError()); 2398 return ret; 2399 } 2400 2401 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType, 2402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2404 { 2405 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo; 2406 BOOL ret; 2407 DWORD dataLen; 2408 BYTE tag; 2409 2410 ret = TRUE; 2411 switch (entry->dwAltNameChoice) 2412 { 2413 case CERT_ALT_NAME_RFC822_NAME: 2414 case CERT_ALT_NAME_DNS_NAME: 2415 case CERT_ALT_NAME_URL: 2416 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1); 2417 if (entry->u.pwszURL) 2418 { 2419 DWORD i; 2420 2421 /* Not + 1: don't encode the NULL-terminator */ 2422 dataLen = lstrlenW(entry->u.pwszURL); 2423 for (i = 0; ret && i < dataLen; i++) 2424 { 2425 if (entry->u.pwszURL[i] > 0x7f) 2426 { 2427 SetLastError(CRYPT_E_INVALID_IA5_STRING); 2428 ret = FALSE; 2429 *pcbEncoded = i; 2430 } 2431 } 2432 } 2433 else 2434 dataLen = 0; 2435 break; 2436 case CERT_ALT_NAME_DIRECTORY_NAME: 2437 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1); 2438 dataLen = entry->u.DirectoryName.cbData; 2439 break; 2440 case CERT_ALT_NAME_IP_ADDRESS: 2441 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1); 2442 dataLen = entry->u.IPAddress.cbData; 2443 break; 2444 case CERT_ALT_NAME_REGISTERED_ID: 2445 { 2446 struct AsnEncodeTagSwappedItem swapped = 2447 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID, 2448 CRYPT_AsnEncodeOid }; 2449 2450 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded, 2451 pcbEncoded); 2452 } 2453 case CERT_ALT_NAME_OTHER_NAME: 2454 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice); 2455 return FALSE; 2456 default: 2457 SetLastError(E_INVALIDARG); 2458 return FALSE; 2459 } 2460 if (ret) 2461 { 2462 DWORD bytesNeeded, lenBytes; 2463 2464 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 2465 bytesNeeded = 1 + dataLen + lenBytes; 2466 if (!pbEncoded) 2467 *pcbEncoded = bytesNeeded; 2468 else if (*pcbEncoded < bytesNeeded) 2469 { 2470 SetLastError(ERROR_MORE_DATA); 2471 *pcbEncoded = bytesNeeded; 2472 ret = FALSE; 2473 } 2474 else 2475 { 2476 *pbEncoded++ = tag; 2477 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 2478 pbEncoded += lenBytes; 2479 switch (entry->dwAltNameChoice) 2480 { 2481 case CERT_ALT_NAME_RFC822_NAME: 2482 case CERT_ALT_NAME_DNS_NAME: 2483 case CERT_ALT_NAME_URL: 2484 { 2485 DWORD i; 2486 2487 for (i = 0; i < dataLen; i++) 2488 *pbEncoded++ = (BYTE)entry->u.pwszURL[i]; 2489 break; 2490 } 2491 case CERT_ALT_NAME_DIRECTORY_NAME: 2492 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen); 2493 break; 2494 case CERT_ALT_NAME_IP_ADDRESS: 2495 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen); 2496 break; 2497 } 2498 if (ret) 2499 *pcbEncoded = bytesNeeded; 2500 } 2501 } 2502 TRACE("returning %d (%08x)\n", ret, GetLastError()); 2503 return ret; 2504 } 2505 2506 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType, 2507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2509 { 2510 BOOL ret; 2511 2512 __TRY 2513 { 2514 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo; 2515 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 2516 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 2517 struct AsnConstructedItem constructed = { 0 }; 2518 DWORD cItem = 0, cSwapped = 0; 2519 2520 if (info->KeyId.cbData) 2521 { 2522 swapped[cSwapped].tag = ASN_CONTEXT | 0; 2523 swapped[cSwapped].pvStructInfo = &info->KeyId; 2524 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 2525 items[cItem].pvStructInfo = &swapped[cSwapped]; 2526 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2527 cSwapped++; 2528 cItem++; 2529 } 2530 if (info->CertIssuer.cbData) 2531 { 2532 constructed.tag = 1; 2533 constructed.pvStructInfo = &info->CertIssuer; 2534 constructed.encodeFunc = CRYPT_CopyEncodedBlob; 2535 items[cItem].pvStructInfo = &constructed; 2536 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 2537 cItem++; 2538 } 2539 if (info->CertSerialNumber.cbData) 2540 { 2541 swapped[cSwapped].tag = ASN_CONTEXT | 2; 2542 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber; 2543 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger; 2544 items[cItem].pvStructInfo = &swapped[cSwapped]; 2545 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2546 cSwapped++; 2547 cItem++; 2548 } 2549 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags, 2550 pEncodePara, pbEncoded, pcbEncoded); 2551 } 2552 __EXCEPT_PAGE_FAULT 2553 { 2554 SetLastError(STATUS_ACCESS_VIOLATION); 2555 ret = FALSE; 2556 } 2557 __ENDTRY 2558 return ret; 2559 } 2560 2561 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType, 2562 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2563 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2564 { 2565 BOOL ret; 2566 2567 __TRY 2568 { 2569 const CERT_ALT_NAME_INFO *info = pvStructInfo; 2570 DWORD bytesNeeded, dataLen, lenBytes, i; 2571 2572 ret = TRUE; 2573 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we 2574 * can't encode an erroneous entry index if it's bigger than this. 2575 */ 2576 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++) 2577 { 2578 DWORD len; 2579 2580 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL, 2581 &info->rgAltEntry[i], 0, NULL, NULL, &len); 2582 if (ret) 2583 dataLen += len; 2584 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING) 2585 { 2586 /* CRYPT_AsnEncodeAltNameEntry encoded the index of 2587 * the bad character, now set the index of the bad 2588 * entry 2589 */ 2590 *pcbEncoded = (BYTE)i << 2591 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len; 2592 } 2593 } 2594 if (ret) 2595 { 2596 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 2597 bytesNeeded = 1 + lenBytes + dataLen; 2598 if (!pbEncoded) 2599 { 2600 *pcbEncoded = bytesNeeded; 2601 ret = TRUE; 2602 } 2603 else 2604 { 2605 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2606 pbEncoded, pcbEncoded, bytesNeeded))) 2607 { 2608 BYTE *out; 2609 2610 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2611 pbEncoded = *(BYTE **)pbEncoded; 2612 out = pbEncoded; 2613 *out++ = ASN_SEQUENCEOF; 2614 CRYPT_EncodeLen(dataLen, out, &lenBytes); 2615 out += lenBytes; 2616 for (i = 0; ret && i < info->cAltEntry; i++) 2617 { 2618 DWORD len = dataLen; 2619 2620 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, 2621 NULL, &info->rgAltEntry[i], 0, NULL, out, &len); 2622 if (ret) 2623 { 2624 out += len; 2625 dataLen -= len; 2626 } 2627 } 2628 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2629 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2630 } 2631 } 2632 } 2633 } 2634 __EXCEPT_PAGE_FAULT 2635 { 2636 SetLastError(STATUS_ACCESS_VIOLATION); 2637 ret = FALSE; 2638 } 2639 __ENDTRY 2640 return ret; 2641 } 2642 2643 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType, 2644 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2645 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2646 { 2647 BOOL ret; 2648 2649 __TRY 2650 { 2651 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo; 2652 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 2653 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 2654 DWORD cItem = 0, cSwapped = 0; 2655 2656 if (info->KeyId.cbData) 2657 { 2658 swapped[cSwapped].tag = ASN_CONTEXT | 0; 2659 swapped[cSwapped].pvStructInfo = &info->KeyId; 2660 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 2661 items[cItem].pvStructInfo = &swapped[cSwapped]; 2662 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2663 cSwapped++; 2664 cItem++; 2665 } 2666 if (info->AuthorityCertIssuer.cAltEntry) 2667 { 2668 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 2669 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer; 2670 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 2671 items[cItem].pvStructInfo = &swapped[cSwapped]; 2672 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2673 cSwapped++; 2674 cItem++; 2675 } 2676 if (info->AuthorityCertSerialNumber.cbData) 2677 { 2678 swapped[cSwapped].tag = ASN_CONTEXT | 2; 2679 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber; 2680 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger; 2681 items[cItem].pvStructInfo = &swapped[cSwapped]; 2682 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 2683 cSwapped++; 2684 cItem++; 2685 } 2686 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags, 2687 pEncodePara, pbEncoded, pcbEncoded); 2688 } 2689 __EXCEPT_PAGE_FAULT 2690 { 2691 SetLastError(STATUS_ACCESS_VIOLATION); 2692 ret = FALSE; 2693 } 2694 __ENDTRY 2695 return ret; 2696 } 2697 2698 static BOOL CRYPT_AsnEncodeAccessDescription( 2699 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded) 2700 { 2701 struct AsnEncodeSequenceItem items[] = { 2702 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 }, 2703 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 }, 2704 }; 2705 2706 if (!descr->pszAccessMethod) 2707 { 2708 SetLastError(E_INVALIDARG); 2709 return FALSE; 2710 } 2711 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 2712 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded); 2713 } 2714 2715 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType, 2716 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2717 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2718 { 2719 BOOL ret; 2720 2721 __TRY 2722 { 2723 DWORD bytesNeeded, dataLen, lenBytes, i; 2724 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo; 2725 2726 ret = TRUE; 2727 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++) 2728 { 2729 DWORD size; 2730 2731 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL, 2732 &size); 2733 if (ret) 2734 dataLen += size; 2735 } 2736 if (ret) 2737 { 2738 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 2739 bytesNeeded = 1 + lenBytes + dataLen; 2740 if (!pbEncoded) 2741 *pcbEncoded = bytesNeeded; 2742 else 2743 { 2744 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2745 pbEncoded, pcbEncoded, bytesNeeded))) 2746 { 2747 BYTE *out; 2748 2749 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2750 pbEncoded = *(BYTE **)pbEncoded; 2751 out = pbEncoded; 2752 *out++ = ASN_SEQUENCEOF; 2753 CRYPT_EncodeLen(dataLen, out, &lenBytes); 2754 out += lenBytes; 2755 for (i = 0; i < info->cAccDescr; i++) 2756 { 2757 DWORD size = dataLen; 2758 2759 ret = CRYPT_AsnEncodeAccessDescription( 2760 &info->rgAccDescr[i], out, &size); 2761 out += size; 2762 dataLen -= size; 2763 } 2764 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2765 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2766 } 2767 } 2768 } 2769 } 2770 __EXCEPT_PAGE_FAULT 2771 { 2772 SetLastError(STATUS_ACCESS_VIOLATION); 2773 ret = FALSE; 2774 } 2775 __ENDTRY 2776 return ret; 2777 } 2778 2779 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType, 2780 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2781 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2782 { 2783 BOOL ret; 2784 2785 __TRY 2786 { 2787 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo; 2788 struct AsnEncodeSequenceItem items[3] = { 2789 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 }, 2790 { 0 } 2791 }; 2792 DWORD cItem = 1; 2793 2794 if (info->fPathLenConstraint) 2795 { 2796 items[cItem].pvStructInfo = &info->dwPathLenConstraint; 2797 items[cItem].encodeFunc = CRYPT_AsnEncodeInt; 2798 cItem++; 2799 } 2800 if (info->cSubtreesConstraint) 2801 { 2802 items[cItem].pvStructInfo = &info->cSubtreesConstraint; 2803 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny; 2804 cItem++; 2805 } 2806 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 2807 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2808 } 2809 __EXCEPT_PAGE_FAULT 2810 { 2811 SetLastError(STATUS_ACCESS_VIOLATION); 2812 ret = FALSE; 2813 } 2814 __ENDTRY 2815 return ret; 2816 } 2817 2818 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType, 2819 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2820 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2821 { 2822 BOOL ret; 2823 2824 __TRY 2825 { 2826 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo; 2827 struct AsnEncodeSequenceItem items[2] = { { 0 } }; 2828 DWORD cItem = 0; 2829 2830 if (info->fCA) 2831 { 2832 items[cItem].pvStructInfo = &info->fCA; 2833 items[cItem].encodeFunc = CRYPT_AsnEncodeBool; 2834 cItem++; 2835 } 2836 if (info->fPathLenConstraint) 2837 { 2838 items[cItem].pvStructInfo = &info->dwPathLenConstraint; 2839 items[cItem].encodeFunc = CRYPT_AsnEncodeInt; 2840 cItem++; 2841 } 2842 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 2843 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 2844 } 2845 __EXCEPT_PAGE_FAULT 2846 { 2847 SetLastError(STATUS_ACCESS_VIOLATION); 2848 ret = FALSE; 2849 } 2850 __ENDTRY 2851 return ret; 2852 } 2853 2854 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType, 2855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2857 { 2858 const CERT_POLICY_INFO *info = pvStructInfo; 2859 BOOL ret; 2860 2861 if (!info->cPolicyQualifier) 2862 { 2863 *pcbEncoded = 0; 2864 ret = TRUE; 2865 } 2866 else 2867 { 2868 struct AsnEncodeSequenceItem items[2] = { 2869 { NULL, CRYPT_AsnEncodeOid, 0 }, 2870 { NULL, CRYPT_CopyEncodedBlob, 0 }, 2871 }; 2872 DWORD bytesNeeded = 0, lenBytes, size, i; 2873 2874 ret = TRUE; 2875 for (i = 0; ret && i < info->cPolicyQualifier; i++) 2876 { 2877 items[0].pvStructInfo = 2878 info->rgPolicyQualifier[i].pszPolicyQualifierId; 2879 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier; 2880 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 2881 sizeof(items) / sizeof(items[0]), 2882 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size); 2883 if (ret) 2884 bytesNeeded += size; 2885 } 2886 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 2887 bytesNeeded += 1 + lenBytes; 2888 if (ret) 2889 { 2890 if (!pbEncoded) 2891 *pcbEncoded = bytesNeeded; 2892 else 2893 { 2894 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2895 pbEncoded, pcbEncoded, bytesNeeded))) 2896 { 2897 BYTE *out; 2898 2899 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2900 pbEncoded = *(BYTE **)pbEncoded; 2901 out = pbEncoded; 2902 *out++ = ASN_SEQUENCEOF; 2903 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 2904 out += lenBytes; 2905 for (i = 0; ret && i < info->cPolicyQualifier; i++) 2906 { 2907 items[0].pvStructInfo = 2908 info->rgPolicyQualifier[i].pszPolicyQualifierId; 2909 items[1].pvStructInfo = 2910 &info->rgPolicyQualifier[i].Qualifier; 2911 size = bytesNeeded; 2912 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 2913 sizeof(items) / sizeof(items[0]), 2914 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size); 2915 if (ret) 2916 { 2917 out += size; 2918 bytesNeeded -= size; 2919 } 2920 } 2921 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 2922 CRYPT_FreeSpace(pEncodePara, pbEncoded); 2923 } 2924 } 2925 } 2926 } 2927 return ret; 2928 } 2929 2930 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType, 2931 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded, 2932 DWORD *pcbEncoded) 2933 { 2934 struct AsnEncodeSequenceItem items[2] = { 2935 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 }, 2936 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 }, 2937 }; 2938 BOOL ret; 2939 2940 if (!info->pszPolicyIdentifier) 2941 { 2942 SetLastError(E_INVALIDARG); 2943 return FALSE; 2944 } 2945 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 2946 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded); 2947 return ret; 2948 } 2949 2950 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType, 2951 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 2952 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 2953 { 2954 BOOL ret = FALSE; 2955 2956 __TRY 2957 { 2958 const CERT_POLICIES_INFO *info = pvStructInfo; 2959 DWORD bytesNeeded = 0, lenBytes, size, i; 2960 2961 ret = TRUE; 2962 for (i = 0; ret && i < info->cPolicyInfo; i++) 2963 { 2964 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType, 2965 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, 2966 &size); 2967 if (ret) 2968 bytesNeeded += size; 2969 } 2970 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 2971 bytesNeeded += 1 + lenBytes; 2972 if (ret) 2973 { 2974 if (!pbEncoded) 2975 *pcbEncoded = bytesNeeded; 2976 else 2977 { 2978 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 2979 pbEncoded, pcbEncoded, bytesNeeded))) 2980 { 2981 BYTE *out; 2982 2983 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 2984 pbEncoded = *(BYTE **)pbEncoded; 2985 out = pbEncoded; 2986 *out++ = ASN_SEQUENCEOF; 2987 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 2988 out += lenBytes; 2989 for (i = 0; ret && i < info->cPolicyInfo; i++) 2990 { 2991 size = bytesNeeded; 2992 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType, 2993 &info->rgPolicyInfo[i], 2994 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size); 2995 if (ret) 2996 { 2997 out += size; 2998 bytesNeeded -= size; 2999 } 3000 } 3001 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 3002 CRYPT_FreeSpace(pEncodePara, pbEncoded); 3003 } 3004 } 3005 } 3006 } 3007 __EXCEPT_PAGE_FAULT 3008 { 3009 SetLastError(STATUS_ACCESS_VIOLATION); 3010 } 3011 __ENDTRY 3012 return ret; 3013 } 3014 3015 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType, 3016 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded, 3017 DWORD *pcbEncoded) 3018 { 3019 struct AsnEncodeSequenceItem items[] = { 3020 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 }, 3021 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 }, 3022 }; 3023 3024 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy) 3025 { 3026 SetLastError(E_INVALIDARG); 3027 return FALSE; 3028 } 3029 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 3030 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded); 3031 } 3032 3033 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType, 3034 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3035 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3036 { 3037 BOOL ret = FALSE; 3038 3039 __TRY 3040 { 3041 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo; 3042 DWORD bytesNeeded = 0, lenBytes, size, i; 3043 3044 ret = TRUE; 3045 for (i = 0; ret && i < info->cPolicyMapping; i++) 3046 { 3047 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType, 3048 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, 3049 NULL, &size); 3050 if (ret) 3051 bytesNeeded += size; 3052 } 3053 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 3054 bytesNeeded += 1 + lenBytes; 3055 if (ret) 3056 { 3057 if (!pbEncoded) 3058 *pcbEncoded = bytesNeeded; 3059 else 3060 { 3061 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3062 pbEncoded, pcbEncoded, bytesNeeded))) 3063 { 3064 BYTE *out; 3065 3066 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3067 pbEncoded = *(BYTE **)pbEncoded; 3068 out = pbEncoded; 3069 *out++ = ASN_SEQUENCEOF; 3070 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 3071 out += lenBytes; 3072 for (i = 0; ret && i < info->cPolicyMapping; i++) 3073 { 3074 size = bytesNeeded; 3075 ret = CRYPT_AsnEncodeCertPolicyMapping( 3076 dwCertEncodingType, &info->rgPolicyMapping[i], 3077 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size); 3078 if (ret) 3079 { 3080 out += size; 3081 bytesNeeded -= size; 3082 } 3083 } 3084 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 3085 CRYPT_FreeSpace(pEncodePara, pbEncoded); 3086 } 3087 } 3088 } 3089 } 3090 __EXCEPT_PAGE_FAULT 3091 { 3092 SetLastError(STATUS_ACCESS_VIOLATION); 3093 } 3094 __ENDTRY 3095 return ret; 3096 } 3097 3098 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints( 3099 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 3100 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 3101 DWORD *pcbEncoded) 3102 { 3103 BOOL ret = FALSE; 3104 3105 __TRY 3106 { 3107 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo; 3108 struct AsnEncodeSequenceItem items[2]; 3109 struct AsnEncodeTagSwappedItem swapped[2]; 3110 DWORD cItem = 0, cSwapped = 0; 3111 3112 if (info->fRequireExplicitPolicy) 3113 { 3114 swapped[cSwapped].tag = ASN_CONTEXT | 0; 3115 swapped[cSwapped].pvStructInfo = 3116 &info->dwRequireExplicitPolicySkipCerts; 3117 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 3118 items[cItem].pvStructInfo = &swapped[cSwapped]; 3119 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3120 cSwapped++; 3121 cItem++; 3122 } 3123 if (info->fInhibitPolicyMapping) 3124 { 3125 swapped[cSwapped].tag = ASN_CONTEXT | 1; 3126 swapped[cSwapped].pvStructInfo = 3127 &info->dwInhibitPolicyMappingSkipCerts; 3128 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 3129 items[cItem].pvStructInfo = &swapped[cSwapped]; 3130 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3131 cSwapped++; 3132 cItem++; 3133 } 3134 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 3135 dwFlags, NULL, pbEncoded, pcbEncoded); 3136 } 3137 __EXCEPT_PAGE_FAULT 3138 { 3139 SetLastError(STATUS_ACCESS_VIOLATION); 3140 } 3141 __ENDTRY 3142 return ret; 3143 } 3144 3145 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType, 3146 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3147 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3148 { 3149 BOOL ret; 3150 3151 __TRY 3152 { 3153 const BLOBHEADER *hdr = pvStructInfo; 3154 3155 if (hdr->bType != PUBLICKEYBLOB) 3156 { 3157 SetLastError(E_INVALIDARG); 3158 ret = FALSE; 3159 } 3160 else 3161 { 3162 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *) 3163 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER)); 3164 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8, 3165 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) }; 3166 struct AsnEncodeSequenceItem items[] = { 3167 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 }, 3168 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 }, 3169 }; 3170 3171 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 3172 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 3173 pcbEncoded); 3174 } 3175 } 3176 __EXCEPT_PAGE_FAULT 3177 { 3178 SetLastError(STATUS_ACCESS_VIOLATION); 3179 ret = FALSE; 3180 } 3181 __ENDTRY 3182 return ret; 3183 } 3184 3185 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType, 3186 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3187 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3188 { 3189 BOOL ret; 3190 3191 __TRY 3192 { 3193 const CRYPT_DATA_BLOB *blob = pvStructInfo; 3194 DWORD bytesNeeded, lenBytes; 3195 3196 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData, 3197 dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0); 3198 3199 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes); 3200 bytesNeeded = 1 + lenBytes + blob->cbData; 3201 if (!pbEncoded) 3202 { 3203 *pcbEncoded = bytesNeeded; 3204 ret = TRUE; 3205 } 3206 else 3207 { 3208 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3209 pcbEncoded, bytesNeeded))) 3210 { 3211 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3212 pbEncoded = *(BYTE **)pbEncoded; 3213 *pbEncoded++ = ASN_OCTETSTRING; 3214 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes); 3215 pbEncoded += lenBytes; 3216 if (blob->cbData) 3217 memcpy(pbEncoded, blob->pbData, blob->cbData); 3218 } 3219 } 3220 } 3221 __EXCEPT_PAGE_FAULT 3222 { 3223 SetLastError(STATUS_ACCESS_VIOLATION); 3224 ret = FALSE; 3225 } 3226 __ENDTRY 3227 TRACE("returning %d (%08x)\n", ret, GetLastError()); 3228 return ret; 3229 } 3230 3231 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, 3232 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3233 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3234 { 3235 BOOL ret; 3236 3237 __TRY 3238 { 3239 const CRYPT_BIT_BLOB *blob = pvStructInfo; 3240 DWORD bytesNeeded, lenBytes, dataBytes; 3241 BYTE unusedBits; 3242 3243 /* yep, MS allows cUnusedBits to be >= 8 */ 3244 if (!blob->cUnusedBits) 3245 { 3246 dataBytes = blob->cbData; 3247 unusedBits = 0; 3248 } 3249 else if (blob->cbData * 8 > blob->cUnusedBits) 3250 { 3251 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1; 3252 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 : 3253 blob->cUnusedBits; 3254 } 3255 else 3256 { 3257 dataBytes = 0; 3258 unusedBits = 0; 3259 } 3260 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes); 3261 bytesNeeded = 1 + lenBytes + dataBytes + 1; 3262 if (!pbEncoded) 3263 { 3264 *pcbEncoded = bytesNeeded; 3265 ret = TRUE; 3266 } 3267 else 3268 { 3269 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3270 pcbEncoded, bytesNeeded))) 3271 { 3272 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3273 pbEncoded = *(BYTE **)pbEncoded; 3274 *pbEncoded++ = ASN_BITSTRING; 3275 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes); 3276 pbEncoded += lenBytes; 3277 *pbEncoded++ = unusedBits; 3278 if (dataBytes) 3279 { 3280 BYTE mask = 0xff << unusedBits; 3281 3282 if (dataBytes > 1) 3283 { 3284 memcpy(pbEncoded, blob->pbData, dataBytes - 1); 3285 pbEncoded += dataBytes - 1; 3286 } 3287 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask; 3288 } 3289 } 3290 } 3291 } 3292 __EXCEPT_PAGE_FAULT 3293 { 3294 SetLastError(STATUS_ACCESS_VIOLATION); 3295 ret = FALSE; 3296 } 3297 __ENDTRY 3298 return ret; 3299 } 3300 3301 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType, 3302 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3303 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3304 { 3305 BOOL ret; 3306 3307 __TRY 3308 { 3309 const CRYPT_BIT_BLOB *blob = pvStructInfo; 3310 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits }; 3311 3312 ret = TRUE; 3313 if (newBlob.cbData) 3314 { 3315 newBlob.pbData = CryptMemAlloc(newBlob.cbData); 3316 if (newBlob.pbData) 3317 { 3318 DWORD i; 3319 3320 for (i = 0; i < newBlob.cbData; i++) 3321 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i]; 3322 } 3323 else 3324 ret = FALSE; 3325 } 3326 if (ret) 3327 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType, 3328 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3329 CryptMemFree(newBlob.pbData); 3330 } 3331 __EXCEPT_PAGE_FAULT 3332 { 3333 SetLastError(STATUS_ACCESS_VIOLATION); 3334 ret = FALSE; 3335 } 3336 __ENDTRY 3337 return ret; 3338 } 3339 3340 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, 3341 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3342 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3343 { 3344 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo }; 3345 3346 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER, 3347 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3348 } 3349 3350 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, 3351 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3352 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3353 { 3354 BOOL ret; 3355 3356 __TRY 3357 { 3358 DWORD significantBytes, lenBytes, bytesNeeded; 3359 BYTE padByte = 0; 3360 BOOL pad = FALSE; 3361 const CRYPT_INTEGER_BLOB *blob = pvStructInfo; 3362 3363 significantBytes = blob->cbData; 3364 if (significantBytes) 3365 { 3366 if (blob->pbData[significantBytes - 1] & 0x80) 3367 { 3368 /* negative, lop off leading (little-endian) 0xffs */ 3369 for (; significantBytes > 0 && 3370 blob->pbData[significantBytes - 1] == 0xff; significantBytes--) 3371 ; 3372 if (blob->pbData[significantBytes - 1] < 0x80) 3373 { 3374 padByte = 0xff; 3375 pad = TRUE; 3376 } 3377 } 3378 else 3379 { 3380 /* positive, lop off leading (little-endian) zeroes */ 3381 for (; significantBytes > 0 && 3382 !blob->pbData[significantBytes - 1]; significantBytes--) 3383 ; 3384 if (significantBytes == 0) 3385 significantBytes = 1; 3386 if (blob->pbData[significantBytes - 1] > 0x7f) 3387 { 3388 padByte = 0; 3389 pad = TRUE; 3390 } 3391 } 3392 } 3393 if (pad) 3394 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); 3395 else 3396 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); 3397 bytesNeeded = 1 + lenBytes + significantBytes; 3398 if (pad) 3399 bytesNeeded++; 3400 if (!pbEncoded) 3401 { 3402 *pcbEncoded = bytesNeeded; 3403 ret = TRUE; 3404 } 3405 else 3406 { 3407 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3408 pcbEncoded, bytesNeeded))) 3409 { 3410 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3411 pbEncoded = *(BYTE **)pbEncoded; 3412 *pbEncoded++ = ASN_INTEGER; 3413 if (pad) 3414 { 3415 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); 3416 pbEncoded += lenBytes; 3417 *pbEncoded++ = padByte; 3418 } 3419 else 3420 { 3421 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); 3422 pbEncoded += lenBytes; 3423 } 3424 for (; significantBytes > 0; significantBytes--) 3425 *(pbEncoded++) = blob->pbData[significantBytes - 1]; 3426 } 3427 } 3428 } 3429 __EXCEPT_PAGE_FAULT 3430 { 3431 SetLastError(STATUS_ACCESS_VIOLATION); 3432 ret = FALSE; 3433 } 3434 __ENDTRY 3435 return ret; 3436 } 3437 3438 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, 3439 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3440 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3441 { 3442 BOOL ret; 3443 3444 __TRY 3445 { 3446 DWORD significantBytes, lenBytes, bytesNeeded; 3447 BOOL pad = FALSE; 3448 const CRYPT_INTEGER_BLOB *blob = pvStructInfo; 3449 3450 significantBytes = blob->cbData; 3451 if (significantBytes) 3452 { 3453 /* positive, lop off leading (little-endian) zeroes */ 3454 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1]; 3455 significantBytes--) 3456 ; 3457 if (significantBytes == 0) 3458 significantBytes = 1; 3459 if (blob->pbData[significantBytes - 1] > 0x7f) 3460 pad = TRUE; 3461 } 3462 if (pad) 3463 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); 3464 else 3465 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); 3466 bytesNeeded = 1 + lenBytes + significantBytes; 3467 if (pad) 3468 bytesNeeded++; 3469 if (!pbEncoded) 3470 { 3471 *pcbEncoded = bytesNeeded; 3472 ret = TRUE; 3473 } 3474 else 3475 { 3476 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3477 pcbEncoded, bytesNeeded))) 3478 { 3479 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3480 pbEncoded = *(BYTE **)pbEncoded; 3481 *pbEncoded++ = ASN_INTEGER; 3482 if (pad) 3483 { 3484 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); 3485 pbEncoded += lenBytes; 3486 *pbEncoded++ = 0; 3487 } 3488 else 3489 { 3490 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); 3491 pbEncoded += lenBytes; 3492 } 3493 for (; significantBytes > 0; significantBytes--) 3494 *(pbEncoded++) = blob->pbData[significantBytes - 1]; 3495 } 3496 } 3497 } 3498 __EXCEPT_PAGE_FAULT 3499 { 3500 SetLastError(STATUS_ACCESS_VIOLATION); 3501 ret = FALSE; 3502 } 3503 __ENDTRY 3504 return ret; 3505 } 3506 3507 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType, 3508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3510 { 3511 CRYPT_INTEGER_BLOB blob; 3512 BOOL ret; 3513 3514 /* Encode as an unsigned integer, then change the tag to enumerated */ 3515 blob.cbData = sizeof(DWORD); 3516 blob.pbData = (BYTE *)pvStructInfo; 3517 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType, 3518 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3519 if (ret && pbEncoded) 3520 { 3521 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3522 pbEncoded = *(BYTE **)pbEncoded; 3523 pbEncoded[0] = ASN_ENUMERATED; 3524 } 3525 return ret; 3526 } 3527 3528 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType, 3529 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3530 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3531 { 3532 BOOL ret; 3533 3534 __TRY 3535 { 3536 SYSTEMTIME sysTime; 3537 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a 3538 * temporary buffer because the output buffer is not NULL-terminated. 3539 */ 3540 static const DWORD bytesNeeded = 15; 3541 char buf[40]; 3542 3543 if (!pbEncoded) 3544 { 3545 *pcbEncoded = bytesNeeded; 3546 ret = TRUE; 3547 } 3548 else 3549 { 3550 /* Sanity check the year, this is a two-digit year format */ 3551 ret = FileTimeToSystemTime(pvStructInfo, &sysTime); 3552 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050)) 3553 { 3554 SetLastError(CRYPT_E_BAD_ENCODE); 3555 ret = FALSE; 3556 } 3557 if (ret) 3558 { 3559 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3560 pbEncoded, pcbEncoded, bytesNeeded))) 3561 { 3562 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3563 pbEncoded = *(BYTE **)pbEncoded; 3564 buf[0] = ASN_UTCTIME; 3565 buf[1] = bytesNeeded - 2; 3566 snprintf(buf + 2, sizeof(buf) - 2, 3567 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ? 3568 sysTime.wYear - 2000 : sysTime.wYear - 1900, 3569 sysTime.wMonth, sysTime.wDay, sysTime.wHour, 3570 sysTime.wMinute, sysTime.wSecond); 3571 memcpy(pbEncoded, buf, bytesNeeded); 3572 } 3573 } 3574 } 3575 } 3576 __EXCEPT_PAGE_FAULT 3577 { 3578 SetLastError(STATUS_ACCESS_VIOLATION); 3579 ret = FALSE; 3580 } 3581 __ENDTRY 3582 return ret; 3583 } 3584 3585 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType, 3586 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3587 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3588 { 3589 BOOL ret; 3590 3591 __TRY 3592 { 3593 SYSTEMTIME sysTime; 3594 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a 3595 * temporary buffer because the output buffer is not NULL-terminated. 3596 */ 3597 static const DWORD bytesNeeded = 17; 3598 char buf[40]; 3599 3600 if (!pbEncoded) 3601 { 3602 *pcbEncoded = bytesNeeded; 3603 ret = TRUE; 3604 } 3605 else 3606 { 3607 ret = FileTimeToSystemTime(pvStructInfo, &sysTime); 3608 if (ret) 3609 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3610 pcbEncoded, bytesNeeded); 3611 if (ret) 3612 { 3613 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3614 pbEncoded = *(BYTE **)pbEncoded; 3615 buf[0] = ASN_GENERALTIME; 3616 buf[1] = bytesNeeded - 2; 3617 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ", 3618 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, 3619 sysTime.wMinute, sysTime.wSecond); 3620 memcpy(pbEncoded, buf, bytesNeeded); 3621 } 3622 } 3623 } 3624 __EXCEPT_PAGE_FAULT 3625 { 3626 SetLastError(STATUS_ACCESS_VIOLATION); 3627 ret = FALSE; 3628 } 3629 __ENDTRY 3630 return ret; 3631 } 3632 3633 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, 3634 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3635 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3636 { 3637 BOOL ret; 3638 3639 __TRY 3640 { 3641 SYSTEMTIME sysTime; 3642 3643 /* Check the year, if it's in the UTCTime range call that encode func */ 3644 if (!FileTimeToSystemTime(pvStructInfo, &sysTime)) 3645 return FALSE; 3646 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050) 3647 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType, 3648 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3649 else 3650 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType, 3651 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded, 3652 pcbEncoded); 3653 } 3654 __EXCEPT_PAGE_FAULT 3655 { 3656 SetLastError(STATUS_ACCESS_VIOLATION); 3657 ret = FALSE; 3658 } 3659 __ENDTRY 3660 return ret; 3661 } 3662 3663 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, 3664 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3665 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3666 { 3667 BOOL ret; 3668 3669 __TRY 3670 { 3671 DWORD bytesNeeded, dataLen, lenBytes, i; 3672 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo; 3673 3674 for (i = 0, dataLen = 0; i < seq->cValue; i++) 3675 dataLen += seq->rgValue[i].cbData; 3676 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 3677 bytesNeeded = 1 + lenBytes + dataLen; 3678 if (!pbEncoded) 3679 { 3680 *pcbEncoded = bytesNeeded; 3681 ret = TRUE; 3682 } 3683 else 3684 { 3685 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, 3686 pcbEncoded, bytesNeeded))) 3687 { 3688 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3689 pbEncoded = *(BYTE **)pbEncoded; 3690 *pbEncoded++ = ASN_SEQUENCEOF; 3691 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 3692 pbEncoded += lenBytes; 3693 for (i = 0; i < seq->cValue; i++) 3694 { 3695 memcpy(pbEncoded, seq->rgValue[i].pbData, 3696 seq->rgValue[i].cbData); 3697 pbEncoded += seq->rgValue[i].cbData; 3698 } 3699 } 3700 } 3701 } 3702 __EXCEPT_PAGE_FAULT 3703 { 3704 SetLastError(STATUS_ACCESS_VIOLATION); 3705 ret = FALSE; 3706 } 3707 __ENDTRY 3708 return ret; 3709 } 3710 3711 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint, 3712 BYTE *pbEncoded, DWORD *pcbEncoded) 3713 { 3714 BOOL ret = TRUE; 3715 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 3716 struct AsnConstructedItem constructed = { 0 }; 3717 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 3718 DWORD cItem = 0, cSwapped = 0; 3719 3720 switch (distPoint->DistPointName.dwDistPointNameChoice) 3721 { 3722 case CRL_DIST_POINT_NO_NAME: 3723 /* do nothing */ 3724 break; 3725 case CRL_DIST_POINT_FULL_NAME: 3726 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 3727 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName; 3728 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 3729 constructed.tag = 0; 3730 constructed.pvStructInfo = &swapped[cSwapped]; 3731 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag; 3732 items[cItem].pvStructInfo = &constructed; 3733 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 3734 cSwapped++; 3735 cItem++; 3736 break; 3737 case CRL_DIST_POINT_ISSUER_RDN_NAME: 3738 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n"); 3739 ret = FALSE; 3740 break; 3741 default: 3742 ret = FALSE; 3743 } 3744 if (ret && distPoint->ReasonFlags.cbData) 3745 { 3746 swapped[cSwapped].tag = ASN_CONTEXT | 1; 3747 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags; 3748 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 3749 items[cItem].pvStructInfo = &swapped[cSwapped]; 3750 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3751 cSwapped++; 3752 cItem++; 3753 } 3754 if (ret && distPoint->CRLIssuer.cAltEntry) 3755 { 3756 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2; 3757 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer; 3758 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 3759 items[cItem].pvStructInfo = &swapped[cSwapped]; 3760 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3761 cSwapped++; 3762 cItem++; 3763 } 3764 if (ret) 3765 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, 3766 pbEncoded, pcbEncoded); 3767 return ret; 3768 } 3769 3770 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType, 3771 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3772 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3773 { 3774 BOOL ret; 3775 3776 __TRY 3777 { 3778 const CRL_DIST_POINTS_INFO *info = pvStructInfo; 3779 3780 if (!info->cDistPoint) 3781 { 3782 SetLastError(E_INVALIDARG); 3783 ret = FALSE; 3784 } 3785 else 3786 { 3787 DWORD bytesNeeded, dataLen, lenBytes, i; 3788 3789 ret = TRUE; 3790 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++) 3791 { 3792 DWORD len; 3793 3794 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL, 3795 &len); 3796 if (ret) 3797 dataLen += len; 3798 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING) 3799 { 3800 /* Have to propagate index of failing character */ 3801 *pcbEncoded = len; 3802 } 3803 } 3804 if (ret) 3805 { 3806 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 3807 bytesNeeded = 1 + lenBytes + dataLen; 3808 if (!pbEncoded) 3809 { 3810 *pcbEncoded = bytesNeeded; 3811 ret = TRUE; 3812 } 3813 else 3814 { 3815 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3816 pbEncoded, pcbEncoded, bytesNeeded))) 3817 { 3818 BYTE *out; 3819 3820 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3821 pbEncoded = *(BYTE **)pbEncoded; 3822 out = pbEncoded; 3823 *out++ = ASN_SEQUENCEOF; 3824 CRYPT_EncodeLen(dataLen, out, &lenBytes); 3825 out += lenBytes; 3826 for (i = 0; ret && i < info->cDistPoint; i++) 3827 { 3828 DWORD len = dataLen; 3829 3830 ret = CRYPT_AsnEncodeDistPoint( 3831 &info->rgDistPoint[i], out, &len); 3832 if (ret) 3833 { 3834 out += len; 3835 dataLen -= len; 3836 } 3837 } 3838 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 3839 CRYPT_FreeSpace(pEncodePara, pbEncoded); 3840 } 3841 } 3842 } 3843 } 3844 } 3845 __EXCEPT_PAGE_FAULT 3846 { 3847 SetLastError(STATUS_ACCESS_VIOLATION); 3848 ret = FALSE; 3849 } 3850 __ENDTRY 3851 return ret; 3852 } 3853 3854 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType, 3855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3857 { 3858 BOOL ret; 3859 3860 __TRY 3861 { 3862 const CERT_ENHKEY_USAGE *usage = pvStructInfo; 3863 DWORD bytesNeeded = 0, lenBytes, size, i; 3864 3865 ret = TRUE; 3866 for (i = 0; ret && i < usage->cUsageIdentifier; i++) 3867 { 3868 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 3869 usage->rgpszUsageIdentifier[i], 3870 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size); 3871 if (ret) 3872 bytesNeeded += size; 3873 } 3874 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 3875 bytesNeeded += 1 + lenBytes; 3876 if (ret) 3877 { 3878 if (!pbEncoded) 3879 *pcbEncoded = bytesNeeded; 3880 else 3881 { 3882 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 3883 pbEncoded, pcbEncoded, bytesNeeded))) 3884 { 3885 BYTE *out; 3886 3887 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 3888 pbEncoded = *(BYTE **)pbEncoded; 3889 out = pbEncoded; 3890 *out++ = ASN_SEQUENCEOF; 3891 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes); 3892 out += lenBytes; 3893 for (i = 0; ret && i < usage->cUsageIdentifier; i++) 3894 { 3895 size = bytesNeeded; 3896 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, 3897 usage->rgpszUsageIdentifier[i], 3898 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size); 3899 if (ret) 3900 { 3901 out += size; 3902 bytesNeeded -= size; 3903 } 3904 } 3905 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)) 3906 CRYPT_FreeSpace(pEncodePara, pbEncoded); 3907 } 3908 } 3909 } 3910 } 3911 __EXCEPT_PAGE_FAULT 3912 { 3913 SetLastError(STATUS_ACCESS_VIOLATION); 3914 ret = FALSE; 3915 } 3916 __ENDTRY 3917 return ret; 3918 } 3919 3920 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType, 3921 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 3922 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 3923 { 3924 BOOL ret; 3925 3926 __TRY 3927 { 3928 const CRL_ISSUING_DIST_POINT *point = pvStructInfo; 3929 struct AsnEncodeSequenceItem items[6] = { { 0 } }; 3930 struct AsnConstructedItem constructed = { 0 }; 3931 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } }; 3932 DWORD cItem = 0, cSwapped = 0; 3933 3934 ret = TRUE; 3935 switch (point->DistPointName.dwDistPointNameChoice) 3936 { 3937 case CRL_DIST_POINT_NO_NAME: 3938 /* do nothing */ 3939 break; 3940 case CRL_DIST_POINT_FULL_NAME: 3941 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 3942 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName; 3943 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName; 3944 constructed.tag = 0; 3945 constructed.pvStructInfo = &swapped[cSwapped]; 3946 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag; 3947 items[cItem].pvStructInfo = &constructed; 3948 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 3949 cSwapped++; 3950 cItem++; 3951 break; 3952 default: 3953 SetLastError(E_INVALIDARG); 3954 ret = FALSE; 3955 } 3956 if (ret && point->fOnlyContainsUserCerts) 3957 { 3958 swapped[cSwapped].tag = ASN_CONTEXT | 1; 3959 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts; 3960 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 3961 items[cItem].pvStructInfo = &swapped[cSwapped]; 3962 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3963 cSwapped++; 3964 cItem++; 3965 } 3966 if (ret && point->fOnlyContainsCACerts) 3967 { 3968 swapped[cSwapped].tag = ASN_CONTEXT | 2; 3969 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts; 3970 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 3971 items[cItem].pvStructInfo = &swapped[cSwapped]; 3972 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3973 cSwapped++; 3974 cItem++; 3975 } 3976 if (ret && point->OnlySomeReasonFlags.cbData) 3977 { 3978 swapped[cSwapped].tag = ASN_CONTEXT | 3; 3979 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags; 3980 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits; 3981 items[cItem].pvStructInfo = &swapped[cSwapped]; 3982 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3983 cSwapped++; 3984 cItem++; 3985 } 3986 if (ret && point->fIndirectCRL) 3987 { 3988 swapped[cSwapped].tag = ASN_CONTEXT | 4; 3989 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL; 3990 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool; 3991 items[cItem].pvStructInfo = &swapped[cSwapped]; 3992 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 3993 cSwapped++; 3994 cItem++; 3995 } 3996 if (ret) 3997 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 3998 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 3999 } 4000 __EXCEPT_PAGE_FAULT 4001 { 4002 SetLastError(STATUS_ACCESS_VIOLATION); 4003 ret = FALSE; 4004 } 4005 __ENDTRY 4006 return ret; 4007 } 4008 4009 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType, 4010 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4011 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4012 { 4013 BOOL ret; 4014 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo; 4015 struct AsnEncodeSequenceItem items[3] = { 4016 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 }, 4017 { 0 } 4018 }; 4019 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4020 DWORD cItem = 1, cSwapped = 0; 4021 4022 if (subtree->dwMinimum) 4023 { 4024 swapped[cSwapped].tag = ASN_CONTEXT | 0; 4025 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum; 4026 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 4027 items[cItem].pvStructInfo = &swapped[cSwapped]; 4028 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4029 cSwapped++; 4030 cItem++; 4031 } 4032 if (subtree->fMaximum) 4033 { 4034 swapped[cSwapped].tag = ASN_CONTEXT | 1; 4035 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum; 4036 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt; 4037 items[cItem].pvStructInfo = &swapped[cSwapped]; 4038 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4039 cSwapped++; 4040 cItem++; 4041 } 4042 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags, 4043 pEncodePara, pbEncoded, pcbEncoded); 4044 return ret; 4045 } 4046 4047 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType, 4048 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4049 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4050 { 4051 BOOL ret = FALSE; 4052 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL }; 4053 4054 TRACE("%p\n", pvStructInfo); 4055 4056 __TRY 4057 { 4058 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo; 4059 struct AsnEncodeSequenceItem items[2] = { { 0 } }; 4060 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4061 DWORD i, cItem = 0, cSwapped = 0; 4062 4063 ret = TRUE; 4064 if (constraints->cPermittedSubtree) 4065 { 4066 permitted.rgBlob = CryptMemAlloc( 4067 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB)); 4068 if (permitted.rgBlob) 4069 { 4070 permitted.cBlob = constraints->cPermittedSubtree; 4071 memset(permitted.rgBlob, 0, 4072 permitted.cBlob * sizeof(CRYPT_DER_BLOB)); 4073 for (i = 0; ret && i < permitted.cBlob; i++) 4074 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType, 4075 NULL, &constraints->rgPermittedSubtree[i], 4076 CRYPT_ENCODE_ALLOC_FLAG, NULL, 4077 (BYTE *)&permitted.rgBlob[i].pbData, 4078 &permitted.rgBlob[i].cbData); 4079 if (ret) 4080 { 4081 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 4082 swapped[cSwapped].pvStructInfo = &permitted; 4083 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet; 4084 items[cItem].pvStructInfo = &swapped[cSwapped]; 4085 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4086 cSwapped++; 4087 cItem++; 4088 } 4089 } 4090 else 4091 ret = FALSE; 4092 } 4093 if (constraints->cExcludedSubtree) 4094 { 4095 excluded.rgBlob = CryptMemAlloc( 4096 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB)); 4097 if (excluded.rgBlob) 4098 { 4099 excluded.cBlob = constraints->cExcludedSubtree; 4100 memset(excluded.rgBlob, 0, 4101 excluded.cBlob * sizeof(CRYPT_DER_BLOB)); 4102 for (i = 0; ret && i < excluded.cBlob; i++) 4103 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType, 4104 NULL, &constraints->rgExcludedSubtree[i], 4105 CRYPT_ENCODE_ALLOC_FLAG, NULL, 4106 (BYTE *)&excluded.rgBlob[i].pbData, 4107 &excluded.rgBlob[i].cbData); 4108 if (ret) 4109 { 4110 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 4111 swapped[cSwapped].pvStructInfo = &excluded; 4112 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet; 4113 items[cItem].pvStructInfo = &swapped[cSwapped]; 4114 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4115 cSwapped++; 4116 cItem++; 4117 } 4118 } 4119 else 4120 ret = FALSE; 4121 } 4122 if (ret) 4123 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 4124 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4125 for (i = 0; i < permitted.cBlob; i++) 4126 LocalFree(permitted.rgBlob[i].pbData); 4127 for (i = 0; i < excluded.cBlob; i++) 4128 LocalFree(excluded.rgBlob[i].pbData); 4129 } 4130 __EXCEPT_PAGE_FAULT 4131 { 4132 SetLastError(STATUS_ACCESS_VIOLATION); 4133 } 4134 __ENDTRY 4135 CryptMemFree(permitted.rgBlob); 4136 CryptMemFree(excluded.rgBlob); 4137 TRACE("returning %d\n", ret); 4138 return ret; 4139 } 4140 4141 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber( 4142 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 4143 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, 4144 DWORD *pcbEncoded) 4145 { 4146 BOOL ret; 4147 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo; 4148 struct AsnEncodeSequenceItem items[] = { 4149 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 }, 4150 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, 4151 }; 4152 4153 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 4154 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 4155 pcbEncoded); 4156 return ret; 4157 } 4158 4159 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType, 4160 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4161 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4162 { 4163 BOOL ret = FALSE; 4164 4165 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING)) 4166 { 4167 SetLastError(E_INVALIDARG); 4168 return FALSE; 4169 } 4170 4171 __TRY 4172 { 4173 const CMSG_SIGNER_INFO *info = pvStructInfo; 4174 4175 if (!info->Issuer.cbData) 4176 SetLastError(E_INVALIDARG); 4177 else 4178 { 4179 struct AsnEncodeSequenceItem items[7] = { 4180 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 4181 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 }, 4182 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 4183 0 }, 4184 }; 4185 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4186 DWORD cItem = 3, cSwapped = 0; 4187 4188 if (info->AuthAttrs.cAttr) 4189 { 4190 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 4191 swapped[cSwapped].pvStructInfo = &info->AuthAttrs; 4192 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4193 items[cItem].pvStructInfo = &swapped[cSwapped]; 4194 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4195 cSwapped++; 4196 cItem++; 4197 } 4198 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; 4199 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4200 cItem++; 4201 items[cItem].pvStructInfo = &info->EncryptedHash; 4202 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 4203 cItem++; 4204 if (info->UnauthAttrs.cAttr) 4205 { 4206 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 4207 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; 4208 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4209 items[cItem].pvStructInfo = &swapped[cSwapped]; 4210 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4211 cSwapped++; 4212 cItem++; 4213 } 4214 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 4215 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4216 } 4217 } 4218 __EXCEPT_PAGE_FAULT 4219 { 4220 SetLastError(STATUS_ACCESS_VIOLATION); 4221 } 4222 __ENDTRY 4223 return ret; 4224 } 4225 4226 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType, 4227 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4228 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4229 { 4230 BOOL ret = FALSE; 4231 4232 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING)) 4233 { 4234 SetLastError(E_INVALIDARG); 4235 return FALSE; 4236 } 4237 4238 __TRY 4239 { 4240 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo; 4241 4242 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER && 4243 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER) 4244 SetLastError(E_INVALIDARG); 4245 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER && 4246 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData) 4247 SetLastError(E_INVALIDARG); 4248 else 4249 { 4250 struct AsnEncodeSequenceItem items[7] = { 4251 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 4252 }; 4253 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } }; 4254 DWORD cItem = 1, cSwapped = 0; 4255 4256 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER) 4257 { 4258 items[cItem].pvStructInfo = 4259 &info->SignerId.u.IssuerSerialNumber.Issuer; 4260 items[cItem].encodeFunc = 4261 CRYPT_AsnEncodeIssuerSerialNumber; 4262 cItem++; 4263 } 4264 else 4265 { 4266 swapped[cSwapped].tag = ASN_CONTEXT | 0; 4267 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId; 4268 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets; 4269 items[cItem].pvStructInfo = &swapped[cSwapped]; 4270 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4271 cSwapped++; 4272 cItem++; 4273 } 4274 items[cItem].pvStructInfo = &info->HashAlgorithm; 4275 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4276 cItem++; 4277 if (info->AuthAttrs.cAttr) 4278 { 4279 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; 4280 swapped[cSwapped].pvStructInfo = &info->AuthAttrs; 4281 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4282 items[cItem].pvStructInfo = &swapped[cSwapped]; 4283 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4284 cSwapped++; 4285 cItem++; 4286 } 4287 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; 4288 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4289 cItem++; 4290 items[cItem].pvStructInfo = &info->EncryptedHash; 4291 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; 4292 cItem++; 4293 if (info->UnauthAttrs.cAttr) 4294 { 4295 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; 4296 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; 4297 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4298 items[cItem].pvStructInfo = &swapped[cSwapped]; 4299 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4300 cSwapped++; 4301 cItem++; 4302 } 4303 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 4304 dwFlags, pEncodePara, pbEncoded, pcbEncoded); 4305 } 4306 } 4307 __EXCEPT_PAGE_FAULT 4308 { 4309 SetLastError(STATUS_ACCESS_VIOLATION); 4310 } 4311 __ENDTRY 4312 return ret; 4313 } 4314 4315 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData, 4316 DWORD *pcbData) 4317 { 4318 struct AsnEncodeSequenceItem items[7] = { 4319 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 }, 4320 }; 4321 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 }; 4322 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 }; 4323 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; 4324 DWORD cItem = 1, cSwapped = 0; 4325 BOOL ret = TRUE; 4326 4327 if (signedInfo->cSignerInfo) 4328 { 4329 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo; 4330 digestAlgorithmsSet.items = signedInfo->rgSignerInfo; 4331 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO); 4332 digestAlgorithmsSet.itemOffset = 4333 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm); 4334 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams; 4335 items[cItem].pvStructInfo = &digestAlgorithmsSet; 4336 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4337 cItem++; 4338 } 4339 items[cItem].pvStructInfo = &signedInfo->content; 4340 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal; 4341 cItem++; 4342 if (signedInfo->cCertEncoded) 4343 { 4344 certSet.cItems = signedInfo->cCertEncoded; 4345 certSet.items = signedInfo->rgCertEncoded; 4346 certSet.itemSize = sizeof(CERT_BLOB); 4347 certSet.itemOffset = 0; 4348 certSet.encode = CRYPT_CopyEncodedBlob; 4349 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0; 4350 swapped[cSwapped].pvStructInfo = &certSet; 4351 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4352 items[cItem].pvStructInfo = &swapped[cSwapped]; 4353 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4354 cSwapped++; 4355 cItem++; 4356 } 4357 if (signedInfo->cCrlEncoded) 4358 { 4359 crlSet.cItems = signedInfo->cCrlEncoded; 4360 crlSet.items = signedInfo->rgCrlEncoded; 4361 crlSet.itemSize = sizeof(CRL_BLOB); 4362 crlSet.itemOffset = 0; 4363 crlSet.encode = CRYPT_CopyEncodedBlob; 4364 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1; 4365 swapped[cSwapped].pvStructInfo = &crlSet; 4366 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4367 items[cItem].pvStructInfo = &swapped[cSwapped]; 4368 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; 4369 cSwapped++; 4370 cItem++; 4371 } 4372 if (ret && signedInfo->cSignerInfo) 4373 { 4374 signerSet.cItems = signedInfo->cSignerInfo; 4375 signerSet.items = signedInfo->rgSignerInfo; 4376 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO); 4377 signerSet.itemOffset = 0; 4378 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo; 4379 items[cItem].pvStructInfo = &signerSet; 4380 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet; 4381 cItem++; 4382 } 4383 if (ret) 4384 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 4385 items, cItem, 0, NULL, pvData, pcbData); 4386 4387 return ret; 4388 } 4389 4390 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType, 4391 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4392 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4393 { 4394 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo; 4395 struct AsnEncodeSequenceItem items[] = { 4396 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, 4397 { &info->RecipientId.u.IssuerSerialNumber, 4398 CRYPT_AsnEncodeIssuerSerialNumber, 0 }, 4399 { &info->KeyEncryptionAlgorithm, 4400 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 4401 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 }, 4402 }; 4403 4404 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 4405 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 4406 pcbEncoded); 4407 } 4408 4409 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType, 4410 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, 4411 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) 4412 { 4413 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo; 4414 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0, 4415 &info->encryptedContent, CRYPT_AsnEncodeOctets }; 4416 struct AsnEncodeSequenceItem items[] = { 4417 { info->contentType, CRYPT_AsnEncodeOid, 0 }, 4418 { &info->contentEncryptionAlgorithm, 4419 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 4420 { &swapped, CRYPT_AsnEncodeSwapTag, 0 }, 4421 }; 4422 4423 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 4424 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, 4425 pcbEncoded); 4426 } 4427 4428 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData, 4429 void *pvData, DWORD *pcbData) 4430 { 4431 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo, 4432 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0, 4433 CRYPT_AsnEncodeRecipientInfo }; 4434 struct AsnEncodeSequenceItem items[] = { 4435 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 }, 4436 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 }, 4437 { &envelopedData->encryptedContentInfo, 4438 CRYPT_AsnEncodeEncryptedContentInfo, 0 }, 4439 }; 4440 4441 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, 4442 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData); 4443 } 4444 4445 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType, 4446 LPCSTR lpszStructType) 4447 { 4448 CryptEncodeObjectExFunc encodeFunc = NULL; 4449 4450 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING 4451 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING) 4452 { 4453 SetLastError(ERROR_FILE_NOT_FOUND); 4454 return NULL; 4455 } 4456 4457 if (IS_INTOID(lpszStructType)) 4458 { 4459 switch (LOWORD(lpszStructType)) 4460 { 4461 case LOWORD(X509_CERT): 4462 encodeFunc = CRYPT_AsnEncodeCert; 4463 break; 4464 case LOWORD(X509_CERT_TO_BE_SIGNED): 4465 encodeFunc = CRYPT_AsnEncodeCertInfo; 4466 break; 4467 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED): 4468 encodeFunc = CRYPT_AsnEncodeCRLInfo; 4469 break; 4470 case LOWORD(X509_EXTENSIONS): 4471 encodeFunc = CRYPT_AsnEncodeExtensions; 4472 break; 4473 case LOWORD(X509_NAME_VALUE): 4474 encodeFunc = CRYPT_AsnEncodeNameValue; 4475 break; 4476 case LOWORD(X509_NAME): 4477 encodeFunc = CRYPT_AsnEncodeName; 4478 break; 4479 case LOWORD(X509_PUBLIC_KEY_INFO): 4480 encodeFunc = CRYPT_AsnEncodePubKeyInfo; 4481 break; 4482 case LOWORD(X509_AUTHORITY_KEY_ID): 4483 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId; 4484 break; 4485 case LOWORD(X509_ALTERNATE_NAME): 4486 encodeFunc = CRYPT_AsnEncodeAltName; 4487 break; 4488 case LOWORD(X509_BASIC_CONSTRAINTS): 4489 encodeFunc = CRYPT_AsnEncodeBasicConstraints; 4490 break; 4491 case LOWORD(X509_BASIC_CONSTRAINTS2): 4492 encodeFunc = CRYPT_AsnEncodeBasicConstraints2; 4493 break; 4494 case LOWORD(X509_CERT_POLICIES): 4495 encodeFunc = CRYPT_AsnEncodeCertPolicies; 4496 break; 4497 case LOWORD(RSA_CSP_PUBLICKEYBLOB): 4498 encodeFunc = CRYPT_AsnEncodeRsaPubKey; 4499 break; 4500 case LOWORD(X509_UNICODE_NAME): 4501 encodeFunc = CRYPT_AsnEncodeUnicodeName; 4502 break; 4503 case LOWORD(PKCS_CONTENT_INFO): 4504 encodeFunc = CRYPT_AsnEncodePKCSContentInfo; 4505 break; 4506 case LOWORD(PKCS_ATTRIBUTE): 4507 encodeFunc = CRYPT_AsnEncodePKCSAttribute; 4508 break; 4509 case LOWORD(X509_UNICODE_NAME_VALUE): 4510 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue; 4511 break; 4512 case LOWORD(X509_OCTET_STRING): 4513 encodeFunc = CRYPT_AsnEncodeOctets; 4514 break; 4515 case LOWORD(X509_BITS): 4516 case LOWORD(X509_KEY_USAGE): 4517 encodeFunc = CRYPT_AsnEncodeBits; 4518 break; 4519 case LOWORD(X509_INTEGER): 4520 encodeFunc = CRYPT_AsnEncodeInt; 4521 break; 4522 case LOWORD(X509_MULTI_BYTE_INTEGER): 4523 encodeFunc = CRYPT_AsnEncodeInteger; 4524 break; 4525 case LOWORD(X509_MULTI_BYTE_UINT): 4526 encodeFunc = CRYPT_AsnEncodeUnsignedInteger; 4527 break; 4528 case LOWORD(X509_ENUMERATED): 4529 encodeFunc = CRYPT_AsnEncodeEnumerated; 4530 break; 4531 case LOWORD(X509_CHOICE_OF_TIME): 4532 encodeFunc = CRYPT_AsnEncodeChoiceOfTime; 4533 break; 4534 case LOWORD(X509_AUTHORITY_KEY_ID2): 4535 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2; 4536 break; 4537 case LOWORD(X509_AUTHORITY_INFO_ACCESS): 4538 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess; 4539 break; 4540 case LOWORD(X509_SEQUENCE_OF_ANY): 4541 encodeFunc = CRYPT_AsnEncodeSequenceOfAny; 4542 break; 4543 case LOWORD(PKCS_UTC_TIME): 4544 encodeFunc = CRYPT_AsnEncodeUtcTime; 4545 break; 4546 case LOWORD(X509_CRL_DIST_POINTS): 4547 encodeFunc = CRYPT_AsnEncodeCRLDistPoints; 4548 break; 4549 case LOWORD(X509_ENHANCED_KEY_USAGE): 4550 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage; 4551 break; 4552 case LOWORD(PKCS_CTL): 4553 encodeFunc = CRYPT_AsnEncodeCTL; 4554 break; 4555 case LOWORD(PKCS_SMIME_CAPABILITIES): 4556 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities; 4557 break; 4558 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE): 4559 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice; 4560 break; 4561 case LOWORD(PKCS_ATTRIBUTES): 4562 encodeFunc = CRYPT_AsnEncodePKCSAttributes; 4563 break; 4564 case LOWORD(X509_ISSUING_DIST_POINT): 4565 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint; 4566 break; 4567 case LOWORD(X509_NAME_CONSTRAINTS): 4568 encodeFunc = CRYPT_AsnEncodeNameConstraints; 4569 break; 4570 case LOWORD(X509_POLICY_MAPPINGS): 4571 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 4572 break; 4573 case LOWORD(X509_POLICY_CONSTRAINTS): 4574 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints; 4575 break; 4576 case LOWORD(PKCS7_SIGNER_INFO): 4577 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo; 4578 break; 4579 case LOWORD(CMS_SIGNER_INFO): 4580 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo; 4581 break; 4582 } 4583 } 4584 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS)) 4585 encodeFunc = CRYPT_AsnEncodeExtensions; 4586 else if (!strcmp(lpszStructType, szOID_RSA_signingTime)) 4587 encodeFunc = CRYPT_AsnEncodeUtcTime; 4588 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities)) 4589 encodeFunc = CRYPT_AsnEncodeUtcTime; 4590 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER)) 4591 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId; 4592 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS)) 4593 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 4594 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2)) 4595 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2; 4596 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE)) 4597 encodeFunc = CRYPT_AsnEncodeEnumerated; 4598 else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) 4599 encodeFunc = CRYPT_AsnEncodeBits; 4600 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER)) 4601 encodeFunc = CRYPT_AsnEncodeOctets; 4602 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS)) 4603 encodeFunc = CRYPT_AsnEncodeBasicConstraints; 4604 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) 4605 encodeFunc = CRYPT_AsnEncodeBasicConstraints2; 4606 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) 4607 encodeFunc = CRYPT_AsnEncodeAltName; 4608 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) 4609 encodeFunc = CRYPT_AsnEncodeAltName; 4610 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION)) 4611 encodeFunc = CRYPT_AsnEncodeAltName; 4612 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) 4613 encodeFunc = CRYPT_AsnEncodeAltName; 4614 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) 4615 encodeFunc = CRYPT_AsnEncodeAltName; 4616 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS)) 4617 encodeFunc = CRYPT_AsnEncodeCRLDistPoints; 4618 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES)) 4619 encodeFunc = CRYPT_AsnEncodeCertPolicies; 4620 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS)) 4621 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings; 4622 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS)) 4623 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints; 4624 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE)) 4625 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage; 4626 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT)) 4627 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint; 4628 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS)) 4629 encodeFunc = CRYPT_AsnEncodeNameConstraints; 4630 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS)) 4631 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess; 4632 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) 4633 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice; 4634 else if (!strcmp(lpszStructType, szOID_CTL)) 4635 encodeFunc = CRYPT_AsnEncodeCTL; 4636 return encodeFunc; 4637 } 4638 4639 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType, 4640 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) 4641 { 4642 static HCRYPTOIDFUNCSET set = NULL; 4643 CryptEncodeObjectFunc encodeFunc = NULL; 4644 4645 if (!set) 4646 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0); 4647 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, 4648 (void **)&encodeFunc, hFunc); 4649 return encodeFunc; 4650 } 4651 4652 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType, 4653 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) 4654 { 4655 static HCRYPTOIDFUNCSET set = NULL; 4656 CryptEncodeObjectExFunc encodeFunc = NULL; 4657 4658 if (!set) 4659 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0); 4660 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, 4661 (void **)&encodeFunc, hFunc); 4662 return encodeFunc; 4663 } 4664 4665 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType, 4666 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded) 4667 { 4668 BOOL ret = FALSE; 4669 HCRYPTOIDFUNCADDR hFunc = NULL; 4670 CryptEncodeObjectFunc pCryptEncodeObject = NULL; 4671 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL; 4672 4673 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 4674 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, 4675 pcbEncoded); 4676 4677 if (!pbEncoded && !pcbEncoded) 4678 { 4679 SetLastError(ERROR_INVALID_PARAMETER); 4680 return FALSE; 4681 } 4682 4683 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType, 4684 lpszStructType))) 4685 { 4686 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", 4687 debugstr_a(lpszStructType)); 4688 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType, 4689 lpszStructType, &hFunc); 4690 if (!pCryptEncodeObject) 4691 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType, 4692 lpszStructType, &hFunc); 4693 } 4694 if (pCryptEncodeObject) 4695 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 4696 pvStructInfo, pbEncoded, pcbEncoded); 4697 else if (pCryptEncodeObjectEx) 4698 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType, 4699 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded); 4700 if (hFunc) 4701 CryptFreeOIDFunctionAddress(hFunc, 0); 4702 TRACE_(crypt)("returning %d\n", ret); 4703 return ret; 4704 } 4705 4706 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, 4707 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, 4708 void *pvEncoded, DWORD *pcbEncoded) 4709 { 4710 BOOL ret = FALSE; 4711 HCRYPTOIDFUNCADDR hFunc = NULL; 4712 CryptEncodeObjectExFunc encodeFunc = NULL; 4713 4714 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType, 4715 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara, 4716 pvEncoded, pcbEncoded); 4717 4718 if (!pvEncoded && !pcbEncoded) 4719 { 4720 SetLastError(ERROR_INVALID_PARAMETER); 4721 return FALSE; 4722 } 4723 4724 SetLastError(NOERROR); 4725 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) { 4726 if (!pvEncoded) { 4727 SetLastError(ERROR_INVALID_PARAMETER); 4728 return FALSE; 4729 } 4730 *(BYTE **)pvEncoded = NULL; 4731 } 4732 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType); 4733 if (!encodeFunc) 4734 { 4735 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", 4736 debugstr_a(lpszStructType)); 4737 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType, 4738 &hFunc); 4739 } 4740 if (encodeFunc) 4741 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo, 4742 dwFlags, pEncodePara, pvEncoded, pcbEncoded); 4743 else 4744 { 4745 CryptEncodeObjectFunc pCryptEncodeObject = 4746 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc); 4747 4748 if (pCryptEncodeObject) 4749 { 4750 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) 4751 { 4752 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 4753 pvStructInfo, NULL, pcbEncoded); 4754 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, 4755 pvEncoded, pcbEncoded, *pcbEncoded))) 4756 ret = pCryptEncodeObject(dwCertEncodingType, 4757 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded, 4758 pcbEncoded); 4759 } 4760 else 4761 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, 4762 pvStructInfo, pvEncoded, pcbEncoded); 4763 } 4764 } 4765 if (hFunc) 4766 CryptFreeOIDFunctionAddress(hFunc, 0); 4767 TRACE_(crypt)("returning %d\n", ret); 4768 return ret; 4769 } 4770 4771 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX, 4772 LPCWSTR szPassword, DWORD dwFlags) 4773 { 4774 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags); 4775 } 4776 4777 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX, 4778 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags) 4779 { 4780 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword, 4781 pvReserved, dwFlags); 4782 return FALSE; 4783 } 4784 4785 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec, 4786 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 4787 { 4788 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType, 4789 NULL, 0, NULL, pInfo, pcbInfo); 4790 } 4791 4792 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 4793 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, 4794 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 4795 { 4796 BOOL ret; 4797 HCRYPTKEY key; 4798 static CHAR oid[] = szOID_RSA_RSA; 4799 4800 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv, 4801 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, 4802 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0); 4803 4804 if (!pszPublicKeyObjId) 4805 pszPublicKeyObjId = oid; 4806 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key))) 4807 { 4808 DWORD keySize = 0; 4809 4810 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize); 4811 if (ret) 4812 { 4813 LPBYTE pubKey = CryptMemAlloc(keySize); 4814 4815 if (pubKey) 4816 { 4817 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey, 4818 &keySize); 4819 if (ret) 4820 { 4821 DWORD encodedLen = 0; 4822 4823 ret = CryptEncodeObject(dwCertEncodingType, 4824 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen); 4825 if (ret) 4826 { 4827 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) + 4828 strlen(pszPublicKeyObjId) + 1 + encodedLen; 4829 4830 if (!pInfo) 4831 *pcbInfo = sizeNeeded; 4832 else if (*pcbInfo < sizeNeeded) 4833 { 4834 SetLastError(ERROR_MORE_DATA); 4835 *pcbInfo = sizeNeeded; 4836 ret = FALSE; 4837 } 4838 else 4839 { 4840 *pcbInfo = sizeNeeded; 4841 pInfo->Algorithm.pszObjId = (char *)pInfo + 4842 sizeof(CERT_PUBLIC_KEY_INFO); 4843 lstrcpyA(pInfo->Algorithm.pszObjId, 4844 pszPublicKeyObjId); 4845 pInfo->Algorithm.Parameters.cbData = 0; 4846 pInfo->Algorithm.Parameters.pbData = NULL; 4847 pInfo->PublicKey.pbData = 4848 (BYTE *)pInfo->Algorithm.pszObjId 4849 + lstrlenA(pInfo->Algorithm.pszObjId) + 1; 4850 pInfo->PublicKey.cbData = encodedLen; 4851 pInfo->PublicKey.cUnusedBits = 0; 4852 ret = CryptEncodeObject(dwCertEncodingType, 4853 RSA_CSP_PUBLICKEYBLOB, pubKey, 4854 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData); 4855 } 4856 } 4857 } 4858 CryptMemFree(pubKey); 4859 } 4860 else 4861 ret = FALSE; 4862 } 4863 CryptDestroyKey(key); 4864 } 4865 return ret; 4866 } 4867 4868 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 4869 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, 4870 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo); 4871 4872 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec, 4873 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags, 4874 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) 4875 { 4876 static HCRYPTOIDFUNCSET set = NULL; 4877 BOOL ret; 4878 ExportPublicKeyInfoExFunc exportFunc = NULL; 4879 HCRYPTOIDFUNCADDR hFunc = NULL; 4880 4881 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv, 4882 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, 4883 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0); 4884 4885 if (!hCryptProv) 4886 { 4887 SetLastError(ERROR_INVALID_PARAMETER); 4888 return FALSE; 4889 } 4890 4891 if (pszPublicKeyObjId) 4892 { 4893 if (!set) 4894 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC, 4895 0); 4896 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId, 4897 0, (void **)&exportFunc, &hFunc); 4898 } 4899 if (!exportFunc) 4900 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx; 4901 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType, 4902 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo); 4903 if (hFunc) 4904 CryptFreeOIDFunctionAddress(hFunc, 0); 4905 return ret; 4906 } 4907 4908 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv, 4909 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) 4910 { 4911 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo, 4912 0, 0, NULL, phKey); 4913 } 4914 4915 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv, 4916 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 4917 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) 4918 { 4919 BOOL ret; 4920 DWORD pubKeySize = 0; 4921 4922 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv, 4923 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); 4924 4925 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 4926 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize); 4927 if (ret) 4928 { 4929 LPBYTE pubKey = CryptMemAlloc(pubKeySize); 4930 4931 if (pubKey) 4932 { 4933 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 4934 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey, 4935 &pubKeySize); 4936 if (ret) 4937 { 4938 if(aiKeyAlg) 4939 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg; 4940 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, 4941 phKey); 4942 } 4943 CryptMemFree(pubKey); 4944 } 4945 else 4946 ret = FALSE; 4947 } 4948 return ret; 4949 } 4950 4951 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv, 4952 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 4953 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey); 4954 4955 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv, 4956 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, 4957 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) 4958 { 4959 static HCRYPTOIDFUNCSET set = NULL; 4960 BOOL ret; 4961 ImportPublicKeyInfoExFunc importFunc = NULL; 4962 HCRYPTOIDFUNCADDR hFunc = NULL; 4963 4964 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv, 4965 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); 4966 4967 if (!set) 4968 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0); 4969 CryptGetOIDFunctionAddress(set, dwCertEncodingType, 4970 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc); 4971 if (!importFunc) 4972 importFunc = CRYPT_ImportRsaPublicKeyInfoEx; 4973 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, 4974 pvAuxInfo, phKey); 4975 if (hFunc) 4976 CryptFreeOIDFunctionAddress(hFunc, 0); 4977 return ret; 4978 } 4979