Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582/* * crypt32 Crypt*Object functions * * Copyright 2007 Juan Lang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */#include <stdarg.h>#define NONAMELESSUNION#include "windef.h"#include "winbase.h"#include "wincrypt.h"#include "mssip.h"#include "winuser.h"#include "wintrust.h"#include "crypt32_private.h"#include "cryptres.h"#include "wine/unicode.h"#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob){ BOOL ret = FALSE; HANDLE file;
TRACE("%s\n", debugstr_w(fileName));
file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (file != INVALID_HANDLE_VALUE) { ret = TRUE; blob->cbData = GetFileSize(file, NULL); if (blob->cbData) { blob->pbData = CryptMemAlloc(blob->cbData); if (blob->pbData) { DWORD read;
ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL) && read == blob->cbData; if (!ret) CryptMemFree(blob->pbData); } else ret = FALSE; } CloseHandle(file); } TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_QueryContextBlob(const CERT_BLOB *blob, DWORD dwExpectedContentTypeFlags, HCERTSTORE store, DWORD *contentType, const void **ppvContext){ BOOL ret = FALSE;
if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) { ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING, blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); if (ret && contentType) *contentType = CERT_QUERY_CONTENT_CERT; } if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL)) { ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING, blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); if (ret && contentType) *contentType = CERT_QUERY_CONTENT_CRL; } if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL)) { ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING, blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); if (ret && contentType) *contentType = CERT_QUERY_CONTENT_CTL; } return ret;}
static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject, DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType, HCERTSTORE *phCertStore, const void **ppvContext){ CERT_BLOB fileBlob; const CERT_BLOB *blob; HCERTSTORE store; BOOL ret; DWORD formatType = 0;
switch (dwObjectType) { case CERT_QUERY_OBJECT_FILE: /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so * just read the file directly */ ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob); blob = &fileBlob; break; case CERT_QUERY_OBJECT_BLOB: blob = pvObject; ret = TRUE; break; default: SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ ret = FALSE; } if (!ret) return FALSE;
ret = FALSE; store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY) { ret = CRYPT_QueryContextBlob(blob, dwExpectedContentTypeFlags, store, pdwContentType, ppvContext); if (ret) formatType = CERT_QUERY_FORMAT_BINARY; } if (!ret && (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED)) { CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData }; CRYPT_DATA_BLOB decoded;
while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1]) trimmed.cbData--; ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData, CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL); if (ret) { decoded.pbData = CryptMemAlloc(decoded.cbData); if (decoded.pbData) { ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData, &decoded.cbData, NULL, NULL); if (ret) { ret = CRYPT_QueryContextBlob(&decoded, dwExpectedContentTypeFlags, store, pdwContentType, ppvContext); if (ret) formatType = CERT_QUERY_FORMAT_BASE64_ENCODED; } CryptMemFree(decoded.pbData); } else ret = FALSE; } } if (ret) { if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; if (pdwFormatType) *pdwFormatType = formatType; if (phCertStore) *phCertStore = CertDuplicateStore(store); } CertCloseStore(store, 0); if (blob == &fileBlob) CryptMemFree(blob->pbData); TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType, const void *pvObject, DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCERTSTORE *phCertStore, const void **ppvContext){ CERT_BLOB fileBlob; const CERT_BLOB *blob; const WINE_CONTEXT_INTERFACE *contextInterface = NULL; const void *context; DWORD contextType; BOOL ret;
switch (dwObjectType) { case CERT_QUERY_OBJECT_FILE: /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so * just read the file directly */ ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob); blob = &fileBlob; break; case CERT_QUERY_OBJECT_BLOB: blob = pvObject; ret = TRUE; break; default: SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ ret = FALSE; } if (!ret) return FALSE;
ret = FALSE; context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData, CERT_STORE_ALL_CONTEXT_FLAG, &contextType); if (context) { DWORD contentType, certStoreOffset;
ret = TRUE; switch (contextType) { case CERT_STORE_CERTIFICATE_CONTEXT: contextInterface = pCertInterface; contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT; certStoreOffset = offsetof(CERT_CONTEXT, hCertStore); if (!(dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT)) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; goto end; } break; case CERT_STORE_CRL_CONTEXT: contextInterface = pCRLInterface; contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL; certStoreOffset = offsetof(CRL_CONTEXT, hCertStore); if (!(dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL)) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; goto end; } break; case CERT_STORE_CTL_CONTEXT: contextInterface = pCTLInterface; contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL; certStoreOffset = offsetof(CTL_CONTEXT, hCertStore); if (!(dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; goto end; } break; default: SetLastError(ERROR_INVALID_DATA); ret = FALSE; goto end; } if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; if (pdwContentType) *pdwContentType = contentType; if (phCertStore) *phCertStore = CertDuplicateStore( *(HCERTSTORE *)((const BYTE *)context + certStoreOffset)); if (ppvContext) { *ppvContext = context; Context_AddRef(context_from_ptr(context)); } }
end: if (contextInterface && context) Context_Release(context_from_ptr(context)); if (blob == &fileBlob) CryptMemFree(blob->pbData); TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_QuerySerializedStoreFromFile(LPCWSTR fileName, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg){ HANDLE file; BOOL ret = FALSE;
TRACE("%s\n", debugstr_w(fileName)); file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (file != INVALID_HANDLE_VALUE) { HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
ret = CRYPT_ReadSerializedStoreFromFile(file, store); if (ret) { if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; if (pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE; if (phCertStore) *phCertStore = CertDuplicateStore(store); } CertCloseStore(store, 0); CloseHandle(file); } TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_QuerySerializedStoreFromBlob(const CRYPT_DATA_BLOB *blob, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg){ HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); BOOL ret;
TRACE("(%d, %p)\n", blob->cbData, blob->pbData);
ret = CRYPT_ReadSerializedStoreFromBlob(blob, store); if (ret) { if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; if (pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE; if (phCertStore) *phCertStore = CertDuplicateStore(store); } CertCloseStore(store, 0); TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType, const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg){ switch (dwObjectType) { case CERT_QUERY_OBJECT_FILE: return CRYPT_QuerySerializedStoreFromFile(pvObject, pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); case CERT_QUERY_OBJECT_BLOB: return CRYPT_QuerySerializedStoreFromBlob(pvObject, pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); default: FIXME("unimplemented for type %d\n", dwObjectType); SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ return FALSE; }}
static BOOL CRYPT_QuerySignedMessage(const CRYPT_DATA_BLOB *blob, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg){ DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; BOOL ret = FALSE; HCRYPTMSG msg;
if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL))) { ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); if (ret) { DWORD type, len = sizeof(type);
ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len); if (ret) { if (type != CMSG_SIGNED) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; } } } if (!ret) { CryptMsgClose(msg); msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); if (!ret) { CryptMsgClose(msg); msg = NULL; } } } } if (ret) { if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = encodingType; if (pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED; if (phMsg) *phMsg = msg; } return ret;}
static BOOL CRYPT_QueryUnsignedMessage(const CRYPT_DATA_BLOB *blob, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg){ DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; BOOL ret = FALSE; HCRYPTMSG msg;
if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL))) { ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); if (ret) { DWORD type, len = sizeof(type);
ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len); if (ret) { if (type != CMSG_DATA) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; } } } if (!ret) { CryptMsgClose(msg); msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); if (!ret) { CryptMsgClose(msg); msg = NULL; } } } } if (ret) { if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = encodingType; if (pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED; if (phMsg) *phMsg = msg; } return ret;}
/* Used to decode non-embedded messages */static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject, DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg){ CERT_BLOB fileBlob; const CERT_BLOB *blob; BOOL ret; HCRYPTMSG msg = NULL; DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; DWORD formatType = 0;
TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType, pvObject, dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore, phMsg);
switch (dwObjectType) { case CERT_QUERY_OBJECT_FILE: /* This isn't an embedded PKCS7 message, so just read the file * directly */ ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob); blob = &fileBlob; break; case CERT_QUERY_OBJECT_BLOB: blob = pvObject; ret = TRUE; break; default: SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ ret = FALSE; } if (!ret) return FALSE;
ret = FALSE; if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY) { /* Try it first as a signed message */ if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ret = CRYPT_QuerySignedMessage(blob, pdwMsgAndCertEncodingType, pdwContentType, &msg); /* Failing that, try as an unsigned message */ if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) ret = CRYPT_QueryUnsignedMessage(blob, pdwMsgAndCertEncodingType, pdwContentType, &msg); if (ret) formatType = CERT_QUERY_FORMAT_BINARY; } if (!ret && (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED)) { CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData }; CRYPT_DATA_BLOB decoded;
while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1]) trimmed.cbData--; ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData, CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL); if (ret) { decoded.pbData = CryptMemAlloc(decoded.cbData); if (decoded.pbData) { ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData, &decoded.cbData, NULL, NULL); if (ret) { /* Try it first as a signed message */ if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ret = CRYPT_QuerySignedMessage(&decoded, pdwMsgAndCertEncodingType, pdwContentType, &msg); /* Failing that, try as an unsigned message */ if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) ret = CRYPT_QueryUnsignedMessage(&decoded, pdwMsgAndCertEncodingType, pdwContentType, &msg); if (ret) formatType = CERT_QUERY_FORMAT_BASE64_ENCODED; } CryptMemFree(decoded.pbData); } else ret = FALSE; } if (!ret && !(blob->cbData % sizeof(WCHAR))) { CRYPT_DATA_BLOB decoded; LPWSTR str = (LPWSTR)blob->pbData; DWORD strLen = blob->cbData / sizeof(WCHAR);
/* Try again, assuming the input string is UTF-16 base64 */ while (strLen && !str[strLen - 1]) strLen--; ret = CryptStringToBinaryW(str, strLen, CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL); if (ret) { decoded.pbData = CryptMemAlloc(decoded.cbData); if (decoded.pbData) { ret = CryptStringToBinaryW(str, strLen, CRYPT_STRING_BASE64_ANY, decoded.pbData, &decoded.cbData, NULL, NULL); if (ret) { /* Try it first as a signed message */ if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ret = CRYPT_QuerySignedMessage(&decoded, pdwMsgAndCertEncodingType, pdwContentType, &msg); /* Failing that, try as an unsigned message */ if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) ret = CRYPT_QueryUnsignedMessage(&decoded, pdwMsgAndCertEncodingType, pdwContentType, &msg); if (ret) formatType = CERT_QUERY_FORMAT_BASE64_ENCODED; } CryptMemFree(decoded.pbData); } else ret = FALSE; } } } if (ret) { if (pdwFormatType) *pdwFormatType = formatType; if (phCertStore) *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0, 0, msg); if (phMsg) *phMsg = msg; else CryptMsgClose(msg); } if (blob == &fileBlob) CryptMemFree(blob->pbData); TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType, const void *pvObject, DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg){ HANDLE file; GUID subject; BOOL ret = FALSE;
TRACE("%s\n", debugstr_w(pvObject));
if (dwObjectType != CERT_QUERY_OBJECT_FILE) { WARN("don't know what to do for type %d embedded signed messages\n", dwObjectType); SetLastError(E_INVALIDARG); return FALSE; } file = CreateFileW(pvObject, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file != INVALID_HANDLE_VALUE) { ret = CryptSIPRetrieveSubjectGuid(pvObject, file, &subject); if (ret) { SIP_DISPATCH_INFO sip;
memset(&sip, 0, sizeof(sip)); sip.cbSize = sizeof(sip); ret = CryptSIPLoad(&subject, 0, &sip); if (ret) { SIP_SUBJECTINFO subjectInfo; CERT_BLOB blob; DWORD encodingType;
memset(&subjectInfo, 0, sizeof(subjectInfo)); subjectInfo.cbSize = sizeof(subjectInfo); subjectInfo.pgSubjectType = &subject; subjectInfo.hFile = file; subjectInfo.pwsFileName = pvObject; ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData, NULL); if (ret) { blob.pbData = CryptMemAlloc(blob.cbData); if (blob.pbData) { ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData, blob.pbData); if (ret) { ret = CRYPT_QueryMessageObject( CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED, CERT_QUERY_FORMAT_FLAG_BINARY, pdwMsgAndCertEncodingType, NULL, NULL, phCertStore, phMsg); if (ret && pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED; } CryptMemFree(blob.pbData); } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } } } CloseHandle(file); } TRACE("returning %d\n", ret); return ret;}
BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject, DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg, const void **ppvContext){ static const DWORD unimplementedTypes = CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX | CERT_QUERY_CONTENT_FLAG_CERT_PAIR; BOOL ret = TRUE;
TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n", dwObjectType, pvObject, dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext);
if (dwObjectType != CERT_QUERY_OBJECT_BLOB && dwObjectType != CERT_QUERY_OBJECT_FILE) { WARN("unsupported type %d\n", dwObjectType); SetLastError(E_INVALIDARG); return FALSE; } if (!pvObject) { WARN("missing required argument\n"); SetLastError(E_INVALIDARG); return FALSE; } if (dwExpectedContentTypeFlags & unimplementedTypes) WARN("unimplemented for types %08x\n", dwExpectedContentTypeFlags & unimplementedTypes);
if (pdwFormatType) *pdwFormatType = CERT_QUERY_FORMAT_BINARY; if (phCertStore) *phCertStore = NULL; if (phMsg) *phMsg = NULL; if (ppvContext) *ppvContext = NULL;
ret = FALSE; if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) || (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) || (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL)) { ret = CRYPT_QueryContextObject(dwObjectType, pvObject, dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore, ppvContext); } if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE)) { ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject, pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); } if (!ret && ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) || (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) || (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))) { ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject, dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, phCertStore, ppvContext); } if (!ret && ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) || (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))) { ret = CRYPT_QueryMessageObject(dwObjectType, pvObject, dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore, phMsg); } if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED)) { ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject, dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); } if (!ret) SetLastError(CRYPT_E_NO_MATCH); TRACE("returning %d\n", ret); return ret;}
static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ BOOL ret; DWORD bytesNeeded;
if (cbEncoded) bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR); else bytesNeeded = sizeof(WCHAR); if (!pbFormat) { *pcbFormat = bytesNeeded; ret = TRUE; } else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { static const WCHAR fmt[] = { '%','0','2','x',' ',0 }; static const WCHAR endFmt[] = { '%','0','2','x',0 }; DWORD i; LPWSTR ptr = pbFormat;
*pcbFormat = bytesNeeded; if (cbEncoded) { for (i = 0; i < cbEncoded; i++) { if (i < cbEncoded - 1) ptr += sprintfW(ptr, fmt, pbEncoded[i]); else ptr += sprintfW(ptr, endFmt, pbEncoded[i]); } } else *ptr = 0; ret = TRUE; } return ret;}
#define MAX_STRING_RESOURCE_LEN 128
static const WCHAR commaSpace[] = { ',',' ',0 };
struct BitToString{ BYTE bit; int id; WCHAR str[MAX_STRING_RESOURCE_LEN];};
static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map, DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first){ DWORD bytesNeeded = sizeof(WCHAR); unsigned int i; BOOL ret = TRUE, localFirst = *first;
for (i = 0; i < mapEntries; i++) if (bits & map[i].bit) { if (!localFirst) bytesNeeded += strlenW(commaSpace) * sizeof(WCHAR); localFirst = FALSE; bytesNeeded += strlenW(map[i].str) * sizeof(WCHAR); } if (!pbFormat) { *first = localFirst; *pcbFormat = bytesNeeded; } else if (*pcbFormat < bytesNeeded) { *first = localFirst; *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
localFirst = *first; *pcbFormat = bytesNeeded; for (i = 0; i < mapEntries; i++) if (bits & map[i].bit) { if (!localFirst) { strcpyW(str, commaSpace); str += strlenW(commaSpace); } localFirst = FALSE; strcpyW(str, map[i].str); str += strlenW(map[i].str); } *first = localFirst; } return ret;}
static struct BitToString keyUsageByte0Map[] = { { CERT_DIGITAL_SIGNATURE_KEY_USAGE, IDS_DIGITAL_SIGNATURE, { 0 } }, { CERT_NON_REPUDIATION_KEY_USAGE, IDS_NON_REPUDIATION, { 0 } }, { CERT_KEY_ENCIPHERMENT_KEY_USAGE, IDS_KEY_ENCIPHERMENT, { 0 } }, { CERT_DATA_ENCIPHERMENT_KEY_USAGE, IDS_DATA_ENCIPHERMENT, { 0 } }, { CERT_KEY_AGREEMENT_KEY_USAGE, IDS_KEY_AGREEMENT, { 0 } }, { CERT_KEY_CERT_SIGN_KEY_USAGE, IDS_CERT_SIGN, { 0 } }, { CERT_OFFLINE_CRL_SIGN_KEY_USAGE, IDS_OFFLINE_CRL_SIGN, { 0 } }, { CERT_CRL_SIGN_KEY_USAGE, IDS_CRL_SIGN, { 0 } }, { CERT_ENCIPHER_ONLY_KEY_USAGE, IDS_ENCIPHER_ONLY, { 0 } },};static struct BitToString keyUsageByte1Map[] = { { CERT_DECIPHER_ONLY_KEY_USAGE, IDS_DECIPHER_ONLY, { 0 } },};
static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ DWORD size; CRYPT_BIT_BLOB *bits; BOOL ret;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_KEY_USAGE, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size))) { WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN]; DWORD bytesNeeded = sizeof(WCHAR);
LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable)); if (!bits->cbData || bits->cbData > 2) { bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = bytesNeeded; strcpyW(str, infoNotAvailable); } } else { static BOOL stringsLoaded = FALSE; unsigned int i; DWORD bitStringLen; BOOL first = TRUE;
if (!stringsLoaded) { for (i = 0; i < ARRAY_SIZE(keyUsageByte0Map); i++) LoadStringW(hInstance, keyUsageByte0Map[i].id, keyUsageByte0Map[i].str, MAX_STRING_RESOURCE_LEN); for (i = 0; i < ARRAY_SIZE(keyUsageByte1Map); i++) LoadStringW(hInstance, keyUsageByte1Map[i].id, keyUsageByte1Map[i].str, MAX_STRING_RESOURCE_LEN); stringsLoaded = TRUE; } CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map, ARRAY_SIZE(keyUsageByte0Map), NULL, &bitStringLen, &first); bytesNeeded += bitStringLen; if (bits->cbData == 2) { CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map, ARRAY_SIZE(keyUsageByte1Map), NULL, &bitStringLen, &first); bytesNeeded += bitStringLen; } bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */ CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, bits->cbData, NULL, &size); bytesNeeded += size; if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
bitStringLen = bytesNeeded; first = TRUE; CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map, ARRAY_SIZE(keyUsageByte0Map), str, &bitStringLen, &first); str += bitStringLen / sizeof(WCHAR) - 1; if (bits->cbData == 2) { bitStringLen = bytesNeeded; CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map, ARRAY_SIZE(keyUsageByte1Map), str, &bitStringLen, &first); str += bitStringLen / sizeof(WCHAR) - 1; } *str++ = ' '; *str++ = '('; CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, bits->cbData, str, &size); str += size / sizeof(WCHAR) - 1; *str++ = ')'; *str = 0; } } LocalFree(bits); } return ret;}
static const WCHAR crlf[] = { '\r','\n',0 };
static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN];static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN];static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN];static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN];
static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ DWORD size; CERT_BASIC_CONSTRAINTS2_INFO *info; BOOL ret;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) { static const WCHAR pathFmt[] = { '%','d',0 }; static BOOL stringsLoaded = FALSE; DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */ WCHAR pathLength[MAX_STRING_RESOURCE_LEN]; LPCWSTR sep, subjectType; DWORD sepLen;
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { sep = crlf; sepLen = strlenW(crlf) * sizeof(WCHAR); } else { sep = commaSpace; sepLen = strlenW(commaSpace) * sizeof(WCHAR); }
if (!stringsLoaded) { LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader, ARRAY_SIZE(subjectTypeHeader)); LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA, ARRAY_SIZE(subjectTypeCA)); LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT, subjectTypeEndCert, ARRAY_SIZE(subjectTypeEndCert)); LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader, ARRAY_SIZE(pathLengthHeader)); stringsLoaded = TRUE; } bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR); if (info->fCA) subjectType = subjectTypeCA; else subjectType = subjectTypeEndCert; bytesNeeded += strlenW(subjectType) * sizeof(WCHAR); bytesNeeded += sepLen; bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR); if (info->fPathLenConstraint) sprintfW(pathLength, pathFmt, info->dwPathLenConstraint); else LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength, ARRAY_SIZE(pathLength)); bytesNeeded += strlenW(pathLength) * sizeof(WCHAR); if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = bytesNeeded; strcpyW(str, subjectTypeHeader); str += strlenW(subjectTypeHeader); strcpyW(str, subjectType); str += strlenW(subjectType); strcpyW(str, sep); str += sepLen / sizeof(WCHAR); strcpyW(str, pathLengthHeader); str += strlenW(pathLengthHeader); strcpyW(str, pathLength); } LocalFree(info); } return ret;}
static BOOL CRYPT_FormatHexStringWithPrefix(const CRYPT_DATA_BLOB *blob, int id, LPWSTR str, DWORD *pcbStr){ WCHAR buf[MAX_STRING_RESOURCE_LEN]; DWORD bytesNeeded; BOOL ret;
LoadStringW(hInstance, id, buf, ARRAY_SIZE(buf)); CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL, blob->pbData, blob->cbData, NULL, &bytesNeeded); bytesNeeded += strlenW(buf) * sizeof(WCHAR); if (!str) { *pcbStr = bytesNeeded; ret = TRUE; } else if (*pcbStr < bytesNeeded) { *pcbStr = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStr = bytesNeeded; strcpyW(str, buf); str += strlenW(str); bytesNeeded -= strlenW(str) * sizeof(WCHAR); ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL, blob->pbData, blob->cbData, str, &bytesNeeded); } return ret;}
static BOOL CRYPT_FormatKeyId(const CRYPT_DATA_BLOB *keyId, LPWSTR str, DWORD *pcbStr){ return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr);}
static BOOL CRYPT_FormatCertSerialNumber(const CRYPT_DATA_BLOB *serialNum, LPWSTR str, DWORD *pcbStr){ return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER, str, pcbStr);}
static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel, const CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr){ BOOL ret; WCHAR buf[MAX_STRING_RESOURCE_LEN]; WCHAR mask[MAX_STRING_RESOURCE_LEN]; WCHAR ipAddrBuf[32]; WCHAR maskBuf[16]; DWORD bytesNeeded = sizeof(WCHAR); DWORD strType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR); switch (entry->dwAltNameChoice) { case CERT_ALT_NAME_RFC822_NAME: LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf, ARRAY_SIZE(buf)); bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR); ret = TRUE; break; case CERT_ALT_NAME_DNS_NAME: LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf, ARRAY_SIZE(buf)); bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR); ret = TRUE; break; case CERT_ALT_NAME_DIRECTORY_NAME: { DWORD directoryNameLen;
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) strType |= CERT_NAME_STR_CRLF_FLAG; directoryNameLen = cert_name_to_str_with_indent(X509_ASN_ENCODING, indentLevel + 1, &entry->u.DirectoryName, strType, NULL, 0); LoadStringW(hInstance, IDS_ALT_NAME_DIRECTORY_NAME, buf, ARRAY_SIZE(buf)); bytesNeeded += (directoryNameLen - 1) * sizeof(WCHAR); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) bytesNeeded += strlenW(colonCrlf) * sizeof(WCHAR); else bytesNeeded += sizeof(WCHAR); /* '=' */ ret = TRUE; break; } case CERT_ALT_NAME_URL: LoadStringW(hInstance, IDS_ALT_NAME_URL, buf, ARRAY_SIZE(buf)); bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR); ret = TRUE; break; case CERT_ALT_NAME_IP_ADDRESS: { static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.', '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0 }; static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d', '.','%','d',0 };
LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf, ARRAY_SIZE(buf)); if (entry->u.IPAddress.cbData == 8) { if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask, ARRAY_SIZE(mask)); bytesNeeded += strlenW(mask) * sizeof(WCHAR); sprintfW(ipAddrBuf, ipAddrFmt, entry->u.IPAddress.pbData[0], entry->u.IPAddress.pbData[1], entry->u.IPAddress.pbData[2], entry->u.IPAddress.pbData[3]); bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR); /* indent again, for the mask line */ bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR); sprintfW(maskBuf, ipAddrFmt, entry->u.IPAddress.pbData[4], entry->u.IPAddress.pbData[5], entry->u.IPAddress.pbData[6], entry->u.IPAddress.pbData[7]); bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR); bytesNeeded += strlenW(crlf) * sizeof(WCHAR); } else { sprintfW(ipAddrBuf, ipAddrWithMaskFmt, entry->u.IPAddress.pbData[0], entry->u.IPAddress.pbData[1], entry->u.IPAddress.pbData[2], entry->u.IPAddress.pbData[3], entry->u.IPAddress.pbData[4], entry->u.IPAddress.pbData[5], entry->u.IPAddress.pbData[6], entry->u.IPAddress.pbData[7]); bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR); } ret = TRUE; } else { FIXME("unknown IP address format (%d bytes)\n", entry->u.IPAddress.cbData); ret = FALSE; } break; } default: FIXME("unimplemented for %d\n", entry->dwAltNameChoice); ret = FALSE; } if (ret) { bytesNeeded += strlenW(buf) * sizeof(WCHAR); if (!str) *pcbStr = bytesNeeded; else if (*pcbStr < bytesNeeded) { *pcbStr = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { DWORD i;
*pcbStr = bytesNeeded; if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { for (i = 0; i < indentLevel; i++) { strcpyW(str, indent); str += strlenW(indent); } } strcpyW(str, buf); str += strlenW(str); switch (entry->dwAltNameChoice) { case CERT_ALT_NAME_RFC822_NAME: case CERT_ALT_NAME_DNS_NAME: case CERT_ALT_NAME_URL: strcpyW(str, entry->u.pwszURL); break; case CERT_ALT_NAME_DIRECTORY_NAME: if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { strcpyW(str, colonCrlf); str += strlenW(colonCrlf); } else *str++ = '='; cert_name_to_str_with_indent(X509_ASN_ENCODING, indentLevel + 1, &entry->u.DirectoryName, strType, str, bytesNeeded / sizeof(WCHAR)); break; case CERT_ALT_NAME_IP_ADDRESS: if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { strcpyW(str, ipAddrBuf); str += strlenW(ipAddrBuf); strcpyW(str, crlf); str += strlenW(crlf); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { for (i = 0; i < indentLevel; i++) { strcpyW(str, indent); str += strlenW(indent); } } strcpyW(str, mask); str += strlenW(mask); strcpyW(str, maskBuf); } else strcpyW(str, ipAddrBuf); break; } } } return ret;}
static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel, const CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr){ DWORD i, size, bytesNeeded = 0; BOOL ret = TRUE; LPCWSTR sep; DWORD sepLen;
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { sep = crlf; sepLen = strlenW(crlf) * sizeof(WCHAR); } else { sep = commaSpace; sepLen = strlenW(commaSpace) * sizeof(WCHAR); }
for (i = 0; ret && i < name->cAltEntry; i++) { ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel, &name->rgAltEntry[i], NULL, &size); if (ret) { bytesNeeded += size - sizeof(WCHAR); if (i < name->cAltEntry - 1) bytesNeeded += sepLen; } } if (ret) { bytesNeeded += sizeof(WCHAR); if (!str) *pcbStr = bytesNeeded; else if (*pcbStr < bytesNeeded) { *pcbStr = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStr = bytesNeeded; for (i = 0; ret && i < name->cAltEntry; i++) { ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel, &name->rgAltEntry[i], str, &size); if (ret) { str += size / sizeof(WCHAR) - 1; if (i < name->cAltEntry - 1) { strcpyW(str, sep); str += sepLen / sizeof(WCHAR); } } } } } return ret;}
static const WCHAR colonSep[] = { ':',' ',0 };
static BOOL WINAPI CRYPT_FormatAltName(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ BOOL ret; CERT_ALT_NAME_INFO *info; DWORD size;
if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ALTERNATE_NAME, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) { ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, info, pbFormat, pcbFormat); LocalFree(info); } return ret;}
static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType, const CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr){ WCHAR buf[MAX_STRING_RESOURCE_LEN]; DWORD bytesNeeded, sepLen; LPCWSTR sep; BOOL ret;
LoadStringW(hInstance, IDS_CERT_ISSUER, buf, ARRAY_SIZE(buf)); ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, NULL, &bytesNeeded); bytesNeeded += strlenW(buf) * sizeof(WCHAR); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { sep = colonCrlf; sepLen = strlenW(colonCrlf) * sizeof(WCHAR); } else { sep = colonSep; sepLen = strlenW(colonSep) * sizeof(WCHAR); } bytesNeeded += sepLen; if (ret) { if (!str) *pcbStr = bytesNeeded; else if (*pcbStr < bytesNeeded) { *pcbStr = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStr = bytesNeeded; strcpyW(str, buf); bytesNeeded -= strlenW(str) * sizeof(WCHAR); str += strlenW(str); strcpyW(str, sep); str += sepLen / sizeof(WCHAR); ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, str, &bytesNeeded); } } return ret;}
static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ CERT_AUTHORITY_KEY_ID2_INFO *info; DWORD size; BOOL ret = FALSE;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) { DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */ LPCWSTR sep; DWORD sepLen; BOOL needSeparator = FALSE;
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { sep = crlf; sepLen = strlenW(crlf) * sizeof(WCHAR); } else { sep = commaSpace; sepLen = strlenW(commaSpace) * sizeof(WCHAR); }
if (info->KeyId.cbData) { needSeparator = TRUE; ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size); if (ret) { /* don't include NULL-terminator more than once */ bytesNeeded += size - sizeof(WCHAR); } } if (info->AuthorityCertIssuer.cAltEntry) { if (needSeparator) bytesNeeded += sepLen; needSeparator = TRUE; ret = CRYPT_FormatCertIssuer(dwFormatStrType, &info->AuthorityCertIssuer, NULL, &size); if (ret) { /* don't include NULL-terminator more than once */ bytesNeeded += size - sizeof(WCHAR); } } if (info->AuthorityCertSerialNumber.cbData) { if (needSeparator) bytesNeeded += sepLen; ret = CRYPT_FormatCertSerialNumber( &info->AuthorityCertSerialNumber, NULL, &size); if (ret) { /* don't include NULL-terminator more than once */ bytesNeeded += size - sizeof(WCHAR); } } if (ret) { if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = bytesNeeded; needSeparator = FALSE; if (info->KeyId.cbData) { needSeparator = TRUE; /* Overestimate size available, it's already been checked * above. */ size = bytesNeeded; ret = CRYPT_FormatKeyId(&info->KeyId, str, &size); if (ret) str += size / sizeof(WCHAR) - 1; } if (info->AuthorityCertIssuer.cAltEntry) { if (needSeparator) { strcpyW(str, sep); str += sepLen / sizeof(WCHAR); } needSeparator = TRUE; /* Overestimate size available, it's already been checked * above. */ size = bytesNeeded; ret = CRYPT_FormatCertIssuer(dwFormatStrType, &info->AuthorityCertIssuer, str, &size); if (ret) str += size / sizeof(WCHAR) - 1; } if (info->AuthorityCertSerialNumber.cbData) { if (needSeparator) { strcpyW(str, sep); str += sepLen / sizeof(WCHAR); } /* Overestimate size available, it's already been checked * above. */ size = bytesNeeded; ret = CRYPT_FormatCertSerialNumber( &info->AuthorityCertSerialNumber, str, &size); } } } LocalFree(info); } return ret;}
static WCHAR aia[MAX_STRING_RESOURCE_LEN];static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN];static WCHAR ocsp[MAX_STRING_RESOURCE_LEN];static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN];static WCHAR unknown[MAX_STRING_RESOURCE_LEN];static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN];
static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ CERT_AUTHORITY_INFO_ACCESS *info; DWORD size; BOOL ret = FALSE;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) { DWORD bytesNeeded = sizeof(WCHAR);
if (!info->cAccDescr) { WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable)); bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbFormat = bytesNeeded; strcpyW(pbFormat, infoNotAvailable); } } else { static const WCHAR numFmt[] = { '%','d',0 }; static const WCHAR equal[] = { '=',0 }; static BOOL stringsLoaded = FALSE; DWORD i; LPCWSTR headingSep, accessMethodSep, locationSep; WCHAR accessDescrNum[11];
if (!stringsLoaded) { LoadStringW(hInstance, IDS_AIA, aia, ARRAY_SIZE(aia)); LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod, ARRAY_SIZE(accessMethod)); LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp, ARRAY_SIZE(ocsp)); LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers, ARRAY_SIZE(caIssuers)); LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown, ARRAY_SIZE(unknown)); LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation, ARRAY_SIZE(accessLocation)); stringsLoaded = TRUE; } if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { headingSep = crlf; accessMethodSep = crlf; locationSep = colonCrlf; } else { headingSep = colonSep; accessMethodSep = commaSpace; locationSep = equal; }
for (i = 0; ret && i < info->cAccDescr; i++) { /* Heading */ bytesNeeded += sizeof(WCHAR); /* left bracket */ sprintfW(accessDescrNum, numFmt, i + 1); bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR); bytesNeeded += sizeof(WCHAR); /* right bracket */ bytesNeeded += strlenW(aia) * sizeof(WCHAR); bytesNeeded += strlenW(headingSep) * sizeof(WCHAR); /* Access method */ bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) bytesNeeded += strlenW(indent) * sizeof(WCHAR); if (!strcmp(info->rgAccDescr[i].pszAccessMethod, szOID_PKIX_OCSP)) bytesNeeded += strlenW(ocsp) * sizeof(WCHAR); else if (!strcmp(info->rgAccDescr[i].pszAccessMethod, szOID_PKIX_CA_ISSUERS)) bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers); else bytesNeeded += strlenW(unknown) * sizeof(WCHAR); bytesNeeded += sizeof(WCHAR); /* space */ bytesNeeded += sizeof(WCHAR); /* left paren */ bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod) * sizeof(WCHAR); bytesNeeded += sizeof(WCHAR); /* right paren */ /* Delimiter between access method and location */ bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) bytesNeeded += strlenW(indent) * sizeof(WCHAR); bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR); bytesNeeded += strlenW(locationSep) * sizeof(WCHAR); ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2, &info->rgAccDescr[i].AccessLocation, NULL, &size); if (ret) bytesNeeded += size - sizeof(WCHAR); /* Need extra delimiter between access method entries */ if (i < info->cAccDescr - 1) bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR); } if (ret) { if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat; DWORD altNameEntrySize;
*pcbFormat = bytesNeeded; for (i = 0; ret && i < info->cAccDescr; i++) { LPCSTR oidPtr;
*str++ = '['; sprintfW(accessDescrNum, numFmt, i + 1); strcpyW(str, accessDescrNum); str += strlenW(accessDescrNum); *str++ = ']'; strcpyW(str, aia); str += strlenW(aia); strcpyW(str, headingSep); str += strlenW(headingSep); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { strcpyW(str, indent); str += strlenW(indent); } strcpyW(str, accessMethod); str += strlenW(accessMethod); if (!strcmp(info->rgAccDescr[i].pszAccessMethod, szOID_PKIX_OCSP)) { strcpyW(str, ocsp); str += strlenW(ocsp); } else if (!strcmp(info->rgAccDescr[i].pszAccessMethod, szOID_PKIX_CA_ISSUERS)) { strcpyW(str, caIssuers); str += strlenW(caIssuers); } else { strcpyW(str, unknown); str += strlenW(unknown); } *str++ = ' '; *str++ = '('; for (oidPtr = info->rgAccDescr[i].pszAccessMethod; *oidPtr; oidPtr++, str++) *str = *oidPtr; *str++ = ')'; strcpyW(str, accessMethodSep); str += strlenW(accessMethodSep); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { strcpyW(str, indent); str += strlenW(indent); } strcpyW(str, accessLocation); str += strlenW(accessLocation); strcpyW(str, locationSep); str += strlenW(locationSep); /* This overestimates the size available, but that * won't matter since we checked earlier whether enough * space for the entire string was available. */ altNameEntrySize = bytesNeeded; ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2, &info->rgAccDescr[i].AccessLocation, str, &altNameEntrySize); if (ret) str += altNameEntrySize / sizeof(WCHAR) - 1; if (i < info->cAccDescr - 1) { strcpyW(str, accessMethodSep); str += strlenW(accessMethodSep); } } } } } LocalFree(info); } return ret;}
static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN];static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN];static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN];static WCHAR superseded[MAX_STRING_RESOURCE_LEN];static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN];static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN];
struct reason_map_entry{ BYTE reasonBit; LPWSTR reason; int id;};static struct reason_map_entry reason_map[] = { { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE }, { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE }, { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged, IDS_REASON_AFFILIATION_CHANGED }, { CRL_REASON_SUPERSEDED_FLAG, superseded, IDS_REASON_SUPERSEDED }, { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased, IDS_REASON_CESSATION_OF_OPERATION }, { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold, IDS_REASON_CERTIFICATE_HOLD },};
static BOOL CRYPT_FormatReason(DWORD dwFormatStrType, const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr){ static const WCHAR sep[] = { ',',' ',0 }; static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 }; static BOOL stringsLoaded = FALSE; unsigned int i, numReasons = 0; BOOL ret = TRUE; DWORD bytesNeeded = sizeof(WCHAR); WCHAR bits[6];
if (!stringsLoaded) { for (i = 0; i < ARRAY_SIZE(reason_map); i++) LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason, MAX_STRING_RESOURCE_LEN); stringsLoaded = TRUE; } /* No need to check reasonFlags->cbData, we already know it's positive. * Ignore any other bytes, as they're for undefined bits. */ for (i = 0; i < ARRAY_SIZE(reason_map); i++) { if (reasonFlags->pbData[0] & reason_map[i].reasonBit) { bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR); if (numReasons++) bytesNeeded += strlenW(sep) * sizeof(WCHAR); } } sprintfW(bits, bitsFmt, reasonFlags->pbData[0]); bytesNeeded += strlenW(bits); if (!str) *pcbStr = bytesNeeded; else if (*pcbStr < bytesNeeded) { *pcbStr = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStr = bytesNeeded; for (i = 0; i < ARRAY_SIZE(reason_map); i++) { if (reasonFlags->pbData[0] & reason_map[i].reasonBit) { strcpyW(str, reason_map[i].reason); str += strlenW(reason_map[i].reason); if (i < ARRAY_SIZE(reason_map) - 1 && numReasons) { strcpyW(str, sep); str += strlenW(sep); } } } strcpyW(str, bits); } return ret;}
static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN];static WCHAR distPointName[MAX_STRING_RESOURCE_LEN];static WCHAR fullName[MAX_STRING_RESOURCE_LEN];static WCHAR rdnName[MAX_STRING_RESOURCE_LEN];static WCHAR reason[MAX_STRING_RESOURCE_LEN];static WCHAR issuer[MAX_STRING_RESOURCE_LEN];
static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ CRL_DIST_POINTS_INFO *info; DWORD size; BOOL ret = FALSE;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) { static const WCHAR numFmt[] = { '%','d',0 }; static const WCHAR colon[] = { ':',0 }; static BOOL stringsLoaded = FALSE; DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */ BOOL haveAnEntry = FALSE; LPCWSTR headingSep, nameSep; WCHAR distPointNum[11]; DWORD i;
if (!stringsLoaded) { LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint, ARRAY_SIZE(crlDistPoint)); LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName, ARRAY_SIZE(distPointName)); LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName, ARRAY_SIZE(fullName)); LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName, ARRAY_SIZE(rdnName)); LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason, ARRAY_SIZE(reason)); LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer, ARRAY_SIZE(issuer)); stringsLoaded = TRUE; } if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { headingSep = crlf; nameSep = colonCrlf; } else { headingSep = colonSep; nameSep = colon; }
for (i = 0; ret && i < info->cDistPoint; i++) { CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
if (distPoint->DistPointName.dwDistPointNameChoice != CRL_DIST_POINT_NO_NAME) { bytesNeeded += strlenW(distPointName) * sizeof(WCHAR); bytesNeeded += strlenW(nameSep) * sizeof(WCHAR); if (distPoint->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME) bytesNeeded += strlenW(fullName) * sizeof(WCHAR); else bytesNeeded += strlenW(rdnName) * sizeof(WCHAR); bytesNeeded += strlenW(nameSep) * sizeof(WCHAR); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) bytesNeeded += 2 * strlenW(indent) * sizeof(WCHAR); /* The indent level (3) is higher than when used as the issuer, * because the name is subordinate to the name type (full vs. * RDN.) */ ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3, &distPoint->DistPointName.u.FullName, NULL, &size); if (ret) bytesNeeded += size - sizeof(WCHAR); haveAnEntry = TRUE; } else if (distPoint->ReasonFlags.cbData) { bytesNeeded += strlenW(reason) * sizeof(WCHAR); ret = CRYPT_FormatReason(dwFormatStrType, &distPoint->ReasonFlags, NULL, &size); if (ret) bytesNeeded += size - sizeof(WCHAR); haveAnEntry = TRUE; } else if (distPoint->CRLIssuer.cAltEntry) { bytesNeeded += strlenW(issuer) * sizeof(WCHAR); bytesNeeded += strlenW(nameSep) * sizeof(WCHAR); ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2, &distPoint->CRLIssuer, NULL, &size); if (ret) bytesNeeded += size - sizeof(WCHAR); haveAnEntry = TRUE; } if (haveAnEntry) { bytesNeeded += sizeof(WCHAR); /* left bracket */ sprintfW(distPointNum, numFmt, i + 1); bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR); bytesNeeded += sizeof(WCHAR); /* right bracket */ bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR); bytesNeeded += strlenW(headingSep) * sizeof(WCHAR); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) bytesNeeded += strlenW(indent) * sizeof(WCHAR); } } if (!haveAnEntry) { WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable)); bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbFormat = bytesNeeded; strcpyW(pbFormat, infoNotAvailable); } } else { if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = bytesNeeded; for (i = 0; ret && i < info->cDistPoint; i++) { CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
*str++ = '['; sprintfW(distPointNum, numFmt, i + 1); strcpyW(str, distPointNum); str += strlenW(distPointNum); *str++ = ']'; strcpyW(str, crlDistPoint); str += strlenW(crlDistPoint); strcpyW(str, headingSep); str += strlenW(headingSep); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { strcpyW(str, indent); str += strlenW(indent); } if (distPoint->DistPointName.dwDistPointNameChoice != CRL_DIST_POINT_NO_NAME) { DWORD altNameSize = bytesNeeded;
strcpyW(str, distPointName); str += strlenW(distPointName); strcpyW(str, nameSep); str += strlenW(nameSep); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } if (distPoint->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME) { strcpyW(str, fullName); str += strlenW(fullName); } else { strcpyW(str, rdnName); str += strlenW(rdnName); } strcpyW(str, nameSep); str += strlenW(nameSep); ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3, &distPoint->DistPointName.u.FullName, str, &altNameSize); if (ret) str += altNameSize / sizeof(WCHAR) - 1; } else if (distPoint->ReasonFlags.cbData) { DWORD reasonSize = bytesNeeded;
strcpyW(str, reason); str += strlenW(reason); ret = CRYPT_FormatReason(dwFormatStrType, &distPoint->ReasonFlags, str, &reasonSize); if (ret) str += reasonSize / sizeof(WCHAR) - 1; } else if (distPoint->CRLIssuer.cAltEntry) { DWORD crlIssuerSize = bytesNeeded;
strcpyW(str, issuer); str += strlenW(issuer); strcpyW(str, nameSep); str += strlenW(nameSep); ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2, &distPoint->CRLIssuer, str, &crlIssuerSize); if (ret) str += crlIssuerSize / sizeof(WCHAR) - 1; } } } } LocalFree(info); } return ret;}
static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ CERT_ENHKEY_USAGE *usage; DWORD size; BOOL ret = FALSE;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size))) { WCHAR unknown[MAX_STRING_RESOURCE_LEN]; DWORD i; DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */ LPCWSTR sep; DWORD sepLen;
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { sep = crlf; sepLen = strlenW(crlf) * sizeof(WCHAR); } else { sep = commaSpace; sepLen = strlenW(commaSpace) * sizeof(WCHAR); }
LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown, ARRAY_SIZE(unknown)); for (i = 0; i < usage->cUsageIdentifier; i++) { PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
if (info) bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR); else bytesNeeded += strlenW(unknown) * sizeof(WCHAR); bytesNeeded += sizeof(WCHAR); /* space */ bytesNeeded += sizeof(WCHAR); /* left paren */ bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) * sizeof(WCHAR); bytesNeeded += sizeof(WCHAR); /* right paren */ if (i < usage->cUsageIdentifier - 1) bytesNeeded += sepLen; } if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = bytesNeeded; for (i = 0; i < usage->cUsageIdentifier; i++) { PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID); LPCSTR oidPtr;
if (info) { strcpyW(str, info->pwszName); str += strlenW(info->pwszName); } else { strcpyW(str, unknown); str += strlenW(unknown); } *str++ = ' '; *str++ = '('; for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++) *str++ = *oidPtr; *str++ = ')'; *str = 0; if (i < usage->cUsageIdentifier - 1) { strcpyW(str, sep); str += sepLen / sizeof(WCHAR); } } } LocalFree(usage); } return ret;}
static struct BitToString netscapeCertTypeMap[] = { { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_CLIENT, { 0 } }, { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_SERVER, { 0 } }, { NETSCAPE_SMIME_CERT_TYPE, IDS_NETSCAPE_SMIME, { 0 } }, { NETSCAPE_SIGN_CERT_TYPE, IDS_NETSCAPE_SIGN, { 0 } }, { NETSCAPE_SSL_CA_CERT_TYPE, IDS_NETSCAPE_SSL_CA, { 0 } }, { NETSCAPE_SMIME_CA_CERT_TYPE, IDS_NETSCAPE_SMIME_CA, { 0 } }, { NETSCAPE_SIGN_CA_CERT_TYPE, IDS_NETSCAPE_SIGN_CA, { 0 } },};
static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ DWORD size; CRYPT_BIT_BLOB *bits; BOOL ret;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size))) { WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN]; DWORD bytesNeeded = sizeof(WCHAR);
LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable)); if (!bits->cbData || bits->cbData > 1) { bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = bytesNeeded; strcpyW(str, infoNotAvailable); } } else { static BOOL stringsLoaded = FALSE; unsigned int i; DWORD bitStringLen; BOOL first = TRUE;
if (!stringsLoaded) { for (i = 0; i < ARRAY_SIZE(netscapeCertTypeMap); i++) LoadStringW(hInstance, netscapeCertTypeMap[i].id, netscapeCertTypeMap[i].str, MAX_STRING_RESOURCE_LEN); stringsLoaded = TRUE; } CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap, ARRAY_SIZE(netscapeCertTypeMap), NULL, &bitStringLen, &first); bytesNeeded += bitStringLen; bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */ CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, bits->cbData, NULL, &size); bytesNeeded += size; if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
bitStringLen = bytesNeeded; first = TRUE; CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap, ARRAY_SIZE(netscapeCertTypeMap), str, &bitStringLen, &first); str += bitStringLen / sizeof(WCHAR) - 1; *str++ = ' '; *str++ = '('; CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, bits->cbData, str, &size); str += size / sizeof(WCHAR) - 1; *str++ = ')'; *str = 0; } } LocalFree(bits); } return ret;}
static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN];static WCHAR available[MAX_STRING_RESOURCE_LEN];static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN];static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN];static WCHAR yes[MAX_STRING_RESOURCE_LEN];static WCHAR no[MAX_STRING_RESOURCE_LEN];
static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ SPC_FINANCIAL_CRITERIA criteria; DWORD size = sizeof(criteria); BOOL ret = FALSE;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria, &size))) { static BOOL stringsLoaded = FALSE; DWORD bytesNeeded = sizeof(WCHAR); LPCWSTR sep; DWORD sepLen;
if (!stringsLoaded) { LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria, ARRAY_SIZE(financialCriteria)); LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available, ARRAY_SIZE(available)); LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE, notAvailable, ARRAY_SIZE(notAvailable)); LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA, meetsCriteria, ARRAY_SIZE(meetsCriteria)); LoadStringW(hInstance, IDS_YES, yes, ARRAY_SIZE(yes)); LoadStringW(hInstance, IDS_NO, no, ARRAY_SIZE(no)); stringsLoaded = TRUE; } if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { sep = crlf; sepLen = strlenW(crlf) * sizeof(WCHAR); } else { sep = commaSpace; sepLen = strlenW(commaSpace) * sizeof(WCHAR); } bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR); if (criteria.fFinancialInfoAvailable) { bytesNeeded += strlenW(available) * sizeof(WCHAR); bytesNeeded += sepLen; bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR); if (criteria.fMeetsCriteria) bytesNeeded += strlenW(yes) * sizeof(WCHAR); else bytesNeeded += strlenW(no) * sizeof(WCHAR); } else bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR); if (!pbFormat) *pcbFormat = bytesNeeded; else if (*pcbFormat < bytesNeeded) { *pcbFormat = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = bytesNeeded; strcpyW(str, financialCriteria); str += strlenW(financialCriteria); if (criteria.fFinancialInfoAvailable) { strcpyW(str, available); str += strlenW(available); strcpyW(str, sep); str += sepLen / sizeof(WCHAR); strcpyW(str, meetsCriteria); str += strlenW(meetsCriteria); if (criteria.fMeetsCriteria) strcpyW(str, yes); else strcpyW(str, no); } else { strcpyW(str, notAvailable); } } } return ret;}
static BOOL WINAPI CRYPT_FormatUnicodeString(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ CERT_NAME_VALUE *value; DWORD size; BOOL ret;
if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &value, &size))) { if (!pbFormat) *pcbFormat = value->Value.cbData; else if (*pcbFormat < value->Value.cbData) { *pcbFormat = value->Value.cbData; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR str = pbFormat;
*pcbFormat = value->Value.cbData; strcpyW(str, (LPWSTR)value->Value.pbData); } } return ret;}
typedef BOOL (WINAPI *CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *, LPCSTR, const BYTE *, DWORD, void *, DWORD *);
static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType, DWORD formatStrType, LPCSTR lpszStructType){ CryptFormatObjectFunc format = NULL;
if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) { SetLastError(ERROR_FILE_NOT_FOUND); return NULL; } if (IS_INTOID(lpszStructType)) { switch (LOWORD(lpszStructType)) { case LOWORD(X509_KEY_USAGE): format = CRYPT_FormatKeyUsage; break; case LOWORD(X509_ALTERNATE_NAME): format = CRYPT_FormatAltName; break; case LOWORD(X509_BASIC_CONSTRAINTS2): format = CRYPT_FormatBasicConstraints2; break; case LOWORD(X509_AUTHORITY_KEY_ID2): format = CRYPT_FormatAuthorityKeyId2; break; case LOWORD(X509_AUTHORITY_INFO_ACCESS): format = CRYPT_FormatAuthorityInfoAccess; break; case LOWORD(X509_CRL_DIST_POINTS): format = CRYPT_FormatCRLDistPoints; break; case LOWORD(X509_ENHANCED_KEY_USAGE): format = CRYPT_FormatEnhancedKeyUsage; break; case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT): format = CRYPT_FormatSpcFinancialCriteria; break; } } else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) format = CRYPT_FormatAltName; else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) format = CRYPT_FormatAltName; else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) format = CRYPT_FormatKeyUsage; else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) format = CRYPT_FormatAltName; else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) format = CRYPT_FormatAltName; else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) format = CRYPT_FormatBasicConstraints2; else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS)) format = CRYPT_FormatAuthorityInfoAccess; else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2)) format = CRYPT_FormatAuthorityKeyId2; else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS)) format = CRYPT_FormatCRLDistPoints; else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE)) format = CRYPT_FormatEnhancedKeyUsage; else if (!strcmp(lpszStructType, szOID_NETSCAPE_CERT_TYPE)) format = CRYPT_FormatNetscapeCertType; else if (!strcmp(lpszStructType, szOID_NETSCAPE_BASE_URL) || !strcmp(lpszStructType, szOID_NETSCAPE_REVOCATION_URL) || !strcmp(lpszStructType, szOID_NETSCAPE_CA_REVOCATION_URL) || !strcmp(lpszStructType, szOID_NETSCAPE_CERT_RENEWAL_URL) || !strcmp(lpszStructType, szOID_NETSCAPE_CA_POLICY_URL) || !strcmp(lpszStructType, szOID_NETSCAPE_SSL_SERVER_NAME) || !strcmp(lpszStructType, szOID_NETSCAPE_COMMENT)) format = CRYPT_FormatUnicodeString; else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID)) format = CRYPT_FormatSpcFinancialCriteria; return format;}
BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat){ CryptFormatObjectFunc format = NULL; HCRYPTOIDFUNCADDR hFunc = NULL; BOOL ret = FALSE;
TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType, dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType), pbEncoded, cbEncoded, pbFormat, pcbFormat);
if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType, dwFormatStrType, lpszStructType))) { static HCRYPTOIDFUNCSET set = NULL;
if (!set) set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0); CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, (void **)&format, &hFunc); } if (!format && (dwCertEncodingType & CERT_ENCODING_TYPE_MASK) == X509_ASN_ENCODING && !(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX)) format = CRYPT_FormatHexString; if (format) ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType, pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat, pcbFormat); if (hFunc) CryptFreeOIDFunctionAddress(hFunc, 0); return ret;}