12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799 |
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include "php.h"
- #include "php_ini.h"
- #include "php_openssl.h"
- #include "zend_exceptions.h"
- #include "ext/standard/file.h"
- #include "ext/standard/info.h"
- #include "ext/standard/php_fopen_wrappers.h"
- #include "ext/standard/md5.h"
- #include "ext/standard/base64.h"
- #ifdef PHP_WIN32
- # include "win32/winutil.h"
- #endif
- #include <openssl/evp.h>
- #include <openssl/bn.h>
- #include <openssl/rsa.h>
- #include <openssl/dsa.h>
- #include <openssl/dh.h>
- #include <openssl/x509.h>
- #include <openssl/x509v3.h>
- #include <openssl/crypto.h>
- #include <openssl/pem.h>
- #include <openssl/err.h>
- #include <openssl/conf.h>
- #include <openssl/rand.h>
- #include <openssl/ssl.h>
- #include <openssl/pkcs12.h>
- #include <openssl/cms.h>
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- #include <openssl/core_names.h>
- #include <openssl/param_build.h>
- #endif
- #include <time.h>
- #if (defined(PHP_WIN32) && defined(_MSC_VER) && _MSC_VER >= 1900)
- #define timezone _timezone
- #endif
- #define MIN_KEY_LENGTH 384
- #define OPENSSL_ALGO_SHA1 1
- #define OPENSSL_ALGO_MD5 2
- #define OPENSSL_ALGO_MD4 3
- #ifdef HAVE_OPENSSL_MD2_H
- #define OPENSSL_ALGO_MD2 4
- #endif
- #if PHP_OPENSSL_API_VERSION < 0x10100
- #define OPENSSL_ALGO_DSS1 5
- #endif
- #define OPENSSL_ALGO_SHA224 6
- #define OPENSSL_ALGO_SHA256 7
- #define OPENSSL_ALGO_SHA384 8
- #define OPENSSL_ALGO_SHA512 9
- #define OPENSSL_ALGO_RMD160 10
- #define DEBUG_SMIME 0
- #if !defined(OPENSSL_NO_EC) && defined(EVP_PKEY_EC)
- #define HAVE_EVP_PKEY_EC 1
- #endif
- #include "openssl_arginfo.h"
- ZEND_DECLARE_MODULE_GLOBALS(openssl)
- enum php_openssl_key_type {
- OPENSSL_KEYTYPE_RSA,
- OPENSSL_KEYTYPE_DSA,
- OPENSSL_KEYTYPE_DH,
- OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA,
- #ifdef HAVE_EVP_PKEY_EC
- OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH +1
- #endif
- };
- enum php_openssl_cipher_type {
- PHP_OPENSSL_CIPHER_RC2_40,
- PHP_OPENSSL_CIPHER_RC2_128,
- PHP_OPENSSL_CIPHER_RC2_64,
- PHP_OPENSSL_CIPHER_DES,
- PHP_OPENSSL_CIPHER_3DES,
- PHP_OPENSSL_CIPHER_AES_128_CBC,
- PHP_OPENSSL_CIPHER_AES_192_CBC,
- PHP_OPENSSL_CIPHER_AES_256_CBC,
- PHP_OPENSSL_CIPHER_DEFAULT = PHP_OPENSSL_CIPHER_AES_128_CBC
- };
- enum php_openssl_encoding {
- ENCODING_DER,
- ENCODING_SMIME,
- ENCODING_PEM,
- };
- zend_class_entry *php_openssl_certificate_ce;
- static zend_object_handlers php_openssl_certificate_object_handlers;
- static zend_object *php_openssl_certificate_create_object(zend_class_entry *class_type) {
- php_openssl_certificate_object *intern = zend_object_alloc(sizeof(php_openssl_certificate_object), class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
- intern->std.handlers = &php_openssl_certificate_object_handlers;
- return &intern->std;
- }
- static zend_function *php_openssl_certificate_get_constructor(zend_object *object) {
- zend_throw_error(NULL, "Cannot directly construct OpenSSLCertificate, use openssl_x509_read() instead");
- return NULL;
- }
- static void php_openssl_certificate_free_obj(zend_object *object)
- {
- php_openssl_certificate_object *x509_object = php_openssl_certificate_from_obj(object);
- X509_free(x509_object->x509);
- zend_object_std_dtor(&x509_object->std);
- }
- typedef struct _php_openssl_x509_request_object {
- X509_REQ *csr;
- zend_object std;
- } php_openssl_request_object;
- zend_class_entry *php_openssl_request_ce;
- static inline php_openssl_request_object *php_openssl_request_from_obj(zend_object *obj) {
- return (php_openssl_request_object *)((char *)(obj) - XtOffsetOf(php_openssl_request_object, std));
- }
- #define Z_OPENSSL_REQUEST_P(zv) php_openssl_request_from_obj(Z_OBJ_P(zv))
- static zend_object_handlers php_openssl_request_object_handlers;
- static zend_object *php_openssl_request_create_object(zend_class_entry *class_type) {
- php_openssl_request_object *intern = zend_object_alloc(sizeof(php_openssl_request_object), class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
- intern->std.handlers = &php_openssl_request_object_handlers;
- return &intern->std;
- }
- static zend_function *php_openssl_request_get_constructor(zend_object *object) {
- zend_throw_error(NULL, "Cannot directly construct OpenSSLCertificateSigningRequest, use openssl_csr_new() instead");
- return NULL;
- }
- static void php_openssl_request_free_obj(zend_object *object)
- {
- php_openssl_request_object *x509_request = php_openssl_request_from_obj(object);
- X509_REQ_free(x509_request->csr);
- zend_object_std_dtor(&x509_request->std);
- }
- typedef struct _php_openssl_pkey_object {
- EVP_PKEY *pkey;
- bool is_private;
- zend_object std;
- } php_openssl_pkey_object;
- zend_class_entry *php_openssl_pkey_ce;
- static inline php_openssl_pkey_object *php_openssl_pkey_from_obj(zend_object *obj) {
- return (php_openssl_pkey_object *)((char *)(obj) - XtOffsetOf(php_openssl_pkey_object, std));
- }
- #define Z_OPENSSL_PKEY_P(zv) php_openssl_pkey_from_obj(Z_OBJ_P(zv))
- static zend_object_handlers php_openssl_pkey_object_handlers;
- static zend_object *php_openssl_pkey_create_object(zend_class_entry *class_type) {
- php_openssl_pkey_object *intern = zend_object_alloc(sizeof(php_openssl_pkey_object), class_type);
- zend_object_std_init(&intern->std, class_type);
- object_properties_init(&intern->std, class_type);
- intern->std.handlers = &php_openssl_pkey_object_handlers;
- return &intern->std;
- }
- static void php_openssl_pkey_object_init(zval *zv, EVP_PKEY *pkey, bool is_private) {
- object_init_ex(zv, php_openssl_pkey_ce);
- php_openssl_pkey_object *obj = Z_OPENSSL_PKEY_P(zv);
- obj->pkey = pkey;
- obj->is_private = is_private;
- }
- static zend_function *php_openssl_pkey_get_constructor(zend_object *object) {
- zend_throw_error(NULL, "Cannot directly construct OpenSSLAsymmetricKey, use openssl_pkey_new() instead");
- return NULL;
- }
- static void php_openssl_pkey_free_obj(zend_object *object)
- {
- php_openssl_pkey_object *key_object = php_openssl_pkey_from_obj(object);
- EVP_PKEY_free(key_object->pkey);
- zend_object_std_dtor(&key_object->std);
- }
- zend_module_entry openssl_module_entry = {
- STANDARD_MODULE_HEADER,
- "openssl",
- ext_functions,
- PHP_MINIT(openssl),
- PHP_MSHUTDOWN(openssl),
- NULL,
- NULL,
- PHP_MINFO(openssl),
- PHP_OPENSSL_VERSION,
- PHP_MODULE_GLOBALS(openssl),
- PHP_GINIT(openssl),
- PHP_GSHUTDOWN(openssl),
- NULL,
- STANDARD_MODULE_PROPERTIES_EX
- };
- #ifdef COMPILE_DL_OPENSSL
- ZEND_GET_MODULE(openssl)
- #endif
- #if PHP_OPENSSL_API_VERSION < 0x10100
- #define EVP_PKEY_get0_RSA(_pkey) _pkey->pkey.rsa
- #define EVP_PKEY_get0_DH(_pkey) _pkey->pkey.dh
- #define EVP_PKEY_get0_DSA(_pkey) _pkey->pkey.dsa
- #define EVP_PKEY_get0_EC_KEY(_pkey) _pkey->pkey.ec
- static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
- {
- r->n = n;
- r->e = e;
- r->d = d;
- return 1;
- }
- static int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
- {
- r->p = p;
- r->q = q;
- return 1;
- }
- static int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
- {
- r->dmp1 = dmp1;
- r->dmq1 = dmq1;
- r->iqmp = iqmp;
- return 1;
- }
- static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
- {
- *n = r->n;
- *e = r->e;
- *d = r->d;
- }
- static void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
- {
- *p = r->p;
- *q = r->q;
- }
- static void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp)
- {
- *dmp1 = r->dmp1;
- *dmq1 = r->dmq1;
- *iqmp = r->iqmp;
- }
- static void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
- {
- *p = dh->p;
- *q = dh->q;
- *g = dh->g;
- }
- static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
- {
- dh->p = p;
- dh->q = q;
- dh->g = g;
- return 1;
- }
- static void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
- {
- *pub_key = dh->pub_key;
- *priv_key = dh->priv_key;
- }
- static int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
- {
- dh->pub_key = pub_key;
- dh->priv_key = priv_key;
- return 1;
- }
- static void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
- {
- *p = d->p;
- *q = d->q;
- *g = d->g;
- }
- int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
- {
- d->p = p;
- d->q = q;
- d->g = g;
- return 1;
- }
- static void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)
- {
- *pub_key = d->pub_key;
- *priv_key = d->priv_key;
- }
- int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
- {
- d->pub_key = pub_key;
- d->priv_key = priv_key;
- return 1;
- }
- static const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1)
- {
- return M_ASN1_STRING_data(asn1);
- }
- static int EVP_PKEY_up_ref(EVP_PKEY *pkey)
- {
- return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
- }
- #if PHP_OPENSSL_API_VERSION < 0x10002
- static int X509_get_signature_nid(const X509 *x)
- {
- return OBJ_obj2nid(x->sig_alg->algorithm);
- }
- #endif
- #define OpenSSL_version SSLeay_version
- #define OPENSSL_VERSION SSLEAY_VERSION
- #define X509_getm_notBefore X509_get_notBefore
- #define X509_getm_notAfter X509_get_notAfter
- #define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_cleanup
- #endif
- #define PHP_OPENSSL_CHECK_NUMBER_CONVERSION(_cond, _name, _arg_num) \
- do { \
- if (_cond) { \
- zend_argument_value_error((_arg_num), #_name" is too long"); \
- RETURN_THROWS(); \
- } \
- } while(0)
- #define PHP_OPENSSL_CHECK_NUMBER_CONVERSION_NULL_RETURN(_cond, _name) \
- do { \
- if (_cond) { \
- zend_value_error(#_name" is too long"); \
- return NULL; \
- } \
- } while(0)
- #define PHP_OPENSSL_CHECK_SIZE_T_TO_INT(_var, _name, _arg_num) \
- PHP_OPENSSL_CHECK_NUMBER_CONVERSION(ZEND_SIZE_T_INT_OVFL(_var), _name, _arg_num)
- #define PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(_var, _name) \
- PHP_OPENSSL_CHECK_NUMBER_CONVERSION_NULL_RETURN(ZEND_SIZE_T_INT_OVFL(_var), _name)
- #define PHP_OPENSSL_CHECK_SIZE_T_TO_UINT(_var, _name, _arg_num) \
- PHP_OPENSSL_CHECK_NUMBER_CONVERSION(ZEND_SIZE_T_UINT_OVFL(_var), _name, _arg_num)
- #define PHP_OPENSSL_CHECK_LONG_TO_INT(_var, _name, _arg_num) \
- PHP_OPENSSL_CHECK_NUMBER_CONVERSION(ZEND_LONG_EXCEEDS_INT(_var), _name, _arg_num)
- #define PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(_var, _name) \
- PHP_OPENSSL_CHECK_NUMBER_CONVERSION_NULL_RETURN(ZEND_LONG_EXCEEDS_INT(_var), _name)
- void php_openssl_store_errors()
- {
- struct php_openssl_errors *errors;
- int error_code = ERR_get_error();
- if (!error_code) {
- return;
- }
- if (!OPENSSL_G(errors)) {
- OPENSSL_G(errors) = pecalloc(1, sizeof(struct php_openssl_errors), 1);
- }
- errors = OPENSSL_G(errors);
- do {
- errors->top = (errors->top + 1) % ERR_NUM_ERRORS;
- if (errors->top == errors->bottom) {
- errors->bottom = (errors->bottom + 1) % ERR_NUM_ERRORS;
- }
- errors->buffer[errors->top] = error_code;
- } while ((error_code = ERR_get_error()));
- }
- static void php_openssl_check_path_error(uint32_t arg_num, int type, const char *format, ...)
- {
- va_list va;
- const char *arg_name;
- va_start(va, format);
- if (type == E_ERROR) {
- zend_argument_error_variadic(zend_ce_value_error, arg_num, format, va);
- } else {
- arg_name = get_active_function_arg_name(arg_num);
- php_verror(NULL, arg_name, type, format, va);
- }
- va_end(va);
- }
- static bool php_openssl_check_path_ex(
- const char *file_path, size_t file_path_len, char *real_path, uint32_t arg_num,
- bool contains_file_protocol, bool is_from_array, const char *option_name)
- {
- const char *fs_file_path;
- size_t fs_file_path_len;
- const char *error_msg = NULL;
- int error_type = E_WARNING;
- if (file_path_len == 0) {
- real_path[0] = '\0';
- return true;
- }
- if (contains_file_protocol) {
- size_t path_prefix_len = sizeof("file://") - 1;
- if (file_path_len <= path_prefix_len) {
- return false;
- }
- fs_file_path = file_path + path_prefix_len;
- fs_file_path_len = file_path_len - path_prefix_len;
- } else {
- fs_file_path = file_path;
- fs_file_path_len = file_path_len;
- }
- if (CHECK_NULL_PATH(fs_file_path, fs_file_path_len)) {
- error_msg = "must not contain any null bytes";
- error_type = E_ERROR;
- } else if (expand_filepath(fs_file_path, real_path) == NULL) {
- error_msg = "must be a valid file path";
- }
- if (error_msg != NULL) {
- if (arg_num == 0) {
- const char *option_title = option_name ? option_name : "unknown";
- const char *option_label = is_from_array ? "array item" : "option";
- php_error_docref(NULL, E_WARNING, "Path for %s %s %s",
- option_title, option_label, error_msg);
- } else if (is_from_array && option_name != NULL) {
- php_openssl_check_path_error(
- arg_num, error_type, "option %s array item %s", option_name, error_msg);
- } else if (is_from_array) {
- php_openssl_check_path_error(arg_num, error_type, "array item %s", error_msg);
- } else if (option_name != NULL) {
- php_openssl_check_path_error(
- arg_num, error_type, "option %s %s", option_name, error_msg);
- } else {
- php_openssl_check_path_error(arg_num, error_type, "%s", error_msg);
- }
- } else if (!php_check_open_basedir(real_path)) {
- return true;
- }
- return false;
- }
- static inline bool php_openssl_check_path(
- const char *file_path, size_t file_path_len, char *real_path, uint32_t arg_num)
- {
- return php_openssl_check_path_ex(
- file_path, file_path_len, real_path, arg_num, false, false, NULL);
- }
- static inline bool php_openssl_check_path_str_ex(
- zend_string *file_path, char *real_path, uint32_t arg_num,
- bool contains_file_protocol, bool is_from_array, const char *option_name)
- {
- return php_openssl_check_path_ex(
- ZSTR_VAL(file_path), ZSTR_LEN(file_path), real_path, arg_num, contains_file_protocol,
- is_from_array, option_name);
- }
- static inline bool php_openssl_check_path_str(
- zend_string *file_path, char *real_path, uint32_t arg_num)
- {
- return php_openssl_check_path_str_ex(file_path, real_path, arg_num, true, false, NULL);
- }
- static int ssl_stream_data_index;
- php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl)
- {
- return (php_stream*)SSL_get_ex_data(ssl, ssl_stream_data_index);
- }
- int php_openssl_get_ssl_stream_data_index(void)
- {
- return ssl_stream_data_index;
- }
- static char default_ssl_conf_filename[MAXPATHLEN];
- struct php_x509_request {
- CONF *global_config;
- CONF *req_config;
- const EVP_MD * md_alg;
- const EVP_MD * digest;
- char * section_name,
- * config_filename,
- * digest_name,
- * extensions_section,
- * request_extensions_section;
- int priv_key_bits;
- int priv_key_type;
- int priv_key_encrypt;
- #ifdef HAVE_EVP_PKEY_EC
- int curve_name;
- #endif
- EVP_PKEY * priv_key;
- const EVP_CIPHER * priv_key_encrypt_cipher;
- };
- static X509 *php_openssl_x509_from_param(
- zend_object *cert_obj, zend_string *cert_str, uint32_t arg_num);
- static X509 *php_openssl_x509_from_zval(
- zval *val, bool *free_cert, uint32_t arg_num, bool is_from_array, const char *option_name);
- static X509_REQ *php_openssl_csr_from_param(
- zend_object *csr_obj, zend_string *csr_str, uint32_t arg_num);
- static EVP_PKEY *php_openssl_pkey_from_zval(
- zval *val, int public_key, char *passphrase, size_t passphrase_len, uint32_t arg_num);
- static X509_STORE * php_openssl_setup_verify(zval * calist, uint32_t arg_num);
- static STACK_OF(X509) * php_openssl_load_all_certs_from_file(
- char *cert_file, size_t cert_file_len, uint32_t arg_num);
- static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req);
- static void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname)
- {
- zval *data;
- zval subitem, tmp;
- int i;
- char *sname;
- int nid;
- X509_NAME_ENTRY * ne;
- ASN1_STRING * str = NULL;
- ASN1_OBJECT * obj;
- if (key != NULL) {
- array_init(&subitem);
- } else {
- ZVAL_COPY_VALUE(&subitem, val);
- }
- for (i = 0; i < X509_NAME_entry_count(name); i++) {
- const unsigned char *to_add = NULL;
- int to_add_len = 0;
- unsigned char *to_add_buf = NULL;
- ne = X509_NAME_get_entry(name, i);
- obj = X509_NAME_ENTRY_get_object(ne);
- nid = OBJ_obj2nid(obj);
- if (shortname) {
- sname = (char *) OBJ_nid2sn(nid);
- } else {
- sname = (char *) OBJ_nid2ln(nid);
- }
- str = X509_NAME_ENTRY_get_data(ne);
- if (ASN1_STRING_type(str) != V_ASN1_UTF8STRING) {
-
- to_add_len = ASN1_STRING_to_UTF8(&to_add_buf, str);
- to_add = to_add_buf;
- } else {
-
- to_add = ASN1_STRING_get0_data(str);
- to_add_len = ASN1_STRING_length(str);
- }
- if (to_add_len != -1) {
- if ((data = zend_hash_str_find(Z_ARRVAL(subitem), sname, strlen(sname))) != NULL) {
- if (Z_TYPE_P(data) == IS_ARRAY) {
- add_next_index_stringl(data, (const char *)to_add, to_add_len);
- } else if (Z_TYPE_P(data) == IS_STRING) {
- array_init(&tmp);
- add_next_index_str(&tmp, zend_string_copy(Z_STR_P(data)));
- add_next_index_stringl(&tmp, (const char *)to_add, to_add_len);
- zend_hash_str_update(Z_ARRVAL(subitem), sname, strlen(sname), &tmp);
- }
- } else {
-
- add_assoc_stringl(&subitem, sname, (char *)to_add, to_add_len);
- }
- } else {
- php_openssl_store_errors();
- }
- if (to_add_buf != NULL) {
- OPENSSL_free(to_add_buf);
- }
- }
- if (key != NULL) {
- zend_hash_str_update(Z_ARRVAL_P(val), key, strlen(key), &subitem);
- }
- }
- static void php_openssl_add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str)
- {
- add_assoc_stringl(val, key, (char *)str->data, str->length);
- }
- static time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr)
- {
- time_t ret;
- struct tm thetime;
- char * strbuf;
- char * thestr;
- long gmadjust = 0;
- size_t timestr_len;
- if (ASN1_STRING_type(timestr) != V_ASN1_UTCTIME && ASN1_STRING_type(timestr) != V_ASN1_GENERALIZEDTIME) {
- php_error_docref(NULL, E_WARNING, "Illegal ASN1 data type for timestamp");
- return (time_t)-1;
- }
- timestr_len = (size_t)ASN1_STRING_length(timestr);
- if (timestr_len != strlen((const char *)ASN1_STRING_get0_data(timestr))) {
- php_error_docref(NULL, E_WARNING, "Illegal length in timestamp");
- return (time_t)-1;
- }
- if (timestr_len < 13 && timestr_len != 11) {
- php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data);
- return (time_t)-1;
- }
- if (ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME && timestr_len < 15) {
- php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data);
- return (time_t)-1;
- }
- strbuf = estrdup((const char *)ASN1_STRING_get0_data(timestr));
- memset(&thetime, 0, sizeof(thetime));
-
- thestr = strbuf + timestr_len - 3;
- if (timestr_len == 11) {
- thetime.tm_sec = 0;
- } else {
- thetime.tm_sec = atoi(thestr);
- *thestr = '\0';
- thestr -= 2;
- }
- thetime.tm_min = atoi(thestr);
- *thestr = '\0';
- thestr -= 2;
- thetime.tm_hour = atoi(thestr);
- *thestr = '\0';
- thestr -= 2;
- thetime.tm_mday = atoi(thestr);
- *thestr = '\0';
- thestr -= 2;
- thetime.tm_mon = atoi(thestr)-1;
- *thestr = '\0';
- if( ASN1_STRING_type(timestr) == V_ASN1_UTCTIME ) {
- thestr -= 2;
- thetime.tm_year = atoi(thestr);
- if (thetime.tm_year < 68) {
- thetime.tm_year += 100;
- }
- } else if( ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME ) {
- thestr -= 4;
- thetime.tm_year = atoi(thestr) - 1900;
- }
- thetime.tm_isdst = -1;
- ret = mktime(&thetime);
- #ifdef HAVE_STRUCT_TM_TM_GMTOFF
- gmadjust = thetime.tm_gmtoff;
- #else
-
- gmadjust = -(thetime.tm_isdst ? (long)timezone - 3600 : (long)timezone);
- #endif
- ret += gmadjust;
- efree(strbuf);
- return ret;
- }
- static inline int php_openssl_config_check_syntax(const char * section_label, const char * config_filename, const char * section, CONF *config)
- {
- X509V3_CTX ctx;
- X509V3_set_ctx_test(&ctx);
- X509V3_set_nconf(&ctx, config);
- if (!X509V3_EXT_add_nconf(config, &ctx, (char *)section, NULL)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error loading %s section %s of %s",
- section_label,
- section,
- config_filename);
- return FAILURE;
- }
- return SUCCESS;
- }
- static char *php_openssl_conf_get_string(CONF *conf, const char *group, const char *name) {
-
- ERR_set_mark();
- char *str = NCONF_get_string(conf, group, name);
- ERR_pop_to_mark();
- return str;
- }
- static long php_openssl_conf_get_number(CONF *conf, const char *group, const char *name) {
-
- long res = 0;
- ERR_set_mark();
- NCONF_get_number(conf, group, name, &res);
- ERR_pop_to_mark();
- return res;
- }
- static int php_openssl_add_oid_section(struct php_x509_request * req)
- {
- char * str;
- STACK_OF(CONF_VALUE) * sktmp;
- CONF_VALUE * cnf;
- int i;
- str = php_openssl_conf_get_string(req->req_config, NULL, "oid_section");
- if (str == NULL) {
- return SUCCESS;
- }
- sktmp = NCONF_get_section(req->req_config, str);
- if (sktmp == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Problem loading oid section %s", str);
- return FAILURE;
- }
- for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
- cnf = sk_CONF_VALUE_value(sktmp, i);
- if (OBJ_sn2nid(cnf->name) == NID_undef && OBJ_ln2nid(cnf->name) == NID_undef &&
- OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Problem creating object %s=%s", cnf->name, cnf->value);
- return FAILURE;
- }
- }
- return SUCCESS;
- }
- #define PHP_SSL_REQ_INIT(req) memset(req, 0, sizeof(*req))
- #define PHP_SSL_REQ_DISPOSE(req) php_openssl_dispose_config(req)
- #define PHP_SSL_REQ_PARSE(req, zval) php_openssl_parse_config(req, zval)
- #define PHP_SSL_CONFIG_SYNTAX_CHECK(var) if (req->var && php_openssl_config_check_syntax(#var, \
- req->config_filename, req->var, req->req_config) == FAILURE) return FAILURE
- #define SET_OPTIONAL_STRING_ARG(key, varname, defval) \
- do { \
- if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), key, sizeof(key)-1)) != NULL && Z_TYPE_P(item) == IS_STRING) { \
- varname = Z_STRVAL_P(item); \
- } else { \
- varname = defval; \
- if (varname == NULL) { \
- php_openssl_store_errors(); \
- } \
- } \
- } while(0)
- #define SET_OPTIONAL_LONG_ARG(key, varname, defval) \
- if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), key, sizeof(key)-1)) != NULL && Z_TYPE_P(item) == IS_LONG) \
- varname = (int)Z_LVAL_P(item); \
- else \
- varname = defval
- static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo);
- static int php_openssl_spki_cleanup(const char *src, char *dest)
- {
- int removed = 0;
- while (*src) {
- if (*src != '\n' && *src != '\r') {
- *dest++ = *src;
- } else {
- ++removed;
- }
- ++src;
- }
- *dest = 0;
- return removed;
- }
- static int php_openssl_parse_config(struct php_x509_request * req, zval * optional_args)
- {
- char * str, path[MAXPATHLEN];
- zval * item;
- SET_OPTIONAL_STRING_ARG("config", req->config_filename, default_ssl_conf_filename);
- SET_OPTIONAL_STRING_ARG("config_section_name", req->section_name, "req");
- req->global_config = NCONF_new(NULL);
- if (!NCONF_load(req->global_config, default_ssl_conf_filename, NULL)) {
- php_openssl_store_errors();
- }
- req->req_config = NCONF_new(NULL);
- if (!NCONF_load(req->req_config, req->config_filename, NULL)) {
- return FAILURE;
- }
-
- str = php_openssl_conf_get_string(req->req_config, NULL, "oid_file");
- if (str != NULL && php_openssl_check_path_ex(str, strlen(str), path, 0, false, false, "oid_file")) {
- BIO *oid_bio = BIO_new_file(path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
- if (oid_bio) {
- OBJ_create_objects(oid_bio);
- BIO_free(oid_bio);
- php_openssl_store_errors();
- }
- }
- if (php_openssl_add_oid_section(req) == FAILURE) {
- return FAILURE;
- }
- SET_OPTIONAL_STRING_ARG("digest_alg", req->digest_name,
- php_openssl_conf_get_string(req->req_config, req->section_name, "default_md"));
- SET_OPTIONAL_STRING_ARG("x509_extensions", req->extensions_section,
- php_openssl_conf_get_string(req->req_config, req->section_name, "x509_extensions"));
- SET_OPTIONAL_STRING_ARG("req_extensions", req->request_extensions_section,
- php_openssl_conf_get_string(req->req_config, req->section_name, "req_extensions"));
- SET_OPTIONAL_LONG_ARG("private_key_bits", req->priv_key_bits,
- php_openssl_conf_get_number(req->req_config, req->section_name, "default_bits"));
- SET_OPTIONAL_LONG_ARG("private_key_type", req->priv_key_type, OPENSSL_KEYTYPE_DEFAULT);
- if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "encrypt_key", sizeof("encrypt_key")-1)) != NULL) {
- req->priv_key_encrypt = Z_TYPE_P(item) == IS_TRUE ? 1 : 0;
- } else {
- str = php_openssl_conf_get_string(req->req_config, req->section_name, "encrypt_rsa_key");
- if (str == NULL) {
- str = php_openssl_conf_get_string(req->req_config, req->section_name, "encrypt_key");
- }
- if (str != NULL && strcmp(str, "no") == 0) {
- req->priv_key_encrypt = 0;
- } else {
- req->priv_key_encrypt = 1;
- }
- }
- if (req->priv_key_encrypt &&
- optional_args &&
- (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "encrypt_key_cipher", sizeof("encrypt_key_cipher")-1)) != NULL &&
- Z_TYPE_P(item) == IS_LONG
- ) {
- zend_long cipher_algo = Z_LVAL_P(item);
- const EVP_CIPHER* cipher = php_openssl_get_evp_cipher_from_algo(cipher_algo);
- if (cipher == NULL) {
- php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm for private key");
- return FAILURE;
- } else {
- req->priv_key_encrypt_cipher = cipher;
- }
- } else {
- req->priv_key_encrypt_cipher = NULL;
- }
-
- if (req->digest_name == NULL) {
- req->digest_name = php_openssl_conf_get_string(req->req_config, req->section_name, "default_md");
- }
- if (req->digest_name != NULL) {
- req->digest = req->md_alg = EVP_get_digestbyname(req->digest_name);
- }
- if (req->md_alg == NULL) {
- req->md_alg = req->digest = EVP_sha1();
- php_openssl_store_errors();
- }
- PHP_SSL_CONFIG_SYNTAX_CHECK(extensions_section);
- #ifdef HAVE_EVP_PKEY_EC
-
- req->curve_name = NID_undef;
- if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "curve_name", sizeof("curve_name")-1)) != NULL
- && Z_TYPE_P(item) == IS_STRING) {
- req->curve_name = OBJ_sn2nid(Z_STRVAL_P(item));
- if (req->curve_name == NID_undef) {
- php_error_docref(NULL, E_WARNING, "Unknown elliptic curve (short) name %s", Z_STRVAL_P(item));
- return FAILURE;
- }
- }
- #endif
-
- str = php_openssl_conf_get_string(req->req_config, req->section_name, "string_mask");
- if (str != NULL && !ASN1_STRING_set_default_mask_asc(str)) {
- php_error_docref(NULL, E_WARNING, "Invalid global string mask setting %s", str);
- return FAILURE;
- }
- PHP_SSL_CONFIG_SYNTAX_CHECK(request_extensions_section);
- return SUCCESS;
- }
- static void php_openssl_dispose_config(struct php_x509_request * req)
- {
- if (req->priv_key) {
- EVP_PKEY_free(req->priv_key);
- req->priv_key = NULL;
- }
- if (req->global_config) {
- NCONF_free(req->global_config);
- req->global_config = NULL;
- }
- if (req->req_config) {
- NCONF_free(req->req_config);
- req->req_config = NULL;
- }
- }
- #if defined(PHP_WIN32) || PHP_OPENSSL_API_VERSION >= 0x10100
- #define PHP_OPENSSL_RAND_ADD_TIME() ((void) 0)
- #else
- #define PHP_OPENSSL_RAND_ADD_TIME() php_openssl_rand_add_timeval()
- static inline void php_openssl_rand_add_timeval(void)
- {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- RAND_add(&tv, sizeof(tv), 0.0);
- }
- #endif
- static int php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded)
- {
- char buffer[MAXPATHLEN];
- *egdsocket = 0;
- *seeded = 0;
- if (file == NULL) {
- file = RAND_file_name(buffer, sizeof(buffer));
- #ifdef HAVE_RAND_EGD
- } else if (RAND_egd(file) > 0) {
-
- *egdsocket = 1;
- return SUCCESS;
- #endif
- }
- if (file == NULL || !RAND_load_file(file, -1)) {
- if (RAND_status() == 0) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to load random state; not enough random data!");
- return FAILURE;
- }
- return FAILURE;
- }
- *seeded = 1;
- return SUCCESS;
- }
- static int php_openssl_write_rand_file(const char * file, int egdsocket, int seeded)
- {
- char buffer[MAXPATHLEN];
- if (egdsocket || !seeded) {
-
- return FAILURE;
- }
- if (file == NULL) {
- file = RAND_file_name(buffer, sizeof(buffer));
- }
- PHP_OPENSSL_RAND_ADD_TIME();
- if (file == NULL || !RAND_write_file(file)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to write random state");
- return FAILURE;
- }
- return SUCCESS;
- }
- static EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo) {
- EVP_MD *mdtype;
- switch (algo) {
- case OPENSSL_ALGO_SHA1:
- mdtype = (EVP_MD *) EVP_sha1();
- break;
- case OPENSSL_ALGO_MD5:
- mdtype = (EVP_MD *) EVP_md5();
- break;
- case OPENSSL_ALGO_MD4:
- mdtype = (EVP_MD *) EVP_md4();
- break;
- #ifdef HAVE_OPENSSL_MD2_H
- case OPENSSL_ALGO_MD2:
- mdtype = (EVP_MD *) EVP_md2();
- break;
- #endif
- #if PHP_OPENSSL_API_VERSION < 0x10100
- case OPENSSL_ALGO_DSS1:
- mdtype = (EVP_MD *) EVP_dss1();
- break;
- #endif
- case OPENSSL_ALGO_SHA224:
- mdtype = (EVP_MD *) EVP_sha224();
- break;
- case OPENSSL_ALGO_SHA256:
- mdtype = (EVP_MD *) EVP_sha256();
- break;
- case OPENSSL_ALGO_SHA384:
- mdtype = (EVP_MD *) EVP_sha384();
- break;
- case OPENSSL_ALGO_SHA512:
- mdtype = (EVP_MD *) EVP_sha512();
- break;
- case OPENSSL_ALGO_RMD160:
- mdtype = (EVP_MD *) EVP_ripemd160();
- break;
- default:
- return NULL;
- break;
- }
- return mdtype;
- }
- static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo) {
- switch (algo) {
- #ifndef OPENSSL_NO_RC2
- case PHP_OPENSSL_CIPHER_RC2_40:
- return EVP_rc2_40_cbc();
- break;
- case PHP_OPENSSL_CIPHER_RC2_64:
- return EVP_rc2_64_cbc();
- break;
- case PHP_OPENSSL_CIPHER_RC2_128:
- return EVP_rc2_cbc();
- break;
- #endif
- #ifndef OPENSSL_NO_DES
- case PHP_OPENSSL_CIPHER_DES:
- return EVP_des_cbc();
- break;
- case PHP_OPENSSL_CIPHER_3DES:
- return EVP_des_ede3_cbc();
- break;
- #endif
- #ifndef OPENSSL_NO_AES
- case PHP_OPENSSL_CIPHER_AES_128_CBC:
- return EVP_aes_128_cbc();
- break;
- case PHP_OPENSSL_CIPHER_AES_192_CBC:
- return EVP_aes_192_cbc();
- break;
- case PHP_OPENSSL_CIPHER_AES_256_CBC:
- return EVP_aes_256_cbc();
- break;
- #endif
- default:
- return NULL;
- break;
- }
- }
- PHP_INI_BEGIN()
- PHP_INI_ENTRY("openssl.cafile", NULL, PHP_INI_PERDIR, NULL)
- PHP_INI_ENTRY("openssl.capath", NULL, PHP_INI_PERDIR, NULL)
- PHP_INI_END()
- PHP_MINIT_FUNCTION(openssl)
- {
- char * config_filename;
- php_openssl_certificate_ce = register_class_OpenSSLCertificate();
- php_openssl_certificate_ce->create_object = php_openssl_certificate_create_object;
- memcpy(&php_openssl_certificate_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
- php_openssl_certificate_object_handlers.offset = XtOffsetOf(php_openssl_certificate_object, std);
- php_openssl_certificate_object_handlers.free_obj = php_openssl_certificate_free_obj;
- php_openssl_certificate_object_handlers.get_constructor = php_openssl_certificate_get_constructor;
- php_openssl_certificate_object_handlers.clone_obj = NULL;
- php_openssl_certificate_object_handlers.compare = zend_objects_not_comparable;
- php_openssl_request_ce = register_class_OpenSSLCertificateSigningRequest();
- php_openssl_request_ce->create_object = php_openssl_request_create_object;
- memcpy(&php_openssl_request_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
- php_openssl_request_object_handlers.offset = XtOffsetOf(php_openssl_request_object, std);
- php_openssl_request_object_handlers.free_obj = php_openssl_request_free_obj;
- php_openssl_request_object_handlers.get_constructor = php_openssl_request_get_constructor;
- php_openssl_request_object_handlers.clone_obj = NULL;
- php_openssl_request_object_handlers.compare = zend_objects_not_comparable;
- php_openssl_pkey_ce = register_class_OpenSSLAsymmetricKey();
- php_openssl_pkey_ce->create_object = php_openssl_pkey_create_object;
- memcpy(&php_openssl_pkey_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
- php_openssl_pkey_object_handlers.offset = XtOffsetOf(php_openssl_pkey_object, std);
- php_openssl_pkey_object_handlers.free_obj = php_openssl_pkey_free_obj;
- php_openssl_pkey_object_handlers.get_constructor = php_openssl_pkey_get_constructor;
- php_openssl_pkey_object_handlers.clone_obj = NULL;
- php_openssl_pkey_object_handlers.compare = zend_objects_not_comparable;
- #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
- OPENSSL_config(NULL);
- SSL_library_init();
- OpenSSL_add_all_ciphers();
- OpenSSL_add_all_digests();
- OpenSSL_add_all_algorithms();
- SSL_load_error_strings();
- #else
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
- #endif
-
- ssl_stream_data_index = SSL_get_ex_new_index(0, "PHP stream index", NULL, NULL, NULL);
- REGISTER_STRING_CONSTANT("OPENSSL_VERSION_TEXT", OPENSSL_VERSION_TEXT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_VERSION_NUMBER", OPENSSL_VERSION_NUMBER, CONST_CS|CONST_PERSISTENT);
-
- REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_CLIENT", X509_PURPOSE_SSL_CLIENT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_SERVER", X509_PURPOSE_SSL_SERVER, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("X509_PURPOSE_NS_SSL_SERVER", X509_PURPOSE_NS_SSL_SERVER, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("X509_PURPOSE_SMIME_SIGN", X509_PURPOSE_SMIME_SIGN, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("X509_PURPOSE_SMIME_ENCRYPT", X509_PURPOSE_SMIME_ENCRYPT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("X509_PURPOSE_CRL_SIGN", X509_PURPOSE_CRL_SIGN, CONST_CS|CONST_PERSISTENT);
- #ifdef X509_PURPOSE_ANY
- REGISTER_LONG_CONSTANT("X509_PURPOSE_ANY", X509_PURPOSE_ANY, CONST_CS|CONST_PERSISTENT);
- #endif
-
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA1", OPENSSL_ALGO_SHA1, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD5", OPENSSL_ALGO_MD5, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD4", OPENSSL_ALGO_MD4, CONST_CS|CONST_PERSISTENT);
- #ifdef HAVE_OPENSSL_MD2_H
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD2", OPENSSL_ALGO_MD2, CONST_CS|CONST_PERSISTENT);
- #endif
- #if PHP_OPENSSL_API_VERSION < 0x10100
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_DSS1", OPENSSL_ALGO_DSS1, CONST_CS|CONST_PERSISTENT);
- #endif
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA224", OPENSSL_ALGO_SHA224, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA256", OPENSSL_ALGO_SHA256, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA384", OPENSSL_ALGO_SHA384, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA512", OPENSSL_ALGO_SHA512, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ALGO_RMD160", OPENSSL_ALGO_RMD160, CONST_CS|CONST_PERSISTENT);
-
- REGISTER_LONG_CONSTANT("PKCS7_DETACHED", PKCS7_DETACHED, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_TEXT", PKCS7_TEXT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_NOINTERN", PKCS7_NOINTERN, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_NOVERIFY", PKCS7_NOVERIFY, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_NOCHAIN", PKCS7_NOCHAIN, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_NOCERTS", PKCS7_NOCERTS, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_NOATTR", PKCS7_NOATTR, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_BINARY", PKCS7_BINARY, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("PKCS7_NOSIGS", PKCS7_NOSIGS, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_DETACHED", CMS_DETACHED, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_TEXT", CMS_TEXT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOINTERN", CMS_NOINTERN, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOVERIFY", CMS_NOVERIFY, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOCERTS", CMS_NOCERTS, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOATTR", CMS_NOATTR, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_BINARY", CMS_BINARY, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOSIGS", CMS_NOSIGS, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT);
- #ifdef RSA_SSLV23_PADDING
- REGISTER_LONG_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT);
- #endif
- REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT);
-
- REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT);
-
- #ifndef OPENSSL_NO_RC2
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_40", PHP_OPENSSL_CIPHER_RC2_40, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_128", PHP_OPENSSL_CIPHER_RC2_128, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_64", PHP_OPENSSL_CIPHER_RC2_64, CONST_CS|CONST_PERSISTENT);
- #endif
- #ifndef OPENSSL_NO_DES
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_DES", PHP_OPENSSL_CIPHER_DES, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_3DES", PHP_OPENSSL_CIPHER_3DES, CONST_CS|CONST_PERSISTENT);
- #endif
- #ifndef OPENSSL_NO_AES
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_128_CBC", PHP_OPENSSL_CIPHER_AES_128_CBC, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_192_CBC", PHP_OPENSSL_CIPHER_AES_192_CBC, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_256_CBC", PHP_OPENSSL_CIPHER_AES_256_CBC, CONST_CS|CONST_PERSISTENT);
- #endif
-
- REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_RSA", OPENSSL_KEYTYPE_RSA, CONST_CS|CONST_PERSISTENT);
- #ifndef NO_DSA
- REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DSA", OPENSSL_KEYTYPE_DSA, CONST_CS|CONST_PERSISTENT);
- #endif
- REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DH", OPENSSL_KEYTYPE_DH, CONST_CS|CONST_PERSISTENT);
- #ifdef HAVE_EVP_PKEY_EC
- REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT);
- #endif
- REGISTER_LONG_CONSTANT("OPENSSL_RAW_DATA", OPENSSL_RAW_DATA, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ZERO_PADDING", OPENSSL_ZERO_PADDING, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_DONT_ZERO_PAD_KEY", OPENSSL_DONT_ZERO_PAD_KEY, CONST_CS|CONST_PERSISTENT);
- #ifndef OPENSSL_NO_TLSEXT
-
- REGISTER_LONG_CONSTANT("OPENSSL_TLSEXT_SERVER_NAME", 1, CONST_CS|CONST_PERSISTENT);
- #endif
-
- REGISTER_LONG_CONSTANT("OPENSSL_ENCODING_DER",ENCODING_DER,CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ENCODING_SMIME",ENCODING_SMIME,CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("OPENSSL_ENCODING_PEM",ENCODING_PEM,CONST_CS|CONST_PERSISTENT);
-
- config_filename = getenv("OPENSSL_CONF");
- if (config_filename == NULL) {
- config_filename = getenv("SSLEAY_CONF");
- }
-
- if (config_filename == NULL) {
- snprintf(default_ssl_conf_filename, sizeof(default_ssl_conf_filename), "%s/%s",
- X509_get_default_cert_area(),
- "openssl.cnf");
- } else {
- strlcpy(default_ssl_conf_filename, config_filename, sizeof(default_ssl_conf_filename));
- }
- php_stream_xport_register("ssl", php_openssl_ssl_socket_factory);
- #ifndef OPENSSL_NO_SSL3
- php_stream_xport_register("sslv3", php_openssl_ssl_socket_factory);
- #endif
- php_stream_xport_register("tls", php_openssl_ssl_socket_factory);
- php_stream_xport_register("tlsv1.0", php_openssl_ssl_socket_factory);
- php_stream_xport_register("tlsv1.1", php_openssl_ssl_socket_factory);
- php_stream_xport_register("tlsv1.2", php_openssl_ssl_socket_factory);
- #if OPENSSL_VERSION_NUMBER >= 0x10101000
- php_stream_xport_register("tlsv1.3", php_openssl_ssl_socket_factory);
- #endif
-
- php_stream_xport_register("tcp", php_openssl_ssl_socket_factory);
- php_register_url_stream_wrapper("https", &php_stream_http_wrapper);
- php_register_url_stream_wrapper("ftps", &php_stream_ftp_wrapper);
- REGISTER_INI_ENTRIES();
- return SUCCESS;
- }
- PHP_GINIT_FUNCTION(openssl)
- {
- #if defined(COMPILE_DL_OPENSSL) && defined(ZTS)
- ZEND_TSRMLS_CACHE_UPDATE();
- #endif
- openssl_globals->errors = NULL;
- }
- PHP_GSHUTDOWN_FUNCTION(openssl)
- {
- if (openssl_globals->errors) {
- pefree(openssl_globals->errors, 1);
- }
- }
- PHP_MINFO_FUNCTION(openssl)
- {
- php_info_print_table_start();
- php_info_print_table_row(2, "OpenSSL support", "enabled");
- php_info_print_table_row(2, "OpenSSL Library Version", OpenSSL_version(OPENSSL_VERSION));
- php_info_print_table_row(2, "OpenSSL Header Version", OPENSSL_VERSION_TEXT);
- php_info_print_table_row(2, "Openssl default config", default_ssl_conf_filename);
- php_info_print_table_end();
- DISPLAY_INI_ENTRIES();
- }
- PHP_MSHUTDOWN_FUNCTION(openssl)
- {
- #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
- EVP_cleanup();
-
- CRYPTO_set_locking_callback(NULL);
-
- ERR_free_strings();
- CONF_modules_free();
- #endif
- php_unregister_url_stream_wrapper("https");
- php_unregister_url_stream_wrapper("ftps");
- php_stream_xport_unregister("ssl");
- #ifndef OPENSSL_NO_SSL3
- php_stream_xport_unregister("sslv3");
- #endif
- php_stream_xport_unregister("tls");
- php_stream_xport_unregister("tlsv1.0");
- php_stream_xport_unregister("tlsv1.1");
- php_stream_xport_unregister("tlsv1.2");
- #if OPENSSL_VERSION_NUMBER >= 0x10101000
- php_stream_xport_unregister("tlsv1.3");
- #endif
-
- php_stream_xport_register("tcp", php_stream_generic_socket_factory);
- UNREGISTER_INI_ENTRIES();
- return SUCCESS;
- }
- PHP_FUNCTION(openssl_get_cert_locations)
- {
- if (zend_parse_parameters_none() == FAILURE) {
- RETURN_THROWS();
- }
- array_init(return_value);
- add_assoc_string(return_value, "default_cert_file", (char *) X509_get_default_cert_file());
- add_assoc_string(return_value, "default_cert_file_env", (char *) X509_get_default_cert_file_env());
- add_assoc_string(return_value, "default_cert_dir", (char *) X509_get_default_cert_dir());
- add_assoc_string(return_value, "default_cert_dir_env", (char *) X509_get_default_cert_dir_env());
- add_assoc_string(return_value, "default_private_dir", (char *) X509_get_default_private_dir());
- add_assoc_string(return_value, "default_default_cert_area", (char *) X509_get_default_cert_area());
- add_assoc_string(return_value, "ini_cafile",
- zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0));
- add_assoc_string(return_value, "ini_capath",
- zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0));
- }
- static X509 *php_openssl_x509_from_str(
- zend_string *cert_str, uint32_t arg_num, bool is_from_array, const char *option_name) {
- X509 *cert = NULL;
- char cert_path[MAXPATHLEN];
- BIO *in;
- if (ZSTR_LEN(cert_str) > 7 && memcmp(ZSTR_VAL(cert_str), "file://", sizeof("file://") - 1) == 0) {
- if (!php_openssl_check_path_str_ex(cert_str, cert_path, arg_num, true, is_from_array, option_name)) {
- return NULL;
- }
- in = BIO_new_file(cert_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
- if (in == NULL) {
- php_openssl_store_errors();
- return NULL;
- }
- cert = PEM_read_bio_X509(in, NULL, NULL, NULL);
- } else {
- in = BIO_new_mem_buf(ZSTR_VAL(cert_str), (int) ZSTR_LEN(cert_str));
- if (in == NULL) {
- php_openssl_store_errors();
- return NULL;
- }
- #ifdef TYPEDEF_D2I_OF
- cert = (X509 *) PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL);
- #else
- cert = (X509 *) PEM_ASN1_read_bio((char *(*)())d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL);
- #endif
- }
- if (!BIO_free(in)) {
- php_openssl_store_errors();
- }
- if (cert == NULL) {
- php_openssl_store_errors();
- return NULL;
- }
- return cert;
- }
- static X509 *php_openssl_x509_from_param(
- zend_object *cert_obj, zend_string *cert_str, uint32_t arg_num) {
- if (cert_obj) {
- return php_openssl_certificate_from_obj(cert_obj)->x509;
- }
- ZEND_ASSERT(cert_str);
- return php_openssl_x509_from_str(cert_str, arg_num, false, NULL);
- }
- static X509 *php_openssl_x509_from_zval(
- zval *val, bool *free_cert, uint32_t arg_num, bool is_from_array, const char *option_name)
- {
- if (Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val) == php_openssl_certificate_ce) {
- *free_cert = 0;
- return php_openssl_certificate_from_obj(Z_OBJ_P(val))->x509;
- }
- *free_cert = 1;
- if (!try_convert_to_string(val)) {
- return NULL;
- }
- return php_openssl_x509_from_str(Z_STR_P(val), arg_num, is_from_array, option_name);
- }
- PHP_FUNCTION(openssl_x509_export_to_file)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- bool notext = 1;
- BIO * bio_out;
- char * filename, file_path[MAXPATHLEN];
- size_t filename_len;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_PATH(filename, filename_len)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(notext)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- return;
- }
- if (!php_openssl_check_path(filename, filename_len, file_path, 2)) {
- return;
- }
- bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (bio_out) {
- if (!notext && !X509_print(bio_out, cert)) {
- php_openssl_store_errors();
- }
- if (!PEM_write_bio_X509(bio_out, cert)) {
- php_openssl_store_errors();
- }
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error opening file %s", file_path);
- }
- if (cert_str) {
- X509_free(cert);
- }
- if (!BIO_free(bio_out)) {
- php_openssl_store_errors();
- }
- }
- PHP_FUNCTION(openssl_spki_new)
- {
- size_t challenge_len;
- char * challenge = NULL, *spkstr = NULL;
- zend_string * s = NULL;
- const char *spkac = "SPKAC=";
- zend_long algo = OPENSSL_ALGO_MD5;
- zval *zpkey = NULL;
- EVP_PKEY *pkey = NULL;
- NETSCAPE_SPKI *spki=NULL;
- const EVP_MD *mdtype;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l", &zpkey, php_openssl_pkey_ce, &challenge, &challenge_len, &algo) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(challenge_len, challenge, 2);
- pkey = php_openssl_pkey_from_zval(zpkey, 0, challenge, challenge_len, 1);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Unable to use supplied private key");
- }
- goto cleanup;
- }
- mdtype = php_openssl_get_evp_md_from_algo(algo);
- if (!mdtype) {
- php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
- goto cleanup;
- }
- if ((spki = NETSCAPE_SPKI_new()) == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to create new SPKAC");
- goto cleanup;
- }
- if (challenge) {
- if (!ASN1_STRING_set(spki->spkac->challenge, challenge, (int)challenge_len)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to set challenge data");
- goto cleanup;
- }
- }
- if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to embed public key");
- goto cleanup;
- }
- if (!NETSCAPE_SPKI_sign(spki, pkey, mdtype)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to sign with specified digest algorithm");
- goto cleanup;
- }
- spkstr = NETSCAPE_SPKI_b64_encode(spki);
- if (!spkstr){
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to encode SPKAC");
- goto cleanup;
- }
- s = zend_string_alloc(strlen(spkac) + strlen(spkstr), 0);
- sprintf(ZSTR_VAL(s), "%s%s", spkac, spkstr);
- ZSTR_LEN(s) = strlen(ZSTR_VAL(s));
- OPENSSL_free(spkstr);
- RETVAL_STR(s);
- goto cleanup;
- cleanup:
- EVP_PKEY_free(pkey);
- if (spki != NULL) {
- NETSCAPE_SPKI_free(spki);
- }
- if (s && ZSTR_LEN(s) <= 0) {
- RETVAL_FALSE;
- }
- }
- PHP_FUNCTION(openssl_spki_verify)
- {
- size_t spkstr_len;
- int i = 0, spkstr_cleaned_len = 0;
- char *spkstr, * spkstr_cleaned = NULL;
- EVP_PKEY *pkey = NULL;
- NETSCAPE_SPKI *spki = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &spkstr, &spkstr_len) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- spkstr_cleaned = emalloc(spkstr_len + 1);
- spkstr_cleaned_len = (int)(spkstr_len - php_openssl_spki_cleanup(spkstr, spkstr_cleaned));
- if (spkstr_cleaned_len == 0) {
- php_error_docref(NULL, E_WARNING, "Invalid SPKAC");
- goto cleanup;
- }
- spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, spkstr_cleaned_len);
- if (spki == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to decode supplied SPKAC");
- goto cleanup;
- }
- pkey = X509_PUBKEY_get(spki->spkac->pubkey);
- if (pkey == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to acquire signed public key");
- goto cleanup;
- }
- i = NETSCAPE_SPKI_verify(spki, pkey);
- goto cleanup;
- cleanup:
- if (spki != NULL) {
- NETSCAPE_SPKI_free(spki);
- }
- EVP_PKEY_free(pkey);
- if (spkstr_cleaned != NULL) {
- efree(spkstr_cleaned);
- }
- if (i > 0) {
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- }
- PHP_FUNCTION(openssl_spki_export)
- {
- size_t spkstr_len;
- char *spkstr, * spkstr_cleaned = NULL, * s = NULL;
- int spkstr_cleaned_len;
- EVP_PKEY *pkey = NULL;
- NETSCAPE_SPKI *spki = NULL;
- BIO *out = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &spkstr, &spkstr_len) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- spkstr_cleaned = emalloc(spkstr_len + 1);
- spkstr_cleaned_len = (int)(spkstr_len - php_openssl_spki_cleanup(spkstr, spkstr_cleaned));
- if (spkstr_cleaned_len == 0) {
- php_error_docref(NULL, E_WARNING, "Invalid SPKAC");
- goto cleanup;
- }
- spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, spkstr_cleaned_len);
- if (spki == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to decode supplied SPKAC");
- goto cleanup;
- }
- pkey = X509_PUBKEY_get(spki->spkac->pubkey);
- if (pkey == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to acquire signed public key");
- goto cleanup;
- }
- out = BIO_new(BIO_s_mem());
- if (out && PEM_write_bio_PUBKEY(out, pkey)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(out, &bio_buf);
- RETVAL_STRINGL((char *)bio_buf->data, bio_buf->length);
- } else {
- php_openssl_store_errors();
- }
- goto cleanup;
- cleanup:
- if (spki != NULL) {
- NETSCAPE_SPKI_free(spki);
- }
- BIO_free_all(out);
- EVP_PKEY_free(pkey);
- if (spkstr_cleaned != NULL) {
- efree(spkstr_cleaned);
- }
- if (s != NULL) {
- efree(s);
- }
- }
- PHP_FUNCTION(openssl_spki_export_challenge)
- {
- size_t spkstr_len;
- char *spkstr, * spkstr_cleaned = NULL;
- int spkstr_cleaned_len;
- NETSCAPE_SPKI *spki = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &spkstr, &spkstr_len) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- spkstr_cleaned = emalloc(spkstr_len + 1);
- spkstr_cleaned_len = (int)(spkstr_len - php_openssl_spki_cleanup(spkstr, spkstr_cleaned));
- if (spkstr_cleaned_len == 0) {
- php_error_docref(NULL, E_WARNING, "Invalid SPKAC");
- goto cleanup;
- }
- spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, spkstr_cleaned_len);
- if (spki == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Unable to decode SPKAC");
- goto cleanup;
- }
- RETVAL_STRING((const char *)ASN1_STRING_get0_data(spki->spkac->challenge));
- goto cleanup;
- cleanup:
- if (spkstr_cleaned != NULL) {
- efree(spkstr_cleaned);
- }
- if (spki) {
- NETSCAPE_SPKI_free(spki);
- }
- }
- PHP_FUNCTION(openssl_x509_export)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- zval *zout;
- bool notext = 1;
- BIO * bio_out;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_ZVAL(zout)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(notext)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- return;
- }
- bio_out = BIO_new(BIO_s_mem());
- if (!bio_out) {
- php_openssl_store_errors();
- goto cleanup;
- }
- if (!notext && !X509_print(bio_out, cert)) {
- php_openssl_store_errors();
- }
- if (PEM_write_bio_X509(bio_out, cert)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZEND_TRY_ASSIGN_REF_STRINGL(zout, bio_buf->data, bio_buf->length);
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- BIO_free(bio_out);
- cleanup:
- if (cert_str) {
- X509_free(cert);
- }
- }
- zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool raw)
- {
- unsigned char md[EVP_MAX_MD_SIZE];
- const EVP_MD *mdtype;
- unsigned int n;
- zend_string *ret;
- if (!(mdtype = EVP_get_digestbyname(method))) {
- php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
- return NULL;
- } else if (!X509_digest(peer, mdtype, md, &n)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_ERROR, "Could not generate signature");
- return NULL;
- }
- if (raw) {
- ret = zend_string_init((char*)md, n, 0);
- } else {
- ret = zend_string_alloc(n * 2, 0);
- make_digest_ex(ZSTR_VAL(ret), md, n);
- ZSTR_VAL(ret)[n * 2] = '\0';
- }
- return ret;
- }
- PHP_FUNCTION(openssl_x509_fingerprint)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- bool raw_output = 0;
- char *method = "sha1";
- size_t method_len;
- zend_string *fingerprint;
- ZEND_PARSE_PARAMETERS_START(1, 3)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_OPTIONAL
- Z_PARAM_STRING(method, method_len)
- Z_PARAM_BOOL(raw_output)
- ZEND_PARSE_PARAMETERS_END();
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- RETURN_FALSE;
- }
- fingerprint = php_openssl_x509_fingerprint(cert, method, raw_output);
- if (fingerprint) {
- RETVAL_STR(fingerprint);
- } else {
- RETVAL_FALSE;
- }
- if (cert_str) {
- X509_free(cert);
- }
- }
- PHP_FUNCTION(openssl_x509_check_private_key)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- zval *zkey;
- EVP_PKEY * key = NULL;
- ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_ZVAL(zkey)
- ZEND_PARSE_PARAMETERS_END();
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- RETURN_FALSE;
- }
- RETVAL_FALSE;
- key = php_openssl_pkey_from_zval(zkey, 0, "", 0, 2);
- if (key) {
- RETVAL_BOOL(X509_check_private_key(cert, key));
- EVP_PKEY_free(key);
- }
- if (cert_str) {
- X509_free(cert);
- }
- }
- PHP_FUNCTION(openssl_x509_verify)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- zval *zkey;
- EVP_PKEY * key = NULL;
- int err = -1;
- ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_ZVAL(zkey)
- ZEND_PARSE_PARAMETERS_END();
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- RETURN_LONG(err);
- }
- key = php_openssl_pkey_from_zval(zkey, 1, NULL, 0, 2);
- if (key != NULL) {
- err = X509_verify(cert, key);
- if (err < 0) {
- php_openssl_store_errors();
- }
- EVP_PKEY_free(key);
- }
- if (cert_str) {
- X509_free(cert);
- }
- RETURN_LONG(err);
- }
- static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
- {
- GENERAL_NAMES *names;
- const X509V3_EXT_METHOD *method = NULL;
- ASN1_OCTET_STRING *extension_data;
- long i, length, num;
- const unsigned char *p;
- method = X509V3_EXT_get(extension);
- if (method == NULL) {
- return -1;
- }
- extension_data = X509_EXTENSION_get_data(extension);
- p = extension_data->data;
- length = extension_data->length;
- if (method->it) {
- names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, &p, length,
- ASN1_ITEM_ptr(method->it)));
- } else {
- names = (GENERAL_NAMES*) (method->d2i(NULL, &p, length));
- }
- if (names == NULL) {
- php_openssl_store_errors();
- return -1;
- }
- num = sk_GENERAL_NAME_num(names);
- for (i = 0; i < num; i++) {
- GENERAL_NAME *name;
- ASN1_STRING *as;
- name = sk_GENERAL_NAME_value(names, i);
- switch (name->type) {
- case GEN_EMAIL:
- BIO_puts(bio, "email:");
- as = name->d.rfc822Name;
- BIO_write(bio, ASN1_STRING_get0_data(as),
- ASN1_STRING_length(as));
- break;
- case GEN_DNS:
- BIO_puts(bio, "DNS:");
- as = name->d.dNSName;
- BIO_write(bio, ASN1_STRING_get0_data(as),
- ASN1_STRING_length(as));
- break;
- case GEN_URI:
- BIO_puts(bio, "URI:");
- as = name->d.uniformResourceIdentifier;
- BIO_write(bio, ASN1_STRING_get0_data(as),
- ASN1_STRING_length(as));
- break;
- default:
-
- GENERAL_NAME_print(bio, name);
- }
-
- if (i < (num - 1)) {
- BIO_puts(bio, ", ");
- }
- }
- sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
- return 0;
- }
- PHP_FUNCTION(openssl_x509_parse)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- int i, sig_nid;
- bool useshortnames = 1;
- char * tmpstr;
- zval subitem;
- X509_EXTENSION *extension;
- X509_NAME *subject_name;
- char *cert_name;
- char *extname;
- BIO *bio_out;
- BUF_MEM *bio_buf;
- ASN1_INTEGER *asn1_serial;
- BIGNUM *bn_serial;
- char *str_serial;
- char *hex_serial;
- char buf[256];
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(useshortnames)
- ZEND_PARSE_PARAMETERS_END();
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
-
- RETURN_FALSE;
- }
- array_init(return_value);
- subject_name = X509_get_subject_name(cert);
- cert_name = X509_NAME_oneline(subject_name, NULL, 0);
- add_assoc_string(return_value, "name", cert_name);
- OPENSSL_free(cert_name);
- php_openssl_add_assoc_name_entry(return_value, "subject", subject_name, useshortnames);
-
- {
- char buf[32];
- snprintf(buf, sizeof(buf), "%08lx", X509_subject_name_hash(cert));
- add_assoc_string(return_value, "hash", buf);
- }
- php_openssl_add_assoc_name_entry(return_value, "issuer", X509_get_issuer_name(cert), useshortnames);
- add_assoc_long(return_value, "version", X509_get_version(cert));
- asn1_serial = X509_get_serialNumber(cert);
- bn_serial = ASN1_INTEGER_to_BN(asn1_serial, NULL);
-
- if (!bn_serial) {
- php_openssl_store_errors();
- RETURN_FALSE;
- }
- hex_serial = BN_bn2hex(bn_serial);
- BN_free(bn_serial);
-
- if (!hex_serial) {
- php_openssl_store_errors();
- RETURN_FALSE;
- }
- str_serial = i2s_ASN1_INTEGER(NULL, asn1_serial);
- add_assoc_string(return_value, "serialNumber", str_serial);
- OPENSSL_free(str_serial);
-
- add_assoc_string(return_value, "serialNumberHex", hex_serial);
- OPENSSL_free(hex_serial);
- php_openssl_add_assoc_asn1_string(return_value, "validFrom", X509_getm_notBefore(cert));
- php_openssl_add_assoc_asn1_string(return_value, "validTo", X509_getm_notAfter(cert));
- add_assoc_long(return_value, "validFrom_time_t", php_openssl_asn1_time_to_time_t(X509_getm_notBefore(cert)));
- add_assoc_long(return_value, "validTo_time_t", php_openssl_asn1_time_to_time_t(X509_getm_notAfter(cert)));
- tmpstr = (char *)X509_alias_get0(cert, NULL);
- if (tmpstr) {
- add_assoc_string(return_value, "alias", tmpstr);
- }
- sig_nid = X509_get_signature_nid(cert);
- add_assoc_string(return_value, "signatureTypeSN", (char*)OBJ_nid2sn(sig_nid));
- add_assoc_string(return_value, "signatureTypeLN", (char*)OBJ_nid2ln(sig_nid));
- add_assoc_long(return_value, "signatureTypeNID", sig_nid);
- array_init(&subitem);
-
- for (i = 0; i < X509_PURPOSE_get_count(); i++) {
- int id, purpset;
- char * pname;
- X509_PURPOSE * purp;
- zval subsub;
- array_init(&subsub);
- purp = X509_PURPOSE_get0(i);
- id = X509_PURPOSE_get_id(purp);
- purpset = X509_check_purpose(cert, id, 0);
- add_index_bool(&subsub, 0, purpset);
- purpset = X509_check_purpose(cert, id, 1);
- add_index_bool(&subsub, 1, purpset);
- pname = useshortnames ? X509_PURPOSE_get0_sname(purp) : X509_PURPOSE_get0_name(purp);
- add_index_string(&subsub, 2, pname);
-
- add_index_zval(&subitem, id, &subsub);
- }
- add_assoc_zval(return_value, "purposes", &subitem);
- array_init(&subitem);
- for (i = 0; i < X509_get_ext_count(cert); i++) {
- int nid;
- extension = X509_get_ext(cert, i);
- nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
- if (nid != NID_undef) {
- extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension)));
- } else {
- OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1);
- extname = buf;
- }
- bio_out = BIO_new(BIO_s_mem());
- if (bio_out == NULL) {
- php_openssl_store_errors();
- RETURN_FALSE;
- }
- if (nid == NID_subject_alt_name) {
- if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) {
- BIO_get_mem_ptr(bio_out, &bio_buf);
- add_assoc_stringl(&subitem, extname, bio_buf->data, bio_buf->length);
- } else {
- zend_array_destroy(Z_ARR_P(return_value));
- BIO_free(bio_out);
- if (cert_str) {
- X509_free(cert);
- }
- RETURN_FALSE;
- }
- }
- else if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
- BIO_get_mem_ptr(bio_out, &bio_buf);
- add_assoc_stringl(&subitem, extname, bio_buf->data, bio_buf->length);
- } else {
- php_openssl_add_assoc_asn1_string(&subitem, extname, X509_EXTENSION_get_data(extension));
- }
- BIO_free(bio_out);
- }
- add_assoc_zval(return_value, "extensions", &subitem);
- if (cert_str) {
- X509_free(cert);
- }
- }
- static STACK_OF(X509) *php_openssl_load_all_certs_from_file(
- char *cert_file, size_t cert_file_len, uint32_t arg_num)
- {
- STACK_OF(X509_INFO) *sk=NULL;
- STACK_OF(X509) *stack=NULL, *ret=NULL;
- BIO *in=NULL;
- X509_INFO *xi;
- char cert_path[MAXPATHLEN];
- if(!(stack = sk_X509_new_null())) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_ERROR, "Memory allocation failure");
- goto end;
- }
- if (!php_openssl_check_path(cert_file, cert_file_len, cert_path, arg_num)) {
- sk_X509_free(stack);
- goto end;
- }
- if (!(in = BIO_new_file(cert_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)))) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error opening the file, %s", cert_path);
- sk_X509_free(stack);
- goto end;
- }
-
- if (!(sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL))) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error reading the file, %s", cert_path);
- sk_X509_free(stack);
- goto end;
- }
-
- while (sk_X509_INFO_num(sk)) {
- xi=sk_X509_INFO_shift(sk);
- if (xi->x509 != NULL) {
- sk_X509_push(stack,xi->x509);
- xi->x509=NULL;
- }
- X509_INFO_free(xi);
- }
- if (!sk_X509_num(stack)) {
- php_error_docref(NULL, E_WARNING, "No certificates in file, %s", cert_path);
- sk_X509_free(stack);
- goto end;
- }
- ret = stack;
- end:
- BIO_free(in);
- sk_X509_INFO_free(sk);
- return ret;
- }
- static int check_cert(X509_STORE *ctx, X509 *x, STACK_OF(X509) *untrustedchain, int purpose)
- {
- int ret=0;
- X509_STORE_CTX *csc;
- csc = X509_STORE_CTX_new();
- if (csc == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_ERROR, "Memory allocation failure");
- return 0;
- }
- if (!X509_STORE_CTX_init(csc, ctx, x, untrustedchain)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Certificate store initialization failed");
- return 0;
- }
- if (purpose >= 0 && !X509_STORE_CTX_set_purpose(csc, purpose)) {
- php_openssl_store_errors();
- }
- ret = X509_verify_cert(csc);
- if (ret < 0) {
- php_openssl_store_errors();
- }
- X509_STORE_CTX_free(csc);
- return ret;
- }
- PHP_FUNCTION(openssl_x509_checkpurpose)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- zval *zcainfo = NULL;
- X509_STORE *cainfo = NULL;
- STACK_OF(X509) *untrustedchain = NULL;
- zend_long purpose;
- char * untrusted = NULL;
- size_t untrusted_len = 0;
- int ret;
- ZEND_PARSE_PARAMETERS_START(2, 4)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_LONG(purpose)
- Z_PARAM_OPTIONAL
- Z_PARAM_ARRAY(zcainfo)
- Z_PARAM_STRING_OR_NULL(untrusted, untrusted_len)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_LONG(-1);
- if (untrusted) {
- untrustedchain = php_openssl_load_all_certs_from_file(untrusted, untrusted_len, 4);
- if (untrustedchain == NULL) {
- goto clean_exit;
- }
- }
- cainfo = php_openssl_setup_verify(zcainfo, 3);
- if (cainfo == NULL) {
- goto clean_exit;
- }
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
-
- goto clean_exit;
- }
- ret = check_cert(cainfo, cert, untrustedchain, (int)purpose);
- if (ret != 0 && ret != 1) {
- RETVAL_LONG(ret);
- } else {
- RETVAL_BOOL(ret);
- }
- if (cert_str) {
- X509_free(cert);
- }
- clean_exit:
- if (cainfo) {
- X509_STORE_free(cainfo);
- }
- if (untrustedchain) {
- sk_X509_pop_free(untrustedchain, X509_free);
- }
- }
- static X509_STORE *php_openssl_setup_verify(zval *calist, uint32_t arg_num)
- {
- X509_STORE *store;
- X509_LOOKUP * dir_lookup, * file_lookup;
- int ndirs = 0, nfiles = 0;
- zval * item;
- zend_stat_t sb;
- char file_path[MAXPATHLEN];
- store = X509_STORE_new();
- if (store == NULL) {
- php_openssl_store_errors();
- return NULL;
- }
- if (calist && (Z_TYPE_P(calist) == IS_ARRAY)) {
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(calist), item) {
- zend_string *str = zval_try_get_string(item);
- if (UNEXPECTED(!str)) {
- return NULL;
- }
- if (!php_openssl_check_path_str_ex(str, file_path, arg_num, false, true, NULL)) {
- zend_string_release(str);
- continue;
- }
- zend_string_release(str);
- if (VCWD_STAT(file_path, &sb) == -1) {
- php_error_docref(NULL, E_WARNING, "Unable to stat %s", file_path);
- continue;
- }
- if ((sb.st_mode & S_IFREG) == S_IFREG) {
- file_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
- if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, file_path, X509_FILETYPE_PEM)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error loading file %s", file_path);
- } else {
- nfiles++;
- }
- file_lookup = NULL;
- } else {
- dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
- if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, file_path, X509_FILETYPE_PEM)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error loading directory %s", file_path);
- } else {
- ndirs++;
- }
- dir_lookup = NULL;
- }
- } ZEND_HASH_FOREACH_END();
- }
- if (nfiles == 0) {
- file_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
- if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, NULL, X509_FILETYPE_DEFAULT)) {
- php_openssl_store_errors();
- }
- }
- if (ndirs == 0) {
- dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
- if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, NULL, X509_FILETYPE_DEFAULT)) {
- php_openssl_store_errors();
- }
- }
- return store;
- }
- PHP_FUNCTION(openssl_x509_read)
- {
- X509 *cert;
- php_openssl_certificate_object *x509_cert_obj;
- zend_object *cert_obj;
- zend_string *cert_str;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- ZEND_PARSE_PARAMETERS_END();
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- RETURN_FALSE;
- }
- object_init_ex(return_value, php_openssl_certificate_ce);
- x509_cert_obj = Z_OPENSSL_CERTIFICATE_P(return_value);
- x509_cert_obj->x509 = cert_obj ? X509_dup(cert) : cert;
- }
- PHP_FUNCTION(openssl_x509_free)
- {
- zval *x509;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_OBJECT_OF_CLASS(x509, php_openssl_certificate_ce)
- ZEND_PARSE_PARAMETERS_END();
- }
- static void php_sk_X509_free(STACK_OF(X509) * sk)
- {
- for (;;) {
- X509* x = sk_X509_pop(sk);
- if (!x) break;
- X509_free(x);
- }
- sk_X509_free(sk);
- }
- static STACK_OF(X509) *php_array_to_X509_sk(zval * zcerts, uint32_t arg_num, const char *option_name)
- {
- zval * zcertval;
- STACK_OF(X509) * sk = NULL;
- X509 * cert;
- bool free_cert;
- sk = sk_X509_new_null();
-
- if (Z_TYPE_P(zcerts) == IS_ARRAY) {
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zcerts), zcertval) {
- cert = php_openssl_x509_from_zval(zcertval, &free_cert, arg_num, true, option_name);
- if (cert == NULL) {
-
- goto clean_exit;
- }
- if (!free_cert) {
- cert = X509_dup(cert);
- if (cert == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- sk_X509_push(sk, cert);
- } ZEND_HASH_FOREACH_END();
- } else {
-
- cert = php_openssl_x509_from_zval(zcerts, &free_cert, arg_num, false, option_name);
- if (cert == NULL) {
-
- goto clean_exit;
- }
- if (!free_cert) {
- cert = X509_dup(cert);
- if (cert == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- sk_X509_push(sk, cert);
- }
- clean_exit:
- return sk;
- }
- PHP_FUNCTION(openssl_pkcs12_export_to_file)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- BIO * bio_out = NULL;
- PKCS12 * p12 = NULL;
- char * filename, file_path[MAXPATHLEN];
- char * friendly_name = NULL;
- size_t filename_len;
- char * pass;
- size_t pass_len;
- zval *zpkey = NULL, *args = NULL;
- EVP_PKEY *priv_key = NULL;
- zval * item;
- STACK_OF(X509) *ca = NULL;
- ZEND_PARSE_PARAMETERS_START(4, 5)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_PATH(filename, filename_len)
- Z_PARAM_ZVAL(zpkey)
- Z_PARAM_STRING(pass, pass_len)
- Z_PARAM_OPTIONAL
- Z_PARAM_ARRAY(args)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- return;
- }
- priv_key = php_openssl_pkey_from_zval(zpkey, 0, "", 0, 3);
- if (priv_key == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Cannot get private key from parameter 3");
- }
- goto cleanup;
- }
- if (!X509_check_private_key(cert, priv_key)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Private key does not correspond to cert");
- goto cleanup;
- }
- if (!php_openssl_check_path(filename, filename_len, file_path, 2)) {
- goto cleanup;
- }
-
- if (args &&
- (item = zend_hash_str_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name")-1)) != NULL &&
- Z_TYPE_P(item) == IS_STRING
- ) {
- friendly_name = Z_STRVAL_P(item);
- }
-
- if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL) {
- ca = php_array_to_X509_sk(item, 5, "extracerts");
- }
-
-
- p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0);
- if (p12 != NULL) {
- bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (bio_out != NULL) {
- i2d_PKCS12_bio(bio_out, p12);
- BIO_free(bio_out);
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error opening file %s", file_path);
- }
- PKCS12_free(p12);
- } else {
- php_openssl_store_errors();
- }
- php_sk_X509_free(ca);
- cleanup:
- EVP_PKEY_free(priv_key);
- if (cert_str) {
- X509_free(cert);
- }
- }
- PHP_FUNCTION(openssl_pkcs12_export)
- {
- X509 *cert;
- zend_object *cert_obj;
- zend_string *cert_str;
- BIO * bio_out;
- PKCS12 * p12 = NULL;
- zval *zout = NULL, *zpkey, *args = NULL;
- EVP_PKEY *priv_key = NULL;
- char * pass;
- size_t pass_len;
- char * friendly_name = NULL;
- zval * item;
- STACK_OF(X509) *ca = NULL;
- ZEND_PARSE_PARAMETERS_START(4, 5)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_ZVAL(zout)
- Z_PARAM_ZVAL(zpkey)
- Z_PARAM_STRING(pass, pass_len)
- Z_PARAM_OPTIONAL
- Z_PARAM_ARRAY(args)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 1);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- return;
- }
- priv_key = php_openssl_pkey_from_zval(zpkey, 0, "", 0, 3);
- if (priv_key == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Cannot get private key from parameter 3");
- }
- goto cleanup;
- }
- if (!X509_check_private_key(cert, priv_key)) {
- php_error_docref(NULL, E_WARNING, "Private key does not correspond to cert");
- goto cleanup;
- }
-
- if (args &&
- (item = zend_hash_str_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name")-1)) != NULL &&
- Z_TYPE_P(item) == IS_STRING
- ) {
- friendly_name = Z_STRVAL_P(item);
- }
- if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL) {
- ca = php_array_to_X509_sk(item, 5, "extracerts");
- }
-
- p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0);
- if (p12 != NULL) {
- bio_out = BIO_new(BIO_s_mem());
- if (i2d_PKCS12_bio(bio_out, p12)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZEND_TRY_ASSIGN_REF_STRINGL(zout, bio_buf->data, bio_buf->length);
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- BIO_free(bio_out);
- PKCS12_free(p12);
- } else {
- php_openssl_store_errors();
- }
- php_sk_X509_free(ca);
- cleanup:
- EVP_PKEY_free(priv_key);
- if (cert_str) {
- X509_free(cert);
- }
- }
- PHP_FUNCTION(openssl_pkcs12_read)
- {
- zval *zout = NULL, zextracerts, zcert, zpkey;
- char *pass, *zp12;
- size_t pass_len, zp12_len;
- PKCS12 * p12 = NULL;
- EVP_PKEY * pkey = NULL;
- X509 * cert = NULL;
- STACK_OF(X509) * ca = NULL;
- BIO * bio_in = NULL;
- int i;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "szs", &zp12, &zp12_len, &zout, &pass, &pass_len) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(zp12_len, pkcs12, 1);
- bio_in = BIO_new(BIO_s_mem());
- if (0 >= BIO_write(bio_in, zp12, (int)zp12_len)) {
- php_openssl_store_errors();
- goto cleanup;
- }
- if (d2i_PKCS12_bio(bio_in, &p12) && PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
- BIO * bio_out;
- int cert_num;
- zout = zend_try_array_init(zout);
- if (!zout) {
- goto cleanup;
- }
- if (cert) {
- bio_out = BIO_new(BIO_s_mem());
- if (PEM_write_bio_X509(bio_out, cert)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length);
- add_assoc_zval(zout, "cert", &zcert);
- } else {
- php_openssl_store_errors();
- }
- BIO_free(bio_out);
- }
- if (pkey) {
- bio_out = BIO_new(BIO_s_mem());
- if (PEM_write_bio_PrivateKey(bio_out, pkey, NULL, NULL, 0, 0, NULL)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(&zpkey, bio_buf->data, bio_buf->length);
- add_assoc_zval(zout, "pkey", &zpkey);
- } else {
- php_openssl_store_errors();
- }
- BIO_free(bio_out);
- }
- cert_num = sk_X509_num(ca);
- if (ca && cert_num) {
- array_init(&zextracerts);
- for (i = 0; i < cert_num; i++) {
- zval zextracert;
- X509* aCA = sk_X509_pop(ca);
- if (!aCA) break;
- bio_out = BIO_new(BIO_s_mem());
- if (PEM_write_bio_X509(bio_out, aCA)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(&zextracert, bio_buf->data, bio_buf->length);
- add_index_zval(&zextracerts, i, &zextracert);
- }
- X509_free(aCA);
- BIO_free(bio_out);
- }
- sk_X509_free(ca);
- add_assoc_zval(zout, "extracerts", &zextracerts);
- }
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- cleanup:
- BIO_free(bio_in);
- EVP_PKEY_free(pkey);
- if (cert) {
- X509_free(cert);
- }
- if (p12) {
- PKCS12_free(p12);
- }
- }
- static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, zval * dn, zval * attribs)
- {
- STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL;
- char * str, *dn_sect, *attr_sect;
- dn_sect = NCONF_get_string(req->req_config, req->section_name, "distinguished_name");
- if (dn_sect == NULL) {
- php_openssl_store_errors();
- return FAILURE;
- }
- dn_sk = NCONF_get_section(req->req_config, dn_sect);
- if (dn_sk == NULL) {
- php_openssl_store_errors();
- return FAILURE;
- }
- attr_sect = php_openssl_conf_get_string(req->req_config, req->section_name, "attributes");
- if (attr_sect == NULL) {
- attr_sk = NULL;
- } else {
- attr_sk = NCONF_get_section(req->req_config, attr_sect);
- if (attr_sk == NULL) {
- php_openssl_store_errors();
- return FAILURE;
- }
- }
-
- if (X509_REQ_set_version(csr, 0L)) {
- int i, nid;
- char * type;
- CONF_VALUE * v;
- X509_NAME * subj;
- zval * item;
- zend_string * strindex = NULL;
- subj = X509_REQ_get_subject_name(csr);
-
- ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(dn), strindex, item) {
- if (strindex) {
- int nid = OBJ_txt2nid(ZSTR_VAL(strindex));
- if (nid != NID_undef) {
- zend_string *str_item = zval_try_get_string(item);
- if (UNEXPECTED(!str_item)) {
- return FAILURE;
- }
- if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8,
- (unsigned char*)ZSTR_VAL(str_item), -1, -1, 0))
- {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING,
- "dn: add_entry_by_NID %d -> %s (failed; check error"
- " queue and value of string_mask OpenSSL option "
- "if illegal characters are reported)",
- nid, ZSTR_VAL(str_item));
- zend_string_release(str_item);
- return FAILURE;
- }
- zend_string_release(str_item);
- } else {
- php_error_docref(NULL, E_WARNING, "dn: %s is not a recognized name", ZSTR_VAL(strindex));
- }
- }
- } ZEND_HASH_FOREACH_END();
-
- for(i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
- size_t len;
- char buffer[200 + 1];
- v = sk_CONF_VALUE_value(dn_sk, i);
- type = v->name;
- len = strlen(type);
- if (len < sizeof("_default")) {
- continue;
- }
- len -= sizeof("_default") - 1;
- if (strcmp("_default", type + len) != 0) {
- continue;
- }
- if (len > 200) {
- len = 200;
- }
- memcpy(buffer, type, len);
- buffer[len] = '\0';
- type = buffer;
-
- for (str = type; *str; str++) {
- if (*str == ':' || *str == ',' || *str == '.') {
- str++;
- if (*str) {
- type = str;
- }
- break;
- }
- }
-
- nid = OBJ_txt2nid(type);
- if (X509_NAME_get_index_by_NID(subj, nid, -1) >= 0) {
- continue;
- }
- if (!X509_NAME_add_entry_by_txt(subj, type, MBSTRING_UTF8, (unsigned char*)v->value, -1, -1, 0)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "add_entry_by_txt %s -> %s (failed)", type, v->value);
- return FAILURE;
- }
- if (!X509_NAME_entry_count(subj)) {
- php_error_docref(NULL, E_WARNING, "No objects specified in config file");
- return FAILURE;
- }
- }
- if (attribs) {
- ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(attribs), strindex, item) {
- int nid;
- if (NULL == strindex) {
- php_error_docref(NULL, E_WARNING, "dn: numeric fild names are not supported");
- continue;
- }
- nid = OBJ_txt2nid(ZSTR_VAL(strindex));
- if (nid != NID_undef) {
- zend_string *str_item = zval_try_get_string(item);
- if (UNEXPECTED(!str_item)) {
- return FAILURE;
- }
- if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (unsigned char*)ZSTR_VAL(str_item), -1, -1, 0)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "attribs: add_entry_by_NID %d -> %s (failed)", nid, ZSTR_VAL(str_item));
- zend_string_release(str_item);
- return FAILURE;
- }
- zend_string_release(str_item);
- } else {
- php_error_docref(NULL, E_WARNING, "dn: %s is not a recognized name", ZSTR_VAL(strindex));
- }
- } ZEND_HASH_FOREACH_END();
- for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
- v = sk_CONF_VALUE_value(attr_sk, i);
-
- nid = OBJ_txt2nid(v->name);
- if (X509_REQ_get_attr_by_NID(csr, nid, -1) >= 0) {
- continue;
- }
- if (!X509_REQ_add1_attr_by_txt(csr, v->name, MBSTRING_UTF8, (unsigned char*)v->value, -1)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING,
- "add1_attr_by_txt %s -> %s (failed; check error queue "
- "and value of string_mask OpenSSL option if illegal "
- "characters are reported)",
- v->name, v->value);
- return FAILURE;
- }
- }
- }
- } else {
- php_openssl_store_errors();
- }
- if (!X509_REQ_set_pubkey(csr, req->priv_key)) {
- php_openssl_store_errors();
- }
- return SUCCESS;
- }
- static X509_REQ *php_openssl_csr_from_str(zend_string *csr_str, uint32_t arg_num)
- {
- X509_REQ * csr = NULL;
- char file_path[MAXPATHLEN];
- BIO * in;
- if (ZSTR_LEN(csr_str) > 7 && memcmp(ZSTR_VAL(csr_str), "file://", sizeof("file://") - 1) == 0) {
- if (!php_openssl_check_path_str(csr_str, file_path, arg_num)) {
- return NULL;
- }
- in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
- } else {
- in = BIO_new_mem_buf(ZSTR_VAL(csr_str), (int) ZSTR_LEN(csr_str));
- }
- if (in == NULL) {
- php_openssl_store_errors();
- return NULL;
- }
- csr = PEM_read_bio_X509_REQ(in, NULL,NULL,NULL);
- if (csr == NULL) {
- php_openssl_store_errors();
- }
- BIO_free(in);
- return csr;
- }
- static X509_REQ *php_openssl_csr_from_param(
- zend_object *csr_obj, zend_string *csr_str, uint32_t arg_num)
- {
- if (csr_obj) {
- return php_openssl_request_from_obj(csr_obj)->csr;
- }
- ZEND_ASSERT(csr_str);
- return php_openssl_csr_from_str(csr_str, arg_num);
- }
- PHP_FUNCTION(openssl_csr_export_to_file)
- {
- X509_REQ *csr;
- zend_object *csr_obj;
- zend_string *csr_str;
- bool notext = 1;
- char * filename = NULL;
- size_t filename_len;
- char file_path[MAXPATHLEN];
- BIO * bio_out;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
- Z_PARAM_PATH(filename, filename_len)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(notext)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- csr = php_openssl_csr_from_param(csr_obj, csr_str, 1);
- if (csr == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate Signing Request cannot be retrieved");
- return;
- }
- if (!php_openssl_check_path(filename, filename_len, file_path, 2)) {
- return;
- }
- bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (bio_out != NULL) {
- if (!notext && !X509_REQ_print(bio_out, csr)) {
- php_openssl_store_errors();
- }
- if (!PEM_write_bio_X509_REQ(bio_out, csr)) {
- php_error_docref(NULL, E_WARNING, "Error writing PEM to file %s", file_path);
- php_openssl_store_errors();
- } else {
- RETVAL_TRUE;
- }
- BIO_free(bio_out);
- } else {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error opening file %s", file_path);
- }
- if (csr_str) {
- X509_REQ_free(csr);
- }
- }
- PHP_FUNCTION(openssl_csr_export)
- {
- X509_REQ *csr;
- zend_object *csr_obj;
- zend_string *csr_str;
- zval *zout;
- bool notext = 1;
- BIO * bio_out;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
- Z_PARAM_ZVAL(zout)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(notext)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- csr = php_openssl_csr_from_param(csr_obj, csr_str, 1);
- if (csr == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate Signing Request cannot be retrieved");
- return;
- }
-
- bio_out = BIO_new(BIO_s_mem());
- if (!notext && !X509_REQ_print(bio_out, csr)) {
- php_openssl_store_errors();
- }
- if (PEM_write_bio_X509_REQ(bio_out, csr)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZEND_TRY_ASSIGN_REF_STRINGL(zout, bio_buf->data, bio_buf->length);
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- if (csr_str) {
- X509_REQ_free(csr);
- }
- BIO_free(bio_out);
- }
- PHP_FUNCTION(openssl_csr_sign)
- {
- X509_REQ *csr;
- zend_object *csr_obj;
- zend_string *csr_str;
- php_openssl_certificate_object *cert_object;
- zend_object *cert_obj;
- zend_string *cert_str;
- zval *zpkey, *args = NULL;
- zend_long num_days;
- zend_long serial = Z_L(0);
- X509 *cert = NULL, *new_cert = NULL;
- EVP_PKEY * key = NULL, *priv_key = NULL;
- int i;
- struct php_x509_request req;
- ZEND_PARSE_PARAMETERS_START(4, 6)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
- Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_ZVAL(zpkey)
- Z_PARAM_LONG(num_days)
- Z_PARAM_OPTIONAL
- Z_PARAM_ARRAY_OR_NULL(args)
- Z_PARAM_LONG(serial)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- csr = php_openssl_csr_from_param(csr_obj, csr_str, 1);
- if (csr == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate Signing Request cannot be retrieved");
- return;
- }
- PHP_SSL_REQ_INIT(&req);
- if (cert_str || cert_obj) {
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 2);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- goto cleanup;
- }
- }
- priv_key = php_openssl_pkey_from_zval(zpkey, 0, "", 0, 3);
- if (priv_key == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Cannot get private key from parameter 3");
- }
- goto cleanup;
- }
- if (cert && !X509_check_private_key(cert, priv_key)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Private key does not correspond to signing cert");
- goto cleanup;
- }
- if (PHP_SSL_REQ_PARSE(&req, args) == FAILURE) {
- goto cleanup;
- }
-
- key = X509_REQ_get_pubkey(csr);
- if (key == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error unpacking public key");
- goto cleanup;
- }
- i = X509_REQ_verify(csr, key);
- if (i < 0) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Signature verification problems");
- goto cleanup;
- }
- else if (i == 0) {
- php_error_docref(NULL, E_WARNING, "Signature did not match the certificate request");
- goto cleanup;
- }
-
- new_cert = X509_new();
- if (new_cert == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "No memory");
- goto cleanup;
- }
-
- if (!X509_set_version(new_cert, 2)) {
- goto cleanup;
- }
- #if PHP_OPENSSL_API_VERSION >= 0x10100 && !defined (LIBRESSL_VERSION_NUMBER)
- ASN1_INTEGER_set_int64(X509_get_serialNumber(new_cert), serial);
- #else
- ASN1_INTEGER_set(X509_get_serialNumber(new_cert), serial);
- #endif
- X509_set_subject_name(new_cert, X509_REQ_get_subject_name(csr));
- if (cert == NULL) {
- cert = new_cert;
- }
- if (!X509_set_issuer_name(new_cert, X509_get_subject_name(cert))) {
- php_openssl_store_errors();
- goto cleanup;
- }
- X509_gmtime_adj(X509_getm_notBefore(new_cert), 0);
- X509_gmtime_adj(X509_getm_notAfter(new_cert), 60*60*24*(long)num_days);
- i = X509_set_pubkey(new_cert, key);
- if (!i) {
- php_openssl_store_errors();
- goto cleanup;
- }
- if (req.extensions_section) {
- X509V3_CTX ctx;
- X509V3_set_ctx(&ctx, cert, new_cert, csr, NULL, 0);
- X509V3_set_nconf(&ctx, req.req_config);
- if (!X509V3_EXT_add_nconf(req.req_config, &ctx, req.extensions_section, new_cert)) {
- php_openssl_store_errors();
- goto cleanup;
- }
- }
-
- if (!X509_sign(new_cert, priv_key, req.digest)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Failed to sign it");
- goto cleanup;
- }
- object_init_ex(return_value, php_openssl_certificate_ce);
- cert_object = Z_OPENSSL_CERTIFICATE_P(return_value);
- cert_object->x509 = new_cert;
- cleanup:
- if (cert == new_cert) {
- cert = NULL;
- }
- PHP_SSL_REQ_DISPOSE(&req);
- EVP_PKEY_free(priv_key);
- EVP_PKEY_free(key);
- if (csr_str) {
- X509_REQ_free(csr);
- }
- if (cert_str && cert) {
- X509_free(cert);
- }
- }
- PHP_FUNCTION(openssl_csr_new)
- {
- struct php_x509_request req;
- php_openssl_request_object *x509_request_obj;
- zval *args = NULL, *dn, *attribs = NULL;
- zval *out_pkey;
- X509_REQ *csr = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "az|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- PHP_SSL_REQ_INIT(&req);
- if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
- int we_made_the_key = 0;
- zval *out_pkey_val = out_pkey;
- ZVAL_DEREF(out_pkey_val);
-
- if (Z_TYPE_P(out_pkey_val) != IS_NULL) {
- req.priv_key = php_openssl_pkey_from_zval(out_pkey_val, 0, NULL, 0, 2);
- }
- if (req.priv_key == NULL) {
- php_openssl_generate_private_key(&req);
- we_made_the_key = 1;
- }
- if (req.priv_key == NULL) {
- php_error_docref(NULL, E_WARNING, "Unable to generate a private key");
- } else {
- csr = X509_REQ_new();
- if (csr) {
- if (php_openssl_make_REQ(&req, csr, dn, attribs) == SUCCESS) {
- X509V3_CTX ext_ctx;
- X509V3_set_ctx(&ext_ctx, NULL, NULL, csr, NULL, 0);
- X509V3_set_nconf(&ext_ctx, req.req_config);
-
- if (req.request_extensions_section && !X509V3_EXT_REQ_add_nconf(req.req_config,
- &ext_ctx, req.request_extensions_section, csr))
- {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error loading extension section %s", req.request_extensions_section);
- } else {
- RETVAL_TRUE;
- if (X509_REQ_sign(csr, req.priv_key, req.digest)) {
- object_init_ex(return_value, php_openssl_request_ce);
- x509_request_obj = Z_OPENSSL_REQUEST_P(return_value);
- x509_request_obj->csr = csr;
- csr = NULL;
- } else {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error signing request");
- }
- if (we_made_the_key) {
-
- zval zkey_object;
- php_openssl_pkey_object_init(
- &zkey_object, req.priv_key, true);
- ZEND_TRY_ASSIGN_REF_TMP(out_pkey, &zkey_object);
- req.priv_key = NULL;
- }
- }
- }
- } else {
- php_openssl_store_errors();
- }
- }
- }
- if (csr) {
- X509_REQ_free(csr);
- }
- PHP_SSL_REQ_DISPOSE(&req);
- }
- PHP_FUNCTION(openssl_csr_get_subject)
- {
- X509_REQ *csr;
- zend_object *csr_obj;
- zend_string *csr_str;
- bool use_shortnames = 1;
- X509_NAME *subject;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(use_shortnames)
- ZEND_PARSE_PARAMETERS_END();
- csr = php_openssl_csr_from_param(csr_obj, csr_str, 1);
- if (csr == NULL) {
- RETURN_FALSE;
- }
- subject = X509_REQ_get_subject_name(csr);
- array_init(return_value);
- php_openssl_add_assoc_name_entry(return_value, NULL, subject, use_shortnames);
- if (csr_str) {
- X509_REQ_free(csr);
- }
- }
- static EVP_PKEY *php_openssl_extract_public_key(EVP_PKEY *priv_key)
- {
-
- BIO *bio = BIO_new(BIO_s_mem());
- if (!bio || !PEM_write_bio_PUBKEY(bio, priv_key)) {
- BIO_free(bio);
- return NULL;
- }
- EVP_PKEY *pub_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
- BIO_free(bio);
- return pub_key;
- }
- PHP_FUNCTION(openssl_csr_get_public_key)
- {
- zend_object *csr_obj;
- zend_string *csr_str;
- bool use_shortnames = 1;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(use_shortnames)
- ZEND_PARSE_PARAMETERS_END();
- X509_REQ *csr = php_openssl_csr_from_param(csr_obj, csr_str, 1);
- if (csr == NULL) {
- RETURN_FALSE;
- }
-
- EVP_PKEY *orig_key = X509_REQ_get_pubkey(csr);
- EVP_PKEY *tpubkey = php_openssl_extract_public_key(orig_key);
- EVP_PKEY_free(orig_key);
- if (csr_str) {
-
- X509_REQ_free(csr);
- }
- if (tpubkey == NULL) {
- php_openssl_store_errors();
- RETURN_FALSE;
- }
- php_openssl_pkey_object_init(return_value, tpubkey, false);
- }
- struct php_openssl_pem_password {
- char *key;
- int len;
- };
- static int php_openssl_pem_password_cb(char *buf, int size, int rwflag, void *userdata)
- {
- struct php_openssl_pem_password *password = userdata;
- if (password == NULL || password->key == NULL) {
- return -1;
- }
- size = (password->len > size) ? size : password->len;
- memcpy(buf, password->key, size);
- return size;
- }
- static EVP_PKEY *php_openssl_pkey_from_zval(
- zval *val, int public_key, char *passphrase, size_t passphrase_len, uint32_t arg_num)
- {
- EVP_PKEY *key = NULL;
- X509 *cert = NULL;
- bool free_cert = false, is_file = false;
- char file_path[MAXPATHLEN];
- zval tmp;
- ZVAL_NULL(&tmp);
- #define TMP_CLEAN \
- if (Z_TYPE(tmp) == IS_STRING) {\
- zval_ptr_dtor_str(&tmp); \
- } \
- return NULL;
- if (Z_TYPE_P(val) == IS_ARRAY) {
- zval * zphrase;
-
- if ((zphrase = zend_hash_index_find(Z_ARRVAL_P(val), 1)) == NULL) {
- zend_value_error("Key array must be of the form array(0 => key, 1 => phrase)");
- return NULL;
- }
- if (Z_TYPE_P(zphrase) == IS_STRING) {
- passphrase = Z_STRVAL_P(zphrase);
- passphrase_len = Z_STRLEN_P(zphrase);
- } else {
- ZVAL_COPY(&tmp, zphrase);
- if (!try_convert_to_string(&tmp)) {
- return NULL;
- }
- passphrase = Z_STRVAL(tmp);
- passphrase_len = Z_STRLEN(tmp);
- }
-
- if ((val = zend_hash_index_find(Z_ARRVAL_P(val), 0)) == NULL) {
- zend_value_error("Key array must be of the form array(0 => key, 1 => phrase)");
- TMP_CLEAN;
- }
- }
- if (Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val) == php_openssl_pkey_ce) {
- php_openssl_pkey_object *obj = php_openssl_pkey_from_obj(Z_OBJ_P(val));
- key = obj->pkey;
- bool is_priv = obj->is_private;
-
- if (!public_key && !is_priv) {
- php_error_docref(NULL, E_WARNING, "Supplied key param is a public key");
- TMP_CLEAN;
- }
- if (public_key && is_priv) {
- php_error_docref(NULL, E_WARNING, "Don't know how to get public key from this private key");
- TMP_CLEAN;
- } else {
- if (Z_TYPE(tmp) == IS_STRING) {
- zval_ptr_dtor_str(&tmp);
- }
- EVP_PKEY_up_ref(key);
- return key;
- }
- } else if (Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val) == php_openssl_certificate_ce) {
- cert = php_openssl_certificate_from_obj(Z_OBJ_P(val))->x509;
- } else {
-
-
- if (!(Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_OBJECT)) {
- TMP_CLEAN;
- }
- if (!try_convert_to_string(val)) {
- TMP_CLEAN;
- }
- if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
- if (!php_openssl_check_path_str(Z_STR_P(val), file_path, arg_num)) {
- TMP_CLEAN;
- }
- is_file = true;
- }
-
- if (public_key) {
- cert = php_openssl_x509_from_str(Z_STR_P(val), arg_num, false, NULL);
- if (cert) {
- free_cert = 1;
- } else {
-
- BIO* in;
- if (is_file) {
- in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
- } else {
- in = BIO_new_mem_buf(Z_STRVAL_P(val), (int)Z_STRLEN_P(val));
- }
- if (in == NULL) {
- php_openssl_store_errors();
- TMP_CLEAN;
- }
- key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
- BIO_free(in);
- }
- } else {
-
- BIO *in;
- if (is_file) {
- in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
- } else {
- in = BIO_new_mem_buf(Z_STRVAL_P(val), (int)Z_STRLEN_P(val));
- }
- if (in == NULL) {
- TMP_CLEAN;
- }
- if (passphrase == NULL) {
- key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
- } else {
- struct php_openssl_pem_password password;
- password.key = passphrase;
- password.len = passphrase_len;
- key = PEM_read_bio_PrivateKey(in, NULL, php_openssl_pem_password_cb, &password);
- }
- BIO_free(in);
- }
- }
- if (key == NULL) {
- php_openssl_store_errors();
- if (public_key && cert) {
-
- key = (EVP_PKEY *) X509_get_pubkey(cert);
- if (key == NULL) {
- php_openssl_store_errors();
- }
- }
- }
- if (free_cert) {
- X509_free(cert);
- }
- if (Z_TYPE(tmp) == IS_STRING) {
- zval_ptr_dtor_str(&tmp);
- }
- return key;
- }
- static int php_openssl_get_evp_pkey_type(int key_type) {
- switch (key_type) {
- case OPENSSL_KEYTYPE_RSA:
- return EVP_PKEY_RSA;
- #if !defined(NO_DSA)
- case OPENSSL_KEYTYPE_DSA:
- return EVP_PKEY_DSA;
- #endif
- #if !defined(NO_DH)
- case OPENSSL_KEYTYPE_DH:
- return EVP_PKEY_DH;
- #endif
- #ifdef HAVE_EVP_PKEY_EC
- case OPENSSL_KEYTYPE_EC:
- return EVP_PKEY_EC;
- #endif
- default:
- return -1;
- }
- }
- static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
- {
- if (req->priv_key_bits < MIN_KEY_LENGTH) {
- php_error_docref(NULL, E_WARNING, "Private key length must be at least %d bits, configured to %d",
- MIN_KEY_LENGTH, req->priv_key_bits);
- return NULL;
- }
- int type = php_openssl_get_evp_pkey_type(req->priv_key_type);
- if (type < 0) {
- php_error_docref(NULL, E_WARNING, "Unsupported private key type");
- return NULL;
- }
- int egdsocket, seeded;
- char *randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE");
- php_openssl_load_rand_file(randfile, &egdsocket, &seeded);
- PHP_OPENSSL_RAND_ADD_TIME();
- EVP_PKEY *key = NULL;
- EVP_PKEY *params = NULL;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(type, NULL);
- if (!ctx) {
- php_openssl_store_errors();
- goto cleanup;
- }
- if (type != EVP_PKEY_RSA) {
- if (EVP_PKEY_paramgen_init(ctx) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- switch (type) {
- #if !defined(NO_DSA)
- case EVP_PKEY_DSA:
- if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, req->priv_key_bits) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- break;
- #endif
- #if !defined(NO_DH)
- case EVP_PKEY_DH:
- if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, req->priv_key_bits) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- break;
- #endif
- #ifdef HAVE_EVP_PKEY_EC
- case EVP_PKEY_EC:
- if (req->curve_name == NID_undef) {
- php_error_docref(NULL, E_WARNING, "Missing configuration value: \"curve_name\" not set");
- goto cleanup;
- }
- if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, req->curve_name) <= 0 ||
- EVP_PKEY_CTX_set_ec_param_enc(ctx, OPENSSL_EC_NAMED_CURVE) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- break;
- #endif
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- if (EVP_PKEY_paramgen(ctx, ¶ms) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- EVP_PKEY_CTX_free(ctx);
- ctx = EVP_PKEY_CTX_new(params, NULL);
- if (!ctx) {
- php_openssl_store_errors();
- goto cleanup;
- }
- }
- if (EVP_PKEY_keygen_init(ctx) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- if (type == EVP_PKEY_RSA && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, req->priv_key_bits) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- if (EVP_PKEY_keygen(ctx, &key) <= 0) {
- php_openssl_store_errors();
- goto cleanup;
- }
- req->priv_key = key;
- cleanup:
- php_openssl_write_rand_file(randfile, egdsocket, seeded);
- EVP_PKEY_free(params);
- EVP_PKEY_CTX_free(ctx);
- return key;
- }
- static void php_openssl_add_bn_to_array(zval *ary, const BIGNUM *bn, const char *name) {
- if (bn != NULL) {
- int len = BN_num_bytes(bn);
- zend_string *str = zend_string_alloc(len, 0);
- BN_bn2bin(bn, (unsigned char *)ZSTR_VAL(str));
- ZSTR_VAL(str)[len] = 0;
- add_assoc_str(ary, name, str);
- }
- }
- #define OPENSSL_PKEY_GET_BN(_type, _name) php_openssl_add_bn_to_array(&_type, _name, #_name)
- #define OPENSSL_PKEY_SET_BN(_data, _name) do { \
- zval *bn; \
- if ((bn = zend_hash_str_find(Z_ARRVAL_P(_data), #_name, sizeof(#_name)-1)) != NULL && \
- Z_TYPE_P(bn) == IS_STRING) { \
- _name = BN_bin2bn( \
- (unsigned char*)Z_STRVAL_P(bn), \
- (int)Z_STRLEN_P(bn), NULL); \
- } else { \
- _name = NULL; \
- } \
- } while (0);
- #if PHP_OPENSSL_API_VERSION < 0x30000
- static bool php_openssl_pkey_init_legacy_rsa(RSA *rsa, zval *data)
- {
- BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
- OPENSSL_PKEY_SET_BN(data, n);
- OPENSSL_PKEY_SET_BN(data, e);
- OPENSSL_PKEY_SET_BN(data, d);
- if (!n || !d || !RSA_set0_key(rsa, n, e, d)) {
- return 0;
- }
- OPENSSL_PKEY_SET_BN(data, p);
- OPENSSL_PKEY_SET_BN(data, q);
- if ((p || q) && !RSA_set0_factors(rsa, p, q)) {
- return 0;
- }
- OPENSSL_PKEY_SET_BN(data, dmp1);
- OPENSSL_PKEY_SET_BN(data, dmq1);
- OPENSSL_PKEY_SET_BN(data, iqmp);
- if ((dmp1 || dmq1 || iqmp) && !RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) {
- return 0;
- }
- return 1;
- }
- #endif
- static EVP_PKEY *php_openssl_pkey_init_rsa(zval *data)
- {
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
- BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
- EVP_PKEY *pkey = NULL;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
- OSSL_PARAM *params = NULL;
- OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
- OPENSSL_PKEY_SET_BN(data, n);
- OPENSSL_PKEY_SET_BN(data, e);
- OPENSSL_PKEY_SET_BN(data, d);
- OPENSSL_PKEY_SET_BN(data, p);
- OPENSSL_PKEY_SET_BN(data, q);
- OPENSSL_PKEY_SET_BN(data, dmp1);
- OPENSSL_PKEY_SET_BN(data, dmq1);
- OPENSSL_PKEY_SET_BN(data, iqmp);
- if (!ctx || !bld || !n || !d) {
- goto cleanup;
- }
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n);
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, d);
- if (e) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e);
- }
- if (p) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR1, p);
- }
- if (q) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR2, q);
- }
- if (dmp1) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1);
- }
- if (dmq1) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1);
- }
- if (iqmp) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp);
- }
- params = OSSL_PARAM_BLD_to_param(bld);
- if (!params) {
- goto cleanup;
- }
- if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
- EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
- goto cleanup;
- }
- cleanup:
- php_openssl_store_errors();
- EVP_PKEY_CTX_free(ctx);
- OSSL_PARAM_free(params);
- OSSL_PARAM_BLD_free(bld);
- BN_free(n);
- BN_free(e);
- BN_free(d);
- BN_free(p);
- BN_free(q);
- BN_free(dmp1);
- BN_free(dmq1);
- BN_free(iqmp);
- return pkey;
- #else
- EVP_PKEY *pkey = EVP_PKEY_new();
- if (!pkey) {
- php_openssl_store_errors();
- return NULL;
- }
- RSA *rsa = RSA_new();
- if (!rsa) {
- php_openssl_store_errors();
- EVP_PKEY_free(pkey);
- return NULL;
- }
- if (!php_openssl_pkey_init_legacy_rsa(rsa, data)
- || !EVP_PKEY_assign_RSA(pkey, rsa)) {
- php_openssl_store_errors();
- EVP_PKEY_free(pkey);
- RSA_free(rsa);
- return NULL;
- }
- return pkey;
- #endif
- }
- #if PHP_OPENSSL_API_VERSION < 0x30000
- static bool php_openssl_pkey_init_legacy_dsa(DSA *dsa, zval *data, bool *is_private)
- {
- BIGNUM *p, *q, *g, *priv_key, *pub_key;
- const BIGNUM *priv_key_const, *pub_key_const;
- OPENSSL_PKEY_SET_BN(data, p);
- OPENSSL_PKEY_SET_BN(data, q);
- OPENSSL_PKEY_SET_BN(data, g);
- if (!p || !q || !g || !DSA_set0_pqg(dsa, p, q, g)) {
- return 0;
- }
- OPENSSL_PKEY_SET_BN(data, pub_key);
- OPENSSL_PKEY_SET_BN(data, priv_key);
- *is_private = priv_key != NULL;
- if (pub_key) {
- return DSA_set0_key(dsa, pub_key, priv_key);
- }
-
- PHP_OPENSSL_RAND_ADD_TIME();
- if (!DSA_generate_key(dsa)) {
- php_openssl_store_errors();
- return 0;
- }
-
- DSA_get0_key(dsa, &pub_key_const, &priv_key_const);
- if (!pub_key_const || BN_is_zero(pub_key_const)) {
- return 0;
- }
-
- *is_private = true;
- return 1;
- }
- #endif
- static EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private)
- {
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
- EVP_PKEY *param_key = NULL, *pkey = NULL;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
- OSSL_PARAM *params = NULL;
- OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
- OPENSSL_PKEY_SET_BN(data, p);
- OPENSSL_PKEY_SET_BN(data, q);
- OPENSSL_PKEY_SET_BN(data, g);
- OPENSSL_PKEY_SET_BN(data, priv_key);
- OPENSSL_PKEY_SET_BN(data, pub_key);
- *is_private = false;
- if (!ctx || !bld || !p || !q || !g) {
- goto cleanup;
- }
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p);
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q);
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g);
-
- if (pub_key) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_key);
- if (priv_key) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv_key);
- }
- }
- params = OSSL_PARAM_BLD_to_param(bld);
- if (!params) {
- goto cleanup;
- }
- if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
- EVP_PKEY_fromdata(ctx, ¶m_key, EVP_PKEY_KEYPAIR, params) <= 0) {
- goto cleanup;
- }
- if (pub_key) {
- *is_private = priv_key != NULL;
- EVP_PKEY_up_ref(param_key);
- pkey = param_key;
- } else {
- *is_private = true;
- PHP_OPENSSL_RAND_ADD_TIME();
- EVP_PKEY_CTX_free(ctx);
- ctx = EVP_PKEY_CTX_new(param_key, NULL);
- if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
- goto cleanup;
- }
- }
- cleanup:
- php_openssl_store_errors();
- EVP_PKEY_free(param_key);
- EVP_PKEY_CTX_free(ctx);
- OSSL_PARAM_free(params);
- OSSL_PARAM_BLD_free(bld);
- BN_free(p);
- BN_free(q);
- BN_free(g);
- BN_free(priv_key);
- BN_free(pub_key);
- return pkey;
- #else
- EVP_PKEY *pkey = EVP_PKEY_new();
- if (!pkey) {
- php_openssl_store_errors();
- return NULL;
- }
- DSA *dsa = DSA_new();
- if (!dsa) {
- php_openssl_store_errors();
- EVP_PKEY_free(pkey);
- return NULL;
- }
- if (!php_openssl_pkey_init_legacy_dsa(dsa, data, is_private)
- || !EVP_PKEY_assign_DSA(pkey, dsa)) {
- php_openssl_store_errors();
- EVP_PKEY_free(pkey);
- DSA_free(dsa);
- return NULL;
- }
- return pkey;
- #endif
- }
- static BIGNUM *php_openssl_dh_pub_from_priv(BIGNUM *priv_key, BIGNUM *g, BIGNUM *p)
- {
- BIGNUM *pub_key, *priv_key_const_time;
- BN_CTX *ctx;
- pub_key = BN_new();
- if (pub_key == NULL) {
- php_openssl_store_errors();
- return NULL;
- }
- priv_key_const_time = BN_new();
- if (priv_key_const_time == NULL) {
- BN_free(pub_key);
- php_openssl_store_errors();
- return NULL;
- }
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- BN_free(pub_key);
- BN_free(priv_key_const_time);
- php_openssl_store_errors();
- return NULL;
- }
- BN_with_flags(priv_key_const_time, priv_key, BN_FLG_CONSTTIME);
- if (!BN_mod_exp_mont(pub_key, g, priv_key_const_time, p, ctx, NULL)) {
- BN_free(pub_key);
- php_openssl_store_errors();
- pub_key = NULL;
- }
- BN_free(priv_key_const_time);
- BN_CTX_free(ctx);
- return pub_key;
- }
- #if PHP_OPENSSL_API_VERSION < 0x30000
- static bool php_openssl_pkey_init_legacy_dh(DH *dh, zval *data, bool *is_private)
- {
- BIGNUM *p, *q, *g, *priv_key, *pub_key;
- OPENSSL_PKEY_SET_BN(data, p);
- OPENSSL_PKEY_SET_BN(data, q);
- OPENSSL_PKEY_SET_BN(data, g);
- if (!p || !g || !DH_set0_pqg(dh, p, q, g)) {
- return 0;
- }
- OPENSSL_PKEY_SET_BN(data, priv_key);
- OPENSSL_PKEY_SET_BN(data, pub_key);
- *is_private = priv_key != NULL;
- if (pub_key) {
- return DH_set0_key(dh, pub_key, priv_key);
- }
- if (priv_key) {
- pub_key = php_openssl_dh_pub_from_priv(priv_key, g, p);
- if (pub_key == NULL) {
- return 0;
- }
- return DH_set0_key(dh, pub_key, priv_key);
- }
-
- PHP_OPENSSL_RAND_ADD_TIME();
- if (!DH_generate_key(dh)) {
- php_openssl_store_errors();
- return 0;
- }
-
- *is_private = true;
- return 1;
- }
- #endif
- static EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
- {
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
- EVP_PKEY *param_key = NULL, *pkey = NULL;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
- OSSL_PARAM *params = NULL;
- OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
- OPENSSL_PKEY_SET_BN(data, p);
- OPENSSL_PKEY_SET_BN(data, q);
- OPENSSL_PKEY_SET_BN(data, g);
- OPENSSL_PKEY_SET_BN(data, priv_key);
- OPENSSL_PKEY_SET_BN(data, pub_key);
- *is_private = false;
- if (!ctx || !bld || !p || !g) {
- goto cleanup;
- }
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p);
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g);
- if (q) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q);
- }
- if (priv_key) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv_key);
- if (!pub_key) {
- pub_key = php_openssl_dh_pub_from_priv(priv_key, g, p);
- if (!pub_key) {
- goto cleanup;
- }
- }
- }
- if (pub_key) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_key);
- }
- params = OSSL_PARAM_BLD_to_param(bld);
- if (!params) {
- goto cleanup;
- }
- if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
- EVP_PKEY_fromdata(ctx, ¶m_key, EVP_PKEY_KEYPAIR, params) <= 0) {
- goto cleanup;
- }
- if (pub_key || priv_key) {
- *is_private = priv_key != NULL;
- EVP_PKEY_up_ref(param_key);
- pkey = param_key;
- } else {
- *is_private = true;
- PHP_OPENSSL_RAND_ADD_TIME();
- EVP_PKEY_CTX_free(ctx);
- ctx = EVP_PKEY_CTX_new(param_key, NULL);
- if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
- goto cleanup;
- }
- }
- cleanup:
- php_openssl_store_errors();
- EVP_PKEY_free(param_key);
- EVP_PKEY_CTX_free(ctx);
- OSSL_PARAM_free(params);
- OSSL_PARAM_BLD_free(bld);
- BN_free(p);
- BN_free(q);
- BN_free(g);
- BN_free(priv_key);
- BN_free(pub_key);
- return pkey;
- #else
- EVP_PKEY *pkey = EVP_PKEY_new();
- if (!pkey) {
- php_openssl_store_errors();
- return NULL;
- }
- DH *dh = DH_new();
- if (!dh) {
- EVP_PKEY_free(pkey);
- return NULL;
- }
- if (!php_openssl_pkey_init_legacy_dh(dh, data, is_private)
- || !EVP_PKEY_assign_DH(pkey, dh)) {
- php_openssl_store_errors();
- EVP_PKEY_free(pkey);
- DH_free(dh);
- return NULL;
- }
- return pkey;
- #endif
- }
- #ifdef HAVE_EVP_PKEY_EC
- #if PHP_OPENSSL_API_VERSION < 0x30000
- static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_private) {
- EC_GROUP *group = NULL;
- EC_POINT *pnt = NULL;
- BIGNUM *d = NULL;
- zval *bn;
- zval *x;
- zval *y;
- *is_private = false;
- if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL &&
- Z_TYPE_P(bn) == IS_STRING) {
- int nid = OBJ_sn2nid(Z_STRVAL_P(bn));
- if (nid != NID_undef) {
- group = EC_GROUP_new_by_curve_name(nid);
- if (!group) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
- EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
- if (!EC_KEY_set_group(eckey, group)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- }
- if (group == NULL) {
- php_error_docref(NULL, E_WARNING, "Unknown curve name");
- goto clean_exit;
- }
-
- if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL &&
- Z_TYPE_P(bn) == IS_STRING) {
- *is_private = true;
- d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL);
- if (!EC_KEY_set_private_key(eckey, d)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
-
-
- pnt = EC_POINT_new(group);
- if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- BN_free(d);
- } else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL &&
- Z_TYPE_P(x) == IS_STRING &&
- (y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL &&
- Z_TYPE_P(y) == IS_STRING) {
- pnt = EC_POINT_new(group);
- if (pnt == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- if (!EC_POINT_set_affine_coordinates_GFp(
- group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL),
- BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- if (pnt != NULL) {
- if (!EC_KEY_set_public_key(eckey, pnt)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- EC_POINT_free(pnt);
- pnt = NULL;
- }
- if (!EC_KEY_check_key(eckey)) {
- *is_private = true;
- PHP_OPENSSL_RAND_ADD_TIME();
- EC_KEY_generate_key(eckey);
- php_openssl_store_errors();
- }
- if (EC_KEY_check_key(eckey)) {
- EC_GROUP_free(group);
- return true;
- } else {
- php_openssl_store_errors();
- }
- clean_exit:
- BN_free(d);
- EC_POINT_free(pnt);
- EC_GROUP_free(group);
- return false;
- }
- #endif
- static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- BIGNUM *d = NULL, *x = NULL, *y = NULL;
- EC_GROUP *group = NULL;
- EC_POINT *pnt = NULL;
- unsigned char *pnt_oct = NULL;
- EVP_PKEY *param_key = NULL, *pkey = NULL;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
- OSSL_PARAM *params = NULL;
- OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
- zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1);
- OPENSSL_PKEY_SET_BN(data, d);
- OPENSSL_PKEY_SET_BN(data, x);
- OPENSSL_PKEY_SET_BN(data, y);
- *is_private = false;
- if (!ctx || !bld || !curve_name_zv || Z_TYPE_P(curve_name_zv) != IS_STRING) {
- goto cleanup;
- }
- int nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv));
- group = EC_GROUP_new_by_curve_name(nid);
- if (!group) {
- php_error_docref(NULL, E_WARNING, "Unknown curve name");
- goto cleanup;
- }
- OSSL_PARAM_BLD_push_utf8_string(
- bld, OSSL_PKEY_PARAM_GROUP_NAME, Z_STRVAL_P(curve_name_zv), Z_STRLEN_P(curve_name_zv));
- if (d) {
- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d);
- pnt = EC_POINT_new(group);
- if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
- goto cleanup;
- }
- } else if (x && y) {
-
- pnt = EC_POINT_new(group);
- if (!pnt || !EC_POINT_set_affine_coordinates(group, pnt, x, y, NULL)) {
- goto cleanup;
- }
- }
- if (pnt) {
- size_t pnt_oct_len =
- EC_POINT_point2buf(group, pnt, POINT_CONVERSION_COMPRESSED, &pnt_oct, NULL);
- if (!pnt_oct_len) {
- goto cleanup;
- }
- OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pnt_oct, pnt_oct_len);
- }
- params = OSSL_PARAM_BLD_to_param(bld);
- if (!params) {
- goto cleanup;
- }
- if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
- EVP_PKEY_fromdata(ctx, ¶m_key, EVP_PKEY_KEYPAIR, params) <= 0) {
- goto cleanup;
- }
- EVP_PKEY_CTX_free(ctx);
- ctx = EVP_PKEY_CTX_new(param_key, NULL);
- if (EVP_PKEY_check(ctx)) {
- *is_private = d != NULL;
- EVP_PKEY_up_ref(param_key);
- pkey = param_key;
- } else {
- *is_private = true;
- PHP_OPENSSL_RAND_ADD_TIME();
- if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
- goto cleanup;
- }
- }
- cleanup:
- php_openssl_store_errors();
- EVP_PKEY_free(param_key);
- EVP_PKEY_CTX_free(ctx);
- OSSL_PARAM_free(params);
- OSSL_PARAM_BLD_free(bld);
- EC_POINT_free(pnt);
- EC_GROUP_free(group);
- OPENSSL_free(pnt_oct);
- BN_free(d);
- BN_free(x);
- BN_free(y);
- return pkey;
- #else
- EVP_PKEY *pkey = EVP_PKEY_new();
- if (!pkey) {
- php_openssl_store_errors();
- return NULL;
- }
- EC_KEY *ec = EC_KEY_new();
- if (!ec) {
- EVP_PKEY_free(pkey);
- return NULL;
- }
- if (!php_openssl_pkey_init_legacy_ec(ec, data, is_private)
- || !EVP_PKEY_assign_EC_KEY(pkey, ec)) {
- php_openssl_store_errors();
- EVP_PKEY_free(pkey);
- EC_KEY_free(ec);
- return NULL;
- }
- return pkey;
- #endif
- }
- #endif
- PHP_FUNCTION(openssl_pkey_new)
- {
- struct php_x509_request req;
- zval * args = NULL;
- zval *data;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &args) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- if (args && Z_TYPE_P(args) == IS_ARRAY) {
- EVP_PKEY *pkey;
- if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "rsa", sizeof("rsa")-1)) != NULL &&
- Z_TYPE_P(data) == IS_ARRAY) {
- pkey = php_openssl_pkey_init_rsa(data);
- if (!pkey) {
- RETURN_FALSE;
- }
- php_openssl_pkey_object_init(return_value, pkey, true);
- return;
- } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "dsa", sizeof("dsa") - 1)) != NULL &&
- Z_TYPE_P(data) == IS_ARRAY) {
- bool is_private;
- pkey = php_openssl_pkey_init_dsa(data, &is_private);
- if (!pkey) {
- RETURN_FALSE;
- }
- php_openssl_pkey_object_init(return_value, pkey, is_private);
- return;
- } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "dh", sizeof("dh") - 1)) != NULL &&
- Z_TYPE_P(data) == IS_ARRAY) {
- bool is_private;
- pkey = php_openssl_pkey_init_dh(data, &is_private);
- if (!pkey) {
- RETURN_FALSE;
- }
- php_openssl_pkey_object_init(return_value, pkey, is_private);
- return;
- #ifdef HAVE_EVP_PKEY_EC
- } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ec", sizeof("ec") - 1)) != NULL &&
- Z_TYPE_P(data) == IS_ARRAY) {
- bool is_private;
- pkey = php_openssl_pkey_init_ec(data, &is_private);
- if (!pkey) {
- RETURN_FALSE;
- }
- php_openssl_pkey_object_init(return_value, pkey, is_private);
- return;
- #endif
- }
- }
- PHP_SSL_REQ_INIT(&req);
- if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
- if (php_openssl_generate_private_key(&req)) {
-
- php_openssl_pkey_object_init(return_value, req.priv_key, true);
-
- req.priv_key = NULL;
- }
- }
- PHP_SSL_REQ_DISPOSE(&req);
- }
- PHP_FUNCTION(openssl_pkey_export_to_file)
- {
- struct php_x509_request req;
- zval * zpkey, * args = NULL;
- char * passphrase = NULL;
- size_t passphrase_len = 0;
- char * filename = NULL, file_path[MAXPATHLEN];
- size_t filename_len = 0;
- int pem_write = 0;
- EVP_PKEY * key;
- BIO * bio_out = NULL;
- const EVP_CIPHER * cipher;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zp|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(passphrase_len, passphrase, 3);
- key = php_openssl_pkey_from_zval(zpkey, 0, passphrase, passphrase_len, 1);
- if (key == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Cannot get key from parameter 1");
- }
- RETURN_FALSE;
- }
- if (!php_openssl_check_path(filename, filename_len, file_path, 2)) {
- RETURN_FALSE;
- }
- PHP_SSL_REQ_INIT(&req);
- if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
- bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (bio_out == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- if (passphrase && req.priv_key_encrypt) {
- if (req.priv_key_encrypt_cipher) {
- cipher = req.priv_key_encrypt_cipher;
- } else {
- cipher = (EVP_CIPHER *) EVP_des_ede3_cbc();
- }
- } else {
- cipher = NULL;
- }
- pem_write = PEM_write_bio_PrivateKey(
- bio_out, key, cipher,
- (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL);
- if (pem_write) {
-
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- }
- clean_exit:
- PHP_SSL_REQ_DISPOSE(&req);
- EVP_PKEY_free(key);
- BIO_free(bio_out);
- }
- PHP_FUNCTION(openssl_pkey_export)
- {
- struct php_x509_request req;
- zval * zpkey, * args = NULL, *out;
- char * passphrase = NULL; size_t passphrase_len = 0;
- int pem_write = 0;
- EVP_PKEY * key;
- BIO * bio_out = NULL;
- const EVP_CIPHER * cipher;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(passphrase_len, passphrase, 3);
- key = php_openssl_pkey_from_zval(zpkey, 0, passphrase, passphrase_len, 1);
- if (key == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Cannot get key from parameter 1");
- }
- RETURN_FALSE;
- }
- PHP_SSL_REQ_INIT(&req);
- if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
- bio_out = BIO_new(BIO_s_mem());
- if (passphrase && req.priv_key_encrypt) {
- if (req.priv_key_encrypt_cipher) {
- cipher = req.priv_key_encrypt_cipher;
- } else {
- cipher = (EVP_CIPHER *) EVP_des_ede3_cbc();
- }
- } else {
- cipher = NULL;
- }
- pem_write = PEM_write_bio_PrivateKey(
- bio_out, key, cipher,
- (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL);
- if (pem_write) {
-
- char * bio_mem_ptr;
- long bio_mem_len;
- RETVAL_TRUE;
- bio_mem_len = BIO_get_mem_data(bio_out, &bio_mem_ptr);
- ZEND_TRY_ASSIGN_REF_STRINGL(out, bio_mem_ptr, bio_mem_len);
- } else {
- php_openssl_store_errors();
- }
- }
- PHP_SSL_REQ_DISPOSE(&req);
- EVP_PKEY_free(key);
- BIO_free(bio_out);
- }
- PHP_FUNCTION(openssl_pkey_get_public)
- {
- zval *cert;
- EVP_PKEY *pkey;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &cert) == FAILURE) {
- RETURN_THROWS();
- }
- pkey = php_openssl_pkey_from_zval(cert, 1, NULL, 0, 1);
- if (pkey == NULL) {
- RETURN_FALSE;
- }
- php_openssl_pkey_object_init(return_value, pkey, false);
- }
- PHP_FUNCTION(openssl_pkey_free)
- {
- zval *key;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &key, php_openssl_pkey_ce) == FAILURE) {
- RETURN_THROWS();
- }
- }
- PHP_FUNCTION(openssl_pkey_get_private)
- {
- zval *cert;
- EVP_PKEY *pkey;
- char * passphrase = "";
- size_t passphrase_len = sizeof("")-1;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|s!", &cert, &passphrase, &passphrase_len) == FAILURE) {
- RETURN_THROWS();
- }
- if (passphrase) {
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(passphrase_len, passphrase, 2);
- }
- pkey = php_openssl_pkey_from_zval(cert, 0, passphrase, passphrase_len, 1);
- if (pkey == NULL) {
- RETURN_FALSE;
- }
- php_openssl_pkey_object_init(return_value, pkey, true);
- }
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- static void php_openssl_copy_bn_param(
- zval *ary, EVP_PKEY *pkey, const char *param, const char *name) {
- BIGNUM *bn = NULL;
- if (EVP_PKEY_get_bn_param(pkey, param, &bn) > 0) {
- php_openssl_add_bn_to_array(ary, bn, name);
- BN_free(bn);
- }
- }
- static zend_string *php_openssl_get_utf8_param(
- EVP_PKEY *pkey, const char *param, const char *name) {
- char buf[64];
- size_t len;
- if (EVP_PKEY_get_utf8_string_param(pkey, param, buf, sizeof(buf), &len) > 0) {
- zend_string *str = zend_string_alloc(len, 0);
- memcpy(ZSTR_VAL(str), buf, len);
- ZSTR_VAL(str)[len] = '\0';
- return str;
- }
- return NULL;
- }
- #endif
- PHP_FUNCTION(openssl_pkey_get_details)
- {
- zval *key;
- unsigned int pbio_len;
- char *pbio;
- zend_long ktype;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &key, php_openssl_pkey_ce) == FAILURE) {
- RETURN_THROWS();
- }
- EVP_PKEY *pkey = Z_OPENSSL_PKEY_P(key)->pkey;
- BIO *out = BIO_new(BIO_s_mem());
- if (!PEM_write_bio_PUBKEY(out, pkey)) {
- BIO_free(out);
- php_openssl_store_errors();
- RETURN_FALSE;
- }
- pbio_len = BIO_get_mem_data(out, &pbio);
- array_init(return_value);
- add_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey));
- add_assoc_stringl(return_value, "key", pbio, pbio_len);
-
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- zval ary;
- switch (EVP_PKEY_base_id(pkey)) {
- case EVP_PKEY_RSA:
- ktype = OPENSSL_KEYTYPE_RSA;
- array_init(&ary);
- add_assoc_zval(return_value, "rsa", &ary);
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_N, "n");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_E, "e");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_D, "d");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, "p");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, "q");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_EXPONENT1, "dmp1");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_EXPONENT2, "dmq1");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, "iqmp");
- break;
- case EVP_PKEY_DSA:
- ktype = OPENSSL_KEYTYPE_DSA;
- array_init(&ary);
- add_assoc_zval(return_value, "dsa", &ary);
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_FFC_P, "p");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_FFC_Q, "q");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_FFC_G, "g");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_PRIV_KEY, "priv_key");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_PUB_KEY, "pub_key");
- break;
- case EVP_PKEY_DH:
- ktype = OPENSSL_KEYTYPE_DH;
- array_init(&ary);
- add_assoc_zval(return_value, "dh", &ary);
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_FFC_P, "p");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_FFC_G, "g");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_PRIV_KEY, "priv_key");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_PUB_KEY, "pub_key");
- break;
- case EVP_PKEY_EC: {
- ktype = OPENSSL_KEYTYPE_EC;
- array_init(&ary);
- add_assoc_zval(return_value, "ec", &ary);
- zend_string *curve_name = php_openssl_get_utf8_param(
- pkey, OSSL_PKEY_PARAM_GROUP_NAME, "curve_name");
- if (curve_name) {
- add_assoc_str(&ary, "curve_name", curve_name);
- int nid = OBJ_sn2nid(ZSTR_VAL(curve_name));
- if (nid != NID_undef) {
- ASN1_OBJECT *obj = OBJ_nid2obj(nid);
- if (obj) {
-
- char oir_buf[80];
- int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
- add_assoc_stringl(&ary, "curve_oid", oir_buf, oir_len);
- ASN1_OBJECT_free(obj);
- }
- }
- }
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_EC_PUB_X, "x");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_EC_PUB_Y, "y");
- php_openssl_copy_bn_param(&ary, pkey, OSSL_PKEY_PARAM_PRIV_KEY, "d");
- break;
- }
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- #else
- switch (EVP_PKEY_base_id(pkey)) {
- case EVP_PKEY_RSA:
- case EVP_PKEY_RSA2:
- {
- RSA *rsa = EVP_PKEY_get0_RSA(pkey);
- ktype = OPENSSL_KEYTYPE_RSA;
- if (rsa != NULL) {
- zval z_rsa;
- const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
- RSA_get0_key(rsa, &n, &e, &d);
- RSA_get0_factors(rsa, &p, &q);
- RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
- array_init(&z_rsa);
- OPENSSL_PKEY_GET_BN(z_rsa, n);
- OPENSSL_PKEY_GET_BN(z_rsa, e);
- OPENSSL_PKEY_GET_BN(z_rsa, d);
- OPENSSL_PKEY_GET_BN(z_rsa, p);
- OPENSSL_PKEY_GET_BN(z_rsa, q);
- OPENSSL_PKEY_GET_BN(z_rsa, dmp1);
- OPENSSL_PKEY_GET_BN(z_rsa, dmq1);
- OPENSSL_PKEY_GET_BN(z_rsa, iqmp);
- add_assoc_zval(return_value, "rsa", &z_rsa);
- }
- }
- break;
- case EVP_PKEY_DSA:
- case EVP_PKEY_DSA2:
- case EVP_PKEY_DSA3:
- case EVP_PKEY_DSA4:
- {
- DSA *dsa = EVP_PKEY_get0_DSA(pkey);
- ktype = OPENSSL_KEYTYPE_DSA;
- if (dsa != NULL) {
- zval z_dsa;
- const BIGNUM *p, *q, *g, *priv_key, *pub_key;
- DSA_get0_pqg(dsa, &p, &q, &g);
- DSA_get0_key(dsa, &pub_key, &priv_key);
- array_init(&z_dsa);
- OPENSSL_PKEY_GET_BN(z_dsa, p);
- OPENSSL_PKEY_GET_BN(z_dsa, q);
- OPENSSL_PKEY_GET_BN(z_dsa, g);
- OPENSSL_PKEY_GET_BN(z_dsa, priv_key);
- OPENSSL_PKEY_GET_BN(z_dsa, pub_key);
- add_assoc_zval(return_value, "dsa", &z_dsa);
- }
- }
- break;
- case EVP_PKEY_DH:
- {
- DH *dh = EVP_PKEY_get0_DH(pkey);
- ktype = OPENSSL_KEYTYPE_DH;
- if (dh != NULL) {
- zval z_dh;
- const BIGNUM *p, *q, *g, *priv_key, *pub_key;
- DH_get0_pqg(dh, &p, &q, &g);
- DH_get0_key(dh, &pub_key, &priv_key);
- array_init(&z_dh);
- OPENSSL_PKEY_GET_BN(z_dh, p);
- OPENSSL_PKEY_GET_BN(z_dh, g);
- OPENSSL_PKEY_GET_BN(z_dh, priv_key);
- OPENSSL_PKEY_GET_BN(z_dh, pub_key);
- add_assoc_zval(return_value, "dh", &z_dh);
- }
- }
- break;
- #ifdef HAVE_EVP_PKEY_EC
- case EVP_PKEY_EC:
- ktype = OPENSSL_KEYTYPE_EC;
- if (EVP_PKEY_get0_EC_KEY(pkey) != NULL) {
- zval ec;
- const EC_GROUP *ec_group;
- const EC_POINT *pub;
- int nid;
- char *crv_sn;
- ASN1_OBJECT *obj;
-
- char oir_buf[80];
- const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
- BIGNUM *x = BN_new();
- BIGNUM *y = BN_new();
- const BIGNUM *d;
- ec_group = EC_KEY_get0_group(ec_key);
-
- nid = EC_GROUP_get_curve_name(ec_group);
- if (nid == NID_undef) {
- break;
- }
- array_init(&ec);
-
- crv_sn = (char*) OBJ_nid2sn(nid);
- if (crv_sn != NULL) {
- add_assoc_string(&ec, "curve_name", crv_sn);
- }
- obj = OBJ_nid2obj(nid);
- if (obj != NULL) {
- int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
- add_assoc_stringl(&ec, "curve_oid", (char*) oir_buf, oir_len);
- ASN1_OBJECT_free(obj);
- }
- pub = EC_KEY_get0_public_key(ec_key);
- if (EC_POINT_get_affine_coordinates_GFp(ec_group, pub, x, y, NULL)) {
- php_openssl_add_bn_to_array(&ec, x, "x");
- php_openssl_add_bn_to_array(&ec, y, "y");
- } else {
- php_openssl_store_errors();
- }
- if ((d = EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(pkey))) != NULL) {
- php_openssl_add_bn_to_array(&ec, d, "d");
- }
- add_assoc_zval(return_value, "ec", &ec);
- BN_free(x);
- BN_free(y);
- }
- break;
- #endif
- default:
- ktype = -1;
- break;
- }
- #endif
- add_assoc_long(return_value, "type", ktype);
- BIO_free(out);
- }
- static zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t key_size) {
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL);
- if (!ctx) {
- return NULL;
- }
- if (EVP_PKEY_derive_init(ctx) <= 0 ||
- EVP_PKEY_derive_set_peer(ctx, peer_key) <= 0 ||
- (key_size == 0 && EVP_PKEY_derive(ctx, NULL, &key_size) <= 0)) {
- php_openssl_store_errors();
- EVP_PKEY_CTX_free(ctx);
- return NULL;
- }
- zend_string *result = zend_string_alloc(key_size, 0);
- if (EVP_PKEY_derive(ctx, (unsigned char *)ZSTR_VAL(result), &key_size) <= 0) {
- php_openssl_store_errors();
- zend_string_release_ex(result, 0);
- EVP_PKEY_CTX_free(ctx);
- return NULL;
- }
- ZSTR_LEN(result) = key_size;
- ZSTR_VAL(result)[key_size] = 0;
- EVP_PKEY_CTX_free(ctx);
- return result;
- }
- static zend_string *php_openssl_dh_compute_key(EVP_PKEY *pkey, char *pub_str, size_t pub_len) {
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- EVP_PKEY *peer_key = EVP_PKEY_new();
- if (!peer_key || EVP_PKEY_copy_parameters(peer_key, pkey) <= 0 ||
- EVP_PKEY_set1_encoded_public_key(peer_key, (unsigned char *) pub_str, pub_len) <= 0) {
- php_openssl_store_errors();
- EVP_PKEY_free(peer_key);
- return NULL;
- }
- zend_string *result = php_openssl_pkey_derive(pkey, peer_key, 0);
- EVP_PKEY_free(peer_key);
- return result;
- #else
- DH *dh = EVP_PKEY_get0_DH(pkey);
- if (dh == NULL) {
- return NULL;
- }
- BIGNUM *pub = BN_bin2bn((unsigned char*)pub_str, (int)pub_len, NULL);
- zend_string *data = zend_string_alloc(DH_size(dh), 0);
- int len = DH_compute_key((unsigned char*)ZSTR_VAL(data), pub, dh);
- BN_free(pub);
- if (len < 0) {
- php_openssl_store_errors();
- zend_string_release_ex(data, 0);
- return NULL;
- }
- ZSTR_LEN(data) = len;
- ZSTR_VAL(data)[len] = 0;
- return data;
- #endif
- }
- PHP_FUNCTION(openssl_dh_compute_key)
- {
- zval *key;
- char *pub_str;
- size_t pub_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sO", &pub_str, &pub_len, &key, php_openssl_pkey_ce) == FAILURE) {
- RETURN_THROWS();
- }
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(pub_len, pub_key, 1);
- EVP_PKEY *pkey = Z_OPENSSL_PKEY_P(key)->pkey;
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) {
- RETURN_FALSE;
- }
- zend_string *result = php_openssl_dh_compute_key(pkey, pub_str, pub_len);
- if (result) {
- RETURN_NEW_STR(result);
- } else {
- RETURN_FALSE;
- }
- }
- PHP_FUNCTION(openssl_pkey_derive)
- {
- zval *priv_key;
- zval *peer_pub_key;
- zend_long key_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|l", &peer_pub_key, &priv_key, &key_len) == FAILURE) {
- RETURN_THROWS();
- }
- if (key_len < 0) {
- zend_argument_value_error(3, "must be greater than or equal to 0");
- RETURN_THROWS();
- }
- EVP_PKEY *pkey = php_openssl_pkey_from_zval(priv_key, 0, "", 0, 2);
- if (!pkey) {
- RETURN_FALSE;
- }
- EVP_PKEY *peer_key = php_openssl_pkey_from_zval(peer_pub_key, 1, NULL, 0, 1);
- if (!peer_key) {
- EVP_PKEY_free(pkey);
- RETURN_FALSE;
- }
- zend_string *result = php_openssl_pkey_derive(pkey, peer_key, key_len);
- EVP_PKEY_free(pkey);
- EVP_PKEY_free(peer_key);
- if (result) {
- RETURN_NEW_STR(result);
- } else {
- RETURN_FALSE;
- }
- }
- PHP_FUNCTION(openssl_pbkdf2)
- {
- zend_long key_length = 0, iterations = 0;
- char *password;
- size_t password_len;
- char *salt;
- size_t salt_len;
- char *method;
- size_t method_len = 0;
- zend_string *out_buffer;
- const EVP_MD *digest;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssll|s",
- &password, &password_len,
- &salt, &salt_len,
- &key_length, &iterations,
- &method, &method_len) == FAILURE) {
- RETURN_THROWS();
- }
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(password_len, password, 1);
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(salt_len, salt, 2);
- PHP_OPENSSL_CHECK_LONG_TO_INT(key_length, key, 3);
- PHP_OPENSSL_CHECK_LONG_TO_INT(iterations, iterations, 4);
- if (key_length <= 0) {
- zend_argument_value_error(3, "must be greater than 0");
- RETURN_THROWS();
- }
- if (method_len) {
- digest = EVP_get_digestbyname(method);
- } else {
- digest = EVP_sha1();
- }
- if (!digest) {
- php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
- RETURN_FALSE;
- }
- out_buffer = zend_string_alloc(key_length, 0);
- if (PKCS5_PBKDF2_HMAC(password, (int)password_len, (unsigned char *)salt, (int)salt_len, (int)iterations, digest, (int)key_length, (unsigned char*)ZSTR_VAL(out_buffer)) == 1) {
- ZSTR_VAL(out_buffer)[key_length] = 0;
- RETURN_NEW_STR(out_buffer);
- } else {
- php_openssl_store_errors();
- zend_string_release_ex(out_buffer, 0);
- RETURN_FALSE;
- }
- }
- static BIO *php_openssl_bio_new_file(
- const char *filename, size_t filename_len, uint32_t arg_num, const char *mode) {
- char file_path[MAXPATHLEN];
- BIO *bio;
- if (!php_openssl_check_path(filename, filename_len, file_path, arg_num)) {
- return NULL;
- }
- bio = BIO_new_file(file_path, mode);
- if (bio == NULL) {
- php_openssl_store_errors();
- return NULL;
- }
- return bio;
- }
- PHP_FUNCTION(openssl_pkcs7_verify)
- {
- X509_STORE * store = NULL;
- zval * cainfo = NULL;
- STACK_OF(X509) *signers= NULL;
- STACK_OF(X509) *others = NULL;
- PKCS7 * p7 = NULL;
- BIO * in = NULL, * datain = NULL, * dataout = NULL, * p7bout = NULL;
- zend_long flags = 0;
- char * filename;
- size_t filename_len;
- char * extracerts = NULL;
- size_t extracerts_len = 0;
- char * signersfilename = NULL;
- size_t signersfilename_len = 0;
- char * datafilename = NULL;
- size_t datafilename_len = 0;
- char * p7bfilename = NULL;
- size_t p7bfilename_len = 0;
- RETVAL_LONG(-1);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "pl|p!ap!p!p!", &filename, &filename_len,
- &flags, &signersfilename, &signersfilename_len, &cainfo,
- &extracerts, &extracerts_len, &datafilename, &datafilename_len, &p7bfilename, &p7bfilename_len) == FAILURE) {
- RETURN_THROWS();
- }
- if (extracerts) {
- others = php_openssl_load_all_certs_from_file(extracerts, extracerts_len, 5);
- if (others == NULL) {
- goto clean_exit;
- }
- }
- flags = flags & ~PKCS7_DETACHED;
- store = php_openssl_setup_verify(cainfo, 4);
- if (!store) {
- goto clean_exit;
- }
- in = php_openssl_bio_new_file(filename, filename_len, 1, PHP_OPENSSL_BIO_MODE_R(flags));
- if (in == NULL) {
- goto clean_exit;
- }
- p7 = SMIME_read_PKCS7(in, &datain);
- if (p7 == NULL) {
- #if DEBUG_SMIME
- zend_printf("SMIME_read_PKCS7 failed\n");
- #endif
- php_openssl_store_errors();
- goto clean_exit;
- }
- if (datafilename) {
- dataout = php_openssl_bio_new_file(
- datafilename, datafilename_len, 6, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (dataout == NULL) {
- goto clean_exit;
- }
- }
- if (p7bfilename) {
- p7bout = php_openssl_bio_new_file(
- p7bfilename, p7bfilename_len, 7, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (p7bout == NULL) {
- goto clean_exit;
- }
- }
- #if DEBUG_SMIME
- zend_printf("Calling PKCS7 verify\n");
- #endif
- if (PKCS7_verify(p7, others, store, datain, dataout, (int)flags)) {
- RETVAL_TRUE;
- if (signersfilename) {
- BIO *certout;
- certout = php_openssl_bio_new_file(
- signersfilename, signersfilename_len, 3, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (certout) {
- int i;
- signers = PKCS7_get0_signers(p7, NULL, (int)flags);
- if (signers != NULL) {
- for (i = 0; i < sk_X509_num(signers); i++) {
- if (!PEM_write_bio_X509(certout, sk_X509_value(signers, i))) {
- php_openssl_store_errors();
- RETVAL_LONG(-1);
- php_error_docref(NULL, E_WARNING, "Failed to write signer %d", i);
- }
- }
- sk_X509_free(signers);
- } else {
- RETVAL_LONG(-1);
- php_openssl_store_errors();
- }
- BIO_free(certout);
- } else {
- php_error_docref(NULL, E_WARNING, "Signature OK, but cannot open %s for writing", signersfilename);
- RETVAL_LONG(-1);
- }
- if (p7bout) {
- PEM_write_bio_PKCS7(p7bout, p7);
- }
- }
- } else {
- php_openssl_store_errors();
- RETVAL_FALSE;
- }
- clean_exit:
- if (p7bout) {
- BIO_free(p7bout);
- }
- X509_STORE_free(store);
- BIO_free(datain);
- BIO_free(in);
- BIO_free(dataout);
- PKCS7_free(p7);
- sk_X509_pop_free(others, X509_free);
- }
- PHP_FUNCTION(openssl_pkcs7_encrypt)
- {
- zval * zrecipcerts, * zheaders = NULL;
- STACK_OF(X509) * recipcerts = NULL;
- BIO * infile = NULL, * outfile = NULL;
- zend_long flags = 0;
- PKCS7 * p7 = NULL;
- zval * zcertval;
- X509 * cert;
- const EVP_CIPHER *cipher = NULL;
- zend_long cipherid = PHP_OPENSSL_CIPHER_DEFAULT;
- zend_string * strindex;
- char * infilename = NULL;
- size_t infilename_len;
- char * outfilename = NULL;
- size_t outfilename_len;
- RETVAL_FALSE;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ppza!|ll", &infilename, &infilename_len,
- &outfilename, &outfilename_len, &zrecipcerts, &zheaders, &flags, &cipherid) == FAILURE) {
- RETURN_THROWS();
- }
- infile = php_openssl_bio_new_file(infilename, infilename_len, 1, PHP_OPENSSL_BIO_MODE_R(flags));
- if (infile == NULL) {
- goto clean_exit;
- }
- outfile = php_openssl_bio_new_file(outfilename, outfilename_len, 2, PHP_OPENSSL_BIO_MODE_W(flags));
- if (outfile == NULL) {
- goto clean_exit;
- }
- recipcerts = sk_X509_new_null();
-
- if (Z_TYPE_P(zrecipcerts) == IS_ARRAY) {
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zrecipcerts), zcertval) {
- bool free_cert;
- cert = php_openssl_x509_from_zval(zcertval, &free_cert, 3, true, NULL);
- if (cert == NULL) {
-
- goto clean_exit;
- }
- if (!free_cert) {
-
- cert = X509_dup(cert);
- if (cert == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- sk_X509_push(recipcerts, cert);
- } ZEND_HASH_FOREACH_END();
- } else {
-
- bool free_cert;
- cert = php_openssl_x509_from_zval(zrecipcerts, &free_cert, 3, false, NULL);
- if (cert == NULL) {
-
- goto clean_exit;
- }
- if (!free_cert) {
-
- cert = X509_dup(cert);
- if (cert == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- sk_X509_push(recipcerts, cert);
- }
-
- cipher = php_openssl_get_evp_cipher_from_algo(cipherid);
- if (cipher == NULL) {
-
- php_error_docref(NULL, E_WARNING, "Failed to get cipher");
- goto clean_exit;
- }
- p7 = PKCS7_encrypt(recipcerts, infile, (EVP_CIPHER*)cipher, (int)flags);
- if (p7 == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
-
- if (zheaders) {
- ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, zcertval) {
- zend_string *str = zval_try_get_string(zcertval);
- if (UNEXPECTED(!str)) {
- goto clean_exit;
- }
- if (strindex) {
- BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
- } else {
- BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
- }
- zend_string_release(str);
- } ZEND_HASH_FOREACH_END();
- }
- (void)BIO_reset(infile);
-
- if (!SMIME_write_PKCS7(outfile, p7, infile, (int)flags)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- RETVAL_TRUE;
- clean_exit:
- PKCS7_free(p7);
- BIO_free(infile);
- BIO_free(outfile);
- if (recipcerts) {
- sk_X509_pop_free(recipcerts, X509_free);
- }
- }
- PHP_FUNCTION(openssl_pkcs7_read)
- {
- zval * zout = NULL, zcert;
- char *p7b;
- size_t p7b_len;
- STACK_OF(X509) *certs = NULL;
- STACK_OF(X509_CRL) *crls = NULL;
- BIO * bio_in = NULL, * bio_out = NULL;
- PKCS7 * p7 = NULL;
- int i;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &p7b, &p7b_len,
- &zout) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(p7b_len, p7b, 1);
- bio_in = BIO_new(BIO_s_mem());
- if (bio_in == NULL) {
- goto clean_exit;
- }
- if (0 >= BIO_write(bio_in, p7b, (int)p7b_len)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL);
- if (p7 == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- switch (OBJ_obj2nid(p7->type)) {
- case NID_pkcs7_signed:
- if (p7->d.sign != NULL) {
- certs = p7->d.sign->cert;
- crls = p7->d.sign->crl;
- }
- break;
- case NID_pkcs7_signedAndEnveloped:
- if (p7->d.signed_and_enveloped != NULL) {
- certs = p7->d.signed_and_enveloped->cert;
- crls = p7->d.signed_and_enveloped->crl;
- }
- break;
- default:
- break;
- }
- zout = zend_try_array_init(zout);
- if (!zout) {
- goto clean_exit;
- }
- if (certs != NULL) {
- for (i = 0; i < sk_X509_num(certs); i++) {
- X509* ca = sk_X509_value(certs, i);
- bio_out = BIO_new(BIO_s_mem());
- if (bio_out && PEM_write_bio_X509(bio_out, ca)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length);
- add_index_zval(zout, i, &zcert);
- BIO_free(bio_out);
- }
- }
- }
- if (crls != NULL) {
- for (i = 0; i < sk_X509_CRL_num(crls); i++) {
- X509_CRL* crl = sk_X509_CRL_value(crls, i);
- bio_out = BIO_new(BIO_s_mem());
- if (bio_out && PEM_write_bio_X509_CRL(bio_out, crl)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length);
- add_index_zval(zout, i, &zcert);
- BIO_free(bio_out);
- }
- }
- }
- RETVAL_TRUE;
- clean_exit:
- BIO_free(bio_in);
- if (p7 != NULL) {
- PKCS7_free(p7);
- }
- }
- PHP_FUNCTION(openssl_pkcs7_sign)
- {
- X509 *cert = NULL;
- zend_object *cert_obj;
- zend_string *cert_str;
- zval *zprivkey, * zheaders;
- zval * hval;
- EVP_PKEY * privkey = NULL;
- zend_long flags = PKCS7_DETACHED;
- PKCS7 * p7 = NULL;
- BIO * infile = NULL, * outfile = NULL;
- STACK_OF(X509) *others = NULL;
- zend_string * strindex;
- char * infilename;
- size_t infilename_len;
- char * outfilename;
- size_t outfilename_len;
- char * extracertsfilename = NULL;
- size_t extracertsfilename_len;
- ZEND_PARSE_PARAMETERS_START(5, 7)
- Z_PARAM_PATH(infilename, infilename_len)
- Z_PARAM_PATH(outfilename, outfilename_len)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_ZVAL(zprivkey)
- Z_PARAM_ARRAY_OR_NULL(zheaders)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(flags)
- Z_PARAM_PATH_OR_NULL(extracertsfilename, extracertsfilename_len)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- if (extracertsfilename) {
- others = php_openssl_load_all_certs_from_file(
- extracertsfilename, extracertsfilename_len, 7);
- if (others == NULL) {
- goto clean_exit;
- }
- }
- privkey = php_openssl_pkey_from_zval(zprivkey, 0, "", 0, 4);
- if (privkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Error getting private key");
- }
- goto clean_exit;
- }
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 3);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- goto clean_exit;
- }
- infile = php_openssl_bio_new_file(infilename, infilename_len, 1, PHP_OPENSSL_BIO_MODE_R(flags));
- if (infile == NULL) {
- php_error_docref(NULL, E_WARNING, "Error opening input file %s!", infilename);
- goto clean_exit;
- }
- outfile = php_openssl_bio_new_file(outfilename, outfilename_len, 2, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (outfile == NULL) {
- php_error_docref(NULL, E_WARNING, "Error opening output file %s!", outfilename);
- goto clean_exit;
- }
- p7 = PKCS7_sign(cert, privkey, others, infile, (int)flags);
- if (p7 == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error creating PKCS7 structure!");
- goto clean_exit;
- }
- (void)BIO_reset(infile);
-
- if (zheaders) {
- int ret;
- ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, hval) {
- zend_string *str = zval_try_get_string(hval);
- if (UNEXPECTED(!str)) {
- goto clean_exit;
- }
- if (strindex) {
- ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
- } else {
- ret = BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
- }
- zend_string_release(str);
- if (ret < 0) {
- php_openssl_store_errors();
- }
- } ZEND_HASH_FOREACH_END();
- }
-
- if (!SMIME_write_PKCS7(outfile, p7, infile, (int)flags)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- RETVAL_TRUE;
- clean_exit:
- PKCS7_free(p7);
- BIO_free(infile);
- BIO_free(outfile);
- if (others) {
- sk_X509_pop_free(others, X509_free);
- }
- EVP_PKEY_free(privkey);
- if (cert && cert_str) {
- X509_free(cert);
- }
- }
- PHP_FUNCTION(openssl_pkcs7_decrypt)
- {
- X509 *cert;
- zval *recipcert, *recipkey = NULL;
- bool free_recipcert;
- EVP_PKEY * key = NULL;
- BIO * in = NULL, *out = NULL, *datain = NULL;
- PKCS7 * p7 = NULL;
- char * infilename;
- size_t infilename_len;
- char * outfilename;
- size_t outfilename_len;
- ZEND_PARSE_PARAMETERS_START(3, 4)
- Z_PARAM_PATH(infilename, infilename_len)
- Z_PARAM_PATH(outfilename, outfilename_len)
- Z_PARAM_ZVAL(recipcert)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_OR_NULL(recipkey)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- cert = php_openssl_x509_from_zval(recipcert, &free_recipcert, 3, false, NULL);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- goto clean_exit;
- }
- key = php_openssl_pkey_from_zval(recipkey ? recipkey : recipcert, 0, "", 0, 4);
- if (key == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Unable to get private key");
- }
- goto clean_exit;
- }
- in = php_openssl_bio_new_file(
- infilename, infilename_len, 1, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
- if (in == NULL) {
- goto clean_exit;
- }
- out = php_openssl_bio_new_file(
- outfilename, outfilename_len, 2, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY));
- if (out == NULL) {
- goto clean_exit;
- }
- p7 = SMIME_read_PKCS7(in, &datain);
- if (p7 == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- if (PKCS7_decrypt(p7, key, cert, out, PKCS7_DETACHED)) {
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- clean_exit:
- PKCS7_free(p7);
- BIO_free(datain);
- BIO_free(in);
- BIO_free(out);
- if (cert && free_recipcert) {
- X509_free(cert);
- }
- EVP_PKEY_free(key);
- }
- PHP_FUNCTION(openssl_cms_verify)
- {
- X509_STORE * store = NULL;
- zval * cainfo = NULL;
- STACK_OF(X509) *signers= NULL;
- STACK_OF(X509) *others = NULL;
- CMS_ContentInfo * cms = NULL;
- BIO * in = NULL, * datain = NULL, * dataout = NULL, * p7bout = NULL;
- BIO *certout = NULL, *sigbio = NULL;
- zend_long flags = 0;
- char * filename;
- size_t filename_len;
- char * extracerts = NULL;
- size_t extracerts_len = 0;
- char * signersfilename = NULL;
- size_t signersfilename_len = 0;
- char * datafilename = NULL;
- size_t datafilename_len = 0;
- char * p7bfilename = NULL;
- size_t p7bfilename_len = 0;
- char * sigfile = NULL;
- size_t sigfile_len = 0;
- zend_long encoding = ENCODING_SMIME;
- RETVAL_FALSE;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "pl|p!ap!p!p!p!l", &filename, &filename_len,
- &flags, &signersfilename, &signersfilename_len, &cainfo,
- &extracerts, &extracerts_len, &datafilename, &datafilename_len,
- &p7bfilename, &p7bfilename_len,
- &sigfile, &sigfile_len, &encoding) == FAILURE) {
- RETURN_THROWS();
- }
- in = php_openssl_bio_new_file(filename, filename_len, 1, PHP_OPENSSL_BIO_MODE_R(flags));
- if (in == NULL) {
- goto clean_exit;
- }
- if (sigfile && (flags & CMS_DETACHED)) {
- sigbio = php_openssl_bio_new_file(sigfile, sigfile_len, 1, PHP_OPENSSL_BIO_MODE_R(flags));
- if (encoding == ENCODING_SMIME) {
- php_error_docref(NULL, E_WARNING,
- "Detached signatures not possible with S/MIME encoding");
- goto clean_exit;
- }
- } else {
- sigbio = in;
- }
- switch (encoding) {
- case ENCODING_PEM:
- cms = PEM_read_bio_CMS(sigbio, NULL, 0, NULL);
- datain = in;
- break;
- case ENCODING_DER:
- cms = d2i_CMS_bio(sigbio, NULL);
- datain = in;
- break;
- case ENCODING_SMIME:
- cms = SMIME_read_CMS(sigbio, &datain);
- break;
- default:
- php_error_docref(NULL, E_WARNING, "Unknown encoding");
- goto clean_exit;
- }
- if (cms == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- if (encoding != ENCODING_SMIME && !(flags & CMS_DETACHED)) {
- datain = NULL;
- }
- if (extracerts) {
- others = php_openssl_load_all_certs_from_file(extracerts, extracerts_len, 5);
- if (others == NULL) {
- goto clean_exit;
- }
- }
- store = php_openssl_setup_verify(cainfo, 4);
- if (!store) {
- goto clean_exit;
- }
- if (datafilename) {
- dataout = php_openssl_bio_new_file(
- datafilename, datafilename_len, 6, PHP_OPENSSL_BIO_MODE_W(CMS_BINARY));
- if (dataout == NULL) {
- goto clean_exit;
- }
- }
- if (p7bfilename) {
- p7bout = php_openssl_bio_new_file(
- p7bfilename, p7bfilename_len, 7, PHP_OPENSSL_BIO_MODE_W(CMS_BINARY));
- if (p7bout == NULL) {
- goto clean_exit;
- }
- }
- #if DEBUG_SMIME
- zend_printf("Calling CMS verify\n");
- #endif
- if (CMS_verify(cms, others, store, datain, dataout, (unsigned int)flags)) {
- RETVAL_TRUE;
- if (signersfilename) {
- certout = php_openssl_bio_new_file(
- signersfilename, signersfilename_len, 3, PHP_OPENSSL_BIO_MODE_W(CMS_BINARY));
- if (certout) {
- int i;
- signers = CMS_get0_signers(cms);
- if (signers != NULL) {
- for (i = 0; i < sk_X509_num(signers); i++) {
- if (!PEM_write_bio_X509(certout, sk_X509_value(signers, i))) {
- php_openssl_store_errors();
- RETVAL_FALSE;
- php_error_docref(NULL, E_WARNING, "Failed to write signer %d", i);
- }
- }
- sk_X509_free(signers);
- } else {
- RETVAL_FALSE;
- php_openssl_store_errors();
- }
- } else {
- php_error_docref(NULL, E_WARNING, "Signature OK, but cannot open %s for writing", signersfilename);
- RETVAL_FALSE;
- }
- if (p7bout) {
- PEM_write_bio_CMS(p7bout, cms);
- }
- }
- } else {
- php_openssl_store_errors();
- RETVAL_FALSE;
- }
- clean_exit:
- BIO_free(p7bout);
- if (store) {
- X509_STORE_free(store);
- }
- if (datain != in) {
- BIO_free(datain);
- }
- if (sigbio != in) {
- BIO_free(sigbio);
- }
- BIO_free(in);
- BIO_free(dataout);
- BIO_free(certout);
- if (cms) {
- CMS_ContentInfo_free(cms);
- }
- if (others) {
- sk_X509_pop_free(others, X509_free);
- }
- }
- PHP_FUNCTION(openssl_cms_encrypt)
- {
- zval * zrecipcerts, * zheaders = NULL;
- STACK_OF(X509) * recipcerts = NULL;
- BIO * infile = NULL, * outfile = NULL;
- zend_long flags = 0;
- zend_long encoding = ENCODING_SMIME;
- CMS_ContentInfo * cms = NULL;
- zval * zcertval;
- X509 * cert;
- const EVP_CIPHER *cipher = NULL;
- zend_long cipherid = PHP_OPENSSL_CIPHER_DEFAULT;
- zend_string * strindex;
- char * infilename = NULL;
- size_t infilename_len;
- char * outfilename = NULL;
- size_t outfilename_len;
- int need_final = 0;
- RETVAL_FALSE;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ppza!|lll", &infilename, &infilename_len,
- &outfilename, &outfilename_len, &zrecipcerts, &zheaders, &flags, &encoding, &cipherid) == FAILURE) {
- RETURN_THROWS();
- }
- infile = php_openssl_bio_new_file(
- infilename, infilename_len, 1, PHP_OPENSSL_BIO_MODE_R(flags));
- if (infile == NULL) {
- goto clean_exit;
- }
- outfile = php_openssl_bio_new_file(
- outfilename, outfilename_len, 2, PHP_OPENSSL_BIO_MODE_W(flags));
- if (outfile == NULL) {
- goto clean_exit;
- }
- recipcerts = sk_X509_new_null();
-
- if (Z_TYPE_P(zrecipcerts) == IS_ARRAY) {
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zrecipcerts), zcertval) {
- bool free_cert;
- cert = php_openssl_x509_from_zval(zcertval, &free_cert, 3, true, NULL);
- if (cert == NULL) {
- goto clean_exit;
- }
- if (!free_cert) {
-
- cert = X509_dup(cert);
- if (cert == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- sk_X509_push(recipcerts, cert);
- } ZEND_HASH_FOREACH_END();
- } else {
-
- bool free_cert;
- cert = php_openssl_x509_from_zval(zrecipcerts, &free_cert, 3, false, NULL);
- if (cert == NULL) {
- goto clean_exit;
- }
- if (!free_cert) {
-
- cert = X509_dup(cert);
- if (cert == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- sk_X509_push(recipcerts, cert);
- }
-
- cipher = php_openssl_get_evp_cipher_from_algo(cipherid);
- if (cipher == NULL) {
-
- php_error_docref(NULL, E_WARNING, "Failed to get cipher");
- goto clean_exit;
- }
- cms = CMS_encrypt(recipcerts, infile, (EVP_CIPHER*)cipher, (unsigned int)flags);
- if (cms == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- if (flags & CMS_PARTIAL && !(flags & CMS_STREAM)) {
- need_final=1;
- }
-
- if (zheaders && encoding == ENCODING_SMIME) {
- ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, zcertval) {
- zend_string *str = zval_try_get_string(zcertval);
- if (UNEXPECTED(!str)) {
- goto clean_exit;
- }
- if (strindex) {
- BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
- } else {
- BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
- }
- zend_string_release(str);
- } ZEND_HASH_FOREACH_END();
- }
- (void)BIO_reset(infile);
- switch (encoding) {
- case ENCODING_SMIME:
- if (!SMIME_write_CMS(outfile, cms, infile, (int)flags)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- break;
- case ENCODING_DER:
- if (need_final) {
- if (CMS_final(cms, infile, NULL, (unsigned int) flags) != 1) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- if (i2d_CMS_bio(outfile, cms) != 1) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- break;
- case ENCODING_PEM:
- if (need_final) {
- if (CMS_final(cms, infile, NULL, (unsigned int) flags) != 1) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- if (flags & CMS_STREAM) {
- if (PEM_write_bio_CMS_stream(outfile, cms, infile, flags) == 0) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- } else {
- if (PEM_write_bio_CMS(outfile, cms) == 0) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- break;
- default:
- php_error_docref(NULL, E_WARNING, "Unknown OPENSSL encoding");
- goto clean_exit;
- }
- RETVAL_TRUE;
- clean_exit:
- if (cms) {
- CMS_ContentInfo_free(cms);
- }
- BIO_free(infile);
- BIO_free(outfile);
- if (recipcerts) {
- sk_X509_pop_free(recipcerts, X509_free);
- }
- }
- PHP_FUNCTION(openssl_cms_read)
- {
- zval * zout = NULL, zcert;
- char *p7b;
- size_t p7b_len;
- STACK_OF(X509) *certs = NULL;
- STACK_OF(X509_CRL) *crls = NULL;
- BIO * bio_in = NULL, * bio_out = NULL;
- CMS_ContentInfo * cms = NULL;
- int i;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &p7b, &p7b_len,
- &zout) == FAILURE) {
- RETURN_THROWS();
- }
- RETVAL_FALSE;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(p7b_len, p7b, 1);
- bio_in = BIO_new(BIO_s_mem());
- if (bio_in == NULL) {
- goto clean_exit;
- }
- if (0 >= BIO_write(bio_in, p7b, (int)p7b_len)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- cms = PEM_read_bio_CMS(bio_in, NULL, NULL, NULL);
- if (cms == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- switch (OBJ_obj2nid(CMS_get0_type(cms))) {
- case NID_pkcs7_signed:
- case NID_pkcs7_signedAndEnveloped:
- certs = CMS_get1_certs(cms);
- crls = CMS_get1_crls(cms);
- break;
- default:
- break;
- }
- zout = zend_try_array_init(zout);
- if (!zout) {
- goto clean_exit;
- }
- if (certs != NULL) {
- for (i = 0; i < sk_X509_num(certs); i++) {
- X509* ca = sk_X509_value(certs, i);
- bio_out = BIO_new(BIO_s_mem());
- if (bio_out && PEM_write_bio_X509(bio_out, ca)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length);
- add_index_zval(zout, i, &zcert);
- BIO_free(bio_out);
- }
- }
- }
- if (crls != NULL) {
- for (i = 0; i < sk_X509_CRL_num(crls); i++) {
- X509_CRL* crl = sk_X509_CRL_value(crls, i);
- bio_out = BIO_new(BIO_s_mem());
- if (bio_out && PEM_write_bio_X509_CRL(bio_out, crl)) {
- BUF_MEM *bio_buf;
- BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length);
- add_index_zval(zout, i, &zcert);
- BIO_free(bio_out);
- }
- }
- }
- RETVAL_TRUE;
- clean_exit:
- BIO_free(bio_in);
- if (cms != NULL) {
- CMS_ContentInfo_free(cms);
- }
- if (certs != NULL) {
- sk_X509_pop_free(certs, X509_free);
- }
- if (crls != NULL) {
- sk_X509_CRL_pop_free(crls, X509_CRL_free);
- }
- }
- PHP_FUNCTION(openssl_cms_sign)
- {
- X509 *cert = NULL;
- zend_object *cert_obj;
- zend_string *cert_str;
- zval *zprivkey, *zheaders;
- zval * hval;
- EVP_PKEY * privkey = NULL;
- zend_long flags = 0;
- zend_long encoding = ENCODING_SMIME;
- CMS_ContentInfo * cms = NULL;
- BIO * infile = NULL, * outfile = NULL;
- STACK_OF(X509) *others = NULL;
- zend_string * strindex;
- char * infilename;
- size_t infilename_len;
- char * outfilename;
- size_t outfilename_len;
- char * extracertsfilename = NULL;
- size_t extracertsfilename_len;
- int need_final = 0;
- ZEND_PARSE_PARAMETERS_START(5, 8)
- Z_PARAM_PATH(infilename, infilename_len)
- Z_PARAM_PATH(outfilename, outfilename_len)
- Z_PARAM_OBJ_OF_CLASS_OR_STR(cert_obj, php_openssl_certificate_ce, cert_str)
- Z_PARAM_ZVAL(zprivkey)
- Z_PARAM_ARRAY_OR_NULL(zheaders)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(flags)
- Z_PARAM_LONG(encoding)
- Z_PARAM_PATH_OR_NULL(extracertsfilename, extracertsfilename_len)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- if (extracertsfilename) {
- others = php_openssl_load_all_certs_from_file(
- extracertsfilename, extracertsfilename_len, 8);
- if (others == NULL) {
- goto clean_exit;
- }
- }
- privkey = php_openssl_pkey_from_zval(zprivkey, 0, "", 0, 4);
- if (privkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Error getting private key");
- }
- goto clean_exit;
- }
- cert = php_openssl_x509_from_param(cert_obj, cert_str, 3);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- goto clean_exit;
- }
- if ((encoding & ENCODING_SMIME) && (flags & CMS_DETACHED)) {
- php_error_docref(NULL,
- E_WARNING, "Detached signatures not possible with S/MIME encoding");
- goto clean_exit;
- }
-
- if (flags & CMS_PARTIAL && !(flags & CMS_STREAM)) {
- need_final=1;
- }
- infile = php_openssl_bio_new_file(
- infilename, infilename_len, 1, PHP_OPENSSL_BIO_MODE_R(flags));
- if (infile == NULL) {
- php_error_docref(NULL, E_WARNING, "Error opening input file %s!", infilename);
- goto clean_exit;
- }
- outfile = php_openssl_bio_new_file(
- outfilename, outfilename_len, 2, PHP_OPENSSL_BIO_MODE_W(CMS_BINARY));
- if (outfile == NULL) {
- php_error_docref(NULL, E_WARNING, "Error opening output file %s!", outfilename);
- goto clean_exit;
- }
- cms = CMS_sign(cert, privkey, others, infile, (unsigned int)flags);
- if (cms == NULL) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Error creating CMS structure!");
- goto clean_exit;
- }
- if (BIO_reset(infile) != 0) {
- php_openssl_store_errors();
- goto clean_exit;
- }
-
- if (zheaders && encoding == ENCODING_SMIME) {
- int ret;
- ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, hval) {
- zend_string *str = zval_try_get_string(hval);
- if (UNEXPECTED(!str)) {
- goto clean_exit;
- }
- if (strindex) {
- ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
- } else {
- ret = BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
- }
- zend_string_release(str);
- if (ret < 0) {
- php_openssl_store_errors();
- }
- } ZEND_HASH_FOREACH_END();
- }
-
- switch (encoding) {
- case ENCODING_SMIME:
- if (!SMIME_write_CMS(outfile, cms, infile, (int)flags)) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- break;
- case ENCODING_DER:
- if (need_final) {
- if (CMS_final(cms, infile, NULL, (unsigned int) flags) != 1) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- if (i2d_CMS_bio(outfile, cms) != 1) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- break;
- case ENCODING_PEM:
- if (need_final) {
- if (CMS_final(cms, infile, NULL, (unsigned int) flags) != 1) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- if (flags & CMS_STREAM) {
- if (PEM_write_bio_CMS_stream(outfile, cms, infile, flags) == 0) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- } else {
- if (PEM_write_bio_CMS(outfile, cms) == 0) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- }
- break;
- default:
- php_error_docref(NULL, E_WARNING, "Unknown OPENSSL encoding");
- goto clean_exit;
- }
- RETVAL_TRUE;
- clean_exit:
- if (cms) {
- CMS_ContentInfo_free(cms);
- }
- BIO_free(infile);
- BIO_free(outfile);
- if (others) {
- sk_X509_pop_free(others, X509_free);
- }
- EVP_PKEY_free(privkey);
- if (cert && cert_str) {
- X509_free(cert);
- }
- }
- PHP_FUNCTION(openssl_cms_decrypt)
- {
- X509 *cert;
- zval *recipcert, *recipkey = NULL;
- bool free_recipcert;
- EVP_PKEY * key = NULL;
- zend_long encoding = ENCODING_SMIME;
- BIO * in = NULL, * out = NULL, * datain = NULL;
- CMS_ContentInfo * cms = NULL;
- char * infilename;
- size_t infilename_len;
- char * outfilename;
- size_t outfilename_len;
- ZEND_PARSE_PARAMETERS_START(3, 5)
- Z_PARAM_PATH(infilename, infilename_len)
- Z_PARAM_PATH(outfilename, outfilename_len)
- Z_PARAM_ZVAL(recipcert)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_OR_NULL(recipkey)
- Z_PARAM_LONG(encoding)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_FALSE;
- cert = php_openssl_x509_from_zval(recipcert, &free_recipcert, 3, false, NULL);
- if (cert == NULL) {
- php_error_docref(NULL, E_WARNING, "X.509 Certificate cannot be retrieved");
- goto clean_exit;
- }
- key = php_openssl_pkey_from_zval(recipkey ? recipkey : recipcert, 0, "", 0, recipkey ? 4 : 3);
- if (key == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Unable to get private key");
- }
- goto clean_exit;
- }
- in = php_openssl_bio_new_file(
- infilename, infilename_len, 1, PHP_OPENSSL_BIO_MODE_R(CMS_BINARY));
- if (in == NULL) {
- goto clean_exit;
- }
- out = php_openssl_bio_new_file(
- outfilename, outfilename_len, 2, PHP_OPENSSL_BIO_MODE_W(CMS_BINARY));
- if (out == NULL) {
- goto clean_exit;
- }
- switch (encoding) {
- case ENCODING_DER:
- cms = d2i_CMS_bio(in, NULL);
- break;
- case ENCODING_PEM:
- cms = PEM_read_bio_CMS(in, NULL, 0, NULL);
- break;
- case ENCODING_SMIME:
- cms = SMIME_read_CMS(in, &datain);
- break;
- default:
- zend_argument_value_error(5, "must be an OPENSSL_ENCODING_* constant");
- goto clean_exit;
- }
- if (cms == NULL) {
- php_openssl_store_errors();
- goto clean_exit;
- }
- if (CMS_decrypt(cms, key, cert, NULL, out, 0)) {
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- }
- clean_exit:
- if (cms) {
- CMS_ContentInfo_free(cms);
- }
- BIO_free(datain);
- BIO_free(in);
- BIO_free(out);
- if (cert && free_recipcert) {
- X509_free(cert);
- }
- EVP_PKEY_free(key);
- }
- PHP_FUNCTION(openssl_private_encrypt)
- {
- zval *key, *crypted;
- char * data;
- size_t data_len;
- zend_long padding = RSA_PKCS1_PADDING;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
- RETURN_THROWS();
- }
- EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 0, "", 0, 3);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "key param is not a valid private key");
- }
- RETURN_FALSE;
- }
- size_t out_len = 0;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (!ctx || EVP_PKEY_sign_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
- EVP_PKEY_sign(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- zend_string *out = zend_string_alloc(out_len, 0);
- if (EVP_PKEY_sign(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
- (unsigned char *) data, data_len) <= 0) {
- zend_string_release(out);
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- ZSTR_VAL(out)[out_len] = '\0';
- ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
- RETVAL_TRUE;
- cleanup:
- EVP_PKEY_CTX_free(ctx);
- EVP_PKEY_free(pkey);
- }
- PHP_FUNCTION(openssl_private_decrypt)
- {
- zval *key, *crypted;
- zend_long padding = RSA_PKCS1_PADDING;
- char * data;
- size_t data_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
- RETURN_THROWS();
- }
- EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 0, "", 0, 3);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "key parameter is not a valid private key");
- }
- RETURN_FALSE;
- }
- size_t out_len = 0;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (!ctx || EVP_PKEY_decrypt_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
- EVP_PKEY_decrypt(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- zend_string *out = zend_string_alloc(out_len, 0);
- if (EVP_PKEY_decrypt(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
- (unsigned char *) data, data_len) <= 0) {
- zend_string_release(out);
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- out = zend_string_truncate(out, out_len, 0);
- ZSTR_VAL(out)[out_len] = '\0';
- ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
- RETVAL_TRUE;
- cleanup:
- EVP_PKEY_CTX_free(ctx);
- EVP_PKEY_free(pkey);
- }
- PHP_FUNCTION(openssl_public_encrypt)
- {
- zval *key, *crypted;
- zend_long padding = RSA_PKCS1_PADDING;
- char * data;
- size_t data_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
- RETURN_THROWS();
- }
- EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 1, NULL, 0, 3);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "key parameter is not a valid public key");
- }
- RETURN_FALSE;
- }
- size_t out_len = 0;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (!ctx || EVP_PKEY_encrypt_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
- EVP_PKEY_encrypt(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- zend_string *out = zend_string_alloc(out_len, 0);
- if (EVP_PKEY_encrypt(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
- (unsigned char *) data, data_len) <= 0) {
- zend_string_release(out);
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- ZSTR_VAL(out)[out_len] = '\0';
- ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
- RETVAL_TRUE;
- cleanup:
- EVP_PKEY_CTX_free(ctx);
- EVP_PKEY_free(pkey);
- }
- PHP_FUNCTION(openssl_public_decrypt)
- {
- zval *key, *crypted;
- zend_long padding = RSA_PKCS1_PADDING;
- char * data;
- size_t data_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
- RETURN_THROWS();
- }
- EVP_PKEY *pkey = php_openssl_pkey_from_zval(key, 1, NULL, 0, 3);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "key parameter is not a valid public key");
- }
- RETURN_FALSE;
- }
- size_t out_len = 0;
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (!ctx || EVP_PKEY_verify_recover_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
- EVP_PKEY_verify_recover(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) {
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- zend_string *out = zend_string_alloc(out_len, 0);
- if (EVP_PKEY_verify_recover(ctx, (unsigned char *) ZSTR_VAL(out), &out_len,
- (unsigned char *) data, data_len) <= 0) {
- zend_string_release(out);
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto cleanup;
- }
- out = zend_string_truncate(out, out_len, 0);
- ZSTR_VAL(out)[out_len] = '\0';
- ZEND_TRY_ASSIGN_REF_NEW_STR(crypted, out);
- RETVAL_TRUE;
- cleanup:
- EVP_PKEY_CTX_free(ctx);
- EVP_PKEY_free(pkey);
- }
- PHP_FUNCTION(openssl_error_string)
- {
- char buf[256];
- unsigned long val;
- if (zend_parse_parameters_none() == FAILURE) {
- RETURN_THROWS();
- }
- php_openssl_store_errors();
- if (OPENSSL_G(errors) == NULL || OPENSSL_G(errors)->top == OPENSSL_G(errors)->bottom) {
- RETURN_FALSE;
- }
- OPENSSL_G(errors)->bottom = (OPENSSL_G(errors)->bottom + 1) % ERR_NUM_ERRORS;
- val = OPENSSL_G(errors)->buffer[OPENSSL_G(errors)->bottom];
- if (val) {
- ERR_error_string_n(val, buf, 256);
- RETURN_STRING(buf);
- } else {
- RETURN_FALSE;
- }
- }
- PHP_FUNCTION(openssl_sign)
- {
- zval *key, *signature;
- EVP_PKEY *pkey;
- unsigned int siglen;
- zend_string *sigbuf;
- char * data;
- size_t data_len;
- EVP_MD_CTX *md_ctx;
- zend_string *method_str = NULL;
- zend_long method_long = OPENSSL_ALGO_SHA1;
- const EVP_MD *mdtype;
- ZEND_PARSE_PARAMETERS_START(3, 4)
- Z_PARAM_STRING(data, data_len)
- Z_PARAM_ZVAL(signature)
- Z_PARAM_ZVAL(key)
- Z_PARAM_OPTIONAL
- Z_PARAM_STR_OR_LONG(method_str, method_long)
- ZEND_PARSE_PARAMETERS_END();
- pkey = php_openssl_pkey_from_zval(key, 0, "", 0, 3);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Supplied key param cannot be coerced into a private key");
- }
- RETURN_FALSE;
- }
- if (method_str) {
- mdtype = EVP_get_digestbyname(ZSTR_VAL(method_str));
- } else {
- mdtype = php_openssl_get_evp_md_from_algo(method_long);
- }
- if (!mdtype) {
- php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
- RETURN_FALSE;
- }
- siglen = EVP_PKEY_size(pkey);
- sigbuf = zend_string_alloc(siglen, 0);
- md_ctx = EVP_MD_CTX_create();
- if (md_ctx != NULL &&
- EVP_SignInit(md_ctx, mdtype) &&
- EVP_SignUpdate(md_ctx, data, data_len) &&
- EVP_SignFinal(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, pkey)) {
- ZSTR_VAL(sigbuf)[siglen] = '\0';
- ZSTR_LEN(sigbuf) = siglen;
- ZEND_TRY_ASSIGN_REF_NEW_STR(signature, sigbuf);
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- efree(sigbuf);
- RETVAL_FALSE;
- }
- EVP_MD_CTX_destroy(md_ctx);
- EVP_PKEY_free(pkey);
- }
- PHP_FUNCTION(openssl_verify)
- {
- zval *key;
- EVP_PKEY *pkey;
- int err = 0;
- EVP_MD_CTX *md_ctx;
- const EVP_MD *mdtype;
- char * data;
- size_t data_len;
- char * signature;
- size_t signature_len;
- zend_string *method_str = NULL;
- zend_long method_long = OPENSSL_ALGO_SHA1;
- ZEND_PARSE_PARAMETERS_START(3, 4)
- Z_PARAM_STRING(data, data_len)
- Z_PARAM_STRING(signature, signature_len)
- Z_PARAM_ZVAL(key)
- Z_PARAM_OPTIONAL
- Z_PARAM_STR_OR_LONG(method_str, method_long)
- ZEND_PARSE_PARAMETERS_END();
- PHP_OPENSSL_CHECK_SIZE_T_TO_UINT(signature_len, signature, 2);
- if (method_str) {
- mdtype = EVP_get_digestbyname(ZSTR_VAL(method_str));
- } else {
- mdtype = php_openssl_get_evp_md_from_algo(method_long);
- }
- if (!mdtype) {
- php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
- RETURN_FALSE;
- }
- pkey = php_openssl_pkey_from_zval(key, 1, NULL, 0, 3);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Supplied key param cannot be coerced into a public key");
- }
- RETURN_FALSE;
- }
- md_ctx = EVP_MD_CTX_create();
- if (md_ctx == NULL ||
- !EVP_VerifyInit (md_ctx, mdtype) ||
- !EVP_VerifyUpdate (md_ctx, data, data_len) ||
- (err = EVP_VerifyFinal(md_ctx, (unsigned char *)signature, (unsigned int)signature_len, pkey)) < 0) {
- php_openssl_store_errors();
- }
- EVP_MD_CTX_destroy(md_ctx);
- EVP_PKEY_free(pkey);
- RETURN_LONG(err);
- }
- PHP_FUNCTION(openssl_seal)
- {
- zval *pubkeys, *pubkey, *sealdata, *ekeys, *iv = NULL;
- HashTable *pubkeysht;
- EVP_PKEY **pkeys;
- int i, len1, len2, *eksl, nkeys, iv_len;
- unsigned char iv_buf[EVP_MAX_IV_LENGTH + 1], *buf = NULL, **eks;
- char * data;
- size_t data_len;
- char *method;
- size_t method_len;
- const EVP_CIPHER *cipher;
- EVP_CIPHER_CTX *ctx;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "szzas|z", &data, &data_len,
- &sealdata, &ekeys, &pubkeys, &method, &method_len, &iv) == FAILURE) {
- RETURN_THROWS();
- }
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(data_len, data, 1);
- pubkeysht = Z_ARRVAL_P(pubkeys);
- nkeys = pubkeysht ? zend_hash_num_elements(pubkeysht) : 0;
- if (!nkeys) {
- zend_argument_value_error(4, "cannot be empty");
- RETURN_THROWS();
- }
- cipher = EVP_get_cipherbyname(method);
- if (!cipher) {
- php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
- RETURN_FALSE;
- }
- iv_len = EVP_CIPHER_iv_length(cipher);
- if (!iv && iv_len > 0) {
- zend_argument_value_error(6, "cannot be null for the chosen cipher algorithm");
- RETURN_THROWS();
- }
- pkeys = safe_emalloc(nkeys, sizeof(*pkeys), 0);
- eksl = safe_emalloc(nkeys, sizeof(*eksl), 0);
- eks = safe_emalloc(nkeys, sizeof(*eks), 0);
- memset(eks, 0, sizeof(*eks) * nkeys);
- memset(pkeys, 0, sizeof(*pkeys) * nkeys);
-
- i = 0;
- ZEND_HASH_FOREACH_VAL(pubkeysht, pubkey) {
- pkeys[i] = php_openssl_pkey_from_zval(pubkey, 1, NULL, 0, 4);
- if (pkeys[i] == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Not a public key (%dth member of pubkeys)", i+1);
- }
- RETVAL_FALSE;
- goto clean_exit;
- }
- eks[i] = emalloc(EVP_PKEY_size(pkeys[i]) + 1);
- i++;
- } ZEND_HASH_FOREACH_END();
- ctx = EVP_CIPHER_CTX_new();
- if (ctx == NULL || !EVP_EncryptInit(ctx,cipher,NULL,NULL)) {
- EVP_CIPHER_CTX_free(ctx);
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto clean_exit;
- }
-
- buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(ctx));
- EVP_CIPHER_CTX_reset(ctx);
- if (EVP_SealInit(ctx, cipher, eks, eksl, &iv_buf[0], pkeys, nkeys) <= 0 ||
- !EVP_SealUpdate(ctx, buf, &len1, (unsigned char *)data, (int)data_len) ||
- !EVP_SealFinal(ctx, buf + len1, &len2)) {
- efree(buf);
- EVP_CIPHER_CTX_free(ctx);
- php_openssl_store_errors();
- RETVAL_FALSE;
- goto clean_exit;
- }
- if (len1 + len2 > 0) {
- ZEND_TRY_ASSIGN_REF_NEW_STR(sealdata, zend_string_init((char*)buf, len1 + len2, 0));
- efree(buf);
- ekeys = zend_try_array_init(ekeys);
- if (!ekeys) {
- EVP_CIPHER_CTX_free(ctx);
- goto clean_exit;
- }
- for (i=0; i<nkeys; i++) {
- eks[i][eksl[i]] = '\0';
- add_next_index_stringl(ekeys, (const char*)eks[i], eksl[i]);
- efree(eks[i]);
- eks[i] = NULL;
- }
- if (iv) {
- iv_buf[iv_len] = '\0';
- ZEND_TRY_ASSIGN_REF_NEW_STR(iv, zend_string_init((char*)iv_buf, iv_len, 0));
- }
- } else {
- efree(buf);
- }
- RETVAL_LONG(len1 + len2);
- EVP_CIPHER_CTX_free(ctx);
- clean_exit:
- for (i=0; i<nkeys; i++) {
- if (pkeys[i] != NULL) {
- EVP_PKEY_free(pkeys[i]);
- }
- if (eks[i]) {
- efree(eks[i]);
- }
- }
- efree(eks);
- efree(eksl);
- efree(pkeys);
- }
- PHP_FUNCTION(openssl_open)
- {
- zval *privkey, *opendata;
- EVP_PKEY *pkey;
- int len1, len2, cipher_iv_len;
- unsigned char *buf, *iv_buf;
- EVP_CIPHER_CTX *ctx;
- char * data;
- size_t data_len;
- char * ekey;
- size_t ekey_len;
- char *method, *iv = NULL;
- size_t method_len, iv_len = 0;
- const EVP_CIPHER *cipher;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "szszs|s!", &data, &data_len, &opendata,
- &ekey, &ekey_len, &privkey, &method, &method_len, &iv, &iv_len) == FAILURE) {
- RETURN_THROWS();
- }
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(data_len, data, 1);
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT(ekey_len, ekey, 3);
- pkey = php_openssl_pkey_from_zval(privkey, 0, "", 0, 4);
- if (pkey == NULL) {
- if (!EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Unable to coerce parameter 4 into a private key");
- }
- RETURN_FALSE;
- }
- cipher = EVP_get_cipherbyname(method);
- if (!cipher) {
- php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
- RETURN_FALSE;
- }
- cipher_iv_len = EVP_CIPHER_iv_length(cipher);
- if (cipher_iv_len > 0) {
- if (!iv) {
- zend_argument_value_error(6, "cannot be null for the chosen cipher algorithm");
- RETURN_THROWS();
- }
- if ((size_t)cipher_iv_len != iv_len) {
- php_error_docref(NULL, E_WARNING, "IV length is invalid");
- RETURN_FALSE;
- }
- iv_buf = (unsigned char *)iv;
- } else {
- iv_buf = NULL;
- }
- buf = emalloc(data_len + 1);
- ctx = EVP_CIPHER_CTX_new();
- if (ctx != NULL && EVP_OpenInit(ctx, cipher, (unsigned char *)ekey, (int)ekey_len, iv_buf, pkey) &&
- EVP_OpenUpdate(ctx, buf, &len1, (unsigned char *)data, (int)data_len) &&
- EVP_OpenFinal(ctx, buf + len1, &len2) && (len1 + len2 > 0)) {
- buf[len1 + len2] = '\0';
- ZEND_TRY_ASSIGN_REF_NEW_STR(opendata, zend_string_init((char*)buf, len1 + len2, 0));
- RETVAL_TRUE;
- } else {
- php_openssl_store_errors();
- RETVAL_FALSE;
- }
- efree(buf);
- EVP_PKEY_free(pkey);
- EVP_CIPHER_CTX_free(ctx);
- }
- static void php_openssl_add_method_or_alias(const OBJ_NAME *name, void *arg)
- {
- add_next_index_string((zval*)arg, (char*)name->name);
- }
- static void php_openssl_add_method(const OBJ_NAME *name, void *arg)
- {
- if (name->alias == 0) {
- add_next_index_string((zval*)arg, (char*)name->name);
- }
- }
- PHP_FUNCTION(openssl_get_md_methods)
- {
- bool aliases = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &aliases) == FAILURE) {
- RETURN_THROWS();
- }
- array_init(return_value);
- OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
- aliases ? php_openssl_add_method_or_alias: php_openssl_add_method,
- return_value);
- }
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- static void php_openssl_add_cipher_name(const char *name, void *arg)
- {
- size_t len = strlen(name);
- zend_string *str = zend_string_alloc(len, 0);
- zend_str_tolower_copy(ZSTR_VAL(str), name, len);
- add_next_index_str((zval*)arg, str);
- }
- static void php_openssl_add_cipher_or_alias(EVP_CIPHER *cipher, void *arg)
- {
- EVP_CIPHER_names_do_all(cipher, php_openssl_add_cipher_name, arg);
- }
- static void php_openssl_add_cipher(EVP_CIPHER *cipher, void *arg)
- {
- php_openssl_add_cipher_name(EVP_CIPHER_get0_name(cipher), arg);
- }
- static int php_openssl_compare_func(Bucket *a, Bucket *b)
- {
- return string_compare_function(&a->val, &b->val);
- }
- #endif
- PHP_FUNCTION(openssl_get_cipher_methods)
- {
- bool aliases = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &aliases) == FAILURE) {
- RETURN_THROWS();
- }
- array_init(return_value);
- #if PHP_OPENSSL_API_VERSION >= 0x30000
- EVP_CIPHER_do_all_provided(NULL,
- aliases ? php_openssl_add_cipher_or_alias : php_openssl_add_cipher,
- return_value);
- zend_hash_sort(Z_ARRVAL_P(return_value), php_openssl_compare_func, 1);
- #else
- OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
- aliases ? php_openssl_add_method_or_alias : php_openssl_add_method,
- return_value);
- #endif
- }
- #ifdef HAVE_EVP_PKEY_EC
- PHP_FUNCTION(openssl_get_curve_names)
- {
- EC_builtin_curve *curves = NULL;
- const char *sname;
- size_t i;
- size_t len = EC_get_builtin_curves(NULL, 0);
- if (zend_parse_parameters_none() == FAILURE) {
- RETURN_THROWS();
- }
- curves = emalloc(sizeof(EC_builtin_curve) * len);
- if (!EC_get_builtin_curves(curves, len)) {
- RETURN_FALSE;
- }
- array_init(return_value);
- for (i = 0; i < len; i++) {
- sname = OBJ_nid2sn(curves[i].nid);
- if (sname != NULL) {
- add_next_index_string(return_value, sname);
- }
- }
- efree(curves);
- }
- #endif
- PHP_FUNCTION(openssl_digest)
- {
- bool raw_output = 0;
- char *data, *method;
- size_t data_len, method_len;
- const EVP_MD *mdtype;
- EVP_MD_CTX *md_ctx;
- unsigned int siglen;
- zend_string *sigbuf;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|b", &data, &data_len, &method, &method_len, &raw_output) == FAILURE) {
- RETURN_THROWS();
- }
- mdtype = EVP_get_digestbyname(method);
- if (!mdtype) {
- php_error_docref(NULL, E_WARNING, "Unknown digest algorithm");
- RETURN_FALSE;
- }
- siglen = EVP_MD_size(mdtype);
- sigbuf = zend_string_alloc(siglen, 0);
- md_ctx = EVP_MD_CTX_create();
- if (EVP_DigestInit(md_ctx, mdtype) &&
- EVP_DigestUpdate(md_ctx, (unsigned char *)data, data_len) &&
- EVP_DigestFinal (md_ctx, (unsigned char *)ZSTR_VAL(sigbuf), &siglen)) {
- if (raw_output) {
- ZSTR_VAL(sigbuf)[siglen] = '\0';
- ZSTR_LEN(sigbuf) = siglen;
- RETVAL_STR(sigbuf);
- } else {
- int digest_str_len = siglen * 2;
- zend_string *digest_str = zend_string_alloc(digest_str_len, 0);
- make_digest_ex(ZSTR_VAL(digest_str), (unsigned char*)ZSTR_VAL(sigbuf), siglen);
- ZSTR_VAL(digest_str)[digest_str_len] = '\0';
- zend_string_release_ex(sigbuf, 0);
- RETVAL_NEW_STR(digest_str);
- }
- } else {
- php_openssl_store_errors();
- zend_string_release_ex(sigbuf, 0);
- RETVAL_FALSE;
- }
- EVP_MD_CTX_destroy(md_ctx);
- }
- struct php_openssl_cipher_mode {
- bool is_aead;
- bool is_single_run_aead;
- bool set_tag_length_always;
- bool set_tag_length_when_encrypting;
- int aead_get_tag_flag;
- int aead_set_tag_flag;
- int aead_ivlen_flag;
- };
- static void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, const EVP_CIPHER *cipher_type)
- {
- int cipher_mode = EVP_CIPHER_mode(cipher_type);
- memset(mode, 0, sizeof(struct php_openssl_cipher_mode));
- switch (cipher_mode) {
- #ifdef EVP_CIPH_OCB_MODE
-
- case EVP_CIPH_GCM_MODE:
- case EVP_CIPH_OCB_MODE:
- case EVP_CIPH_CCM_MODE:
- mode->is_aead = 1;
-
- mode->set_tag_length_always = cipher_mode == EVP_CIPH_OCB_MODE;
- mode->set_tag_length_when_encrypting = cipher_mode == EVP_CIPH_CCM_MODE;
- mode->is_single_run_aead = cipher_mode == EVP_CIPH_CCM_MODE;
- mode->aead_get_tag_flag = EVP_CTRL_AEAD_GET_TAG;
- mode->aead_set_tag_flag = EVP_CTRL_AEAD_SET_TAG;
- mode->aead_ivlen_flag = EVP_CTRL_AEAD_SET_IVLEN;
- break;
- #else
- # ifdef EVP_CIPH_GCM_MODE
- case EVP_CIPH_GCM_MODE:
- mode->is_aead = 1;
- mode->aead_get_tag_flag = EVP_CTRL_GCM_GET_TAG;
- mode->aead_set_tag_flag = EVP_CTRL_GCM_SET_TAG;
- mode->aead_ivlen_flag = EVP_CTRL_GCM_SET_IVLEN;
- break;
- # endif
- # ifdef EVP_CIPH_CCM_MODE
- case EVP_CIPH_CCM_MODE:
- mode->is_aead = 1;
- mode->is_single_run_aead = 1;
- mode->set_tag_length_when_encrypting = 1;
- mode->aead_get_tag_flag = EVP_CTRL_CCM_GET_TAG;
- mode->aead_set_tag_flag = EVP_CTRL_CCM_SET_TAG;
- mode->aead_ivlen_flag = EVP_CTRL_CCM_SET_IVLEN;
- break;
- # endif
- #endif
- }
- }
- static int php_openssl_validate_iv(const char **piv, size_t *piv_len, size_t iv_required_len,
- bool *free_iv, EVP_CIPHER_CTX *cipher_ctx, struct php_openssl_cipher_mode *mode)
- {
- char *iv_new;
- if (mode->is_aead) {
- if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_ivlen_flag, *piv_len, NULL) != 1) {
- php_error_docref(NULL, E_WARNING, "Setting of IV length for AEAD mode failed");
- return FAILURE;
- }
- return SUCCESS;
- }
-
- if (*piv_len == iv_required_len) {
- return SUCCESS;
- }
- iv_new = ecalloc(1, iv_required_len + 1);
- if (*piv_len == 0) {
-
- *piv_len = iv_required_len;
- *piv = iv_new;
- *free_iv = 1;
- return SUCCESS;
- }
- if (*piv_len < iv_required_len) {
- php_error_docref(NULL, E_WARNING,
- "IV passed is only %zd bytes long, cipher expects an IV of precisely %zd bytes, padding with \\0",
- *piv_len, iv_required_len);
- memcpy(iv_new, *piv, *piv_len);
- *piv_len = iv_required_len;
- *piv = iv_new;
- *free_iv = 1;
- return SUCCESS;
- }
- php_error_docref(NULL, E_WARNING,
- "IV passed is %zd bytes long which is longer than the %zd expected by selected cipher, truncating",
- *piv_len, iv_required_len);
- memcpy(iv_new, *piv, iv_required_len);
- *piv_len = iv_required_len;
- *piv = iv_new;
- *free_iv = 1;
- return SUCCESS;
- }
- static int php_openssl_cipher_init(const EVP_CIPHER *cipher_type,
- EVP_CIPHER_CTX *cipher_ctx, struct php_openssl_cipher_mode *mode,
- const char **ppassword, size_t *ppassword_len, bool *free_password,
- const char **piv, size_t *piv_len, bool *free_iv,
- const char *tag, int tag_len, zend_long options, int enc)
- {
- unsigned char *key;
- int key_len, password_len;
- size_t max_iv_len;
- *free_password = 0;
- max_iv_len = EVP_CIPHER_iv_length(cipher_type);
- if (enc && *piv_len == 0 && max_iv_len > 0 && !mode->is_aead) {
- php_error_docref(NULL, E_WARNING,
- "Using an empty Initialization Vector (iv) is potentially insecure and not recommended");
- }
- if (!EVP_CipherInit_ex(cipher_ctx, cipher_type, NULL, NULL, NULL, enc)) {
- php_openssl_store_errors();
- return FAILURE;
- }
- if (php_openssl_validate_iv(piv, piv_len, max_iv_len, free_iv, cipher_ctx, mode) == FAILURE) {
- return FAILURE;
- }
- if (mode->set_tag_length_always || (enc && mode->set_tag_length_when_encrypting)) {
- if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, NULL)) {
- php_error_docref(NULL, E_WARNING, "Setting tag length for AEAD cipher failed");
- return FAILURE;
- }
- }
- if (!enc && tag && tag_len > 0) {
- if (!mode->is_aead) {
- php_error_docref(NULL, E_WARNING, "The tag cannot be used because the cipher algorithm does not support AEAD");
- } else if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, (unsigned char *) tag)) {
- php_error_docref(NULL, E_WARNING, "Setting tag for AEAD cipher decryption failed");
- return FAILURE;
- }
- }
-
- password_len = (int) *ppassword_len;
- key_len = EVP_CIPHER_key_length(cipher_type);
- if (key_len > password_len) {
- if ((OPENSSL_DONT_ZERO_PAD_KEY & options) && !EVP_CIPHER_CTX_set_key_length(cipher_ctx, password_len)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Key length cannot be set for the cipher algorithm");
- return FAILURE;
- }
- key = emalloc(key_len);
- memset(key, 0, key_len);
- memcpy(key, *ppassword, password_len);
- *ppassword = (char *) key;
- *ppassword_len = key_len;
- *free_password = 1;
- } else {
- if (password_len > key_len && !EVP_CIPHER_CTX_set_key_length(cipher_ctx, password_len)) {
- php_openssl_store_errors();
- }
- key = (unsigned char*)*ppassword;
- }
- if (!EVP_CipherInit_ex(cipher_ctx, NULL, NULL, key, (unsigned char *)*piv, enc)) {
- php_openssl_store_errors();
- return FAILURE;
- }
- if (options & OPENSSL_ZERO_PADDING) {
- EVP_CIPHER_CTX_set_padding(cipher_ctx, 0);
- }
- return SUCCESS;
- }
- static int php_openssl_cipher_update(const EVP_CIPHER *cipher_type,
- EVP_CIPHER_CTX *cipher_ctx, struct php_openssl_cipher_mode *mode,
- zend_string **poutbuf, int *poutlen, const char *data, size_t data_len,
- const char *aad, size_t aad_len, int enc)
- {
- int i = 0;
- if (mode->is_single_run_aead && !EVP_CipherUpdate(cipher_ctx, NULL, &i, NULL, (int)data_len)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Setting of data length failed");
- return FAILURE;
- }
- if (mode->is_aead && !EVP_CipherUpdate(cipher_ctx, NULL, &i, (const unsigned char *) aad, (int) aad_len)) {
- php_openssl_store_errors();
- php_error_docref(NULL, E_WARNING, "Setting of additional application data failed");
- return FAILURE;
- }
- *poutbuf = zend_string_alloc((int)data_len + EVP_CIPHER_block_size(cipher_type), 0);
- if (!EVP_CipherUpdate(cipher_ctx, (unsigned char*)ZSTR_VAL(*poutbuf),
- &i, (const unsigned char *)data, (int)data_len)) {
-
- php_openssl_store_errors();
- zend_string_release_ex(*poutbuf, 0);
- return FAILURE;
- }
- *poutlen = i;
- return SUCCESS;
- }
- PHP_OPENSSL_API zend_string* php_openssl_encrypt(
- const char *data, size_t data_len,
- const char *method, size_t method_len,
- const char *password, size_t password_len,
- zend_long options,
- const char *iv, size_t iv_len,
- zval *tag, zend_long tag_len,
- const char *aad, size_t aad_len)
- {
- const EVP_CIPHER *cipher_type;
- EVP_CIPHER_CTX *cipher_ctx;
- struct php_openssl_cipher_mode mode;
- int i = 0, outlen;
- bool free_iv = 0, free_password = 0;
- zend_string *outbuf = NULL;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(data_len, data);
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(password_len, password);
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(aad_len, aad);
- PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(tag_len, tag_len);
- cipher_type = EVP_get_cipherbyname(method);
- if (!cipher_type) {
- php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
- return NULL;
- }
- cipher_ctx = EVP_CIPHER_CTX_new();
- if (!cipher_ctx) {
- php_error_docref(NULL, E_WARNING, "Failed to create cipher context");
- return NULL;
- }
- php_openssl_load_cipher_mode(&mode, cipher_type);
- if (php_openssl_cipher_init(cipher_type, cipher_ctx, &mode,
- &password, &password_len, &free_password,
- &iv, &iv_len, &free_iv, NULL, tag_len, options, 1) == FAILURE ||
- php_openssl_cipher_update(cipher_type, cipher_ctx, &mode, &outbuf, &outlen,
- data, data_len, aad, aad_len, 1) == FAILURE) {
- outbuf = NULL;
- } else if (EVP_EncryptFinal(cipher_ctx, (unsigned char *)ZSTR_VAL(outbuf) + outlen, &i)) {
- outlen += i;
- if (options & OPENSSL_RAW_DATA) {
- ZSTR_VAL(outbuf)[outlen] = '\0';
- ZSTR_LEN(outbuf) = outlen;
- } else {
- zend_string *base64_str;
- base64_str = php_base64_encode((unsigned char*)ZSTR_VAL(outbuf), outlen);
- zend_string_release_ex(outbuf, 0);
- outbuf = base64_str;
- }
- if (mode.is_aead && tag) {
- zend_string *tag_str = zend_string_alloc(tag_len, 0);
- if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode.aead_get_tag_flag, tag_len, ZSTR_VAL(tag_str)) == 1) {
- ZSTR_VAL(tag_str)[tag_len] = '\0';
- ZSTR_LEN(tag_str) = tag_len;
- ZEND_TRY_ASSIGN_REF_NEW_STR(tag, tag_str);
- } else {
- php_error_docref(NULL, E_WARNING, "Retrieving verification tag failed");
- zend_string_release_ex(tag_str, 0);
- zend_string_release_ex(outbuf, 0);
- outbuf = NULL;
- }
- } else if (tag) {
- ZEND_TRY_ASSIGN_REF_NULL(tag);
- } else if (mode.is_aead) {
- php_error_docref(NULL, E_WARNING, "A tag should be provided when using AEAD mode");
- zend_string_release_ex(outbuf, 0);
- outbuf = NULL;
- }
- } else {
- php_openssl_store_errors();
- zend_string_release_ex(outbuf, 0);
- outbuf = NULL;
- }
- if (free_password) {
- efree((void *) password);
- }
- if (free_iv) {
- efree((void *) iv);
- }
- EVP_CIPHER_CTX_reset(cipher_ctx);
- EVP_CIPHER_CTX_free(cipher_ctx);
- return outbuf;
- }
- PHP_FUNCTION(openssl_encrypt)
- {
- zend_long options = 0, tag_len = 16;
- char *data, *method, *password, *iv = "", *aad = "";
- size_t data_len, method_len, password_len, iv_len = 0, aad_len = 0;
- zend_string *ret;
- zval *tag = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lszsl", &data, &data_len, &method, &method_len,
- &password, &password_len, &options, &iv, &iv_len, &tag, &aad, &aad_len, &tag_len) == FAILURE) {
- RETURN_THROWS();
- }
- if ((ret = php_openssl_encrypt(data, data_len, method, method_len, password, password_len, options, iv, iv_len, tag, tag_len, aad, aad_len))) {
- RETVAL_STR(ret);
- } else {
- RETVAL_FALSE;
- }
- }
- PHP_OPENSSL_API zend_string* php_openssl_decrypt(
- const char *data, size_t data_len,
- const char *method, size_t method_len,
- const char *password, size_t password_len,
- zend_long options,
- const char *iv, size_t iv_len,
- const char *tag, zend_long tag_len,
- const char *aad, size_t aad_len)
- {
- const EVP_CIPHER *cipher_type;
- EVP_CIPHER_CTX *cipher_ctx;
- struct php_openssl_cipher_mode mode;
- int i = 0, outlen;
- zend_string *base64_str = NULL;
- bool free_iv = 0, free_password = 0;
- zend_string *outbuf = NULL;
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(data_len, data);
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(password_len, password);
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(aad_len, aad);
- PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(tag_len, tag);
- cipher_type = EVP_get_cipherbyname(method);
- if (!cipher_type) {
- php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
- return NULL;
- }
- cipher_ctx = EVP_CIPHER_CTX_new();
- if (!cipher_ctx) {
- php_error_docref(NULL, E_WARNING, "Failed to create cipher context");
- return NULL;
- }
- php_openssl_load_cipher_mode(&mode, cipher_type);
- if (!(options & OPENSSL_RAW_DATA)) {
- base64_str = php_base64_decode((unsigned char*)data, data_len);
- if (!base64_str) {
- php_error_docref(NULL, E_WARNING, "Failed to base64 decode the input");
- EVP_CIPHER_CTX_free(cipher_ctx);
- return NULL;
- }
- data_len = ZSTR_LEN(base64_str);
- data = ZSTR_VAL(base64_str);
- }
- if (php_openssl_cipher_init(cipher_type, cipher_ctx, &mode,
- &password, &password_len, &free_password,
- &iv, &iv_len, &free_iv, tag, tag_len, options, 0) == FAILURE ||
- php_openssl_cipher_update(cipher_type, cipher_ctx, &mode, &outbuf, &outlen,
- data, data_len, aad, aad_len, 0) == FAILURE) {
- outbuf = NULL;
- } else if (mode.is_single_run_aead ||
- EVP_DecryptFinal(cipher_ctx, (unsigned char *)ZSTR_VAL(outbuf) + outlen, &i)) {
- outlen += i;
- ZSTR_VAL(outbuf)[outlen] = '\0';
- ZSTR_LEN(outbuf) = outlen;
- } else {
- php_openssl_store_errors();
- zend_string_release_ex(outbuf, 0);
- outbuf = NULL;
- }
- if (free_password) {
- efree((void *) password);
- }
- if (free_iv) {
- efree((void *) iv);
- }
- if (base64_str) {
- zend_string_release_ex(base64_str, 0);
- }
- EVP_CIPHER_CTX_reset(cipher_ctx);
- EVP_CIPHER_CTX_free(cipher_ctx);
- return outbuf;
- }
- PHP_FUNCTION(openssl_decrypt)
- {
- zend_long options = 0;
- char *data, *method, *password, *iv = "", *tag = NULL, *aad = "";
- size_t data_len, method_len, password_len, iv_len = 0, tag_len = 0, aad_len = 0;
- zend_string *ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lss!s", &data, &data_len, &method, &method_len,
- &password, &password_len, &options, &iv, &iv_len, &tag, &tag_len, &aad, &aad_len) == FAILURE) {
- RETURN_THROWS();
- }
- if (!method_len) {
- zend_argument_value_error(2, "cannot be empty");
- RETURN_THROWS();
- }
- if ((ret = php_openssl_decrypt(data, data_len, method, method_len, password, password_len, options, iv, iv_len, tag, tag_len, aad, aad_len))) {
- RETVAL_STR(ret);
- } else {
- RETVAL_FALSE;
- }
- }
- PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method)
- {
- const EVP_CIPHER *cipher_type;
- cipher_type = EVP_get_cipherbyname(method);
- if (!cipher_type) {
- php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
- return -1;
- }
- return EVP_CIPHER_iv_length(cipher_type);
- }
- PHP_FUNCTION(openssl_cipher_iv_length)
- {
- char *method;
- size_t method_len;
- zend_long ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &method, &method_len) == FAILURE) {
- RETURN_THROWS();
- }
- if (!method_len) {
- zend_argument_value_error(1, "cannot be empty");
- RETURN_THROWS();
- }
-
- if ((ret = php_openssl_cipher_iv_length(method)) == -1) {
- RETURN_FALSE;
- }
- RETURN_LONG(ret);
- }
- PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_length)
- {
- zend_string *buffer = NULL;
- if (buffer_length <= 0
- #ifndef PHP_WIN32
- || ZEND_LONG_INT_OVFL(buffer_length)
- #endif
- ) {
- zend_argument_value_error(1, "must be greater than 0");
- return NULL;
- }
- buffer = zend_string_alloc(buffer_length, 0);
- #ifdef PHP_WIN32
-
- if (php_win32_get_random_bytes((unsigned char*)(buffer)->val, (size_t) buffer_length) == FAILURE){
- zend_string_release_ex(buffer, 0);
- zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
- return NULL;
- }
- #else
- PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(buffer_length, length);
- PHP_OPENSSL_RAND_ADD_TIME();
-
- if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), (int)buffer_length) <= 0) {
- zend_string_release_ex(buffer, 0);
- zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
- return NULL;
- } else {
- php_openssl_store_errors();
- }
- #endif
- return buffer;
- }
- PHP_FUNCTION(openssl_random_pseudo_bytes)
- {
- zend_string *buffer = NULL;
- zend_long buffer_length;
- zval *zstrong_result_returned = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) {
- RETURN_THROWS();
- }
- if (zstrong_result_returned) {
- ZEND_TRY_ASSIGN_REF_FALSE(zstrong_result_returned);
- }
- if ((buffer = php_openssl_random_pseudo_bytes(buffer_length))) {
- ZSTR_VAL(buffer)[buffer_length] = 0;
- RETVAL_NEW_STR(buffer);
- }
- if (zstrong_result_returned) {
- ZEND_TRY_ASSIGN_REF_TRUE(zstrong_result_returned);
- }
- }
|