Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413/* * Copyright 2005-2009 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 * * This file implements ASN.1 DER decoding of a limited set of types. * It isn't a full ASN.1 implementation. Microsoft implements BER * encoding of many of the basic types in msasn1.dll, but that interface isn't * implemented, so I implement them here. * * References: * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski * (available online, look for a PDF copy as the HTML versions tend to have * translation errors.) * * RFC3280, http://www.faqs.org/rfcs/rfc3280.html * * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject" */
#include "config.h"#include "wine/port.h"
#include <assert.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>
#define NONAMELESSUNION
#include "windef.h"#include "winbase.h"#include "wincrypt.h"#include "winnls.h"#include "snmp.h"#include "wine/debug.h"#include "wine/exception.h"#include "crypt32_private.h"
/* This is a bit arbitrary, but to set some limit: */#define MAX_ENCODED_LEN 0x02000000
#define ASN_FLAGS_MASK 0xe0#define ASN_TYPE_MASK 0x1f
WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);WINE_DECLARE_DEBUG_CHANNEL(crypt);
typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *, DWORD, DWORD, void *, DWORD *);typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *, DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
/* Internal decoders don't do memory allocation or exception handling, and * they report how many bytes they decoded. */typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);/* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time. */static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);/* Assumes algo->Parameters.pbData is set ahead of time. */static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);/* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);/* Doesn't check the tag, assumes the caller does so */static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);/* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData * member has been initialized, doesn't do exception handling, and doesn't do * memory allocation. Also doesn't check tag, assumes the caller has checked * it. */static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);/* Like CRYPT_AsnDecodeInteger, but unsigned. */static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
/* Gets the number of length bytes from the given (leading) length byte */#define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
/* Helper function to get the encoded length of the data starting at pbEncoded, * where pbEncoded[0] is the tag. If the data are too short to contain a * length or if the length is too large for cbEncoded, sets an appropriate * error code and returns FALSE. If the encoded length is unknown due to * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH. */static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len){ BOOL ret;
if (cbEncoded <= 1) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else if (pbEncoded[1] <= 0x7f) { if (pbEncoded[1] + 1 > cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); ret = FALSE; } else { *len = pbEncoded[1]; ret = TRUE; } } else if (pbEncoded[1] == 0x80) { *len = CMSG_INDEFINITE_LENGTH; ret = TRUE; } else { BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
if (lenLen > sizeof(DWORD) + 1) { SetLastError(CRYPT_E_ASN1_LARGE); ret = FALSE; } else if (lenLen + 2 > cbEncoded) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else { DWORD out = 0;
pbEncoded += 2; while (--lenLen) { out <<= 8; out |= *pbEncoded++; } if (out + lenLen + 1 > cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); ret = FALSE; } else { *len = out; ret = TRUE; } } } return ret;}
/* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len){ BOOL ret;
if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) && *len == CMSG_INDEFINITE_LENGTH) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } return ret;}
/* Helper function to check *pcbStructInfo, set it to the required size, and * optionally to allocate memory. Assumes pvStructInfo is not NULL. * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a * pointer to the newly allocated memory. */static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags, const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo, DWORD bytesNeeded){ BOOL ret = TRUE;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) { if (pDecodePara && pDecodePara->pfnAlloc) *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded); else *(BYTE **)pvStructInfo = LocalAlloc(LPTR, bytesNeeded); if (!*(BYTE **)pvStructInfo) ret = FALSE; else *pcbStructInfo = bytesNeeded; } else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else *pcbStructInfo = bytesNeeded; return ret;}
static void CRYPT_FreeSpace(const CRYPT_DECODE_PARA *pDecodePara, LPVOID pv){ if (pDecodePara && pDecodePara->pfnFree) pDecodePara->pfnFree(pv); else LocalFree(pv);}
/* Helper function to check *pcbStructInfo and set it to the required size. * Assumes pvStructInfo is not NULL. */static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded){ BOOL ret;
if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStructInfo = bytesNeeded; ret = TRUE; } return ret;}
/* tag: * The expected tag of the item. If tag is 0, decodeFunc is called * regardless of the tag value seen. * offset: * A sequence is decoded into a struct. The offset member is the * offset of this item within that struct. * decodeFunc: * The decoder function to use. If this is NULL, then the member isn't * decoded, but minSize space is reserved for it. * minSize: * The minimum amount of space occupied after decoding. You must set this. * optional: * If true, and the tag doesn't match the expected tag for this item, * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is * filled with 0 for this member. * hasPointer, pointerOffset: * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to * the offset within the struct of the data pointer (or to the * first data pointer, if more than one exist). * size: * Used by CRYPT_AsnDecodeSequence, not for your use. */struct AsnDecodeSequenceItem{ BYTE tag; DWORD offset; InternalDecodeFunc decodeFunc; DWORD minSize; BOOL optional; BOOL hasPointer; DWORD pointerOffset; DWORD size;};
#define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))#define MEMBERSIZE(s, member, nextmember) \ (offsetof(s, nextmember) - offsetof(s, member))
/* Decodes the items in a sequence, where the items are described in items, * the encoded data are in pbEncoded with length cbEncoded. Decodes into * pvStructInfo. nextData is a pointer to the memory location at which the * first decoded item with a dynamic pointer should point. * Upon decoding, *cbDecoded is the total number of bytes decoded. * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set. */static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded){ BOOL ret; DWORD i, decoded = 0; const BYTE *ptr = pbEncoded;
TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
for (i = 0, ret = TRUE; ret && i < cItem; i++) { if (cbEncoded - (ptr - pbEncoded) != 0) { DWORD itemLen;
if ((ret = CRYPT_GetLengthIndefinite(ptr, cbEncoded - (ptr - pbEncoded), &itemLen))) { BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
if (ptr[0] == items[i].tag || !items[i].tag) { DWORD itemEncodedLen;
if (itemLen == CMSG_INDEFINITE_LENGTH) itemEncodedLen = cbEncoded - (ptr - pbEncoded); else itemEncodedLen = 1 + itemLenBytes + itemLen; if (nextData && pvStructInfo && items[i].hasPointer) { TRACE("Setting next pointer to %p\n", nextData); *(BYTE **)((BYTE *)pvStructInfo + items[i].pointerOffset) = nextData; } if (items[i].decodeFunc) { DWORD itemDecoded;
if (pvStructInfo) TRACE("decoding item %d\n", i); else TRACE("sizing item %d\n", i); ret = items[i].decodeFunc(ptr, itemEncodedLen, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset : NULL, &items[i].size, &itemDecoded); if (ret) { if (items[i].size < items[i].minSize) items[i].size = items[i].minSize; else if (items[i].size > items[i].minSize) { /* Account for alignment padding */ items[i].size = ALIGN_DWORD_PTR(items[i].size); } TRACE("item %d size: %d\n", i, items[i].size); if (nextData && items[i].hasPointer && items[i].size > items[i].minSize) nextData += items[i].size - items[i].minSize; if (itemDecoded > itemEncodedLen) { WARN("decoded length %d exceeds encoded %d\n", itemDecoded, itemEncodedLen); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else { ptr += itemDecoded; decoded += itemDecoded; TRACE("item %d: decoded %d bytes\n", i, itemDecoded); } } else if (items[i].optional && GetLastError() == CRYPT_E_ASN1_BADTAG) { TRACE("skipping optional item %d\n", i); items[i].size = items[i].minSize; SetLastError(NOERROR); ret = TRUE; } else TRACE("item %d failed: %08x\n", i, GetLastError()); } else if (itemLen == CMSG_INDEFINITE_LENGTH) { ERR("can't use indefinite length encoding without a decoder\n"); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else { TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen); ptr += itemEncodedLen; decoded += itemEncodedLen; items[i].size = items[i].minSize; } } else if (items[i].optional) { TRACE("skipping optional item %d\n", i); items[i].size = items[i].minSize; } else { TRACE("item %d: tag %02x doesn't match expected %02x\n", i, ptr[0], items[i].tag); SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } } } else if (items[i].optional) { TRACE("missing optional item %d, skipping\n", i); items[i].size = items[i].minSize; } else { TRACE("not enough bytes for item %d, failing\n", i); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } } if (cbDecoded) *cbDecoded = decoded; TRACE("returning %d\n", ret); return ret;}
/* This decodes an arbitrary sequence into a contiguous block of memory * (basically, a struct.) Each element being decoded is described by a struct * AsnDecodeSequenceItem, see above. * startingPointer is an optional pointer to the first place where dynamic * data will be stored. If you know the starting offset, you may pass it * here. Otherwise, pass NULL, and one will be inferred from the items. */static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded, void *startingPointer){ BOOL ret;
TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo, startingPointer);
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); return FALSE; } if (pbEncoded[0] == ASN_SEQUENCE) { DWORD dataLen;
if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) { DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded; const BYTE *ptr = pbEncoded + 1 + lenBytes; BOOL indefinite = FALSE;
cbEncoded -= 1 + lenBytes; if (dataLen == CMSG_INDEFINITE_LENGTH) { dataLen = cbEncoded; indefinite = TRUE; lenBytes += 2; } else if (cbEncoded < dataLen) { TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen, cbEncoded); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } if (ret) { ret = CRYPT_AsnDecodeSequenceItems(items, cItem, ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded); if (ret && dataLen == CMSG_INDEFINITE_LENGTH) { if (cbDecoded > cbEncoded - 2) { /* Not enough space for 0 TLV */ SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else if (*(ptr + cbDecoded) != 0 || *(ptr + cbDecoded + 1) != 0) { TRACE("expected 0 TLV\n"); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else cbDecoded += 2; } } if (ret && !indefinite && cbDecoded != dataLen) { TRACE("expected %d decoded, got %d, failing\n", dataLen, cbDecoded); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } if (ret) { DWORD i, bytesNeeded = 0, structSize = 0;
for (i = 0; i < cItem; i++) { if (items[i].size > items[i].minSize) bytesNeeded += items[i].size - items[i].minSize; structSize = max( structSize, items[i].offset + items[i].minSize ); } bytesNeeded += structSize; if (pcbDecoded) *pcbDecoded = 1 + lenBytes + cbDecoded; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { BYTE *nextData;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; if (startingPointer) nextData = startingPointer; else nextData = (BYTE *)pvStructInfo + structSize; memset(pvStructInfo, 0, structSize); ret = CRYPT_AsnDecodeSequenceItems(items, cItem, ptr, dataLen, dwFlags, pvStructInfo, nextData, &cbDecoded); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, pvStructInfo); } } } } else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
/* tag: * The expected tag of the entire encoded array (usually a variant * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called * regardless of the tag seen. * countOffset: * The offset within the outer structure at which the count exists. * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0, * while CRYPT_ATTRIBUTE has countOffset == * offsetof(CRYPT_ATTRIBUTE, cValue). * arrayOffset: * The offset within the outer structure at which the array pointer exists. * For example, CRYPT_ATTRIBUTES has arrayOffset == * offsetof(CRYPT_ATTRIBUTES, rgAttr). * minArraySize: * The minimum size of the decoded array. On WIN32, this is always 8: * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to * alignment. * decodeFunc: * used to decode each item in the array * itemSize: * is the minimum size of each decoded item * hasPointer: * indicates whether each item has a dynamic pointer * pointerOffset: * indicates the offset within itemSize at which the pointer exists */struct AsnArrayDescriptor{ BYTE tag; DWORD countOffset; DWORD arrayOffset; DWORD minArraySize; InternalDecodeFunc decodeFunc; DWORD itemSize; BOOL hasPointer; DWORD pointerOffset;};
struct AsnArrayItemSize{ DWORD encodedLen; DWORD size;};
/* Decodes an array of like types into a structure described by a struct * AsnArrayDescriptor. */static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE;
TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded, cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); ret = FALSE; } else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag) { DWORD dataLen;
if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) { DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded; BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); /* There can be arbitrarily many items, but there is often only one. */ struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
decoded = 1 + lenBytes; if (dataLen) { const BYTE *ptr; BOOL doneDecoding = FALSE;
for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; ) { if (dataLen == CMSG_INDEFINITE_LENGTH) { if (ptr[0] == 0) { doneDecoding = TRUE; if (ptr[1] != 0) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else decoded += 2; } } else if (ptr - pbEncoded - 1 - lenBytes >= dataLen) doneDecoding = TRUE; if (!doneDecoding) { DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
/* Each item decoded may not tolerate extraneous bytes, * so get the length of the next element if known. */ if ((ret = CRYPT_GetLengthIndefinite(ptr, cbEncoded - (ptr - pbEncoded), &itemDataLen))) { if (itemDataLen == CMSG_INDEFINITE_LENGTH) itemEncoded = cbEncoded - (ptr - pbEncoded); else itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) + itemDataLen; } if (ret) ret = arrayDesc->decodeFunc(ptr, itemEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size, &itemDecoded); if (ret) { cItems++; if (itemSizes != &itemSize) itemSizes = CryptMemRealloc(itemSizes, cItems * sizeof(struct AsnArrayItemSize)); else if (cItems > 1) { itemSizes = CryptMemAlloc( cItems * sizeof(struct AsnArrayItemSize)); if (itemSizes) *itemSizes = itemSize; } if (itemSizes) { decoded += itemDecoded; itemSizes[cItems - 1].encodedLen = itemEncoded; itemSizes[cItems - 1].size = size; bytesNeeded += size; ptr += itemEncoded; } else ret = FALSE; } } } } if (ret) { if (pcbDecoded) *pcbDecoded = decoded; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { DWORD i, *pcItems; BYTE *nextData; const BYTE *ptr; void *rgItems;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(void **)pvStructInfo; pcItems = pvStructInfo; *pcItems = cItems; if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) { rgItems = (BYTE *)pvStructInfo + arrayDesc->minArraySize; *(void **)((BYTE *)pcItems - arrayDesc->countOffset + arrayDesc->arrayOffset) = rgItems; } else rgItems = *(void **)((BYTE *)pcItems - arrayDesc->countOffset + arrayDesc->arrayOffset); nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize; for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret && i < cItems && ptr - pbEncoded - 1 - lenBytes < dataLen; i++) { DWORD itemDecoded;
if (arrayDesc->hasPointer) *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize + arrayDesc->pointerOffset) = nextData; ret = arrayDesc->decodeFunc(ptr, itemSizes[i].encodedLen, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, (BYTE *)rgItems + i * arrayDesc->itemSize, &itemSizes[i].size, &itemDecoded); if (ret) { nextData += itemSizes[i].size - arrayDesc->itemSize; ptr += itemDecoded; } } if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, pvStructInfo); } } if (itemSizes != &itemSize) CryptMemFree(itemSizes); } } else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } return ret;}
/* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set * to CRYPT_E_ASN1_CORRUPT. * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData * set! */static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB); if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += 1 + lenBytes + dataLen;
if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded))) { CRYPT_DER_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; blob = pvStructInfo; blob->cbData = 1 + lenBytes + dataLen; if (blob->cbData) { if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) blob->pbData = (BYTE *)pbEncoded; else { assert(blob->pbData); memcpy(blob->pbData, pbEncoded, blob->cbData); } } else { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } } } return ret;}
/* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret;
TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
/* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in- * place. */ ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo, pcbDecoded); if (ret && pvStructInfo) { CRYPT_BIT_BLOB *blob = pvStructInfo;
if (blob->cbData) { DWORD i; BYTE temp;
for (i = 0; i < blob->cbData / 2; i++) { temp = blob->pbData[i]; blob->pbData[i] = blob->pbData[blob->cbData - i - 1]; blob->pbData[blob->cbData - i - 1] = temp; } } } TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnDecodeSequenceItem items[] = { { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned), CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 }, { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 }, { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature), CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 }, };
if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG) items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal; ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY
TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL); if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; } return ret;}
static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret;
struct AsnDecodeSequenceItem items[] = { { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore), CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter), CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, NULL); return ret;}
static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension), FINALMEMBERSIZE(CERT_INFO, cExtension), CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE, offsetof(CERT_EXTENSION, pszObjId) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes, dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL); if (ret && pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; } return ret;}
static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE; struct AsnDecodeSequenceItem items[] = { { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 }, { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 }, { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 }, { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, Issuer.pbData) }, { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 }, { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, Subject.pbData) }, { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO, SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 }, { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 }, { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension), TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 }, };
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); if (ret && pvStructInfo) { CERT_INFO *info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) info = *(CERT_INFO **)pvStructInfo; else info = pvStructInfo; if (!info->SerialNumber.cbData || !info->Issuer.cbData || !info->Subject.cbData) { SetLastError(CRYPT_E_ASN1_CORRUPT); /* Don't need to deallocate, because it should have failed on the * first pass (and no memory was allocated.) */ ret = FALSE; } }
TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { DWORD size = 0;
/* Unless told not to, first try to decode it as a signed cert. */ if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG)) { PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &signedCert, &size); if (ret) { size = 0; ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType, X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData, signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); LocalFree(signedCert); } } /* Failing that, try it as an unsigned cert */ if (!ret) { size = 0; ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType, X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY
TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension), FINALMEMBERSIZE(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE, offsetof(CERT_EXTENSION, pszObjId) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY, SerialNumber.pbData), 0 }, { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeCRLEntryExtensions, FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE, offsetof(CRL_ENTRY, rgExtension), 0 }, }; PCRL_ENTRY entry = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded, entry ? entry->SerialNumber.pbData : NULL); if (ret && entry && !entry->SerialNumber.cbData) { WARN("empty CRL entry serial number\n"); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } return ret;}
/* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO * whose rgCRLEntry member has been set prior to calling. */static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry), MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension), CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE, offsetof(CRL_ENTRY, SerialNumber.pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension), FINALMEMBERSIZE(CRL_INFO, cExtension), CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE, offsetof(CERT_EXTENSION, pszObjId) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes, dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL); if (ret && pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; } return ret;}
static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 }, { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 }, { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO, Issuer.pbData) }, { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE, 0 }, { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension), TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension), CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension), TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 }, }; BOOL ret = TRUE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { DWORD size = 0;
/* Unless told not to, first try to decode it as a signed crl. */ if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG)) { PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &signedCrl, &size); if (ret) { size = 0; ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData, signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); LocalFree(signedCrl); } } /* Failing that, try it as an unsigned crl */ if (!ret) { size = 0; ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY
TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; DWORD dataLen;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD bytesNeeded = sizeof(LPSTR);
if (dataLen) { const BYTE *ptr; char str[32];
snprintf(str, sizeof(str), "%d.%d", pbEncoded[1 + lenBytes] / 40, pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40) * 40); bytesNeeded += strlen(str) + 1; for (ptr = pbEncoded + 2 + lenBytes; ret && ptr - pbEncoded - 1 - lenBytes < dataLen; ) { int val = 0;
while (ptr - pbEncoded - 1 - lenBytes < dataLen && (*ptr & 0x80)) { val <<= 7; val |= *ptr & 0x7f; ptr++; } if (ptr - pbEncoded - 1 - lenBytes >= dataLen || (*ptr & 0x80)) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else { val <<= 7; val |= *ptr++; snprintf(str, sizeof(str), ".%d", val); bytesNeeded += strlen(str); } } } if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { if (dataLen) { const BYTE *ptr; LPSTR pszObjId = *(LPSTR *)pvStructInfo;
*pszObjId = 0; sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40, pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40) * 40); pszObjId += strlen(pszObjId); for (ptr = pbEncoded + 2 + lenBytes; ret && ptr - pbEncoded - 1 - lenBytes < dataLen; ) { int val = 0;
while (ptr - pbEncoded - 1 - lenBytes < dataLen && (*ptr & 0x80)) { val <<= 7; val |= *ptr & 0x7f; ptr++; } val <<= 7; val |= *ptr++; sprintf(pszObjId, ".%d", val); pszObjId += strlen(pszObjId); } } else *(LPSTR *)pvStructInfo = NULL; *pcbStructInfo = bytesNeeded; } } return ret;}
static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
if (pbEncoded[0] == ASN_OBJECTIDENTIFIER) ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, pcbDecoded); else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } return ret;}
static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 }, { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 }, { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION, Value.pbData) }, }; BOOL ret = TRUE; PCERT_EXTENSION ext = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext, *pcbStructInfo);
if (ext) TRACE("ext->pszObjId is %p\n", ext->pszObjId); ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo, pcbDecoded, ext ? ext->pszObjId : NULL); if (ext) TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId, debugstr_a(ext->pszObjId)); TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_EXTENSIONS, cExtension), offsetof(CERT_EXTENSIONS, rgExtension), sizeof(CERT_EXTENSIONS), CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE, offsetof(CERT_EXTENSION, pszObjId) }; CERT_EXTENSIONS *exts = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) exts->rgExtension = (CERT_EXTENSION *)(exts + 1); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
/* Warning: this assumes the address of value->Value.pbData is already set, in * order to avoid overwriting memory. (In some cases, it may change it, if it * doesn't copy anything to memory.) Be sure to set it correctly! */static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; DWORD dataLen; CERT_NAME_VALUE *value = pvStructInfo;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
switch (pbEncoded[0]) { case ASN_OCTETSTRING: valueType = CERT_RDN_OCTET_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_NUMERICSTRING: valueType = CERT_RDN_NUMERIC_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_PRINTABLESTRING: valueType = CERT_RDN_PRINTABLE_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_IA5STRING: valueType = CERT_RDN_IA5_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_T61STRING: valueType = CERT_RDN_T61_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_VIDEOTEXSTRING: valueType = CERT_RDN_VIDEOTEX_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_GRAPHICSTRING: valueType = CERT_RDN_GRAPHIC_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_VISIBLESTRING: valueType = CERT_RDN_VISIBLE_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_GENERALSTRING: valueType = CERT_RDN_GENERAL_STRING; if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen; break; case ASN_UNIVERSALSTRING: FIXME("ASN_UNIVERSALSTRING: unimplemented\n"); SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; case ASN_BMPSTRING: valueType = CERT_RDN_BMP_STRING; bytesNeeded += dataLen; break; case ASN_UTF8STRING: valueType = CERT_RDN_UTF8_STRING; bytesNeeded += MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * sizeof(WCHAR); break; default: SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; }
if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!value) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStructInfo = bytesNeeded; value->dwValueType = valueType; if (dataLen) { DWORD i;
assert(value->Value.pbData); switch (pbEncoded[0]) { case ASN_OCTETSTRING: case ASN_NUMERICSTRING: case ASN_PRINTABLESTRING: case ASN_IA5STRING: case ASN_T61STRING: case ASN_VIDEOTEXSTRING: case ASN_GRAPHICSTRING: case ASN_VISIBLESTRING: case ASN_GENERALSTRING: value->Value.cbData = dataLen; if (dataLen) { if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) memcpy(value->Value.pbData, pbEncoded + 1 + lenBytes, dataLen); else value->Value.pbData = (LPBYTE)pbEncoded + 1 + lenBytes; } break; case ASN_BMPSTRING: { LPWSTR str = (LPWSTR)value->Value.pbData;
value->Value.cbData = dataLen; for (i = 0; i < dataLen / 2; i++) str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) | pbEncoded[1 + lenBytes + 2 * i + 1]; break; } case ASN_UTF8STRING: { LPWSTR str = (LPWSTR)value->Value.pbData;
value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2; break; } } } else { value->Value.cbData = 0; value->Value.pbData = NULL; } } } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
__TRY { ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); if (ret && pvStructInfo) { ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, *pcbStructInfo); if (ret) { CERT_NAME_VALUE *value;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; value = pvStructInfo; value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE)); ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, pcbStructInfo, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, value); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; DWORD dataLen; CERT_NAME_VALUE *value = pvStructInfo;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
switch (pbEncoded[0]) { case ASN_NUMERICSTRING: valueType = CERT_RDN_NUMERIC_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_PRINTABLESTRING: valueType = CERT_RDN_PRINTABLE_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_IA5STRING: valueType = CERT_RDN_IA5_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_T61STRING: valueType = CERT_RDN_T61_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_VIDEOTEXSTRING: valueType = CERT_RDN_VIDEOTEX_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_GRAPHICSTRING: valueType = CERT_RDN_GRAPHIC_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_VISIBLESTRING: valueType = CERT_RDN_VISIBLE_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_GENERALSTRING: valueType = CERT_RDN_GENERAL_STRING; if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_UNIVERSALSTRING: valueType = CERT_RDN_UNIVERSAL_STRING; if (dataLen) bytesNeeded += dataLen / 2 + sizeof(WCHAR); break; case ASN_BMPSTRING: valueType = CERT_RDN_BMP_STRING; if (dataLen) bytesNeeded += dataLen + sizeof(WCHAR); break; case ASN_UTF8STRING: valueType = CERT_RDN_UTF8_STRING; if (dataLen) bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2; break; default: SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; }
if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!value) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStructInfo = bytesNeeded; value->dwValueType = valueType; if (dataLen) { DWORD i; LPWSTR str = (LPWSTR)value->Value.pbData;
assert(value->Value.pbData); switch (pbEncoded[0]) { case ASN_NUMERICSTRING: case ASN_PRINTABLESTRING: case ASN_IA5STRING: case ASN_T61STRING: case ASN_VIDEOTEXSTRING: case ASN_GRAPHICSTRING: case ASN_VISIBLESTRING: case ASN_GENERALSTRING: value->Value.cbData = dataLen * 2; for (i = 0; i < dataLen; i++) str[i] = pbEncoded[1 + lenBytes + i]; str[i] = 0; break; case ASN_UNIVERSALSTRING: value->Value.cbData = dataLen / 2; for (i = 0; i < dataLen / 4; i++) str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8) | pbEncoded[1 + lenBytes + 2 * i + 3]; str[i] = 0; break; case ASN_BMPSTRING: value->Value.cbData = dataLen; for (i = 0; i < dataLen / 2; i++) str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) | pbEncoded[1 + lenBytes + 2 * i + 1]; str[i] = 0; break; case ASN_UTF8STRING: value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR); *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0; value->Value.cbData += sizeof(WCHAR); break; } } else { value->Value.cbData = 0; value->Value.pbData = NULL; } } } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
__TRY { ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); if (ret && pvStructInfo) { ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, *pcbStructInfo); if (ret) { CERT_NAME_VALUE *value;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; value = pvStructInfo; value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE)); ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, pcbStructInfo, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, value); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId), CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_RDN_ATTR, pszObjId), 0 }, { 0, offsetof(CERT_RDN_ATTR, dwValueType), CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE), FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 }, }; CERT_RDN_ATTR *attr = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
if (attr) TRACE("attr->pszObjId is %p\n", attr->pszObjId); ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL); if (attr) { TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId, debugstr_a(attr->pszObjId)); TRACE("attr->dwValueType is %d\n", attr->dwValueType); } TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr), sizeof(CERT_RDN), CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE, offsetof(CERT_RDN_ATTR, pszObjId) };
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN), sizeof(CERT_NAME_INFO), CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE, offsetof(CERT_RDN, rgRDNAttr) }; DWORD bytesNeeded = 0;
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { CERT_NAME_INFO *info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; info = pvStructInfo; info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo + sizeof(CERT_NAME_INFO)); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, info); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId), CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_RDN_ATTR, pszObjId), 0 }, { 0, offsetof(CERT_RDN_ATTR, dwValueType), CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE), FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 }, }; CERT_RDN_ATTR *attr = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
if (attr) TRACE("attr->pszObjId is %p\n", attr->pszObjId); ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL); if (attr) { TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId, debugstr_a(attr->pszObjId)); TRACE("attr->dwValueType is %d\n", attr->dwValueType); } TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr), sizeof(CERT_RDN), CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE, offsetof(CERT_RDN_ATTR, pszObjId) };
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN), sizeof(CERT_NAME_INFO), CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE, offsetof(CERT_RDN, rgRDNAttr) }; DWORD bytesNeeded = 0;
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { CERT_NAME_INFO *info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; info = pvStructInfo; info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo + sizeof(CERT_NAME_INFO)); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, info); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *pcbDecoded){ BOOL ret = TRUE, done = FALSE; DWORD indefiniteNestingLevels = 0, decoded = 0;
TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
do { DWORD dataLen;
if (!cbEncoded) done = TRUE; else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
if (dataLen == CMSG_INDEFINITE_LENGTH) { indefiniteNestingLevels++; pbEncoded += 1 + lenBytes; cbEncoded -= 1 + lenBytes; decoded += 1 + lenBytes; TRACE("indefiniteNestingLevels = %d\n", indefiniteNestingLevels); } else { if (pbEncoded[0] == 0 && pbEncoded[1] == 0 && indefiniteNestingLevels) { indefiniteNestingLevels--; TRACE("indefiniteNestingLevels = %d\n", indefiniteNestingLevels); } pbEncoded += 1 + lenBytes + dataLen; cbEncoded -= 1 + lenBytes + dataLen; decoded += 1 + lenBytes + dataLen; if (!indefiniteNestingLevels) done = TRUE; } } } while (ret && !done); /* If we haven't found all 0 TLVs, we haven't found the end */ if (ret && indefiniteNestingLevels) { SetLastError(CRYPT_E_ASN1_EOD); ret = FALSE; } if (ret) *pcbDecoded = decoded; TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0); return ret;}
static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen))) { if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += encodedLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { SetLastError(ERROR_MORE_DATA); *pcbStructInfo = bytesNeeded; ret = FALSE; } else { PCRYPT_OBJID_BLOB blob = pvStructInfo;
*pcbStructInfo = bytesNeeded; blob->cbData = encodedLen; if (encodedLen) { if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) blob->pbData = (LPBYTE)pbEncoded; else { assert(blob->pbData); memcpy(blob->pbData, pbEncoded, blob->cbData); } } else blob->pbData = NULL; } if (pcbDecoded) *pcbDecoded = encodedLen; } return ret;}
static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CTL_USAGE, cUsageIdentifier), offsetof(CTL_USAGE, rgpszUsageIdentifier), sizeof(CTL_USAGE), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute), FINALMEMBERSIZE(CTL_ENTRY, cAttribute), CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) }; BOOL ret;
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnDecodeSequenceItem items[] = { { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE, offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 }, { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute), CRYPT_AsnDecodeCTLEntryAttributes, FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 }, }; BOOL ret = TRUE; CTL_ENTRY *entry = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL); return ret;}
static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry), FINALMEMBERSIZE(CTL_INFO, cExtension), CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE, offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension), FINALMEMBERSIZE(CTL_INFO, cExtension), CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE, offsetof(CERT_EXTENSION, pszObjId) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes, dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL); if (ret && pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CTL_INFO, dwVersion), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 }, { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage), CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE, offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 }, { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 }, { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber), CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 }, { 0, offsetof(CTL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, { 0, offsetof(CTL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE, 0 }, { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 }, { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry), CRYPT_AsnDecodeCTLEntries, MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension), TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension), CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension), TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 }, { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters), CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 }, }; PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, capability ? capability->pszObjId : NULL); TRACE("returning %d\n", ret); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CRYPT_SMIME_CAPABILITIES, cCapability), offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability), sizeof(CRYPT_SMIME_CAPABILITIES), CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) }; CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) capabilities->rgCapability = (CRYPT_SMIME_CAPABILITY *)(capabilities + 1); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; DWORD dataLen; LPSTR *pStr = pvStructInfo;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
if (pbEncoded[0] != ASN_IA5STRING) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else { bytesNeeded += dataLen; if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStructInfo = bytesNeeded; if (dataLen) { LPSTR str = *pStr;
assert(str); memcpy(str, pbEncoded + 1 + lenBytes, dataLen); str[dataLen] = 0; } else *pStr = NULL; } } } return ret;}
static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers), offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers), FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers), CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 }; BOOL ret;
TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 }, { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers, FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers), FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers), 0 }, }; DWORD bytesNeeded = 0;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded, NULL); if (ret) { /* The caller is expecting a pointer to a * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas * CRYPT_AsnDecodeSequence is decoding a * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes * needed, and decode again if the requisite space is available. */ bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE); if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
*pcbStructInfo = bytesNeeded; /* The pointer (pvStructInfo) passed in points to the first dynamic * pointer, so use it as the pointer to the * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the * appropriate offset for the first dynamic pointer within the * notice reference by pointing to the first memory location past * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. */ noticeRef = *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo; noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef + sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE)); ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, noticeRef, &bytesNeeded, pcbDecoded, noticeRef->pszOrganization); } } TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD bytesNeeded = sizeof(LPWSTR);
switch (pbEncoded[0]) { case ASN_NUMERICSTRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_PRINTABLESTRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_IA5STRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_T61STRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_VIDEOTEXSTRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_GRAPHICSTRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_VISIBLESTRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_GENERALSTRING: if (dataLen) bytesNeeded += (dataLen + 1) * 2; break; case ASN_UNIVERSALSTRING: if (dataLen) bytesNeeded += dataLen / 2 + sizeof(WCHAR); break; case ASN_BMPSTRING: if (dataLen) bytesNeeded += dataLen + sizeof(WCHAR); break; case ASN_UTF8STRING: if (dataLen) bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2; break; default: SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; }
if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { LPWSTR *pStr = pvStructInfo;
*pcbStructInfo = bytesNeeded; if (dataLen) { DWORD i; LPWSTR str = *(LPWSTR *)pStr;
assert(str); switch (pbEncoded[0]) { case ASN_NUMERICSTRING: case ASN_PRINTABLESTRING: case ASN_IA5STRING: case ASN_T61STRING: case ASN_VIDEOTEXSTRING: case ASN_GRAPHICSTRING: case ASN_VISIBLESTRING: case ASN_GENERALSTRING: for (i = 0; i < dataLen; i++) str[i] = pbEncoded[1 + lenBytes + i]; str[i] = 0; break; case ASN_UNIVERSALSTRING: for (i = 0; i < dataLen / 4; i++) str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8) | pbEncoded[1 + lenBytes + 2 * i + 3]; str[i] = 0; break; case ASN_BMPSTRING: for (i = 0; i < dataLen / 2; i++) str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) | pbEncoded[1 + lenBytes + 2 * i + 1]; str[i] = 0; break; case ASN_UTF8STRING: { int len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2; str[len] = 0; break; } } } else *pStr = NULL; } } return ret;}
static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal( const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), CRYPT_AsnDecodeNoticeReference, sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 }, { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 }, }; PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, notice ? notice->pNoticeReference : NULL); TRACE("returning %d\n", ret); return ret;}
static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice( DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { DWORD bytesNeeded = 0;
ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; notice = pvStructInfo; notice->pNoticeReference = (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE) ((BYTE *)pvStructInfo + sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE)); ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal( pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, notice); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue), FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId), CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 }, { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue), CRYPT_AsnDecodePKCSAttributeValue, FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE, TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 }, }; PCRYPT_ATTRIBUTE attr = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL); TRACE("returning %d\n", ret); return ret;}
static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { DWORD bytesNeeded = 0;
ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { PCRYPT_ATTRIBUTE attr;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; attr = pvStructInfo; attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo + sizeof(CRYPT_ATTRIBUTE)); ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, attr); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr), sizeof(CRYPT_ATTRIBUTES), CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) }; BOOL ret;
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr), sizeof(CRYPT_ATTRIBUTES), CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) }; CRYPT_ATTRIBUTES *attrs = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) attrs->rgAttr = (CRYPT_ATTRIBUTE *)(attrs + 1); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; BOOL ret = TRUE; struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 }, { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters), CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 }, };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, algo ? algo->pszObjId : NULL); if (ret && pvStructInfo) { TRACE("pszObjId is %p (%s)\n", algo->pszObjId, debugstr_a(algo->pszObjId)); } return ret;}
static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnDecodeSequenceItem items[] = { { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm.pszObjId) }, { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey), CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) }, }; PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
__TRY { DWORD bytesNeeded = 0;
if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { PCERT_PUBLIC_KEY_INFO info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; info = pvStructInfo; info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo + sizeof(CERT_PUBLIC_KEY_INFO); ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, info); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret;
if (cbEncoded < 3) { SetLastError(CRYPT_E_ASN1_CORRUPT); return FALSE; } if (GET_LEN_BYTES(pbEncoded[1]) > 1) { SetLastError(CRYPT_E_ASN1_CORRUPT); return FALSE; } if (pbEncoded[1] > 1) { SetLastError(CRYPT_E_ASN1_CORRUPT); return FALSE; } if (pcbDecoded) *pcbDecoded = 3; if (!pvStructInfo) { *pcbStructInfo = sizeof(BOOL); ret = TRUE; } else if (*pcbStructInfo < sizeof(BOOL)) { *pcbStructInfo = sizeof(BOOL); SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStructInfo = sizeof(BOOL); *(BOOL *)pvStructInfo = pbEncoded[2] != 0; ret = TRUE; } TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ PCERT_ALT_NAME_ENTRY entry = pvStructInfo; DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY); BOOL ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
if (cbEncoded < 2) { SetLastError(CRYPT_E_ASN1_CORRUPT); return FALSE; } lenBytes = GET_LEN_BYTES(pbEncoded[1]); if (1 + lenBytes > cbEncoded) { SetLastError(CRYPT_E_ASN1_CORRUPT); return FALSE; } if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { switch (pbEncoded[0] & ASN_TYPE_MASK) { case 1: /* rfc822Name */ case 2: /* dNSName */ case 6: /* uniformResourceIdentifier */ if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen)) { SetLastError(CRYPT_E_ASN1_RULE); ret = FALSE; } else bytesNeeded += (dataLen + 1) * sizeof(WCHAR); break; case 4: /* directoryName */ case 7: /* iPAddress */ bytesNeeded += dataLen; break; case 8: /* registeredID */ ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL, &dataLen, NULL); if (ret) { /* FIXME: ugly, shouldn't need to know internals of OID decode * function to use it. */ bytesNeeded += dataLen - sizeof(LPSTR); } break; case 0: /* otherName */ FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK); SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; break; case 3: /* x400Address, unimplemented */ case 5: /* ediPartyName, unimplemented */ TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK); SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; break; default: TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } if (ret) { if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!entry) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { *pcbStructInfo = bytesNeeded; /* MS used values one greater than the asn1 ones.. sigh */ entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1; switch (pbEncoded[0] & ASN_TYPE_MASK) { case 1: /* rfc822Name */ case 2: /* dNSName */ case 6: /* uniformResourceIdentifier */ { DWORD i;
for (i = 0; i < dataLen; i++) entry->u.pwszURL[i] = (WCHAR)pbEncoded[1 + lenBytes + i]; entry->u.pwszURL[i] = 0; TRACE("URL is %p (%s)\n", entry->u.pwszURL, debugstr_w(entry->u.pwszURL)); break; } case 4: /* directoryName */ /* The data are memory-equivalent with the IPAddress case, * fall-through */ case 7: /* iPAddress */ /* The next data pointer is in the pwszURL spot, that is, * the first 4 bytes. Need to move it to the next spot. */ entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL; entry->u.IPAddress.cbData = dataLen; memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes, dataLen); break; case 8: /* registeredID */ ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, &entry->u.pszRegisteredID, &dataLen, NULL); break; } } } } return ret;}
static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CERT_ALT_NAME_INFO, cAltEntry), offsetof(CERT_ALT_NAME_INFO, rgAltEntry), sizeof(CERT_ALT_NAME_INFO), CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR| 1, offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer), CRYPT_AsnDecodeOctets, sizeof(CERT_NAME_BLOB), TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 }, { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber), CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR| 1, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer), CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer.rgAltEntry), 0 }, { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertSerialNumber.pbData), 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnDecodeSequenceItem items[] = { { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 }, { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation), CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE, TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 }, }; CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, descr ? descr->pszAccessMethod : NULL);}
static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr), offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr), sizeof(CERT_AUTHORITY_INFO_ACCESS), CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION), TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) }; CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) info->rgAccDescr = (CERT_ACCESS_DESCRIPTION *)(info + 1); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD dataLen;
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
/* The caller has already checked the tag, no need to check it again. * Check the outer length is valid: */ if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD innerLen;
pbEncoded += 1 + lenBytes; cbEncoded -= 1 + lenBytes; if (dataLen == CMSG_INDEFINITE_LENGTH) cbEncoded -= 2; /* space for 0 TLV */ /* Check the inner length is valid: */ if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen))) { DWORD decodedLen;
ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, &decodedLen); if (dataLen == CMSG_INDEFINITE_LENGTH) { if (*(pbEncoded + decodedLen) != 0 || *(pbEncoded + decodedLen + 1) != 0) { TRACE("expected 0 TLV, got {%02x,%02x}\n", *(pbEncoded + decodedLen), *(pbEncoded + decodedLen + 1)); SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else decodedLen += 2; } if (ret && pcbDecoded) { *pcbDecoded = 1 + lenBytes + decodedLen; TRACE("decoded %d bytes\n", *pcbDecoded); } } } return ret;}
static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ CRYPT_CONTENT_INFO *info = pvStructInfo; struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId), CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent, sizeof(CRYPT_DER_BLOB), TRUE, TRUE, offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 }, }; BOOL ret;
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, info ? info->pszObjId : NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); if (ret && pvStructInfo) { ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, *pcbStructInfo); if (ret) { CRYPT_CONTENT_INFO *info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; info = pvStructInfo; info->pszObjId = (LPSTR)((BYTE *)info + sizeof(CRYPT_CONTENT_INFO)); ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, pcbStructInfo, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, info); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY return ret;}
BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId), 0 }, { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo), CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, ContentInfo.pszObjId), 0 }, { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash), CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData, NULL, NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { DWORD bytesNeeded = 0;
if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { CERT_ALT_NAME_INFO *name;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; name = pvStructInfo; name->rgAltEntry = (PCERT_ALT_NAME_ENTRY) ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO)); ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, name); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
struct PATH_LEN_CONSTRAINT{ BOOL fPathLenConstraint; DWORD dwPathLenConstraint;};
static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
if (!pvStructInfo) { ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL, &size, pcbDecoded); *pcbStructInfo = bytesNeeded; } else if (*pcbStructInfo < bytesNeeded) { SetLastError(ERROR_MORE_DATA); *pcbStructInfo = bytesNeeded; ret = FALSE; } else { struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
*pcbStructInfo = bytesNeeded; size = sizeof(constraint->dwPathLenConstraint); ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, &constraint->dwPathLenConstraint, &size, pcbDecoded); if (ret) constraint->fPathLenConstraint = TRUE; TRACE("got an int, dwPathLenConstraint is %d\n", constraint->dwPathLenConstraint); } TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint), offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint), CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE, offsetof(CERT_NAME_BLOB, pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType), CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 }, { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO, fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 }, { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints, FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint), TRUE, TRUE, offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 }, { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId), 0 }, { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier), CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 }, }; BOOL ret; CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL); return ret;}
static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier), offsetof(CERT_POLICY_INFO, rgPolicyQualifier), FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); TRACE("Returning %d (%08x)\n", ret, GetLastError()); return ret;}
static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 }, { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier), CRYPT_AsnDecodePolicyQualifiers, FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE, TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 }, }; CERT_POLICY_INFO *info = pvStructInfo; BOOL ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, info ? info->pszPolicyIdentifier : NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_POLICIES_INFO, cPolicyInfo), offsetof(CERT_POLICIES_INFO, rgPolicyInfo), sizeof(CERT_POLICIES_INFO), CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) }; CERT_POLICIES_INFO *info = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) info->rgPolicyInfo = (CERT_POLICY_INFO *)(info + 1);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 }, { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 }, }; CERT_POLICY_MAPPING *mapping = pvStructInfo; BOOL ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping), offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping), sizeof(CERT_POLICY_MAPPING), CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) }; CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) info->rgPolicyMapping = (CERT_POLICY_MAPPING *)(info + 1); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD skip, size = sizeof(skip);
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); return FALSE; } if (pbEncoded[0] != (ASN_CONTEXT | 0)) { SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; } if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, &skip, &size, pcbDecoded))) { DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy, fInhibitPolicyMapping);
if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo, CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy);
*pcbStructInfo = bytesNeeded; /* The BOOL is implicit: if the integer is present, then it's * TRUE. */ info->fRequireExplicitPolicy = TRUE; info->dwRequireExplicitPolicySkipCerts = skip; } } return ret;}
static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD skip, size = sizeof(skip);
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); return FALSE; } if (pbEncoded[0] != (ASN_CONTEXT | 1)) { SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; } if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, &skip, &size, pcbDecoded))) { DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo, CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
*pcbStructInfo = bytesNeeded; /* The BOOL is implicit: if the integer is present, then it's * TRUE. */ info->fInhibitPolicyMapping = TRUE; info->dwInhibitPolicyMappingSkipCerts = skip; } } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints( DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_CONTEXT | 0, offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy), CRYPT_AsnDecodeRequireExplicit, MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy, fInhibitPolicyMapping), TRUE, FALSE, 0, 0 }, { ASN_CONTEXT | 1, offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping), CRYPT_AsnDecodeInhibitMapping, FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping), TRUE, FALSE, 0, 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY return ret;}
#define RSA1_MAGIC 0x31415352
struct DECODED_RSA_PUB_KEY{ DWORD pubexp; CRYPT_INTEGER_BLOB modulus;};
static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData), 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, }; struct DECODED_RSA_PUB_KEY *decodedKey = NULL; DWORD size = 0;
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL, NULL); if (ret) { DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + decodedKey->modulus.cbData;
if (!pvStructInfo) { *pcbStructInfo = bytesNeeded; ret = TRUE; } else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { BLOBHEADER *hdr; RSAPUBKEY *rsaPubKey;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; hdr = pvStructInfo; hdr->bType = PUBLICKEYBLOB; hdr->bVersion = CUR_BLOB_VERSION; hdr->reserved = 0; hdr->aiKeyAlg = CALG_RSA_KEYX; rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo + sizeof(BLOBHEADER)); rsaPubKey->magic = RSA1_MAGIC; rsaPubKey->pubexp = decodedKey->pubexp; rsaPubKey->bitlen = decodedKey->modulus.cbData * 8; memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), decodedKey->modulus.pbData, decodedKey->modulus.cbData); } LocalFree(decodedKey); } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
#define RSA2_MAGIC 0x32415352
struct DECODED_RSA_PRIV_KEY{ DWORD version; DWORD pubexp; CRYPT_INTEGER_BLOB modulus; CRYPT_INTEGER_BLOB privexp; CRYPT_INTEGER_BLOB prime1; CRYPT_INTEGER_BLOB prime2; CRYPT_INTEGER_BLOB exponent1; CRYPT_INTEGER_BLOB exponent2; CRYPT_INTEGER_BLOB coefficient;};
static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret; DWORD halflen;
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData), 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData), 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData), 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData), 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData), 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData), 0 }, { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData), 0 }, }; struct DECODED_RSA_PRIV_KEY *decodedKey = NULL; DWORD size = 0;
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL, NULL); if (ret) { halflen = decodedKey->prime1.cbData; if (halflen < decodedKey->prime2.cbData) halflen = decodedKey->prime2.cbData; if (halflen < decodedKey->exponent1.cbData) halflen = decodedKey->exponent1.cbData; if (halflen < decodedKey->exponent2.cbData) halflen = decodedKey->exponent2.cbData; if (halflen < decodedKey->coefficient.cbData) halflen = decodedKey->coefficient.cbData; if (halflen * 2 < decodedKey->modulus.cbData) halflen = decodedKey->modulus.cbData / 2 + decodedKey->modulus.cbData % 2; if (halflen * 2 < decodedKey->privexp.cbData) halflen = decodedKey->privexp.cbData / 2 + decodedKey->privexp.cbData % 2;
if (ret) { DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (halflen * 9);
if (!pvStructInfo) { *pcbStructInfo = bytesNeeded; ret = TRUE; } else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { BLOBHEADER *hdr; RSAPUBKEY *rsaPubKey; BYTE *vardata;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo;
hdr = pvStructInfo; hdr->bType = PRIVATEKEYBLOB; hdr->bVersion = CUR_BLOB_VERSION; hdr->reserved = 0; hdr->aiKeyAlg = CALG_RSA_KEYX;
rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo + sizeof(BLOBHEADER)); rsaPubKey->magic = RSA2_MAGIC; rsaPubKey->pubexp = decodedKey->pubexp; rsaPubKey->bitlen = halflen * 16;
vardata = (BYTE*)(rsaPubKey + 1); memset(vardata, 0, halflen * 9); memcpy(vardata, decodedKey->modulus.pbData, decodedKey->modulus.cbData); memcpy(vardata + halflen * 2, decodedKey->prime1.pbData, decodedKey->prime1.cbData); memcpy(vardata + halflen * 3, decodedKey->prime2.pbData, decodedKey->prime2.cbData); memcpy(vardata + halflen * 4, decodedKey->exponent1.pbData, decodedKey->exponent1.cbData); memcpy(vardata + halflen * 5, decodedKey->exponent2.pbData, decodedKey->exponent2.cbData); memcpy(vardata + halflen * 6, decodedKey->coefficient.pbData, decodedKey->coefficient.cbData); memcpy(vardata + halflen * 7, decodedKey->privexp.pbData, decodedKey->privexp.cbData); } }
LocalFree(decodedKey); } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD bytesNeeded, dataLen;
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) bytesNeeded = sizeof(CRYPT_DATA_BLOB); else bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB); if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { SetLastError(ERROR_MORE_DATA); *pcbStructInfo = bytesNeeded; ret = FALSE; } else { CRYPT_DATA_BLOB *blob;
*pcbStructInfo = bytesNeeded; blob = pvStructInfo; blob->cbData = dataLen; if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes; else { assert(blob->pbData); if (blob->cbData) memcpy(blob->pbData, pbEncoded + 1 + lenBytes, blob->cbData); } } } return ret;}
static BOOL CRYPT_AsnDecodeOctetStringInternal(const BYTE *encoded, DWORD encoded_size, DWORD flags, void *buf, DWORD *buf_size, DWORD *ret_decoded){ DWORD decoded = 0, indefinite_len_depth = 0, len_size, len, bytes_needed; CRYPT_DATA_BLOB *blob; const BYTE *string;
while (encoded[0] == (ASN_CONSTRUCTOR | ASN_OCTETSTRING)) { if (!CRYPT_GetLengthIndefinite(encoded, encoded_size, &len)) return FALSE;
len_size = GET_LEN_BYTES(encoded[1]); encoded += 1 + len_size; encoded_size -= 1 + len_size; decoded += 1 + len_size;
if (len == CMSG_INDEFINITE_LENGTH) { indefinite_len_depth++; if (encoded_size < 2) { SetLastError(CRYPT_E_ASN1_EOD); return FALSE; } encoded_size -= 2; decoded += 2; } }
if (encoded[0] != ASN_OCTETSTRING) { WARN("Unexpected tag %02x\n", encoded[0]); SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; }
if (!CRYPT_GetLen(encoded, encoded_size, &len)) return FALSE; len_size = GET_LEN_BYTES(encoded[1]); decoded += 1 + len_size + len; encoded_size -= 1 + len_size;
if (len > encoded_size) { SetLastError(CRYPT_E_ASN1_EOD); return FALSE; } if (ret_decoded) *ret_decoded = decoded;
encoded += 1 + len_size; string = encoded; encoded += len;
while (indefinite_len_depth--) { if (encoded[0] || encoded[1]) { TRACE("expected 0 TLV, got %02x %02x\n", encoded[0], encoded[1]); SetLastError(CRYPT_E_ASN1_CORRUPT); return FALSE; } }
bytes_needed = sizeof(*blob); if (!(flags & CRYPT_DECODE_NOCOPY_FLAG)) bytes_needed += len; if (!buf) { *buf_size = bytes_needed; return TRUE; } if (*buf_size < bytes_needed) { SetLastError(ERROR_MORE_DATA); *buf_size = bytes_needed; return FALSE; }
*buf_size = bytes_needed; blob = buf; blob->cbData = len; if (flags & CRYPT_DECODE_NOCOPY_FLAG) blob->pbData = (BYTE*)string; else if (blob->cbData) memcpy(blob->pbData, string, blob->cbData);
if (ret_decoded) *ret_decoded = decoded; return TRUE;}
static BOOL WINAPI CRYPT_AsnDecodeOctetString(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_CORRUPT); return FALSE; }
__TRY { DWORD bytesNeeded = 0;
if ((ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { CRYPT_DATA_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; blob = pvStructInfo; blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB); ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, blob); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD bytesNeeded, dataLen; BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) bytesNeeded = sizeof(CRYPT_BIT_BLOB); else bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB); if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { CRYPT_BIT_BLOB *blob;
*pcbStructInfo = bytesNeeded; blob = pvStructInfo; blob->cbData = dataLen - 1; blob->cUnusedBits = *(pbEncoded + 1 + lenBytes); if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) { blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes; } else { assert(blob->pbData); if (blob->cbData) { BYTE mask = 0xff << blob->cUnusedBits;
memcpy(blob->pbData, pbEncoded + 2 + lenBytes, blob->cbData); blob->pbData[blob->cbData - 1] &= mask; } } } } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
__TRY { DWORD bytesNeeded = 0;
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else if (pbEncoded[0] != ASN_BITSTRING) { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { CRYPT_BIT_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; blob = pvStructInfo; blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB); ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, blob); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY TRACE("returning %d (%08x)\n", ret, GetLastError()); return ret;}
/* Ignores tag. Only allows integers 4 bytes or smaller in size. */static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (dataLen > sizeof(int)) { SetLastError(CRYPT_E_ASN1_LARGE); ret = FALSE; } else if (!pvStructInfo) *pcbStructInfo = sizeof(int); else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int)))) { int val, i;
if (dataLen && pbEncoded[1 + lenBytes] & 0x80) { /* initialize to a negative value to sign-extend */ val = -1; } else val = 0; for (i = 0; i < dataLen; i++) { val <<= 8; val |= pbEncoded[1 + lenBytes + i]; } memcpy(pvStructInfo, &val, sizeof(int)); } } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { DWORD bytesNeeded = 0;
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); ret = FALSE; } else if (pbEncoded[0] != ASN_INTEGER) { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } else ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, pvStructInfo); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD bytesNeeded, dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB); if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { CRYPT_INTEGER_BLOB *blob = pvStructInfo;
*pcbStructInfo = bytesNeeded; blob->cbData = dataLen; assert(blob->pbData); if (blob->cbData) { DWORD i;
for (i = 0; i < blob->cbData; i++) { blob->pbData[i] = *(pbEncoded + 1 + lenBytes + dataLen - i - 1); } } } } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { DWORD bytesNeeded = 0;
if (pbEncoded[0] != ASN_INTEGER) { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } else ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { CRYPT_INTEGER_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; blob = pvStructInfo; blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_INTEGER_BLOB); ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, blob); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret;
if (pbEncoded[0] == ASN_INTEGER) { DWORD bytesNeeded, dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB); if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { CRYPT_INTEGER_BLOB *blob = pvStructInfo;
*pcbStructInfo = bytesNeeded; blob->cbData = dataLen; assert(blob->pbData); /* remove leading zero byte if it exists */ if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0) { blob->cbData--; blob->pbData++; } if (blob->cbData) { DWORD i;
for (i = 0; i < blob->cbData; i++) { blob->pbData[i] = *(pbEncoded + 1 + lenBytes + dataLen - i - 1); } } } } } else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { DWORD bytesNeeded = 0;
if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { CRYPT_INTEGER_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; blob = pvStructInfo; blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_INTEGER_BLOB); ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, blob); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
if (!pvStructInfo) { *pcbStructInfo = sizeof(int); return TRUE; } __TRY { if (pbEncoded[0] == ASN_ENUMERATED) { unsigned int val = 0, i;
if (cbEncoded <= 1) { SetLastError(CRYPT_E_ASN1_EOD); ret = FALSE; } else if (pbEncoded[1] == 0) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else { /* A little strange looking, but we have to accept a sign byte: * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also, * assuming a small length is okay here, it has to be in short * form. */ if (pbEncoded[1] > sizeof(unsigned int) + 1) { SetLastError(CRYPT_E_ASN1_LARGE); return FALSE; } for (i = 0; i < pbEncoded[1]; i++) { val <<= 8; val |= pbEncoded[2 + i]; } if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, sizeof(unsigned int)))) { if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; memcpy(pvStructInfo, &val, sizeof(unsigned int)); } } } else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
/* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE * if it fails. */#define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \ do { \ BYTE i; \ \ (word) = 0; \ for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \ { \ if (!isdigit(*(pbEncoded))) \ { \ SetLastError(CRYPT_E_ASN1_CORRUPT); \ ret = FALSE; \ } \ else \ { \ (word) *= 10; \ (word) += *(pbEncoded)++ - '0'; \ } \ } \ } while (0)
static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len, SYSTEMTIME *sysTime){ BOOL ret = TRUE;
if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-')) { WORD hours, minutes = 0; BYTE sign = *pbEncoded++;
len--; CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours); if (ret && hours >= 24) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } else if (len >= 2) { CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes); if (ret && minutes >= 60) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } } if (ret) { if (sign == '+') { sysTime->wHour += hours; sysTime->wMinute += minutes; } else { if (hours > sysTime->wHour) { sysTime->wDay--; sysTime->wHour = 24 - (hours - sysTime->wHour); } else sysTime->wHour -= hours; if (minutes > sysTime->wMinute) { sysTime->wHour--; sysTime->wMinute = 60 - (minutes - sysTime->wMinute); } else sysTime->wMinute -= minutes; } } } return ret;}
#define MIN_ENCODED_TIME_LENGTH 10
static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = FALSE;
if (pbEncoded[0] == ASN_UTCTIME) { if (cbEncoded <= 1) SetLastError(CRYPT_E_ASN1_EOD); else if (pbEncoded[1] > 0x7f) { /* long-form date strings really can't be valid */ SetLastError(CRYPT_E_ASN1_CORRUPT); } else { SYSTEMTIME sysTime = { 0 }; BYTE len = pbEncoded[1];
if (len < MIN_ENCODED_TIME_LENGTH) SetLastError(CRYPT_E_ASN1_CORRUPT); else { ret = TRUE; if (pcbDecoded) *pcbDecoded = 2 + len; pbEncoded += 2; CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear); if (sysTime.wYear >= 50) sysTime.wYear += 1900; else sysTime.wYear += 2000; CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth); CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay); CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour); CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute); if (ret && len > 0) { if (len >= 2 && isdigit(*pbEncoded) && isdigit(*(pbEncoded + 1))) CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wSecond); else if (isdigit(*pbEncoded)) CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1, sysTime.wSecond); if (ret) ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len, &sysTime); } if (ret) { if (!pvStructInfo) *pcbStructInfo = sizeof(FILETIME); else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(FILETIME)))) ret = SystemTimeToFileTime(&sysTime, pvStructInfo); } } } } else SetLastError(CRYPT_E_ASN1_BADTAG); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
__TRY { DWORD bytesNeeded = 0;
ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, pvStructInfo); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = FALSE;
if (pbEncoded[0] == ASN_GENERALTIME) { if (cbEncoded <= 1) SetLastError(CRYPT_E_ASN1_EOD); else if (pbEncoded[1] > 0x7f) { /* long-form date strings really can't be valid */ SetLastError(CRYPT_E_ASN1_CORRUPT); } else { BYTE len = pbEncoded[1];
if (len < MIN_ENCODED_TIME_LENGTH) SetLastError(CRYPT_E_ASN1_CORRUPT); else { SYSTEMTIME sysTime = { 0 };
ret = TRUE; if (pcbDecoded) *pcbDecoded = 2 + len; pbEncoded += 2; CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear); CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth); CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay); CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour); if (ret && len > 0) { CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute); if (ret && len > 0) CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wSecond); if (ret && len > 0 && (*pbEncoded == '.' || *pbEncoded == ',')) { BYTE digits;
pbEncoded++; len--; /* workaround macro weirdness */ digits = min(len, 3); CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits, sysTime.wMilliseconds); } if (ret) ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len, &sysTime); } if (ret) { if (!pvStructInfo) *pcbStructInfo = sizeof(FILETIME); else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(FILETIME)))) ret = SystemTimeToFileTime(&sysTime, pvStructInfo); } } } } else SetLastError(CRYPT_E_ASN1_BADTAG); return ret;}
static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; InternalDecodeFunc decode = NULL;
if (pbEncoded[0] == ASN_UTCTIME) decode = CRYPT_AsnDecodeUtcTimeInternal; else if (pbEncoded[0] == ASN_GENERALTIME) decode = CRYPT_AsnDecodeGeneralizedTime; if (decode) ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, pcbDecoded); else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } return ret;}
static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
__TRY { DWORD bytesNeeded = 0;
ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, pvStructInfo); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = TRUE;
__TRY { if (pbEncoded[0] == ASN_SEQUENCEOF) { DWORD bytesNeeded, dataLen, remainingLen, cValue;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { BYTE lenBytes; const BYTE *ptr;
lenBytes = GET_LEN_BYTES(pbEncoded[1]); bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY); cValue = 0; ptr = pbEncoded + 1 + lenBytes; remainingLen = dataLen; while (ret && remainingLen) { DWORD nextLen;
ret = CRYPT_GetLen(ptr, remainingLen, &nextLen); if (ret) { DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
remainingLen -= 1 + nextLenBytes + nextLen; ptr += 1 + nextLenBytes + nextLen; bytesNeeded += sizeof(CRYPT_DER_BLOB); if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += 1 + nextLenBytes + nextLen; cValue++; } } if (ret) { CRYPT_SEQUENCE_OF_ANY *seq; BYTE *nextPtr; DWORD i;
if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; seq = pvStructInfo; seq->cValue = cValue; seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq + sizeof(*seq)); nextPtr = (BYTE *)seq->rgValue + cValue * sizeof(CRYPT_DER_BLOB); ptr = pbEncoded + 1 + lenBytes; remainingLen = dataLen; i = 0; while (ret && remainingLen) { DWORD nextLen;
ret = CRYPT_GetLen(ptr, remainingLen, &nextLen); if (ret) { DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
seq->rgValue[i].cbData = 1 + nextLenBytes + nextLen; if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) seq->rgValue[i].pbData = (BYTE *)ptr; else { seq->rgValue[i].pbData = nextPtr; memcpy(nextPtr, ptr, 1 + nextLenBytes + nextLen); nextPtr += 1 + nextLenBytes + nextLen; } remainingLen -= 1 + nextLenBytes + nextLen; ptr += 1 + nextLenBytes + nextLen; i++; } } if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, seq); } } } } else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret;
if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0)) { DWORD bytesNeeded = 0, dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) { struct AsnArrayDescriptor arrayDesc = { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry), offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry), FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u), CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) }; BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD nameLen;
if (dataLen) { ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags, NULL, NULL, &nameLen, NULL); bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen - FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u); } else bytesNeeded = sizeof(CRL_DIST_POINT_NAME); if (pcbDecoded) *pcbDecoded = 1 + lenBytes + dataLen; if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { CRL_DIST_POINT_NAME *name = pvStructInfo;
*pcbStructInfo = bytesNeeded; if (dataLen) { name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME; ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen, NULL); } else name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME; } } } else { SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } return ret;}
static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ struct AsnDecodeSequenceItem items[] = { { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT, DistPointName), CRYPT_AsnDecodeDistPointName, sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry), 0 }, { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags), CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer), CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE, offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 }, }; CRL_DIST_POINT *point = pvStructInfo; BOOL ret;
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CRL_DIST_POINTS_INFO, cDistPoint), offsetof(CRL_DIST_POINTS_INFO, rgDistPoint), sizeof(CRL_DIST_POINTS_INFO), CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE, offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) }; CRL_DIST_POINTS_INFO *info = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) info->rgDistPoint = (CRL_DIST_POINT *)(info + 1); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier), offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier), sizeof(CERT_ENHKEY_USAGE), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 }; CERT_ENHKEY_USAGE *usage = pvStructInfo;
if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG)) usage->rgpszUsageIdentifier = (LPSTR *)(usage + 1); ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT, DistPointName), CRYPT_AsnDecodeDistPointName, sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT, DistPointName.u.FullName.rgAltEntry), 0 }, { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT, fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 }, { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT, fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 }, { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT, OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT, OnlySomeReasonFlags.pbData), 0 }, { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT, fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; DWORD max, size = sizeof(max);
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
if (!cbEncoded) { SetLastError(CRYPT_E_ASN1_EOD); return FALSE; } if (pbEncoded[0] != (ASN_CONTEXT | 1)) { SetLastError(CRYPT_E_ASN1_BADTAG); return FALSE; } if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, &max, &size, pcbDecoded))) { DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if (*pcbStructInfo < bytesNeeded) { *pcbStructInfo = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo, CERT_GENERAL_SUBTREE, fMaximum);
*pcbStructInfo = bytesNeeded; /* The BOOL is implicit: if the integer is present, then it's * TRUE. */ subtree->fMaximum = TRUE; subtree->dwMaximum = max; } } TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { 0, offsetof(CERT_GENERAL_SUBTREE, Base), CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE, offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 }, { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 }, { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum), CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum), TRUE, FALSE, 0, 0 }, }; CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL); if (pcbDecoded) { TRACE("%d\n", *pcbDecoded); if (*pcbDecoded < cbEncoded) TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded), *(pbEncoded + *pcbDecoded + 1)); } TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree), offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree, cExcludedSubtree), CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE, offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret = TRUE; struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree), offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree), CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE, offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { struct AsnDecodeSequenceItem items[] = { { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree), CRYPT_AsnDecodePermittedSubtree, MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree, cExcludedSubtree), TRUE, TRUE, offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 }, { ASN_CONTEXT | ASN_CONSTRUCTOR | 1, offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree), CRYPT_AsnDecodeExcludedSubtree, FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree), TRUE, TRUE, offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 }, };
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY return ret;}
static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer.pbData) }, { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber), CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 }, }; CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL); if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData) { SetLastError(CRYPT_E_ASN1_CORRUPT); ret = FALSE; } TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ CMSG_SIGNER_INFO *info = pvStructInfo; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer), CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 }, { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, offsetof(CMSG_SIGNER_INFO, AuthAttrs), CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm.pszObjId), 0 }, { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 }, { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, offsetof(CMSG_SIGNER_INFO, UnauthAttrs), CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 }, }; BOOL ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, info ? info->Issuer.pbData : NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); if (ret && pvStructInfo) { ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, *pcbStructInfo); if (ret) { CMSG_SIGNER_INFO *info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; info = pvStructInfo; info->Issuer.pbData = ((BYTE *)info + sizeof(CMSG_SIGNER_INFO)); ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, pcbStructInfo, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, info); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CRYPT_SIGNED_INFO, cCertEncoded), offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { 0, offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ CERT_ID *id = pvStructInfo; BOOL ret = FALSE;
if (*pbEncoded == ASN_SEQUENCEOF) { ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags, id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded); if (ret) { if (id) id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER)) *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo - sizeof(CERT_ISSUER_SERIAL_NUMBER); else *pcbStructInfo = sizeof(CERT_ID); } } else if (*pbEncoded == (ASN_CONTEXT | 0)) { ret = CRYPT_AsnDecodeOctets(pbEncoded, cbEncoded, dwFlags, id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded); if (ret) { if (id) id->dwIdChoice = CERT_ID_KEY_IDENTIFIER; if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB)) *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo - sizeof(CRYPT_DATA_BLOB); else *pcbStructInfo = sizeof(CERT_ID); } } else SetLastError(CRYPT_E_ASN1_BADTAG); return ret;}
static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ CMSG_CMS_SIGNER_INFO *info = pvStructInfo; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId), CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 }, { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs), CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 }, /* FIXME: Tests show that CertOpenStore accepts such certificates, but * how exactly should they be interpreted? */ { ASN_CONSTRUCTOR | ASN_UNIVERSAL | 0x11, 0, NULL, 0, TRUE, FALSE, 0, 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm.pszObjId), 0 }, { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 }, { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs), CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 }, }; BOOL ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY { ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); if (ret && pvStructInfo) { ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, *pcbStructInfo); if (ret) { CMSG_CMS_SIGNER_INFO *info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo; info = pvStructInfo; info->SignerId.u.KeyId.pbData = ((BYTE *)info + sizeof(CMSG_CMS_SIGNER_INFO)); ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, pcbStructInfo, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, info); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); } __ENDTRY TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo), offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE, offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); return ret;}
BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo){ BOOL ret = FALSE; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, /* Placeholder for the hash algorithms - redundant with those in the * signers, so just ignore them. */ { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 }, { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content), CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 }, { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded, MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE, offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 }, { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded, MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE, offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 }, { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo), CRYPT_DecodeSignerArray, FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE, offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 }, };
TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo, NULL, NULL); TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, KeyEncryptionAlgorithm.pszObjId), 0 }, { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 }, };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData : NULL); if (info) info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo), offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo), CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded); TRACE("returning %d\n", ret); return ret;}
static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded){ BOOL ret; CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo; struct AsnDecodeSequenceItem items[] = { { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, contentType), 0 }, { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, contentEncryptionAlgorithm.pszObjId), 0 }, { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent), CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) }, };
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, pcbDecoded);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, info ? info->contentType : NULL); TRACE("returning %d\n", ret); return ret;}
BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version), CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo), CRYPT_DecodeRecipientInfoArray, MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo), FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 }, { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo), CRYPT_AsnDecodeEncryptedContentInfo, sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 }, };
TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData, pcbEnvelopedData);
ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData, pcbEnvelopedData, NULL, NULL); TRACE("returning %d\n", ret); return ret;}
static BOOL WINAPI CRYPT_AsnDecodeObjectIdentifier(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ DWORD bytesNeeded = 0; BOOL ret;
__TRY { ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); if (ret) { if (!pvStructInfo) *pcbStructInfo = bytesNeeded; else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) { LPSTR *info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) pvStructInfo = *(BYTE **)pvStructInfo;
info = pvStructInfo; *info = (void *)((BYTE *)info + sizeof(*info)); ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, NULL); if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) CRYPT_FreeSpace(pDecodePara, info); } } } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static BOOL WINAPI CRYPT_AsnDecodeEccSignature(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret; struct AsnDecodeSequenceItem items[] = { { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, r), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE, TRUE, offsetof(CERT_ECC_SIGNATURE, r.pbData), 0 }, { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, s), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE, TRUE, offsetof(CERT_ECC_SIGNATURE, s.pbData), 0 }, };
__TRY { ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); } __EXCEPT_PAGE_FAULT { SetLastError(STATUS_ACCESS_VIOLATION); ret = FALSE; } __ENDTRY return ret;}
static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType, LPCSTR lpszStructType){ CryptDecodeObjectExFunc decodeFunc = NULL;
if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING) { SetLastError(ERROR_FILE_NOT_FOUND); return NULL; } if (IS_INTOID(lpszStructType)) { switch (LOWORD(lpszStructType)) { case LOWORD(X509_CERT): decodeFunc = CRYPT_AsnDecodeCertSignedContent; break; case LOWORD(X509_CERT_TO_BE_SIGNED): decodeFunc = CRYPT_AsnDecodeCert; break; case LOWORD(X509_CERT_CRL_TO_BE_SIGNED): decodeFunc = CRYPT_AsnDecodeCRL; break; case LOWORD(X509_EXTENSIONS): decodeFunc = CRYPT_AsnDecodeExtensions; break; case LOWORD(X509_NAME_VALUE): decodeFunc = CRYPT_AsnDecodeNameValue; break; case LOWORD(X509_NAME): decodeFunc = CRYPT_AsnDecodeName; break; case LOWORD(X509_PUBLIC_KEY_INFO): decodeFunc = CRYPT_AsnDecodePubKeyInfo; break; case LOWORD(X509_AUTHORITY_KEY_ID): decodeFunc = CRYPT_AsnDecodeAuthorityKeyId; break; case LOWORD(X509_ALTERNATE_NAME): decodeFunc = CRYPT_AsnDecodeAltName; break; case LOWORD(X509_BASIC_CONSTRAINTS): decodeFunc = CRYPT_AsnDecodeBasicConstraints; break; case LOWORD(X509_BASIC_CONSTRAINTS2): decodeFunc = CRYPT_AsnDecodeBasicConstraints2; break; case LOWORD(X509_CERT_POLICIES): decodeFunc = CRYPT_AsnDecodeCertPolicies; break; case LOWORD(RSA_CSP_PUBLICKEYBLOB): decodeFunc = CRYPT_AsnDecodeRsaPubKey; break; case LOWORD(PKCS_RSA_PRIVATE_KEY): decodeFunc = CRYPT_AsnDecodeRsaPrivKey; break; case LOWORD(X509_UNICODE_NAME): decodeFunc = CRYPT_AsnDecodeUnicodeName; break; case LOWORD(PKCS_ATTRIBUTE): decodeFunc = CRYPT_AsnDecodePKCSAttribute; break; case LOWORD(X509_UNICODE_NAME_VALUE): decodeFunc = CRYPT_AsnDecodeUnicodeNameValue; break; case LOWORD(X509_OCTET_STRING): decodeFunc = CRYPT_AsnDecodeOctetString; break; case LOWORD(X509_BITS): case LOWORD(X509_KEY_USAGE): decodeFunc = CRYPT_AsnDecodeBits; break; case LOWORD(X509_INTEGER): decodeFunc = CRYPT_AsnDecodeInt; break; case LOWORD(X509_MULTI_BYTE_INTEGER): decodeFunc = CRYPT_AsnDecodeInteger; break; case LOWORD(X509_MULTI_BYTE_UINT): decodeFunc = CRYPT_AsnDecodeUnsignedInteger; break; case LOWORD(X509_ENUMERATED): decodeFunc = CRYPT_AsnDecodeEnumerated; break; case LOWORD(X509_CHOICE_OF_TIME): decodeFunc = CRYPT_AsnDecodeChoiceOfTime; break; case LOWORD(X509_AUTHORITY_KEY_ID2): decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2; break; case LOWORD(X509_AUTHORITY_INFO_ACCESS): decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess; break; case LOWORD(PKCS_CONTENT_INFO): decodeFunc = CRYPT_AsnDecodePKCSContentInfo; break; case LOWORD(X509_SEQUENCE_OF_ANY): decodeFunc = CRYPT_AsnDecodeSequenceOfAny; break; case LOWORD(PKCS_UTC_TIME): decodeFunc = CRYPT_AsnDecodeUtcTime; break; case LOWORD(X509_CRL_DIST_POINTS): decodeFunc = CRYPT_AsnDecodeCRLDistPoints; break; case LOWORD(X509_ENHANCED_KEY_USAGE): decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage; break; case LOWORD(PKCS_CTL): decodeFunc = CRYPT_AsnDecodeCTL; break; case LOWORD(PKCS_SMIME_CAPABILITIES): decodeFunc = CRYPT_AsnDecodeSMIMECapabilities; break; case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE): decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice; break; case LOWORD(PKCS_ATTRIBUTES): decodeFunc = CRYPT_AsnDecodePKCSAttributes; break; case LOWORD(X509_ISSUING_DIST_POINT): decodeFunc = CRYPT_AsnDecodeIssuingDistPoint; break; case LOWORD(X509_NAME_CONSTRAINTS): decodeFunc = CRYPT_AsnDecodeNameConstraints; break; case LOWORD(X509_POLICY_MAPPINGS): decodeFunc = CRYPT_AsnDecodeCertPolicyMappings; break; case LOWORD(X509_POLICY_CONSTRAINTS): decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints; break; case LOWORD(PKCS7_SIGNER_INFO): decodeFunc = CRYPT_AsnDecodePKCSSignerInfo; break; case LOWORD(CMS_SIGNER_INFO): decodeFunc = CRYPT_AsnDecodeCMSSignerInfo; break; case LOWORD(X509_OBJECT_IDENTIFIER): decodeFunc = CRYPT_AsnDecodeObjectIdentifier; break; case LOWORD(X509_ECC_SIGNATURE): decodeFunc = CRYPT_AsnDecodeEccSignature; break; } } else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS)) decodeFunc = CRYPT_AsnDecodeExtensions; else if (!strcmp(lpszStructType, szOID_RSA_signingTime)) decodeFunc = CRYPT_AsnDecodeUtcTime; else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities)) decodeFunc = CRYPT_AsnDecodeSMIMECapabilities; else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER)) decodeFunc = CRYPT_AsnDecodeAuthorityKeyId; else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS)) decodeFunc = CRYPT_AsnDecodeCertPolicyMappings; else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2)) decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2; else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE)) decodeFunc = CRYPT_AsnDecodeEnumerated; else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) decodeFunc = CRYPT_AsnDecodeBits; else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER)) decodeFunc = CRYPT_AsnDecodeOctetString; else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS)) decodeFunc = CRYPT_AsnDecodeBasicConstraints; else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) decodeFunc = CRYPT_AsnDecodeBasicConstraints2; else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) decodeFunc = CRYPT_AsnDecodeAltName; else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) decodeFunc = CRYPT_AsnDecodeAltName; else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION)) decodeFunc = CRYPT_AsnDecodeAltName; else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) decodeFunc = CRYPT_AsnDecodeAltName; else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) decodeFunc = CRYPT_AsnDecodeAltName; else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS)) decodeFunc = CRYPT_AsnDecodeCRLDistPoints; else if (!strcmp(lpszStructType, szOID_CERT_POLICIES)) decodeFunc = CRYPT_AsnDecodeCertPolicies; else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS)) decodeFunc = CRYPT_AsnDecodeCertPolicyMappings; else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS)) decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints; else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE)) decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage; else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT)) decodeFunc = CRYPT_AsnDecodeIssuingDistPoint; else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS)) decodeFunc = CRYPT_AsnDecodeNameConstraints; else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS)) decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess; else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice; else if (!strcmp(lpszStructType, szOID_CTL)) decodeFunc = CRYPT_AsnDecodeCTL; else if (!strcmp(lpszStructType, szOID_ECC_PUBLIC_KEY)) decodeFunc = CRYPT_AsnDecodeObjectIdentifier; return decodeFunc;}
static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc){ static HCRYPTOIDFUNCSET set = NULL; CryptDecodeObjectFunc decodeFunc = NULL;
if (!set) set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0); CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, (void **)&decodeFunc, hFunc); return decodeFunc;}
static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc){ static HCRYPTOIDFUNCSET set = NULL; CryptDecodeObjectExFunc decodeFunc = NULL;
if (!set) set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0); CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, (void **)&decodeFunc, hFunc); return decodeFunc;}
BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo){ return CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);}
BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo){ BOOL ret = FALSE; CryptDecodeObjectExFunc decodeFunc; HCRYPTOIDFUNCADDR hFunc = NULL;
TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n", dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
if (!pvStructInfo && !pcbStructInfo) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (cbEncoded > MAX_ENCODED_LEN) { SetLastError(CRYPT_E_ASN1_LARGE); return FALSE; }
SetLastError(NOERROR); if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) { if (!pvStructInfo) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } *(BYTE **)pvStructInfo = NULL; } decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType); if (!decodeFunc) { TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", debugstr_a(lpszStructType)); decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType, &hFunc); } if (decodeFunc) ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); else { CryptDecodeObjectFunc pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
/* Try CryptDecodeObject function. Don't call CryptDecodeObject * directly, as that could cause an infinite loop. */ if (pCryptDecodeObject) { if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) { ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo); if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, *pcbStructInfo))) { ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags, *(BYTE **)pvStructInfo, pcbStructInfo); if (!ret) CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo); } } else ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo); } } if (hFunc) CryptFreeOIDFunctionAddress(hFunc, 0); TRACE_(crypt)("returning %d\n", ret); return ret;}
BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX){ BOOL ret;
TRACE_(crypt)("(%p)\n", pPFX);
/* A PFX blob is an asn.1-encoded sequence, consisting of at least a * version integer of length 1 (3 encoded byes) and at least one other * datum (two encoded bytes), plus at least two bytes for the outer * sequence. Thus, even an empty PFX blob is at least 7 bytes in length. */ if (pPFX->cbData < 7) ret = FALSE; else if (pPFX->pbData[0] == ASN_SEQUENCE) { DWORD len;
if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len))) { BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
/* Need at least three bytes for the integer version */ if (pPFX->cbData < 1 + lenLen + 3) ret = FALSE; else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */ pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */ pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */ ret = FALSE; } } else ret = FALSE; return ret;}
HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, DWORD dwFlags){ FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags); return NULL;}
BOOL WINAPI PFXVerifyPassword(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, DWORD dwFlags){ FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags); return FALSE;}