123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526 |
- /* ssl.c
- *
- * Copyright (C) 2006-2022 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #if defined(OPENSSL_EXTRA) && !defined(_WIN32)
- /* turn on GNU extensions for XISASCII */
- #undef _GNU_SOURCE
- #define _GNU_SOURCE
- #endif
- #if !defined(WOLFCRYPT_ONLY) || defined(OPENSSL_EXTRA) || \
- defined(OPENSSL_EXTRA_X509_SMALL)
- #include <wolfssl/internal.h>
- #include <wolfssl/error-ssl.h>
- #include <wolfssl/wolfcrypt/coding.h>
- #include <wolfssl/wolfcrypt/kdf.h>
- #ifdef NO_INLINE
- #include <wolfssl/wolfcrypt/misc.h>
- #else
- #define WOLFSSL_MISC_INCLUDED
- #include <wolfcrypt/src/misc.c>
- #endif
- #ifdef HAVE_ERRNO_H
- #include <errno.h>
- #endif
- #if !defined(WOLFSSL_ALLOW_NO_SUITES) && !defined(WOLFCRYPT_ONLY)
- #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \
- && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \
- && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448)
- #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README"
- #endif
- #ifdef WOLFSSL_CERT_GEN
- /* need access to Cert struct for creating certificate */
- #include <wolfssl/wolfcrypt/asn_public.h>
- #endif
- #endif
- #if !defined(WOLFCRYPT_ONLY) && (defined(OPENSSL_EXTRA) \
- || defined(OPENSSL_EXTRA_X509_SMALL) \
- || defined(HAVE_WEBSERVER) || defined(WOLFSSL_KEY_GEN))
- #include <wolfssl/openssl/evp.h>
- /* openssl headers end, wolfssl internal headers next */
- #endif
- #include <wolfssl/wolfcrypt/wc_encrypt.h>
- #ifndef NO_RSA
- #include <wolfssl/wolfcrypt/rsa.h>
- #endif
- #ifdef OPENSSL_EXTRA
- /* openssl headers begin */
- #include <wolfssl/openssl/ssl.h>
- #include <wolfssl/openssl/aes.h>
- #ifndef WOLFCRYPT_ONLY
- #include <wolfssl/openssl/hmac.h>
- #include <wolfssl/openssl/cmac.h>
- #endif
- #include <wolfssl/openssl/crypto.h>
- #include <wolfssl/openssl/des.h>
- #include <wolfssl/openssl/bn.h>
- #include <wolfssl/openssl/buffer.h>
- #include <wolfssl/openssl/dh.h>
- #include <wolfssl/openssl/rsa.h>
- #include <wolfssl/openssl/fips_rand.h>
- #ifndef WOLFCRYPT_ONLY
- #include <wolfssl/openssl/pem.h>
- #endif
- #include <wolfssl/openssl/ec.h>
- #include <wolfssl/openssl/ec25519.h>
- #include <wolfssl/openssl/ed25519.h>
- #include <wolfssl/openssl/ec448.h>
- #include <wolfssl/openssl/ed448.h>
- #include <wolfssl/openssl/ecdsa.h>
- #include <wolfssl/openssl/ecdh.h>
- #include <wolfssl/openssl/err.h>
- #include <wolfssl/openssl/modes.h>
- #include <wolfssl/openssl/opensslv.h>
- #include <wolfssl/openssl/rc4.h>
- #include <wolfssl/openssl/stack.h>
- #include <wolfssl/openssl/x509_vfy.h>
- /* openssl headers end, wolfssl internal headers next */
- #include <wolfssl/wolfcrypt/hmac.h>
- #include <wolfssl/wolfcrypt/random.h>
- #include <wolfssl/wolfcrypt/des3.h>
- #include <wolfssl/wolfcrypt/ecc.h>
- #include <wolfssl/wolfcrypt/md4.h>
- #include <wolfssl/wolfcrypt/md5.h>
- #include <wolfssl/wolfcrypt/arc4.h>
- #include <wolfssl/wolfcrypt/curve25519.h>
- #include <wolfssl/wolfcrypt/ed25519.h>
- #include <wolfssl/wolfcrypt/curve448.h>
- #if defined(HAVE_PQC)
- #if defined(HAVE_FALCON)
- #include <wolfssl/wolfcrypt/falcon.h>
- #endif /* HAVE_FALCON */
- #if defined(HAVE_DILITHIUM)
- #include <wolfssl/wolfcrypt/dilithium.h>
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL)
- #ifdef HAVE_OCSP
- #include <wolfssl/openssl/ocsp.h>
- #endif
- #include <wolfssl/openssl/lhash.h>
- #include <wolfssl/openssl/txt_db.h>
- #endif /* WITH_STUNNEL */
- #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
- #include <wolfssl/wolfcrypt/sha512.h>
- #endif
- #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
- && !defined(WC_NO_RNG)
- #include <wolfssl/wolfcrypt/srp.h>
- #endif
- #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
- #include <wolfssl/wolfcrypt/pkcs7.h>
- #endif
- #if defined(OPENSSL_ALL) && defined(HAVE_PKCS7)
- #include <wolfssl/openssl/pkcs7.h>
- #endif /* OPENSSL_ALL && HAVE_PKCS7 */
- #endif
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- #include <wolfssl/openssl/x509v3.h>
- int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi);
- int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi);
- #endif
- #if defined(WOLFSSL_QT)
- #include <wolfssl/wolfcrypt/sha.h>
- #endif
- #ifdef NO_ASN
- #include <wolfssl/wolfcrypt/dh.h>
- #endif
- #endif /* !WOLFCRYPT_ONLY || OPENSSL_EXTRA */
- /*
- * OPENSSL_COMPATIBLE_DEFAULTS:
- * Enable default behaviour that is compatible with OpenSSL. For example
- * SSL_CTX by default doesn't verify the loaded certs. Enabling this
- * should make porting to new projects easier.
- * WOLFSSL_CHECK_ALERT_ON_ERR:
- * Check for alerts during the handshake in the event of an error.
- * NO_SESSION_CACHE_REF:
- * wolfSSL_get_session on a client will return a reference to the internal
- * ClientCache by default for backwards compatibility. This define will
- * make wolfSSL_get_session return a reference to ssl->session. The returned
- * pointer will be freed with the related WOLFSSL object.
- */
- #define WOLFSSL_EVP_INCLUDED
- #include "wolfcrypt/src/evp.c"
- #ifndef WOLFCRYPT_ONLY
- #define WOLFSSL_PK_INCLUDED
- #include "src/pk.c"
- #ifdef OPENSSL_EXTRA
- /* Global pointer to constant BN on */
- static WOLFSSL_BIGNUM* bn_one = NULL;
- /* WOLFSSL_NO_OPENSSL_RAND_CB: Allows way to reduce code size for
- * OPENSSL_EXTRA where RAND callbacks are not used */
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- static const WOLFSSL_RAND_METHOD* gRandMethods = NULL;
- static int gRandMethodsInit = 0;
- static wolfSSL_Mutex gRandMethodMutex;
- #endif /* !WOLFSSL_NO_OPENSSL_RAND_CB */
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
- const WOLF_EC_NIST_NAME kNistCurves[] = {
- {XSTR_SIZEOF("P-192"), "P-192", NID_X9_62_prime192v1},
- {XSTR_SIZEOF("P-256"), "P-256", NID_X9_62_prime256v1},
- {XSTR_SIZEOF("P-112"), "P-112", NID_secp112r1},
- {XSTR_SIZEOF("P-112-2"), "P-112-2", NID_secp112r2},
- {XSTR_SIZEOF("P-128"), "P-128", NID_secp128r1},
- {XSTR_SIZEOF("P-128-2"), "P-128-2", NID_secp128r2},
- {XSTR_SIZEOF("P-160"), "P-160", NID_secp160r1},
- {XSTR_SIZEOF("P-160-2"), "P-160-2", NID_secp160r2},
- {XSTR_SIZEOF("P-224"), "P-224", NID_secp224r1},
- {XSTR_SIZEOF("P-384"), "P-384", NID_secp384r1},
- {XSTR_SIZEOF("P-521"), "P-521", NID_secp521r1},
- {XSTR_SIZEOF("K-160"), "K-160", NID_secp160k1},
- {XSTR_SIZEOF("K-192"), "K-192", NID_secp192k1},
- {XSTR_SIZEOF("K-224"), "K-224", NID_secp224k1},
- {XSTR_SIZEOF("K-256"), "K-256", NID_secp256k1},
- {XSTR_SIZEOF("B-160"), "B-160", NID_brainpoolP160r1},
- {XSTR_SIZEOF("B-192"), "B-192", NID_brainpoolP192r1},
- {XSTR_SIZEOF("B-224"), "B-224", NID_brainpoolP224r1},
- {XSTR_SIZEOF("B-256"), "B-256", NID_brainpoolP256r1},
- {XSTR_SIZEOF("B-320"), "B-320", NID_brainpoolP320r1},
- {XSTR_SIZEOF("B-384"), "B-384", NID_brainpoolP384r1},
- {XSTR_SIZEOF("B-512"), "B-512", NID_brainpoolP512r1},
- #ifdef HAVE_PQC
- {XSTR_SIZEOF("KYBER_LEVEL1"), "KYBER_LEVEL1", WOLFSSL_KYBER_LEVEL1},
- {XSTR_SIZEOF("KYBER_LEVEL3"), "KYBER_LEVEL3", WOLFSSL_KYBER_LEVEL3},
- {XSTR_SIZEOF("KYBER_LEVEL5"), "KYBER_LEVEL5", WOLFSSL_KYBER_LEVEL5},
- {XSTR_SIZEOF("NTRU_HPS_LEVEL1"), "NTRU_HPS_LEVEL1", WOLFSSL_NTRU_HPS_LEVEL1},
- {XSTR_SIZEOF("NTRU_HPS_LEVEL3"), "NTRU_HPS_LEVEL3", WOLFSSL_NTRU_HPS_LEVEL3},
- {XSTR_SIZEOF("NTRU_HPS_LEVEL5"), "NTRU_HPS_LEVEL5", WOLFSSL_NTRU_HPS_LEVEL5},
- {XSTR_SIZEOF("NTRU_HRSS_LEVEL3"), "NTRU_HRSS_LEVEL3", WOLFSSL_NTRU_HRSS_LEVEL3},
- {XSTR_SIZEOF("SABER_LEVEL1"), "SABER_LEVEL1", WOLFSSL_SABER_LEVEL1},
- {XSTR_SIZEOF("SABER_LEVEL3"), "SABER_LEVEL3", WOLFSSL_SABER_LEVEL3},
- {XSTR_SIZEOF("SABER_LEVEL5"), "SABER_LEVEL5", WOLFSSL_SABER_LEVEL5},
- {XSTR_SIZEOF("KYBER_90S_LEVEL1"), "KYBER_90S_LEVEL1", WOLFSSL_KYBER_90S_LEVEL1},
- {XSTR_SIZEOF("KYBER_90S_LEVEL3"), "KYBER_90S_LEVEL3", WOLFSSL_KYBER_90S_LEVEL3},
- {XSTR_SIZEOF("KYBER_90S_LEVEL5"), "KYBER_90S_LEVEL5", WOLFSSL_KYBER_90S_LEVEL5},
- {XSTR_SIZEOF("P256_NTRU_HPS_LEVEL1"), "P256_NTRU_HPS_LEVEL1", WOLFSSL_P256_NTRU_HPS_LEVEL1},
- {XSTR_SIZEOF("P384_NTRU_HPS_LEVEL3"), "P384_NTRU_HPS_LEVEL3", WOLFSSL_P384_NTRU_HPS_LEVEL3},
- {XSTR_SIZEOF("P521_NTRU_HPS_LEVEL5"), "P521_NTRU_HPS_LEVEL5", WOLFSSL_P521_NTRU_HPS_LEVEL5},
- {XSTR_SIZEOF("P384_NTRU_HRSS_LEVEL3"), "P384_NTRU_HRSS_LEVEL3", WOLFSSL_P384_NTRU_HRSS_LEVEL3},
- {XSTR_SIZEOF("P256_SABER_LEVEL1"), "P256_SABER_LEVEL1", WOLFSSL_P256_SABER_LEVEL1},
- {XSTR_SIZEOF("P384_SABER_LEVEL3"), "P384_SABER_LEVEL3", WOLFSSL_P384_SABER_LEVEL3},
- {XSTR_SIZEOF("P521_SABER_LEVEL5"), "P521_SABER_LEVEL5", WOLFSSL_P521_SABER_LEVEL5},
- {XSTR_SIZEOF("P256_KYBER_LEVEL1"), "P256_KYBER_LEVEL1", WOLFSSL_P256_KYBER_LEVEL1},
- {XSTR_SIZEOF("P384_KYBER_LEVEL3"), "P384_KYBER_LEVEL3", WOLFSSL_P384_KYBER_LEVEL3},
- {XSTR_SIZEOF("P521_KYBER_LEVEL5"), "P521_KYBER_LEVEL5", WOLFSSL_P521_KYBER_LEVEL5},
- {XSTR_SIZEOF("P256_KYBER_90S_LEVEL1"), "P256_KYBER_90S_LEVEL1", WOLFSSL_P256_KYBER_90S_LEVEL1},
- {XSTR_SIZEOF("P384_KYBER_90S_LEVEL3"), "P384_KYBER_90S_LEVEL3", WOLFSSL_P384_KYBER_90S_LEVEL3},
- {XSTR_SIZEOF("P521_KYBER_90S_LEVEL5"), "P521_KYBER_90S_LEVEL5", WOLFSSL_P521_KYBER_90S_LEVEL5},
- #endif
- {0, NULL, 0},
- };
- #endif
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_SCEPROTECT)
- #include <wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h>
- #endif
- #ifdef WOLFSSL_SESSION_EXPORT
- /* Used to import a serialized TLS session.
- * WARNING: buf contains sensitive information about the state and is best to be
- * encrypted before storing if stored.
- *
- * @param ssl WOLFSSL structure to import the session into
- * @param buf serialized session
- * @param sz size of buffer 'buf'
- * @return the number of bytes read from buffer 'buf'
- */
- int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz)
- {
- if (ssl == NULL || buf == NULL) {
- return BAD_FUNC_ARG;
- }
- return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS);
- }
- /* Used to export a serialized TLS session.
- * WARNING: buf contains sensitive information about the state and is best to be
- * encrypted before storing if stored.
- *
- * @param ssl WOLFSSL structure to export the session from
- * @param buf output of serialized session
- * @param sz size in bytes set in 'buf'
- * @return the number of bytes written into buffer 'buf'
- */
- int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
- {
- if (ssl == NULL || sz == NULL) {
- return BAD_FUNC_ARG;
- }
- return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS);
- }
- #ifdef WOLFSSL_DTLS
- int wolfSSL_dtls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz)
- {
- WOLFSSL_ENTER("wolfSSL_session_import");
- if (ssl == NULL || buf == NULL) {
- return BAD_FUNC_ARG;
- }
- /* sanity checks on buffer and protocol are done in internal function */
- return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS);
- }
- /* Sets the function to call for serializing the session. This function is
- * called right after the handshake is completed. */
- int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export");
- /* purposefully allow func to be NULL */
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- ctx->dtls_export = func;
- return WOLFSSL_SUCCESS;
- }
- /* Sets the function in WOLFSSL struct to call for serializing the session. This
- * function is called right after the handshake is completed. */
- int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
- {
- WOLFSSL_ENTER("wolfSSL_dtls_set_export");
- /* purposefully allow func to be NULL */
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- ssl->dtls_export = func;
- return WOLFSSL_SUCCESS;
- }
- /* This function allows for directly serializing a session rather than using
- * callbacks. It has less overhead by removing a temporary buffer and gives
- * control over when the session gets serialized. When using callbacks the
- * session is always serialized immediately after the handshake is finished.
- *
- * buf is the argument to contain the serialized session
- * sz is the size of the buffer passed in
- * ssl is the WOLFSSL struct to serialize
- * returns the size of serialized session on success, 0 on no action, and
- * negative value on error */
- int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
- {
- WOLFSSL_ENTER("wolfSSL_dtls_export");
- if (ssl == NULL || sz == NULL) {
- return BAD_FUNC_ARG;
- }
- if (buf == NULL) {
- *sz = MAX_EXPORT_BUFFER;
- return 0;
- }
- /* if not DTLS do nothing */
- if (!ssl->options.dtls) {
- WOLFSSL_MSG("Currently only DTLS export is supported");
- return 0;
- }
- /* copy over keys, options, and dtls state struct */
- return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS);
- }
- /* This function is similar to wolfSSL_dtls_export but only exports the portion
- * of the WOLFSSL structure related to the state of the connection, i.e. peer
- * sequence number, epoch, AEAD state etc.
- *
- * buf is the argument to contain the serialized state, if null then set "sz" to
- * buffer size required
- * sz is the size of the buffer passed in
- * ssl is the WOLFSSL struct to serialize
- * returns the size of serialized session on success, 0 on no action, and
- * negative value on error */
- int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf,
- unsigned int* sz)
- {
- WOLFSSL_ENTER("wolfSSL_dtls_export_state_only");
- if (ssl == NULL || sz == NULL) {
- return BAD_FUNC_ARG;
- }
- if (buf == NULL) {
- *sz = MAX_EXPORT_STATE_BUFFER;
- return 0;
- }
- /* if not DTLS do nothing */
- if (!ssl->options.dtls) {
- WOLFSSL_MSG("Currently only DTLS export state is supported");
- return 0;
- }
- /* copy over keys, options, and dtls state struct */
- return wolfSSL_dtls_export_state_internal(ssl, buf, *sz);
- }
- /* returns 0 on success */
- int wolfSSL_send_session(WOLFSSL* ssl)
- {
- int ret;
- byte* buf;
- word32 bufSz = MAX_EXPORT_BUFFER;
- WOLFSSL_ENTER("wolfSSL_send_session");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf == NULL) {
- return MEMORY_E;
- }
- /* if not DTLS do nothing */
- if (!ssl->options.dtls) {
- XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- WOLFSSL_MSG("Currently only DTLS export is supported");
- return 0;
- }
- /* copy over keys, options, and dtls state struct */
- ret = wolfSSL_session_export_internal(ssl, buf, &bufSz, WOLFSSL_EXPORT_DTLS);
- if (ret < 0) {
- XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- /* if no error ret has size of buffer */
- ret = ssl->dtls_export(ssl, buf, ret, NULL);
- if (ret != WOLFSSL_SUCCESS) {
- XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return 0;
- }
- #endif /* WOLFSSL_DTLS */
- #endif /* WOLFSSL_SESSION_EXPORT */
- /* prevent multiple mutex initializations */
- static volatile WOLFSSL_GLOBAL int initRefCount = 0;
- static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex; /* init ref count mutex */
- static WOLFSSL_GLOBAL int count_mutex_valid = 0;
- /* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
- WOLFSSL_METHOD pointer passed in is given to ctx to manage.
- This function frees the passed in WOLFSSL_METHOD struct on failure and on
- success is freed when ctx is freed.
- */
- WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
- {
- WOLFSSL_CTX* ctx = NULL;
- WOLFSSL_ENTER("wolfSSL_CTX_new_ex");
- if (initRefCount == 0) {
- /* user no longer forced to call Init themselves */
- int ret = wolfSSL_Init();
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_Init failed");
- WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
- if (method != NULL) {
- XFREE(method, heap, DYNAMIC_TYPE_METHOD);
- }
- return NULL;
- }
- }
- if (method == NULL)
- return ctx;
- ctx = (WOLFSSL_CTX*)XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX);
- if (ctx) {
- int ret;
- ret = InitSSL_Ctx(ctx, method, heap);
- #ifdef WOLFSSL_STATIC_MEMORY
- if (heap != NULL) {
- ctx->onHeapHint = 1; /* free the memory back to heap when done */
- }
- #endif
- if (ret < 0) {
- WOLFSSL_MSG("Init CTX failed");
- wolfSSL_CTX_free(ctx);
- ctx = NULL;
- }
- #if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
- && !defined(NO_SHA256) && !defined(WC_NO_RNG)
- else {
- ctx->srp = (Srp*)XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP);
- if (ctx->srp == NULL){
- WOLFSSL_MSG("Init CTX failed");
- wolfSSL_CTX_free(ctx);
- return NULL;
- }
- XMEMSET(ctx->srp, 0, sizeof(Srp));
- }
- #endif
- }
- else {
- WOLFSSL_MSG("Alloc CTX failed, method freed");
- XFREE(method, heap, DYNAMIC_TYPE_METHOD);
- }
- #ifdef OPENSSL_COMPATIBLE_DEFAULTS
- if (ctx) {
- wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
- wolfSSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
- if (wolfSSL_CTX_set_min_proto_version(ctx,
- (method->version.major == DTLS_MAJOR) ?
- DTLS1_VERSION : SSL3_VERSION) != WOLFSSL_SUCCESS ||
- #ifdef HAVE_ANON
- wolfSSL_CTX_allow_anon_cipher(ctx) != WOLFSSL_SUCCESS ||
- #endif
- wolfSSL_CTX_set_group_messages(ctx) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Setting OpenSSL CTX defaults failed");
- wolfSSL_CTX_free(ctx);
- ctx = NULL;
- }
- }
- #endif
- WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
- return ctx;
- }
- WOLFSSL_ABI
- WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
- {
- #ifdef WOLFSSL_HEAP_TEST
- /* if testing the heap hint then set top level CTX to have test value */
- return wolfSSL_CTX_new_ex(method, (void*)WOLFSSL_HEAP_TEST);
- #else
- return wolfSSL_CTX_new_ex(method, NULL);
- #endif
- }
- /* increases CTX reference count to track proper time to "free" */
- int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx)
- {
- int refCount = SSL_CTX_RefCount(ctx, 1);
- return ((refCount > 1) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE);
- }
- WOLFSSL_ABI
- void wolfSSL_CTX_free(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("SSL_CTX_free");
- if (ctx) {
- #if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
- && !defined(NO_SHA256) && !defined(WC_NO_RNG)
- if (ctx->srp != NULL) {
- if (ctx->srp_password != NULL){
- XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp_password = NULL;
- }
- wc_SrpTerm(ctx->srp);
- XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp = NULL;
- }
- #endif
- FreeSSL_Ctx(ctx);
- }
- WOLFSSL_LEAVE("SSL_CTX_free", 0);
- }
- #ifdef HAVE_ENCRYPT_THEN_MAC
- /**
- * Sets whether Encrypt-Then-MAC extension can be negotiated against context.
- * The default value: enabled.
- *
- * ctx SSL/TLS context.
- * set Whether to allow or not: 1 is allow and 0 is disallow.
- * returns WOLFSSL_SUCCESS
- */
- int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *ctx, int set)
- {
- ctx->disallowEncThenMac = !set;
- return WOLFSSL_SUCCESS;
- }
- /**
- * Sets whether Encrypt-Then-MAC extension can be negotiated against context.
- * The default value comes from context.
- *
- * ctx SSL/TLS context.
- * set Whether to allow or not: 1 is allow and 0 is disallow.
- * returns WOLFSSL_SUCCESS
- */
- int wolfSSL_AllowEncryptThenMac(WOLFSSL *ssl, int set)
- {
- ssl->options.disallowEncThenMac = !set;
- return WOLFSSL_SUCCESS;
- }
- #endif
- #ifdef SINGLE_THREADED
- /* no locking in single threaded mode, allow a CTX level rng to be shared with
- * WOLFSSL objects, WOLFSSL_SUCCESS on ok */
- int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx)
- {
- WC_RNG* rng;
- int ret;
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG);
- if (rng == NULL) {
- return MEMORY_E;
- }
- #ifndef HAVE_FIPS
- ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId);
- #else
- ret = wc_InitRng(rng);
- #endif
- if (ret != 0) {
- XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
- return ret;
- }
- ctx->rng = rng;
- return WOLFSSL_SUCCESS;
- }
- #endif
- WOLFSSL_ABI
- WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
- {
- WOLFSSL* ssl = NULL;
- int ret = 0;
- WOLFSSL_ENTER("SSL_new");
- if (ctx == NULL)
- return ssl;
- ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL);
- if (ssl)
- if ( (ret = InitSSL(ssl, ctx, 0)) < 0) {
- FreeSSL(ssl, ctx->heap);
- ssl = 0;
- }
- WOLFSSL_LEAVE("SSL_new", ret);
- (void)ret;
- return ssl;
- }
- WOLFSSL_ABI
- void wolfSSL_free(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_free");
- if (ssl)
- FreeSSL(ssl, ssl->ctx->heap);
- WOLFSSL_LEAVE("SSL_free", 0);
- }
- int wolfSSL_is_server(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return ssl->options.side == WOLFSSL_SERVER_END;
- }
- #ifdef HAVE_WRITE_DUP
- /*
- * Release resources around WriteDup object
- *
- * ssl WOLFSSL object
- *
- * no return, destruction so make best attempt
- */
- void FreeWriteDup(WOLFSSL* ssl)
- {
- int doFree = 0;
- WOLFSSL_ENTER("FreeWriteDup");
- if (ssl->dupWrite) {
- if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
- ssl->dupWrite->dupCount--;
- if (ssl->dupWrite->dupCount == 0) {
- doFree = 1;
- } else {
- WOLFSSL_MSG("WriteDup count not zero, no full free");
- }
- wc_UnLockMutex(&ssl->dupWrite->dupMutex);
- }
- }
- if (doFree) {
- WOLFSSL_MSG("Doing WriteDup full free, count to zero");
- wc_FreeMutex(&ssl->dupWrite->dupMutex);
- XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
- }
- }
- /*
- * duplicate existing ssl members into dup needed for writing
- *
- * dup write only WOLFSSL
- * ssl existing WOLFSSL
- *
- * 0 on success
- */
- static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
- {
- /* shared dupWrite setup */
- ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap,
- DYNAMIC_TYPE_WRITEDUP);
- if (ssl->dupWrite == NULL) {
- return MEMORY_E;
- }
- XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup));
- if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) {
- XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
- ssl->dupWrite = NULL;
- return BAD_MUTEX_E;
- }
- ssl->dupWrite->dupCount = 2; /* both sides have a count to start */
- dup->dupWrite = ssl->dupWrite; /* each side uses */
- /* copy write parts over to dup writer */
- XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs));
- XMEMCPY(&dup->options, &ssl->options, sizeof(Options));
- XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys));
- XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers));
- XMEMCPY(&dup->version, &ssl->version, sizeof(ProtocolVersion));
- XMEMCPY(&dup->chVersion, &ssl->chVersion, sizeof(ProtocolVersion));
- /* dup side now owns encrypt/write ciphers */
- XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
- dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
- dup->CBIOSend = ssl->CBIOSend;
- #ifdef OPENSSL_EXTRA
- dup->cbioFlag = ssl->cbioFlag;
- #endif
- dup->wfd = ssl->wfd;
- dup->wflags = ssl->wflags;
- #ifndef WOLFSSL_AEAD_ONLY
- dup->hmac = ssl->hmac;
- #endif
- #ifdef HAVE_TRUNCATED_HMAC
- dup->truncated_hmac = ssl->truncated_hmac;
- #endif
- /* unique side dup setup */
- dup->dupSide = WRITE_DUP_SIDE;
- ssl->dupSide = READ_DUP_SIDE;
- return 0;
- }
- /*
- * duplicate a WOLFSSL object post handshake for writing only
- * turn existing object into read only. Allows concurrent access from two
- * different threads.
- *
- * ssl existing WOLFSSL object
- *
- * return dup'd WOLFSSL object on success
- */
- WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl)
- {
- WOLFSSL* dup = NULL;
- int ret = 0;
- (void)ret;
- WOLFSSL_ENTER("wolfSSL_write_dup");
- if (ssl == NULL) {
- return ssl;
- }
- if (ssl->options.handShakeDone == 0) {
- WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete");
- return NULL;
- }
- if (ssl->dupWrite) {
- WOLFSSL_MSG("wolfSSL_write_dup already called once");
- return NULL;
- }
- dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL);
- if (dup) {
- if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) {
- FreeSSL(dup, ssl->ctx->heap);
- dup = NULL;
- } else if ( (ret = DupSSL(dup, ssl)) < 0) {
- FreeSSL(dup, ssl->ctx->heap);
- dup = NULL;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_write_dup", ret);
- return dup;
- }
- /*
- * Notify write dup side of fatal error or close notify
- *
- * ssl WOLFSSL object
- * err Notify err
- *
- * 0 on success
- */
- int NotifyWriteSide(WOLFSSL* ssl, int err)
- {
- int ret;
- WOLFSSL_ENTER("NotifyWriteSide");
- ret = wc_LockMutex(&ssl->dupWrite->dupMutex);
- if (ret == 0) {
- ssl->dupWrite->dupErr = err;
- ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
- }
- return ret;
- }
- #endif /* HAVE_WRITE_DUP */
- #ifdef HAVE_POLY1305
- /* set if to use old poly 1 for yes 0 to use new poly */
- int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
- {
- (void)ssl;
- (void)value;
- #ifndef WOLFSSL_NO_TLS12
- WOLFSSL_ENTER("SSL_use_old_poly");
- WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function"
- "is depreciated");
- ssl->options.oldPoly = (word16)value;
- WOLFSSL_LEAVE("SSL_use_old_poly", 0);
- #endif
- return 0;
- }
- #endif
- WOLFSSL_ABI
- int wolfSSL_set_fd(WOLFSSL* ssl, int fd)
- {
- int ret;
- WOLFSSL_ENTER("SSL_set_fd");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- ret = wolfSSL_set_read_fd(ssl, fd);
- if (ret == WOLFSSL_SUCCESS) {
- ret = wolfSSL_set_write_fd(ssl, fd);
- }
- return ret;
- }
- #ifdef WOLFSSL_DTLS
- int wolfSSL_set_dtls_fd_connected(WOLFSSL* ssl, int fd)
- {
- int ret;
- WOLFSSL_ENTER("SSL_set_dtls_fd_connected");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- ret = wolfSSL_set_fd(ssl, fd);
- if (ret == WOLFSSL_SUCCESS)
- ssl->buffers.dtlsCtx.connected = 1;
- return ret;
- }
- #endif
- int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
- {
- WOLFSSL_ENTER("SSL_set_read_fd");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- ssl->rfd = fd; /* not used directly to allow IO callbacks */
- ssl->IOCB_ReadCtx = &ssl->rfd;
- #ifdef WOLFSSL_DTLS
- ssl->buffers.dtlsCtx.connected = 0;
- if (ssl->options.dtls) {
- ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
- ssl->buffers.dtlsCtx.rfd = fd;
- }
- #endif
- WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd)
- {
- WOLFSSL_ENTER("SSL_set_write_fd");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- ssl->wfd = fd; /* not used directly to allow IO callbacks */
- ssl->IOCB_WriteCtx = &ssl->wfd;
- #ifdef WOLFSSL_DTLS
- ssl->buffers.dtlsCtx.connected = 0;
- if (ssl->options.dtls) {
- ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
- ssl->buffers.dtlsCtx.wfd = fd;
- }
- #endif
- WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- /**
- * Get the name of cipher at priority level passed in.
- */
- char* wolfSSL_get_cipher_list(int priority)
- {
- const CipherSuiteInfo* ciphers = GetCipherNames();
- if (priority >= GetCipherNamesSize() || priority < 0) {
- return 0;
- }
- return (char*)ciphers[priority].name;
- }
- /**
- * Get the name of cipher at priority level passed in.
- */
- char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority)
- {
- if (ssl == NULL) {
- return NULL;
- }
- else {
- const char* cipher;
- if ((cipher = wolfSSL_get_cipher_name_internal(ssl)) != NULL) {
- if (priority == 0) {
- return (char*)cipher;
- }
- else {
- return NULL;
- }
- }
- else {
- return wolfSSL_get_cipher_list(priority);
- }
- }
- }
- int wolfSSL_get_ciphers(char* buf, int len)
- {
- const CipherSuiteInfo* ciphers = GetCipherNames();
- int ciphersSz = GetCipherNamesSize();
- int i;
- int cipherNameSz;
- if (buf == NULL || len <= 0)
- return BAD_FUNC_ARG;
- /* Add each member to the buffer delimited by a : */
- for (i = 0; i < ciphersSz; i++) {
- cipherNameSz = (int)XSTRLEN(ciphers[i].name);
- if (cipherNameSz + 1 < len) {
- XSTRNCPY(buf, ciphers[i].name, len);
- buf += cipherNameSz;
- if (i < ciphersSz - 1)
- *buf++ = ':';
- *buf = 0;
- len -= cipherNameSz + 1;
- }
- else
- return BUFFER_E;
- }
- return WOLFSSL_SUCCESS;
- }
- #ifndef NO_ERROR_STRINGS
- /* places a list of all supported cipher suites in TLS_* format into "buf"
- * return WOLFSSL_SUCCESS on success */
- int wolfSSL_get_ciphers_iana(char* buf, int len)
- {
- const CipherSuiteInfo* ciphers = GetCipherNames();
- int ciphersSz = GetCipherNamesSize();
- int i;
- int cipherNameSz;
- if (buf == NULL || len <= 0)
- return BAD_FUNC_ARG;
- /* Add each member to the buffer delimited by a : */
- for (i = 0; i < ciphersSz; i++) {
- #ifndef NO_CIPHER_SUITE_ALIASES
- if (ciphers[i].flags & WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS)
- continue;
- #endif
- cipherNameSz = (int)XSTRLEN(ciphers[i].name_iana);
- if (cipherNameSz + 1 < len) {
- XSTRNCPY(buf, ciphers[i].name_iana, len);
- buf += cipherNameSz;
- if (i < ciphersSz - 1)
- *buf++ = ':';
- *buf = 0;
- len -= cipherNameSz + 1;
- }
- else
- return BUFFER_E;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* NO_ERROR_STRINGS */
- const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len)
- {
- const char* cipher;
- if (ssl == NULL)
- return NULL;
- cipher = wolfSSL_get_cipher_name_iana(ssl);
- len = min(len, (int)(XSTRLEN(cipher) + 1));
- XMEMCPY(buf, cipher, len);
- return buf;
- }
- int wolfSSL_get_fd(const WOLFSSL* ssl)
- {
- int fd = -1;
- WOLFSSL_ENTER("SSL_get_fd");
- if (ssl) {
- fd = ssl->rfd;
- }
- WOLFSSL_LEAVE("SSL_get_fd", fd);
- return fd;
- }
- int wolfSSL_dtls(WOLFSSL* ssl)
- {
- int dtlsOpt = 0;
- if (ssl)
- dtlsOpt = ssl->options.dtls;
- return dtlsOpt;
- }
- #if !defined(NO_CERTS)
- /* Set whether mutual authentication is required for connections.
- * Server side only.
- *
- * ctx The SSL/TLS CTX object.
- * req 1 to indicate required and 0 when not.
- * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
- * 0 on success.
- */
- int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- if (ctx->method->side == WOLFSSL_CLIENT_END)
- return SIDE_ERROR;
- ctx->mutualAuth = (byte)req;
- return 0;
- }
- /* Set whether mutual authentication is required for the connection.
- * Server side only.
- *
- * ssl The SSL/TLS object.
- * req 1 to indicate required and 0 when not.
- * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
- * SIDE_ERROR when not a client and 0 on success.
- */
- int wolfSSL_mutual_auth(WOLFSSL* ssl, int req)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (ssl->options.side == WOLFSSL_SERVER_END)
- return SIDE_ERROR;
- ssl->options.mutualAuth = (word16)req;
- return 0;
- }
- #endif /* NO_CERTS */
- #ifdef WOLFSSL_WOLFSENTRY_HOOKS
- int wolfSSL_CTX_set_AcceptFilter(
- WOLFSSL_CTX *ctx,
- NetworkFilterCallback_t AcceptFilter,
- void *AcceptFilter_arg)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->AcceptFilter = AcceptFilter;
- ctx->AcceptFilter_arg = AcceptFilter_arg;
- return 0;
- }
- int wolfSSL_set_AcceptFilter(
- WOLFSSL *ssl,
- NetworkFilterCallback_t AcceptFilter,
- void *AcceptFilter_arg)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->AcceptFilter = AcceptFilter;
- ssl->AcceptFilter_arg = AcceptFilter_arg;
- return 0;
- }
- int wolfSSL_CTX_set_ConnectFilter(
- WOLFSSL_CTX *ctx,
- NetworkFilterCallback_t ConnectFilter,
- void *ConnectFilter_arg)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->ConnectFilter = ConnectFilter;
- ctx->ConnectFilter_arg = ConnectFilter_arg;
- return 0;
- }
- int wolfSSL_set_ConnectFilter(
- WOLFSSL *ssl,
- NetworkFilterCallback_t ConnectFilter,
- void *ConnectFilter_arg)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->ConnectFilter = ConnectFilter;
- ssl->ConnectFilter_arg = ConnectFilter_arg;
- return 0;
- }
- #endif /* WOLFSSL_WOLFSENTRY_HOOKS */
- #ifndef WOLFSSL_LEANPSK
- #if defined(WOLFSSL_DTLS) && defined(XINET_PTON) && \
- !defined(WOLFSSL_NO_SOCK) && defined(HAVE_SOCKADDR)
- void* wolfSSL_dtls_create_peer(int port, char* ip)
- {
- SOCKADDR_IN *addr;
- addr = (SOCKADDR_IN*)XMALLOC(sizeof(*addr), NULL,
- DYNAMIC_TYPE_SOCKADDR);
- if (addr == NULL) {
- return NULL;
- }
- addr->sin_family = AF_INET;
- addr->sin_port = htons(port);
- if (XINET_PTON(AF_INET, ip, &addr->sin_addr) < 1) {
- XFREE(addr, NULL, DYNAMIC_TYPE_SOCKADDR);
- return NULL;
- }
- return addr;
- }
- int wolfSSL_dtls_free_peer(void* addr)
- {
- XFREE(addr, NULL, DYNAMIC_TYPE_SOCKADDR);
- return WOLFSSL_SUCCESS;
- }
- #endif
- int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
- {
- #ifdef WOLFSSL_DTLS
- void* sa;
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- if (peer == NULL || peerSz == 0) {
- if (ssl->buffers.dtlsCtx.peer.sa != NULL)
- XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
- ssl->buffers.dtlsCtx.peer.sa = NULL;
- ssl->buffers.dtlsCtx.peer.sz = 0;
- ssl->buffers.dtlsCtx.peer.bufSz = 0;
- ssl->buffers.dtlsCtx.userSet = 0;
- return WOLFSSL_SUCCESS;
- }
- sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
- if (sa != NULL) {
- if (ssl->buffers.dtlsCtx.peer.sa != NULL) {
- XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
- ssl->buffers.dtlsCtx.peer.sa = NULL;
- }
- XMEMCPY(sa, peer, peerSz);
- ssl->buffers.dtlsCtx.peer.sa = sa;
- ssl->buffers.dtlsCtx.peer.sz = peerSz;
- ssl->buffers.dtlsCtx.peer.bufSz = peerSz;
- ssl->buffers.dtlsCtx.userSet = 1;
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- #else
- (void)ssl;
- (void)peer;
- (void)peerSz;
- return WOLFSSL_NOT_IMPLEMENTED;
- #endif
- }
- int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
- {
- #ifdef WOLFSSL_DTLS
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (peer != NULL && peerSz != NULL
- && *peerSz >= ssl->buffers.dtlsCtx.peer.sz
- && ssl->buffers.dtlsCtx.peer.sa != NULL) {
- *peerSz = ssl->buffers.dtlsCtx.peer.sz;
- XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- #else
- (void)ssl;
- (void)peer;
- (void)peerSz;
- return WOLFSSL_NOT_IMPLEMENTED;
- #endif
- }
- #if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
- int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->dtlsSctp = 1;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_dtls_set_sctp(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->options.dtlsSctp = 1;
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */
- #if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
- defined(WOLFSSL_DTLS)
- int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu)
- {
- if (ctx == NULL || newMtu > MAX_RECORD_SIZE)
- return BAD_FUNC_ARG;
- ctx->dtlsMtuSz = newMtu;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (newMtu > MAX_RECORD_SIZE) {
- ssl->error = BAD_FUNC_ARG;
- return WOLFSSL_FAILURE;
- }
- ssl->dtlsMtuSz = newMtu;
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */
- #ifdef WOLFSSL_SRTP
- static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = {
- /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 80-bits
- * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */
- {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80, (((128 + 112) * 2) / 8) },
- /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 32-bits
- * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */
- {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32, (((128 + 112) * 2) / 8) },
- /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 80-bits */
- {"SRTP_NULL_SHA1_80", SRTP_NULL_SHA1_80, ((112 * 2) / 8)},
- /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 32-bits */
- {"SRTP_NULL_SHA1_32", SRTP_NULL_SHA1_32, ((112 * 2) / 8)},
- /* AES GCM 128, Salt: 96-bits, Auth GCM Tag 128-bits
- * (master_key:128bits + master_salt:96bits) * 2 = 448 bits (56) */
- {"SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM, (((128 + 96) * 2) / 8) },
- /* AES GCM 256, Salt: 96-bits, Auth GCM Tag 128-bits
- * (master_key:256bits + master_salt:96bits) * 2 = 704 bits (88) */
- {"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM, (((256 + 96) * 2) / 8) },
- };
- static const WOLFSSL_SRTP_PROTECTION_PROFILE* DtlsSrtpFindProfile(
- const char* profile_str, word32 profile_str_len, unsigned long id)
- {
- int i;
- const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL;
- for (i=0;
- i<(int)(sizeof(gSrtpProfiles)/sizeof(WOLFSSL_SRTP_PROTECTION_PROFILE));
- i++) {
- if (profile_str != NULL) {
- word32 srtp_profile_len = (word32)XSTRLEN(gSrtpProfiles[i].name);
- if (srtp_profile_len == profile_str_len &&
- XMEMCMP(gSrtpProfiles[i].name, profile_str, profile_str_len)
- == 0) {
- profile = &gSrtpProfiles[i];
- break;
- }
- }
- else if (id != 0 && gSrtpProfiles[i].id == id) {
- profile = &gSrtpProfiles[i];
- break;
- }
- }
- return profile;
- }
- /* profile_str: accepts ":" colon separated list of SRTP profiles */
- static int DtlsSrtpSelProfiles(word16* id, const char* profile_str)
- {
- const WOLFSSL_SRTP_PROTECTION_PROFILE* profile;
- const char *current, *next = NULL;
- word32 length = 0, current_length;
- *id = 0; /* reset destination ID's */
- if (profile_str == NULL) {
- return WOLFSSL_FAILURE;
- }
- /* loop on end of line or colon ":" */
- next = profile_str;
- length = (word32)XSTRLEN(profile_str);
- do {
- current = next;
- next = XSTRSTR(current, ":");
- current_length = (!next) ? (word32)XSTRLEN(current)
- : (word32)(next - current);
- if (current_length < length)
- length = current_length;
- profile = DtlsSrtpFindProfile(current, current_length, 0);
- if (profile != NULL) {
- *id |= (1 << profile->id); /* selected bit based on ID */
- }
- } while (next != NULL && next++); /* ++ needed to skip ':' */
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_set_tlsext_use_srtp(WOLFSSL_CTX* ctx, const char* profile_str)
- {
- int ret = WOLFSSL_FAILURE;
- if (ctx != NULL) {
- ret = DtlsSrtpSelProfiles(&ctx->dtlsSrtpProfiles, profile_str);
- }
- return ret;
- }
- int wolfSSL_set_tlsext_use_srtp(WOLFSSL* ssl, const char* profile_str)
- {
- int ret = WOLFSSL_FAILURE;
- if (ssl != NULL) {
- ret = DtlsSrtpSelProfiles(&ssl->dtlsSrtpProfiles, profile_str);
- }
- return ret;
- }
- const WOLFSSL_SRTP_PROTECTION_PROFILE* wolfSSL_get_selected_srtp_profile(
- WOLFSSL* ssl)
- {
- const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL;
- if (ssl) {
- profile = DtlsSrtpFindProfile(NULL, 0, ssl->dtlsSrtpId);
- }
- return profile;
- }
- #ifndef NO_WOLFSSL_STUB
- WOLF_STACK_OF(WOLFSSL_SRTP_PROTECTION_PROFILE)* wolfSSL_get_srtp_profiles(
- WOLFSSL* ssl)
- {
- /* Not yet implemented - should return list of available SRTP profiles
- * ssl->dtlsSrtpProfiles */
- (void)ssl;
- return NULL;
- }
- #endif
- int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl,
- unsigned char* out, size_t* olen)
- {
- int ret = WOLFSSL_FAILURE;
- const char* label = "EXTRACTOR-dtls_srtp";
- const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL;
- byte seed[SEED_LEN];
- if (ssl == NULL || olen == NULL) {
- return BAD_FUNC_ARG;
- }
- profile = DtlsSrtpFindProfile(NULL, 0, ssl->dtlsSrtpId);
- if (profile == NULL) {
- WOLFSSL_MSG("Not using DTLS SRTP");
- return EXT_MISSING;
- }
- if (out == NULL) {
- *olen = profile->kdfBits;
- return LENGTH_ONLY_E;
- }
- if (*olen < (size_t)profile->kdfBits) {
- return BUFFER_E;
- }
- #ifdef WOLFSSL_HAVE_PRF
- XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
- PRIVATE_KEY_UNLOCK();
- ret = wc_PRF_TLS(out, profile->kdfBits, /* out: generated keys / salt */
- ssl->arrays->masterSecret, SECRET_LEN, /* existing master secret */
- (const byte*)label, (int)XSTRLEN(label),/* label */
- seed, SEED_LEN, /* seed: client/server random */
- IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
- ssl->heap, INVALID_DEVID);
- if (ret == 0) {
- *olen = profile->kdfBits;
- ret = WOLFSSL_SUCCESS;
- }
- PRIVATE_KEY_LOCK();
- #else
- /* Pseudo random function must be enabled in the configuration */
- ret = PRF_MISSING;
- #endif
- return ret;
- }
- #endif /* WOLFSSL_SRTP */
- #ifdef WOLFSSL_DTLS_DROP_STATS
- int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
- word32* macDropCount, word32* replayDropCount)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()");
- if (ssl == NULL)
- ret = BAD_FUNC_ARG;
- else {
- ret = WOLFSSL_SUCCESS;
- if (macDropCount != NULL)
- *macDropCount = ssl->macDropCount;
- if (replayDropCount != NULL)
- *replayDropCount = ssl->replayDropCount;
- }
- WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret);
- return ret;
- }
- #endif /* WOLFSSL_DTLS_DROP_STATS */
- #if defined(WOLFSSL_MULTICAST)
- int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
- {
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()");
- if (ctx == NULL || id > 255)
- ret = BAD_FUNC_ARG;
- if (ret == 0) {
- ctx->haveEMS = 0;
- ctx->haveMcast = 1;
- ctx->mcastID = (byte)id;
- #ifndef WOLFSSL_USER_IO
- ctx->CBIORecv = EmbedReceiveFromMcast;
- #endif /* WOLFSSL_USER_IO */
- ret = WOLFSSL_SUCCESS;
- }
- WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret);
- return ret;
- }
- int wolfSSL_mcast_get_max_peers(void)
- {
- return WOLFSSL_MULTICAST_PEERS;
- }
- #ifdef WOLFSSL_DTLS
- static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
- word32 second, word32 high)
- {
- word32 newCur = 0;
- if (cur < first)
- newCur = first;
- else if (cur < second)
- newCur = second;
- else if (cur < high)
- newCur = high;
- return newCur;
- }
- #endif /* WOLFSSL_DTLS */
- int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch,
- const byte* preMasterSecret, word32 preMasterSz,
- const byte* clientRandom, const byte* serverRandom,
- const byte* suite)
- {
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_set_secret()");
- if (ssl == NULL || preMasterSecret == NULL ||
- preMasterSz == 0 || preMasterSz > ENCRYPT_LEN ||
- clientRandom == NULL || serverRandom == NULL || suite == NULL) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0 && ssl->arrays->preMasterSecret == NULL) {
- ssl->arrays->preMasterSz = ENCRYPT_LEN;
- ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
- DYNAMIC_TYPE_SECRET);
- if (ssl->arrays->preMasterSecret == NULL) {
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz);
- XMEMSET(ssl->arrays->preMasterSecret + preMasterSz, 0, ENCRYPT_LEN - preMasterSz);
- ssl->arrays->preMasterSz = preMasterSz;
- XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN);
- XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN);
- ssl->options.cipherSuite0 = suite[0];
- ssl->options.cipherSuite = suite[1];
- ret = SetCipherSpecs(ssl);
- }
- if (ret == 0)
- ret = MakeTlsMasterSecret(ssl);
- if (ret == 0) {
- ssl->keys.encryptionOn = 1;
- ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
- }
- if (ret == 0) {
- if (ssl->options.dtls) {
- #ifdef WOLFSSL_DTLS
- WOLFSSL_DTLS_PEERSEQ* peerSeq;
- int i;
- ssl->keys.dtls_epoch = epoch;
- for (i = 0, peerSeq = ssl->keys.peerSeq;
- i < WOLFSSL_DTLS_PEERSEQ_SZ;
- i++, peerSeq++) {
- peerSeq->nextEpoch = epoch;
- peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
- peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
- peerSeq->nextSeq_lo = 0;
- peerSeq->nextSeq_hi = 0;
- XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ);
- XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
- peerSeq->highwaterMark = UpdateHighwaterMark(0,
- ssl->ctx->mcastFirstSeq,
- ssl->ctx->mcastSecondSeq,
- ssl->ctx->mcastMaxSeq);
- }
- #else
- (void)epoch;
- #endif
- }
- FreeHandshakeResources(ssl);
- ret = WOLFSSL_SUCCESS;
- }
- else {
- if (ssl)
- ssl->error = ret;
- ret = WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_LEAVE("wolfSSL_set_secret()", ret);
- return ret;
- }
- #ifdef WOLFSSL_DTLS
- int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int sub)
- {
- WOLFSSL_DTLS_PEERSEQ* p = NULL;
- int ret = WOLFSSL_SUCCESS;
- int i;
- WOLFSSL_ENTER("wolfSSL_mcast_peer_add()");
- if (ssl == NULL || peerId > 255)
- return BAD_FUNC_ARG;
- if (!sub) {
- /* Make sure it isn't already present, while keeping the first
- * open spot. */
- for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
- if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID)
- p = &ssl->keys.peerSeq[i];
- if (ssl->keys.peerSeq[i].peerId == peerId) {
- WOLFSSL_MSG("Peer ID already in multicast peer list.");
- p = NULL;
- }
- }
- if (p != NULL) {
- XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ));
- p->peerId = peerId;
- p->highwaterMark = UpdateHighwaterMark(0,
- ssl->ctx->mcastFirstSeq,
- ssl->ctx->mcastSecondSeq,
- ssl->ctx->mcastMaxSeq);
- }
- else {
- WOLFSSL_MSG("No room in peer list.");
- ret = -1;
- }
- }
- else {
- for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
- if (ssl->keys.peerSeq[i].peerId == peerId)
- p = &ssl->keys.peerSeq[i];
- }
- if (p != NULL) {
- p->peerId = INVALID_PEER_ID;
- }
- else {
- WOLFSSL_MSG("Peer not found in list.");
- }
- }
- WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret);
- return ret;
- }
- /* If peerId is in the list of peers and its last sequence number is non-zero,
- * return 1, otherwise return 0. */
- int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
- {
- int known = 0;
- int i;
- WOLFSSL_ENTER("wolfSSL_mcast_peer_known()");
- if (ssl == NULL || peerId > 255) {
- return BAD_FUNC_ARG;
- }
- for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
- if (ssl->keys.peerSeq[i].peerId == peerId) {
- if (ssl->keys.peerSeq[i].nextSeq_hi ||
- ssl->keys.peerSeq[i].nextSeq_lo) {
- known = 1;
- }
- break;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known);
- return known;
- }
- int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq,
- word32 first, word32 second,
- CallbackMcastHighwater cb)
- {
- if (ctx == NULL || (second && first > second) ||
- first > maxSeq || second > maxSeq || cb == NULL) {
- return BAD_FUNC_ARG;
- }
- ctx->mcastHwCb = cb;
- ctx->mcastFirstSeq = first;
- ctx->mcastSecondSeq = second;
- ctx->mcastMaxSeq = maxSeq;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
- {
- if (ssl == NULL || ctx == NULL)
- return BAD_FUNC_ARG;
- ssl->mcastHwCbCtx = ctx;
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_DTLS */
- #endif /* WOLFSSL_MULTICAST */
- #endif /* WOLFSSL_LEANPSK */
- /* return underlying connect or accept, WOLFSSL_SUCCESS on ok */
- int wolfSSL_negotiate(WOLFSSL* ssl)
- {
- int err = WOLFSSL_FATAL_ERROR;
- WOLFSSL_ENTER("wolfSSL_negotiate");
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
- #ifndef NO_WOLFSSL_SERVER
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version))
- err = wolfSSL_accept_TLSv13(ssl);
- else
- #endif
- err = wolfSSL_accept(ssl);
- }
- #endif
- #ifndef NO_WOLFSSL_CLIENT
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version))
- err = wolfSSL_connect_TLSv13(ssl);
- else
- #endif
- err = wolfSSL_connect(ssl);
- }
- #endif
- (void)ssl;
- WOLFSSL_LEAVE("wolfSSL_negotiate", err);
- return err;
- }
- WOLFSSL_ABI
- WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl)
- {
- if (ssl) {
- return ssl->rng;
- }
- return NULL;
- }
- #ifndef WOLFSSL_LEANPSK
- /* object size based on build */
- int wolfSSL_GetObjectSize(void)
- {
- #ifdef SHOW_SIZES
- printf("sizeof suites = %lu\n", (unsigned long)sizeof(Suites));
- printf("sizeof ciphers(2) = %lu\n", (unsigned long)sizeof(Ciphers));
- #ifndef NO_RC4
- printf("\tsizeof arc4 = %lu\n", (unsigned long)sizeof(Arc4));
- #endif
- printf("\tsizeof aes = %lu\n", (unsigned long)sizeof(Aes));
- #ifndef NO_DES3
- printf("\tsizeof des3 = %lu\n", (unsigned long)sizeof(Des3));
- #endif
- #ifdef HAVE_CHACHA
- printf("\tsizeof chacha = %lu\n", (unsigned long)sizeof(ChaCha));
- #endif
- printf("sizeof cipher specs = %lu\n", (unsigned long)sizeof(CipherSpecs));
- printf("sizeof keys = %lu\n", (unsigned long)sizeof(Keys));
- printf("sizeof Hashes(2) = %lu\n", (unsigned long)sizeof(Hashes));
- #ifndef NO_MD5
- printf("\tsizeof MD5 = %lu\n", (unsigned long)sizeof(wc_Md5));
- #endif
- #ifndef NO_SHA
- printf("\tsizeof SHA = %lu\n", (unsigned long)sizeof(wc_Sha));
- #endif
- #ifdef WOLFSSL_SHA224
- printf("\tsizeof SHA224 = %lu\n", (unsigned long)sizeof(wc_Sha224));
- #endif
- #ifndef NO_SHA256
- printf("\tsizeof SHA256 = %lu\n", (unsigned long)sizeof(wc_Sha256));
- #endif
- #ifdef WOLFSSL_SHA384
- printf("\tsizeof SHA384 = %lu\n", (unsigned long)sizeof(wc_Sha384));
- #endif
- #ifdef WOLFSSL_SHA384
- printf("\tsizeof SHA512 = %lu\n", (unsigned long)sizeof(wc_Sha512));
- #endif
- printf("sizeof Buffers = %lu\n", (unsigned long)sizeof(Buffers));
- printf("sizeof Options = %lu\n", (unsigned long)sizeof(Options));
- printf("sizeof Arrays = %lu\n", (unsigned long)sizeof(Arrays));
- #ifndef NO_RSA
- printf("sizeof RsaKey = %lu\n", (unsigned long)sizeof(RsaKey));
- #endif
- #ifdef HAVE_ECC
- printf("sizeof ecc_key = %lu\n", (unsigned long)sizeof(ecc_key));
- #endif
- printf("sizeof WOLFSSL_CIPHER = %lu\n", (unsigned long)sizeof(WOLFSSL_CIPHER));
- printf("sizeof WOLFSSL_SESSION = %lu\n", (unsigned long)sizeof(WOLFSSL_SESSION));
- printf("sizeof WOLFSSL = %lu\n", (unsigned long)sizeof(WOLFSSL));
- printf("sizeof WOLFSSL_CTX = %lu\n", (unsigned long)sizeof(WOLFSSL_CTX));
- #endif
- return sizeof(WOLFSSL);
- }
- int wolfSSL_CTX_GetObjectSize(void)
- {
- return sizeof(WOLFSSL_CTX);
- }
- int wolfSSL_METHOD_GetObjectSize(void)
- {
- return sizeof(WOLFSSL_METHOD);
- }
- #endif
- #ifdef WOLFSSL_STATIC_MEMORY
- int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method,
- unsigned char* buf, unsigned int sz,
- int flag, int maxSz)
- {
- WOLFSSL_HEAP* heap;
- WOLFSSL_HEAP_HINT* hint;
- word32 idx = 0;
- if (ctx == NULL || buf == NULL) {
- return BAD_FUNC_ARG;
- }
- if (*ctx == NULL && method == NULL) {
- return BAD_FUNC_ARG;
- }
- if (*ctx == NULL || (*ctx)->heap == NULL) {
- if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) {
- return BUFFER_E; /* not enough memory for structures */
- }
- heap = (WOLFSSL_HEAP*)buf;
- idx += sizeof(WOLFSSL_HEAP);
- if (wolfSSL_init_memory_heap(heap) != 0) {
- return WOLFSSL_FAILURE;
- }
- hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
- idx += sizeof(WOLFSSL_HEAP_HINT);
- XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
- hint->memory = heap;
- if (*ctx && (*ctx)->heap == NULL) {
- (*ctx)->heap = (void*)hint;
- }
- }
- else {
- #ifdef WOLFSSL_HEAP_TEST
- /* do not load in memory if test has been set */
- if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) {
- return WOLFSSL_SUCCESS;
- }
- #endif
- hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap);
- heap = hint->memory;
- }
- if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) {
- WOLFSSL_MSG("Error partitioning memory");
- return WOLFSSL_FAILURE;
- }
- /* create ctx if needed */
- if (*ctx == NULL) {
- *ctx = wolfSSL_CTX_new_ex(method(hint), hint);
- if (*ctx == NULL) {
- WOLFSSL_MSG("Error creating ctx");
- return WOLFSSL_FAILURE;
- }
- }
- /* determine what max applies too */
- if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
- heap->maxIO = maxSz;
- }
- else { /* general memory used in handshakes */
- heap->maxHa = maxSz;
- }
- heap->flag |= flag;
- (void)maxSz;
- (void)method;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats)
- {
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- WOLFSSL_ENTER("wolfSSL_is_static_memory");
- /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */
- if (mem_stats != NULL && ssl->heap != NULL) {
- WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
- WOLFSSL_HEAP* heap = hint->memory;
- if (heap->flag & WOLFMEM_TRACK_STATS && hint->stats != NULL) {
- XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS));
- }
- }
- return (ssl->heap) ? 1 : 0;
- }
- int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats)
- {
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory");
- /* fill out statistics if wanted */
- if (mem_stats != NULL && ctx->heap != NULL) {
- WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory;
- if (wolfSSL_GetMemStats(heap, mem_stats) != 1) {
- return MEMORY_E;
- }
- }
- return (ctx->heap) ? 1 : 0;
- }
- #endif /* WOLFSSL_STATIC_MEMORY */
- /* return max record layer size plaintext input size */
- int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_GetMaxOutputSize");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (ssl->options.handShakeState != HANDSHAKE_DONE) {
- WOLFSSL_MSG("Handshake not complete yet");
- return BAD_FUNC_ARG;
- }
- return wolfSSL_GetMaxFragSize(ssl, OUTPUT_RECORD_SIZE);
- }
- /* return record layer size of plaintext input size */
- int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz)
- {
- int maxSize;
- WOLFSSL_ENTER("wolfSSL_GetOutputSize");
- if (inSz < 0)
- return BAD_FUNC_ARG;
- maxSize = wolfSSL_GetMaxOutputSize(ssl);
- if (maxSize < 0)
- return maxSize; /* error */
- if (inSz > maxSize)
- return INPUT_SIZE_E;
- return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0, CUR_ORDER);
- }
- #ifdef HAVE_ECC
- int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz)
- {
- if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
- WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null");
- return BAD_FUNC_ARG;
- }
- ctx->minEccKeySz = keySz / 8;
- #ifndef NO_CERTS
- ctx->cm->minEccKeySz = keySz / 8;
- #endif
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz)
- {
- if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
- WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null");
- return BAD_FUNC_ARG;
- }
- ssl->options.minEccKeySz = keySz / 8;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_ECC */
- #ifndef NO_RSA
- int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz)
- {
- if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
- WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null");
- return BAD_FUNC_ARG;
- }
- ctx->minRsaKeySz = keySz / 8;
- ctx->cm->minRsaKeySz = keySz / 8;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz)
- {
- if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
- WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null");
- return BAD_FUNC_ARG;
- }
- ssl->options.minRsaKeySz = keySz / 8;
- return WOLFSSL_SUCCESS;
- }
- #endif /* !NO_RSA */
- #ifndef NO_DH
- /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
- int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
- const unsigned char* g, int gSz)
- {
- WOLFSSL_ENTER("wolfSSL_SetTmpDH");
- if (ssl == NULL || p == NULL || g == NULL)
- return BAD_FUNC_ARG;
- if ((word16)pSz < ssl->options.minDhKeySz)
- return DH_KEY_SIZE_E;
- if ((word16)pSz > ssl->options.maxDhKeySz)
- return DH_KEY_SIZE_E;
- /* this function is for server only */
- if (ssl->options.side == WOLFSSL_CLIENT_END)
- return SIDE_ERROR;
- #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
- !defined(HAVE_SELFTEST)
- ssl->options.dhKeyTested = 0;
- ssl->options.dhDoKeyTest = 1;
- #endif
- if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ssl->buffers.serverDH_P.buffer = NULL;
- }
- if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ssl->buffers.serverDH_G.buffer = NULL;
- }
- ssl->buffers.weOwnDH = 1; /* SSL owns now */
- ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (ssl->buffers.serverDH_P.buffer == NULL)
- return MEMORY_E;
- ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (ssl->buffers.serverDH_G.buffer == NULL) {
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ssl->buffers.serverDH_P.buffer = NULL;
- return MEMORY_E;
- }
- ssl->buffers.serverDH_P.length = pSz;
- ssl->buffers.serverDH_G.length = gSz;
- XMEMCPY(ssl->buffers.serverDH_P.buffer, p, pSz);
- XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz);
- ssl->options.haveDH = 1;
- if (ssl->options.side != WOLFSSL_NEITHER_END) {
- word16 havePSK;
- word16 haveRSA;
- int keySz = 0;
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #else
- havePSK = 0;
- #endif
- #ifdef NO_RSA
- haveRSA = 0;
- #else
- haveRSA = 1;
- #endif
- #ifndef NO_CERTS
- keySz = ssl->buffers.keySz;
- #endif
- InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
- ssl->options.haveDH, ssl->options.haveECDSAsig,
- ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
- ssl->options.haveFalconSig, ssl->options.haveDilithiumSig,
- ssl->options.haveAnon, TRUE, ssl->options.side);
- }
- WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0);
- return WOLFSSL_SUCCESS;
- }
- #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
- !defined(HAVE_SELFTEST)
- /* Enables or disables the session's DH key prime test. */
- int wolfSSL_SetEnableDhKeyTest(WOLFSSL* ssl, int enable)
- {
- WOLFSSL_ENTER("wolfSSL_SetEnableDhKeyTest");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (!enable)
- ssl->options.dhDoKeyTest = 0;
- else
- ssl->options.dhDoKeyTest = 1;
- WOLFSSL_LEAVE("wolfSSL_SetEnableDhKeyTest", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- #endif
- /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
- int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
- const unsigned char* g, int gSz)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
- if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
- if ((word16)pSz < ctx->minDhKeySz)
- return DH_KEY_SIZE_E;
- if ((word16)pSz > ctx->maxDhKeySz)
- return DH_KEY_SIZE_E;
- #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
- !defined(HAVE_SELFTEST)
- {
- WC_RNG rng;
- int error, freeKey = 0;
- #ifdef WOLFSSL_SMALL_STACK
- DhKey *checkKey = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
- if (checkKey == NULL)
- return MEMORY_E;
- #else
- DhKey checkKey[1];
- #endif
- error = wc_InitRng(&rng);
- if (!error)
- error = wc_InitDhKey(checkKey);
- if (!error) {
- freeKey = 1;
- error = wc_DhSetCheckKey(checkKey,
- p, pSz, g, gSz, NULL, 0, 0, &rng);
- }
- if (freeKey)
- wc_FreeDhKey(checkKey);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(checkKey, NULL, DYNAMIC_TYPE_DH);
- #endif
- wc_FreeRng(&rng);
- if (error)
- return error;
- ctx->dhKeyTested = 1;
- }
- #endif
- XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ctx->serverDH_P.buffer = NULL;
- XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ctx->serverDH_G.buffer = NULL;
- ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (ctx->serverDH_P.buffer == NULL)
- return MEMORY_E;
- ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (ctx->serverDH_G.buffer == NULL) {
- XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ctx->serverDH_P.buffer = NULL;
- return MEMORY_E;
- }
- ctx->serverDH_P.length = pSz;
- ctx->serverDH_G.length = gSz;
- XMEMCPY(ctx->serverDH_P.buffer, p, pSz);
- XMEMCPY(ctx->serverDH_G.buffer, g, gSz);
- ctx->haveDH = 1;
- WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0);
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz_bits)
- {
- if (ctx == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0)
- return BAD_FUNC_ARG;
- ctx->minDhKeySz = keySz_bits / 8;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz_bits)
- {
- if (ssl == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0)
- return BAD_FUNC_ARG;
- ssl->options.minDhKeySz = keySz_bits / 8;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz_bits)
- {
- if (ctx == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0)
- return BAD_FUNC_ARG;
- ctx->maxDhKeySz = keySz_bits / 8;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz_bits)
- {
- if (ssl == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0)
- return BAD_FUNC_ARG;
- ssl->options.maxDhKeySz = keySz_bits / 8;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return (ssl->options.dhKeySz * 8);
- }
- #endif /* !NO_DH */
- WOLFSSL_ABI
- int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
- {
- int ret;
- WOLFSSL_ENTER("SSL_write()");
- if (ssl == NULL || data == NULL || sz < 0)
- return BAD_FUNC_ARG;
- #ifdef WOLFSSL_QUIC
- if (WOLFSSL_IS_QUIC(ssl)) {
- WOLFSSL_MSG("SSL_write() on QUIC not allowed");
- return BAD_FUNC_ARG;
- }
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) {
- ssl->error = ret;
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->earlyData = no_early_data;
- #endif
- #ifdef HAVE_WRITE_DUP
- { /* local variable scope */
- int dupErr = 0; /* local copy */
- ret = 0;
- if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
- WOLFSSL_MSG("Read dup side cannot write");
- return WRITE_DUP_WRITE_E;
- }
- if (ssl->dupWrite) {
- if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) {
- return BAD_MUTEX_E;
- }
- dupErr = ssl->dupWrite->dupErr;
- ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
- }
- if (ret != 0) {
- ssl->error = ret; /* high priority fatal error */
- return WOLFSSL_FATAL_ERROR;
- }
- if (dupErr != 0) {
- WOLFSSL_MSG("Write dup error from other side");
- ssl->error = dupErr;
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif
- #ifdef HAVE_ERRNO_H
- errno = 0;
- #endif
- #ifdef OPENSSL_EXTRA
- if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_WRITE, WOLFSSL_SUCCESS);
- ssl->cbmode = SSL_CB_WRITE;
- }
- #endif
- ret = SendData(ssl, data, sz);
- WOLFSSL_LEAVE("SSL_write()", ret);
- if (ret < 0)
- return WOLFSSL_FATAL_ERROR;
- else
- return ret;
- }
- static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_read_internal()");
- if (ssl == NULL || data == NULL || sz < 0)
- return BAD_FUNC_ARG;
- #ifdef WOLFSSL_QUIC
- if (WOLFSSL_IS_QUIC(ssl)) {
- WOLFSSL_MSG("SSL_read() on QUIC not allowed");
- return BAD_FUNC_ARG;
- }
- #endif
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL) && defined(OPENSSL_EXTRA)
- /* This additional logic is meant to simulate following openSSL behavior:
- * After bidirectional SSL_shutdown complete, SSL_read returns 0 and
- * SSL_get_error_code returns SSL_ERROR_ZERO_RETURN.
- * This behavior is used to know the disconnect of the underlying
- * transport layer.
- *
- * In this logic, CBIORecv is called with a read size of 0 to check the
- * transport layer status. It also returns WOLFSSL_FAILURE so that
- * SSL_read does not return a positive number on failure.
- */
- /* make sure bidirectional TLS shutdown completes */
- if (ssl->error == WOLFSSL_ERROR_SYSCALL) {
- /* ask the underlying transport the connection is closed */
- if (ssl->CBIORecv(ssl, (char*)data, 0, ssl->IOCB_ReadCtx) ==
- WOLFSSL_CBIO_ERR_CONN_CLOSE) {
- ssl->options.isClosed = 1;
- ssl->error = WOLFSSL_ERROR_ZERO_RETURN;
- }
- return WOLFSSL_FAILURE;
- }
- #endif
- #ifdef HAVE_WRITE_DUP
- if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
- WOLFSSL_MSG("Write dup side cannot read");
- return WRITE_DUP_READ_E;
- }
- #endif
- #ifdef HAVE_ERRNO_H
- errno = 0;
- #endif
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- ssl->dtls_expected_rx = max(sz + DTLS_MTU_ADDITIONAL_READ_BUFFER,
- MAX_MTU);
- #ifdef WOLFSSL_SCTP
- if (ssl->options.dtlsSctp)
- #endif
- #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)
- /* Add some bytes so that we can operate with slight difference
- * in set MTU size on each peer */
- ssl->dtls_expected_rx = max(ssl->dtls_expected_rx,
- ssl->dtlsMtuSz + (word32)DTLS_MTU_ADDITIONAL_READ_BUFFER);
- #endif
- }
- #endif
- ret = ReceiveData(ssl, (byte*)data, sz, peek);
- #ifdef HAVE_WRITE_DUP
- if (ssl->dupWrite) {
- if (ssl->error != 0 && ssl->error != WANT_READ
- #ifdef WOLFSSL_ASYNC_CRYPT
- && ssl->error != WC_PENDING_E
- #endif
- ) {
- int notifyErr;
- WOLFSSL_MSG("Notifying write side of fatal read error");
- notifyErr = NotifyWriteSide(ssl, ssl->error);
- if (notifyErr < 0) {
- ret = ssl->error = notifyErr;
- }
- }
- }
- #endif
- WOLFSSL_LEAVE("wolfSSL_read_internal()", ret);
- if (ret < 0)
- return WOLFSSL_FATAL_ERROR;
- else
- return ret;
- }
- int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz)
- {
- WOLFSSL_ENTER("wolfSSL_peek()");
- return wolfSSL_read_internal(ssl, data, sz, TRUE);
- }
- WOLFSSL_ABI
- int wolfSSL_read(WOLFSSL* ssl, void* data, int sz)
- {
- WOLFSSL_ENTER("wolfSSL_read()");
- #ifdef OPENSSL_EXTRA
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_READ, WOLFSSL_SUCCESS);
- ssl->cbmode = SSL_CB_READ;
- }
- #endif
- return wolfSSL_read_internal(ssl, data, sz, FALSE);
- }
- #ifdef WOLFSSL_MULTICAST
- int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
- {
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_mcast_read()");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
- if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
- *id = ssl->keys.curPeerId;
- return ret;
- }
- #endif /* WOLFSSL_MULTICAST */
- /* helpers to set the device id, WOLFSSL_SUCCESS on ok */
- WOLFSSL_ABI
- int wolfSSL_SetDevId(WOLFSSL* ssl, int devId)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->devId = devId;
- return WOLFSSL_SUCCESS;
- }
- WOLFSSL_ABI
- int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->devId = devId;
- return WOLFSSL_SUCCESS;
- }
- /* helpers to get device id and heap */
- WOLFSSL_ABI
- int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
- {
- int devId = INVALID_DEVID;
- if (ssl != NULL)
- devId = ssl->devId;
- if (ctx != NULL && devId == INVALID_DEVID)
- devId = ctx->devId;
- return devId;
- }
- void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
- {
- void* heap = NULL;
- if (ctx != NULL)
- heap = ctx->heap;
- else if (ssl != NULL)
- heap = ssl->heap;
- return heap;
- }
- #ifdef HAVE_SNI
- WOLFSSL_ABI
- int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap);
- }
- WOLFSSL_ABI
- int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data,
- word16 size)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap);
- }
- #ifndef NO_WOLFSSL_SERVER
- void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options)
- {
- if (ssl && ssl->extensions)
- TLSX_SNI_SetOptions(ssl->extensions, type, options);
- }
- void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options)
- {
- if (ctx && ctx->extensions)
- TLSX_SNI_SetOptions(ctx->extensions, type, options);
- }
- byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type)
- {
- return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type);
- }
- word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data)
- {
- if (data)
- *data = NULL;
- if (ssl && ssl->extensions)
- return TLSX_SNI_GetRequest(ssl->extensions, type, data);
- return 0;
- }
- int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
- byte type, byte* sni, word32* inOutSz)
- {
- if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0)
- return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz);
- return BAD_FUNC_ARG;
- }
- #endif /* NO_WOLFSSL_SERVER */
- #endif /* HAVE_SNI */
- #ifdef HAVE_TRUSTED_CA
- WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, byte type,
- const byte* certId, word32 certIdSz)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED) {
- if (certId != NULL || certIdSz != 0)
- return BAD_FUNC_ARG;
- }
- else if (type == WOLFSSL_TRUSTED_CA_X509_NAME) {
- if (certId == NULL || certIdSz == 0)
- return BAD_FUNC_ARG;
- }
- #ifndef NO_SHA
- else if (type == WOLFSSL_TRUSTED_CA_KEY_SHA1 ||
- type == WOLFSSL_TRUSTED_CA_CERT_SHA1) {
- if (certId == NULL || certIdSz != WC_SHA_DIGEST_SIZE)
- return BAD_FUNC_ARG;
- }
- #endif
- else
- return BAD_FUNC_ARG;
- return TLSX_UseTrustedCA(&ssl->extensions,
- type, certId, certIdSz, ssl->heap);
- }
- #endif /* HAVE_TRUSTED_CA */
- #ifdef HAVE_MAX_FRAGMENT
- #ifndef NO_WOLFSSL_CLIENT
- int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- #ifdef WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST
- /* The following is a non-standard way to reconfigure the max packet size
- post-handshake for wolfSSL_write/wolfSSL_read */
- if (ssl->options.handShakeState == HANDSHAKE_DONE) {
- switch (mfl) {
- case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break;
- case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break;
- case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break;
- case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break;
- case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break;
- case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break;
- default: ssl->max_fragment = MAX_RECORD_SIZE; break;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_MAX_FRAGMENT_ADJUST */
- /* This call sets the max fragment TLS extension, which gets sent to server.
- The server_hello response is what sets the `ssl->max_fragment` in
- TLSX_MFL_Parse */
- return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap);
- }
- int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap);
- }
- #endif /* NO_WOLFSSL_CLIENT */
- #endif /* HAVE_MAX_FRAGMENT */
- #ifdef HAVE_TRUNCATED_HMAC
- #ifndef NO_WOLFSSL_CLIENT
- int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
- }
- int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap);
- }
- #endif /* NO_WOLFSSL_CLIENT */
- #endif /* HAVE_TRUNCATED_HMAC */
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options)
- {
- WOLFSSL_ENTER("wolfSSL_UseOCSPStapling");
- if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
- return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
- options, NULL, ssl->heap, ssl->devId);
- }
- int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type,
- byte options)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_UseOCSPStapling");
- if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
- return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
- options, NULL, ctx->heap, ctx->devId);
- }
- #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
- int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options)
- {
- if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
- return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type,
- options, ssl->heap, ssl->devId);
- }
- int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type,
- byte options)
- {
- if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
- return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type,
- options, ctx->heap, ctx->devId);
- }
- #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
- /* Elliptic Curves */
- #if defined(HAVE_SUPPORTED_CURVES)
- static int isValidCurveGroup(word16 name)
- {
- switch (name) {
- case WOLFSSL_ECC_SECP160K1:
- case WOLFSSL_ECC_SECP160R1:
- case WOLFSSL_ECC_SECP160R2:
- case WOLFSSL_ECC_SECP192K1:
- case WOLFSSL_ECC_SECP192R1:
- case WOLFSSL_ECC_SECP224K1:
- case WOLFSSL_ECC_SECP224R1:
- case WOLFSSL_ECC_SECP256K1:
- case WOLFSSL_ECC_SECP256R1:
- case WOLFSSL_ECC_SECP384R1:
- case WOLFSSL_ECC_SECP521R1:
- case WOLFSSL_ECC_BRAINPOOLP256R1:
- case WOLFSSL_ECC_BRAINPOOLP384R1:
- case WOLFSSL_ECC_BRAINPOOLP512R1:
- case WOLFSSL_ECC_X25519:
- case WOLFSSL_ECC_X448:
- case WOLFSSL_FFDHE_2048:
- case WOLFSSL_FFDHE_3072:
- case WOLFSSL_FFDHE_4096:
- case WOLFSSL_FFDHE_6144:
- case WOLFSSL_FFDHE_8192:
- #ifdef HAVE_PQC
- case WOLFSSL_KYBER_LEVEL1:
- case WOLFSSL_KYBER_LEVEL3:
- case WOLFSSL_KYBER_LEVEL5:
- case WOLFSSL_NTRU_HPS_LEVEL1:
- case WOLFSSL_NTRU_HPS_LEVEL3:
- case WOLFSSL_NTRU_HPS_LEVEL5:
- case WOLFSSL_NTRU_HRSS_LEVEL3:
- case WOLFSSL_SABER_LEVEL1:
- case WOLFSSL_SABER_LEVEL3:
- case WOLFSSL_SABER_LEVEL5:
- case WOLFSSL_KYBER_90S_LEVEL1:
- case WOLFSSL_KYBER_90S_LEVEL3:
- case WOLFSSL_KYBER_90S_LEVEL5:
- case WOLFSSL_P256_NTRU_HPS_LEVEL1:
- case WOLFSSL_P384_NTRU_HPS_LEVEL3:
- case WOLFSSL_P521_NTRU_HPS_LEVEL5:
- case WOLFSSL_P384_NTRU_HRSS_LEVEL3:
- case WOLFSSL_P256_SABER_LEVEL1:
- case WOLFSSL_P384_SABER_LEVEL3:
- case WOLFSSL_P521_SABER_LEVEL5:
- case WOLFSSL_P256_KYBER_LEVEL1:
- case WOLFSSL_P384_KYBER_LEVEL3:
- case WOLFSSL_P521_KYBER_LEVEL5:
- case WOLFSSL_P256_KYBER_90S_LEVEL1:
- case WOLFSSL_P384_KYBER_90S_LEVEL3:
- case WOLFSSL_P521_KYBER_90S_LEVEL5:
- #endif
- return 1;
- default:
- return 0;
- }
- }
- int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name)
- {
- if (ssl == NULL || !isValidCurveGroup(name))
- return BAD_FUNC_ARG;
- ssl->options.userCurves = 1;
- #if defined(NO_TLS)
- return WOLFSSL_FAILURE;
- #else
- return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
- #endif /* NO_TLS */
- }
- int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name)
- {
- if (ctx == NULL || !isValidCurveGroup(name))
- return BAD_FUNC_ARG;
- ctx->userCurves = 1;
- #if defined(NO_TLS)
- return WOLFSSL_FAILURE;
- #else
- return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap);
- #endif /* NO_TLS */
- }
- #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13)
- int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups,
- int count)
- {
- int i;
- int _groups[WOLFSSL_MAX_GROUP_COUNT];
- WOLFSSL_ENTER("wolfSSL_CTX_set1_groups");
- if (count == 0) {
- WOLFSSL_MSG("Group count is zero");
- return WOLFSSL_FAILURE;
- }
- for (i = 0; i < count; i++) {
- if (isValidCurveGroup((word16)groups[i])) {
- _groups[i] = groups[i];
- }
- #ifdef HAVE_ECC
- else {
- /* groups may be populated with curve NIDs */
- int oid = nid2oid(groups[i], oidCurveType);
- int name = (int)GetCurveByOID(oid);
- if (name == 0) {
- WOLFSSL_MSG("Invalid group name");
- return WOLFSSL_FAILURE;
- }
- _groups[i] = name;
- }
- #else
- else {
- WOLFSSL_MSG("Invalid group name");
- return WOLFSSL_FAILURE;
- }
- #endif
- }
- return wolfSSL_CTX_set_groups(ctx, _groups, count) == WOLFSSL_SUCCESS ?
- WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count)
- {
- int i;
- int _groups[WOLFSSL_MAX_GROUP_COUNT];
- WOLFSSL_ENTER("wolfSSL_CTX_set1_groups");
- if (count == 0) {
- WOLFSSL_MSG("Group count is zero");
- return WOLFSSL_FAILURE;
- }
- for (i = 0; i < count; i++) {
- if (isValidCurveGroup((word16)groups[i])) {
- _groups[i] = groups[i];
- }
- #ifdef HAVE_ECC
- else {
- /* groups may be populated with curve NIDs */
- int oid = nid2oid(groups[i], oidCurveType);
- int name = (int)GetCurveByOID(oid);
- if (name == 0) {
- WOLFSSL_MSG("Invalid group name");
- return WOLFSSL_FAILURE;
- }
- _groups[i] = name;
- }
- #else
- else {
- WOLFSSL_MSG("Invalid group name");
- return WOLFSSL_FAILURE;
- }
- #endif
- }
- return wolfSSL_set_groups(ssl, _groups, count) == WOLFSSL_SUCCESS ?
- WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- #endif /* OPENSSL_EXTRA && WOLFSSL_TLS13 */
- #endif /* HAVE_SUPPORTED_CURVES */
- /* Application-Layer Protocol Negotiation */
- #ifdef HAVE_ALPN
- WOLFSSL_ABI
- int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
- word32 protocol_name_listSz, byte options)
- {
- char *list, *ptr, **token;
- word16 len;
- int idx = 0;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_UseALPN");
- if (ssl == NULL || protocol_name_list == NULL)
- return BAD_FUNC_ARG;
- if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
- WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
- WOLFSSL_MAX_ALPN_NUMBER)) {
- WOLFSSL_MSG("Invalid arguments, protocol name list too long");
- return BAD_FUNC_ARG;
- }
- if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) &&
- !(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) {
- WOLFSSL_MSG("Invalid arguments, options not supported");
- return BAD_FUNC_ARG;
- }
- list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap,
- DYNAMIC_TYPE_ALPN);
- if (list == NULL) {
- WOLFSSL_MSG("Memory failure");
- return MEMORY_ERROR;
- }
- token = (char **)XMALLOC(sizeof(char *) * (WOLFSSL_MAX_ALPN_NUMBER+1), ssl->heap, DYNAMIC_TYPE_ALPN);
- if (token == NULL) {
- XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN);
- WOLFSSL_MSG("Memory failure");
- return MEMORY_ERROR;
- }
- XMEMSET(token, 0, sizeof(char *) * (WOLFSSL_MAX_ALPN_NUMBER+1));
- XSTRNCPY(list, protocol_name_list, protocol_name_listSz);
- list[protocol_name_listSz] = '\0';
- /* read all protocol name from the list */
- token[idx] = XSTRTOK(list, ",", &ptr);
- while (idx < WOLFSSL_MAX_ALPN_NUMBER && token[idx] != NULL)
- token[++idx] = XSTRTOK(NULL, ",", &ptr);
- /* add protocol name list in the TLS extension in reverse order */
- while ((idx--) > 0) {
- len = (word16)XSTRLEN(token[idx]);
- ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options,
- ssl->heap);
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("TLSX_UseALPN failure");
- break;
- }
- }
- XFREE(token, ssl->heap, DYNAMIC_TYPE_ALPN);
- XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN);
- return ret;
- }
- int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size)
- {
- return TLSX_ALPN_GetRequest(ssl ? ssl->extensions : NULL,
- (void **)protocol_name, size);
- }
- int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz)
- {
- if (list == NULL || listSz == NULL)
- return BAD_FUNC_ARG;
- if (ssl->alpn_client_list == NULL)
- return BUFFER_ERROR;
- *listSz = (word16)XSTRLEN(ssl->alpn_client_list);
- if (*listSz == 0)
- return BUFFER_ERROR;
- *list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX);
- if (*list == NULL)
- return MEMORY_ERROR;
- XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1);
- (*list)[*listSz] = 0;
- return WOLFSSL_SUCCESS;
- }
- /* used to free memory allocated by wolfSSL_ALPN_GetPeerProtocol */
- int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list)
- {
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX);
- *list = NULL;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_ALPN */
- /* Secure Renegotiation */
- #ifdef HAVE_SERVER_RENEGOTIATION_INFO
- /* user is forcing ability to use secure renegotiation, we discourage it */
- int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl)
- {
- int ret = BAD_FUNC_ARG;
- #if defined(NO_TLS)
- (void)ssl;
- #else
- if (ssl)
- ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap);
- if (ret == WOLFSSL_SUCCESS) {
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
- if (extension)
- ssl->secure_renegotiation = (SecureRenegotiation*)extension->data;
- }
- #endif /* !NO_TLS */
- return ret;
- }
- int wolfSSL_CTX_UseSecureRenegotiation(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->useSecureReneg = 1;
- return WOLFSSL_SUCCESS;
- }
- /* do a secure renegotiation handshake, user forced, we discourage */
- static int _Rehandshake(WOLFSSL* ssl)
- {
- int ret;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (ssl->secure_renegotiation == NULL) {
- WOLFSSL_MSG("Secure Renegotiation not forced on by user");
- return SECURE_RENEGOTIATION_E;
- }
- if (ssl->secure_renegotiation->enabled == 0) {
- WOLFSSL_MSG("Secure Renegotiation not enabled at extension level");
- return SECURE_RENEGOTIATION_E;
- }
- /* If the client started the renegotiation, the server will already
- * have processed the client's hello. */
- if (ssl->options.side != WOLFSSL_SERVER_END ||
- ssl->options.acceptState != ACCEPT_FIRST_REPLY_DONE) {
- if (ssl->options.handShakeState != HANDSHAKE_DONE) {
- if (!ssl->options.handShakeDone) {
- WOLFSSL_MSG("Can't renegotiate until initial "
- "handshake complete");
- return SECURE_RENEGOTIATION_E;
- }
- else {
- WOLFSSL_MSG("Renegotiation already started. "
- "Moving it forward.");
- ret = wolfSSL_negotiate(ssl);
- if (ret == WOLFSSL_SUCCESS)
- ssl->secure_rene_count++;
- return ret;
- }
- }
- #ifndef NO_FORCE_SCR_SAME_SUITE
- /* force same suite */
- if (ssl->suites) {
- ssl->suites->suiteSz = SUITE_LEN;
- ssl->suites->suites[0] = ssl->options.cipherSuite0;
- ssl->suites->suites[1] = ssl->options.cipherSuite;
- }
- #endif
- /* reset handshake states */
- ssl->options.sendVerify = 0;
- ssl->options.serverState = NULL_STATE;
- ssl->options.clientState = NULL_STATE;
- ssl->options.connectState = CONNECT_BEGIN;
- ssl->options.acceptState = ACCEPT_BEGIN_RENEG;
- ssl->options.handShakeState = NULL_STATE;
- ssl->options.processReply = 0; /* TODO, move states in internal.h */
- XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
- ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
- #if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SECURE_RENEGOTIATION)
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- ret = SendHelloRequest(ssl);
- if (ret != 0) {
- ssl->error = ret;
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif /* !NO_WOLFSSL_SERVER && HAVE_SECURE_RENEGOTIATION */
- ret = InitHandshakeHashes(ssl);
- if (ret != 0) {
- ssl->error = ret;
- return WOLFSSL_FATAL_ERROR;
- }
- }
- ret = wolfSSL_negotiate(ssl);
- if (ret == WOLFSSL_SUCCESS)
- ssl->secure_rene_count++;
- return ret;
- }
- /* do a secure renegotiation handshake, user forced, we discourage */
- int wolfSSL_Rehandshake(WOLFSSL* ssl)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_Rehandshake");
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- #ifdef HAVE_SESSION_TICKET
- ret = WOLFSSL_SUCCESS;
- #endif
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- /* Reset option to send certificate verify. */
- ssl->options.sendVerify = 0;
- }
- else {
- /* Reset resuming flag to do full secure handshake. */
- ssl->options.resuming = 0;
- #ifdef HAVE_SESSION_TICKET
- /* Clearing the ticket. */
- ret = wolfSSL_UseSessionTicket(ssl);
- #endif
- }
- /* CLIENT/SERVER: Reset peer authentication for full secure handshake. */
- ssl->options.peerAuthGood = 0;
- #ifdef HAVE_SESSION_TICKET
- if (ret == WOLFSSL_SUCCESS)
- #endif
- ret = _Rehandshake(ssl);
- return ret;
- }
- #ifndef NO_WOLFSSL_CLIENT
- /* do a secure resumption handshake, user forced, we discourage */
- int wolfSSL_SecureResume(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_SecureResume");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- ssl->error = SIDE_ERROR;
- return WOLFSSL_FATAL_ERROR;
- }
- return _Rehandshake(ssl);
- }
- #endif /* NO_WOLFSSL_CLIENT */
- long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_get_secure_renegotiation_support");
- if (!ssl || !ssl->secure_renegotiation)
- return WOLFSSL_FAILURE;
- return ssl->secure_renegotiation->enabled;
- }
- #endif /* HAVE_SECURE_RENEGOTIATION_INFO */
- #if defined(HAVE_SESSION_TICKET)
- /* Session Ticket */
- #if !defined(NO_WOLFSSL_SERVER)
- int wolfSSL_CTX_NoTicketTLSv12(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->noTicketTls12 = 1;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_NoTicketTLSv12(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->options.noTicketTls12 = 1;
- return WOLFSSL_SUCCESS;
- }
- /* WOLFSSL_SUCCESS on ok */
- int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->ticketEncCb = cb;
- return WOLFSSL_SUCCESS;
- }
- /* set hint interval, WOLFSSL_SUCCESS on ok */
- int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->ticketHint = hint;
- return WOLFSSL_SUCCESS;
- }
- /* set user context, WOLFSSL_SUCCESS on ok */
- int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->ticketEncCtx = userCtx;
- return WOLFSSL_SUCCESS;
- }
- /* get user context - returns userCtx on success, NULL on failure */
- void* wolfSSL_CTX_get_TicketEncCtx(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return NULL;
- return ctx->ticketEncCtx;
- }
- #ifdef WOLFSSL_TLS13
- /* set the maximum number of tickets to send
- * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
- */
- int wolfSSL_CTX_set_num_tickets(WOLFSSL_CTX* ctx, size_t mxTickets)
- {
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
- ctx->maxTicketTls13 = (unsigned int)mxTickets;
- return WOLFSSL_SUCCESS;
- }
- /* get the maximum number of tickets to send
- * return number of tickets set to be sent
- */
- size_t wolfSSL_CTX_get_num_tickets(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return 0;
- return (size_t)ctx->maxTicketTls13;
- }
- #endif /* WOLFSSL_TLS13 */
- #endif /* !NO_WOLFSSL_SERVER */
- #if !defined(NO_WOLFSSL_CLIENT)
- int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
- }
- int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap);
- }
- WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl,
- byte* buf, word32* bufSz)
- {
- if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0)
- return BAD_FUNC_ARG;
- if (ssl->session->ticketLen <= *bufSz) {
- XMEMCPY(buf, ssl->session->ticket, ssl->session->ticketLen);
- *bufSz = ssl->session->ticketLen;
- }
- else
- *bufSz = 0;
- return WOLFSSL_SUCCESS;
- }
- WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
- word32 bufSz)
- {
- if (ssl == NULL || (buf == NULL && bufSz > 0))
- return BAD_FUNC_ARG;
- if (bufSz > 0) {
- /* Ticket will fit into static ticket */
- if (bufSz <= SESSION_TICKET_LEN) {
- if (ssl->session->ticketLenAlloc > 0) {
- XFREE(ssl->session->ticket, ssl->session->heap,
- DYNAMIC_TYPE_SESSION_TICK);
- ssl->session->ticketLenAlloc = 0;
- ssl->session->ticket = ssl->session->staticTicket;
- }
- }
- else { /* Ticket requires dynamic ticket storage */
- if (ssl->session->ticketLen < bufSz) { /* is dyn buffer big enough */
- if (ssl->session->ticketLenAlloc > 0) {
- XFREE(ssl->session->ticket, ssl->session->heap,
- DYNAMIC_TYPE_SESSION_TICK);
- }
- ssl->session->ticket = (byte*)XMALLOC(bufSz, ssl->session->heap,
- DYNAMIC_TYPE_SESSION_TICK);
- if(ssl->session->ticket == NULL) {
- ssl->session->ticket = ssl->session->staticTicket;
- ssl->session->ticketLenAlloc = 0;
- return MEMORY_ERROR;
- }
- ssl->session->ticketLenAlloc = (word16)bufSz;
- }
- }
- XMEMCPY(ssl->session->ticket, buf, bufSz);
- }
- ssl->session->ticketLen = (word16)bufSz;
- return WOLFSSL_SUCCESS;
- }
- WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl,
- CallbackSessionTicket cb, void* ctx)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->session_ticket_cb = cb;
- ssl->session_ticket_ctx = ctx;
- return WOLFSSL_SUCCESS;
- }
- #endif /* !NO_WOLFSSL_CLIENT */
- #endif /* HAVE_SESSION_TICKET */
- #ifdef HAVE_EXTENDED_MASTER
- #ifndef NO_WOLFSSL_CLIENT
- int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->haveEMS = 0;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->options.haveEMS = 0;
- return WOLFSSL_SUCCESS;
- }
- #endif
- #endif
- #ifndef WOLFSSL_LEANPSK
- int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags)
- {
- int ret;
- int oldFlags;
- WOLFSSL_ENTER("wolfSSL_send()");
- if (ssl == NULL || data == NULL || sz < 0)
- return BAD_FUNC_ARG;
- oldFlags = ssl->wflags;
- ssl->wflags = flags;
- ret = wolfSSL_write(ssl, data, sz);
- ssl->wflags = oldFlags;
- WOLFSSL_LEAVE("wolfSSL_send()", ret);
- return ret;
- }
- int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags)
- {
- int ret;
- int oldFlags;
- WOLFSSL_ENTER("wolfSSL_recv()");
- if (ssl == NULL || data == NULL || sz < 0)
- return BAD_FUNC_ARG;
- oldFlags = ssl->rflags;
- ssl->rflags = flags;
- ret = wolfSSL_read(ssl, data, sz);
- ssl->rflags = oldFlags;
- WOLFSSL_LEAVE("wolfSSL_recv()", ret);
- return ret;
- }
- #endif
- /* WOLFSSL_SUCCESS on ok */
- WOLFSSL_ABI
- int wolfSSL_shutdown(WOLFSSL* ssl)
- {
- int ret = WOLFSSL_FATAL_ERROR;
- WOLFSSL_ENTER("SSL_shutdown()");
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
- if (ssl->options.quietShutdown) {
- WOLFSSL_MSG("quiet shutdown, no close notify sent");
- ret = WOLFSSL_SUCCESS;
- }
- else {
- /* try to send close notify, not an error if can't */
- if (!ssl->options.isClosed && !ssl->options.connReset &&
- !ssl->options.sentNotify) {
- ssl->error = SendAlert(ssl, alert_warning, close_notify);
- if (ssl->error < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.sentNotify = 1; /* don't send close_notify twice */
- if (ssl->options.closeNotify)
- ret = WOLFSSL_SUCCESS;
- else {
- ret = WOLFSSL_SHUTDOWN_NOT_DONE;
- WOLFSSL_LEAVE("SSL_shutdown()", ret);
- return ret;
- }
- }
- #ifdef WOLFSSL_SHUTDOWNONCE
- if (ssl->options.isClosed || ssl->options.connReset) {
- /* Shutdown has already occurred.
- * Caller is free to ignore this error. */
- return SSL_SHUTDOWN_ALREADY_DONE_E;
- }
- #endif
- /* call wolfSSL_shutdown again for bidirectional shutdown */
- if (ssl->options.sentNotify && !ssl->options.closeNotify) {
- ret = ProcessReply(ssl);
- if (ret == ZERO_RETURN) {
- /* simulate OpenSSL behavior */
- ssl->error = WOLFSSL_ERROR_SYSCALL;
- ret = WOLFSSL_SUCCESS;
- } else if (ssl->error == WOLFSSL_ERROR_NONE) {
- ret = WOLFSSL_SHUTDOWN_NOT_DONE;
- } else {
- WOLFSSL_ERROR(ssl->error);
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- }
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- /* reset WOLFSSL structure state for possible re-use */
- if (ret == WOLFSSL_SUCCESS) {
- if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("could not clear WOLFSSL");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- #endif
- WOLFSSL_LEAVE("SSL_shutdown()", ret);
- return ret;
- }
- /* get current error state value */
- int wolfSSL_state(WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- return ssl->error;
- }
- WOLFSSL_ABI
- int wolfSSL_get_error(WOLFSSL* ssl, int ret)
- {
- WOLFSSL_ENTER("SSL_get_error");
- if (ret > 0)
- return WOLFSSL_ERROR_NONE;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- WOLFSSL_LEAVE("SSL_get_error", ssl->error);
- /* make sure converted types are handled in SetErrorString() too */
- if (ssl->error == WANT_READ)
- return WOLFSSL_ERROR_WANT_READ; /* convert to OpenSSL type */
- else if (ssl->error == WANT_WRITE)
- return WOLFSSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */
- else if (ssl->error == ZERO_RETURN)
- return WOLFSSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */
- return ssl->error;
- }
- /* retrieve alert history, WOLFSSL_SUCCESS on ok */
- int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h)
- {
- if (ssl && h) {
- *h = ssl->alert_history;
- }
- return WOLFSSL_SUCCESS;
- }
- #ifdef OPENSSL_EXTRA
- /* returns SSL_WRITING, SSL_READING or SSL_NOTHING */
- int wolfSSL_want(WOLFSSL* ssl)
- {
- int rw_state = SSL_NOTHING;
- if (ssl) {
- if (ssl->error == WANT_READ)
- rw_state = SSL_READING;
- else if (ssl->error == WANT_WRITE)
- rw_state = SSL_WRITING;
- }
- return rw_state;
- }
- #endif
- /* return TRUE if current error is want read */
- int wolfSSL_want_read(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_want_read");
- if (ssl->error == WANT_READ)
- return 1;
- return 0;
- }
- /* return TRUE if current error is want write */
- int wolfSSL_want_write(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_want_write");
- if (ssl->error == WANT_WRITE)
- return 1;
- return 0;
- }
- char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data)
- {
- static char tmp[WOLFSSL_MAX_ERROR_SZ] = {0};
- WOLFSSL_ENTER("ERR_error_string");
- if (data) {
- SetErrorString((int)errNumber, data);
- return data;
- }
- else {
- SetErrorString((int)errNumber, tmp);
- return tmp;
- }
- }
- void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, unsigned long len)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_error_string_n");
- if (len >= WOLFSSL_MAX_ERROR_SZ)
- wolfSSL_ERR_error_string(e, buf);
- else {
- char tmp[WOLFSSL_MAX_ERROR_SZ];
- WOLFSSL_MSG("Error buffer too short, truncating");
- if (len) {
- wolfSSL_ERR_error_string(e, tmp);
- XMEMCPY(buf, tmp, len-1);
- buf[len-1] = '\0';
- }
- }
- }
- /* don't free temporary arrays at end of handshake */
- void wolfSSL_KeepArrays(WOLFSSL* ssl)
- {
- if (ssl)
- ssl->options.saveArrays = 1;
- }
- /* user doesn't need temporary arrays anymore, Free */
- void wolfSSL_FreeArrays(WOLFSSL* ssl)
- {
- if (ssl && ssl->options.handShakeState == HANDSHAKE_DONE) {
- ssl->options.saveArrays = 0;
- FreeArrays(ssl, 1);
- }
- }
- /* Set option to indicate that the resources are not to be freed after
- * handshake.
- *
- * ssl The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
- int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->options.keepResources = 1;
- return 0;
- }
- /* Free the handshake resources after handshake.
- *
- * ssl The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
- int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- FreeHandshakeResources(ssl);
- return 0;
- }
- /* Use the client's order of preference when matching cipher suites.
- *
- * ssl The SSL/TLS context object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
- int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->useClientOrder = 1;
- return 0;
- }
- /* Use the client's order of preference when matching cipher suites.
- *
- * ssl The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
- int wolfSSL_UseClientSuites(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->options.useClientOrder = 1;
- return 0;
- }
- #ifdef WOLFSSL_DTLS
- const byte* wolfSSL_GetDtlsMacSecret(WOLFSSL* ssl, int verify, int epochOrder)
- {
- #ifndef WOLFSSL_AEAD_ONLY
- Keys* keys = NULL;
- (void)epochOrder;
- if (ssl == NULL)
- return NULL;
- #ifdef HAVE_SECURE_RENEGOTIATION
- switch (epochOrder) {
- case PEER_ORDER:
- if (IsDtlsMsgSCRKeys(ssl))
- keys = &ssl->secure_renegotiation->tmp_keys;
- else
- keys = &ssl->keys;
- break;
- case PREV_ORDER:
- keys = &ssl->keys;
- break;
- case CUR_ORDER:
- if (DtlsUseSCRKeys(ssl))
- keys = &ssl->secure_renegotiation->tmp_keys;
- else
- keys = &ssl->keys;
- break;
- default:
- WOLFSSL_MSG("Unknown epoch order");
- return NULL;
- }
- #else
- keys = &ssl->keys;
- #endif
- if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
- (ssl->options.side == WOLFSSL_SERVER_END && verify) )
- return keys->client_write_MAC_secret;
- else
- return keys->server_write_MAC_secret;
- #else
- (void)ssl;
- (void)verify;
- (void)epochOrder;
- return NULL;
- #endif
- }
- #endif /* WOLFSSL_DTLS */
- const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify)
- {
- #ifndef WOLFSSL_AEAD_ONLY
- if (ssl == NULL)
- return NULL;
- if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
- (ssl->options.side == WOLFSSL_SERVER_END && verify) )
- return ssl->keys.client_write_MAC_secret;
- else
- return ssl->keys.server_write_MAC_secret;
- #else
- (void)ssl;
- (void)verify;
- return NULL;
- #endif
- }
- #ifdef ATOMIC_USER
- void wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX* ctx, CallbackMacEncrypt cb)
- {
- if (ctx)
- ctx->MacEncryptCb = cb;
- }
- void wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->MacEncryptCtx = ctx;
- }
- void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->MacEncryptCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX* ctx, CallbackDecryptVerify cb)
- {
- if (ctx)
- ctx->DecryptVerifyCb = cb;
- }
- void wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->DecryptVerifyCtx = ctx;
- }
- void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->DecryptVerifyCtx;
- return NULL;
- }
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- /**
- * Set the callback, against the context, that encrypts then MACs.
- *
- * ctx SSL/TLS context.
- * cb Callback function to use with Encrypt-Then-MAC.
- */
- void wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX* ctx, CallbackEncryptMac cb)
- {
- if (ctx)
- ctx->EncryptMacCb = cb;
- }
- /**
- * Set the context to use with callback that encrypts then MACs.
- *
- * ssl SSL/TLS object.
- * ctx Callback function's context.
- */
- void wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->EncryptMacCtx = ctx;
- }
- /**
- * Get the context being used with callback that encrypts then MACs.
- *
- * ssl SSL/TLS object.
- * returns callback function's context or NULL if SSL/TLS object is NULL.
- */
- void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->EncryptMacCtx;
- return NULL;
- }
- /**
- * Set the callback, against the context, that MAC verifies then decrypts.
- *
- * ctx SSL/TLS context.
- * cb Callback function to use with Encrypt-Then-MAC.
- */
- void wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX* ctx, CallbackVerifyDecrypt cb)
- {
- if (ctx)
- ctx->VerifyDecryptCb = cb;
- }
- /**
- * Set the context to use with callback that MAC verifies then decrypts.
- *
- * ssl SSL/TLS object.
- * ctx Callback function's context.
- */
- void wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->VerifyDecryptCtx = ctx;
- }
- /**
- * Get the context being used with callback that MAC verifies then decrypts.
- *
- * ssl SSL/TLS object.
- * returns callback function's context or NULL if SSL/TLS object is NULL.
- */
- void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->VerifyDecryptCtx;
- return NULL;
- }
- #endif /* HAVE_ENCRYPT_THEN_MAC !WOLFSSL_AEAD_ONLY */
- const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->keys.client_write_key;
- return NULL;
- }
- const byte* wolfSSL_GetClientWriteIV(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->keys.client_write_IV;
- return NULL;
- }
- const byte* wolfSSL_GetServerWriteKey(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->keys.server_write_key;
- return NULL;
- }
- const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->keys.server_write_IV;
- return NULL;
- }
- int wolfSSL_GetKeySize(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->specs.key_size;
- return BAD_FUNC_ARG;
- }
- int wolfSSL_GetIVSize(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->specs.iv_size;
- return BAD_FUNC_ARG;
- }
- int wolfSSL_GetBulkCipher(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->specs.bulk_cipher_algorithm;
- return BAD_FUNC_ARG;
- }
- int wolfSSL_GetCipherType(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- #ifndef WOLFSSL_AEAD_ONLY
- if (ssl->specs.cipher_type == block)
- return WOLFSSL_BLOCK_TYPE;
- if (ssl->specs.cipher_type == stream)
- return WOLFSSL_STREAM_TYPE;
- #endif
- if (ssl->specs.cipher_type == aead)
- return WOLFSSL_AEAD_TYPE;
- return -1;
- }
- int wolfSSL_GetCipherBlockSize(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return ssl->specs.block_size;
- }
- int wolfSSL_GetAeadMacSize(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return ssl->specs.aead_mac_size;
- }
- int wolfSSL_IsTLSv1_1(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (ssl->options.tls1_1)
- return 1;
- return 0;
- }
- int wolfSSL_GetSide(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->options.side;
- return BAD_FUNC_ARG;
- }
- int wolfSSL_GetHmacSize(WOLFSSL* ssl)
- {
- /* AEAD ciphers don't have HMAC keys */
- if (ssl)
- return (ssl->specs.cipher_type != aead) ? ssl->specs.hash_size : 0;
- return BAD_FUNC_ARG;
- }
- #ifdef WORD64_AVAILABLE
- int wolfSSL_GetPeerSequenceNumber(WOLFSSL* ssl, word64 *seq)
- {
- if ((ssl == NULL) || (seq == NULL))
- return BAD_FUNC_ARG;
- *seq = ((word64)ssl->keys.peer_sequence_number_hi << 32) |
- ssl->keys.peer_sequence_number_lo;
- return !(*seq);
- }
- int wolfSSL_GetSequenceNumber(WOLFSSL* ssl, word64 *seq)
- {
- if ((ssl == NULL) || (seq == NULL))
- return BAD_FUNC_ARG;
- *seq = ((word64)ssl->keys.sequence_number_hi << 32) |
- ssl->keys.sequence_number_lo;
- return !(*seq);
- }
- #endif
- #endif /* ATOMIC_USER */
- #ifndef NO_CERTS
- WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_CERT_MANAGER* cm = NULL;
- if (ctx)
- cm = ctx->cm;
- return cm;
- }
- WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
- {
- WOLFSSL_CERT_MANAGER* cm;
- WOLFSSL_ENTER("wolfSSL_CertManagerNew");
- cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
- DYNAMIC_TYPE_CERT_MANAGER);
- if (cm) {
- XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
- cm->refCount = 1;
- if (wc_InitMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("Bad mutex init");
- wolfSSL_CertManagerFree(cm);
- return NULL;
- }
- #ifndef SINGLE_THREADED
- if (wc_InitMutex(&cm->refMutex) != 0) {
- WOLFSSL_MSG("Bad mutex init");
- wolfSSL_CertManagerFree(cm);
- return NULL;
- }
- #endif
- #ifdef WOLFSSL_TRUST_PEER_CERT
- if (wc_InitMutex(&cm->tpLock) != 0) {
- WOLFSSL_MSG("Bad mutex init");
- wolfSSL_CertManagerFree(cm);
- return NULL;
- }
- #endif
- /* set default minimum key size allowed */
- #ifndef NO_RSA
- cm->minRsaKeySz = MIN_RSAKEY_SZ;
- #endif
- #ifdef HAVE_ECC
- cm->minEccKeySz = MIN_ECCKEY_SZ;
- #endif
- #ifdef HAVE_PQC
- #ifdef HAVE_FALCON
- cm->minFalconKeySz = MIN_FALCONKEY_SZ;
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ;
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- cm->heap = heap;
- }
- return cm;
- }
- WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
- {
- return wolfSSL_CertManagerNew_ex(NULL);
- }
- void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
- {
- int doFree = 0;
- WOLFSSL_ENTER("wolfSSL_CertManagerFree");
- if (cm) {
- #ifndef SINGLE_THREADED
- if (wc_LockMutex(&cm->refMutex) != 0) {
- WOLFSSL_MSG("Couldn't lock cm mutex");
- }
- #endif
- cm->refCount--;
- if (cm->refCount == 0)
- doFree = 1;
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&cm->refMutex);
- #endif
- if (doFree) {
- #ifdef HAVE_CRL
- if (cm->crl)
- FreeCRL(cm->crl, 1);
- #endif
- #ifdef HAVE_OCSP
- if (cm->ocsp)
- FreeOCSP(cm->ocsp, 1);
- XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
- #if !defined(NO_WOLFSSL_SERVER) && \
- (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
- defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
- if (cm->ocsp_stapling)
- FreeOCSP(cm->ocsp_stapling, 1);
- #endif
- #endif
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
- wc_FreeMutex(&cm->caLock);
- #ifdef WOLFSSL_TRUST_PEER_CERT
- FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
- wc_FreeMutex(&cm->tpLock);
- #endif
- #ifndef SINGLE_THREADED
- if (wc_FreeMutex(&cm->refMutex) != 0) {
- WOLFSSL_MSG("Couldn't free refMutex mutex");
- }
- #endif
- XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
- }
- }
- }
- int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm)
- {
- if (cm) {
- #ifndef SINGLE_THREADED
- if (wc_LockMutex(&cm->refMutex) != 0) {
- WOLFSSL_MSG("Failed to lock cm mutex");
- return WOLFSSL_FAILURE;
- }
- #endif
- cm->refCount++;
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&cm->refMutex);
- #endif
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
- #if defined(WOLFSSL_SIGNER_DER_CERT)
- /******************************************************************************
- * wolfSSL_CertManagerGetCerts - retrieve stack of X509 certificates in a
- * certificate manager (CM).
- *
- * RETURNS:
- * returns stack of X509 certs on success, otherwise returns a NULL.
- */
- WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_STACK* sk = NULL;
- int numCerts = 0;
- DerBuffer** certBuffers = NULL;
- const byte* derBuffer = NULL;
- Signer* signers = NULL;
- word32 row = 0;
- WOLFSSL_X509* x509 = NULL;
- int i = 0;
- int ret = 0;
- if (cm == NULL)
- return NULL;
- sk = wolfSSL_sk_X509_new();
- if (sk == NULL)
- goto error;
- if (wc_LockMutex(&cm->caLock) != 0)
- goto error;
- /* Iterate once to get the number of certs, for memory allocation
- purposes. */
- for (row = 0; row < CA_TABLE_SIZE; row++) {
- signers = cm->caTable[row];
- while (signers && signers->derCert && signers->derCert->buffer) {
- ++numCerts;
- signers = signers->next;
- }
- }
- if (numCerts == 0) {
- wc_UnLockMutex(&cm->caLock);
- goto error;
- }
- certBuffers = (DerBuffer**)XMALLOC(sizeof(DerBuffer*) * numCerts, cm->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (certBuffers == NULL) {
- wc_UnLockMutex(&cm->caLock);
- goto error;
- }
- XMEMSET(certBuffers, 0, sizeof(DerBuffer*) * numCerts);
- /* Copy the certs locally so that we can release the caLock. If the lock is
- held when wolfSSL_d2i_X509 is called, GetCA will also try to get the
- lock, leading to deadlock. */
- for (row = 0; row < CA_TABLE_SIZE; row++) {
- signers = cm->caTable[row];
- while (signers && signers->derCert && signers->derCert->buffer) {
- ret = AllocDer(&certBuffers[i], signers->derCert->length, CA_TYPE,
- cm->heap);
- if (ret < 0) {
- wc_UnLockMutex(&cm->caLock);
- goto error;
- }
- XMEMCPY(certBuffers[i]->buffer, signers->derCert->buffer,
- signers->derCert->length);
- certBuffers[i]->length = signers->derCert->length;
- ++i;
- signers = signers->next;
- }
- }
- wc_UnLockMutex(&cm->caLock);
- for (i = 0; i < numCerts; ++i) {
- derBuffer = certBuffers[i]->buffer;
- wolfSSL_d2i_X509(&x509, &derBuffer, certBuffers[i]->length);
- if (x509 == NULL)
- goto error;
- if (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS)
- goto error;
- }
- for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) {
- FreeDer(&certBuffers[i]);
- }
- XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return sk;
- error:
- if (sk)
- wolfSSL_sk_X509_pop_free(sk, NULL);
- if (certBuffers != NULL) {
- for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) {
- FreeDer(&certBuffers[i]);
- }
- }
- if (certBuffers)
- XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- #endif /* WOLFSSL_SIGNER_DER_CERT */
- #endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
- /* Unload the CA signer list */
- int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- if (wc_LockMutex(&cm->caLock) != 0)
- return BAD_MUTEX_E;
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
- wc_UnLockMutex(&cm->caLock);
- return WOLFSSL_SUCCESS;
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- if (wc_LockMutex(&cm->tpLock) != 0)
- return BAD_MUTEX_E;
- FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
- wc_UnLockMutex(&cm->tpLock);
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- #endif /* NO_CERTS */
- #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
- void wolfSSL_ERR_print_errors_fp(XFILE fp, int err)
- {
- char data[WOLFSSL_MAX_ERROR_SZ + 1];
- WOLFSSL_ENTER("wolfSSL_ERR_print_errors_fp");
- SetErrorString(err, data);
- if (XFPRINTF(fp, "%s", data) < 0)
- WOLFSSL_MSG("fprintf failed in wolfSSL_ERR_print_errors_fp");
- }
- #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
- void wolfSSL_ERR_dump_errors_fp(XFILE fp)
- {
- wc_ERR_print_errors_fp(fp);
- }
- void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len,
- void *u), void *u)
- {
- wc_ERR_print_errors_cb(cb, u);
- }
- #endif
- #endif
- /*
- * TODO This ssl parameter needs to be changed to const once our ABI checker
- * stops flagging qualifier additions as ABI breaking.
- */
- WOLFSSL_ABI
- int wolfSSL_pending(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_pending");
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- return ssl->buffers.clearOutputBuffer.length;
- }
- int wolfSSL_has_pending(const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_has_pending");
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- return ssl->buffers.clearOutputBuffer.length > 0;
- }
- #ifndef WOLFSSL_LEANPSK
- /* turn on handshake group messages for context */
- int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->groupMessages = 1;
- return WOLFSSL_SUCCESS;
- }
- #endif
- #ifndef NO_WOLFSSL_CLIENT
- /* connect enough to get peer cert chain */
- int wolfSSL_connect_cert(WOLFSSL* ssl)
- {
- int ret;
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- ssl->options.certOnly = 1;
- ret = wolfSSL_connect(ssl);
- ssl->options.certOnly = 0;
- return ret;
- }
- #endif
- #ifndef WOLFSSL_LEANPSK
- /* turn on handshake group messages for ssl object */
- int wolfSSL_set_group_messages(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->options.groupMessages = 1;
- return WOLFSSL_SUCCESS;
- }
- /* make minVersion the internal equivalent SSL version */
- static int SetMinVersionHelper(byte* minVersion, int version)
- {
- #ifdef NO_TLS
- (void)minVersion;
- #endif
- switch (version) {
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- case WOLFSSL_SSLV3:
- *minVersion = SSLv3_MINOR;
- break;
- #endif
- #ifndef NO_TLS
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_TLSV10
- case WOLFSSL_TLSV1:
- *minVersion = TLSv1_MINOR;
- break;
- #endif
- case WOLFSSL_TLSV1_1:
- *minVersion = TLSv1_1_MINOR;
- break;
- #endif
- #ifndef WOLFSSL_NO_TLS12
- case WOLFSSL_TLSV1_2:
- *minVersion = TLSv1_2_MINOR;
- break;
- #endif
- #endif
- #ifdef WOLFSSL_TLS13
- case WOLFSSL_TLSV1_3:
- *minVersion = TLSv1_3_MINOR;
- break;
- #endif
- #ifdef WOLFSSL_DTLS
- case WOLFSSL_DTLSV1:
- *minVersion = DTLS_MINOR;
- break;
- case WOLFSSL_DTLSV1_2:
- *minVersion = DTLSv1_2_MINOR;
- break;
- #ifdef WOLFSSL_DTLS13
- case WOLFSSL_DTLSV1_3:
- *minVersion = DTLSv1_3_MINOR;
- break;
- #endif /* WOLFSSL_DTLS13 */
- #endif /* WOLFSSL_DTLS */
- default:
- WOLFSSL_MSG("Bad function argument");
- return BAD_FUNC_ARG;
- }
- return WOLFSSL_SUCCESS;
- }
- /* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
- WOLFSSL_ABI
- int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion");
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return BAD_FUNC_ARG;
- }
- return SetMinVersionHelper(&ctx->minDowngrade, version);
- }
- /* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
- int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version)
- {
- WOLFSSL_ENTER("wolfSSL_SetMinVersion");
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return BAD_FUNC_ARG;
- }
- return SetMinVersionHelper(&ssl->options.minDowngrade, version);
- }
- /* Function to get version as WOLFSSL_ enum value for wolfSSL_SetVersion */
- int wolfSSL_GetVersion(const WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (ssl->version.major == SSLv3_MAJOR) {
- switch (ssl->version.minor) {
- case SSLv3_MINOR :
- return WOLFSSL_SSLV3;
- case TLSv1_MINOR :
- return WOLFSSL_TLSV1;
- case TLSv1_1_MINOR :
- return WOLFSSL_TLSV1_1;
- case TLSv1_2_MINOR :
- return WOLFSSL_TLSV1_2;
- case TLSv1_3_MINOR :
- return WOLFSSL_TLSV1_3;
- default:
- break;
- }
- }
- return VERSION_ERROR;
- }
- int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
- {
- word16 haveRSA = 1;
- word16 havePSK = 0;
- int keySz = 0;
- WOLFSSL_ENTER("wolfSSL_SetVersion");
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return BAD_FUNC_ARG;
- }
- switch (version) {
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- case WOLFSSL_SSLV3:
- ssl->version = MakeSSLv3();
- break;
- #endif
- #ifndef NO_TLS
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_TLSV10
- case WOLFSSL_TLSV1:
- ssl->version = MakeTLSv1();
- break;
- #endif
- case WOLFSSL_TLSV1_1:
- ssl->version = MakeTLSv1_1();
- break;
- #endif
- #ifndef WOLFSSL_NO_TLS12
- case WOLFSSL_TLSV1_2:
- ssl->version = MakeTLSv1_2();
- break;
- #endif
- #ifdef WOLFSSL_TLS13
- case WOLFSSL_TLSV1_3:
- ssl->version = MakeTLSv1_3();
- break;
- #endif /* WOLFSSL_TLS13 */
- #endif
- default:
- WOLFSSL_MSG("Bad function argument");
- return BAD_FUNC_ARG;
- }
- #ifdef NO_RSA
- haveRSA = 0;
- #endif
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #endif
- #ifndef NO_CERTS
- keySz = ssl->buffers.keySz;
- #endif
- InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
- ssl->options.haveDH, ssl->options.haveECDSAsig,
- ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
- ssl->options.haveFalconSig, ssl->options.haveDilithiumSig,
- ssl->options.haveAnon, TRUE, ssl->options.side);
- return WOLFSSL_SUCCESS;
- }
- #endif /* !leanpsk */
- #ifndef NO_CERTS
- /* hash is the SHA digest of name, just use first 32 bits as hash */
- static WC_INLINE word32 HashSigner(const byte* hash)
- {
- return MakeWordFromHash(hash) % CA_TABLE_SIZE;
- }
- /* does CA already exist on signer list */
- int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
- {
- Signer* signers;
- int ret = 0;
- word32 row;
- if (cm == NULL || hash == NULL) {
- return ret;
- }
- row = HashSigner(hash);
- if (wc_LockMutex(&cm->caLock) != 0) {
- return ret;
- }
- signers = cm->caTable[row];
- while (signers) {
- byte* subjectHash;
- #ifndef NO_SKID
- subjectHash = signers->subjectKeyIdHash;
- #else
- subjectHash = signers->subjectNameHash;
- #endif
- if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
- ret = 1; /* success */
- break;
- }
- signers = signers->next;
- }
- wc_UnLockMutex(&cm->caLock);
- return ret;
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- /* hash is the SHA digest of name, just use first 32 bits as hash */
- static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
- {
- return MakeWordFromHash(hash) % TP_TABLE_SIZE;
- }
- /* does trusted peer already exist on signer list */
- int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert)
- {
- TrustedPeerCert* tp;
- int ret = 0;
- word32 row = TrustedPeerHashSigner(cert->subjectHash);
- if (wc_LockMutex(&cm->tpLock) != 0)
- return ret;
- tp = cm->tpTable[row];
- while (tp) {
- if (XMEMCMP(cert->subjectHash, tp->subjectNameHash,
- SIGNER_DIGEST_SIZE) == 0)
- ret = 1;
- #ifndef NO_SKID
- if (cert->extSubjKeyIdSet) {
- /* Compare SKID as well if available */
- if (ret == 1 && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
- SIGNER_DIGEST_SIZE) != 0)
- ret = 0;
- }
- #endif
- if (ret == 1)
- break;
- tp = tp->next;
- }
- wc_UnLockMutex(&cm->tpLock);
- return ret;
- }
- /* return Trusted Peer if found, otherwise NULL
- type is what to match on
- */
- TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert)
- {
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- TrustedPeerCert* ret = NULL;
- TrustedPeerCert* tp = NULL;
- word32 row;
- if (cm == NULL || cert == NULL)
- return NULL;
- row = TrustedPeerHashSigner(cert->subjectHash);
- if (wc_LockMutex(&cm->tpLock) != 0)
- return ret;
- tp = cm->tpTable[row];
- while (tp) {
- if (XMEMCMP(cert->subjectHash, tp->subjectNameHash,
- SIGNER_DIGEST_SIZE) == 0)
- ret = tp;
- #ifndef NO_SKID
- if (cert->extSubjKeyIdSet) {
- /* Compare SKID as well if available */
- if (ret != NULL && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
- SIGNER_DIGEST_SIZE) != 0)
- ret = NULL;
- }
- #endif
- if (ret != NULL)
- break;
- tp = tp->next;
- }
- wc_UnLockMutex(&cm->tpLock);
- return ret;
- }
- int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
- {
- if (tp == NULL || cert == NULL)
- return BAD_FUNC_ARG;
- /* subject key id or subject hash has been compared when searching
- tpTable for the cert from function GetTrustedPeer */
- /* compare signatures */
- if (tp->sigLen == cert->sigLength) {
- if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
- return WOLFSSL_FAILURE;
- }
- }
- else {
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- /* return CA if found, otherwise NULL */
- Signer* GetCA(void* vp, byte* hash)
- {
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- Signer* ret = NULL;
- Signer* signers;
- word32 row = 0;
- if (cm == NULL || hash == NULL)
- return NULL;
- row = HashSigner(hash);
- if (wc_LockMutex(&cm->caLock) != 0)
- return ret;
- signers = cm->caTable[row];
- while (signers) {
- byte* subjectHash;
- #ifndef NO_SKID
- subjectHash = signers->subjectKeyIdHash;
- #else
- subjectHash = signers->subjectNameHash;
- #endif
- if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
- ret = signers;
- break;
- }
- signers = signers->next;
- }
- wc_UnLockMutex(&cm->caLock);
- return ret;
- }
- #ifndef NO_SKID
- /* return CA if found, otherwise NULL. Walk through hash table. */
- Signer* GetCAByName(void* vp, byte* hash)
- {
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- Signer* ret = NULL;
- Signer* signers;
- word32 row;
- if (cm == NULL)
- return NULL;
- if (wc_LockMutex(&cm->caLock) != 0)
- return ret;
- for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
- signers = cm->caTable[row];
- while (signers && ret == NULL) {
- if (XMEMCMP(hash, signers->subjectNameHash,
- SIGNER_DIGEST_SIZE) == 0) {
- ret = signers;
- }
- signers = signers->next;
- }
- }
- wc_UnLockMutex(&cm->caLock);
- return ret;
- }
- #endif
- #ifdef WOLFSSL_TRUST_PEER_CERT
- /* add a trusted peer cert to linked list */
- int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
- {
- int ret, row;
- TrustedPeerCert* peerCert;
- DecodedCert* cert;
- DerBuffer* der = *pDer;
- WOLFSSL_MSG("Adding a Trusted Peer Cert");
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL) {
- FreeDer(&der);
- return MEMORY_E;
- }
- InitDecodedCert(cert, der->buffer, der->length, cm->heap);
- if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
- FreeDecodedCert(cert);
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
- FreeDer(&der);
- return ret;
- }
- WOLFSSL_MSG("\tParsed new trusted peer cert");
- peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
- DYNAMIC_TYPE_CERT);
- if (peerCert == NULL) {
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- FreeDer(&der);
- return MEMORY_E;
- }
- XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
- #ifndef IGNORE_NAME_CONSTRAINTS
- if (peerCert->permittedNames)
- FreeNameSubtrees(peerCert->permittedNames, cm->heap);
- if (peerCert->excludedNames)
- FreeNameSubtrees(peerCert->excludedNames, cm->heap);
- #endif
- if (AlreadyTrustedPeer(cm, cert)) {
- WOLFSSL_MSG("\tAlready have this CA, not adding again");
- FreeTrustedPeer(peerCert, cm->heap);
- (void)ret;
- }
- else {
- /* add trusted peer signature */
- peerCert->sigLen = cert->sigLength;
- peerCert->sig = (byte *)XMALLOC(cert->sigLength, cm->heap,
- DYNAMIC_TYPE_SIGNATURE);
- if (peerCert->sig == NULL) {
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- FreeTrustedPeer(peerCert, cm->heap);
- FreeDer(&der);
- return MEMORY_E;
- }
- XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
- /* add trusted peer name */
- peerCert->nameLen = cert->subjectCNLen;
- peerCert->name = cert->subjectCN;
- #ifndef IGNORE_NAME_CONSTRAINTS
- peerCert->permittedNames = cert->permittedNames;
- peerCert->excludedNames = cert->excludedNames;
- #endif
- /* add SKID when available and hash of name */
- #ifndef NO_SKID
- XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
- SIGNER_DIGEST_SIZE);
- #endif
- XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
- SIGNER_DIGEST_SIZE);
- peerCert->next = NULL; /* If Key Usage not set, all uses valid. */
- cert->subjectCN = 0;
- #ifndef IGNORE_NAME_CONSTRAINTS
- cert->permittedNames = NULL;
- cert->excludedNames = NULL;
- #endif
- row = TrustedPeerHashSigner(peerCert->subjectNameHash);
- if (wc_LockMutex(&cm->tpLock) == 0) {
- peerCert->next = cm->tpTable[row];
- cm->tpTable[row] = peerCert; /* takes ownership */
- wc_UnLockMutex(&cm->tpLock);
- }
- else {
- WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- FreeTrustedPeer(peerCert, cm->heap);
- FreeDer(&der);
- return BAD_MUTEX_E;
- }
- }
- WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- WOLFSSL_MSG("\tFreeing der trusted peer cert");
- FreeDer(&der);
- WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
- WOLFSSL_LEAVE("AddTrustedPeer", ret);
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- /* owns der, internal now uses too */
- /* type flag ids from user or from chain received during verify
- don't allow chain ones to be added w/o isCA extension */
- int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
- {
- int ret;
- Signer* signer = NULL;
- word32 row;
- byte* subjectHash;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
- DerBuffer* der = *pDer;
- WOLFSSL_MSG("Adding a CA");
- if (cm == NULL) {
- FreeDer(pDer);
- return BAD_FUNC_ARG;
- }
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL) {
- FreeDer(pDer);
- return MEMORY_E;
- }
- #endif
- InitDecodedCert(cert, der->buffer, der->length, cm->heap);
- ret = ParseCert(cert, CA_TYPE, verify, cm);
- WOLFSSL_MSG("\tParsed new CA");
- #ifndef NO_SKID
- subjectHash = cert->extSubjKeyId;
- #else
- subjectHash = cert->subjectHash;
- #endif
- /* check CA key size */
- if (verify) {
- switch (cert->keyOID) {
- #ifndef NO_RSA
- #ifdef WC_RSA_PSS
- case RSAPSSk:
- #endif
- case RSAk:
- if (cm->minRsaKeySz < 0 ||
- cert->pubKeySize < (word16)cm->minRsaKeySz) {
- ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA RSA key size error");
- }
- break;
- #endif /* !NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- if (cm->minEccKeySz < 0 ||
- cert->pubKeySize < (word16)cm->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA ECC key size error");
- }
- break;
- #endif /* HAVE_ECC */
- #ifdef HAVE_ED25519
- case ED25519k:
- if (cm->minEccKeySz < 0 ||
- ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA ECC key size error");
- }
- break;
- #endif /* HAVE_ED25519 */
- #ifdef HAVE_ED448
- case ED448k:
- if (cm->minEccKeySz < 0 ||
- ED448_KEY_SIZE < (word16)cm->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA ECC key size error");
- }
- break;
- #endif /* HAVE_ED448 */
- #if defined(HAVE_PQC)
- #if defined(HAVE_FALCON)
- case FALCON_LEVEL1k:
- if (cm->minFalconKeySz < 0 ||
- FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Falcon level 1 key size error");
- }
- break;
- case FALCON_LEVEL5k:
- if (cm->minFalconKeySz < 0 ||
- FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Falcon level 5 key size error");
- }
- break;
- #endif /* HAVE_FALCON */
- #if defined(HAVE_DILITHIUM)
- case DILITHIUM_LEVEL2k:
- case DILITHIUM_AES_LEVEL2k:
- if (cm->minDilithiumKeySz < 0 ||
- DILITHIUM_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
- }
- break;
- case DILITHIUM_LEVEL3k:
- case DILITHIUM_AES_LEVEL3k:
- if (cm->minDilithiumKeySz < 0 ||
- DILITHIUM_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
- }
- break;
- case DILITHIUM_LEVEL5k:
- case DILITHIUM_AES_LEVEL5k:
- if (cm->minDilithiumKeySz < 0 ||
- DILITHIUM_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
- }
- break;
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- default:
- WOLFSSL_MSG("\tNo key size check done on CA");
- break; /* no size check if key type is not in switch */
- }
- }
- if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) {
- WOLFSSL_MSG("\tCan't add as CA if not actually one");
- ret = NOT_CA_ERROR;
- }
- #ifndef ALLOW_INVALID_CERTSIGN
- else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
- !cert->selfSigned && (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
- /* Intermediate CA certs are required to have the keyCertSign
- * extension set. User loaded root certs are not. */
- WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
- ret = NOT_CA_ERROR;
- }
- #endif
- else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
- WOLFSSL_MSG("\tAlready have this CA, not adding again");
- (void)ret;
- }
- else if (ret == 0) {
- /* take over signer parts */
- signer = MakeSigner(cm->heap);
- if (!signer)
- ret = MEMORY_ERROR;
- }
- if (ret == 0 && signer != NULL) {
- #ifdef WOLFSSL_SIGNER_DER_CERT
- ret = AllocDer(&signer->derCert, der->length, der->type, NULL);
- }
- if (ret == 0 && signer != NULL) {
- XMEMCPY(signer->derCert->buffer, der->buffer, der->length);
- #endif
- signer->keyOID = cert->keyOID;
- if (cert->pubKeyStored) {
- signer->publicKey = cert->publicKey;
- signer->pubKeySize = cert->pubKeySize;
- }
- if (cert->subjectCNStored) {
- signer->nameLen = cert->subjectCNLen;
- signer->name = cert->subjectCN;
- }
- signer->pathLength = cert->pathLength;
- signer->maxPathLen = cert->maxPathLen;
- signer->pathLengthSet = cert->pathLengthSet;
- signer->selfSigned = cert->selfSigned;
- #ifndef IGNORE_NAME_CONSTRAINTS
- signer->permittedNames = cert->permittedNames;
- signer->excludedNames = cert->excludedNames;
- #endif
- #ifndef NO_SKID
- XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
- SIGNER_DIGEST_SIZE);
- #endif
- XMEMCPY(signer->subjectNameHash, cert->subjectHash,
- SIGNER_DIGEST_SIZE);
- #ifdef HAVE_OCSP
- XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash,
- KEYID_SIZE);
- #endif
- signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
- : 0xFFFF;
- signer->next = NULL; /* If Key Usage not set, all uses valid. */
- cert->publicKey = 0; /* in case lock fails don't free here. */
- cert->subjectCN = 0;
- #ifndef IGNORE_NAME_CONSTRAINTS
- cert->permittedNames = NULL;
- cert->excludedNames = NULL;
- #endif
- #ifndef NO_SKID
- row = HashSigner(signer->subjectKeyIdHash);
- #else
- row = HashSigner(signer->subjectNameHash);
- #endif
- if (wc_LockMutex(&cm->caLock) == 0) {
- signer->next = cm->caTable[row];
- cm->caTable[row] = signer; /* takes ownership */
- wc_UnLockMutex(&cm->caLock);
- if (cm->caCacheCallback)
- cm->caCacheCallback(der->buffer, (int)der->length, type);
- }
- else {
- WOLFSSL_MSG("\tCA Mutex Lock failed");
- ret = BAD_MUTEX_E;
- FreeSigner(signer, cm->heap);
- }
- }
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_SCEPROTECT)
- /* Verify CA by TSIP so that generated tsip key is going to be able to */
- /* be used for peer's cert verification */
- /* TSIP is only able to handle USER CA, and only one CA. */
- /* Therefore, it doesn't need to call TSIP again if there is already */
- /* verified CA. */
- if ( ret == 0 && signer != NULL ) {
- signer->cm_idx = row;
- if (type == WOLFSSL_USER_CA) {
- if ((ret = wc_Renesas_cmn_RootCertVerify(cert->source, cert->maxIdx,
- cert->sigCtx.CertAtt.pubkey_n_start,
- cert->sigCtx.CertAtt.pubkey_n_len - 1,
- cert->sigCtx.CertAtt.pubkey_e_start,
- cert->sigCtx.CertAtt.pubkey_e_len - 1,
- row/* cm index */))
- < 0)
- WOLFSSL_MSG("Renesas_RootCertVerify() failed");
- else
- WOLFSSL_MSG("Renesas_RootCertVerify() succeed or skipped");
- }
- }
- #endif /* TSIP or SCE */
- WOLFSSL_MSG("\tFreeing Parsed CA");
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
- #endif
- WOLFSSL_MSG("\tFreeing der CA");
- FreeDer(pDer);
- WOLFSSL_MSG("\t\tOK Freeing der CA");
- WOLFSSL_LEAVE("AddCA", ret);
- return ret == 0 ? WOLFSSL_SUCCESS : ret;
- }
- #endif /* !NO_CERTS */
- #ifndef NO_SESSION_CACHE
- /* basic config gives a cache with 33 sessions, adequate for clients and
- embedded servers
- TITAN_SESSION_CACHE allows just over 2 million sessions, for servers
- with titanic amounts of memory with long session ID timeouts and high
- levels of traffic.
- ENABLE_SESSION_CACHE_ROW_LOCK: Allows row level locking for increased
- performance with large session caches
- HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
- allows over 13,000 new sessions per minute or over 200 new sessions per
- second
- BIG_SESSION_CACHE yields 20,027 sessions
- MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
- aren't under heavy load, basically allows 200 new sessions per minute
- SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients
- or systems where the default of nearly 3kB is too much RAM, this define
- uses less than 500 bytes RAM
- default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined)
- */
- #if defined(TITAN_SESSION_CACHE)
- #define SESSIONS_PER_ROW 31
- #define SESSION_ROWS 64937
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- #define ENABLE_SESSION_CACHE_ROW_LOCK
- #endif
- #elif defined(HUGE_SESSION_CACHE)
- #define SESSIONS_PER_ROW 11
- #define SESSION_ROWS 5981
- #elif defined(BIG_SESSION_CACHE)
- #define SESSIONS_PER_ROW 7
- #define SESSION_ROWS 2861
- #elif defined(MEDIUM_SESSION_CACHE)
- #define SESSIONS_PER_ROW 5
- #define SESSION_ROWS 211
- #elif defined(SMALL_SESSION_CACHE)
- #define SESSIONS_PER_ROW 2
- #define SESSION_ROWS 3
- #else
- #define SESSIONS_PER_ROW 3
- #define SESSION_ROWS 11
- #endif
- #define INVALID_SESSION_ROW (-1)
- #ifdef NO_SESSION_CACHE_ROW_LOCK
- #undef ENABLE_SESSION_CACHE_ROW_LOCK
- #endif
- typedef struct SessionRow {
- int nextIdx; /* where to place next one */
- int totalCount; /* sessions ever on this row */
- WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- /* not included in import/export */
- wolfSSL_Mutex row_mutex;
- int mutex_valid;
- #endif
- } SessionRow;
- #define SIZEOF_SESSION_ROW (sizeof(WOLFSSL_SESSION) + (sizeof(int) * 2))
- static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS];
- #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
- static WOLFSSL_GLOBAL word32 PeakSessions;
- #endif
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- #define SESSION_ROW_LOCK(row) wc_LockMutex(&(row)->row_mutex)
- #define SESSION_ROW_UNLOCK(row) wc_UnLockMutex(&(row)->row_mutex);
- #else
- static WOLFSSL_GLOBAL wolfSSL_Mutex session_mutex; /* SessionCache mutex */
- static WOLFSSL_GLOBAL int session_mutex_valid = 0;
- #define SESSION_ROW_LOCK(row) wc_LockMutex(&session_mutex)
- #define SESSION_ROW_UNLOCK(row) wc_UnLockMutex(&session_mutex);
- #endif
- #if !defined(NO_SESSION_CACHE_REF) && defined(NO_CLIENT_CACHE)
- #error ClientCache is required when not using NO_SESSION_CACHE_REF
- #endif
- #ifndef NO_CLIENT_CACHE
- #ifndef CLIENT_SESSIONS_MULTIPLIER
- #ifdef NO_SESSION_CACHE_REF
- #define CLIENT_SESSIONS_MULTIPLIER 1
- #else
- /* ClientSession objects are lightweight (compared to
- * WOLFSSL_SESSION) so to decrease chance that user will reuse
- * thse wrong session, increase the ClientCache size. This will
- * make the entire ClientCache about the size of one
- * WOLFSSL_SESSION object. */
- #define CLIENT_SESSIONS_MULTIPLIER 8
- #endif
- #endif
- #define CLIENT_SESSIONS_PER_ROW \
- (SESSIONS_PER_ROW * CLIENT_SESSIONS_MULTIPLIER)
- #define CLIENT_SESSION_ROWS (SESSION_ROWS * CLIENT_SESSIONS_MULTIPLIER)
- #if CLIENT_SESSIONS_PER_ROW > 65535
- #error CLIENT_SESSIONS_PER_ROW too big
- #endif
- #if CLIENT_SESSION_ROWS > 65535
- #error CLIENT_SESSION_ROWS too big
- #endif
- struct ClientSession {
- word16 serverRow; /* SessionCache Row id */
- word16 serverIdx; /* SessionCache Idx (column) */
- word32 sessionIDHash;
- };
- #ifndef WOLFSSL_CLIENT_SESSION_DEFINED
- typedef struct ClientSession ClientSession;
- #define WOLFSSL_CLIENT_SESSION_DEFINED
- #endif
- typedef struct ClientRow {
- int nextIdx; /* where to place next one */
- int totalCount; /* sessions ever on this row */
- ClientSession Clients[CLIENT_SESSIONS_PER_ROW];
- } ClientRow;
- static WOLFSSL_GLOBAL ClientRow ClientCache[CLIENT_SESSION_ROWS];
- /* Client Cache */
- /* uses session mutex */
- static WOLFSSL_GLOBAL wolfSSL_Mutex clisession_mutex; /* ClientCache mutex */
- static WOLFSSL_GLOBAL int clisession_mutex_valid = 0;
- #endif /* !NO_CLIENT_CACHE */
- #endif /* !NO_SESSION_CACHE */
- #if !defined(WC_NO_RNG) && (defined(OPENSSL_EXTRA) || \
- (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)))
- #define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */
- static WC_RNG globalRNG;
- static int initGlobalRNG = 0;
- static wolfSSL_Mutex globalRNGMutex;
- static int globalRNGMutex_valid = 0;
- #if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
- static WOLFSSL_DRBG_CTX* gDrbgDefCtx = NULL;
- #endif
- WC_RNG* wolfssl_get_global_rng(void)
- {
- WC_RNG* ret = NULL;
- if (initGlobalRNG == 0)
- WOLFSSL_MSG("Global RNG no Init");
- else
- ret = &globalRNG;
- return ret;
- }
- #endif
- #if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB)
- static int wolfSSL_RAND_InitMutex(void);
- #endif
- #if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT)
- static void AtExitCleanup(void)
- {
- if (initRefCount > 0) {
- initRefCount = 1;
- (void)wolfSSL_Cleanup();
- }
- }
- #endif
- WOLFSSL_ABI
- int wolfSSL_Init(void)
- {
- int ret = WOLFSSL_SUCCESS;
- #if !defined(NO_SESSION_CACHE) && defined(ENABLE_SESSION_CACHE_ROW_LOCK)
- int i;
- #endif
- WOLFSSL_ENTER("wolfSSL_Init");
- #if FIPS_VERSION_GE(5,1)
- ret = wolfCrypt_SetPrivateKeyReadEnable_fips(1, WC_KEYTYPE_ALL);
- if (ret != 0)
- return ret;
- else
- ret = WOLFSSL_SUCCESS;
- #endif
- if (initRefCount == 0) {
- /* Initialize crypto for use with TLS connection */
- if (wolfCrypt_Init() != 0) {
- WOLFSSL_MSG("Bad wolfCrypt Init");
- ret = WC_INIT_E;
- }
- #ifdef HAVE_GLOBAL_RNG
- if (ret == WOLFSSL_SUCCESS) {
- if (wc_InitMutex(&globalRNGMutex) != 0) {
- WOLFSSL_MSG("Bad Init Mutex rng");
- ret = BAD_MUTEX_E;
- }
- else {
- globalRNGMutex_valid = 1;
- }
- }
- #endif
- #ifdef WC_RNG_SEED_CB
- wc_SetSeed_Cb(wc_GenerateSeed);
- #endif
- #ifdef OPENSSL_EXTRA
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if ((ret == WOLFSSL_SUCCESS) && (wolfSSL_RAND_InitMutex() != 0)) {
- ret = BAD_MUTEX_E;
- }
- #endif
- if ((ret == WOLFSSL_SUCCESS) &&
- (wolfSSL_RAND_seed(NULL, 0) != WOLFSSL_SUCCESS)) {
- WOLFSSL_MSG("wolfSSL_RAND_Seed failed");
- ret = WC_INIT_E;
- }
- #endif
- #ifndef NO_SESSION_CACHE
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- for (i = 0; i < SESSION_ROWS; ++i) {
- SessionCache[i].mutex_valid = 0;
- }
- for (i = 0; (ret == WOLFSSL_SUCCESS) && (i < SESSION_ROWS); ++i) {
- if (wc_InitMutex(&SessionCache[i].row_mutex) != 0) {
- WOLFSSL_MSG("Bad Init Mutex session");
- ret = BAD_MUTEX_E;
- }
- else {
- SessionCache[i].mutex_valid = 1;
- }
- }
- #else
- if (ret == WOLFSSL_SUCCESS) {
- if (wc_InitMutex(&session_mutex) != 0) {
- WOLFSSL_MSG("Bad Init Mutex session");
- ret = BAD_MUTEX_E;
- }
- else {
- session_mutex_valid = 1;
- }
- }
- #endif
- #ifndef NO_CLIENT_CACHE
- if (ret == WOLFSSL_SUCCESS) {
- if (wc_InitMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Bad Init Mutex session");
- ret = BAD_MUTEX_E;
- }
- else {
- clisession_mutex_valid = 1;
- }
- }
- #endif
- #endif
- if (ret == WOLFSSL_SUCCESS) {
- if (wc_InitMutex(&count_mutex) != 0) {
- WOLFSSL_MSG("Bad Init Mutex count");
- ret = BAD_MUTEX_E;
- }
- else {
- count_mutex_valid = 1;
- }
- }
- #if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT)
- /* OpenSSL registers cleanup using atexit */
- if ((ret == WOLFSSL_SUCCESS) && (atexit(AtExitCleanup) != 0)) {
- WOLFSSL_MSG("Bad atexit registration");
- ret = WC_INIT_E;
- }
- #endif
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (wc_LockMutex(&count_mutex) != 0) {
- WOLFSSL_MSG("Bad Lock Mutex count");
- ret = BAD_MUTEX_E;
- }
- else {
- initRefCount++;
- wc_UnLockMutex(&count_mutex);
- }
- }
- if (ret != WOLFSSL_SUCCESS) {
- initRefCount = 1; /* Force cleanup */
- (void)wolfSSL_Cleanup(); /* Ignore any error from cleanup */
- }
- return ret;
- }
- #ifndef NO_CERTS
- /* process user cert chain to pass during the handshake */
- static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
- long sz, int format, int type, WOLFSSL* ssl,
- long* used, EncryptedInfo* info, int verify)
- {
- int ret = 0;
- void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
- #ifdef WOLFSSL_TLS13
- int cnt = 0;
- #endif
- if ((type == CA_TYPE) && (ctx == NULL)) {
- WOLFSSL_MSG("Need context for CA load");
- return BAD_FUNC_ARG;
- }
- /* we may have a user cert chain, try to consume */
- if ((type == CERT_TYPE || type == CA_TYPE) && (info->consumed < sz)) {
- #ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
- #else
- byte staticBuffer[FILE_BUFFER_SIZE]; /* tmp chain buffer */
- #endif
- byte* chainBuffer = staticBuffer;
- int dynamicBuffer = 0;
- word32 bufferSz;
- long consumed = info->consumed;
- word32 idx = 0;
- int gotOne = 0;
- /* Calculate max possible size, including max headers */
- bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH);
- if (bufferSz > sizeof(staticBuffer)) {
- WOLFSSL_MSG("Growing Tmp Chain Buffer");
- /* will shrink to actual size */
- chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE);
- if (chainBuffer == NULL) {
- return MEMORY_E;
- }
- dynamicBuffer = 1;
- }
- WOLFSSL_MSG("Processing Cert Chain");
- while (consumed < sz) {
- DerBuffer* part = NULL;
- word32 remain = (word32)(sz - consumed);
- info->consumed = 0;
- if (format == WOLFSSL_FILETYPE_PEM) {
- #ifdef WOLFSSL_PEM_TO_DER
- ret = PemToDer(buff + consumed, remain, type, &part,
- heap, info, NULL);
- #else
- ret = NOT_COMPILED_IN;
- #endif
- }
- else {
- int length = remain;
- if (format == WOLFSSL_FILETYPE_ASN1) {
- /* get length of der (read sequence) */
- word32 inOutIdx = 0;
- if (GetSequence(buff + consumed, &inOutIdx, &length,
- remain) < 0) {
- ret = ASN_NO_PEM_HEADER;
- }
- length += inOutIdx; /* include leading sequence */
- }
- info->consumed = length;
- if (ret == 0) {
- ret = AllocDer(&part, length, type, heap);
- if (ret == 0) {
- XMEMCPY(part->buffer, buff + consumed, length);
- }
- }
- }
- if (ret == 0) {
- gotOne = 1;
- #ifdef WOLFSSL_TLS13
- cnt++;
- #endif
- if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) {
- WOLFSSL_MSG(" Cert Chain bigger than buffer. "
- "Consider increasing MAX_CHAIN_DEPTH");
- ret = BUFFER_E;
- }
- else {
- c32to24(part->length, &chainBuffer[idx]);
- idx += CERT_HEADER_SZ;
- XMEMCPY(&chainBuffer[idx], part->buffer, part->length);
- idx += part->length;
- consumed += info->consumed;
- if (used)
- *used += info->consumed;
- }
- /* add CA's to certificate manager */
- if (ret == 0 && type == CA_TYPE) {
- /* verify CA unless user set to no verify */
- ret = AddCA(ctx->cm, &part, WOLFSSL_USER_CA, verify);
- if (ret == WOLFSSL_SUCCESS) {
- ret = 0; /* converted success case */
- }
- gotOne = 0; /* don't exit loop for CA type */
- }
- }
- FreeDer(&part);
- if (ret == ASN_NO_PEM_HEADER && gotOne) {
- WOLFSSL_MSG("We got one good cert, so stuff at end ok");
- break;
- }
- if (ret < 0) {
- WOLFSSL_MSG(" Error in Cert in Chain");
- if (dynamicBuffer)
- XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
- return ret;
- }
- WOLFSSL_MSG(" Consumed another Cert in Chain");
- }
- WOLFSSL_MSG("Finished Processing Cert Chain");
- /* only retain actual size used */
- ret = 0;
- if (idx > 0) {
- if (ssl) {
- if (ssl->buffers.weOwnCertChain) {
- FreeDer(&ssl->buffers.certChain);
- }
- ret = AllocDer(&ssl->buffers.certChain, idx, type, heap);
- if (ret == 0) {
- XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer,
- idx);
- ssl->buffers.weOwnCertChain = 1;
- }
- #ifdef WOLFSSL_TLS13
- ssl->buffers.certChainCnt = cnt;
- #endif
- } else if (ctx) {
- FreeDer(&ctx->certChain);
- ret = AllocDer(&ctx->certChain, idx, type, heap);
- if (ret == 0) {
- XMEMCPY(ctx->certChain->buffer, chainBuffer, idx);
- }
- #ifdef WOLFSSL_TLS13
- ctx->certChainCnt = cnt;
- #endif
- }
- }
- if (dynamicBuffer)
- XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
- }
- return ret;
- }
- static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der,
- int* keySz, word32* idx, int* resetSuites, int* keyFormat, void* heap, int devId)
- {
- int ret = 0;
- (void)heap;
- (void)devId;
- if (ctx == NULL && ssl == NULL)
- return BAD_FUNC_ARG;
- if (!der || !keySz || !idx || !resetSuites || !keyFormat)
- return BAD_FUNC_ARG;
- #ifndef NO_RSA
- if ((*keyFormat == 0 || *keyFormat == RSAk)) {
- /* make sure RSA key can be used */
- #ifdef WOLFSSL_SMALL_STACK
- RsaKey* key;
- #else
- RsaKey key[1];
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
- if (key == NULL)
- return MEMORY_E;
- #endif
- ret = wc_InitRsaKey_ex(key, heap, devId);
- if (ret == 0) {
- *idx = 0;
- ret = wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length);
- #ifdef WOLF_PRIVATE_KEY_ID
- if (ret != 0 && (devId != INVALID_DEVID
- #ifdef HAVE_PK_CALLBACKS
- || wolfSSL_CTX_IsPrivatePkSet(ctx)
- #endif
- )) {
- /* if using crypto or PK callbacks, try public key decode */
- *idx = 0;
- ret = wc_RsaPublicKeyDecode(der->buffer, idx, key, der->length);
- }
- #endif
- if (ret != 0) {
- #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
- !defined(HAVE_ED448) && !defined(HAVE_PQC)
- WOLFSSL_MSG("RSA decode failed and other algorithms "
- "not enabled to try");
- ret = WOLFSSL_BAD_FILE;
- #else
- ret = 0; /* continue trying other algorithms */
- #endif
- }
- else {
- /* check that the size of the RSA key is enough */
- int minRsaSz = ssl ? ssl->options.minRsaKeySz :
- ctx->minRsaKeySz;
- *keySz = wc_RsaEncryptSize((RsaKey*)key);
- if (*keySz < minRsaSz) {
- ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG("Private Key size too small");
- }
- if (ssl) {
- ssl->buffers.keyType = rsa_sa_algo;
- ssl->buffers.keySz = *keySz;
- }
- else {
- ctx->privateKeyType = rsa_sa_algo;
- ctx->privateKeySz = *keySz;
- }
- *keyFormat = RSAk;
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- ssl->options.haveStaticECC = 0;
- *resetSuites = 1;
- }
- }
- wc_FreeRsaKey(key);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_RSA);
- #endif
- if (ret != 0)
- return ret;
- }
- #endif
- #ifdef HAVE_ECC
- if ((*keyFormat == 0 || *keyFormat == ECDSAk)) {
- /* make sure ECC key can be used */
- #ifdef WOLFSSL_SMALL_STACK
- ecc_key* key;
- #else
- ecc_key key[1];
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
- if (key == NULL)
- return MEMORY_E;
- #endif
- if (wc_ecc_init_ex(key, heap, devId) == 0) {
- *idx = 0;
- ret = wc_EccPrivateKeyDecode(der->buffer, idx, key, der->length);
- #ifdef WOLF_PRIVATE_KEY_ID
- if (ret != 0 && (devId != INVALID_DEVID
- #ifdef HAVE_PK_CALLBACKS
- || wolfSSL_CTX_IsPrivatePkSet(ctx)
- #endif
- )) {
- /* if using crypto or PK callbacks, try public key decode */
- *idx = 0;
- ret = wc_EccPublicKeyDecode(der->buffer, idx, key, der->length);
- }
- #endif
- if (ret == 0) {
- /* check for minimum ECC key size and then free */
- int minKeySz = ssl ? ssl->options.minEccKeySz :
- ctx->minEccKeySz;
- *keySz = wc_ecc_size(key);
- if (*keySz < minKeySz) {
- WOLFSSL_MSG("ECC private key too small");
- ret = ECC_KEY_SIZE_E;
- }
- *keyFormat = ECDSAk;
- if (ssl) {
- ssl->options.haveStaticECC = 1;
- ssl->buffers.keyType = ecc_dsa_sa_algo;
- ssl->buffers.keySz = *keySz;
- }
- else {
- ctx->haveStaticECC = 1;
- ctx->privateKeyType = ecc_dsa_sa_algo;
- ctx->privateKeySz = *keySz;
- }
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- else {
- ret = 0; /* continue trying other algorithms */
- }
- wc_ecc_free(key);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_ECC);
- #endif
- if (ret != 0)
- return ret;
- }
- #endif /* HAVE_ECC */
- #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)
- if ((*keyFormat == 0 || *keyFormat == ED25519k)) {
- /* make sure Ed25519 key can be used */
- #ifdef WOLFSSL_SMALL_STACK
- ed25519_key* key;
- #else
- ed25519_key key[1];
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
- DYNAMIC_TYPE_ED25519);
- if (key == NULL)
- return MEMORY_E;
- #endif
- ret = wc_ed25519_init_ex(key, heap, devId);
- if (ret == 0) {
- *idx = 0;
- ret = wc_Ed25519PrivateKeyDecode(der->buffer, idx, key, der->length);
- #ifdef WOLF_PRIVATE_KEY_ID
- if (ret != 0 && (devId != INVALID_DEVID
- #ifdef HAVE_PK_CALLBACKS
- || wolfSSL_CTX_IsPrivatePkSet(ctx)
- #endif
- )) {
- /* if using crypto or PK callbacks, try public key decode */
- *idx = 0;
- ret = wc_Ed25519PublicKeyDecode(der->buffer, idx, key,
- der->length);
- }
- #endif
- if (ret == 0) {
- /* check for minimum key size and then free */
- int minKeySz = ssl ? ssl->options.minEccKeySz :
- ctx->minEccKeySz;
- *keySz = ED25519_KEY_SIZE;
- if (*keySz < minKeySz) {
- WOLFSSL_MSG("ED25519 private key too small");
- ret = ECC_KEY_SIZE_E;
- }
- if (ret == 0) {
- if (ssl) {
- ssl->buffers.keyType = ed25519_sa_algo;
- ssl->buffers.keySz = *keySz;
- }
- else if (ctx) {
- ctx->privateKeyType = ed25519_sa_algo;
- ctx->privateKeySz = *keySz;
- }
- *keyFormat = ED25519k;
- if (ssl != NULL) {
- /* ED25519 requires caching enabled for tracking message
- * hash used in EdDSA_Update for signing */
- ssl->options.cacheMessages = 1;
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- }
- }
- else {
- ret = 0; /* continue trying other algorithms */
- }
- wc_ed25519_free(key);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_ED25519);
- #endif
- if (ret != 0)
- return ret;
- }
- #endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */
- #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
- if ((*keyFormat == 0 || *keyFormat == ED448k)) {
- /* make sure Ed448 key can be used */
- #ifdef WOLFSSL_SMALL_STACK
- ed448_key* key = NULL;
- #else
- ed448_key key[1];
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448);
- if (key == NULL)
- return MEMORY_E;
- #endif
- ret = wc_ed448_init(key);
- if (ret == 0) {
- *idx = 0;
- ret = wc_Ed448PrivateKeyDecode(der->buffer, idx, key, der->length);
- #ifdef WOLF_PRIVATE_KEY_ID
- if (ret != 0 && (devId != INVALID_DEVID
- #ifdef HAVE_PK_CALLBACKS
- || wolfSSL_CTX_IsPrivatePkSet(ctx)
- #endif
- )) {
- /* if using crypto or PK callbacks, try public key decode */
- *idx = 0;
- ret = wc_Ed448PublicKeyDecode(der->buffer, idx, key,
- der->length);
- }
- #endif
- if (ret == 0) {
- /* check for minimum key size and then free */
- int minKeySz = ssl ? ssl->options.minEccKeySz :
- ctx->minEccKeySz;
- *keySz = ED448_KEY_SIZE;
- if (*keySz < minKeySz) {
- WOLFSSL_MSG("ED448 private key too small");
- ret = ECC_KEY_SIZE_E;
- }
- }
- if (ret == 0) {
- if (ssl) {
- ssl->buffers.keyType = ed448_sa_algo;
- ssl->buffers.keySz = *keySz;
- }
- else if (ctx) {
- ctx->privateKeyType = ed448_sa_algo;
- ctx->privateKeySz = *keySz;
- }
- *keyFormat = ED448k;
- if (ssl != NULL) {
- /* ED448 requires caching enabled for tracking message
- * hash used in EdDSA_Update for signing */
- ssl->options.cacheMessages = 1;
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- }
- wc_ed448_free(key);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_ED448);
- #endif
- if (ret != 0)
- return ret;
- }
- #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */
- #if defined(HAVE_PQC)
- #if defined(HAVE_FALCON)
- if (((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) ||
- (*keyFormat == FALCON_LEVEL5k))) {
- /* make sure Falcon key can be used */
- falcon_key* key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap,
- DYNAMIC_TYPE_FALCON);
- if (key == NULL) {
- return MEMORY_E;
- }
- ret = wc_falcon_init(key);
- if (ret == 0) {
- if (*keyFormat == FALCON_LEVEL1k) {
- ret = wc_falcon_set_level(key, 1);
- }
- else if (*keyFormat == FALCON_LEVEL5k) {
- ret = wc_falcon_set_level(key, 5);
- }
- else {
- /* What if *keyformat is 0? We might want to do something more
- * graceful here. */
- wc_falcon_free(key);
- ret = ALGO_ID_E;
- }
- }
- if (ret == 0) {
- *idx = 0;
- ret = wc_falcon_import_private_only(der->buffer, der->length, key);
- if (ret == 0) {
- /* check for minimum key size and then free */
- int minKeySz = ssl ? ssl->options.minFalconKeySz :
- ctx->minFalconKeySz;
- *keySz = FALCON_MAX_KEY_SIZE;
- if (*keySz < minKeySz) {
- WOLFSSL_MSG("Falcon private key too small");
- ret = FALCON_KEY_SIZE_E;
- }
- if (ssl) {
- if (*keyFormat == FALCON_LEVEL1k) {
- ssl->buffers.keyType = falcon_level1_sa_algo;
- }
- else {
- ssl->buffers.keyType = falcon_level5_sa_algo;
- }
- ssl->buffers.keySz = *keySz;
- }
- else {
- if (*keyFormat == FALCON_LEVEL1k) {
- ctx->privateKeyType = falcon_level1_sa_algo;
- }
- else {
- ctx->privateKeyType = falcon_level5_sa_algo;
- }
- ctx->privateKeySz = *keySz;
- }
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- wc_falcon_free(key);
- }
- XFREE(key, heap, DYNAMIC_TYPE_FALCON);
- if (ret != 0)
- return ret;
- }
- #endif /* HAVE_FALCON */
- #if defined(HAVE_DILITHIUM)
- if ((*keyFormat == 0) ||
- (*keyFormat == DILITHIUM_LEVEL2k) ||
- (*keyFormat == DILITHIUM_LEVEL3k) ||
- (*keyFormat == DILITHIUM_LEVEL5k) ||
- (*keyFormat == DILITHIUM_AES_LEVEL2k) ||
- (*keyFormat == DILITHIUM_AES_LEVEL3k) ||
- (*keyFormat == DILITHIUM_AES_LEVEL5k)) {
- /* make sure Dilithium key can be used */
- dilithium_key* key = (dilithium_key*)XMALLOC(sizeof(dilithium_key),
- heap,
- DYNAMIC_TYPE_DILITHIUM);
- if (key == NULL) {
- return MEMORY_E;
- }
- ret = wc_dilithium_init(key);
- if (ret == 0) {
- if (*keyFormat == DILITHIUM_LEVEL2k) {
- ret = wc_dilithium_set_level_and_sym(key, 2, SHAKE_VARIANT);
- }
- else if (*keyFormat == DILITHIUM_LEVEL3k) {
- ret = wc_dilithium_set_level_and_sym(key, 3, SHAKE_VARIANT);
- }
- else if (*keyFormat == DILITHIUM_LEVEL5k) {
- ret = wc_dilithium_set_level_and_sym(key, 5, SHAKE_VARIANT);
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL2k) {
- ret = wc_dilithium_set_level_and_sym(key, 2, AES_VARIANT);
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL3k) {
- ret = wc_dilithium_set_level_and_sym(key, 3, AES_VARIANT);
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL5k) {
- ret = wc_dilithium_set_level_and_sym(key, 5, AES_VARIANT);
- }
- else {
- /* What if *keyformat is 0? We might want to do something more
- * graceful here. */
- wc_dilithium_free(key);
- ret = ALGO_ID_E;
- }
- }
- if (ret == 0) {
- *idx = 0;
- ret = wc_dilithium_import_private_only(der->buffer, der->length,
- key);
- if (ret == 0) {
- /* check for minimum key size and then free */
- int minKeySz = ssl ? ssl->options.minDilithiumKeySz :
- ctx->minDilithiumKeySz;
- *keySz = DILITHIUM_MAX_KEY_SIZE;
- if (*keySz < minKeySz) {
- WOLFSSL_MSG("Dilithium private key too small");
- ret = DILITHIUM_KEY_SIZE_E;
- }
- if (ssl) {
- if (*keyFormat == DILITHIUM_LEVEL2k) {
- ssl->buffers.keyType = dilithium_level2_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_LEVEL3k) {
- ssl->buffers.keyType = dilithium_level3_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_LEVEL5k) {
- ssl->buffers.keyType = dilithium_level5_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL2k) {
- ssl->buffers.keyType = dilithium_aes_level2_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL3k) {
- ssl->buffers.keyType = dilithium_aes_level3_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL5k) {
- ssl->buffers.keyType = dilithium_aes_level5_sa_algo;
- }
- ssl->buffers.keySz = *keySz;
- }
- else {
- if (*keyFormat == DILITHIUM_LEVEL2k) {
- ctx->privateKeyType = dilithium_level2_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_LEVEL3k) {
- ctx->privateKeyType = dilithium_level3_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_LEVEL5k) {
- ctx->privateKeyType = dilithium_level5_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL2k) {
- ctx->privateKeyType = dilithium_aes_level2_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL3k) {
- ctx->privateKeyType = dilithium_aes_level3_sa_algo;
- }
- else if (*keyFormat == DILITHIUM_AES_LEVEL5k) {
- ctx->privateKeyType = dilithium_aes_level5_sa_algo;
- }
- ctx->privateKeySz = *keySz;
- }
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- wc_dilithium_free(key);
- }
- XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM);
- if (ret != 0) {
- return ret;
- }
- }
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- return ret;
- }
- /* process the buffer buff, length sz, into ctx of format and type
- used tracks bytes consumed, userChain specifies a user cert chain
- to pass during the handshake */
- int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
- long sz, int format, int type, WOLFSSL* ssl,
- long* used, int userChain, int verify)
- {
- DerBuffer* der = NULL;
- int ret = 0;
- int done = 0;
- int keyFormat = 0;
- int resetSuites = 0;
- void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
- int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
- word32 idx = 0;
- int keySz = 0;
- #if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \
- defined(HAVE_PKCS8)
- word32 algId = 0;
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
- #else
- EncryptedInfo info[1];
- #endif
- (void)devId;
- (void)idx;
- (void)keySz;
- if (used)
- *used = sz; /* used bytes default to sz, PEM chain may shorten*/
- /* check args */
- if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)
- return WOLFSSL_BAD_FILETYPE;
- if (ctx == NULL && ssl == NULL)
- return BAD_FUNC_ARG;
- #ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
- DYNAMIC_TYPE_ENCRYPTEDINFO);
- if (info == NULL)
- return MEMORY_E;
- #endif
- XMEMSET(info, 0, sizeof(EncryptedInfo));
- #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
- if (ctx) {
- info->passwd_cb = ctx->passwd_cb;
- info->passwd_userdata = ctx->passwd_userdata;
- }
- #endif
- if (format == WOLFSSL_FILETYPE_PEM) {
- #ifdef WOLFSSL_PEM_TO_DER
- ret = PemToDer(buff, sz, type, &der, heap, info, &keyFormat);
- #else
- ret = NOT_COMPILED_IN;
- #endif
- }
- else {
- /* ASN1 (DER) */
- int length = (int)sz;
- if (format == WOLFSSL_FILETYPE_ASN1) {
- /* get length of der (read sequence or octet string) */
- word32 inOutIdx = 0;
- if (GetSequence(buff, &inOutIdx, &length, (word32)sz) >= 0) {
- length += inOutIdx; /* include leading sequence */
- }
- /* get length using octect string (allowed for private key types) */
- else if (type == PRIVATEKEY_TYPE &&
- GetOctetString(buff, &inOutIdx, &length, (word32)sz) >= 0) {
- length += inOutIdx; /* include leading oct string */
- }
- else {
- ret = ASN_PARSE_E;
- }
- }
- info->consumed = length;
- if (ret == 0) {
- ret = AllocDer(&der, (word32)length, type, heap);
- if (ret == 0) {
- XMEMCPY(der->buffer, buff, length);
- }
- #ifdef HAVE_PKCS8
- /* if private key try and remove PKCS8 header */
- if (type == PRIVATEKEY_TYPE) {
- if ((ret = ToTraditional_ex(der->buffer, der->length,
- &algId)) > 0) {
- /* Found PKCS8 header */
- /* ToTraditional_ex moves buff and returns adjusted length */
- der->length = ret;
- keyFormat = algId;
- }
- ret = 0; /* failures should be ignored */
- }
- #endif
- }
- }
- if (used) {
- *used = info->consumed;
- }
- /* process user chain */
- if (ret >= 0) {
- /* Chain should have server cert first, then intermediates, then root.
- * First certificate in chain is processed below after ProcessUserChain
- * and is loaded into ssl->buffers.certificate.
- * Remainder are processed using ProcessUserChain and are loaded into
- * ssl->buffers.certChain. */
- if (userChain) {
- ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info,
- verify);
- if (ret == ASN_NO_PEM_HEADER) { /* Additional chain is optional */
- unsigned long pemErr;
- CLEAR_ASN_NO_PEM_HEADER_ERROR(pemErr);
- ret = 0;
- }
- }
- }
- /* info is only used for private key with DER or PEM, so free now */
- if (ret < 0 || type != PRIVATEKEY_TYPE) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- }
- /* check for error */
- if (ret < 0) {
- FreeDer(&der);
- done = 1;
- }
- if (done == 1) {
- /* No operation, just skip the next section */
- }
- /* Handle DER owner */
- else if (type == CA_TYPE) {
- if (ctx == NULL) {
- WOLFSSL_MSG("Need context for CA load");
- FreeDer(&der);
- return BAD_FUNC_ARG;
- }
- /* verify CA unless user set to no verify */
- ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify);
- done = 1;
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- else if (type == TRUSTED_PEER_TYPE) {
- /* add trusted peer cert. der is freed within */
- if (ctx != NULL)
- ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone);
- else
- ret = AddTrustedPeer(SSL_CM(ssl), &der, !ssl->options.verifyNone);
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error adding trusted peer");
- }
- done = 1;
- }
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- else if (type == CERT_TYPE) {
- if (ssl != NULL) {
- /* Make sure previous is free'd */
- if (ssl->buffers.weOwnCert) {
- FreeDer(&ssl->buffers.certificate);
- #ifdef KEEP_OUR_CERT
- wolfSSL_X509_free(ssl->ourCert);
- ssl->ourCert = NULL;
- #endif
- }
- ssl->buffers.certificate = der;
- #ifdef KEEP_OUR_CERT
- ssl->keepCert = 1; /* hold cert for ssl lifetime */
- #endif
- ssl->buffers.weOwnCert = 1;
- }
- else if (ctx != NULL) {
- FreeDer(&ctx->certificate); /* Make sure previous is free'd */
- #ifdef KEEP_OUR_CERT
- if (ctx->ourCert) {
- if (ctx->ownOurCert)
- wolfSSL_X509_free(ctx->ourCert);
- ctx->ourCert = NULL;
- }
- #endif
- ctx->certificate = der;
- }
- }
- else if (type == PRIVATEKEY_TYPE) {
- if (ssl != NULL) {
- /* Make sure previous is free'd */
- if (ssl->buffers.weOwnKey) {
- ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
- FreeDer(&ssl->buffers.key);
- }
- ssl->buffers.key = der;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("SSL Buffers key", der->buffer, der->length);
- #endif
- ssl->buffers.weOwnKey = 1;
- }
- else if (ctx != NULL) {
- if (ctx->privateKey != NULL && ctx->privateKey->buffer != NULL) {
- ForceZero(ctx->privateKey->buffer, ctx->privateKey->length);
- }
- FreeDer(&ctx->privateKey);
- ctx->privateKey = der;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("CTX private key", der->buffer, der->length);
- #endif
- }
- }
- else {
- FreeDer(&der);
- return WOLFSSL_BAD_CERTTYPE;
- }
- if (done == 1) {
- /* No operation, just skip the next section */
- }
- else if (type == PRIVATEKEY_TYPE) {
- ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites,
- &keyFormat, heap, devId);
- #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
- /* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */
- /* If private key type PKCS8 header wasn't already removed (algoId == 0) */
- if ((ret != 0 || keyFormat == 0)
- && format != WOLFSSL_FILETYPE_PEM && info->passwd_cb && algId == 0)
- {
- int passwordSz = NAME_SZ;
- #ifndef WOLFSSL_SMALL_STACK
- char password[NAME_SZ];
- #else
- char* password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
- if (password == NULL) {
- XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
- FreeDer(&der);
- return MEMORY_E;
- }
- #endif
- /* get password */
- ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
- info->passwd_userdata);
- if (ret >= 0) {
- passwordSz = ret;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("ProcessBuffer password", password, passwordSz);
- #endif
- /* PKCS8 decrypt */
- ret = ToTraditionalEnc(der->buffer, der->length,
- password, passwordSz, &algId);
- if (ret >= 0) {
- ForceZero(der->buffer + ret, der->length - ret);
- der->length = ret;
- }
- /* ignore failures and try parsing as unencrypted */
- ForceZero(password, passwordSz);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(password, heap, DYNAMIC_TYPE_STRING);
- #elif defined(WOLFSSL_CHECK_MEM_ZERO)
- wc_MemZero_Check(password, NAME_SZ);
- #endif
- ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx,
- &resetSuites, &keyFormat, heap, devId);
- }
- #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- if (ret != 0)
- return ret;
- if (keyFormat == 0) {
- #ifdef OPENSSL_EXTRA
- /* Reaching this point probably means that the
- * decryption password is wrong */
- if (info->passwd_cb)
- EVPerr(0, EVP_R_BAD_DECRYPT);
- #endif
- WOLFSSL_ERROR(WOLFSSL_BAD_FILE);
- return WOLFSSL_BAD_FILE;
- }
- (void)devId;
- }
- else if (type == CERT_TYPE) {
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert;
- #else
- DecodedCert cert[1];
- #endif
- #ifdef WOLF_PRIVATE_KEY_ID
- int keyType = 0;
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
- WOLFSSL_MSG("Checking cert signature type");
- InitDecodedCert(cert, der->buffer, der->length, heap);
- if (DecodeToKey(cert, 0) < 0) {
- WOLFSSL_MSG("Decode to key failed");
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
- #endif
- return WOLFSSL_BAD_FILE;
- }
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- resetSuites = 1;
- }
- if (ssl && ssl->ctx->haveECDSAsig) {
- WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off");
- ssl->options.haveECDSAsig = 0; /* may turn back on next */
- }
- switch (cert->signatureOID) {
- case CTC_SHAwECDSA:
- case CTC_SHA256wECDSA:
- case CTC_SHA384wECDSA:
- case CTC_SHA512wECDSA:
- case CTC_ED25519:
- case CTC_ED448:
- WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature");
- if (ssl)
- ssl->options.haveECDSAsig = 1;
- else if (ctx)
- ctx->haveECDSAsig = 1;
- break;
- case CTC_FALCON_LEVEL1:
- case CTC_FALCON_LEVEL5:
- WOLFSSL_MSG("Falcon cert signature");
- if (ssl)
- ssl->options.haveFalconSig = 1;
- else if (ctx)
- ctx->haveFalconSig = 1;
- break;
- case CTC_DILITHIUM_LEVEL2:
- case CTC_DILITHIUM_LEVEL3:
- case CTC_DILITHIUM_LEVEL5:
- case CTC_DILITHIUM_AES_LEVEL2:
- case CTC_DILITHIUM_AES_LEVEL3:
- case CTC_DILITHIUM_AES_LEVEL5:
- WOLFSSL_MSG("Dilithium cert signature");
- if (ssl)
- ssl->options.haveDilithiumSig = 1;
- else if (ctx)
- ctx->haveDilithiumSig = 1;
- break;
- default:
- WOLFSSL_MSG("Not ECDSA cert signature");
- break;
- }
- #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
- defined(HAVE_PQC) || !defined(NO_RSA)
- if (ssl) {
- #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
- (defined(HAVE_CURVE448) && defined(HAVE_ED448))
- ssl->pkCurveOID = cert->pkCurveOID;
- #endif
- #ifndef WC_STRICT_SIG
- if (cert->keyOID == ECDSAk) {
- ssl->options.haveECC = 1;
- }
- #ifndef NO_RSA
- else if (cert->keyOID == RSAk) {
- ssl->options.haveRSA = 1;
- }
- #ifdef WC_RSA_PSS
- else if (cert->keyOID == RSAPSSk) {
- ssl->options.haveRSA = 1;
- }
- #endif
- #endif
- #ifdef HAVE_ED25519
- else if (cert->keyOID == ED25519k) {
- ssl->options.haveECC = 1;
- }
- #endif
- #ifdef HAVE_ED448
- else if (cert->keyOID == ED448k) {
- ssl->options.haveECC = 1;
- }
- #endif
- #ifdef HAVE_PQC
- #ifdef HAVE_FALCON
- else if (cert->keyOID == FALCON_LEVEL1k ||
- cert->keyOID == FALCON_LEVEL5k) {
- ssl->options.haveFalconSig = 1;
- }
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- else if (cert->keyOID == DILITHIUM_LEVEL2k ||
- cert->keyOID == DILITHIUM_LEVEL3k ||
- cert->keyOID == DILITHIUM_LEVEL5k ||
- cert->keyOID == DILITHIUM_AES_LEVEL2k ||
- cert->keyOID == DILITHIUM_AES_LEVEL3k ||
- cert->keyOID == DILITHIUM_AES_LEVEL5k) {
- ssl->options.haveDilithiumSig = 1;
- }
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- #else
- ssl->options.haveECC = ssl->options.haveECDSAsig;
- #endif
- }
- else if (ctx) {
- #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
- ctx->pkCurveOID = cert->pkCurveOID;
- #endif
- #ifndef WC_STRICT_SIG
- if (cert->keyOID == ECDSAk) {
- ctx->haveECC = 1;
- }
- #ifndef NO_RSA
- else if (cert->keyOID == RSAk) {
- ctx->haveRSA = 1;
- }
- #ifdef WC_RSA_PSS
- else if (cert->keyOID == RSAPSSk) {
- ctx->haveRSA = 1;
- }
- #endif
- #endif
- #ifdef HAVE_ED25519
- else if (cert->keyOID == ED25519k) {
- ctx->haveECC = 1;
- }
- #endif
- #ifdef HAVE_ED448
- else if (cert->keyOID == ED448k) {
- ctx->haveECC = 1;
- }
- #endif
- #ifdef HAVE_PQC
- #ifdef HAVE_FALCON
- else if (cert->keyOID == FALCON_LEVEL1k ||
- cert->keyOID == FALCON_LEVEL5k) {
- ctx->haveFalconSig = 1;
- }
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- else if (cert->keyOID == DILITHIUM_LEVEL2k ||
- cert->keyOID == DILITHIUM_LEVEL3k ||
- cert->keyOID == DILITHIUM_LEVEL5k ||
- cert->keyOID == DILITHIUM_AES_LEVEL2k ||
- cert->keyOID == DILITHIUM_AES_LEVEL3k ||
- cert->keyOID == DILITHIUM_AES_LEVEL5k) {
- ctx->haveDilithiumSig = 1;
- }
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- #else
- ctx->haveECC = ctx->haveECDSAsig;
- #endif
- }
- #endif
- /* check key size of cert unless specified not to */
- switch (cert->keyOID) {
- #ifndef NO_RSA
- #ifdef WC_RSA_PSS
- case RSAPSSk:
- #endif
- case RSAk:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = rsa_sa_algo;
- #endif
- /* Determine RSA key size by parsing public key */
- idx = 0;
- ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx,
- cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL);
- if (ret < 0)
- break;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minRsaKeySz < 0 ||
- keySz < (int)ssl->options.minRsaKeySz ||
- keySz > (RSA_MAX_SIZE / 8)) {
- ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate RSA key size too small");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minRsaKeySz < 0 ||
- keySz < (int)ctx->minRsaKeySz ||
- keySz > (RSA_MAX_SIZE / 8)) {
- ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate RSA key size too small");
- }
- }
- break;
- #endif /* !NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = ecc_dsa_sa_algo;
- #endif
- /* Determine ECC key size based on curve */
- keySz = wc_ecc_get_curve_size_from_id(
- wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL));
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minEccKeySz < 0 ||
- keySz < (int)ssl->options.minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minEccKeySz < 0 ||
- keySz < (int)ctx->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- break;
- #endif /* HAVE_ECC */
- #ifdef HAVE_ED25519
- case ED25519k:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = ed25519_sa_algo;
- #endif
- /* ED25519 is fixed key size */
- keySz = ED25519_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minEccKeySz < 0 ||
- keySz < (int)ssl->options.minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Ed key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minEccKeySz < 0 ||
- keySz < (int)ctx->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- break;
- #endif /* HAVE_ED25519 */
- #ifdef HAVE_ED448
- case ED448k:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = ed448_sa_algo;
- #endif
- /* ED448 is fixed key size */
- keySz = ED448_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minEccKeySz < 0 ||
- keySz < (int)ssl->options.minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Ed key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minEccKeySz < 0 ||
- keySz < (int)ctx->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- break;
- #endif /* HAVE_ED448 */
- #if defined(HAVE_PQC)
- #if defined(HAVE_FALCON)
- case FALCON_LEVEL1k:
- case FALCON_LEVEL5k:
- /* Falcon is fixed key size */
- keySz = FALCON_MAX_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minFalconKeySz < 0 ||
- keySz < (int)ssl->options.minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Falcon key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minFalconKeySz < 0 ||
- keySz < (int)ctx->minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Falcon key size error");
- }
- }
- break;
- #endif /* HAVE_FALCON */
- #if defined(HAVE_DILITHIUM)
- case DILITHIUM_LEVEL2k:
- case DILITHIUM_LEVEL3k:
- case DILITHIUM_LEVEL5k:
- case DILITHIUM_AES_LEVEL2k:
- case DILITHIUM_AES_LEVEL3k:
- case DILITHIUM_AES_LEVEL5k:
- /* Dilithium is fixed key size */
- keySz = DILITHIUM_MAX_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minDilithiumKeySz < 0 ||
- keySz < (int)ssl->options.minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Dilithium key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minDilithiumKeySz < 0 ||
- keySz < (int)ctx->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Dilithium key size error");
- }
- }
- break;
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- default:
- WOLFSSL_MSG("No key size check done on certificate");
- break; /* do no check if not a case for the key */
- }
- #ifdef WOLF_PRIVATE_KEY_ID
- if (ssl != NULL && ssl->buffers.keyType == 0) {
- ssl->buffers.keyType = keyType;
- ssl->buffers.keySz = keySz;
- }
- else if (ctx != NULL && ctx->privateKeyType == 0) {
- ctx->privateKeyType = keyType;
- ctx->privateKeySz = keySz;
- }
- #endif
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
- #endif
- if (ret != 0) {
- done = 1;
- }
- }
- if (done == 1) {
- #if !defined(NO_WOLFSSL_CM_VERIFY) && (!defined(NO_WOLFSSL_CLIENT) || \
- !defined(WOLFSSL_NO_CLIENT_AUTH))
- if ((type == CA_TYPE) || (type == CERT_TYPE)) {
- /* Call to over-ride status */
- if ((ctx != NULL) && (ctx->cm != NULL) &&
- (ctx->cm->verifyCallback != NULL)) {
- ret = CM_VerifyBuffer_ex(ctx->cm, buff,
- sz, format, (ret == WOLFSSL_SUCCESS ? 0 : ret));
- }
- }
- #endif /* NO_WOLFSSL_CM_VERIFY */
- return ret;
- }
- if (ssl && resetSuites) {
- word16 havePSK = 0;
- word16 haveRSA = 0;
- #ifndef NO_PSK
- if (ssl->options.havePSK) {
- havePSK = 1;
- }
- #endif
- #ifndef NO_RSA
- haveRSA = 1;
- #endif
- keySz = ssl->buffers.keySz;
- /* let's reset suites */
- InitSuites(ssl->suites, ssl->version, keySz, haveRSA,
- havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig,
- ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
- ssl->options.haveFalconSig, ssl->options.haveDilithiumSig,
- ssl->options.haveAnon, TRUE, ssl->options.side);
- }
- return WOLFSSL_SUCCESS;
- }
- /* CA PEM file for verification, may have multiple/chain certs to process */
- static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
- long sz, int format, int type, WOLFSSL* ssl, int verify)
- {
- long used = 0;
- int ret = 0;
- int gotOne = 0;
- WOLFSSL_MSG("Processing CA PEM file");
- while (used < sz) {
- long consumed = 0;
- ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
- &consumed, 0, verify);
- if (ret < 0) {
- #if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
- DerBuffer* der = NULL;
- EncryptedInfo info;
- WOLFSSL_MSG("Trying a CRL");
- if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info,
- NULL) == 0) {
- WOLFSSL_MSG(" Processed a CRL");
- wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer,
- der->length, WOLFSSL_FILETYPE_ASN1);
- FreeDer(&der);
- used += info.consumed;
- continue;
- }
- #endif
- if (consumed > 0) { /* Made progress in file */
- WOLFSSL_ERROR(ret);
- WOLFSSL_MSG("CA Parse failed, with progress in file.");
- WOLFSSL_MSG("Search for other certs in file");
- }
- else {
- WOLFSSL_MSG("CA Parse failed, no progress in file.");
- WOLFSSL_MSG("Do not continue search for other certs in file");
- break;
- }
- }
- else {
- WOLFSSL_MSG(" Processed a CA");
- gotOne = 1;
- }
- used += consumed;
- }
- if (gotOne) {
- WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
- return WOLFSSL_SUCCESS;
- }
- return ret;
- }
- static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void)
- {
- #ifndef NO_WOLFSSL_CLIENT
- #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
- return wolfSSLv3_client_method();
- #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
- return wolfTLSv1_client_method();
- #elif !defined(NO_OLD_TLS)
- return wolfTLSv1_1_client_method();
- #elif !defined(WOLFSSL_NO_TLS12)
- return wolfTLSv1_2_client_method();
- #elif defined(WOLFSSL_TLS13)
- return wolfTLSv1_3_client_method();
- #else
- return NULL;
- #endif
- #elif !defined(NO_WOLFSSL_SERVER)
- #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
- return wolfSSLv3_server_method();
- #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
- return wolfTLSv1_server_method();
- #elif !defined(NO_OLD_TLS)
- return wolfTLSv1_1_server_method();
- #elif !defined(WOLFSSL_NO_TLS12)
- return wolfTLSv1_2_server_method();
- #elif defined(WOLFSSL_TLS13)
- return wolfTLSv1_3_server_method();
- #else
- return NULL;
- #endif
- #else
- return NULL;
- #endif
- }
- /* like load verify locations, 1 for success, < 0 for error */
- int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* in, long sz, int format)
- {
- int ret = WOLFSSL_FATAL_ERROR;
- WOLFSSL_CTX* tmp;
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer");
- if (cm == NULL) {
- WOLFSSL_MSG("No CertManager error");
- return ret;
- }
- tmp = wolfSSL_CTX_new(cm_pick_method());
- if (tmp == NULL) {
- WOLFSSL_MSG("CTX new failed");
- return ret;
- }
- /* for tmp use */
- wolfSSL_CertManagerFree(tmp->cm);
- tmp->cm = cm;
- ret = wolfSSL_CTX_load_verify_buffer(tmp, in, sz, format);
- /* don't loose our good one */
- tmp->cm = NULL;
- wolfSSL_CTX_free(tmp);
- return ret;
- }
- #ifdef HAVE_CRL
- int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
- const unsigned char* buff, long sz, int type)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- if (cm->crl == NULL) {
- if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Enable CRL failed");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- return BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
- }
- int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- if (cm->crl != NULL){
- FreeCRL(cm->crl, 1);
- cm->crl = NULL;
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
- long sz, int type)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
- }
- int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
- long sz, int type)
- {
- WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
- if (ssl == NULL || ssl->ctx == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type);
- }
- #endif /* HAVE_CRL */
- /* turn on CRL if off and compiled in, set options */
- int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
- {
- int ret = WOLFSSL_SUCCESS;
- (void)options;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- #ifdef HAVE_CRL
- if (cm->crl == NULL) {
- cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
- DYNAMIC_TYPE_CRL);
- if (cm->crl == NULL)
- return MEMORY_E;
- if (InitCRL(cm->crl, cm) != 0) {
- WOLFSSL_MSG("Init CRL failed");
- FreeCRL(cm->crl, 1);
- cm->crl = NULL;
- return WOLFSSL_FAILURE;
- }
- #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO)
- cm->crl->crlIOCb = EmbedCrlLookup;
- #endif
- }
- cm->crlEnabled = 1;
- if (options & WOLFSSL_CRL_CHECKALL)
- cm->crlCheckAll = 1;
- #else
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- cm->crlEnabled = 0;
- return WOLFSSL_SUCCESS;
- }
- #ifndef NO_WOLFSSL_CM_VERIFY
- void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
- if (cm == NULL)
- return;
- cm->verifyCallback = vc;
- }
- #endif /* NO_WOLFSSL_CM_VERIFY */
- #if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
- /* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
- int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
- long sz, int format, int err_val)
- {
- int ret = 0;
- DerBuffer* der = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert;
- #else
- DecodedCert cert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
- if (format == WOLFSSL_FILETYPE_PEM) {
- #ifdef WOLFSSL_PEM_TO_DER
- ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
- if (ret != 0) {
- FreeDer(&der);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- #endif
- return ret;
- }
- InitDecodedCert(cert, der->buffer, der->length, cm->heap);
- #else
- ret = NOT_COMPILED_IN;
- #endif
- }
- else {
- InitDecodedCert(cert, buff, (word32)sz, cm->heap);
- }
- if (ret == 0)
- ret = ParseCertRelative(cert, CERT_TYPE, 1, cm);
- #ifdef HAVE_CRL
- if (ret == 0 && cm->crlEnabled)
- ret = CheckCertCRL(cm->crl, cert);
- #endif
- #ifndef NO_WOLFSSL_CM_VERIFY
- /* if verify callback has been set */
- if (cm->verifyCallback) {
- buffer certBuf;
- #ifdef WOLFSSL_SMALL_STACK
- ProcPeerCertArgs* args;
- args = (ProcPeerCertArgs*)XMALLOC(
- sizeof(ProcPeerCertArgs), cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (args == NULL) {
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- return MEMORY_E;
- }
- #else
- ProcPeerCertArgs args[1];
- #endif
- certBuf.buffer = (byte*)buff;
- certBuf.length = (unsigned int)sz;
- XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
- args->totalCerts = 1;
- args->certs = &certBuf;
- args->dCert = cert;
- args->dCertInit = 1;
- if (err_val != 0) {
- ret = err_val;
- }
- ret = DoVerifyCallback(cm, NULL, ret, args);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- }
- #else
- (void)err_val;
- #endif
- FreeDecodedCert(cert);
- FreeDer(&der);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- #endif
- return ret == 0 ? WOLFSSL_SUCCESS : ret;
- }
- /* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
- int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
- long sz, int format)
- {
- return CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
- }
- #endif /* !NO_WOLFSSL_CLIENT || !WOLFSSL_NO_CLIENT_AUTH */
- /* turn on OCSP if off and compiled in, set options */
- int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
- {
- int ret = WOLFSSL_SUCCESS;
- (void)options;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- #ifdef HAVE_OCSP
- if (cm->ocsp == NULL) {
- cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
- DYNAMIC_TYPE_OCSP);
- if (cm->ocsp == NULL)
- return MEMORY_E;
- if (InitOCSP(cm->ocsp, cm) != 0) {
- WOLFSSL_MSG("Init OCSP failed");
- FreeOCSP(cm->ocsp, 1);
- cm->ocsp = NULL;
- return WOLFSSL_FAILURE;
- }
- }
- cm->ocspEnabled = 1;
- if (options & WOLFSSL_OCSP_URL_OVERRIDE)
- cm->ocspUseOverrideURL = 1;
- if (options & WOLFSSL_OCSP_NO_NONCE)
- cm->ocspSendNonce = 0;
- else
- cm->ocspSendNonce = 1;
- if (options & WOLFSSL_OCSP_CHECKALL)
- cm->ocspCheckAll = 1;
- #ifndef WOLFSSL_USER_IO
- cm->ocspIOCb = EmbedOcspLookup;
- cm->ocspRespFreeCb = EmbedOcspRespFree;
- cm->ocspIOCtx = cm->heap;
- #endif /* WOLFSSL_USER_IO */
- #else
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- cm->ocspEnabled = 0;
- return WOLFSSL_SUCCESS;
- }
- /* turn on OCSP Stapling if off and compiled in, set options */
- int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- #ifndef NO_WOLFSSL_SERVER
- if (cm->ocsp_stapling == NULL) {
- cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
- cm->heap, DYNAMIC_TYPE_OCSP);
- if (cm->ocsp_stapling == NULL)
- return MEMORY_E;
- if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
- WOLFSSL_MSG("Init OCSP failed");
- FreeOCSP(cm->ocsp_stapling, 1);
- cm->ocsp_stapling = NULL;
- return WOLFSSL_FAILURE;
- }
- }
- #ifndef WOLFSSL_USER_IO
- cm->ocspIOCb = EmbedOcspLookup;
- cm->ocspRespFreeCb = EmbedOcspRespFree;
- cm->ocspIOCtx = cm->heap;
- #endif /* WOLFSSL_USER_IO */
- #endif /* NO_WOLFSSL_SERVER */
- cm->ocspStaplingEnabled = 1;
- #else
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- cm->ocspStaplingEnabled = 0;
- #else
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- /* require OCSP stapling response */
- int wolfSSL_CertManagerEnableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPMustStaple");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- #ifndef NO_WOLFSSL_CLIENT
- cm->ocspMustStaple = 1;
- #endif
- ret = WOLFSSL_SUCCESS;
- #else
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- int wolfSSL_CertManagerDisableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPMustStaple");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- #ifndef NO_WOLFSSL_CLIENT
- cm->ocspMustStaple = 0;
- #endif
- ret = WOLFSSL_SUCCESS;
- #else
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- #ifdef HAVE_OCSP
- /* check CRL if enabled, WOLFSSL_SUCCESS */
- int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
- {
- int ret;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- if (cm->ocspEnabled == 0)
- return WOLFSSL_SUCCESS;
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
- InitDecodedCert(cert, der, sz, NULL);
- if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) {
- WOLFSSL_MSG("ParseCert failed");
- }
- else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) {
- WOLFSSL_MSG("CheckCertOCSP failed");
- }
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- #endif
- return ret == 0 ? WOLFSSL_SUCCESS : ret;
- }
- WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
- byte *response, int responseSz, buffer *responseBuffer,
- CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSPResponse");
- if (cm == NULL || response == NULL)
- return BAD_FUNC_ARG;
- if (cm->ocspEnabled == 0)
- return WOLFSSL_SUCCESS;
- ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer, status,
- entry, ocspRequest);
- return ret == 0 ? WOLFSSL_SUCCESS : ret;
- }
- int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
- const char* url)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
- if (url != NULL) {
- int urlSz = (int)XSTRLEN(url) + 1;
- cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, DYNAMIC_TYPE_URL);
- if (cm->ocspOverrideURL != NULL) {
- XMEMCPY(cm->ocspOverrideURL, url, urlSz);
- }
- else
- return MEMORY_E;
- }
- else
- cm->ocspOverrideURL = NULL;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm,
- CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- cm->ocspIOCb = ioCb;
- cm->ocspRespFreeCb = respFreeCb;
- cm->ocspIOCtx = ioCbCtx;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options)
- {
- WOLFSSL_ENTER("wolfSSL_EnableOCSP");
- if (ssl)
- return wolfSSL_CertManagerEnableOCSP(SSL_CM(ssl), options);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_DisableOCSP(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_DisableOCSP");
- if (ssl)
- return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl));
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
- if (ssl)
- return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl));
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
- if (ssl)
- return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl));
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
- {
- WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
- if (ssl)
- return wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
- CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
- {
- WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
- if (ssl) {
- ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
- return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl),
- ioCb, respFreeCb, NULL);
- }
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSP(ctx->cm, options);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSP(ctx->cm);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url)
- {
- WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
- if (ctx)
- return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb,
- CbOCSPRespFree respFreeCb, void* ioCbCtx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb");
- if (ctx)
- return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb,
- respFreeCb, ioCbCtx);
- else
- return BAD_FUNC_ARG;
- }
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_DisableOCSPMustStaple(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPMustStaple");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSPMustStaple(ctx->cm);
- else
- return BAD_FUNC_ARG;
- }
- #endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
- #endif /* HAVE_OCSP */
- /* macro to get verify settings for AddCA */
- #define GET_VERIFY_SETTING_CTX(ctx) \
- ((ctx) && (ctx)->verifyNone ? NO_VERIFY : VERIFY)
- #define GET_VERIFY_SETTING_SSL(ssl) \
- ((ssl)->options.verifyNone ? NO_VERIFY : VERIFY)
- #ifndef NO_FILESYSTEM
- /* process a file with name fname into ctx of format and type
- userChain specifies a user certificate chain to pass during handshake */
- int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
- WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify)
- {
- #ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
- #else
- byte staticBuffer[FILE_BUFFER_SIZE];
- #endif
- byte* myBuffer = staticBuffer;
- int dynamic = 0;
- int ret;
- long sz = 0;
- XFILE file;
- void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl);
- #ifndef NO_CODING
- const char* header = NULL;
- const char* footer = NULL;
- #endif
- (void)crl;
- (void)heapHint;
- if (fname == NULL) return WOLFSSL_BAD_FILE;
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE) return WOLFSSL_BAD_FILE;
- if (XFSEEK(file, 0, XSEEK_END) != 0) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- sz = XFTELL(file);
- XREWIND(file);
- if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
- WOLFSSL_MSG("ProcessFile file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- if (sz > (long)sizeof(staticBuffer)) {
- WOLFSSL_MSG("Getting dynamic buffer");
- myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE);
- if (myBuffer == NULL) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- dynamic = 1;
- }
- if ((size_t)XFREAD(myBuffer, 1, sz, file) != (size_t)sz)
- ret = WOLFSSL_BAD_FILE;
- else {
- /* Try to detect type by parsing cert header and footer */
- if (type == DETECT_CERT_TYPE) {
- #ifndef NO_CODING
- if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 &&
- (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
- type = CA_TYPE;
- }
- #ifdef HAVE_CRL
- else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
- (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
- type = CRL_TYPE;
- }
- #endif
- else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
- (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
- type = CERT_TYPE;
- }
- else
- #endif
- {
- WOLFSSL_MSG("Failed to detect certificate type");
- if (dynamic)
- XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE);
- XFCLOSE(file);
- return WOLFSSL_BAD_CERTTYPE;
- }
- }
- if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE)
- && format == WOLFSSL_FILETYPE_PEM) {
- ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl,
- verify);
- }
- #ifdef HAVE_CRL
- else if (type == CRL_TYPE)
- ret = BufferLoadCRL(crl, myBuffer, sz, format, verify);
- #endif
- else
- ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL,
- userChain, verify);
- }
- XFCLOSE(file);
- if (dynamic)
- XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE);
- return ret;
- }
- /* loads file then loads each file in path, no c_rehash */
- int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
- const char* path, word32 flags)
- {
- int ret = WOLFSSL_SUCCESS;
- #ifndef NO_WOLFSSL_DIR
- int fileRet;
- int successCount = 0;
- int failCount = 0;
- #endif
- int verify;
- WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex");
- if (ctx == NULL || (file == NULL && path == NULL)) {
- return WOLFSSL_FAILURE;
- }
- verify = GET_VERIFY_SETTING_CTX(ctx);
- if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
- verify = VERIFY_SKIP_DATE;
- if (file) {
- ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0,
- NULL, verify);
- #ifndef NO_WOLFSSL_DIR
- if (ret == WOLFSSL_SUCCESS)
- successCount++;
- #endif
- #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
- ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM);
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error");
- }
- #endif
- }
- if (ret == WOLFSSL_SUCCESS && path) {
- #ifndef NO_WOLFSSL_DIR
- char* name = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- ReadDirCtx* readCtx;
- readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
- DYNAMIC_TYPE_DIRCTX);
- if (readCtx == NULL)
- return MEMORY_E;
- #else
- ReadDirCtx readCtx[1];
- #endif
- /* try to load each regular file in path */
- fileRet = wc_ReadDirFirst(readCtx, path, &name);
- while (fileRet == 0 && name) {
- WOLFSSL_MSG(name); /* log file name */
- ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE,
- NULL, 0, NULL, verify);
- if (ret != WOLFSSL_SUCCESS) {
- /* handle flags for ignoring errors, skipping expired certs or
- by PEM certificate header error */
- if ( (flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) ||
- ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) &&
- (ret == ASN_NO_PEM_HEADER))) {
- /* Do not fail here if a certificate fails to load,
- continue to next file */
- unsigned long err;
- CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
- #if defined(WOLFSSL_QT)
- ret = WOLFSSL_SUCCESS;
- #endif
- }
- else {
- WOLFSSL_ERROR(ret);
- WOLFSSL_MSG("Load CA file failed, continuing");
- failCount++;
- }
- }
- else {
- #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
- ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM);
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error. Ignoring"
- "this error.");
- }
- #endif
- successCount++;
- }
- fileRet = wc_ReadDirNext(readCtx, path, &name);
- }
- wc_ReadDirClose(readCtx);
- /* pass directory read failure to response code */
- if (fileRet != WC_READDIR_NOFILE) {
- ret = fileRet;
- #if defined(WOLFSSL_QT)
- if (ret == BAD_PATH_ERROR &&
- flags & WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR) {
- /* QSslSocket always loads certs in system folder
- * when it is initialized.
- * Compliant with OpenSSL when flag sets.
- */
- ret = WOLFSSL_SUCCESS;
- }
- else {
- /* qssl socket wants to know errors. */
- WOLFSSL_ERROR(ret);
- }
- #endif
- }
- /* report failure if no files were loaded or there were failures */
- else if (successCount == 0 || failCount > 0) {
- /* use existing error code if exists */
- #if defined(WOLFSSL_QT)
- /* compliant with OpenSSL when flag sets*/
- if (!(flags & WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE))
- #endif
- {
- ret = WOLFSSL_FAILURE;
- }
- }
- else {
- ret = WOLFSSL_SUCCESS;
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
- #endif
- #else
- ret = NOT_COMPILED_IN;
- (void)flags;
- #endif
- }
- return ret;
- }
- WOLFSSL_ABI
- int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
- const char* path)
- {
- int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path,
- WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
- return WS_RETURN_CODE(ret,WOLFSSL_FAILURE);
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- /* Used to specify a peer cert to match when connecting
- ctx : the ctx structure to load in peer cert
- file: the string name of cert file
- type: type of format such as PEM/DER
- */
- int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert");
- if (ctx == NULL || file == NULL) {
- return WOLFSSL_FAILURE;
- }
- return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx));
- }
- int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int type)
- {
- WOLFSSL_ENTER("wolfSSL_trust_peer_cert");
- if (ssl == NULL || file == NULL) {
- return WOLFSSL_FAILURE;
- }
- return ProcessFile(NULL, file, type, TRUSTED_PEER_TYPE, ssl, 0, NULL,
- GET_VERIFY_SETTING_SSL(ssl));
- }
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- #if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
- /* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
- int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
- int format)
- {
- int ret = WOLFSSL_FATAL_ERROR;
- #ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
- #else
- byte staticBuffer[FILE_BUFFER_SIZE];
- #endif
- byte* myBuffer = staticBuffer;
- int dynamic = 0;
- long sz = 0;
- XFILE file = XFOPEN(fname, "rb");
- WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
- if (file == XBADFILE) return WOLFSSL_BAD_FILE;
- if(XFSEEK(file, 0, XSEEK_END) != 0) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- sz = XFTELL(file);
- XREWIND(file);
- if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
- WOLFSSL_MSG("CertManagerVerify file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- if (sz > (long)sizeof(staticBuffer)) {
- WOLFSSL_MSG("Getting dynamic buffer");
- myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE);
- if (myBuffer == NULL) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- dynamic = 1;
- }
- if ((size_t)XFREAD(myBuffer, 1, sz, file) != (size_t)sz)
- ret = WOLFSSL_BAD_FILE;
- else
- ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format);
- XFCLOSE(file);
- if (dynamic)
- XFREE(myBuffer, cm->heap, DYNAMIC_TYPE_FILE);
- return ret;
- }
- #endif
- /* like load verify locations, 1 for success, < 0 for error */
- int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
- const char* path)
- {
- int ret = WOLFSSL_FATAL_ERROR;
- WOLFSSL_CTX* tmp;
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
- if (cm == NULL) {
- WOLFSSL_MSG("No CertManager error");
- return ret;
- }
- tmp = wolfSSL_CTX_new(cm_pick_method());
- if (tmp == NULL) {
- WOLFSSL_MSG("CTX new failed");
- return ret;
- }
- /* for tmp use */
- wolfSSL_CertManagerFree(tmp->cm);
- tmp->cm = cm;
- ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
- /* don't lose our good one */
- tmp->cm = NULL;
- wolfSSL_CTX_free(tmp);
- return ret;
- }
- #endif /* NO_FILESYSTEM */
- #ifdef HAVE_CRL
- /* check CRL if enabled, WOLFSSL_SUCCESS */
- int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
- {
- int ret = 0;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- if (cm->crlEnabled == 0)
- return WOLFSSL_SUCCESS;
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
- InitDecodedCert(cert, der, sz, NULL);
- if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm)) != 0) {
- WOLFSSL_MSG("ParseCert failed");
- }
- else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
- WOLFSSL_MSG("CheckCertCRL failed");
- }
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
- #endif
- return ret == 0 ? WOLFSSL_SUCCESS : ret;
- }
- int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- cm->cbMissingCRL = cb;
- return WOLFSSL_SUCCESS;
- }
- #ifdef HAVE_CRL_IO
- int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
- {
- if (cm == NULL)
- return BAD_FUNC_ARG;
- cm->crl->crlIOCb = cb;
- return WOLFSSL_SUCCESS;
- }
- #endif
- #ifndef NO_FILESYSTEM
- int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
- int type, int monitor)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
- if (cm == NULL)
- return BAD_FUNC_ARG;
- if (cm->crl == NULL) {
- if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Enable CRL failed");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- return LoadCRL(cm->crl, path, type, monitor);
- }
- int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, const char* file,
- int type)
- {
- WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLFile");
- if (cm == NULL || file == NULL)
- return BAD_FUNC_ARG;
- if (cm->crl == NULL) {
- if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Enable CRL failed");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- return ProcessFile(NULL, file, type, CRL_TYPE, NULL, 0, cm->crl,
- VERIFY);
- }
- #endif
- int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
- {
- WOLFSSL_ENTER("wolfSSL_EnableCRL");
- if (ssl)
- return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_DisableCRL(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_DisableCRL");
- if (ssl)
- return wolfSSL_CertManagerDisableCRL(SSL_CM(ssl));
- else
- return BAD_FUNC_ARG;
- }
- #ifndef NO_FILESYSTEM
- int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
- {
- WOLFSSL_ENTER("wolfSSL_LoadCRL");
- if (ssl)
- return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type)
- {
- WOLFSSL_ENTER("wolfSSL_LoadCRL");
- if (ssl)
- return wolfSSL_CertManagerLoadCRLFile(SSL_CM(ssl), file, type);
- else
- return BAD_FUNC_ARG;
- }
- #endif
- int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
- {
- WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
- if (ssl)
- return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb);
- else
- return BAD_FUNC_ARG;
- }
- #ifdef HAVE_CRL_IO
- int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb)
- {
- WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
- if (ssl)
- return wolfSSL_CertManagerSetCRL_IOCb(SSL_CM(ssl), cb);
- else
- return BAD_FUNC_ARG;
- }
- #endif
- int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL");
- if (ctx)
- return wolfSSL_CertManagerEnableCRL(ctx->cm, options);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
- if (ctx)
- return wolfSSL_CertManagerDisableCRL(ctx->cm);
- else
- return BAD_FUNC_ARG;
- }
- #ifndef NO_FILESYSTEM
- int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
- int type, int monitor)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
- if (ctx)
- return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor);
- else
- return BAD_FUNC_ARG;
- }
- int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file,
- int type)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
- if (ctx)
- return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type);
- else
- return BAD_FUNC_ARG;
- }
- #endif
- int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb");
- if (ctx)
- return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb);
- else
- return BAD_FUNC_ARG;
- }
- #ifdef HAVE_CRL_IO
- int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
- if (ctx)
- return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
- else
- return BAD_FUNC_ARG;
- }
- #endif
- #endif /* HAVE_CRL */
- #ifndef NO_FILESYSTEM
- #ifdef WOLFSSL_DER_LOAD
- /* Add format parameter to allow DER load of CA files */
- int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
- int format)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations");
- if (ctx == NULL || file == NULL)
- return WOLFSSL_FAILURE;
- if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* WOLFSSL_DER_LOAD */
- WOLFSSL_ABI
- int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
- int format)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
- if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- WOLFSSL_ABI
- int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
- int format)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
- if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* NO_FILESYSTEM */
- /* Sets the max chain depth when verifying a certificate chain. Default depth
- * is set to MAX_CHAIN_DEPTH.
- *
- * ctx WOLFSSL_CTX structure to set depth in
- * depth max depth
- */
- void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
- WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
- if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
- WOLFSSL_MSG("Bad depth argument, too large or less than 0");
- return;
- }
- ctx->verifyDepth = (byte)depth;
- }
- /* get cert chaining depth using ssl struct */
- long wolfSSL_get_verify_depth(WOLFSSL* ssl)
- {
- if(ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- #ifndef OPENSSL_EXTRA
- return MAX_CHAIN_DEPTH;
- #else
- return ssl->options.verifyDepth;
- #endif
- }
- /* get cert chaining depth using ctx struct */
- long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- #ifndef OPENSSL_EXTRA
- return MAX_CHAIN_DEPTH;
- #else
- return ctx->verifyDepth;
- #endif
- }
- #ifndef NO_FILESYSTEM
- WOLFSSL_ABI
- int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
- {
- /* process up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
- if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
- const char* file, int format)
- {
- /* process up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
- if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #ifndef NO_DH
- /* server Diffie-Hellman parameters */
- static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- const char* fname, int format)
- {
- #ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
- #else
- byte staticBuffer[FILE_BUFFER_SIZE];
- #endif
- byte* myBuffer = staticBuffer;
- int dynamic = 0;
- int ret;
- long sz = 0;
- XFILE file;
- if (ctx == NULL || fname == NULL)
- return BAD_FUNC_ARG;
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE) return WOLFSSL_BAD_FILE;
- if(XFSEEK(file, 0, XSEEK_END) != 0) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- sz = XFTELL(file);
- XREWIND(file);
- if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
- WOLFSSL_MSG("SetTmpDH file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- if (sz > (long)sizeof(staticBuffer)) {
- WOLFSSL_MSG("Getting dynamic buffer");
- myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
- if (myBuffer == NULL) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- dynamic = 1;
- }
- if ((size_t)XFREAD(myBuffer, 1, sz, file) != (size_t)sz)
- ret = WOLFSSL_BAD_FILE;
- else {
- if (ssl)
- ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format);
- else
- ret = wolfSSL_CTX_SetTmpDH_buffer(ctx, myBuffer, sz, format);
- }
- XFCLOSE(file);
- if (dynamic)
- XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
- return ret;
- }
- /* server Diffie-Hellman parameters */
- int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format);
- }
- /* server Diffie-Hellman parameters */
- int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
- {
- return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format);
- }
- #endif /* NO_DH */
- #endif /* NO_FILESYSTEM */
- #ifndef NO_CHECK_PRIVATE_KEY
- /* Check private against public in certificate for match
- *
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched */
- static int check_cert_key(DerBuffer* cert, DerBuffer* key, void* heap,
- int devId, int isKeyLabel, int isKeyId)
- {
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* der = NULL;
- #else
- DecodedCert der[1];
- #endif
- word32 size;
- byte* buff;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("check_cert_key");
- if (cert == NULL || key == NULL) {
- return WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
- if (der == NULL)
- return MEMORY_E;
- #endif
- size = cert->length;
- buff = cert->buffer;
- InitDecodedCert(der, buff, size, heap);
- if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
- FreeDecodedCert(der);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
- #endif
- return WOLFSSL_FAILURE;
- }
- size = key->length;
- buff = key->buffer;
- #ifdef WOLF_PRIVATE_KEY_ID
- if (devId != INVALID_DEVID) {
- int type = 0;
- void *pkey = NULL;
- #ifndef NO_RSA
- if (der->keyOID == RSAk) {
- type = DYNAMIC_TYPE_RSA;
- }
- #ifdef WC_RSA_PSS
- if (der->keyOID == RSAPSSk) {
- type = DYNAMIC_TYPE_RSA;
- }
- #endif
- #endif
- #ifdef HAVE_ECC
- if (der->keyOID == ECDSAk) {
- type = DYNAMIC_TYPE_ECC;
- }
- #endif
- ret = CreateDevPrivateKey(&pkey, buff, size, type,
- isKeyLabel, isKeyId, heap, devId);
- #ifdef WOLF_CRYPTO_CB
- if (ret == 0) {
- #ifndef NO_RSA
- if (der->keyOID == RSAk
- #ifdef WC_RSA_PSS
- || der->keyOID == RSAPSSk
- #endif
- ) {
- ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey,
- der->publicKey, der->pubKeySize);
- }
- #endif
- #ifdef HAVE_ECC
- if (der->keyOID == ECDSAk) {
- ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey,
- der->publicKey, der->pubKeySize);
- }
- #endif
- }
- #else
- /* devId was set, don't check, for now */
- /* TODO: Add callback for private key check? */
- #endif
- if (pkey != NULL) {
- #ifndef NO_RSA
- if (der->keyOID == RSAk
- #ifdef WC_RSA_PSS
- || der->keyOID == RSAPSSk
- #endif
- ) {
- wc_FreeRsaKey((RsaKey*)pkey);
- }
- #endif
- #ifdef HAVE_ECC
- if (der->keyOID == ECDSAk) {
- wc_ecc_free((ecc_key*)pkey);
- }
- #endif
- XFREE(pkey, heap, type);
- }
- if (ret != CRYPTOCB_UNAVAILABLE) {
- ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
- }
- }
- else {
- /* fall through if unavailable */
- ret = CRYPTOCB_UNAVAILABLE;
- }
- if (ret == CRYPTOCB_UNAVAILABLE)
- #endif /* WOLF_PRIVATE_KEY_ID */
- {
- ret = wc_CheckPrivateKeyCert(buff, size, der);
- ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
- }
- FreeDecodedCert(der);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
- #endif
- (void)devId;
- (void)isKeyLabel;
- (void)isKeyId;
- return ret;
- }
- /* Check private against public in certificate for match
- *
- * ctx WOLFSSL_CTX structure to check private key in
- *
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched. */
- int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
- return check_cert_key(ctx->certificate, ctx->privateKey, ctx->heap,
- ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId);
- }
- #endif /* !NO_CHECK_PRIVATE_KEY */
- #ifdef OPENSSL_ALL
- /**
- * Return the private key of the WOLFSSL_CTX struct
- * @return WOLFSSL_EVP_PKEY* The caller doesn *NOT*` free the returned object.
- */
- WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx)
- {
- const unsigned char *key;
- int type;
- WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey");
- if (ctx == NULL || ctx->privateKey == NULL ||
- ctx->privateKey->buffer == NULL) {
- WOLFSSL_MSG("Bad parameter or key not set");
- return NULL;
- }
- switch (ctx->privateKeyType) {
- #ifndef NO_RSA
- case rsa_sa_algo:
- type = EVP_PKEY_RSA;
- break;
- #endif
- #ifdef HAVE_ECC
- case ecc_dsa_sa_algo:
- type = EVP_PKEY_EC;
- break;
- #endif
- default:
- /* Other key types not supported either as ssl private keys
- * or in the EVP layer */
- WOLFSSL_MSG("Unsupported key type");
- return NULL;
- }
- key = ctx->privateKey->buffer;
- if (ctx->privateKeyPKey != NULL)
- return ctx->privateKeyPKey;
- else
- return wolfSSL_d2i_PrivateKey(type,
- (WOLFSSL_EVP_PKEY**)&ctx->privateKeyPKey, &key,
- (long)ctx->privateKey->length);
- }
- #endif
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out,
- const unsigned char** in, long inSz, int priv)
- {
- WOLFSSL_EVP_PKEY* pkey = NULL;
- const unsigned char* mem;
- long memSz = inSz;
- WOLFSSL_ENTER("d2iGenericKey");
- if (in == NULL || *in == NULL || inSz < 0) {
- WOLFSSL_MSG("Bad argument");
- return NULL;
- }
- mem = *in;
- #if !defined(NO_RSA)
- {
- word32 keyIdx = 0;
- int isRsaKey;
- #ifdef WOLFSSL_SMALL_STACK
- RsaKey *rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
- if (rsa == NULL)
- return NULL;
- #else
- RsaKey rsa[1];
- #endif
- XMEMSET(rsa, 0, sizeof(RsaKey));
- /* test if RSA key */
- if (priv)
- isRsaKey = wc_InitRsaKey(rsa, NULL) == 0 &&
- wc_RsaPrivateKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0;
- else
- isRsaKey = wc_InitRsaKey(rsa, NULL) == 0 &&
- wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0;
- wc_FreeRsaKey(rsa);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
- #endif
- if (isRsaKey) {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey != NULL) {
- pkey->pkey_sz = keyIdx;
- pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
- pkey->type = EVP_PKEY_RSA;
- if (out != NULL) {
- *out = pkey;
- }
- pkey->ownRsa = 1;
- pkey->rsa = wolfSSL_RSA_new();
- if (pkey->rsa == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE
- : WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- return pkey;
- }
- else {
- WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error");
- }
- }
- }
- #endif /* NO_RSA */
- #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
- {
- word32 keyIdx = 0;
- int isEccKey;
- #ifdef WOLFSSL_SMALL_STACK
- ecc_key *ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC);
- if (ecc == NULL)
- return NULL;
- #else
- ecc_key ecc[1];
- #endif
- XMEMSET(ecc, 0, sizeof(ecc_key));
- if (priv)
- isEccKey = wc_ecc_init(ecc) == 0 &&
- wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0;
- else
- isEccKey = wc_ecc_init(ecc) == 0 &&
- wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0;
- wc_ecc_free(ecc);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(ecc, NULL, DYNAMIC_TYPE_ECC);
- #endif
- if (isEccKey) {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey != NULL) {
- pkey->pkey_sz = keyIdx;
- pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
- pkey->type = EVP_PKEY_EC;
- if (out != NULL) {
- *out = pkey;
- }
- pkey->ownEcc = 1;
- pkey->ecc = wolfSSL_EC_KEY_new();
- if (pkey->ecc == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- if (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE
- : WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- return pkey;
- }
- else {
- WOLFSSL_MSG("ECC wolfSSL_EVP_PKEY_new error");
- }
- }
- }
- #endif /* HAVE_ECC && OPENSSL_EXTRA */
- #if !defined(NO_DSA)
- {
- word32 keyIdx = 0;
- int isDsaKey;
- #ifdef WOLFSSL_SMALL_STACK
- DsaKey *dsa = (DsaKey*)XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA);
- if (dsa == NULL)
- return NULL;
- #else
- DsaKey dsa[1];
- #endif
- XMEMSET(dsa, 0, sizeof(DsaKey));
- if (priv)
- isDsaKey = wc_InitDsaKey(dsa) == 0 &&
- wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0;
- else
- isDsaKey = wc_InitDsaKey(dsa) == 0 &&
- wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0;
- wc_FreeDsaKey(dsa);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
- #endif
- /* test if DSA key */
- if (isDsaKey) {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey != NULL) {
- pkey->pkey_sz = keyIdx;
- pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
- pkey->type = EVP_PKEY_DSA;
- if (out != NULL) {
- *out = pkey;
- }
- pkey->ownDsa = 1;
- pkey->dsa = wolfSSL_DSA_new();
- if (pkey->dsa == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- if (wolfSSL_DSA_LoadDer_ex(pkey->dsa,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE
- : WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- return pkey;
- }
- else {
- WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error");
- }
- }
- }
- #endif /* NO_DSA */
- #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
- #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2))
- {
- int isDhKey;
- word32 keyIdx = 0;
- #ifdef WOLFSSL_SMALL_STACK
- DhKey *dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
- if (dh == NULL)
- return NULL;
- #else
- DhKey dh[1];
- #endif
- XMEMSET(dh, 0, sizeof(DhKey));
- isDhKey = wc_InitDhKey(dh) == 0 &&
- wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0;
- wc_FreeDhKey(dh);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dh, NULL, DYNAMIC_TYPE_DH);
- #endif
- /* test if DH key */
- if (isDhKey) {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey != NULL) {
- pkey->pkey_sz = (int)memSz;
- pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- XMEMCPY(pkey->pkey.ptr, mem, memSz);
- pkey->type = EVP_PKEY_DH;
- if (out != NULL) {
- *out = pkey;
- }
- pkey->ownDh = 1;
- pkey->dh = wolfSSL_DH_new();
- if (pkey->dh == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- if (wolfSSL_DH_LoadDer(pkey->dh,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz) != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- return pkey;
- }
- else {
- WOLFSSL_MSG("DH wolfSSL_EVP_PKEY_new error");
- }
- }
- }
- #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
- #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
- #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
- #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2))
- {
- word32 keyIdx = 0;
- DhKey* key = NULL;
- int ret;
- int elements;
- #ifdef WOLFSSL_SMALL_STACK
- DhKey* dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
- if (dh == NULL)
- return NULL;
- #else
- DhKey dh[1];
- #endif
- XMEMSET(dh, 0, sizeof(DhKey));
- /* test if DH-public key */
- if (wc_InitDhKey(dh) != 0)
- return NULL;
- ret = wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz);
- wc_FreeDhKey(dh);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dh, NULL, DYNAMIC_TYPE_DH);
- #endif
- if (ret == 0) {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey != NULL) {
- pkey->type = EVP_PKEY_DH;
- pkey->pkey_sz = (int)memSz;
- pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- XMEMCPY(pkey->pkey.ptr, mem, memSz);
- if (out != NULL) {
- *out = pkey;
- }
- pkey->ownDh = 1;
- pkey->dh = wolfSSL_DH_new();
- if (pkey->dh == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- key = (DhKey*)pkey->dh->internal;
- keyIdx = 0;
- if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) == 0)
- {
- elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB;
- if (priv)
- elements |= ELEMENT_PRV;
- if(SetDhExternal_ex(pkey->dh, elements)
- == WOLFSSL_SUCCESS ) {
- return pkey;
- }
- }
- else {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- }
- }
- }
- #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
- #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
- #ifdef HAVE_PQC
- #ifdef HAVE_FALCON
- {
- int isFalcon = 0;
- #ifdef WOLFSSL_SMALL_STACK
- falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(falcon_key), NULL,
- DYNAMIC_TYPE_FALCON);
- if (falcon == NULL) {
- return NULL;
- }
- #else
- falcon_key falcon[1];
- #endif
- if (wc_falcon_init(falcon) == 0) {
- /* test if Falcon key */
- if (priv) {
- /* Try level 1 */
- isFalcon = wc_falcon_set_level(falcon, 1) == 0 &&
- wc_falcon_import_private_only(mem, (word32)memSz,
- falcon) == 0;
- if (!isFalcon) {
- /* Try level 5 */
- isFalcon = wc_falcon_set_level(falcon, 5) == 0 &&
- wc_falcon_import_private_only(mem, (word32)memSz,
- falcon) == 0;
- }
- } else {
- /* Try level 1 */
- isFalcon = wc_falcon_set_level(falcon, 1) == 0 &&
- wc_falcon_import_public(mem, (word32)memSz, falcon)
- == 0;
- if (!isFalcon) {
- /* Try level 5 */
- isFalcon = wc_falcon_set_level(falcon, 5) == 0 &&
- wc_falcon_import_public(mem, (word32)memSz,
- falcon) == 0;
- }
- }
- wc_falcon_free(falcon);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON);
- #endif
- if (isFalcon) {
- /* Create a fake Falcon EVP_PKEY. In the future, we might integrate
- * Falcon into the compatibility layer. */
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("Falcon wolfSSL_EVP_PKEY_new error");
- return NULL;
- }
- pkey->type = EVP_PKEY_FALCON;
- pkey->pkey.ptr = NULL;
- pkey->pkey_sz = 0;
- return pkey;
- }
- }
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- {
- int isDilithium = 0;
- #ifdef WOLFSSL_SMALL_STACK
- dilithium_key *dilithium = (dilithium_key *)
- XMALLOC(sizeof(dilithium_key), NULL, DYNAMIC_TYPE_DILITHIUM);
- if (dilithium == NULL) {
- return NULL;
- }
- #else
- dilithium_key dilithium[1];
- #endif
- if (wc_dilithium_init(dilithium) == 0) {
- /* Test if Dilithium key. Try all levels for both SHAKE and AES */
- if (priv) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2,
- SHAKE_VARIANT) == 0 &&
- wc_dilithium_import_private_only(mem,
- (word32)memSz, dilithium) == 0;
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3,
- SHAKE_VARIANT) == 0 &&
- wc_dilithium_import_private_only(mem,
- (word32)memSz, dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5,
- SHAKE_VARIANT) == 0 &&
- wc_dilithium_import_private_only(mem,
- (word32)memSz, dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2,
- AES_VARIANT) == 0 &&
- wc_dilithium_import_private_only(mem,
- (word32)memSz, dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3,
- AES_VARIANT) == 0 &&
- wc_dilithium_import_private_only(mem,
- (word32)memSz, dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5,
- AES_VARIANT) == 0 &&
- wc_dilithium_import_private_only(mem,
- (word32)memSz, dilithium) == 0;
- }
- } else {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2,
- SHAKE_VARIANT) == 0 &&
- wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0;
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3,
- SHAKE_VARIANT) == 0 &&
- wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5,
- SHAKE_VARIANT) == 0 &&
- wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 2,
- AES_VARIANT) == 0 &&
- wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 3,
- AES_VARIANT) == 0 &&
- wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0;
- }
- if (!isDilithium) {
- isDilithium = wc_dilithium_set_level_and_sym(dilithium, 5,
- AES_VARIANT) == 0 &&
- wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0;
- }
- }
- wc_dilithium_free(dilithium);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
- #endif
- if (isDilithium) {
- /* Create a fake Dilithium EVP_PKEY. In the future, we might
- * integrate Dilithium into the compatibility layer. */
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("Dilithium wolfSSL_EVP_PKEY_new error");
- return NULL;
- }
- pkey->type = EVP_PKEY_DILITHIUM;
- pkey->pkey.ptr = NULL;
- pkey->pkey_sz = 0;
- return pkey;
- }
- }
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- if (pkey == NULL) {
- WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type");
- }
- return pkey;
- }
- #endif /* OPENSSL_EXTRA || WPA_SMALL */
- #ifdef OPENSSL_EXTRA
- WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY(
- WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, long keyLen)
- {
- WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
- #ifdef WOLFSSL_PEM_TO_DER
- int ret;
- DerBuffer* der = NULL;
- if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) {
- WOLFSSL_MSG("Bad key PEM/DER args");
- return NULL;
- }
- ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &der, NULL, NULL, NULL);
- if (ret < 0) {
- WOLFSSL_MSG("Not PEM format");
- ret = AllocDer(&der, (word32)keyLen, PRIVATEKEY_TYPE, NULL);
- if (ret == 0) {
- XMEMCPY(der->buffer, *keyBuf, keyLen);
- }
- }
- if (ret == 0) {
- /* Verify this is PKCS8 Key */
- word32 inOutIdx = 0;
- word32 algId;
- ret = ToTraditionalInline_ex(der->buffer, &inOutIdx, der->length, &algId);
- if (ret >= 0) {
- ret = 0; /* good DER */
- }
- }
- if (ret == 0) {
- pkcs8 = wolfSSL_EVP_PKEY_new();
- if (pkcs8 == NULL)
- ret = MEMORY_E;
- }
- if (ret == 0) {
- pkcs8->pkey.ptr = (char*)XMALLOC(der->length, NULL,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkcs8->pkey.ptr == NULL)
- ret = MEMORY_E;
- }
- if (ret == 0) {
- XMEMCPY(pkcs8->pkey.ptr, der->buffer, der->length);
- pkcs8->pkey_sz = der->length;
- }
- FreeDer(&der);
- if (ret != 0) {
- wolfSSL_EVP_PKEY_free(pkcs8);
- pkcs8 = NULL;
- }
- if (pkey != NULL) {
- *pkey = pkcs8;
- }
- #else
- (void)bio;
- (void)pkey;
- #endif /* WOLFSSL_PEM_TO_DER */
- return pkcs8;
- }
- #ifndef NO_BIO
- /* put SSL type in extra for now, not very common */
- /* Converts a DER format key read from "bio" to a PKCS8 structure.
- *
- * bio input bio to read DER from
- * pkey If not NULL then this pointer will be overwritten with a new PKCS8
- * structure.
- *
- * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail
- * case.
- */
- WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
- WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
- {
- WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
- #ifdef WOLFSSL_PEM_TO_DER
- unsigned char* mem = NULL;
- int memSz;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio");
- if (bio == NULL) {
- return NULL;
- }
- if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
- return NULL;
- }
- pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz);
- #else
- (void)bio;
- (void)pkey;
- #endif /* WOLFSSL_PEM_TO_DER */
- return pkcs8;
- }
- /* expecting DER format public key
- *
- * bio input bio to read DER from
- * out If not NULL then this pointer will be overwritten with a new
- * WOLFSSL_EVP_PKEY pointer
- *
- * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case.
- */
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** out)
- {
- unsigned char* mem;
- long memSz;
- WOLFSSL_EVP_PKEY* pkey = NULL;
- WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()");
- if (bio == NULL) {
- return NULL;
- }
- (void)out;
- memSz = wolfSSL_BIO_get_len(bio);
- if (memSz <= 0) {
- return NULL;
- }
- mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- return NULL;
- }
- if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
- pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz);
- if (out != NULL && pkey != NULL) {
- *out = pkey;
- }
- }
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return pkey;
- }
- #endif /* !NO_BIO */
- /* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure.
- *
- * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL
- * in DER buffer to convert
- * inSz size of in buffer
- *
- * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
- * on fail
- */
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out,
- const unsigned char** in, long inSz)
- {
- WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
- return d2iGenericKey(out, in, inSz, 0);
- }
- /* helper function to get raw pointer to DER buffer from WOLFSSL_EVP_PKEY */
- static int wolfSSL_EVP_PKEY_get_der(const WOLFSSL_EVP_PKEY* key, unsigned char** der)
- {
- unsigned char* pt;
- int sz;
- word16 pkcs8HeaderSz;
- if (!key || !key->pkey_sz)
- return WOLFSSL_FATAL_ERROR;
- /* return the key without PKCS8 for compatibility */
- /* if pkcs8HeaderSz is invalid, use 0 and return all of pkey */
- pkcs8HeaderSz = 0;
- if (key->pkey_sz > key->pkcs8HeaderSz)
- pkcs8HeaderSz = key->pkcs8HeaderSz;
- sz = key->pkey_sz - pkcs8HeaderSz;
- if (der) {
- pt = (unsigned char*)key->pkey.ptr;
- if (*der) {
- /* since this function signature has no size value passed in it is
- * assumed that the user has allocated a large enough buffer */
- XMEMCPY(*der, pt + pkcs8HeaderSz, sz);
- *der += sz;
- }
- else {
- *der = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
- if (*der == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
- XMEMCPY(*der, pt + pkcs8HeaderSz, sz);
- }
- }
- return sz;
- }
- int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
- {
- return wolfSSL_EVP_PKEY_get_der(key, der);
- }
- static WOLFSSL_EVP_PKEY* _d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz, int priv)
- {
- int ret = 0;
- word32 idx = 0, algId;
- word16 pkcs8HeaderSz = 0;
- WOLFSSL_EVP_PKEY* local;
- int opt;
- (void)opt;
- if (in == NULL || inSz < 0) {
- WOLFSSL_MSG("Bad argument");
- return NULL;
- }
- if (priv == 1) {
- /* Check if input buffer has PKCS8 header. In the case that it does not
- * have a PKCS8 header then do not error out. */
- if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx,
- (word32)inSz, &algId)) > 0) {
- WOLFSSL_MSG("Found PKCS8 header");
- pkcs8HeaderSz = (word16)idx;
- if ((type == EVP_PKEY_RSA && algId != RSAk
- #ifdef WC_RSA_PSS
- && algId != RSAPSSk
- #endif
- ) ||
- (type == EVP_PKEY_EC && algId != ECDSAk) ||
- (type == EVP_PKEY_DSA && algId != DSAk) ||
- (type == EVP_PKEY_DH && algId != DHk)) {
- WOLFSSL_MSG("PKCS8 does not match EVP key type");
- return NULL;
- }
- (void)idx; /* not used */
- }
- else {
- if (ret != ASN_PARSE_E) {
- WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 "
- "header");
- return NULL;
- }
- }
- }
- if (out != NULL && *out != NULL) {
- wolfSSL_EVP_PKEY_free(*out);
- *out = NULL;
- }
- local = wolfSSL_EVP_PKEY_new();
- if (local == NULL) {
- return NULL;
- }
- local->type = type;
- local->pkey_sz = (int)inSz;
- local->pkcs8HeaderSz = pkcs8HeaderSz;
- local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- if (local->pkey.ptr == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- local = NULL;
- return NULL;
- }
- else {
- XMEMCPY(local->pkey.ptr, *in, inSz);
- }
- switch (type) {
- #ifndef NO_RSA
- case EVP_PKEY_RSA:
- local->ownRsa = 1;
- local->rsa = wolfSSL_RSA_new();
- if (local->rsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC;
- if (wolfSSL_RSA_LoadDer_ex(local->rsa,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz,
- opt) != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case EVP_PKEY_EC:
- local->ownEcc = 1;
- local->ecc = wolfSSL_EC_KEY_new();
- if (local->ecc == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE :
- WOLFSSL_EC_KEY_LOAD_PUBLIC;
- if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz,
- opt)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
- #endif /* HAVE_ECC */
- #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
- #ifndef NO_DSA
- case EVP_PKEY_DSA:
- local->ownDsa = 1;
- local->dsa = wolfSSL_DSA_new();
- if (local->dsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC;
- if (wolfSSL_DSA_LoadDer_ex(local->dsa,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz,
- opt)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
- #endif /* NO_DSA */
- #ifndef NO_DH
- #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
- case EVP_PKEY_DH:
- local->ownDh = 1;
- local->dh = wolfSSL_DH_new();
- if (local->dh == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- if (wolfSSL_DH_LoadDer(local->dh,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
- #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
- #endif /* HAVE_DH */
- #endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */
- default:
- WOLFSSL_MSG("Unsupported key type");
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- /* advance pointer with success */
- if (local != NULL) {
- if (local->pkey_sz <= (int)inSz) {
- *in += local->pkey_sz;
- }
- if (out != NULL) {
- *out = local;
- }
- }
- return local;
- }
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz)
- {
- WOLFSSL_ENTER("wolfSSL_d2i_PublicKey");
- return _d2i_PublicKey(type, out, in, inSz, 0);
- }
- /* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
- *
- * type type of key
- * out newly created WOLFSSL_EVP_PKEY structure
- * in pointer to input key DER
- * inSz size of in buffer
- *
- * On success a non null pointer is returned and the pointer in is advanced the
- * same number of bytes read.
- */
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz)
- {
- WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
- return _d2i_PublicKey(type, out, in, inSz, 1);
- }
- #ifdef WOLF_PRIVATE_KEY_ID
- /* Create an EVP structure for use with crypto callbacks */
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out,
- void* heap, int devId)
- {
- WOLFSSL_EVP_PKEY* local;
- if (out != NULL && *out != NULL) {
- wolfSSL_EVP_PKEY_free(*out);
- *out = NULL;
- }
- local = wolfSSL_EVP_PKEY_new_ex(heap);
- if (local == NULL) {
- return NULL;
- }
- local->type = type;
- local->pkey_sz = 0;
- local->pkcs8HeaderSz = 0;
- switch (type) {
- #ifndef NO_RSA
- case EVP_PKEY_RSA:
- {
- RsaKey* key;
- local->ownRsa = 1;
- local->rsa = wolfSSL_RSA_new_ex(heap, devId);
- if (local->rsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- key = (RsaKey*)local->rsa->internal;
- #ifdef WOLF_CRYPTO_CB
- key->devId = devId;
- #endif
- (void)key;
- local->rsa->inSet = 1;
- break;
- }
- #endif /* !NO_RSA */
- #ifdef HAVE_ECC
- case EVP_PKEY_EC:
- {
- ecc_key* key;
- local->ownEcc = 1;
- local->ecc = wolfSSL_EC_KEY_new_ex(heap, devId);
- if (local->ecc == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- key = (ecc_key*)local->ecc->internal;
- #ifdef WOLF_CRYPTO_CB
- key->devId = devId;
- #endif
- key->type = ECC_PRIVATEKEY;
- /* key is required to have a key size / curve set, although
- * actual one used is determined by devId callback function */
- wc_ecc_set_curve(key, ECDHE_SIZE, ECC_CURVE_DEF);
- local->ecc->inSet = 1;
- break;
- }
- #endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Unsupported private key id type");
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- if (local != NULL && out != NULL) {
- *out = local;
- }
- return local;
- }
- #endif /* WOLF_PRIVATE_KEY_ID */
- #ifndef NO_CERTS // NOLINT(readability-redundant-preprocessor)
- #ifndef NO_CHECK_PRIVATE_KEY
- /* Check private against public in certificate for match
- *
- * ssl WOLFSSL structure to check private key in
- *
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched. */
- int wolfSSL_check_private_key(const WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- return check_cert_key(ssl->buffers.certificate, ssl->buffers.key, ssl->heap,
- ssl->buffers.keyDevId, ssl->buffers.keyLabel, ssl->buffers.keyId);
- }
- #endif /* !NO_CHECK_PRIVATE_KEY */
- #if defined(OPENSSL_ALL)
- int wolfSSL_ASN1_BIT_STRING_set_bit(WOLFSSL_ASN1_BIT_STRING* str, int pos,
- int val)
- {
- int bytes_cnt, bit;
- byte* temp;
- if (!str || (val != 0 && val != 1) || pos < 0) {
- return WOLFSSL_FAILURE;
- }
- bytes_cnt = pos/8;
- bit = 1<<(7-(pos%8));
- if (bytes_cnt+1 > str->length) {
- if (!(temp = (byte*)XREALLOC(str->data, bytes_cnt+1, NULL,
- DYNAMIC_TYPE_OPENSSL))) {
- return WOLFSSL_FAILURE;
- }
- XMEMSET(temp+str->length, 0, bytes_cnt+1 - str->length);
- str->data = temp;
- str->length = bytes_cnt+1;
- }
- str->data[bytes_cnt] &= ~bit;
- str->data[bytes_cnt] |= val ? bit : 0;
- return WOLFSSL_SUCCESS;
- }
- #endif /* OPENSSL_ALL */
- #endif /* !NO_CERTS */
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void)
- {
- WOLFSSL_ASN1_BIT_STRING* str;
- str = (WOLFSSL_ASN1_BIT_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_BIT_STRING),
- NULL, DYNAMIC_TYPE_OPENSSL);
- if (str) {
- XMEMSET(str, 0, sizeof(WOLFSSL_ASN1_BIT_STRING));
- }
- return str;
- }
- void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING* str)
- {
- if (str) {
- if (str->data) {
- XFREE(str->data, NULL, DYNAMIC_TYPE_OPENSSL);
- str->data = NULL;
- }
- XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- int wolfSSL_ASN1_BIT_STRING_get_bit(const WOLFSSL_ASN1_BIT_STRING* str, int i)
- {
- if (!str || !str->data || str->length <= (i/8) || i < 0) {
- return WOLFSSL_FAILURE;
- }
- return (str->data[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #ifdef OPENSSL_EXTRA
- int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
- {
- WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
- if (ssl == NULL || pkey == NULL ) {
- return WOLFSSL_FAILURE;
- }
- return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
- }
- int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der,
- long derSz)
- {
- WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
- if (ssl == NULL || der == NULL ) {
- return WOLFSSL_FAILURE;
- }
- (void)pri; /* type of private key */
- return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
- }
- /******************************************************************************
- * wolfSSL_CTX_use_PrivateKey_ASN1 - loads a private key buffer into the SSL ctx
- *
- * RETURNS:
- * returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
- */
- int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx,
- unsigned char* der, long derSz)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1");
- if (ctx == NULL || der == NULL ) {
- return WOLFSSL_FAILURE;
- }
- (void)pri; /* type of private key */
- return wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1);
- }
- #ifndef NO_RSA
- int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
- {
- WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
- if (ssl == NULL || der == NULL ) {
- return WOLFSSL_FAILURE;
- }
- return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
- }
- #endif
- int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
- {
- long idx;
- WOLFSSL_ENTER("wolfSSL_use_certificate");
- if (x509 != NULL && ssl != NULL && x509->derCert != NULL) {
- if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length,
- WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0,
- GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- }
- (void)idx;
- return WOLFSSL_FAILURE;
- }
- #endif /* OPENSSL_EXTRA */
- int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der,
- int derSz)
- {
- long idx;
- WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1");
- if (der != NULL && ssl != NULL) {
- if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
- ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- }
- (void)idx;
- return WOLFSSL_FAILURE;
- }
- #ifndef NO_FILESYSTEM
- WOLFSSL_ABI
- int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format)
- {
- WOLFSSL_ENTER("wolfSSL_use_certificate_file");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- if (ProcessFile(ssl->ctx, file, format, CERT_TYPE,
- ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- WOLFSSL_ABI
- int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format)
- {
- WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE,
- ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- WOLFSSL_ABI
- int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file)
- {
- /* process up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE,
- ssl, 1, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
- int format)
- {
- /* process up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1,
- NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* !NO_FILESYSTEM */
- #ifdef HAVE_ECC
- /* Set Temp CTX EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */
- int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz)
- {
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- /* if 0 then get from loaded private key */
- if (sz == 0) {
- /* applies only to ECDSA */
- if (ctx->privateKeyType != ecc_dsa_sa_algo)
- return WOLFSSL_SUCCESS;
- if (ctx->privateKeySz == 0) {
- WOLFSSL_MSG("Must set private key/cert first");
- return BAD_FUNC_ARG;
- }
- sz = (word16)ctx->privateKeySz;
- }
- /* check size */
- if (sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
- return BAD_FUNC_ARG;
- ctx->eccTempKeySz = sz;
- return WOLFSSL_SUCCESS;
- }
- /* Set Temp SSL EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */
- int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- /* check size */
- if (sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
- return BAD_FUNC_ARG;
- ssl->eccTempKeySz = sz;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_ECC */
- #ifdef OPENSSL_EXTRA
- #ifndef NO_FILESYSTEM
- int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
- int format)
- {
- WOLFSSL_ENTER("SSL_CTX_use_RSAPrivateKey_file");
- return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format);
- }
- int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
- {
- WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file");
- return wolfSSL_use_PrivateKey_file(ssl, file, format);
- }
- #endif /* NO_FILESYSTEM */
- /* Copies the master secret over to out buffer. If outSz is 0 returns the size
- * of master secret.
- *
- * ses : a session from completed TLS/SSL handshake
- * out : buffer to hold copy of master secret
- * outSz : size of out buffer
- * returns : number of bytes copied into out buffer on success
- * less then or equal to 0 is considered a failure case
- */
- int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
- unsigned char* out, int outSz)
- {
- int size;
- ses = ClientSessionToSession(ses);
- if (outSz == 0) {
- return SECRET_LEN;
- }
- if (ses == NULL || out == NULL || outSz < 0) {
- return 0;
- }
- if (outSz > SECRET_LEN) {
- size = SECRET_LEN;
- }
- else {
- size = outSz;
- }
- XMEMCPY(out, ses->masterSecret, size);
- return size;
- }
- int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses)
- {
- (void)ses;
- return SECRET_LEN;
- }
- #ifdef WOLFSSL_EARLY_DATA
- unsigned int wolfSSL_SESSION_get_max_early_data(const WOLFSSL_SESSION *session)
- {
- return session->maxEarlyDataSz;
- }
- #endif /* WOLFSSL_EARLY_DATA */
- #endif /* OPENSSL_EXTRA */
- typedef struct {
- byte verifyPeer:1;
- byte verifyNone:1;
- byte failNoCert:1;
- byte failNoCertxPSK:1;
- byte verifyPostHandshake:1;
- } SetVerifyOptions;
- static SetVerifyOptions ModeToVerifyOptions(int mode)
- {
- SetVerifyOptions opts;
- XMEMSET(&opts, 0, sizeof(SetVerifyOptions));
- if (mode != WOLFSSL_VERIFY_DEFAULT) {
- opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE);
- if (!opts.verifyNone) {
- opts.verifyPeer =
- (mode & WOLFSSL_VERIFY_PEER) != 0;
- opts.failNoCertxPSK =
- (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0;
- opts.failNoCert =
- (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0;
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- opts.verifyPostHandshake =
- (mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0;
- #endif
- }
- }
- return opts;
- }
- WOLFSSL_ABI
- void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc)
- {
- SetVerifyOptions opts;
- WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
- if (ctx == NULL)
- return;
- opts = ModeToVerifyOptions(mode);
- ctx->verifyNone = opts.verifyNone;
- ctx->verifyPeer = opts.verifyPeer;
- ctx->failNoCert = opts.failNoCert;
- ctx->failNoCertxPSK = opts.failNoCertxPSK;
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- ctx->verifyPostHandshake = opts.verifyPostHandshake;
- #endif
- ctx->verifyCallback = vc;
- }
- #ifdef OPENSSL_ALL
- void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
- CertVerifyCallback cb, void* arg)
- {
- WOLFSSL_ENTER("SSL_CTX_set_cert_verify_callback");
- if (ctx == NULL)
- return;
- ctx->verifyCertCb = cb;
- ctx->verifyCertCbArg = arg;
- }
- #endif
- void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc)
- {
- SetVerifyOptions opts;
- WOLFSSL_ENTER("wolfSSL_set_verify");
- if (ssl == NULL)
- return;
- opts = ModeToVerifyOptions(mode);
- ssl->options.verifyNone = opts.verifyNone;
- ssl->options.verifyPeer = opts.verifyPeer;
- ssl->options.failNoCert = opts.failNoCert;
- ssl->options.failNoCertxPSK = opts.failNoCertxPSK;
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- ssl->options.verifyPostHandshake = opts.verifyPostHandshake;
- #endif
- ssl->verifyCallback = vc;
- }
- void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
- {
- WOLFSSL_ENTER("wolfSSL_set_verify_result");
- if (ssl == NULL)
- return;
- #ifdef OPENSSL_ALL
- ssl->verifyCallbackResult = v;
- #else
- (void)v;
- WOLFSSL_STUB("wolfSSL_set_verify_result");
- #endif
- }
- #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
- defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- /* For TLS v1.3 send handshake messages after handshake completes. */
- /* Returns 1=WOLFSSL_SUCCESS or 0=WOLFSSL_FAILURE */
- int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl)
- {
- int ret = wolfSSL_request_certificate(ssl);
- if (ret != WOLFSSL_SUCCESS) {
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- /* specific error of wrong version expected */
- WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION);
- }
- else {
- WOLFSSL_ERROR(ret); /* log the error in the error queue */
- }
- }
- return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val)
- {
- int ret = wolfSSL_CTX_allow_post_handshake_auth(ctx);
- if (ret == 0) {
- ctx->postHandshakeAuth = (val != 0);
- }
- return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val)
- {
- int ret = wolfSSL_allow_post_handshake_auth(ssl);
- if (ret == 0) {
- ssl->options.postHandshakeAuth = (val != 0);
- }
- return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- #endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_TLS13 && WOLFSSL_POST_HANDSHAKE_AUTH */
- /* store user ctx for verify callback */
- void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
- if (ssl)
- ssl->verifyCbCtx = ctx;
- }
- /* store user ctx for verify callback */
- void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx");
- if (ctx)
- ctx->verifyCbCtx = userCtx;
- }
- /* store context CA Cache addition callback */
- void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
- {
- if (ctx && ctx->cm)
- ctx->cm->caCacheCallback = cb;
- }
- #if defined(PERSIST_CERT_CACHE)
- #if !defined(NO_FILESYSTEM)
- /* Persist cert cache to file */
- int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
- if (ctx == NULL || fname == NULL)
- return BAD_FUNC_ARG;
- return CM_SaveCertCache(ctx->cm, fname);
- }
- /* Persist cert cache from file */
- int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
- if (ctx == NULL || fname == NULL)
- return BAD_FUNC_ARG;
- return CM_RestoreCertCache(ctx->cm, fname);
- }
- #endif /* NO_FILESYSTEM */
- /* Persist cert cache to memory */
- int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
- int sz, int* used)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
- if (ctx == NULL || mem == NULL || used == NULL || sz <= 0)
- return BAD_FUNC_ARG;
- return CM_MemSaveCertCache(ctx->cm, mem, sz, used);
- }
- /* Restore cert cache from memory */
- int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
- if (ctx == NULL || mem == NULL || sz <= 0)
- return BAD_FUNC_ARG;
- return CM_MemRestoreCertCache(ctx->cm, mem, sz);
- }
- /* get how big the the cert cache save buffer needs to be */
- int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return CM_GetCertCacheMemSize(ctx->cm);
- }
- #endif /* PERSIST_CERT_CACHE */
- #endif /* !NO_CERTS */
- #ifndef NO_SESSION_CACHE
- WOLFSSL_ABI
- WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_get_session");
- if (ssl) {
- #ifdef NO_SESSION_CACHE_REF
- return ssl->session;
- #else
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- /* On the client side we want to return a persistant reference for
- * backwards compatibility. */
- #ifndef NO_CLIENT_CACHE
- if (ssl->clientSession) {
- return (WOLFSSL_SESSION*)ssl->clientSession;
- }
- else {
- /* Try to add a ClientCache entry to associate with the current
- * session. Ignore any session cache options. */
- int err;
- const byte* id = ssl->session->sessionID;
- byte idSz = ssl->session->sessionIDSz;
- if (ssl->session->haveAltSessionID) {
- id = ssl->session->altSessionID;
- idSz = ID_LEN;
- }
- err = AddSessionToCache(ssl->ctx, ssl->session, id, idSz,
- NULL, ssl->session->side,
- #ifdef HAVE_SESSION_TICKET
- ssl->session->ticketLen > 0,
- #else
- 0,
- #endif
- &ssl->clientSession);
- if (err == 0) {
- return (WOLFSSL_SESSION*)ssl->clientSession;
- }
- }
- #endif
- }
- else {
- return ssl->session;
- }
- #endif
- }
- return NULL;
- }
- /* The get1 version requires caller to call SSL_SESSION_free */
- WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl)
- {
- WOLFSSL_SESSION* sess = NULL;
- WOLFSSL_ENTER("SSL_get1_session");
- if (ssl != NULL) {
- sess = ssl->session;
- if (sess != NULL) {
- /* increase reference count if allocated session */
- if (sess->type == WOLFSSL_SESSION_TYPE_HEAP) {
- if (wolfSSL_SESSION_up_ref(sess) != WOLFSSL_SUCCESS)
- sess = NULL;
- }
- }
- }
- return sess;
- }
- /*
- * Sets the session object to use when establishing a TLS/SSL session using
- * the ssl object. Therefore, this function must be called before
- * wolfSSL_connect. The session object to use can be obtained in a previous
- * TLS/SSL connection using wolfSSL_get_session.
- *
- * This function rejects the session if it has been expired when this function
- * is called. Note that this expiration check is wolfSSL specific and differs
- * from OpenSSL return code behavior.
- *
- * By default, wolfSSL_set_session returns WOLFSSL_SUCCESS on successfully
- * setting the session, WOLFSSL_FAILURE on failure due to the session cache
- * being disabled, or the session has expired.
- *
- * To match OpenSSL return code behavior when session is expired, define
- * OPENSSL_EXTRA and WOLFSSL_ERROR_CODE_OPENSSL. This behavior will return
- * WOLFSSL_SUCCESS even when the session is expired and rejected.
- */
- WOLFSSL_ABI
- int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session)
- {
- WOLFSSL_ENTER("SSL_set_session");
- if (session)
- return wolfSSL_SetSession(ssl, session);
- return WOLFSSL_FAILURE;
- }
- #ifndef NO_CLIENT_CACHE
- /* Associate client session with serverID, find existing or store for saving
- if newSession flag on, don't reuse existing session
- WOLFSSL_SUCCESS on ok */
- int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
- {
- WOLFSSL_SESSION* session = NULL;
- WOLFSSL_ENTER("wolfSSL_SetServerID");
- if (ssl == NULL || id == NULL || len <= 0)
- return BAD_FUNC_ARG;
- if (newSession == 0) {
- session = wolfSSL_GetSessionClient(ssl, id, len);
- if (session) {
- if (wolfSSL_SetSession(ssl, session) != WOLFSSL_SUCCESS) {
- #ifdef HAVE_EXT_CACHE
- wolfSSL_FreeSession(ssl->ctx, session);
- #endif
- WOLFSSL_MSG("wolfSSL_SetSession failed");
- session = NULL;
- }
- }
- }
- if (session == NULL) {
- WOLFSSL_MSG("Valid ServerID not cached already");
- ssl->session->idLen = (word16)min(SERVER_ID_LEN, (word32)len);
- XMEMCPY(ssl->session->serverID, id, ssl->session->idLen);
- }
- #ifdef HAVE_EXT_CACHE
- else {
- wolfSSL_FreeSession(ssl->ctx, session);
- }
- #endif
- return WOLFSSL_SUCCESS;
- }
- #endif /* !NO_CLIENT_CACHE */
- #if defined(PERSIST_SESSION_CACHE)
- /* for persistence, if changes to layout need to increment and modify
- save_session_cache() and restore_session_cache and memory versions too */
- #define WOLFSSL_CACHE_VERSION 2
- /* Session Cache Header information */
- typedef struct {
- int version; /* cache layout version id */
- int rows; /* session rows */
- int columns; /* session columns */
- int sessionSz; /* sizeof WOLFSSL_SESSION */
- } cache_header_t;
- /* current persistence layout is:
- 1) cache_header_t
- 2) SessionCache
- 3) ClientCache
- update WOLFSSL_CACHE_VERSION if change layout for the following
- PERSISTENT_SESSION_CACHE functions
- */
- /* get how big the the session cache save buffer needs to be */
- int wolfSSL_get_session_cache_memsize(void)
- {
- int sz = (int)(sizeof(SessionCache) + sizeof(cache_header_t));
- #ifndef NO_CLIENT_CACHE
- sz += (int)(sizeof(ClientCache));
- #endif
- return sz;
- }
- /* Persist session cache to memory */
- int wolfSSL_memsave_session_cache(void* mem, int sz)
- {
- int i;
- cache_header_t cache_header;
- SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header));
- WOLFSSL_ENTER("wolfSSL_memsave_session_cache");
- if (sz < wolfSSL_get_session_cache_memsize()) {
- WOLFSSL_MSG("Memory buffer too small");
- return BUFFER_E;
- }
- cache_header.version = WOLFSSL_CACHE_VERSION;
- cache_header.rows = SESSION_ROWS;
- cache_header.columns = SESSIONS_PER_ROW;
- cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
- XMEMCPY(mem, &cache_header, sizeof(cache_header));
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- if (wc_LockMutex(&session_mutex) != 0) {
- WOLFSSL_MSG("Session cache mutex lock failed");
- return BAD_MUTEX_E;
- }
- #endif
- for (i = 0; i < cache_header.rows; ++i) {
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- if (SESSION_ROW_LOCK(&SessionCache[i]) != 0) {
- WOLFSSL_MSG("Session row cache mutex lock failed");
- return BAD_MUTEX_E;
- }
- #endif
- XMEMCPY(row++, &SessionCache[i], SIZEOF_SESSION_ROW);
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- SESSION_ROW_UNLOCK(&SessionCache[i]);
- #endif
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- wc_UnLockMutex(&session_mutex);
- #endif
- #ifndef NO_CLIENT_CACHE
- if (wc_LockMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Client cache mutex lock failed");
- return BAD_MUTEX_E;
- }
- XMEMCPY(row, ClientCache, sizeof(ClientCache));
- wc_UnLockMutex(&clisession_mutex);
- #endif
- WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- /* Restore the persistent session cache from memory */
- int wolfSSL_memrestore_session_cache(const void* mem, int sz)
- {
- int i;
- cache_header_t cache_header;
- SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header));
- WOLFSSL_ENTER("wolfSSL_memrestore_session_cache");
- if (sz < wolfSSL_get_session_cache_memsize()) {
- WOLFSSL_MSG("Memory buffer too small");
- return BUFFER_E;
- }
- XMEMCPY(&cache_header, mem, sizeof(cache_header));
- if (cache_header.version != WOLFSSL_CACHE_VERSION ||
- cache_header.rows != SESSION_ROWS ||
- cache_header.columns != SESSIONS_PER_ROW ||
- cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
- WOLFSSL_MSG("Session cache header match failed");
- return CACHE_MATCH_ERROR;
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- if (wc_LockMutex(&session_mutex) != 0) {
- WOLFSSL_MSG("Session cache mutex lock failed");
- return BAD_MUTEX_E;
- }
- #endif
- for (i = 0; i < cache_header.rows; ++i) {
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- if (SESSION_ROW_LOCK(&SessionCache[i]) != 0) {
- WOLFSSL_MSG("Session row cache mutex lock failed");
- return BAD_MUTEX_E;
- }
- #endif
- XMEMCPY(&SessionCache[i], row++, SIZEOF_SESSION_ROW);
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- SESSION_ROW_UNLOCK(&SessionCache[i]);
- #endif
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- wc_UnLockMutex(&session_mutex);
- #endif
- #ifndef NO_CLIENT_CACHE
- if (wc_LockMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Client cache mutex lock failed");
- return BAD_MUTEX_E;
- }
- XMEMCPY(ClientCache, row, sizeof(ClientCache));
- wc_UnLockMutex(&clisession_mutex);
- #endif
- WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- #if !defined(NO_FILESYSTEM)
- /* Persist session cache to file */
- /* doesn't use memsave because of additional memory use */
- int wolfSSL_save_session_cache(const char *fname)
- {
- XFILE file;
- int ret;
- int rc = WOLFSSL_SUCCESS;
- int i;
- cache_header_t cache_header;
- WOLFSSL_ENTER("wolfSSL_save_session_cache");
- file = XFOPEN(fname, "w+b");
- if (file == XBADFILE) {
- WOLFSSL_MSG("Couldn't open session cache save file");
- return WOLFSSL_BAD_FILE;
- }
- cache_header.version = WOLFSSL_CACHE_VERSION;
- cache_header.rows = SESSION_ROWS;
- cache_header.columns = SESSIONS_PER_ROW;
- cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
- /* cache header */
- ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file);
- if (ret != 1) {
- WOLFSSL_MSG("Session cache header file write failed");
- XFCLOSE(file);
- return FWRITE_ERROR;
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- if (wc_LockMutex(&session_mutex) != 0) {
- WOLFSSL_MSG("Session cache mutex lock failed");
- XFCLOSE(file);
- return BAD_MUTEX_E;
- }
- #endif
- /* session cache */
- for (i = 0; i < cache_header.rows; ++i) {
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- if (SESSION_ROW_LOCK(&SessionCache[i]) != 0) {
- WOLFSSL_MSG("Session row cache mutex lock failed");
- XFCLOSE(file);
- return BAD_MUTEX_E;
- }
- #endif
- ret = (int)XFWRITE(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file);
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- SESSION_ROW_UNLOCK(&SessionCache[i]);
- #endif
- if (ret != 1) {
- WOLFSSL_MSG("Session cache member file write failed");
- rc = FWRITE_ERROR;
- break;
- }
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- wc_UnLockMutex(&session_mutex);
- #endif
- #ifndef NO_CLIENT_CACHE
- /* client cache */
- if (wc_LockMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Client cache mutex lock failed");
- XFCLOSE(file);
- return BAD_MUTEX_E;
- }
- ret = (int)XFWRITE(ClientCache, sizeof(ClientCache), 1, file);
- if (ret != 1) {
- WOLFSSL_MSG("Client cache member file write failed");
- rc = FWRITE_ERROR;
- }
- wc_UnLockMutex(&clisession_mutex);
- #endif /* !NO_CLIENT_CACHE */
- XFCLOSE(file);
- WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc);
- return rc;
- }
- /* Restore the persistent session cache from file */
- /* doesn't use memstore because of additional memory use */
- int wolfSSL_restore_session_cache(const char *fname)
- {
- XFILE file;
- int rc = WOLFSSL_SUCCESS;
- int ret;
- int i;
- cache_header_t cache_header;
- WOLFSSL_ENTER("wolfSSL_restore_session_cache");
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE) {
- WOLFSSL_MSG("Couldn't open session cache save file");
- return WOLFSSL_BAD_FILE;
- }
- /* cache header */
- ret = (int)XFREAD(&cache_header, sizeof(cache_header), 1, file);
- if (ret != 1) {
- WOLFSSL_MSG("Session cache header file read failed");
- XFCLOSE(file);
- return FREAD_ERROR;
- }
- if (cache_header.version != WOLFSSL_CACHE_VERSION ||
- cache_header.rows != SESSION_ROWS ||
- cache_header.columns != SESSIONS_PER_ROW ||
- cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
- WOLFSSL_MSG("Session cache header match failed");
- XFCLOSE(file);
- return CACHE_MATCH_ERROR;
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- if (wc_LockMutex(&session_mutex) != 0) {
- WOLFSSL_MSG("Session cache mutex lock failed");
- XFCLOSE(file);
- return BAD_MUTEX_E;
- }
- #endif
- /* session cache */
- for (i = 0; i < cache_header.rows; ++i) {
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- if (SESSION_ROW_LOCK(&SessionCache[i]) != 0) {
- WOLFSSL_MSG("Session row cache mutex lock failed");
- XFCLOSE(file);
- return BAD_MUTEX_E;
- }
- #endif
- ret = (int)XFREAD(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file);
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- SESSION_ROW_UNLOCK(&SessionCache[i]);
- #endif
- if (ret != 1) {
- WOLFSSL_MSG("Session cache member file read failed");
- XMEMSET(SessionCache, 0, sizeof SessionCache);
- rc = FREAD_ERROR;
- break;
- }
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- wc_UnLockMutex(&session_mutex);
- #endif
- #ifndef NO_CLIENT_CACHE
- /* client cache */
- if (wc_LockMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Client cache mutex lock failed");
- XFCLOSE(file);
- return BAD_MUTEX_E;
- }
- ret = (int)XFREAD(ClientCache, sizeof(ClientCache), 1, file);
- if (ret != 1) {
- WOLFSSL_MSG("Client cache member file read failed");
- XMEMSET(ClientCache, 0, sizeof ClientCache);
- rc = FREAD_ERROR;
- }
- wc_UnLockMutex(&clisession_mutex);
- #endif /* !NO_CLIENT_CACHE */
- XFCLOSE(file);
- WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc);
- return rc;
- }
- #endif /* !NO_FILESYSTEM */
- #endif /* PERSIST_SESSION_CACHE */
- #endif /* NO_SESSION_CACHE */
- void wolfSSL_load_error_strings(void)
- {
- /* compatibility only */
- }
- int wolfSSL_library_init(void)
- {
- WOLFSSL_ENTER("SSL_library_init");
- if (wolfSSL_Init() == WOLFSSL_SUCCESS)
- return WOLFSSL_SUCCESS;
- else
- return WOLFSSL_FATAL_ERROR;
- }
- #ifdef HAVE_SECRET_CALLBACK
- int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_set_session_secret_cb");
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
- ssl->sessionSecretCb = cb;
- ssl->sessionSecretCtx = ctx;
- if (cb != NULL) {
- /* If using a pre-set key, assume session resumption. */
- ssl->session->sessionIDSz = 0;
- ssl->options.resuming = 1;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif
- #ifndef NO_SESSION_CACHE
- /* on by default if built in but allow user to turn off */
- WOLFSSL_ABI
- long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode)
- {
- WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
- if (mode == WOLFSSL_SESS_CACHE_OFF)
- ctx->sessionCacheOff = 1;
- if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0)
- ctx->sessionCacheFlushOff = 1;
- #ifdef HAVE_EXT_CACHE
- if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0)
- ctx->internalCacheOff = 1;
- if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP) != 0)
- ctx->internalCacheLookupOff = 1;
- #endif
- return WOLFSSL_SUCCESS;
- }
- #endif /* NO_SESSION_CACHE */
- #if !defined(NO_CERTS)
- #if defined(PERSIST_CERT_CACHE)
- #define WOLFSSL_CACHE_CERT_VERSION 1
- typedef struct {
- int version; /* cache cert layout version id */
- int rows; /* hash table rows, CA_TABLE_SIZE */
- int columns[CA_TABLE_SIZE]; /* columns per row on list */
- int signerSz; /* sizeof Signer object */
- } CertCacheHeader;
- /* current cert persistence layout is:
- 1) CertCacheHeader
- 2) caTable
- update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
- PERSIST_CERT_CACHE functions
- */
- /* Return memory needed to persist this signer, have lock */
- static WC_INLINE int GetSignerMemory(Signer* signer)
- {
- int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
- + sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
- #if !defined(NO_SKID)
- sz += (int)sizeof(signer->subjectKeyIdHash);
- #endif
- /* add dynamic bytes needed */
- sz += signer->pubKeySize;
- sz += signer->nameLen;
- return sz;
- }
- /* Return memory needed to persist this row, have lock */
- static WC_INLINE int GetCertCacheRowMemory(Signer* row)
- {
- int sz = 0;
- while (row) {
- sz += GetSignerMemory(row);
- row = row->next;
- }
- return sz;
- }
- /* get the size of persist cert cache, have lock */
- static WC_INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
- {
- int sz;
- int i;
- sz = sizeof(CertCacheHeader);
- for (i = 0; i < CA_TABLE_SIZE; i++)
- sz += GetCertCacheRowMemory(cm->caTable[i]);
- return sz;
- }
- /* Store cert cache header columns with number of items per list, have lock */
- static WC_INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns)
- {
- int i;
- Signer* row;
- for (i = 0; i < CA_TABLE_SIZE; i++) {
- int count = 0;
- row = cm->caTable[i];
- while (row) {
- ++count;
- row = row->next;
- }
- columns[i] = count;
- }
- }
- /* Restore whole cert row from memory, have lock, return bytes consumed,
- < 0 on error, have lock */
- static WC_INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
- int row, int listSz, const byte* end)
- {
- int idx = 0;
- if (listSz < 0) {
- WOLFSSL_MSG("Row header corrupted, negative value");
- return PARSE_ERROR;
- }
- while (listSz) {
- Signer* signer;
- byte* publicKey;
- byte* start = current + idx; /* for end checks on this signer */
- int minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
- sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
- #ifndef NO_SKID
- minSz += (int)sizeof(signer->subjectKeyIdHash);
- #endif
- if (start + minSz > end) {
- WOLFSSL_MSG("Would overread restore buffer");
- return BUFFER_E;
- }
- signer = MakeSigner(cm->heap);
- if (signer == NULL)
- return MEMORY_E;
- /* pubKeySize */
- XMEMCPY(&signer->pubKeySize, current + idx, sizeof(signer->pubKeySize));
- idx += (int)sizeof(signer->pubKeySize);
- /* keyOID */
- XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
- idx += (int)sizeof(signer->keyOID);
- /* publicKey */
- if (start + minSz + signer->pubKeySize > end) {
- WOLFSSL_MSG("Would overread restore buffer");
- FreeSigner(signer, cm->heap);
- return BUFFER_E;
- }
- publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
- DYNAMIC_TYPE_KEY);
- if (publicKey == NULL) {
- FreeSigner(signer, cm->heap);
- return MEMORY_E;
- }
- XMEMCPY(publicKey, current + idx, signer->pubKeySize);
- signer->publicKey = publicKey;
- idx += signer->pubKeySize;
- /* nameLen */
- XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
- idx += (int)sizeof(signer->nameLen);
- /* name */
- if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
- WOLFSSL_MSG("Would overread restore buffer");
- FreeSigner(signer, cm->heap);
- return BUFFER_E;
- }
- signer->name = (char*)XMALLOC(signer->nameLen, cm->heap,
- DYNAMIC_TYPE_SUBJECT_CN);
- if (signer->name == NULL) {
- FreeSigner(signer, cm->heap);
- return MEMORY_E;
- }
- XMEMCPY(signer->name, current + idx, signer->nameLen);
- idx += signer->nameLen;
- /* subjectNameHash */
- XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
- idx += SIGNER_DIGEST_SIZE;
- #ifndef NO_SKID
- /* subjectKeyIdHash */
- XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
- idx += SIGNER_DIGEST_SIZE;
- #endif
- signer->next = cm->caTable[row];
- cm->caTable[row] = signer;
- --listSz;
- }
- return idx;
- }
- /* Store whole cert row into memory, have lock, return bytes added */
- static WC_INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row)
- {
- int added = 0;
- Signer* list = cm->caTable[row];
- while (list) {
- XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
- added += (int)sizeof(list->pubKeySize);
- XMEMCPY(current + added, &list->keyOID, sizeof(list->keyOID));
- added += (int)sizeof(list->keyOID);
- XMEMCPY(current + added, list->publicKey, list->pubKeySize);
- added += list->pubKeySize;
- XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
- added += (int)sizeof(list->nameLen);
- XMEMCPY(current + added, list->name, list->nameLen);
- added += list->nameLen;
- XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
- added += SIGNER_DIGEST_SIZE;
- #ifndef NO_SKID
- XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
- added += SIGNER_DIGEST_SIZE;
- #endif
- list = list->next;
- }
- return added;
- }
- /* Persist cert cache to memory, have lock */
- static WC_INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm,
- void* mem, int sz)
- {
- int realSz;
- int ret = WOLFSSL_SUCCESS;
- int i;
- WOLFSSL_ENTER("DoMemSaveCertCache");
- realSz = GetCertCacheMemSize(cm);
- if (realSz > sz) {
- WOLFSSL_MSG("Mem output buffer too small");
- ret = BUFFER_E;
- }
- else {
- byte* current;
- CertCacheHeader hdr;
- hdr.version = WOLFSSL_CACHE_CERT_VERSION;
- hdr.rows = CA_TABLE_SIZE;
- SetCertHeaderColumns(cm, hdr.columns);
- hdr.signerSz = (int)sizeof(Signer);
- XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
- current = (byte*)mem + sizeof(CertCacheHeader);
- for (i = 0; i < CA_TABLE_SIZE; ++i)
- current += StoreCertRow(cm, current, i);
- }
- return ret;
- }
- #if !defined(NO_FILESYSTEM)
- /* Persist cert cache to file */
- int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
- {
- XFILE file;
- int rc = WOLFSSL_SUCCESS;
- int memSz;
- byte* mem;
- WOLFSSL_ENTER("CM_SaveCertCache");
- file = XFOPEN(fname, "w+b");
- if (file == XBADFILE) {
- WOLFSSL_MSG("Couldn't open cert cache save file");
- return WOLFSSL_BAD_FILE;
- }
- if (wc_LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- XFCLOSE(file);
- return BAD_MUTEX_E;
- }
- memSz = GetCertCacheMemSize(cm);
- mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_MSG("Alloc for tmp buffer failed");
- rc = MEMORY_E;
- } else {
- rc = DoMemSaveCertCache(cm, mem, memSz);
- if (rc == WOLFSSL_SUCCESS) {
- int ret = (int)XFWRITE(mem, memSz, 1, file);
- if (ret != 1) {
- WOLFSSL_MSG("Cert cache file write failed");
- rc = FWRITE_ERROR;
- }
- }
- XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- wc_UnLockMutex(&cm->caLock);
- XFCLOSE(file);
- return rc;
- }
- /* Restore cert cache from file */
- int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
- {
- XFILE file;
- int rc = WOLFSSL_SUCCESS;
- int ret;
- int memSz;
- byte* mem;
- WOLFSSL_ENTER("CM_RestoreCertCache");
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE) {
- WOLFSSL_MSG("Couldn't open cert cache save file");
- return WOLFSSL_BAD_FILE;
- }
- if(XFSEEK(file, 0, XSEEK_END) != 0) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- memSz = (int)XFTELL(file);
- XREWIND(file);
- if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz <= 0) {
- WOLFSSL_MSG("CM_RestoreCertCache file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_MSG("Alloc for tmp buffer failed");
- XFCLOSE(file);
- return MEMORY_E;
- }
- ret = (int)XFREAD(mem, memSz, 1, file);
- if (ret != 1) {
- WOLFSSL_MSG("Cert file read error");
- rc = FREAD_ERROR;
- } else {
- rc = CM_MemRestoreCertCache(cm, mem, memSz);
- if (rc != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Mem restore cert cache failed");
- }
- }
- XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFCLOSE(file);
- return rc;
- }
- #endif /* NO_FILESYSTEM */
- /* Persist cert cache to memory */
- int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("CM_MemSaveCertCache");
- if (wc_LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- return BAD_MUTEX_E;
- }
- ret = DoMemSaveCertCache(cm, mem, sz);
- if (ret == WOLFSSL_SUCCESS)
- *used = GetCertCacheMemSize(cm);
- wc_UnLockMutex(&cm->caLock);
- return ret;
- }
- /* Restore cert cache from memory */
- int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
- {
- int ret = WOLFSSL_SUCCESS;
- int i;
- CertCacheHeader* hdr = (CertCacheHeader*)mem;
- byte* current = (byte*)mem + sizeof(CertCacheHeader);
- byte* end = (byte*)mem + sz; /* don't go over */
- WOLFSSL_ENTER("CM_MemRestoreCertCache");
- if (current > end) {
- WOLFSSL_MSG("Cert Cache Memory buffer too small");
- return BUFFER_E;
- }
- if (hdr->version != WOLFSSL_CACHE_CERT_VERSION ||
- hdr->rows != CA_TABLE_SIZE ||
- hdr->signerSz != (int)sizeof(Signer)) {
- WOLFSSL_MSG("Cert Cache Memory header mismatch");
- return CACHE_MATCH_ERROR;
- }
- if (wc_LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- return BAD_MUTEX_E;
- }
- FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
- for (i = 0; i < CA_TABLE_SIZE; ++i) {
- int added = RestoreCertRow(cm, current, i, hdr->columns[i], end);
- if (added < 0) {
- WOLFSSL_MSG("RestoreCertRow error");
- ret = added;
- break;
- }
- current += added;
- }
- wc_UnLockMutex(&cm->caLock);
- return ret;
- }
- /* get how big the the cert cache save buffer needs to be */
- int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
- {
- int sz;
- WOLFSSL_ENTER("CM_GetCertCacheMemSize");
- if (wc_LockMutex(&cm->caLock) != 0) {
- WOLFSSL_MSG("wc_LockMutex on caLock failed");
- return BAD_MUTEX_E;
- }
- sz = GetCertCacheMemSize(cm);
- wc_UnLockMutex(&cm->caLock);
- return sz;
- }
- #endif /* PERSIST_CERT_CACHE */
- #endif /* NO_CERTS */
- #ifdef OPENSSL_EXTRA
- /*
- * build enabled cipher list w/ TLS13 or w/o TLS13 suites
- * @param ctx a pointer to WOLFSSL_CTX structure
- * @param suites currently enabled suites
- * @param onlytlsv13suites flag whether correcting w/ TLS13 suites
- * or w/o TLS13 suties
- * @param list suites list that user wants to update
- * @return suites list on success, otherwise NULL
- */
- static char* buildEnabledCipherList(WOLFSSL_CTX* ctx, Suites* suites,
- int tls13Only, const char* list)
- {
- word32 idx = 0;
- word32 listsz = 0;
- word32 len = 0;
- word32 ianasz = 0;
- const char* enabledcs = NULL;
- char* locallist = NULL;
- char* head = NULL;
- byte cipherSuite0;
- byte cipherSuite;
- /* sanity check */
- if (ctx == NULL || suites == NULL || list == NULL)
- return NULL;
- if (!suites->setSuites)
- return NULL;
- listsz = (word32)XSTRLEN(list);
- /* calculate necessary buffer length */
- for(idx = 0; idx < suites->suiteSz; idx++) {
- cipherSuite0 = suites->suites[idx];
- cipherSuite = suites->suites[++idx];
- if (tls13Only && cipherSuite0 == TLS13_BYTE) {
- enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite);
- }
- else if (!tls13Only && cipherSuite0 != TLS13_BYTE) {
- enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite);
- }
- else
- continue;
- if (XSTRCMP(enabledcs, "None") != 0) {
- len += (word32)XSTRLEN(enabledcs) + 2;
- }
- }
- len += listsz + 2;
- /* build string */
- if (len > (listsz + 2)) {
- locallist = (char*)XMALLOC(len, ctx->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- /* sanity check */
- if (!locallist)
- return NULL;
- XMEMSET(locallist, 0, len);
- head = locallist;
- if (!tls13Only)
- {
- /* always tls13 suites in the head position */
- XSTRNCPY(locallist, list, len);
- locallist += listsz;
- *locallist++ = ':';
- *locallist = 0;
- len -= listsz + 1;
- }
- for(idx = 0; idx < suites->suiteSz; idx++) {
- cipherSuite0 = suites->suites[idx];
- cipherSuite = suites->suites[++idx];
- if (tls13Only && cipherSuite0 == TLS13_BYTE) {
- enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite);
- }
- else if (!tls13Only && cipherSuite0 != TLS13_BYTE) {
- enabledcs = GetCipherNameInternal(cipherSuite0, cipherSuite);
- }
- else
- continue;
- ianasz = (int)XSTRLEN(enabledcs);
- if (ianasz + 1 < len) {
- XSTRNCPY(locallist, enabledcs, len);
- locallist += ianasz;
- *locallist++ = ':';
- *locallist = 0;
- len -= ianasz + 1;
- }
- else{
- XFREE(locallist, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- }
- if (tls13Only) {
- XSTRNCPY(locallist, list, len);
- locallist += listsz;
- *locallist = 0;
- }
- return head;
- }
- else
- return NULL;
- }
- /*
- * check if the list has TLS13 and pre-TLS13 suites
- * @param list cipher suite list that user want to set
- * @return mixed: 0, only pre-TLS13: 1, only TLS13: 2
- */
- static int CheckcipherList(const char* list)
- {
- int ret;
- int findTLSv13Suites = 0;
- int findbeforeSuites = 0;
- byte cipherSuite0;
- byte cipherSuite1;
- int flags;
- char* next = (char*)list;
- do {
- char* current = next;
- char name[MAX_SUITE_NAME + 1];
- word32 length = MAX_SUITE_NAME;
- word32 current_length;
- next = XSTRSTR(next, ":");
- current_length = (!next) ? (word32)XSTRLEN(current)
- : (word32)(next - current);
- if (current_length < length) {
- length = current_length;
- }
- XMEMCPY(name, current, length);
- name[length] = 0;
- ret = wolfSSL_get_cipher_suite_from_name(name, &cipherSuite0,
- &cipherSuite1, &flags);
- if (ret == 0) {
- if (cipherSuite0 == TLS13_BYTE) {
- /* TLSv13 suite */
- findTLSv13Suites = 1;
- break;
- }
- else {
- findbeforeSuites = 1;
- break;
- }
- }
- if (findTLSv13Suites == 1 && findbeforeSuites == 1) {
- /* list has mixed suites */
- return 0;
- }
- } while (next++); /* ++ needed to skip ':' */
- if (findTLSv13Suites == 0 && findbeforeSuites == 1) {
- return 1;/* only before TLSv13 suites */
- }
- else if (findTLSv13Suites == 1 && findbeforeSuites == 0) {
- return 2;/* only TLSv13 suties */
- }
- else {
- return 0;/* handle as mixed */
- }
- }
- /* parse some bulk lists like !eNULL / !aNULL
- *
- * returns WOLFSSL_SUCCESS on success and sets the cipher suite list
- */
- static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, Suites* suites,
- const char* list)
- {
- int ret = 0;
- int listattribute = 0;
- char* buildcipherList = NULL;
- int tls13Only = 0;
- if (suites == NULL || list == NULL) {
- WOLFSSL_MSG("NULL argument");
- return WOLFSSL_FAILURE;
- }
- listattribute = CheckcipherList(list);
- if (listattribute == 0) {
- /* list has mixed(pre-TLSv13 and TLSv13) suites
- * update cipher suites the same as before
- */
- return (SetCipherList(ctx, suites, list)) ? WOLFSSL_SUCCESS :
- WOLFSSL_FAILURE;
- }
- else if (listattribute == 1) {
- /* list has only pre-TLSv13 suites.
- * Only update before TLSv13 suites.
- */
- tls13Only = 1;
- }
- else if (listattribute == 2) {
- /* list has only TLSv13 suites. Only update TLv13 suites
- * simulate set_ciphersuites() compatibility layer API
- */
- tls13Only = 0;
- }
- buildcipherList = buildEnabledCipherList(ctx, ctx->suites,
- tls13Only, list);
- if (buildcipherList) {
- ret = SetCipherList(ctx, suites, buildcipherList);
- XFREE(buildcipherList, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- else {
- ret = SetCipherList(ctx, suites, list);
- }
- return ret;
- }
- #endif
- int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list");
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
- /* alloc/init on demand only */
- if (ctx->suites == NULL) {
- ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap,
- DYNAMIC_TYPE_SUITES);
- if (ctx->suites == NULL) {
- WOLFSSL_MSG("Memory alloc for Suites failed");
- return WOLFSSL_FAILURE;
- }
- XMEMSET(ctx->suites, 0, sizeof(Suites));
- }
- #ifdef OPENSSL_EXTRA
- return wolfSSL_parse_cipher_list(ctx, ctx->suites, list);
- #else
- return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- #endif
- }
- int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list)
- {
- WOLFSSL_ENTER("wolfSSL_set_cipher_list");
- #ifdef SINGLE_THREADED
- if (ssl->ctx->suites == ssl->suites) {
- ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
- DYNAMIC_TYPE_SUITES);
- if (ssl->suites == NULL) {
- WOLFSSL_MSG("Suites Memory error");
- return MEMORY_E;
- }
- *ssl->suites = *ssl->ctx->suites;
- ssl->options.ownSuites = 1;
- }
- #endif
- #ifdef OPENSSL_EXTRA
- return wolfSSL_parse_cipher_list(ssl->ctx, ssl->suites, list);
- #else
- return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- #endif
- }
- #ifdef HAVE_KEYING_MATERIAL
- #define TLS_PRF_LABEL_CLIENT_FINISHED "client finished"
- #define TLS_PRF_LABEL_SERVER_FINISHED "server finished"
- #define TLS_PRF_LABEL_MASTER_SECRET "master secret"
- #define TLS_PRF_LABEL_EXT_MASTER_SECRET "extended master secret"
- #define TLS_PRF_LABEL_KEY_EXPANSION "key expansion"
- static const struct ForbiddenLabels {
- const char* label;
- size_t labelLen;
- } forbiddenLabels[] = {
- {TLS_PRF_LABEL_CLIENT_FINISHED, XSTR_SIZEOF(TLS_PRF_LABEL_CLIENT_FINISHED)},
- {TLS_PRF_LABEL_SERVER_FINISHED, XSTR_SIZEOF(TLS_PRF_LABEL_SERVER_FINISHED)},
- {TLS_PRF_LABEL_MASTER_SECRET, XSTR_SIZEOF(TLS_PRF_LABEL_MASTER_SECRET)},
- {TLS_PRF_LABEL_EXT_MASTER_SECRET, XSTR_SIZEOF(TLS_PRF_LABEL_EXT_MASTER_SECRET)},
- {TLS_PRF_LABEL_KEY_EXPANSION, XSTR_SIZEOF(TLS_PRF_LABEL_KEY_EXPANSION)},
- {NULL, 0},
- };
- /**
- * Implement RFC 5705
- * TLS 1.3 uses a different exporter definition (section 7.5 of RFC 8446)
- * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error
- */
- int wolfSSL_export_keying_material(WOLFSSL *ssl,
- unsigned char *out, size_t outLen,
- const char *label, size_t labelLen,
- const unsigned char *context, size_t contextLen,
- int use_context)
- {
- byte* seed = NULL;
- word32 seedLen;
- const struct ForbiddenLabels* fl;
- WOLFSSL_ENTER("wolfSSL_export_keying_material");
- if (ssl == NULL || out == NULL || label == NULL ||
- (use_context && contextLen && context == NULL)) {
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
- }
- /* clientRandom + serverRandom
- * OR
- * clientRandom + serverRandom + ctx len encoding + ctx */
- seedLen = !use_context ? (word32)SEED_LEN :
- (word32)SEED_LEN + 2 + (word32)contextLen;
- if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
- WOLFSSL_MSG("To export keying material wolfSSL needs to keep handshake "
- "data. Call wolfSSL_KeepArrays before attempting to "
- "export keyid material.");
- return WOLFSSL_FAILURE;
- }
- /* check forbidden labels */
- for (fl = &forbiddenLabels[0]; fl->label != NULL; fl++) {
- if (labelLen >= fl->labelLen &&
- XMEMCMP(label, fl->label, fl->labelLen) == 0) {
- WOLFSSL_MSG("Forbidden label");
- return WOLFSSL_FAILURE;
- }
- }
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- /* Path for TLS 1.3 */
- if (!use_context) {
- contextLen = 0;
- context = (byte*)""; /* Give valid pointer for 0 length memcpy */
- }
- if (Tls13_Exporter(ssl, out, (word32)outLen, label, labelLen,
- context, contextLen) != 0) {
- WOLFSSL_MSG("Tls13_Exporter error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif
- /* Path for <=TLS 1.2 */
- seed = (byte*)XMALLOC(seedLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (seed == NULL) {
- WOLFSSL_MSG("malloc error");
- return WOLFSSL_FAILURE;
- }
- XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
- if (use_context) {
- /* Encode len in big endian */
- seed[SEED_LEN ] = (contextLen >> 8) & 0xFF;
- seed[SEED_LEN + 1] = (contextLen) & 0xFF;
- if (contextLen) {
- /* 0 length context is allowed */
- XMEMCPY(seed + SEED_LEN + 2, context, contextLen);
- }
- }
- PRIVATE_KEY_UNLOCK();
- if (wc_PRF_TLS(out, (word32)outLen, ssl->arrays->masterSecret, SECRET_LEN,
- (byte*)label, (word32)labelLen, seed, seedLen, IsAtLeastTLSv1_2(ssl),
- ssl->specs.mac_algorithm, ssl->heap, ssl->devId) != 0) {
- WOLFSSL_MSG("wc_PRF_TLS error");
- PRIVATE_KEY_LOCK();
- XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_FAILURE;
- }
- PRIVATE_KEY_LOCK();
- XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_KEYING_MATERIAL */
- int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
- {
- int useNb = 0;
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
- if (ssl->options.dtls) {
- #ifdef WOLFSSL_DTLS
- useNb = ssl->options.dtlsUseNonblock;
- #endif
- }
- else {
- WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
- "DEPRECATED for non-DTLS use.");
- }
- return useNb;
- }
- #ifndef WOLFSSL_LEANPSK
- void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
- {
- (void)nonblock;
- WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
- if (ssl == NULL)
- return;
- if (ssl->options.dtls) {
- #ifdef WOLFSSL_DTLS
- ssl->options.dtlsUseNonblock = (nonblock != 0);
- #endif
- }
- else {
- WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
- "DEPRECATED for non-DTLS use.");
- }
- }
- #ifdef WOLFSSL_DTLS
- int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
- {
- int timeout = 0;
- if (ssl)
- timeout = ssl->dtls_timeout;
- WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout()", timeout);
- return timeout;
- }
- #ifdef WOLFSSL_DTLS13
- /*
- * This API returns 1 when the user should set a short timeout for receiving
- * data. It is recommended that it is at most 1/4 the value returned by
- * wolfSSL_dtls_get_current_timeout().
- */
- int wolfSSL_dtls13_use_quick_timeout(WOLFSSL* ssl)
- {
- return ssl->dtls13FastTimeout;
- }
- /*
- * When this is set, a DTLS 1.3 connection will send acks immediately when a
- * disruption is detected to shortcut timeouts. This results in potentially
- * more traffic but may make the handshake quicker.
- */
- void wolfSSL_dtls13_set_send_more_acks(WOLFSSL* ssl, int value)
- {
- if (ssl != NULL)
- ssl->options.dtls13SendMoreAcks = !!value;
- }
- #endif /* WOLFSSL_DTLS13 */
- int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, WOLFSSL_TIMEVAL* timeleft)
- {
- if (ssl && timeleft) {
- XMEMSET(timeleft, 0, sizeof(WOLFSSL_TIMEVAL));
- timeleft->tv_sec = ssl->dtls_timeout;
- }
- return 0;
- }
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl)
- {
- WOLFSSL_STUB("SSL_DTLSv1_handle_timeout");
- (void)ssl;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl, word32 duration_ms)
- {
- WOLFSSL_STUB("SSL_DTLSv1_set_initial_timeout_duration");
- (void)ssl;
- (void)duration_ms;
- }
- #endif
- /* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */
- int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout)
- {
- if (ssl == NULL || timeout < 0)
- return BAD_FUNC_ARG;
- if (timeout > ssl->dtls_timeout_max) {
- WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max");
- return BAD_FUNC_ARG;
- }
- ssl->dtls_timeout_init = timeout;
- ssl->dtls_timeout = timeout;
- return WOLFSSL_SUCCESS;
- }
- /* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */
- int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
- {
- if (ssl == NULL || timeout < 0)
- return BAD_FUNC_ARG;
- if (timeout < ssl->dtls_timeout_init) {
- WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init");
- return BAD_FUNC_ARG;
- }
- ssl->dtls_timeout_max = timeout;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
- {
- int result = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_dtls_got_timeout()");
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
- #ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
- result = Dtls13RtxTimeout(ssl);
- if (result < 0) {
- if (result == WANT_WRITE)
- ssl->dtls13SendingAckOrRtx = 1;
- ssl->error = result;
- WOLFSSL_ERROR(result);
- return WOLFSSL_FATAL_ERROR;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_DTLS13 */
- if ((IsSCR(ssl) || !ssl->options.handShakeDone)) {
- if (DtlsMsgPoolTimeout(ssl) < 0){
- ssl->error = SOCKET_ERROR_E;
- WOLFSSL_ERROR(ssl->error);
- result = WOLFSSL_FATAL_ERROR;
- }
- else if ((result = DtlsMsgPoolSend(ssl, 0)) < 0) {
- ssl->error = result;
- WOLFSSL_ERROR(result);
- result = WOLFSSL_FATAL_ERROR;
- }
- else {
- /* Reset return value to success */
- result = WOLFSSL_SUCCESS;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout()", result);
- return result;
- }
- /* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */
- int wolfSSL_dtls_retransmit(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_dtls_retransmit()");
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
- if (!ssl->options.handShakeDone) {
- int result = DtlsMsgPoolSend(ssl, 0);
- if (result < 0) {
- ssl->error = result;
- WOLFSSL_ERROR(result);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- return 0;
- }
- #endif /* DTLS */
- #endif /* LEANPSK */
- #if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
- /* Not an SSL function, return 0 for success, error code otherwise */
- /* Prereq: ssl's RNG needs to be initialized. */
- int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
- const byte* secret, word32 secretSz)
- {
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
- if (ssl == NULL) {
- WOLFSSL_MSG("need a SSL object");
- return BAD_FUNC_ARG;
- }
- if (secret != NULL && secretSz == 0) {
- WOLFSSL_MSG("can't have a new secret without a size");
- return BAD_FUNC_ARG;
- }
- /* If secretSz is 0, use the default size. */
- if (secretSz == 0)
- secretSz = COOKIE_SECRET_SZ;
- if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
- byte* newSecret;
- if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
- ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
- ssl->buffers.dtlsCookieSecret.length);
- XFREE(ssl->buffers.dtlsCookieSecret.buffer,
- ssl->heap, DYNAMIC_TYPE_NONE);
- }
- newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD);
- if (newSecret == NULL) {
- ssl->buffers.dtlsCookieSecret.buffer = NULL;
- ssl->buffers.dtlsCookieSecret.length = 0;
- WOLFSSL_MSG("couldn't allocate new cookie secret");
- return MEMORY_ERROR;
- }
- ssl->buffers.dtlsCookieSecret.buffer = newSecret;
- ssl->buffers.dtlsCookieSecret.length = secretSz;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("wolfSSL_DTLS_SetCookieSecret secret",
- ssl->buffers.dtlsCookieSecret.buffer,
- ssl->buffers.dtlsCookieSecret.length);
- #endif
- }
- /* If the supplied secret is NULL, randomly generate a new secret. */
- if (secret == NULL) {
- ret = wc_RNG_GenerateBlock(ssl->rng,
- ssl->buffers.dtlsCookieSecret.buffer, secretSz);
- }
- else
- XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
- WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
- return ret;
- }
- #endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
- /* EITHER SIDE METHODS */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
- WOLFSSL_METHOD* wolfSSLv23_method(void)
- {
- return wolfSSLv23_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m = NULL;
- WOLFSSL_ENTER("SSLv23_method");
- #if !defined(NO_WOLFSSL_CLIENT)
- m = wolfSSLv23_client_method_ex(heap);
- #elif !defined(NO_WOLFSSL_SERVER)
- m = wolfSSLv23_server_method_ex(heap);
- #else
- (void)heap;
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #ifdef WOLFSSL_ALLOW_SSLV3
- WOLFSSL_METHOD* wolfSSLv3_method(void)
- {
- return wolfSSLv3_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m = NULL;
- WOLFSSL_ENTER("SSLv3_method");
- #if !defined(NO_WOLFSSL_CLIENT)
- m = wolfSSLv3_client_method_ex(heap);
- #elif !defined(NO_WOLFSSL_SERVER)
- m = wolfSSLv3_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #endif
- #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
- /* client only parts */
- #ifndef NO_WOLFSSL_CLIENT
- #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS)
- WOLFSSL_METHOD* wolfSSLv2_client_method(void)
- {
- WOLFSSL_STUB("wolfSSLv2_client_method");
- return NULL;
- }
- #endif
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- WOLFSSL_METHOD* wolfSSLv3_client_method(void)
- {
- return wolfSSLv3_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("SSLv3_client_method_ex");
- if (method)
- InitSSL_Method(method, MakeSSLv3());
- return method;
- }
- #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
- WOLFSSL_METHOD* wolfSSLv23_client_method(void)
- {
- return wolfSSLv23_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("SSLv23_client_method_ex");
- if (method) {
- #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
- #if defined(WOLFSSL_TLS13)
- InitSSL_Method(method, MakeTLSv1_3());
- #elif !defined(WOLFSSL_NO_TLS12)
- InitSSL_Method(method, MakeTLSv1_2());
- #elif !defined(NO_OLD_TLS)
- InitSSL_Method(method, MakeTLSv1_1());
- #endif
- #else
- #ifndef NO_OLD_TLS
- InitSSL_Method(method, MakeTLSv1_1());
- #endif
- #endif
- #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
- method->downgrade = 1;
- #endif
- }
- return method;
- }
- /* please see note at top of README if you get an error from connect */
- WOLFSSL_ABI
- int wolfSSL_connect(WOLFSSL* ssl)
- {
- #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
- int neededState;
- byte advanceState;
- #endif
- int ret = 0;
- (void)ret;
- #ifdef HAVE_ERRNO_H
- errno = 0;
- #endif
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
- if (ssl->options.side == WOLFSSL_NEITHER_END) {
- ssl->error = InitSSL_Side(ssl, WOLFSSL_CLIENT_END);
- if (ssl->error != WOLFSSL_SUCCESS) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->error = 0; /* expected to be zero here */
- }
- #ifdef OPENSSL_EXTRA
- if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_ST_CONNECT, WOLFSSL_SUCCESS);
- ssl->cbmode = SSL_CB_WRITE;
- }
- #endif
- #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
- #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)
- return wolfSSL_connect_TLSv13(ssl);
- #else
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3)
- return wolfSSL_connect_TLSv13(ssl);
- #endif
- WOLFSSL_ENTER("SSL_connect()");
- /* make sure this wolfSSL object has arrays and rng setup. Protects
- * case where the WOLFSSL object is re-used via wolfSSL_clear() */
- if ((ret = ReinitSSL(ssl, ssl->ctx, 0)) != 0) {
- return ret;
- }
- #ifdef WOLFSSL_WOLFSENTRY_HOOKS
- if ((ssl->ConnectFilter != NULL) &&
- (ssl->options.connectState == CONNECT_BEGIN)) {
- wolfSSL_netfilter_decision_t res;
- if ((ssl->ConnectFilter(ssl, ssl->ConnectFilter_arg, &res) ==
- WOLFSSL_SUCCESS) &&
- (res == WOLFSSL_NETFILTER_REJECT)) {
- ssl->error = SOCKET_FILTERED_E;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif /* WOLFSSL_WOLFSENTRY_HOOKS */
- if (ssl->options.side != WOLFSSL_CLIENT_END) {
- ssl->error = SIDE_ERROR;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- #ifdef WOLFSSL_DTLS
- if (ssl->version.major == DTLS_MAJOR) {
- ssl->options.dtls = 1;
- ssl->options.tls = 1;
- ssl->options.tls1_1 = 1;
- }
- #endif
- /* fragOffset is non-zero when sending fragments. On the last
- * fragment, fragOffset is zero again, and the state can be
- * advanced. */
- advanceState = ssl->fragOffset == 0 &&
- (ssl->options.connectState == CONNECT_BEGIN ||
- ssl->options.connectState == HELLO_AGAIN ||
- (ssl->options.connectState >= FIRST_REPLY_DONE &&
- ssl->options.connectState <= FIRST_REPLY_FOURTH));
- #ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
- advanceState = advanceState && !ssl->dtls13SendingAckOrRtx;
- #endif /* WOLFSSL_DTLS13 */
- if (ssl->buffers.outputBuffer.length > 0
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* do not send buffered or advance state if last error was an
- async pending operation */
- && ssl->error != WC_PENDING_E
- #endif
- ) {
- ret = SendBuffered(ssl);
- if (ret == 0) {
- if (ssl->fragOffset == 0 && !ssl->options.buildingMsg) {
- if (advanceState) {
- ssl->options.connectState++;
- WOLFSSL_MSG("connect state: "
- "Advanced from last buffered fragment send");
- #ifdef WOLFSSL_ASYNC_IO
- /* Cleanup async */
- FreeAsyncCtx(ssl, 0);
- #endif
- }
- }
- else {
- WOLFSSL_MSG("connect state: "
- "Not advanced, more fragments to send");
- }
- }
- else {
- ssl->error = ret;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- ret = RetrySendAlert(ssl);
- if (ret != 0) {
- ssl->error = ret;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- switch (ssl->options.connectState) {
- case CONNECT_BEGIN :
- /* always send client hello first */
- if ( (ssl->error = SendClientHello(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.connectState = CLIENT_HELLO_SENT;
- WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
- FALL_THROUGH;
- case CLIENT_HELLO_SENT :
- neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE :
- SERVER_HELLODONE_COMPLETE;
- #ifdef WOLFSSL_DTLS
- /* In DTLS, when resuming, we can go straight to FINISHED,
- * or do a cookie exchange and then skip to FINISHED, assume
- * we need the cookie exchange first. */
- if (IsDtlsNotSctpMode(ssl))
- neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
- #endif
- /* get response */
- while (ssl->options.serverState < neededState) {
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3)
- return wolfSSL_connect_TLSv13(ssl);
- #endif
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- /* if resumption failed, reset needed state */
- else if (neededState == SERVER_FINISHED_COMPLETE)
- if (!ssl->options.resuming) {
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl))
- neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
- else
- #endif
- neededState = SERVER_HELLODONE_COMPLETE;
- }
- #ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)
- && ssl->dtls13Rtx.sendAcks == 1) {
- ssl->dtls13Rtx.sendAcks = 0;
- /* we aren't negotiated the version yet, so we aren't sure
- * the other end can speak v1.3. On the other side we have
- * received a unified records, assuming that the
- * ServerHello got lost, we will send an empty ACK. In case
- * the server is a DTLS with version less than 1.3, it
- * should just ignore the message */
- if ((ssl->error = SendDtls13Ack(ssl)) < 0) {
- if (ssl->error == WANT_WRITE)
- ssl->dtls13SendingAckOrRtx = 1;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif /* WOLFSSL_DTLS13 */
- }
- ssl->options.connectState = HELLO_AGAIN;
- WOLFSSL_MSG("connect state: HELLO_AGAIN");
- FALL_THROUGH;
- case HELLO_AGAIN :
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3)
- return wolfSSL_connect_TLSv13(ssl);
- #endif
- #ifdef WOLFSSL_DTLS
- if (ssl->options.serverState ==
- SERVER_HELLOVERIFYREQUEST_COMPLETE) {
- if (IsDtlsNotSctpMode(ssl)) {
- /* re-init hashes, exclude first hello and verify request */
- if ((ssl->error = InitHandshakeHashes(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- if ( (ssl->error = SendClientHello(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- }
- #endif
- ssl->options.connectState = HELLO_AGAIN_REPLY;
- WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
- FALL_THROUGH;
- case HELLO_AGAIN_REPLY :
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl)) {
- neededState = ssl->options.resuming ?
- SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
- /* get response */
- while (ssl->options.serverState < neededState) {
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- /* if resumption failed, reset needed state */
- if (neededState == SERVER_FINISHED_COMPLETE) {
- if (!ssl->options.resuming)
- neededState = SERVER_HELLODONE_COMPLETE;
- }
- }
- }
- #endif
- ssl->options.connectState = FIRST_REPLY_DONE;
- WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
- FALL_THROUGH;
- case FIRST_REPLY_DONE :
- if (ssl->options.certOnly)
- return WOLFSSL_SUCCESS;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3)
- return wolfSSL_connect_TLSv13(ssl);
- #endif
- if (ssl->options.sendVerify) {
- if ( (ssl->error = SendCertificate(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_MSG("sent: certificate");
- }
- #endif
- ssl->options.connectState = FIRST_REPLY_FIRST;
- WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
- FALL_THROUGH;
- case FIRST_REPLY_FIRST :
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3)
- return wolfSSL_connect_TLSv13(ssl);
- #endif
- if (!ssl->options.resuming) {
- if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_MSG("sent: client key exchange");
- }
- ssl->options.connectState = FIRST_REPLY_SECOND;
- WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
- FALL_THROUGH;
- #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
- case FIRST_REPLY_SECOND :
- /* CLIENT: Fail-safe for Server Authentication. */
- if (!ssl->options.peerAuthGood) {
- WOLFSSL_MSG("Server authentication did not happen");
- ssl->error = NO_PEER_VERIFY;
- return WOLFSSL_FATAL_ERROR;
- }
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
- if (ssl->options.sendVerify) {
- if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_MSG("sent: certificate verify");
- }
- #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
- ssl->options.connectState = FIRST_REPLY_THIRD;
- WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
- FALL_THROUGH;
- case FIRST_REPLY_THIRD :
- if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_MSG("sent: change cipher spec");
- ssl->options.connectState = FIRST_REPLY_FOURTH;
- WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
- FALL_THROUGH;
- case FIRST_REPLY_FOURTH :
- if ( (ssl->error = SendFinished(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_MSG("sent: finished");
- ssl->options.connectState = FINISHED_DONE;
- WOLFSSL_MSG("connect state: FINISHED_DONE");
- FALL_THROUGH;
- #ifdef WOLFSSL_DTLS13
- case WAIT_FINISHED_ACK:
- ssl->options.connectState = FINISHED_DONE;
- FALL_THROUGH;
- #endif /* WOLFSSL_DTLS13 */
- case FINISHED_DONE :
- /* get response */
- while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.connectState = SECOND_REPLY_DONE;
- WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
- FALL_THROUGH;
- case SECOND_REPLY_DONE:
- #ifndef NO_HANDSHAKE_DONE_CB
- if (ssl->hsDoneCb) {
- int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
- if (cbret < 0) {
- ssl->error = cbret;
- WOLFSSL_MSG("HandShake Done Cb don't continue error");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif /* NO_HANDSHAKE_DONE_CB */
- if (!ssl->options.dtls) {
- if (!ssl->options.keepResources) {
- FreeHandshakeResources(ssl);
- }
- }
- #ifdef WOLFSSL_DTLS
- else {
- ssl->options.dtlsHsRetain = 1;
- }
- #endif /* WOLFSSL_DTLS */
- #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SECURE_RENEGOTIATION)
- /* This may be necessary in async so that we don't try to
- * renegotiate again */
- if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
- ssl->secure_renegotiation->startScr = 0;
- }
- #endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */
- #if defined(WOLFSSL_ASYNC_IO) && !defined(WOLFSSL_ASYNC_CRYPT)
- /* Free the remaining async context if not using it for crypto */
- FreeAsyncCtx(ssl, 1);
- #endif
- ssl->error = 0; /* clear the error */
- WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */
- default:
- WOLFSSL_MSG("Unknown connect state ERROR");
- return WOLFSSL_FATAL_ERROR; /* unknown connect state */
- }
- #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS || !WOLFSSL_TLS13 */
- }
- #endif /* NO_WOLFSSL_CLIENT */
- /* server only parts */
- #ifndef NO_WOLFSSL_SERVER
- #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS)
- WOLFSSL_METHOD* wolfSSLv2_server_method(void)
- {
- WOLFSSL_STUB("wolfSSLv2_server_method");
- return 0;
- }
- #endif
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- WOLFSSL_METHOD* wolfSSLv3_server_method(void)
- {
- return wolfSSLv3_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("SSLv3_server_method_ex");
- if (method) {
- InitSSL_Method(method, MakeSSLv3());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
- WOLFSSL_METHOD* wolfSSLv23_server_method(void)
- {
- return wolfSSLv23_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("SSLv23_server_method_ex");
- if (method) {
- #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
- #ifdef WOLFSSL_TLS13
- InitSSL_Method(method, MakeTLSv1_3());
- #elif !defined(WOLFSSL_NO_TLS12)
- InitSSL_Method(method, MakeTLSv1_2());
- #elif !defined(NO_OLD_TLS)
- InitSSL_Method(method, MakeTLSv1_1());
- #endif
- #else
- #ifndef NO_OLD_TLS
- InitSSL_Method(method, MakeTLSv1_1());
- #else
- #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2
- #endif
- #endif
- #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
- method->downgrade = 1;
- #endif
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- WOLFSSL_ABI
- int wolfSSL_accept(WOLFSSL* ssl)
- {
- #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
- word16 havePSK = 0;
- word16 haveAnon = 0;
- word16 haveMcast = 0;
- #endif
- int ret = 0;
- (void)ret;
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
- if (ssl->options.side == WOLFSSL_NEITHER_END) {
- WOLFSSL_MSG("Setting WOLFSSL_SSL to be server side");
- ssl->error = InitSSL_Side(ssl, WOLFSSL_SERVER_END);
- if (ssl->error != WOLFSSL_SUCCESS) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->error = 0; /* expected to be zero here */
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
- #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)
- return wolfSSL_accept_TLSv13(ssl);
- #else
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3)
- return wolfSSL_accept_TLSv13(ssl);
- #endif
- WOLFSSL_ENTER("SSL_accept()");
- /* make sure this wolfSSL object has arrays and rng setup. Protects
- * case where the WOLFSSL object is re-used via wolfSSL_clear() */
- if ((ret = ReinitSSL(ssl, ssl->ctx, 0)) != 0) {
- return ret;
- }
- #ifdef WOLFSSL_WOLFSENTRY_HOOKS
- if ((ssl->AcceptFilter != NULL) &&
- ((ssl->options.acceptState == ACCEPT_BEGIN)
- #ifdef HAVE_SECURE_RENEGOTIATION
- || (ssl->options.acceptState == ACCEPT_BEGIN_RENEG)
- #endif
- ))
- {
- wolfSSL_netfilter_decision_t res;
- if ((ssl->AcceptFilter(ssl, ssl->AcceptFilter_arg, &res) ==
- WOLFSSL_SUCCESS) &&
- (res == WOLFSSL_NETFILTER_REJECT)) {
- ssl->error = SOCKET_FILTERED_E;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif /* WOLFSSL_WOLFSENTRY_HOOKS */
- #ifdef HAVE_ERRNO_H
- errno = 0;
- #endif
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #endif
- (void)havePSK;
- #ifdef HAVE_ANON
- haveAnon = ssl->options.haveAnon;
- #endif
- (void)haveAnon;
- #ifdef WOLFSSL_MULTICAST
- haveMcast = ssl->options.haveMcast;
- #endif
- (void)haveMcast;
- if (ssl->options.side != WOLFSSL_SERVER_END) {
- ssl->error = SIDE_ERROR;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- #ifndef NO_CERTS
- /* in case used set_accept_state after init */
- if (!havePSK && !haveAnon && !haveMcast) {
- #ifdef OPENSSL_EXTRA
- if (ssl->ctx->certSetupCb != NULL) {
- WOLFSSL_MSG("CertSetupCb set. server cert and "
- "key not checked");
- }
- else
- #endif
- {
- if (!ssl->buffers.certificate ||
- !ssl->buffers.certificate->buffer) {
- WOLFSSL_MSG("accept error: server cert required");
- ssl->error = NO_PRIVATE_KEY;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
- /* allow no private key if using existing key */
- #ifdef WOLF_PRIVATE_KEY_ID
- if (ssl->devId != INVALID_DEVID
- #ifdef HAVE_PK_CALLBACKS
- || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)
- #endif
- ) {
- WOLFSSL_MSG("Allowing no server private key "
- "(external)");
- }
- else
- #endif
- {
- WOLFSSL_MSG("accept error: server key required");
- ssl->error = NO_PRIVATE_KEY;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- }
- }
- #endif
- #ifdef WOLFSSL_DTLS
- if (ssl->version.major == DTLS_MAJOR) {
- ssl->options.dtls = 1;
- ssl->options.tls = 1;
- ssl->options.tls1_1 = 1;
- }
- #endif
- if (ssl->buffers.outputBuffer.length > 0
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* do not send buffered or advance state if last error was an
- async pending operation */
- && ssl->error != WC_PENDING_E
- #endif
- ) {
- ret = SendBuffered(ssl);
- if (ret == 0) {
- /* fragOffset is non-zero when sending fragments. On the last
- * fragment, fragOffset is zero again, and the state can be
- * advanced. */
- if (ssl->fragOffset == 0 && !ssl->options.buildingMsg) {
- if (ssl->options.acceptState == ACCEPT_FIRST_REPLY_DONE ||
- ssl->options.acceptState == SERVER_HELLO_SENT ||
- ssl->options.acceptState == CERT_SENT ||
- ssl->options.acceptState == CERT_STATUS_SENT ||
- ssl->options.acceptState == KEY_EXCHANGE_SENT ||
- ssl->options.acceptState == CERT_REQ_SENT ||
- ssl->options.acceptState == ACCEPT_SECOND_REPLY_DONE ||
- ssl->options.acceptState == TICKET_SENT ||
- ssl->options.acceptState == CHANGE_CIPHER_SENT) {
- ssl->options.acceptState++;
- WOLFSSL_MSG("accept state: "
- "Advanced from last buffered fragment send");
- #ifdef WOLFSSL_ASYNC_IO
- /* Cleanup async */
- FreeAsyncCtx(ssl, 0);
- #endif
- }
- }
- else {
- WOLFSSL_MSG("accept state: "
- "Not advanced, more fragments to send");
- }
- }
- else {
- ssl->error = ret;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- ret = RetrySendAlert(ssl);
- if (ret != 0) {
- ssl->error = ret;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- switch (ssl->options.acceptState) {
- case ACCEPT_BEGIN :
- #ifdef HAVE_SECURE_RENEGOTIATION
- case ACCEPT_BEGIN_RENEG:
- #endif
- /* get response */
- while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- #ifdef WOLFSSL_TLS13
- ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE;
- WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
- FALL_THROUGH;
- case ACCEPT_CLIENT_HELLO_DONE :
- if (ssl->options.tls1_3) {
- return wolfSSL_accept_TLSv13(ssl);
- }
- #endif
- #ifdef WOLFSSL_DTLS
- if (ssl->chGoodCb != NULL && !IsSCR(ssl)) {
- int cbret = ssl->chGoodCb(ssl, ssl->chGoodCtx);
- if (cbret < 0) {
- ssl->error = cbret;
- WOLFSSL_MSG("ClientHello Good Cb don't continue error");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif
- ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
- WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
- FALL_THROUGH;
- case ACCEPT_FIRST_REPLY_DONE :
- if ( (ssl->error = SendServerHello(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.acceptState = SERVER_HELLO_SENT;
- WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
- FALL_THROUGH;
- case SERVER_HELLO_SENT :
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3) {
- return wolfSSL_accept_TLSv13(ssl);
- }
- #endif
- #ifndef NO_CERTS
- if (!ssl->options.resuming)
- if ( (ssl->error = SendCertificate(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- #endif
- ssl->options.acceptState = CERT_SENT;
- WOLFSSL_MSG("accept state CERT_SENT");
- FALL_THROUGH;
- case CERT_SENT :
- #ifndef NO_CERTS
- if (!ssl->options.resuming)
- if ( (ssl->error = SendCertificateStatus(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- #endif
- ssl->options.acceptState = CERT_STATUS_SENT;
- WOLFSSL_MSG("accept state CERT_STATUS_SENT");
- FALL_THROUGH;
- case CERT_STATUS_SENT :
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3) {
- return wolfSSL_accept_TLSv13(ssl);
- }
- #endif
- if (!ssl->options.resuming)
- if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.acceptState = KEY_EXCHANGE_SENT;
- WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT");
- FALL_THROUGH;
- case KEY_EXCHANGE_SENT :
- #ifndef NO_CERTS
- if (!ssl->options.resuming) {
- if (ssl->options.verifyPeer) {
- if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- else {
- /* SERVER: Peer auth good if not verifying client. */
- ssl->options.peerAuthGood = 1;
- }
- }
- #endif
- ssl->options.acceptState = CERT_REQ_SENT;
- WOLFSSL_MSG("accept state CERT_REQ_SENT");
- FALL_THROUGH;
- case CERT_REQ_SENT :
- if (!ssl->options.resuming)
- if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.acceptState = SERVER_HELLO_DONE;
- WOLFSSL_MSG("accept state SERVER_HELLO_DONE");
- FALL_THROUGH;
- case SERVER_HELLO_DONE :
- if (!ssl->options.resuming) {
- while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
- WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
- FALL_THROUGH;
- case ACCEPT_SECOND_REPLY_DONE :
- #ifndef NO_CERTS
- /* SERVER: When not resuming and verifying peer but no certificate
- * received and not failing when not received then peer auth good.
- */
- if (!ssl->options.resuming && ssl->options.verifyPeer &&
- !ssl->options.havePeerCert && !ssl->options.failNoCert) {
- ssl->options.peerAuthGood = 1;
- }
- #endif /* !NO_CERTS */
- #ifdef WOLFSSL_NO_CLIENT_AUTH
- if (!ssl->options.resuming) {
- ssl->options.peerAuthGood = 1;
- }
- #endif
- #ifdef HAVE_SESSION_TICKET
- if (ssl->options.createTicket && !ssl->options.noTicketTls12) {
- if ( (ssl->error = SendTicket(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif /* HAVE_SESSION_TICKET */
- ssl->options.acceptState = TICKET_SENT;
- WOLFSSL_MSG("accept state TICKET_SENT");
- FALL_THROUGH;
- case TICKET_SENT:
- /* SERVER: Fail-safe for CLient Authentication. */
- if (!ssl->options.peerAuthGood) {
- WOLFSSL_MSG("Client authentication did not happen");
- return WOLFSSL_FATAL_ERROR;
- }
- if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.acceptState = CHANGE_CIPHER_SENT;
- WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT");
- FALL_THROUGH;
- case CHANGE_CIPHER_SENT :
- if ( (ssl->error = SendFinished(ssl)) != 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.acceptState = ACCEPT_FINISHED_DONE;
- WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
- FALL_THROUGH;
- case ACCEPT_FINISHED_DONE :
- if (ssl->options.resuming) {
- while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) {
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- }
- ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
- WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
- FALL_THROUGH;
- case ACCEPT_THIRD_REPLY_DONE :
- #ifndef NO_HANDSHAKE_DONE_CB
- if (ssl->hsDoneCb) {
- int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
- if (cbret < 0) {
- ssl->error = cbret;
- WOLFSSL_MSG("HandShake Done Cb don't continue error");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif /* NO_HANDSHAKE_DONE_CB */
- if (!ssl->options.dtls) {
- if (!ssl->options.keepResources) {
- FreeHandshakeResources(ssl);
- }
- }
- #ifdef WOLFSSL_DTLS
- else {
- ssl->options.dtlsHsRetain = 1;
- }
- #endif /* WOLFSSL_DTLS */
- #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SECURE_RENEGOTIATION)
- /* This may be necessary in async so that we don't try to
- * renegotiate again */
- if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
- ssl->secure_renegotiation->startScr = 0;
- }
- #endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */
- #if defined(WOLFSSL_ASYNC_IO) && !defined(WOLFSSL_ASYNC_CRYPT)
- /* Free the remaining async context if not using it for crypto */
- FreeAsyncCtx(ssl, 1);
- #endif
- #if defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS)
- if (ssl->dtls_export) {
- if ((ssl->error = wolfSSL_send_session(ssl)) != 0) {
- WOLFSSL_MSG("Export DTLS session error");
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
- #endif
- ssl->error = 0; /* clear the error */
- WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- default :
- WOLFSSL_MSG("Unknown accept state ERROR");
- return WOLFSSL_FATAL_ERROR;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- }
- #endif /* NO_WOLFSSL_SERVER */
- #if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
- int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx)
- {
- WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->chGoodCb = cb;
- ssl->chGoodCtx = user_ctx;
- return WOLFSSL_SUCCESS;
- }
- #endif
- #ifndef NO_HANDSHAKE_DONE_CB
- int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx)
- {
- WOLFSSL_ENTER("wolfSSL_SetHsDoneCb");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- ssl->hsDoneCb = cb;
- ssl->hsDoneCtx = user_ctx;
- return WOLFSSL_SUCCESS;
- }
- #endif /* NO_HANDSHAKE_DONE_CB */
- WOLFSSL_ABI
- int wolfSSL_Cleanup(void)
- {
- int ret = WOLFSSL_SUCCESS; /* Only the first error will be returned */
- int release = 0;
- #if !defined(NO_SESSION_CACHE) && defined(ENABLE_SESSION_CACHE_ROW_LOCK)
- int i;
- #endif
- WOLFSSL_ENTER("wolfSSL_Cleanup");
- if (initRefCount == 0)
- return ret; /* possibly no init yet, but not failure either way */
- if ((count_mutex_valid == 1) && (wc_LockMutex(&count_mutex) != 0)) {
- WOLFSSL_MSG("Bad Lock Mutex count");
- ret = BAD_MUTEX_E;
- }
- release = initRefCount-- == 1;
- if (initRefCount < 0)
- initRefCount = 0;
- if (count_mutex_valid == 1) {
- wc_UnLockMutex(&count_mutex);
- }
- if (!release)
- return ret;
- #ifdef OPENSSL_EXTRA
- if (bn_one) {
- wolfSSL_BN_free(bn_one);
- bn_one = NULL;
- }
- #endif
- #ifndef NO_SESSION_CACHE
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- for (i = 0; i < SESSION_ROWS; ++i) {
- if ((SessionCache[i].mutex_valid == 1) &&
- (wc_FreeMutex(&SessionCache[i].row_mutex) != 0)) {
- if (ret == WOLFSSL_SUCCESS)
- ret = BAD_MUTEX_E;
- }
- SessionCache[i].mutex_valid = 0;
- }
- #else
- if ((session_mutex_valid == 1) && (wc_FreeMutex(&session_mutex) != 0)) {
- if (ret == WOLFSSL_SUCCESS)
- ret = BAD_MUTEX_E;
- }
- session_mutex_valid = 0;
- #endif
- #ifndef NO_CLIENT_CACHE
- if ((clisession_mutex_valid == 1) &&
- (wc_FreeMutex(&clisession_mutex) != 0)) {
- if (ret == WOLFSSL_SUCCESS)
- ret = BAD_MUTEX_E;
- }
- clisession_mutex_valid = 0;
- #endif
- #endif /* !NO_SESSION_CACHE */
- if ((count_mutex_valid == 1) && (wc_FreeMutex(&count_mutex) != 0)) {
- if (ret == WOLFSSL_SUCCESS)
- ret = BAD_MUTEX_E;
- }
- count_mutex_valid = 0;
- #ifdef OPENSSL_EXTRA
- wolfSSL_RAND_Cleanup();
- #endif
- if (wolfCrypt_Cleanup() != 0) {
- WOLFSSL_MSG("Error with wolfCrypt_Cleanup call");
- if (ret == WOLFSSL_SUCCESS)
- ret = WC_CLEANUP_E;
- }
- #if FIPS_VERSION_GE(5,1)
- if (wolfCrypt_SetPrivateKeyReadEnable_fips(0, WC_KEYTYPE_ALL) < 0) {
- if (ret == WOLFSSL_SUCCESS)
- ret = WC_CLEANUP_E;
- }
- #endif
- #ifdef HAVE_GLOBAL_RNG
- if ((globalRNGMutex_valid == 1) && (wc_FreeMutex(&globalRNGMutex) != 0)) {
- if (ret == WOLFSSL_SUCCESS)
- ret = BAD_MUTEX_E;
- }
- globalRNGMutex_valid = 0;
- #if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
- wolfSSL_FIPS_drbg_free(gDrbgDefCtx);
- gDrbgDefCtx = NULL;
- #endif
- #endif
- return ret;
- }
- #ifndef NO_SESSION_CACHE
- WOLFSSL_ABI
- void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm)
- {
- /* static table now, no flushing needed */
- (void)ctx;
- (void)tm;
- }
- /* set ssl session timeout in seconds */
- WOLFSSL_ABI
- int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (to == 0)
- to = WOLFSSL_SESSION_TIMEOUT;
- ssl->timeout = to;
- return WOLFSSL_SUCCESS;
- }
- /**
- * Sets ctx session timeout in seconds.
- * The timeout value set here should be reflected in the
- * "session ticket lifetime hint" if this API works in the openssl compat-layer.
- * Therefore wolfSSL_CTX_set_TicketHint is called internally.
- * Arguments:
- * - ctx WOLFSSL_CTX object which the timeout is set to
- * - to timeout value in second
- * Returns:
- * WOLFSSL_SUCCESS on success, BAD_FUNC_ARG on failure.
- * When WOLFSSL_ERROR_CODE_OPENSSL is defined, returns previous timeout value
- * on success, BAD_FUNC_ARG on failure.
- */
- WOLFSSL_ABI
- int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to)
- {
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- word32 prev_timeout = 0;
- #endif
- int ret = WOLFSSL_SUCCESS;
- (void)ret;
- if (ctx == NULL)
- ret = BAD_FUNC_ARG;
- if (ret == WOLFSSL_SUCCESS) {
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- prev_timeout = ctx->timeout;
- #endif
- if (to == 0) {
- ctx->timeout = WOLFSSL_SESSION_TIMEOUT;
- }
- else {
- ctx->timeout = to;
- }
- }
- #if defined(OPENSSL_EXTRA) && defined(HAVE_SESSION_TICKET) && \
- !defined(NO_WOLFSSL_SERVER)
- if (ret == WOLFSSL_SUCCESS) {
- if (to == 0) {
- ret = wolfSSL_CTX_set_TicketHint(ctx, SESSION_TICKET_HINT_DEFAULT);
- }
- else {
- ret = wolfSSL_CTX_set_TicketHint(ctx, to);
- }
- }
- #endif /* OPENSSL_EXTRA && HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER */
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- if (ret == WOLFSSL_SUCCESS) {
- return prev_timeout;
- }
- else {
- return ret;
- }
- #else
- return ret;
- #endif /* WOLFSSL_ERROR_CODE_OPENSSL */
- }
- #ifndef NO_CLIENT_CACHE
- /* Get Session from Client cache based on id/len, return NULL on failure */
- WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
- {
- WOLFSSL_SESSION* ret = NULL;
- word32 row;
- int idx;
- int count;
- int error = 0;
- ClientSession* clSess;
- WOLFSSL_ENTER("GetSessionClient");
- if (ssl->ctx->sessionCacheOff) {
- WOLFSSL_MSG("Session Cache off");
- return NULL;
- }
- if (ssl->options.side == WOLFSSL_SERVER_END)
- return NULL;
- len = min(SERVER_ID_LEN, (word32)len);
- #ifdef HAVE_EXT_CACHE
- if (ssl->ctx->get_sess_cb != NULL) {
- int copy = 0;
- WOLFSSL_MSG("Calling external session cache");
- ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, ©);
- if (ret != NULL) {
- WOLFSSL_MSG("Session found in external cache");
- return ret;
- }
- WOLFSSL_MSG("Session not found in external cache");
- }
- if (ssl->ctx->internalCacheLookupOff) {
- WOLFSSL_MSG("Internal cache turned off");
- return NULL;
- }
- #endif
- row = HashObject(id, len, &error) % CLIENT_SESSION_ROWS;
- if (error != 0) {
- WOLFSSL_MSG("Hash session failed");
- return NULL;
- }
- if (wc_LockMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Client cache mutex lock failed");
- return NULL;
- }
- /* start from most recently used */
- count = min((word32)ClientCache[row].totalCount, CLIENT_SESSIONS_PER_ROW);
- idx = ClientCache[row].nextIdx - 1;
- if (idx < 0 || idx >= CLIENT_SESSIONS_PER_ROW) {
- idx = CLIENT_SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
- }
- clSess = ClientCache[row].Clients;
- for (; count > 0; --count) {
- WOLFSSL_SESSION* current;
- SessionRow* sessRow;
- if (clSess[idx].serverRow >= SESSION_ROWS) {
- WOLFSSL_MSG("Client cache serverRow invalid");
- break;
- }
- /* lock row */
- sessRow = &SessionCache[clSess[idx].serverRow];
- if (SESSION_ROW_LOCK(sessRow) != 0) {
- WOLFSSL_MSG("Session cache row lock failure");
- break;
- }
- current = &sessRow->Sessions[clSess[idx].serverIdx];
- if (XMEMCMP(current->serverID, id, len) == 0) {
- WOLFSSL_MSG("Found a serverid match for client");
- if (LowResTimer() < (current->bornOn + current->timeout)) {
- WOLFSSL_MSG("Session valid");
- ret = current;
- SESSION_ROW_UNLOCK(sessRow);
- break;
- } else {
- WOLFSSL_MSG("Session timed out"); /* could have more for id */
- }
- } else {
- WOLFSSL_MSG("ServerID not a match from client table");
- }
- SESSION_ROW_UNLOCK(sessRow);
- idx = idx > 0 ? idx - 1 : CLIENT_SESSIONS_PER_ROW - 1;
- }
- wc_UnLockMutex(&clisession_mutex);
- return ret;
- }
- #endif /* !NO_CLIENT_CACHE */
- static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session)
- {
- (void)session;
- return ssl->options.sessionCacheOff
- #if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_FORCE_CACHE_ON_TICKET)
- && session->ticketLen == 0
- #endif
- #ifdef OPENSSL_EXTRA
- && ssl->options.side != WOLFSSL_CLIENT_END
- #endif
- ;
- }
- int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
- {
- WOLFSSL_SESSION* sess = NULL;
- const byte* id = NULL;
- word32 row;
- int idx;
- int count;
- int error = 0;
- SessionRow* sessRow;
- #ifdef HAVE_SESSION_TICKET
- #ifndef WOLFSSL_SMALL_STACK
- byte tmpTicket[PREALLOC_SESSION_TICKET_LEN];
- #else
- byte* tmpTicket = NULL;
- #endif
- byte tmpBufSet = 0;
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- WOLFSSL_X509* peer = NULL;
- #endif
- byte bogusID[ID_LEN];
- byte bogusIDSz = 0;
- WOLFSSL_ENTER("wolfSSL_GetSessionFromCache");
- if (output == NULL) {
- WOLFSSL_MSG("NULL output");
- return WOLFSSL_FAILURE;
- }
- if (SslSessionCacheOff(ssl, ssl->session))
- return WOLFSSL_FAILURE;
- if (ssl->options.haveSessionId == 0)
- return WOLFSSL_FAILURE;
- #ifdef HAVE_SESSION_TICKET
- if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
- return WOLFSSL_FAILURE;
- #endif
- XMEMSET(bogusID, 0, sizeof(bogusID));
- if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL)
- id = ssl->arrays->sessionID;
- else if (ssl->session->haveAltSessionID) {
- id = ssl->session->altSessionID;
- /* We want to restore the bogus ID for TLS compatibility */
- if (output == ssl->session) {
- XMEMCPY(bogusID, ssl->session->sessionID, ID_LEN);
- bogusIDSz = ssl->session->sessionIDSz;
- }
- }
- else
- id = ssl->session->sessionID;
- #ifdef HAVE_EXT_CACHE
- if (ssl->ctx->get_sess_cb != NULL) {
- int copy = 0;
- /* Attempt to retrieve the session from the external cache. */
- WOLFSSL_MSG("Calling external session cache");
- sess = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©);
- if (sess != NULL) {
- WOLFSSL_MSG("Session found in external cache");
- error = wolfSSL_DupSession(sess, output, 0);
- #ifdef HAVE_EX_DATA
- output->ownExData = 0; /* Session cache owns external data */
- #endif
- /* If copy not set then free immediately */
- if (!copy)
- wolfSSL_FreeSession(ssl->ctx, sess);
- /* We want to restore the bogus ID for TLS compatibility */
- if (ssl->session->haveAltSessionID &&
- output == ssl->session) {
- XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN);
- ssl->session->sessionIDSz = bogusIDSz;
- }
- return error;
- }
- WOLFSSL_MSG("Session not found in external cache");
- }
- if (ssl->ctx->internalCacheLookupOff) {
- WOLFSSL_MSG("Internal cache lookup turned off");
- return WOLFSSL_FAILURE;
- }
- #endif
- row = HashObject(id, ID_LEN, &error) % SESSION_ROWS;
- if (error != 0) {
- WOLFSSL_MSG("Hash session failed");
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_SESSION_TICKET
- if (output->ticket == NULL ||
- output->ticketLenAlloc < PREALLOC_SESSION_TICKET_LEN) {
- #ifdef WOLFSSL_SMALL_STACK
- tmpTicket = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_LEN, output->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (tmpTicket == NULL) {
- WOLFSSL_MSG("tmpTicket malloc failed");
- return WOLFSSL_FAILURE;
- }
- #endif
- if (output->ticketLenAlloc)
- XFREE(output->ticket, output->heap, DYNAMIC_TYPE_SESSION_TICK);
- output->ticket = tmpTicket;
- output->ticketLenAlloc = PREALLOC_SESSION_TICKET_LEN;
- output->ticketLen = 0;
- tmpBufSet = 1;
- }
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- if (output->peer != NULL) {
- wolfSSL_X509_free(output->peer);
- output->peer = NULL;
- }
- #endif
- /* lock row */
- sessRow = &SessionCache[row];
- if (SESSION_ROW_LOCK(sessRow) != 0) {
- WOLFSSL_MSG("Session cache row lock failure");
- #ifdef HAVE_SESSION_TICKET
- if (tmpBufSet) {
- output->ticket = output->staticTicket;
- output->ticketLenAlloc = 0;
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (tmpTicket != NULL)
- XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #endif
- return WOLFSSL_FAILURE;
- }
- /* start from most recently used */
- count = min((word32)sessRow->totalCount, SESSIONS_PER_ROW);
- idx = sessRow->nextIdx - 1;
- if (idx < 0 || idx >= SESSIONS_PER_ROW) {
- idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
- }
- for (; count > 0; --count) {
- WOLFSSL_SESSION* current;
- current = &sessRow->Sessions[idx];
- if (XMEMCMP(current->sessionID, id, ID_LEN) == 0 &&
- current->side == ssl->options.side) {
- WOLFSSL_MSG("Found a session match");
- if (LowResTimer() < (current->bornOn + current->timeout)) {
- WOLFSSL_MSG("Session valid");
- sess = current;
- } else {
- WOLFSSL_MSG("Session timed out");
- }
- break; /* no more sessionIDs whether valid or not that match */
- } else {
- WOLFSSL_MSG("SessionID not a match at this idx");
- }
- idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1;
- }
- if (sess != NULL) {
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- /* We don't want the peer member. We will free it at the end. */
- if (sess->peer != NULL) {
- peer = sess->peer;
- sess->peer = NULL;
- }
- #endif
- error = wolfSSL_DupSession(sess, output, 1);
- #ifdef HAVE_EX_DATA
- output->ownExData = 0; /* Session cache owns external data */
- #endif
- }
- else {
- error = WOLFSSL_FAILURE;
- }
- SESSION_ROW_UNLOCK(sessRow);
- /* We want to restore the bogus ID for TLS compatibility */
- if (ssl->session->haveAltSessionID &&
- output == ssl->session) {
- XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN);
- ssl->session->sessionIDSz = bogusIDSz;
- }
- #ifdef HAVE_SESSION_TICKET
- if (tmpBufSet) {
- if (error == WOLFSSL_SUCCESS) {
- if (output->ticketLen > SESSION_TICKET_LEN) {
- output->ticket = (byte*)XMALLOC(output->ticketLen, output->heap,
- DYNAMIC_TYPE_SESSION_TICK);
- if (output->ticket == NULL) {
- error = WOLFSSL_FAILURE;
- output->ticket = output->staticTicket;
- output->ticketLenAlloc = 0;
- output->ticketLen = 0;
- }
- }
- else {
- output->ticket = output->staticTicket;
- output->ticketLenAlloc = 0;
- }
- }
- else {
- output->ticket = output->staticTicket;
- output->ticketLenAlloc = 0;
- output->ticketLen = 0;
- }
- if (error == WOLFSSL_SUCCESS) {
- XMEMCPY(output->ticket, tmpTicket, output->ticketLen);
- }
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (tmpTicket != NULL)
- XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- if (peer != NULL) {
- wolfSSL_X509_free(peer);
- }
- #endif
- return error;
- }
- WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret,
- byte restoreSessionCerts)
- {
- WOLFSSL_SESSION* ret = NULL;
- (void)restoreSessionCerts; /* Kept for compatibility */
- if (wolfSSL_GetSessionFromCache(ssl, ssl->session) == WOLFSSL_SUCCESS) {
- ret = ssl->session;
- }
- else {
- WOLFSSL_MSG("wolfSSL_GetSessionFromCache did not return a session");
- }
- if (ret != NULL && masterSecret != NULL)
- XMEMCPY(masterSecret, ret->masterSecret, SECRET_LEN);
- return ret;
- }
- int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
- {
- SessionRow* sessRow = NULL;
- int ret = WOLFSSL_SUCCESS;
- session = ClientSessionToSession(session);
- if (ssl == NULL || session == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (session->type == WOLFSSL_SESSION_TYPE_CACHE) {
- if (session->cacheRow < SESSION_ROWS) {
- sessRow = &SessionCache[session->cacheRow];
- if (SESSION_ROW_LOCK(sessRow) != 0) {
- WOLFSSL_MSG("Session row lock failed");
- return WOLFSSL_FAILURE;
- }
- }
- }
- if (ret == WOLFSSL_SUCCESS && SslSessionCacheOff(ssl, session)) {
- WOLFSSL_MSG("Session cache off");
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS && ssl->options.side != WOLFSSL_NEITHER_END &&
- (byte)ssl->options.side != session->side) {
- WOLFSSL_MSG("Setting session for wrong role");
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS &&
- wolfSSL_DupSession(session, ssl->session, 0) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Session duplicate failed");
- ret = WOLFSSL_FAILURE;
- }
- /* Let's copy over the altSessionID for local cache purposes */
- if (ret == WOLFSSL_SUCCESS && session->haveAltSessionID) {
- ssl->session->haveAltSessionID = 1;
- XMEMCPY(ssl->session->altSessionID, session->altSessionID, ID_LEN);
- }
- if (sessRow != NULL) {
- SESSION_ROW_UNLOCK(sessRow);
- sessRow = NULL;
- }
- /* Note: the `session` variable cannot be used below, since the row is
- * un-locked */
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- #ifdef OPENSSL_EXTRA
- /* check for application context id */
- if (ssl->sessionCtxSz > 0) {
- if (XMEMCMP(ssl->sessionCtx, ssl->session->sessionCtx, ssl->sessionCtxSz)) {
- /* context id did not match! */
- WOLFSSL_MSG("Session context did not match");
- return WOLFSSL_FAILURE;
- }
- }
- #endif /* OPENSSL_EXTRA */
- if (LowResTimer() < (ssl->session->bornOn + ssl->session->timeout)) {
- ssl->options.resuming = 1;
- ssl->options.haveEMS = ssl->session->haveEMS;
- #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
- defined(HAVE_SESSION_TICKET))
- ssl->version = ssl->session->version;
- if (IsAtLeastTLSv1_3(ssl->version))
- ssl->options.tls1_3 = 1;
- #endif
- #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
- ssl->options.cipherSuite0 = ssl->session->cipherSuite0;
- ssl->options.cipherSuite = ssl->session->cipherSuite;
- #endif
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- ssl->peerVerifyRet = (unsigned long)ssl->session->peerVerifyRet;
- #endif
- ret = WOLFSSL_SUCCESS;
- }
- else {
- #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL)
- WOLFSSL_MSG("Session is expired but return success for \
- OpenSSL compatibility");
- ret = WOLFSSL_SUCCESS;
- #else
- ret = WOLFSSL_FAILURE; /* session timed out */
- #endif /* OPENSSL_EXTRA && WOLFSSL_ERROR_CODE_OPENSSL */
- }
- return ret;
- }
- #ifdef WOLFSSL_SESSION_STATS
- static int get_locked_session_stats(word32* active, word32* total,
- word32* peak);
- #endif
- #ifndef NO_CLIENT_CACHE
- ClientSession* AddSessionToClientCache(int side, int row, int idx, byte* serverID,
- word16 idLen, const byte* sessionID,
- word16 useTicket)
- {
- int error = -1;
- word32 clientRow = 0, clientIdx = 0, sessionIDHash = 0;
- (void)useTicket;
- if (side == WOLFSSL_CLIENT_END
- && row != INVALID_SESSION_ROW
- && (idLen
- #ifdef HAVE_SESSION_TICKET
- || useTicket == 1
- #endif
- || serverID != NULL
- )) {
- WOLFSSL_MSG("Trying to add client cache entry");
- if (idLen) {
- clientRow = HashObject(serverID,
- idLen, &error) % CLIENT_SESSION_ROWS;
- }
- else if (serverID != NULL) {
- clientRow = HashObject(sessionID,
- ID_LEN, &error) % CLIENT_SESSION_ROWS;
- }
- else {
- error = -1;
- }
- if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) {
- clientIdx = ClientCache[clientRow].nextIdx;
- if (clientIdx < CLIENT_SESSIONS_PER_ROW) {
- ClientCache[clientRow].Clients[clientIdx].serverRow =
- (word16)row;
- ClientCache[clientRow].Clients[clientIdx].serverIdx =
- (word16)idx;
- if (sessionID != NULL) {
- sessionIDHash = HashObject(sessionID, ID_LEN, &error);
- if (error == 0) {
- ClientCache[clientRow].Clients[clientIdx].sessionIDHash
- = sessionIDHash;
- }
- }
- }
- else {
- error = -1;
- ClientCache[clientRow].nextIdx = 0; /* reset index as saftey */
- WOLFSSL_MSG("Invalid client cache index! "
- "Possible corrupted memory");
- }
- if (error == 0) {
- WOLFSSL_MSG("Adding client cache entry");
- if (ClientCache[clientRow].totalCount < CLIENT_SESSIONS_PER_ROW)
- ClientCache[clientRow].totalCount++;
- ClientCache[clientRow].nextIdx++;
- ClientCache[clientRow].nextIdx %= CLIENT_SESSIONS_PER_ROW;
- }
- wc_UnLockMutex(&clisession_mutex);
- }
- else {
- WOLFSSL_MSG("Hash session or lock failed");
- error = -1;
- }
- }
- else {
- WOLFSSL_MSG("Skipping client cache");
- }
- if (error == 0)
- return &ClientCache[clientRow].Clients[clientIdx];
- else
- return NULL;
- }
- #endif
- /**
- * For backwards compatibility, this API needs to be used in *ALL* functions
- * that access the WOLFSSL_SESSION members directly.
- *
- * This API checks if the passed in session is actually a ClientSession object
- * and returns the matching session cache object. Otherwise just return the
- * input. ClientSession objects only occur in the ClientCache. They are not
- * allocated anywhere else.
- */
- WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session)
- {
- WOLFSSL_ENTER("ClientSessionToSession");
- #ifdef NO_SESSION_CACHE_REF
- return (WOLFSSL_SESSION*)session;
- #else
- #ifndef NO_CLIENT_CACHE
- if (session == NULL)
- return NULL;
- /* Check if session points into ClientCache */
- if ((byte*)session >= (byte*)ClientCache &&
- /* Cast to byte* to make pointer arithmetic work per byte */
- (byte*)session < ((byte*)ClientCache) + sizeof(ClientCache)) {
- ClientSession* clientSession = (ClientSession*)session;
- SessionRow* sessRow = NULL;
- WOLFSSL_SESSION* cacheSession = NULL;
- word32 sessionIDHash = 0;
- int error = 0;
- session = NULL; /* Default to NULL for failure case */
- if (wc_LockMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Client cache mutex lock failed");
- return NULL;
- }
- if (clientSession->serverRow >= SESSION_ROWS ||
- clientSession->serverIdx >= SESSIONS_PER_ROW) {
- WOLFSSL_MSG("Client cache serverRow or serverIdx invalid");
- error = -1;
- }
- if (error == 0) {
- /* Lock row */
- sessRow = &SessionCache[clientSession->serverRow];
- error = SESSION_ROW_LOCK(sessRow);
- if (error != 0) {
- WOLFSSL_MSG("Session cache row lock failure");
- sessRow = NULL;
- }
- }
- if (error == 0) {
- cacheSession = &sessRow->Sessions[clientSession->serverIdx];
- if (cacheSession->sessionIDSz == 0) {
- cacheSession = NULL;
- WOLFSSL_MSG("Session cache entry not set");
- error = -1;
- }
- }
- if (error == 0) {
- /* Calculate the hash of the session ID */
- sessionIDHash = HashObject(cacheSession->sessionID, ID_LEN,
- &error);
- }
- if (error == 0) {
- /* Check the session ID hash matches */
- error = clientSession->sessionIDHash != sessionIDHash;
- }
- if (error == 0) {
- /* Hashes match */
- session = cacheSession;
- WOLFSSL_MSG("Found session cache matching client session object");
- }
- if (sessRow != NULL) {
- SESSION_ROW_UNLOCK(sessRow);
- }
- wc_UnLockMutex(&clisession_mutex);
- return (WOLFSSL_SESSION*)session;
- }
- else {
- /* Plain WOLFSSL_SESSION object */
- return (WOLFSSL_SESSION*)session;
- }
- #else
- return (WOLFSSL_SESSION*)session;
- #endif
- #endif
- }
- int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
- const byte* id, byte idSz, int* sessionIndex, int side,
- word16 useTicket, ClientSession** clientCacheEntry)
- {
- WOLFSSL_SESSION* cacheSession = NULL;
- SessionRow* sessRow = NULL;
- word32 idx = 0;
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- WOLFSSL_X509* peer = NULL;
- #endif
- #ifdef HAVE_SESSION_TICKET
- byte* cacheTicBuff = NULL;
- byte ticBuffUsed = 0;
- byte* ticBuff = NULL;
- int ticLen = 0;
- #endif
- int ret = 0;
- int row;
- int i;
- int overwrite = 0;
- (void)ctx;
- (void)sessionIndex;
- (void)useTicket;
- (void)clientCacheEntry;
- if (idSz == 0) {
- WOLFSSL_MSG("AddSessionToCache idSz == 0");
- return BAD_FUNC_ARG;
- }
- addSession = ClientSessionToSession(addSession);
- if (addSession == NULL) {
- WOLFSSL_MSG("AddSessionToCache is NULL");
- return MEMORY_E;
- }
- /* Find a position for the new session in cache and use that */
- #ifdef HAVE_SESSION_TICKET
- ticLen = addSession->ticketLen;
- /* Alloc Memory here to avoid syscalls during lock */
- if (ticLen > SESSION_TICKET_LEN) {
- ticBuff = (byte*)XMALLOC(ticLen, NULL,
- DYNAMIC_TYPE_SESSION_TICK);
- if (ticBuff == NULL) {
- return MEMORY_E;
- }
- }
- #endif
- /* Use the session object in the cache for external cache if required */
- row = (int)(HashObject(id, ID_LEN, &ret) % SESSION_ROWS);
- if (ret != 0) {
- WOLFSSL_MSG("Hash session failed");
- #ifdef HAVE_SESSION_TICKET
- XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
- #endif
- return ret;
- }
- sessRow = &SessionCache[row];
- if (SESSION_ROW_LOCK(sessRow) != 0) {
- #ifdef HAVE_SESSION_TICKET
- XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
- #endif
- WOLFSSL_MSG("Session row lock failed");
- return BAD_MUTEX_E;
- }
- for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) {
- if (XMEMCMP(id,
- sessRow->Sessions[i].sessionID, ID_LEN) == 0 &&
- sessRow->Sessions[i].side == side) {
- WOLFSSL_MSG("Session already exists. Overwriting.");
- overwrite = 1;
- idx = i;
- break;
- }
- }
- if (!overwrite)
- idx = sessRow->nextIdx;
- #ifdef SESSION_INDEX
- if (sessionIndex != NULL)
- *sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx;
- #endif
- cacheSession = &sessRow->Sessions[idx];
- #ifdef HAVE_EX_DATA
- if (cacheSession->rem_sess_cb && cacheSession->ownExData) {
- cacheSession->rem_sess_cb(NULL, cacheSession);
- /* Make sure not to call remove functions again */
- cacheSession->ownExData = 0;
- cacheSession->rem_sess_cb = NULL;
- }
- #endif
- cacheSession->type = WOLFSSL_SESSION_TYPE_CACHE;
- cacheSession->cacheRow = row;
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- /* Save the peer field to free after unlocking the row */
- if (cacheSession->peer != NULL)
- peer = cacheSession->peer;
- cacheSession->peer = NULL;
- #endif
- #ifdef HAVE_SESSION_TICKET
- /* If we can re-use the existing buffer in cacheSession then we won't touch
- * ticBuff at all making it a very cheap malloc/free. The page on a modern
- * OS will most likely not even be allocated to the process. */
- if (ticBuff != NULL && cacheSession->ticketLenAlloc < ticLen) {
- /* Save pointer only if separately allocated */
- if (cacheSession->ticket != cacheSession->staticTicket)
- cacheTicBuff = cacheSession->ticket;
- ticBuffUsed = 1;
- cacheSession->ticket = ticBuff;
- cacheSession->ticketLenAlloc = (word16) ticLen;
- }
- #endif
- #ifdef SESSION_CERTS
- if (overwrite &&
- addSession->chain.count == 0 &&
- cacheSession->chain.count > 0) {
- /* Copy in the certs from the session */
- addSession->chain.count = cacheSession->chain.count;
- XMEMCPY(addSession->chain.certs, cacheSession->chain.certs,
- sizeof(x509_buffer) * cacheSession->chain.count);
- }
- #endif /* SESSION_CERTS */
- cacheSession->heap = NULL;
- /* Copy data into the cache object */
- ret = wolfSSL_DupSession(addSession, cacheSession, 1) == WOLFSSL_FAILURE;
- if (ret == 0) {
- /* Increment the totalCount and the nextIdx */
- if (sessRow->totalCount < SESSIONS_PER_ROW)
- sessRow->totalCount++;
- sessRow->nextIdx = (sessRow->nextIdx + 1) % SESSIONS_PER_ROW;
- if (id != addSession->sessionID) {
- /* ssl->session->sessionID may contain the bogus ID or we want the
- * ID from the arrays object */
- XMEMCPY(cacheSession->sessionID, id, ID_LEN);
- cacheSession->sessionIDSz = ID_LEN;
- }
- #ifdef HAVE_EX_DATA
- if (ctx->rem_sess_cb != NULL) {
- addSession->ownExData = 0;
- cacheSession->ownExData = 1;
- cacheSession->rem_sess_cb = ctx->rem_sess_cb;
- }
- #endif
- }
- #ifdef HAVE_SESSION_TICKET
- else if (ticBuffUsed) {
- /* Error occured. Need to clean up the ticket buffer. */
- cacheSession->ticket = cacheSession->staticTicket;
- cacheSession->ticketLenAlloc = 0;
- cacheSession->ticketLen = 0;
- }
- #endif
- SESSION_ROW_UNLOCK(sessRow);
- cacheSession = NULL; /* Can't access after unlocked */
- #ifndef NO_CLIENT_CACHE
- if (ret == 0 && clientCacheEntry != NULL) {
- ClientSession* clientCache = AddSessionToClientCache(side, row, idx,
- addSession->serverID, addSession->idLen, id, useTicket);
- if (clientCache != NULL)
- *clientCacheEntry = clientCache;
- }
- #endif
- #ifdef HAVE_SESSION_TICKET
- if (ticBuff != NULL && !ticBuffUsed)
- XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
- if (cacheTicBuff != NULL)
- XFREE(cacheTicBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- if (peer != NULL) {
- wolfSSL_X509_free(peer);
- peer = NULL; /* Make sure not use after this point */
- }
- #endif
- return ret;
- }
- #ifndef NO_CLIENT_CACHE
- #endif
- void AddSession(WOLFSSL* ssl)
- {
- int error = 0;
- const byte* id = NULL;
- byte idSz = 0;
- WOLFSSL_SESSION* session = ssl->session;
- #ifdef HAVE_EXT_CACHE
- int cbRet = 0;
- #endif
- (void)error;
- WOLFSSL_ENTER("AddSession");
- if (SslSessionCacheOff(ssl, session)) {
- WOLFSSL_MSG("Cache off");
- return;
- }
- if (ssl->options.haveSessionId == 0) {
- WOLFSSL_MSG("Don't have session id");
- return;
- }
- #if defined(HAVE_SESSION_TICKET) && !defined(OPENSSL_EXTRA)
- /* For the compat layer generate a session object to use */
- if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) {
- WOLFSSL_MSG("Using tickets instead of cache");
- return;
- }
- #endif
- if (session->haveAltSessionID) {
- id = session->altSessionID;
- idSz = ID_LEN;
- }
- else {
- if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) {
- /* Make sure the session ID is available when the user calls any
- * get_session API */
- XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN);
- session->sessionIDSz = ssl->arrays->sessionIDSz;
- }
- id = session->sessionID;
- idSz = session->sessionIDSz;
- }
- session->timeout = ssl->timeout;
- session->side = (byte)ssl->options.side;
- if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL)
- XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN);
- session->haveEMS = ssl->options.haveEMS;
- #ifdef OPENSSL_EXTRA
- /* If using compatibility layer then check for and copy over session context
- * id. */
- if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) {
- XMEMCPY(ssl->session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz);
- session->sessionCtxSz = ssl->sessionCtxSz;
- }
- #endif
- session->timeout = ssl->timeout;
- session->bornOn = LowResTimer();
- #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
- defined(HAVE_SESSION_TICKET))
- session->version = ssl->version;
- #endif
- #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
- session->cipherSuite0 = ssl->options.cipherSuite0;
- session->cipherSuite = ssl->options.cipherSuite;
- #endif
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- session->peerVerifyRet = (byte)ssl->peerVerifyRet;
- #endif
- /* Do this last so that if it fails, the rest of the session is setup. Do
- * this only for the client because if the server doesn't have an ID at
- * this point, it won't on resumption. */
- if (idSz == 0 && ssl->options.side == WOLFSSL_CLIENT_END) {
- WC_RNG* rng = NULL;
- if (ssl->rng != NULL)
- rng = ssl->rng;
- #if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA)
- else if (initGlobalRNG == 1 || wolfSSL_RAND_Init() == WOLFSSL_SUCCESS) {
- rng = &globalRNG;
- }
- #endif
- if (wc_RNG_GenerateBlock(rng, ssl->session->altSessionID,
- ID_LEN) != 0)
- return;
- ssl->session->haveAltSessionID = 1;
- id = ssl->session->altSessionID;
- idSz = ID_LEN;
- }
- /* Setup done */
- if (ssl->options.side == WOLFSSL_SERVER_END /* No point in adding a
- * client session */
- #ifdef HAVE_EXT_CACHE
- && !ssl->options.internalCacheOff
- #endif
- )
- {
- /* Try to add the session to cache. Its ok if we don't succeed. */
- (void)AddSessionToCache(ssl->ctx, session, id, idSz,
- #ifdef SESSION_INDEX
- &ssl->sessionIndex,
- #else
- NULL,
- #endif
- ssl->options.side,
- #ifdef HAVE_SESSION_TICKET
- ssl->options.useTicket,
- #else
- 0,
- #endif
- NULL
- );
- }
- #ifdef HAVE_EXT_CACHE
- if (error == 0 && ssl->ctx->new_sess_cb != NULL) {
- wolfSSL_SESSION_up_ref(session);
- cbRet = ssl->ctx->new_sess_cb(ssl, session);
- if (cbRet == 0)
- wolfSSL_FreeSession(ssl->ctx, session);
- }
- #endif
- #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
- if (error == 0) {
- word32 active = 0;
- error = get_locked_session_stats(&active, NULL, NULL);
- if (error == WOLFSSL_SUCCESS) {
- error = 0; /* back to this function ok */
- if (PeakSessions < active) {
- PeakSessions = active;
- }
- }
- }
- #endif /* WOLFSSL_SESSION_STATS && WOLFSSL_PEAK_SESSIONS */
- (void)error;
- }
- #ifdef SESSION_INDEX
- int wolfSSL_GetSessionIndex(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_GetSessionIndex");
- WOLFSSL_LEAVE("wolfSSL_GetSessionIndex", ssl->sessionIndex);
- return ssl->sessionIndex;
- }
- int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
- {
- int row, col, result = WOLFSSL_FAILURE;
- SessionRow* sessRow;
- WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex");
- session = ClientSessionToSession(session);
- row = idx >> SESSIDX_ROW_SHIFT;
- col = idx & SESSIDX_IDX_MASK;
- if (session == NULL ||
- row < 0 || row >= SESSION_ROWS || col >= SESSIONS_PER_ROW) {
- return WOLFSSL_FAILURE;
- }
- sessRow = &SessionCache[row];
- if (SESSION_ROW_LOCK(sessRow) != 0) {
- return BAD_MUTEX_E;
- }
- XMEMCPY(session, &sessRow->Sessions[col], sizeof(WOLFSSL_SESSION));
- result = WOLFSSL_SUCCESS;
- SESSION_ROW_UNLOCK(sessRow);
- WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result);
- return result;
- }
- #endif /* SESSION_INDEX */
- #if defined(SESSION_CERTS)
- WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session)
- {
- WOLFSSL_X509_CHAIN* chain = NULL;
- WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
- session = ClientSessionToSession(session);
- if (session)
- chain = &session->chain;
- WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0);
- return chain;
- }
- #ifdef OPENSSL_EXTRA
- /* gets the peer certificate associated with the session passed in
- * returns null on failure, the caller should not free the returned pointer */
- WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session)
- {
- WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
- session = ClientSessionToSession(session);
- if (session) {
- int count;
- count = wolfSSL_get_chain_count(&session->chain);
- if (count < 1 || count >= MAX_CHAIN_DEPTH) {
- WOLFSSL_MSG("bad count found");
- return NULL;
- }
- if (session->peer == NULL) {
- session->peer = wolfSSL_get_chain_X509(&session->chain, 0);
- }
- return session->peer;
- }
- WOLFSSL_MSG("No session passed in");
- return NULL;
- }
- #endif /* OPENSSL_EXTRA */
- #endif /* SESSION_INDEX && SESSION_CERTS */
- #ifdef WOLFSSL_SESSION_STATS
- static int get_locked_session_stats(word32* active, word32* total, word32* peak)
- {
- int result = WOLFSSL_SUCCESS;
- int i;
- int count;
- int idx;
- word32 now = 0;
- word32 seen = 0;
- word32 ticks = LowResTimer();
- WOLFSSL_ENTER("get_locked_session_stats");
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- wc_LockMutex(&session_mutex);
- #endif
- for (i = 0; i < SESSION_ROWS; i++) {
- SessionRow* row = &SessionCache[i];
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- if (SESSION_ROW_LOCK(row) != 0) {
- WOLFSSL_MSG("Session row cache mutex lock failed");
- return BAD_MUTEX_E;
- }
- #endif
- seen += row->totalCount;
- if (active == NULL) {
- SESSION_ROW_UNLOCK(row);
- continue;
- }
- count = min((word32)row->totalCount, SESSIONS_PER_ROW);
- idx = row->nextIdx - 1;
- if (idx < 0 || idx >= SESSIONS_PER_ROW) {
- idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */
- }
- for (; count > 0; --count) {
- /* if not expired then good */
- if (ticks < (row->Sessions[idx].bornOn +
- row->Sessions[idx].timeout) ) {
- now++;
- }
- idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1;
- }
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- SESSION_ROW_UNLOCK(row);
- #endif
- }
- #ifndef ENABLE_SESSION_CACHE_ROW_LOCK
- wc_UnLockMutex(&session_mutex);
- #endif
- if (active) {
- *active = now;
- }
- if (total) {
- *total = seen;
- }
- #ifdef WOLFSSL_PEAK_SESSIONS
- if (peak) {
- *peak = PeakSessions;
- }
- #else
- (void)peak;
- #endif
- WOLFSSL_LEAVE("get_locked_session_stats", result);
- return result;
- }
- /* return WOLFSSL_SUCCESS on ok */
- int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
- word32* maxSessions)
- {
- int result = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_get_session_stats");
- if (maxSessions) {
- *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS;
- if (active == NULL && total == NULL && peak == NULL)
- return result; /* we're done */
- }
- /* user must provide at least one query value */
- if (active == NULL && total == NULL && peak == NULL) {
- return BAD_FUNC_ARG;
- }
- result = get_locked_session_stats(active, total, peak);
- WOLFSSL_LEAVE("wolfSSL_get_session_stats", result);
- return result;
- }
- #endif /* WOLFSSL_SESSION_STATS */
- #ifdef PRINT_SESSION_STATS
- /* WOLFSSL_SUCCESS on ok */
- int wolfSSL_PrintSessionStats(void)
- {
- word32 totalSessionsSeen = 0;
- word32 totalSessionsNow = 0;
- word32 peak = 0;
- word32 maxSessions = 0;
- int i;
- int ret;
- double E; /* expected freq */
- double chiSquare = 0;
- ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen,
- &peak, &maxSessions);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- printf("Total Sessions Seen = %u\n", totalSessionsSeen);
- printf("Total Sessions Now = %u\n", totalSessionsNow);
- #ifdef WOLFSSL_PEAK_SESSIONS
- printf("Peak Sessions = %u\n", peak);
- #endif
- printf("Max Sessions = %u\n", maxSessions);
- E = (double)totalSessionsSeen / SESSION_ROWS;
- for (i = 0; i < SESSION_ROWS; i++) {
- double diff = SessionCache[i].totalCount - E;
- diff *= diff; /* square */
- diff /= E; /* normalize */
- chiSquare += diff;
- }
- printf(" chi-square = %5.1f, d.f. = %d\n", chiSquare,
- SESSION_ROWS - 1);
- #if (SESSION_ROWS == 11)
- printf(" .05 p value = 18.3, chi-square should be less\n");
- #elif (SESSION_ROWS == 211)
- printf(".05 p value = 244.8, chi-square should be less\n");
- #elif (SESSION_ROWS == 5981)
- printf(".05 p value = 6161.0, chi-square should be less\n");
- #elif (SESSION_ROWS == 3)
- printf(".05 p value = 6.0, chi-square should be less\n");
- #elif (SESSION_ROWS == 2861)
- printf(".05 p value = 2985.5, chi-square should be less\n");
- #endif
- printf("\n");
- return ret;
- }
- #endif /* SESSION_STATS */
- #else /* NO_SESSION_CACHE */
- WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session)
- {
- return (WOLFSSL_SESSION*)session;
- }
- /* No session cache version */
- WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret,
- byte restoreSessionCerts)
- {
- (void)ssl;
- (void)masterSecret;
- (void)restoreSessionCerts;
- return NULL;
- }
- #endif /* NO_SESSION_CACHE */
- /* call before SSL_connect, if verifying will add name check to
- date check and signature check */
- WOLFSSL_ABI
- int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
- {
- WOLFSSL_ENTER("wolfSSL_check_domain_name");
- if (ssl == NULL || dn == NULL) {
- WOLFSSL_MSG("Bad function argument: NULL");
- return WOLFSSL_FAILURE;
- }
- if (ssl->buffers.domainName.buffer)
- XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
- ssl->buffers.domainName.length = (word32)XSTRLEN(dn);
- ssl->buffers.domainName.buffer = (byte*)XMALLOC(
- ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN);
- if (ssl->buffers.domainName.buffer) {
- unsigned char* domainName = ssl->buffers.domainName.buffer;
- XMEMCPY(domainName, dn, ssl->buffers.domainName.length);
- domainName[ssl->buffers.domainName.length] = '\0';
- return WOLFSSL_SUCCESS;
- }
- else {
- ssl->error = MEMORY_ERROR;
- return WOLFSSL_FAILURE;
- }
- }
- /* turn on wolfSSL zlib compression
- returns WOLFSSL_SUCCESS for success, else error (not built in)
- */
- int wolfSSL_set_compression(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_set_compression");
- (void)ssl;
- #ifdef HAVE_LIBZ
- ssl->options.usingCompression = 1;
- return WOLFSSL_SUCCESS;
- #else
- return NOT_COMPILED_IN;
- #endif
- }
- #ifndef USE_WINDOWS_API
- #ifndef NO_WRITEV
- /* simulate writev semantics, doesn't actually do block at a time though
- because of SSL_write behavior and because front adds may be small */
- int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt)
- {
- #ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
- #else
- byte staticBuffer[FILE_BUFFER_SIZE];
- #endif
- byte* myBuffer = staticBuffer;
- int dynamic = 0;
- int sending = 0;
- int idx = 0;
- int i;
- int ret;
- WOLFSSL_ENTER("wolfSSL_writev");
- for (i = 0; i < iovcnt; i++)
- sending += (int)iov[i].iov_len;
- if (sending > (int)sizeof(staticBuffer)) {
- myBuffer = (byte*)XMALLOC(sending, ssl->heap,
- DYNAMIC_TYPE_WRITEV);
- if (!myBuffer)
- return MEMORY_ERROR;
- dynamic = 1;
- }
- for (i = 0; i < iovcnt; i++) {
- XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len);
- idx += (int)iov[i].iov_len;
- }
- /* myBuffer may not be initialized fully, but the span up to the
- * sending length will be.
- */
- PRAGMA_GCC_DIAG_PUSH;
- PRAGMA_GCC("GCC diagnostic ignored \"-Wmaybe-uninitialized\"");
- ret = wolfSSL_write(ssl, myBuffer, sending);
- PRAGMA_GCC_DIAG_POP;
- if (dynamic)
- XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
- return ret;
- }
- #endif
- #endif
- #ifdef WOLFSSL_CALLBACKS
- typedef struct itimerval Itimerval;
- /* don't keep calling simple functions while setting up timer and signals
- if no inlining these are the next best */
- #define AddTimes(a, b, c) \
- do { \
- c.tv_sec = a.tv_sec + b.tv_sec; \
- c.tv_usec = a.tv_usec + b.tv_usec; \
- if (c.tv_usec >= 1000000) { \
- c.tv_sec++; \
- c.tv_usec -= 1000000; \
- } \
- } while (0)
- #define SubtractTimes(a, b, c) \
- do { \
- c.tv_sec = a.tv_sec - b.tv_sec; \
- c.tv_usec = a.tv_usec - b.tv_usec; \
- if (c.tv_usec < 0) { \
- c.tv_sec--; \
- c.tv_usec += 1000000; \
- } \
- } while (0)
- #define CmpTimes(a, b, cmp) \
- ((a.tv_sec == b.tv_sec) ? \
- (a.tv_usec cmp b.tv_usec) : \
- (a.tv_sec cmp b.tv_sec)) \
- /* do nothing handler */
- static void myHandler(int signo)
- {
- (void)signo;
- return;
- }
- static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
- {
- int ret = WOLFSSL_FATAL_ERROR;
- int oldTimerOn = 0; /* was timer already on */
- WOLFSSL_TIMEVAL startTime;
- WOLFSSL_TIMEVAL endTime;
- WOLFSSL_TIMEVAL totalTime;
- Itimerval myTimeout;
- Itimerval oldTimeout; /* if old timer adjust from total time to reset */
- struct sigaction act, oact;
- #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
- if (hsCb) {
- ssl->hsInfoOn = 1;
- InitHandShakeInfo(&ssl->handShakeInfo, ssl);
- }
- if (toCb) {
- ssl->toInfoOn = 1;
- InitTimeoutInfo(&ssl->timeoutInfo);
- if (gettimeofday(&startTime, 0) < 0)
- ERR_OUT(GETTIME_ERROR);
- /* use setitimer to simulate getitimer, init 0 myTimeout */
- myTimeout.it_interval.tv_sec = 0;
- myTimeout.it_interval.tv_usec = 0;
- myTimeout.it_value.tv_sec = 0;
- myTimeout.it_value.tv_usec = 0;
- if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0)
- ERR_OUT(SETITIMER_ERROR);
- if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) {
- oldTimerOn = 1;
- /* is old timer going to expire before ours */
- if (CmpTimes(oldTimeout.it_value, timeout, <)) {
- timeout.tv_sec = oldTimeout.it_value.tv_sec;
- timeout.tv_usec = oldTimeout.it_value.tv_usec;
- }
- }
- myTimeout.it_value.tv_sec = timeout.tv_sec;
- myTimeout.it_value.tv_usec = timeout.tv_usec;
- /* set up signal handler, don't restart socket send/recv */
- act.sa_handler = myHandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- #ifdef SA_INTERRUPT
- act.sa_flags |= SA_INTERRUPT;
- #endif
- if (sigaction(SIGALRM, &act, &oact) < 0)
- ERR_OUT(SIGACT_ERROR);
- if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
- ERR_OUT(SETITIMER_ERROR);
- }
- /* do main work */
- #ifndef NO_WOLFSSL_CLIENT
- if (ssl->options.side == WOLFSSL_CLIENT_END)
- ret = wolfSSL_connect(ssl);
- #endif
- #ifndef NO_WOLFSSL_SERVER
- if (ssl->options.side == WOLFSSL_SERVER_END)
- ret = wolfSSL_accept(ssl);
- #endif
- /* do callbacks */
- if (toCb) {
- if (oldTimerOn) {
- gettimeofday(&endTime, 0);
- SubtractTimes(endTime, startTime, totalTime);
- /* adjust old timer for elapsed time */
- if (CmpTimes(totalTime, oldTimeout.it_value, <))
- SubtractTimes(oldTimeout.it_value, totalTime,
- oldTimeout.it_value);
- else {
- /* reset value to interval, may be off */
- oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec;
- oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec;
- }
- /* keep iter the same whether there or not */
- }
- /* restore old handler */
- if (sigaction(SIGALRM, &oact, 0) < 0)
- ret = SIGACT_ERROR; /* more pressing error, stomp */
- else
- /* use old settings which may turn off (expired or not there) */
- if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0)
- ret = SETITIMER_ERROR;
- /* if we had a timeout call callback */
- if (ssl->timeoutInfo.timeoutName[0]) {
- ssl->timeoutInfo.timeoutValue.tv_sec = timeout.tv_sec;
- ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec;
- (toCb)(&ssl->timeoutInfo);
- }
- ssl->toInfoOn = 0;
- }
- /* clean up buffers allocated by AddPacketInfo */
- FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
- if (hsCb) {
- FinishHandShakeInfo(&ssl->handShakeInfo);
- (hsCb)(&ssl->handShakeInfo);
- ssl->hsInfoOn = 0;
- }
- return ret;
- }
- #ifndef NO_WOLFSSL_CLIENT
- int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
- {
- WOLFSSL_ENTER("wolfSSL_connect_ex");
- return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
- }
- #endif
- #ifndef NO_WOLFSSL_SERVER
- int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
- {
- WOLFSSL_ENTER("wolfSSL_accept_ex");
- return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
- }
- #endif
- #endif /* WOLFSSL_CALLBACKS */
- #ifndef NO_PSK
- void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx,
- wc_psk_client_callback cb)
- {
- WOLFSSL_ENTER("SSL_CTX_set_psk_client_callback");
- if (ctx == NULL)
- return;
- ctx->havePSK = 1;
- ctx->client_psk_cb = cb;
- }
- void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb)
- {
- byte haveRSA = 1;
- int keySz = 0;
- WOLFSSL_ENTER("SSL_set_psk_client_callback");
- if (ssl == NULL)
- return;
- ssl->options.havePSK = 1;
- ssl->options.client_psk_cb = cb;
- #ifdef NO_RSA
- haveRSA = 0;
- #endif
- #ifndef NO_CERTS
- keySz = ssl->buffers.keySz;
- #endif
- InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
- ssl->options.haveDH, ssl->options.haveECDSAsig,
- ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
- ssl->options.haveFalconSig, ssl->options.haveDilithiumSig,
- ssl->options.haveAnon, TRUE, ssl->options.side);
- }
- #ifdef OPENSSL_EXTRA
- /**
- * set call back function for psk session use
- * @param ssl a pointer to WOLFSSL structure
- * @param cb a function pointer to wc_psk_use_session_cb
- * @return none
- */
- void wolfSSL_set_psk_use_session_callback(WOLFSSL* ssl,
- wc_psk_use_session_cb_func cb)
- {
- WOLFSSL_ENTER("wolfSSL_set_psk_use_session_callback");
- ssl->options.havePSK = 1;
- ssl->options.session_psk_cb = cb;
- WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", WOLFSSL_SUCCESS);
- }
- #endif
- void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx,
- wc_psk_server_callback cb)
- {
- WOLFSSL_ENTER("SSL_CTX_set_psk_server_callback");
- if (ctx == NULL)
- return;
- ctx->havePSK = 1;
- ctx->server_psk_cb = cb;
- }
- void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb)
- {
- byte haveRSA = 1;
- int keySz = 0;
- WOLFSSL_ENTER("SSL_set_psk_server_callback");
- if (ssl == NULL)
- return;
- ssl->options.havePSK = 1;
- ssl->options.server_psk_cb = cb;
- #ifdef NO_RSA
- haveRSA = 0;
- #endif
- #ifndef NO_CERTS
- keySz = ssl->buffers.keySz;
- #endif
- InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
- ssl->options.haveDH, ssl->options.haveECDSAsig,
- ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
- ssl->options.haveFalconSig, ssl->options.haveDilithiumSig,
- ssl->options.haveAnon, TRUE, ssl->options.side);
- }
- const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_get_psk_identity_hint");
- if (ssl == NULL || ssl->arrays == NULL)
- return NULL;
- return ssl->arrays->server_hint;
- }
- const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_get_psk_identity");
- if (ssl == NULL || ssl->arrays == NULL)
- return NULL;
- return ssl->arrays->client_identity;
- }
- int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX* ctx, const char* hint)
- {
- WOLFSSL_ENTER("SSL_CTX_use_psk_identity_hint");
- if (hint == 0)
- ctx->server_hint[0] = '\0';
- else {
- /* Qt does not call CTX_set_*_psk_callbacks where havePSK is set */
- #ifdef WOLFSSL_QT
- ctx->havePSK=1;
- #endif
- XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN);
- ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint)
- {
- WOLFSSL_ENTER("SSL_use_psk_identity_hint");
- if (ssl == NULL || ssl->arrays == NULL)
- return WOLFSSL_FAILURE;
- if (hint == 0)
- ssl->arrays->server_hint[0] = 0;
- else {
- XSTRNCPY(ssl->arrays->server_hint, hint,
- sizeof(ssl->arrays->server_hint)-1);
- ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0';
- }
- return WOLFSSL_SUCCESS;
- }
- void* wolfSSL_get_psk_callback_ctx(WOLFSSL* ssl)
- {
- return ssl ? ssl->options.psk_ctx : NULL;
- }
- void* wolfSSL_CTX_get_psk_callback_ctx(WOLFSSL_CTX* ctx)
- {
- return ctx ? ctx->psk_ctx : NULL;
- }
- int wolfSSL_set_psk_callback_ctx(WOLFSSL* ssl, void* psk_ctx)
- {
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- ssl->options.psk_ctx = psk_ctx;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_set_psk_callback_ctx(WOLFSSL_CTX* ctx, void* psk_ctx)
- {
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
- ctx->psk_ctx = psk_ctx;
- return WOLFSSL_SUCCESS;
- }
- #endif /* NO_PSK */
- #ifdef HAVE_ANON
- int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher");
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
- ctx->haveAnon = 1;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_ANON */
- #ifndef NO_CERTS
- /* used to be defined on NO_FILESYSTEM only, but are generally useful */
- int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx,
- const unsigned char* in,
- long sz, int format, int userChain,
- word32 flags)
- {
- int verify;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex");
- verify = GET_VERIFY_SETTING_CTX(ctx);
- if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
- verify = VERIFY_SKIP_DATE;
- if (format == WOLFSSL_FILETYPE_PEM)
- ret = ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL,
- verify);
- else
- ret = ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL,
- userChain, verify);
- #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
- if (ret == WOLFSSL_SUCCESS)
- ret = wolfSSL_CTX_trust_peer_buffer(ctx, in, sz, format);
- #endif
- WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret);
- return ret;
- }
- /* wolfSSL extension allows DER files to be loaded from buffers as well */
- int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx,
- const unsigned char* in,
- long sz, int format)
- {
- return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0,
- WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
- }
- int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx,
- const unsigned char* in,
- long sz, int format)
- {
- return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1,
- WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx,
- const unsigned char* in,
- long sz, int format)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer");
- /* sanity check on arguments */
- if (sz < 0 || in == NULL || ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- if (format == WOLFSSL_FILETYPE_PEM)
- return ProcessChainBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE,
- NULL, GET_VERIFY_SETTING_CTX(ctx));
- else
- return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL,
- NULL, 0, GET_VERIFY_SETTING_CTX(ctx));
- }
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
- const unsigned char* in, long sz, int format)
- {
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer");
- ret = ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0,
- GET_VERIFY_SETTING_CTX(ctx));
- WOLFSSL_LEAVE("wolfSSL_CTX_use_certificate_buffer", ret);
- return ret;
- }
- int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx,
- const unsigned char* in, long sz, int format)
- {
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer");
- ret = ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, NULL,
- 0, GET_VERIFY_SETTING_CTX(ctx));
- WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_buffer", ret);
- return ret;
- }
- #ifdef WOLF_PRIVATE_KEY_ID
- int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
- long sz, int devId, long keySz)
- {
- int ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId);
- if (ret == WOLFSSL_SUCCESS)
- ctx->privateKeySz = (word32)keySz;
- return ret;
- }
- int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
- long sz, int devId)
- {
- int ret = WOLFSSL_FAILURE;
- FreeDer(&ctx->privateKey);
- if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE,
- ctx->heap) == 0) {
- XMEMCPY(ctx->privateKey->buffer, id, sz);
- ctx->privateKeyId = 1;
- if (devId != INVALID_DEVID)
- ctx->privateKeyDevId = devId;
- else
- ctx->privateKeyDevId = ctx->devId;
- ret = WOLFSSL_SUCCESS;
- }
- return ret;
- }
- int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
- int devId)
- {
- int ret = WOLFSSL_FAILURE;
- word32 sz = (word32)XSTRLEN(label) + 1;
- FreeDer(&ctx->privateKey);
- if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE,
- ctx->heap) == 0) {
- XMEMCPY(ctx->privateKey->buffer, label, sz);
- ctx->privateKeyLabel = 1;
- if (devId != INVALID_DEVID)
- ctx->privateKeyDevId = devId;
- else
- ctx->privateKeyDevId = ctx->devId;
- ret = WOLFSSL_SUCCESS;
- }
- return ret;
- }
- #endif /* WOLF_PRIVATE_KEY_ID */
- int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
- const unsigned char* in, long sz, int format)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
- return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1,
- GET_VERIFY_SETTING_CTX(ctx));
- }
- int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
- const unsigned char* in, long sz)
- {
- return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
- WOLFSSL_FILETYPE_PEM);
- }
- #ifndef NO_DH
- /* server wrapper for ctx or ssl Diffie-Hellman parameters */
- static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- const unsigned char* buf,
- long sz, int format)
- {
- DerBuffer* der = NULL;
- int ret = 0;
- word32 pSz = MAX_DH_SIZE;
- word32 gSz = MAX_DH_SIZE;
- #ifdef WOLFSSL_SMALL_STACK
- byte* p = NULL;
- byte* g = NULL;
- #else
- byte p[MAX_DH_SIZE];
- byte g[MAX_DH_SIZE];
- #endif
- if (ctx == NULL || buf == NULL)
- return BAD_FUNC_ARG;
- ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap);
- if (ret != 0) {
- return ret;
- }
- der->buffer = (byte*)buf;
- der->length = (word32)sz;
- #ifdef WOLFSSL_SMALL_STACK
- p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- if (p == NULL || g == NULL) {
- XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- return MEMORY_E;
- }
- #endif
- if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)
- ret = WOLFSSL_BAD_FILETYPE;
- else {
- if (format == WOLFSSL_FILETYPE_PEM) {
- #ifdef WOLFSSL_PEM_TO_DER
- FreeDer(&der);
- ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap,
- NULL, NULL);
- if (ret < 0) {
- /* Also try X9.42 format */
- ret = PemToDer(buf, sz, X942_PARAM_TYPE, &der, ctx->heap,
- NULL, NULL);
- }
- #ifdef WOLFSSL_WPAS
- #ifndef NO_DSA
- if (ret < 0) {
- ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap,
- NULL, NULL);
- }
- #endif
- #endif /* WOLFSSL_WPAS */
- #else
- ret = NOT_COMPILED_IN;
- #endif /* WOLFSSL_PEM_TO_DER */
- }
- if (ret == 0) {
- if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0)
- ret = WOLFSSL_BAD_FILETYPE;
- else if (ssl)
- ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
- else
- ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
- }
- }
- FreeDer(&der);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- #endif
- return ret;
- }
- /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
- int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
- int format)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
- }
- /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
- int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
- long sz, int format)
- {
- return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format);
- }
- #endif /* NO_DH */
- int wolfSSL_use_certificate_buffer(WOLFSSL* ssl,
- const unsigned char* in, long sz, int format)
- {
- WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0,
- GET_VERIFY_SETTING_SSL(ssl));
- }
- int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl,
- const unsigned char* in, long sz, int format)
- {
- WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE,
- ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl));
- }
- #ifdef WOLF_PRIVATE_KEY_ID
- int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id,
- long sz, int devId, long keySz)
- {
- int ret = wolfSSL_use_PrivateKey_Id(ssl, id, sz, devId);
- if (ret == WOLFSSL_SUCCESS)
- ssl->buffers.keySz = (word32)keySz;
- return ret;
- }
- int wolfSSL_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id,
- long sz, int devId)
- {
- int ret = WOLFSSL_FAILURE;
- if (ssl->buffers.weOwnKey)
- FreeDer(&ssl->buffers.key);
- if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE,
- ssl->heap) == 0) {
- XMEMCPY(ssl->buffers.key->buffer, id, sz);
- ssl->buffers.weOwnKey = 1;
- ssl->buffers.keyId = 1;
- if (devId != INVALID_DEVID)
- ssl->buffers.keyDevId = devId;
- else
- ssl->buffers.keyDevId = ssl->devId;
- ret = WOLFSSL_SUCCESS;
- }
- return ret;
- }
- int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId)
- {
- int ret = WOLFSSL_FAILURE;
- word32 sz = (word32)XSTRLEN(label) + 1;
- if (ssl->buffers.weOwnKey)
- FreeDer(&ssl->buffers.key);
- if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE,
- ssl->heap) == 0) {
- XMEMCPY(ssl->buffers.key->buffer, label, sz);
- ssl->buffers.weOwnKey = 1;
- ssl->buffers.keyLabel = 1;
- if (devId != INVALID_DEVID)
- ssl->buffers.keyDevId = devId;
- else
- ssl->buffers.keyDevId = ssl->devId;
- ret = WOLFSSL_SUCCESS;
- }
- return ret;
- }
- #endif /* WOLF_PRIVATE_KEY_ID */
- int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl,
- const unsigned char* in, long sz, int format)
- {
- WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE,
- ssl, NULL, 1, GET_VERIFY_SETTING_SSL(ssl));
- }
- int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl,
- const unsigned char* in, long sz)
- {
- return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
- WOLFSSL_FILETYPE_PEM);
- }
- /* unload any certs or keys that SSL owns, leave CTX as is
- WOLFSSL_SUCCESS on ok */
- int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- WOLFSSL_MSG("Null function arg");
- return BAD_FUNC_ARG;
- }
- if (ssl->buffers.weOwnCert && !ssl->keepCert) {
- WOLFSSL_MSG("Unloading cert");
- FreeDer(&ssl->buffers.certificate);
- #ifdef KEEP_OUR_CERT
- wolfSSL_X509_free(ssl->ourCert);
- ssl->ourCert = NULL;
- #endif
- ssl->buffers.weOwnCert = 0;
- }
- if (ssl->buffers.weOwnCertChain) {
- WOLFSSL_MSG("Unloading cert chain");
- FreeDer(&ssl->buffers.certChain);
- ssl->buffers.weOwnCertChain = 0;
- }
- if (ssl->buffers.weOwnKey) {
- WOLFSSL_MSG("Unloading key");
- ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
- FreeDer(&ssl->buffers.key);
- ssl->buffers.weOwnKey = 0;
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_CertManagerUnloadCAs(ctx->cm);
- }
- #ifdef WOLFSSL_TRUST_PEER_CERT
- int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
- }
- #ifdef WOLFSSL_LOCAL_X509_STORE
- int wolfSSL_Unload_trust_peers(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl));
- }
- #endif /* WOLFSSL_LOCAL_X509_STORE */
- #endif /* WOLFSSL_TRUST_PEER_CERT */
- /* old NO_FILESYSTEM end */
- #endif /* !NO_CERTS */
- #ifdef OPENSSL_EXTRA
- int wolfSSL_add_all_algorithms(void)
- {
- WOLFSSL_ENTER("wolfSSL_add_all_algorithms");
- if (initRefCount != 0 || wolfSSL_Init() == WOLFSSL_SUCCESS)
- return WOLFSSL_SUCCESS;
- else
- return WOLFSSL_FATAL_ERROR;
- }
- int wolfSSL_OpenSSL_add_all_algorithms_noconf(void)
- {
- WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf");
- if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR)
- return WOLFSSL_FATAL_ERROR;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_OpenSSL_add_all_algorithms_conf(void)
- {
- WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_conf");
- /* This function is currently the same as
- wolfSSL_OpenSSL_add_all_algorithms_noconf since we do not employ
- the use of a wolfssl.cnf type configuration file and is only used for
- OpenSSL compatability. */
- if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) {
- return WOLFSSL_FATAL_ERROR;
- }
- return WOLFSSL_SUCCESS;
- }
- /* returns previous set cache size which stays constant */
- long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz)
- {
- /* cache size fixed at compile time in wolfSSL */
- (void)ctx;
- (void)sz;
- WOLFSSL_MSG("session cache is set at compile time");
- #ifndef NO_SESSION_CACHE
- return (long)(SESSIONS_PER_ROW * SESSION_ROWS);
- #else
- return 0;
- #endif
- }
- #endif
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
- if (mode)
- ctx->quietShutdown = 1;
- }
- void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
- if (mode)
- ssl->options.quietShutdown = 1;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #ifdef OPENSSL_EXTRA
- #ifndef NO_BIO
- void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr)
- {
- WOLFSSL_ENTER("wolfSSL_set_bio");
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument, ssl was NULL");
- return;
- }
- /* free any existing WOLFSSL_BIOs in use but don't free those in
- * a chain */
- if (ssl->biord != NULL) {
- if (ssl->biord != ssl->biowr) {
- if (ssl->biowr != NULL && ssl->biowr->prev != NULL)
- wolfSSL_BIO_free(ssl->biowr);
- ssl->biowr = NULL;
- }
- if (ssl->biord->prev != NULL)
- wolfSSL_BIO_free(ssl->biord);
- ssl->biord = NULL;
- }
- /* set flag obviously */
- if (rd && !(rd->flags & WOLFSSL_BIO_FLAG_READ))
- rd->flags |= WOLFSSL_BIO_FLAG_READ;
- if (wr && !(wr->flags & WOLFSSL_BIO_FLAG_WRITE))
- wr->flags |= WOLFSSL_BIO_FLAG_WRITE;
- ssl->biord = rd;
- ssl->biowr = wr;
- /* set SSL to use BIO callbacks instead */
- if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0)) {
- ssl->CBIORecv = BioReceive;
- }
- if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0)) {
- ssl->CBIOSend = BioSend;
- }
- /* User programs should always retry reading from these BIOs */
- if (rd) {
- /* User writes to rd */
- BIO_set_retry_write(rd);
- }
- if (wr) {
- /* User reads from wr */
- BIO_set_retry_read(wr);
- }
- }
- #endif /* !NO_BIO */
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
- void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
- if (ctx != NULL) {
- wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
- ctx->ca_names = names;
- }
- }
- void wolfSSL_set_client_CA_list(WOLFSSL* ssl,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_set_client_CA_list");
- if (ssl != NULL) {
- if (ssl->ca_names != ssl->ctx->ca_names)
- wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
- ssl->ca_names = names;
- }
- }
- #ifdef OPENSSL_EXTRA
- /* registers client cert callback, called during handshake if server
- requests client auth but user has not loaded client cert/key */
- void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb");
- if (ctx != NULL) {
- ctx->CBClientCert = cb;
- }
- }
- void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx,
- CertSetupCallback cb, void *arg)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb");
- if (ctx == NULL)
- return;
- ctx->certSetupCb = cb;
- ctx->certSetupCbArg = arg;
- }
- /**
- * Internal wrapper for calling certSetupCb
- * @param ssl The SSL/TLS Object
- * @return 0 on success
- */
- int CertSetupCbWrapper(WOLFSSL* ssl)
- {
- int ret = 0;
- if (ssl->ctx->certSetupCb != NULL) {
- WOLFSSL_MSG("Calling user cert setup callback");
- ret = ssl->ctx->certSetupCb(ssl, ssl->ctx->certSetupCbArg);
- if (ret == 1) {
- WOLFSSL_MSG("User cert callback returned success");
- ret = 0;
- }
- else if (ret == 0) {
- SendAlert(ssl, alert_fatal, internal_error);
- ret = CLIENT_CERT_CB_ERROR;
- }
- else if (ret < 0) {
- ret = WOLFSSL_ERROR_WANT_X509_LOOKUP;
- }
- else {
- WOLFSSL_MSG("Unexpected user callback return");
- ret = CLIENT_CERT_CB_ERROR;
- }
- }
- return ret;
- }
- #endif /* OPENSSL_EXTRA */
- #endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
- const WOLFSSL_CTX *ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list");
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list");
- return NULL;
- }
- return ctx->ca_names;
- }
- /* returns the CA's set on server side or the CA's sent from server when
- * on client side */
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(
- const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
- return NULL;
- }
- return SSL_CA_NAMES(ssl);
- }
- #if !defined(NO_CERTS)
- int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
- {
- WOLFSSL_X509_NAME *nameCopy = NULL;
- WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
- if (ctx == NULL || x509 == NULL){
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
- }
- if (ctx->ca_names == NULL) {
- ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
- if (ctx->ca_names == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- return WOLFSSL_FAILURE;
- }
- }
- nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509));
- if (nameCopy == NULL) {
- WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
- return WOLFSSL_FAILURE;
- }
- if (wolfSSL_sk_X509_NAME_push(ctx->ca_names, nameCopy) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
- wolfSSL_X509_NAME_free(nameCopy);
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif
- #ifndef NO_BIO
- #if !defined(NO_RSA) && !defined(NO_CERTS)
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
- {
- /* The webserver build is using this to load a CA into the server
- * for client authentication as an option. Have this return NULL in
- * that case. If OPENSSL_EXTRA is enabled, go ahead and include
- * the function. */
- #ifdef OPENSSL_EXTRA
- WOLFSSL_STACK *list = NULL;
- WOLFSSL_BIO* bio = NULL;
- WOLFSSL_X509 *cert = NULL;
- WOLFSSL_X509_NAME *nameCopy = NULL;
- unsigned long err = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
- bio = wolfSSL_BIO_new_file(fname, "rb");
- if (bio == NULL) {
- WOLFSSL_MSG("wolfSSL_BIO_new_file error");
- goto cleanup;
- }
- list = wolfSSL_sk_X509_NAME_new(NULL);
- if (list == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- goto cleanup;
- }
- /* Read each certificate in the chain out of the file. */
- while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
- /* Need a persistent copy of the subject name. */
- nameCopy = wolfSSL_X509_NAME_dup(
- wolfSSL_X509_get_subject_name(cert));
- if (nameCopy == NULL) {
- WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
- goto cleanup;
- }
- /*
- * Original cert will be freed so make sure not to try to access
- * it in the future.
- */
- nameCopy->x509 = NULL;
- if (wolfSSL_sk_X509_NAME_push(list, nameCopy) !=
- WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
- /* Do free in loop because nameCopy is now responsibility
- * of list to free and adding jumps to cleanup after this
- * might result in a double free. */
- wolfSSL_X509_NAME_free(nameCopy);
- goto cleanup;
- }
- wolfSSL_X509_free(cert);
- cert = NULL;
- }
- CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
- err = WOLFSSL_SUCCESS;
- cleanup:
- wolfSSL_X509_free(cert);
- wolfSSL_BIO_free(bio);
- if (err != WOLFSSL_SUCCESS) {
- /* We failed so return NULL */
- wolfSSL_sk_X509_NAME_pop_free(list, NULL);
- list = NULL;
- }
- return list;
- #else
- (void)fname;
- return NULL;
- #endif
- }
- #endif
- #endif /* !NO_BIO */
- #endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
- #ifdef OPENSSL_EXTRA
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
- {
- /* TODO:, not needed in goahead */
- (void)ctx;
- WOLFSSL_STUB("SSL_CTX_set_default_verify_paths");
- return SSL_NOT_IMPLEMENTED;
- }
- #endif
- #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
- && !defined(WC_NO_RNG)
- static const byte srp_N[] = {
- 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8,
- 0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF,
- 0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6,
- 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13,
- 0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B,
- 0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7,
- 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69,
- 0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
- 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC,
- 0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E,
- 0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F,
- 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
- };
- static const byte srp_g[] = {
- 0x02
- };
- int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username)
- {
- int r = 0;
- SrpSide srp_side = SRP_CLIENT_SIDE;
- byte salt[SRP_SALT_SIZE];
- WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username");
- if (ctx == NULL || ctx->srp == NULL || username==NULL)
- return SSL_FAILURE;
- if (ctx->method->side == WOLFSSL_SERVER_END){
- srp_side = SRP_SERVER_SIDE;
- } else if (ctx->method->side == WOLFSSL_CLIENT_END){
- srp_side = SRP_CLIENT_SIDE;
- } else {
- WOLFSSL_MSG("Init CTX failed");
- return SSL_FAILURE;
- }
- if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0) {
- WOLFSSL_MSG("Init SRP CTX failed");
- XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp = NULL;
- return SSL_FAILURE;
- }
- r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
- (word32)XSTRLEN(username));
- if (r < 0) {
- WOLFSSL_MSG("fail to set srp username.");
- return SSL_FAILURE;
- }
- /* if wolfSSL_CTX_set_srp_password has already been called, */
- /* execute wc_SrpSetPassword here */
- if (ctx->srp_password != NULL) {
- WC_RNG rng;
- if (wc_InitRng(&rng) < 0){
- WOLFSSL_MSG("wc_InitRng failed");
- return SSL_FAILURE;
- }
- XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
- r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0]));
- wc_FreeRng(&rng);
- if (r < 0) {
- WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
- return SSL_FAILURE;
- }
- if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
- srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
- salt, sizeof(salt)/sizeof(salt[0])) < 0) {
- WOLFSSL_MSG("wc_SrpSetParam failed");
- return SSL_FAILURE;
- }
- r = wc_SrpSetPassword(ctx->srp,
- (const byte*)ctx->srp_password,
- (word32)XSTRLEN((char *)ctx->srp_password));
- if (r < 0) {
- WOLFSSL_MSG("fail to set srp password.");
- return SSL_FAILURE;
- }
- XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp_password = NULL;
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
- {
- int r;
- byte salt[SRP_SALT_SIZE];
- WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
- if (ctx == NULL || ctx->srp == NULL || password == NULL)
- return SSL_FAILURE;
- if (ctx->srp->user != NULL) {
- WC_RNG rng;
- if (wc_InitRng(&rng) < 0) {
- WOLFSSL_MSG("wc_InitRng failed");
- return SSL_FAILURE;
- }
- XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
- r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0]));
- wc_FreeRng(&rng);
- if (r < 0) {
- WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
- return SSL_FAILURE;
- }
- if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
- srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
- salt, sizeof(salt)/sizeof(salt[0])) < 0){
- WOLFSSL_MSG("wc_SrpSetParam failed");
- wc_FreeRng(&rng);
- return SSL_FAILURE;
- }
- r = wc_SrpSetPassword(ctx->srp, (const byte*)password,
- (word32)XSTRLEN(password));
- if (r < 0) {
- WOLFSSL_MSG("wc_SrpSetPassword failed.");
- wc_FreeRng(&rng);
- return SSL_FAILURE;
- }
- if (ctx->srp_password != NULL){
- XFREE(ctx->srp_password,NULL,
- DYNAMIC_TYPE_SRP);
- ctx->srp_password = NULL;
- }
- wc_FreeRng(&rng);
- } else {
- /* save password for wolfSSL_set_srp_username */
- if (ctx->srp_password != NULL)
- XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap,
- DYNAMIC_TYPE_SRP);
- if (ctx->srp_password == NULL){
- WOLFSSL_MSG("memory allocation error");
- return SSL_FAILURE;
- }
- XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1);
- }
- return WOLFSSL_SUCCESS;
- }
- /**
- * The modulus passed to wc_SrpSetParams in ssl.c is constant so check
- * that the requested strength is less than or equal to the size of the
- * static modulus size.
- * @param ctx Not used
- * @param strength Minimum number of bits for the modulus
- * @return 1 if strength is less than or equal to static modulus
- * 0 if strength is greater than static modulus
- */
- int wolfSSL_CTX_set_srp_strength(WOLFSSL_CTX *ctx, int strength)
- {
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_CTX_set_srp_strength");
- if (strength > (int)(sizeof(srp_N)*8)) {
- WOLFSSL_MSG("Bad Parameter");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- char* wolfSSL_get_srp_username(WOLFSSL *ssl)
- {
- if (ssl && ssl->ctx && ssl->ctx->srp) {
- return (char*) ssl->ctx->srp->user;
- }
- return NULL;
- }
- #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */
- /* keyblock size in bytes or -1 */
- int wolfSSL_get_keyblock_size(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
- return 2 * (ssl->specs.key_size + ssl->specs.iv_size +
- ssl->specs.hash_size);
- }
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- /* store keys returns WOLFSSL_SUCCESS or -1 on error */
- int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen,
- unsigned char** sr, unsigned int* srLen,
- unsigned char** cr, unsigned int* crLen)
- {
- if (ssl == NULL || ssl->arrays == NULL)
- return WOLFSSL_FATAL_ERROR;
- *ms = ssl->arrays->masterSecret;
- *sr = ssl->arrays->serverRandom;
- *cr = ssl->arrays->clientRandom;
- *msLen = SECRET_LEN;
- *srLen = RAN_LEN;
- *crLen = RAN_LEN;
- return WOLFSSL_SUCCESS;
- }
- void wolfSSL_set_accept_state(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_set_accept_state");
- if (ssl == NULL)
- return;
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- #ifdef HAVE_ECC
- #ifdef WOLFSSL_SMALL_STACK
- ecc_key* key = NULL;
- #else
- ecc_key key[1];
- #endif
- word32 idx = 0;
- #ifdef WOLFSSL_SMALL_STACK
- key = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
- DYNAMIC_TYPE_ECC);
- if (key == NULL) {
- WOLFSSL_MSG("Error allocating memory for ecc_key");
- }
- #endif
- if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) {
- if (wc_ecc_init(key) >= 0) {
- if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
- key, ssl->buffers.key->length) != 0) {
- ssl->options.haveECDSAsig = 0;
- ssl->options.haveECC = 0;
- ssl->options.haveStaticECC = 0;
- }
- wc_ecc_free(key);
- }
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(key, ssl->heap, DYNAMIC_TYPE_ECC);
- #endif
- #endif
- #ifndef NO_DH
- if (!ssl->options.haveDH && ssl->ctx->haveDH) {
- ssl->buffers.serverDH_P = ssl->ctx->serverDH_P;
- ssl->buffers.serverDH_G = ssl->ctx->serverDH_G;
- ssl->options.haveDH = 1;
- }
- #endif
- }
- if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error initializing server side");
- }
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- /* return true if connection established */
- int wolfSSL_is_init_finished(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return 0;
- if (ssl->options.handShakeState == HANDSHAKE_DONE)
- return 1;
- return 0;
- }
- #ifdef OPENSSL_EXTRA
- void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx,
- WOLFSSL_RSA*(*f)(WOLFSSL*, int, int))
- {
- /* wolfSSL verifies all these internally */
- (void)ctx;
- (void)f;
- }
- void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt)
- {
- WOLFSSL_ENTER("wolfSSL_set_shutdown");
- if(ssl==NULL) {
- WOLFSSL_MSG("Shutdown not set. ssl is null");
- return;
- }
- ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0;
- ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0;
- }
- #endif
- long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_options");
- WOLFSSL_MSG("wolfSSL options are set through API calls and macros");
- if(ctx == NULL)
- return BAD_FUNC_ARG;
- return ctx->mask;
- }
- static long wolf_set_options(long old_op, long op);
- long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt)
- {
- WOLFSSL_ENTER("SSL_CTX_set_options");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->mask = wolf_set_options(ctx->mask, opt);
- return ctx->mask;
- }
- long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt)
- {
- WOLFSSL_ENTER("SSL_CTX_clear_options");
- if(ctx == NULL)
- return BAD_FUNC_ARG;
- ctx->mask &= ~opt;
- return ctx->mask;
- }
- #ifdef OPENSSL_EXTRA
- int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd)
- {
- WOLFSSL_ENTER("SSL_set_rfd");
- ssl->rfd = rfd; /* not used directly to allow IO callbacks */
- ssl->IOCB_ReadCtx = &ssl->rfd;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
- ssl->buffers.dtlsCtx.rfd = rfd;
- }
- #endif
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd)
- {
- WOLFSSL_ENTER("SSL_set_wfd");
- ssl->wfd = wfd; /* not used directly to allow IO callbacks */
- ssl->IOCB_WriteCtx = &ssl->wfd;
- return WOLFSSL_SUCCESS;
- }
- #endif /* OPENSSL_EXTRA */
- #if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- /**
- * Implemented in a similar way that ngx_ssl_ocsp_validate does it when
- * SSL_get0_verified_chain is not available.
- * @param ssl WOLFSSL object to extract certs from
- * @return Stack of verified certs
- */
- WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl)
- {
- WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL;
- WOLFSSL_X509_STORE_CTX* storeCtx = NULL;
- WOLFSSL_X509* peerCert = NULL;
- WOLFSSL_ENTER("wolfSSL_get0_verified_chain");
- if (ssl == NULL || ssl->ctx == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
- peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl);
- if (peerCert == NULL) {
- WOLFSSL_MSG("wolfSSL_get_peer_certificate error");
- return NULL;
- }
- /* wolfSSL_get_peer_certificate returns a copy. We want the internal
- * member so that we don't have to worry about free'ing it. We call
- * wolfSSL_get_peer_certificate so that we don't have to worry about
- * setting up the internal pointer. */
- wolfSSL_X509_free(peerCert);
- peerCert = (WOLFSSL_X509*)&ssl->peerCert;
- chain = wolfSSL_get_peer_cert_chain(ssl);
- if (chain == NULL) {
- WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error");
- return NULL;
- }
- storeCtx = wolfSSL_X509_STORE_CTX_new();
- if (storeCtx == NULL) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error");
- return NULL;
- }
- if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl),
- peerCert, chain) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error");
- wolfSSL_X509_STORE_CTX_free(storeCtx);
- return NULL;
- }
- if (wolfSSL_X509_verify_cert(storeCtx) <= 0) {
- WOLFSSL_MSG("wolfSSL_X509_verify_cert error");
- wolfSSL_X509_STORE_CTX_free(storeCtx);
- return NULL;
- }
- wolfSSL_X509_STORE_CTX_free(storeCtx);
- return chain;
- }
- #endif /* SESSION_CERTS && OPENSSL_EXTRA */
- WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL) {
- return NULL;
- }
- if (ctx->x509_store_pt != NULL)
- return ctx->x509_store_pt;
- return &ctx->x509_store;
- }
- void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store");
- if (ctx == NULL || str == NULL || ctx->cm == str->cm) {
- return;
- }
- if (wolfSSL_CertManager_up_ref(str->cm) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_CertManager_up_ref error");
- return;
- }
- /* free cert manager if have one */
- if (ctx->cm != NULL) {
- wolfSSL_CertManagerFree(ctx->cm);
- }
- ctx->cm = str->cm;
- ctx->x509_store.cm = str->cm;
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ctx->x509_store_pt);
- ctx->x509_store.cache = str->cache;
- ctx->x509_store_pt = str; /* take ownership of store and free it
- with CTX free */
- ctx->cm->x509_store_p = ctx->x509_store_pt;/* CTX has onwership
- and free it with CTX free*/
- }
- int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store");
- if (ssl == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- /* NO-OP when setting existing store */
- if (str == SSL_STORE(ssl))
- return WOLFSSL_SUCCESS;
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ssl->x509_store_pt);
- if (str == ssl->ctx->x509_store_pt)
- ssl->x509_store_pt = NULL; /* if setting ctx store then just revert
- to using that instead */
- else
- ssl->x509_store_pt = str; /* take ownership of store and free it
- with SSL free */
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store");
- if (ssl == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- /* NO-OP when setting existing store */
- if (str == SSL_STORE(ssl))
- return WOLFSSL_SUCCESS;
- if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
- return WOLFSSL_FAILURE;
- }
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ssl->x509_store_pt);
- if (str == ssl->ctx->x509_store_pt)
- ssl->x509_store_pt = NULL; /* if setting ctx store then just revert
- to using that instead */
- else
- ssl->x509_store_pt = str; /* take ownership of store and free it
- with SSL free */
- return WOLFSSL_SUCCESS;
- }
- #endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */
- #ifdef WOLFSSL_ENCRYPTED_KEYS
- void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
- void* userdata)
- {
- WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata");
- if (ctx)
- ctx->passwd_userdata = userdata;
- }
- void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, wc_pem_password_cb*
- cb)
- {
- WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb");
- if (ctx)
- ctx->passwd_cb = cb;
- }
- wc_pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx)
- {
- if (ctx == NULL || ctx->passwd_cb == NULL) {
- return NULL;
- }
- return ctx->passwd_cb;
- }
- void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx)
- {
- if (ctx == NULL) {
- return NULL;
- }
- return ctx->passwd_userdata;
- }
- #endif /* WOLFSSL_ENCRYPTED_KEYS */
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- int wolfSSL_num_locks(void)
- {
- return 0;
- }
- void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int))
- {
- WOLFSSL_ENTER("wolfSSL_set_locking_callback");
- if (wc_SetMutexCb(f) != 0) {
- WOLFSSL_MSG("Error when setting mutex call back");
- }
- }
- typedef unsigned long (idCb)(void);
- static idCb* inner_idCb = NULL;
- unsigned long wolfSSL_thread_id(void)
- {
- if (inner_idCb != NULL) {
- return inner_idCb();
- }
- else {
- return 0;
- }
- }
- void wolfSSL_set_id_callback(unsigned long (*f)(void))
- {
- inner_idCb = f;
- }
- unsigned long wolfSSL_ERR_get_error(void)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_ERR_get_error");
- #ifdef WOLFSSL_HAVE_ERROR_QUEUE
- ret = wc_PullErrorNode(NULL, NULL, NULL);
- if (ret < 0) {
- if (ret == BAD_STATE_E) {
- ret = 0; /* no errors in queue */
- }
- else {
- WOLFSSL_MSG("Error with pulling error node!");
- WOLFSSL_LEAVE("wolfSSL_ERR_get_error", ret);
- ret = 0 - ret; /* return absolute value of error */
- /* panic and try to clear out nodes */
- wc_ClearErrorNodes();
- }
- }
- else {
- wc_RemoveErrorNode(0);
- }
- return ret;
- #else
- (void)ret;
- return (unsigned long)(0 - NOT_COMPILED_IN);
- #endif /* WOLFSSL_HAVE_ERROR_QUEUE */
- }
- #ifdef WOLFSSL_HAVE_ERROR_QUEUE
- #ifndef NO_BIO
- /* print out and clear all errors */
- void wolfSSL_ERR_print_errors(WOLFSSL_BIO* bio)
- {
- const char* file = NULL;
- const char* reason = NULL;
- int ret;
- int line = 0;
- char buf[WOLFSSL_MAX_ERROR_SZ * 2];
- WOLFSSL_ENTER("wolfSSL_ERR_print_errors");
- if (bio == NULL) {
- WOLFSSL_MSG("BIO passed in was null");
- return;
- }
- do {
- ret = wc_PeekErrorNode(0, &file, &reason, &line);
- if (ret >= 0) {
- const char* r = wolfSSL_ERR_reason_error_string(0 - ret);
- if (XSNPRINTF(buf, sizeof(buf),
- "error:%d:wolfSSL library:%s:%s:%d\n",
- ret, r, file, line)
- >= (int)sizeof(buf))
- {
- WOLFSSL_MSG("Buffer overrun formatting error message");
- }
- wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf));
- wc_RemoveErrorNode(0);
- }
- } while (ret >= 0);
- if (wolfSSL_BIO_write(bio, "", 1) != 1) {
- WOLFSSL_MSG("Issue writing final string terminator");
- }
- }
- #endif /* !NO_BIO */
- #endif /* WOLFSSL_HAVE_ERROR_QUEUE */
- #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
- defined(HAVE_SECRET_CALLBACK)
- #if !defined(NO_WOLFSSL_SERVER)
- /* Return the amount of random bytes copied over or error case.
- * ssl : ssl struct after handshake
- * out : buffer to hold random bytes
- * outSz : either 0 (return max buffer sz) or size of out buffer
- */
- size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out,
- size_t outSz)
- {
- size_t size;
- /* return max size of buffer */
- if (outSz == 0) {
- return RAN_LEN;
- }
- if (ssl == NULL || out == NULL) {
- return 0;
- }
- if (ssl->arrays == NULL) {
- WOLFSSL_MSG("Arrays struct not saved after handshake");
- return 0;
- }
- if (outSz > RAN_LEN) {
- size = RAN_LEN;
- }
- else {
- size = outSz;
- }
- XMEMCPY(out, ssl->arrays->serverRandom, size);
- return size;
- }
- #endif /* !NO_WOLFSSL_SERVER */
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */
- #ifdef OPENSSL_EXTRA
- #if !defined(NO_WOLFSSL_SERVER)
- /* Used to get the peer ephemeral public key sent during the connection
- * NOTE: currently wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) must be called
- * before the ephemeral key is stored.
- * return WOLFSSL_SUCCESS on success */
- int wolfSSL_get_server_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey)
- {
- WOLFSSL_EVP_PKEY* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_get_server_tmp_key");
- if (ssl == NULL || pkey == NULL) {
- WOLFSSL_MSG("Bad argument passed in");
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_ECC
- if (ssl->peerEccKey != NULL) {
- unsigned char* der;
- const unsigned char* pt;
- unsigned int derSz = 0;
- int sz;
- PRIVATE_KEY_UNLOCK();
- if (wc_ecc_export_x963(ssl->peerEccKey, NULL, &derSz) !=
- LENGTH_ONLY_E) {
- WOLFSSL_MSG("get ecc der size failed");
- PRIVATE_KEY_LOCK();
- return WOLFSSL_FAILURE;
- }
- PRIVATE_KEY_LOCK();
- derSz += MAX_SEQ_SZ + (2 * MAX_ALGO_SZ) + MAX_SEQ_SZ + TRAILING_ZERO;
- der = (unsigned char*)XMALLOC(derSz, ssl->heap, DYNAMIC_TYPE_KEY);
- if (der == NULL) {
- WOLFSSL_MSG("Memory error");
- return WOLFSSL_FAILURE;
- }
- if ((sz = wc_EccPublicKeyToDer(ssl->peerEccKey, der, derSz, 1)) <= 0) {
- WOLFSSL_MSG("get ecc der failed");
- XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY);
- return WOLFSSL_FAILURE;
- }
- pt = der; /* in case pointer gets advanced */
- ret = wolfSSL_d2i_PUBKEY(NULL, &pt, sz);
- XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY);
- }
- #endif
- *pkey = ret;
- #ifdef HAVE_ECC
- if (ret != NULL)
- return WOLFSSL_SUCCESS;
- else
- #endif
- return WOLFSSL_FAILURE;
- }
- #endif /* !NO_WOLFSSL_SERVER */
- /**
- * This function checks if any compiled in protocol versions are
- * left enabled after calls to set_min or set_max API.
- * @param major The SSL/TLS major version
- * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no
- * protocol versions are left enabled.
- */
- static int CheckSslMethodVersion(byte major, unsigned long options)
- {
- int sanityConfirmed = 0;
- (void)options;
- switch (major) {
- #ifndef NO_TLS
- case SSLv3_MAJOR:
- #ifdef WOLFSSL_ALLOW_SSLV3
- if (!(options & WOLFSSL_OP_NO_SSLv3)) {
- sanityConfirmed = 1;
- }
- #endif
- #ifndef NO_OLD_TLS
- if (!(options & WOLFSSL_OP_NO_TLSv1))
- sanityConfirmed = 1;
- if (!(options & WOLFSSL_OP_NO_TLSv1_1))
- sanityConfirmed = 1;
- #endif
- #ifndef WOLFSSL_NO_TLS12
- if (!(options & WOLFSSL_OP_NO_TLSv1_2))
- sanityConfirmed = 1;
- #endif
- #ifdef WOLFSSL_TLS13
- if (!(options & WOLFSSL_OP_NO_TLSv1_3))
- sanityConfirmed = 1;
- #endif
- break;
- #endif
- #ifdef WOLFSSL_DTLS
- case DTLS_MAJOR:
- sanityConfirmed = 1;
- break;
- #endif
- default:
- WOLFSSL_MSG("Invalid major version");
- return WOLFSSL_FAILURE;
- }
- if (!sanityConfirmed) {
- WOLFSSL_MSG("All compiled in TLS versions disabled");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- /**
- * protoVerTbl holds (D)TLS version numbers in ascending order.
- * Except DTLS versions, the newer version is located in the latter part of
- * the table. This table is referred by wolfSSL_CTX_set_min_proto_version and
- * wolfSSL_CTX_set_max_proto_version.
- */
- static const int protoVerTbl[] = {
- SSL3_VERSION,
- TLS1_VERSION,
- TLS1_1_VERSION,
- TLS1_2_VERSION,
- TLS1_3_VERSION,
- DTLS1_VERSION,
- DTLS1_2_VERSION
- };
- /* number of protocol versions listed in protoVerTbl */
- #define NUMBER_OF_PROTOCOLS (sizeof(protoVerTbl)/sizeof(int))
- /**
- * wolfSSL_CTX_set_min_proto_version attempts to set the minimum protocol
- * version to use by SSL objects created from this WOLFSSL_CTX.
- * This API guarantees that a version of SSL/TLS lower than specified
- * here will not be allowed. If the version specified is not compiled in
- * then this API sets the lowest compiled in protocol version.
- * This API also accept 0 as version, to set the minimum version automatically.
- * CheckSslMethodVersion() is called to check if any remaining protocol versions
- * are enabled.
- * @param ctx The wolfSSL CONTEXT factory for spawning SSL/TLS objects
- * @param version Any of the following
- * * 0
- * * SSL3_VERSION
- * * TLS1_VERSION
- * * TLS1_1_VERSION
- * * TLS1_2_VERSION
- * * TLS1_3_VERSION
- * * DTLS1_VERSION
- * * DTLS1_2_VERSION
- * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no
- * protocol versions are left enabled.
- */
- static int Set_CTX_min_proto_version(WOLFSSL_CTX* ctx, int version)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version_ex");
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
- switch (version) {
- #ifndef NO_TLS
- case SSL3_VERSION:
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- ctx->minDowngrade = SSLv3_MINOR;
- break;
- #endif
- case TLS1_VERSION:
- #ifdef WOLFSSL_ALLOW_TLSV10
- ctx->minDowngrade = TLSv1_MINOR;
- break;
- #endif
- case TLS1_1_VERSION:
- #ifndef NO_OLD_TLS
- ctx->minDowngrade = TLSv1_1_MINOR;
- break;
- #endif
- case TLS1_2_VERSION:
- #ifndef WOLFSSL_NO_TLS12
- ctx->minDowngrade = TLSv1_2_MINOR;
- break;
- #endif
- case TLS1_3_VERSION:
- #ifdef WOLFSSL_TLS13
- ctx->minDowngrade = TLSv1_3_MINOR;
- break;
- #endif
- #endif
- #ifdef WOLFSSL_DTLS
- case DTLS1_VERSION:
- #ifndef NO_OLD_TLS
- ctx->minDowngrade = DTLS_MINOR;
- break;
- #endif
- case DTLS1_2_VERSION:
- ctx->minDowngrade = DTLSv1_2_MINOR;
- break;
- #endif
- default:
- WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
- return WOLFSSL_FAILURE;
- }
- switch (version) {
- #ifndef NO_TLS
- case TLS1_3_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_2);
- FALL_THROUGH;
- case TLS1_2_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_1);
- FALL_THROUGH;
- case TLS1_1_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1);
- FALL_THROUGH;
- case TLS1_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_SSLv3);
- break;
- case SSL3_VERSION:
- case SSL2_VERSION:
- /* Nothing to do here */
- break;
- #endif
- #ifdef WOLFSSL_DTLS
- case DTLS1_VERSION:
- case DTLS1_2_VERSION:
- break;
- #endif
- default:
- WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
- return WOLFSSL_FAILURE;
- }
- return CheckSslMethodVersion(ctx->method->version.major, ctx->mask);
- }
- /* Sets the min protocol version allowed with WOLFSSL_CTX
- * returns WOLFSSL_SUCCESS on success */
- int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
- {
- int ret;
- int proto = 0;
- int maxProto = 0;
- int i;
- int idx = 0;
- WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version");
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (version != 0) {
- proto = version;
- ctx->minProto = 0; /* turn min proto flag off */
- for (i = 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) {
- if (protoVerTbl[i] == version) {
- break;
- }
- }
- }
- else {
- /* when 0 is specified as version, try to find out the min version */
- for (i = 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) {
- ret = Set_CTX_min_proto_version(ctx, protoVerTbl[i]);
- if (ret == WOLFSSL_SUCCESS) {
- proto = protoVerTbl[i];
- ctx->minProto = 1; /* turn min proto flag on */
- break;
- }
- }
- }
- /* check case where max > min , if so then clear the NO_* options
- * i is the index into the table for proto version used, see if the max
- * proto version index found is smaller */
- maxProto = wolfSSL_CTX_get_max_proto_version(ctx);
- for (idx = 0; (unsigned)idx < NUMBER_OF_PROTOCOLS; idx++) {
- if (protoVerTbl[idx] == maxProto) {
- break;
- }
- }
- if (idx < i) {
- wolfSSL_CTX_clear_options(ctx, WOLFSSL_OP_NO_TLSv1 |
- WOLFSSL_OP_NO_TLSv1_1 | WOLFSSL_OP_NO_TLSv1_2 |
- WOLFSSL_OP_NO_TLSv1_3);
- }
- ret = Set_CTX_min_proto_version(ctx, proto);
- return ret;
- }
- /**
- * wolfSSL_CTX_set_max_proto_version attempts to set the maximum protocol
- * version to use by SSL objects created from this WOLFSSL_CTX.
- * This API guarantees that a version of SSL/TLS higher than specified
- * here will not be allowed. If the version specified is not compiled in
- * then this API sets the highest compiled in protocol version.
- * This API also accept 0 as version, to set the maximum version automatically.
- * CheckSslMethodVersion() is called to check if any remaining protocol versions
- * are enabled.
- * @param ctx The wolfSSL CONTEXT factory for spawning SSL/TLS objects
- * @param ver Any of the following
- * * 0
- * * SSL3_VERSION
- * * TLS1_VERSION
- * * TLS1_1_VERSION
- * * TLS1_2_VERSION
- * * TLS1_3_VERSION
- * * DTLS1_VERSION
- * * DTLS1_2_VERSION
- * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no
- * protocol versions are left enabled.
- */
- static int Set_CTX_max_proto_version(WOLFSSL_CTX* ctx, int ver)
- {
- WOLFSSL_ENTER("Set_CTX_max_proto_version");
- if (!ctx || !ctx->method) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- switch (ver) {
- case SSL2_VERSION:
- WOLFSSL_MSG("wolfSSL does not support SSLv2");
- return WOLFSSL_FAILURE;
- #ifndef NO_TLS
- case SSL3_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1);
- FALL_THROUGH;
- case TLS1_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_1);
- FALL_THROUGH;
- case TLS1_1_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_2);
- FALL_THROUGH;
- case TLS1_2_VERSION:
- wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_3);
- FALL_THROUGH;
- case TLS1_3_VERSION:
- /* Nothing to do here */
- break;
- #endif
- #ifdef WOLFSSL_DTLS
- case DTLS1_VERSION:
- case DTLS1_2_VERSION:
- break;
- #endif
- default:
- WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
- return WOLFSSL_FAILURE;
- }
- return CheckSslMethodVersion(ctx->method->version.major, ctx->mask);
- }
- /* Sets the max protocol version allowed with WOLFSSL_CTX
- * returns WOLFSSL_SUCCESS on success */
- int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version)
- {
- int i;
- int ret = WOLFSSL_FAILURE;
- int minProto;
- WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version");
- if (ctx == NULL) {
- return ret;
- }
- /* clear out flags and reset min protocol version */
- minProto = wolfSSL_CTX_get_min_proto_version(ctx);
- wolfSSL_CTX_clear_options(ctx,
- WOLFSSL_OP_NO_TLSv1 | WOLFSSL_OP_NO_TLSv1_1 |
- WOLFSSL_OP_NO_TLSv1_2 | WOLFSSL_OP_NO_TLSv1_3);
- wolfSSL_CTX_set_min_proto_version(ctx, minProto);
- if (version != 0) {
- ctx->maxProto = 0; /* turn max proto flag off */
- return Set_CTX_max_proto_version(ctx, version);
- }
- /* when 0 is specified as version, try to find out the min version from
- * the bottom to top of the protoverTbl.
- */
- for (i = NUMBER_OF_PROTOCOLS -1; i >= 0; i--) {
- ret = Set_CTX_max_proto_version(ctx, protoVerTbl[i]);
- if (ret == WOLFSSL_SUCCESS) {
- ctx->maxProto = 1; /* turn max proto flag on */
- break;
- }
- }
- return ret;
- }
- static int Set_SSL_min_proto_version(WOLFSSL* ssl, int ver)
- {
- WOLFSSL_ENTER("Set_SSL_min_proto_version");
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- switch (ver) {
- #ifndef NO_TLS
- case SSL3_VERSION:
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- ssl->options.minDowngrade = SSLv3_MINOR;
- break;
- #endif
- case TLS1_VERSION:
- #ifdef WOLFSSL_ALLOW_TLSV10
- ssl->options.minDowngrade = TLSv1_MINOR;
- break;
- #endif
- case TLS1_1_VERSION:
- #ifndef NO_OLD_TLS
- ssl->options.minDowngrade = TLSv1_1_MINOR;
- break;
- #endif
- case TLS1_2_VERSION:
- #ifndef WOLFSSL_NO_TLS12
- ssl->options.minDowngrade = TLSv1_2_MINOR;
- break;
- #endif
- case TLS1_3_VERSION:
- #ifdef WOLFSSL_TLS13
- ssl->options.minDowngrade = TLSv1_3_MINOR;
- break;
- #endif
- #endif
- #ifdef WOLFSSL_DTLS
- case DTLS1_VERSION:
- #ifndef NO_OLD_TLS
- ssl->options.minDowngrade = DTLS_MINOR;
- break;
- #endif
- case DTLS1_2_VERSION:
- ssl->options.minDowngrade = DTLSv1_2_MINOR;
- break;
- #endif
- default:
- WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
- return WOLFSSL_FAILURE;
- }
- switch (ver) {
- #ifndef NO_TLS
- case TLS1_3_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_2;
- FALL_THROUGH;
- case TLS1_2_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_1;
- FALL_THROUGH;
- case TLS1_1_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_TLSv1;
- FALL_THROUGH;
- case TLS1_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_SSLv3;
- break;
- case SSL3_VERSION:
- case SSL2_VERSION:
- /* Nothing to do here */
- break;
- #endif
- #ifdef WOLFSSL_DTLS
- case DTLS1_VERSION:
- case DTLS1_2_VERSION:
- break;
- #endif
- default:
- WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
- return WOLFSSL_FAILURE;
- }
- return CheckSslMethodVersion(ssl->version.major, ssl->options.mask);
- }
- int wolfSSL_set_min_proto_version(WOLFSSL* ssl, int version)
- {
- int i;
- int ret = WOLFSSL_FAILURE;;
- WOLFSSL_ENTER("wolfSSL_set_min_proto_version");
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (version != 0) {
- return Set_SSL_min_proto_version(ssl, version);
- }
- /* when 0 is specified as version, try to find out the min version */
- for (i= 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) {
- ret = Set_SSL_min_proto_version(ssl, protoVerTbl[i]);
- if (ret == WOLFSSL_SUCCESS)
- break;
- }
- return ret;
- }
- static int Set_SSL_max_proto_version(WOLFSSL* ssl, int ver)
- {
- WOLFSSL_ENTER("Set_SSL_max_proto_version");
- if (!ssl) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- switch (ver) {
- case SSL2_VERSION:
- WOLFSSL_MSG("wolfSSL does not support SSLv2");
- return WOLFSSL_FAILURE;
- #ifndef NO_TLS
- case SSL3_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_TLSv1;
- FALL_THROUGH;
- case TLS1_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_1;
- FALL_THROUGH;
- case TLS1_1_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_2;
- FALL_THROUGH;
- case TLS1_2_VERSION:
- ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_3;
- FALL_THROUGH;
- case TLS1_3_VERSION:
- /* Nothing to do here */
- break;
- #endif
- #ifdef WOLFSSL_DTLS
- case DTLS1_VERSION:
- case DTLS1_2_VERSION:
- break;
- #endif
- default:
- WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
- return WOLFSSL_FAILURE;
- }
- return CheckSslMethodVersion(ssl->version.major, ssl->options.mask);
- }
- int wolfSSL_set_max_proto_version(WOLFSSL* ssl, int version)
- {
- int i;
- int ret = WOLFSSL_FAILURE;;
- WOLFSSL_ENTER("wolfSSL_set_max_proto_version");
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (version != 0) {
- return Set_SSL_max_proto_version(ssl, version);
- }
- /* when 0 is specified as version, try to find out the min version from
- * the bottom to top of the protoverTbl.
- */
- for (i = NUMBER_OF_PROTOCOLS -1; i >= 0; i--) {
- ret = Set_SSL_max_proto_version(ssl, protoVerTbl[i]);
- if (ret == WOLFSSL_SUCCESS)
- break;
- }
- return ret;
- }
- static int GetMinProtoVersion(int minDowngrade)
- {
- int ret;
- switch (minDowngrade) {
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_SSLV3
- case SSLv3_MINOR:
- ret = SSL3_VERSION;
- break;
- #endif
- #ifdef WOLFSSL_ALLOW_TLSV10
- case TLSv1_MINOR:
- ret = TLS1_VERSION;
- break;
- #endif
- case TLSv1_1_MINOR:
- ret = TLS1_1_VERSION;
- break;
- #endif
- #ifndef WOLFSSL_NO_TLS12
- case TLSv1_2_MINOR:
- ret = TLS1_2_VERSION;
- break;
- #endif
- #ifdef WOLFSSL_TLS13
- case TLSv1_3_MINOR:
- ret = TLS1_3_VERSION;
- break;
- #endif
- default:
- ret = 0;
- break;
- }
- return ret;
- }
- WOLFSSL_API int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx)
- {
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version");
- if (ctx != NULL) {
- if (ctx->minProto) {
- ret = 0;
- }
- else {
- ret = GetMinProtoVersion(ctx->minDowngrade);
- }
- }
- else {
- ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE);
- }
- WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret);
- return ret;
- }
- /* returns the maximum allowed protocol version given the 'options' used
- * returns WOLFSSL_FATAL_ERROR on no match */
- static int GetMaxProtoVersion(long options)
- {
- #ifndef NO_TLS
- #ifdef WOLFSSL_TLS13
- if (!(options & WOLFSSL_OP_NO_TLSv1_3))
- return TLS1_3_VERSION;
- #endif
- #ifndef WOLFSSL_NO_TLS12
- if (!(options & WOLFSSL_OP_NO_TLSv1_2))
- return TLS1_2_VERSION;
- #endif
- #ifndef NO_OLD_TLS
- if (!(options & WOLFSSL_OP_NO_TLSv1_1))
- return TLS1_1_VERSION;
- #ifdef WOLFSSL_ALLOW_TLSV10
- if (!(options & WOLFSSL_OP_NO_TLSv1))
- return TLS1_VERSION;
- #endif
- #ifdef WOLFSSL_ALLOW_SSLV3
- if (!(options & WOLFSSL_OP_NO_SSLv3))
- return SSL3_VERSION;
- #endif
- #endif
- #else
- (void)options;
- #endif /* NO_TLS */
- return WOLFSSL_FATAL_ERROR;
- }
- /* returns the maximum protocol version for 'ctx' */
- int wolfSSL_CTX_get_max_proto_version(WOLFSSL_CTX* ctx)
- {
- int ret = 0;
- long options = 0; /* default to nothing set */
- WOLFSSL_ENTER("wolfSSL_CTX_get_max_proto_version");
- if (ctx != NULL) {
- options = wolfSSL_CTX_get_options(ctx);
- }
- if ((ctx != NULL) && ctx->maxProto) {
- ret = 0;
- }
- else {
- ret = GetMaxProtoVersion(options);
- }
- WOLFSSL_LEAVE("wolfSSL_CTX_get_max_proto_version", ret);
- if (ret == WOLFSSL_FATAL_ERROR) {
- WOLFSSL_MSG("Error getting max proto version");
- ret = 0; /* setting ret to 0 to match compat return */
- }
- return ret;
- }
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
- defined(HAVE_SECRET_CALLBACK)
- #if !defined(NO_WOLFSSL_CLIENT)
- /* Return the amount of random bytes copied over or error case.
- * ssl : ssl struct after handshake
- * out : buffer to hold random bytes
- * outSz : either 0 (return max buffer sz) or size of out buffer
- */
- size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
- size_t outSz)
- {
- size_t size;
- /* return max size of buffer */
- if (outSz == 0) {
- return RAN_LEN;
- }
- if (ssl == NULL || out == NULL) {
- return 0;
- }
- if (ssl->arrays == NULL) {
- WOLFSSL_MSG("Arrays struct not saved after handshake");
- return 0;
- }
- if (outSz > RAN_LEN) {
- size = RAN_LEN;
- }
- else {
- size = outSz;
- }
- XMEMCPY(out, ssl->arrays->clientRandom, size);
- return size;
- }
- #endif /* !NO_WOLFSSL_CLIENT */
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */
- #ifdef OPENSSL_EXTRA
- unsigned long wolfSSLeay(void)
- {
- return SSLEAY_VERSION_NUMBER;
- }
- unsigned long wolfSSL_OpenSSL_version_num(void)
- {
- return OPENSSL_VERSION_NUMBER;
- }
- const char* wolfSSLeay_version(int type)
- {
- (void)type;
- #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
- return wolfSSL_OpenSSL_version(type);
- #else
- return wolfSSL_OpenSSL_version();
- #endif
- }
- #ifndef NO_MD5
- int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
- {
- int ret;
- typedef char md5_test[sizeof(MD5_CTX) >= sizeof(wc_Md5) ? 1 : -1];
- (void)sizeof(md5_test);
- WOLFSSL_ENTER("MD5_Init");
- ret = wc_InitMd5((wc_Md5*)md5);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_MD5_Update");
- ret = wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_MD5_Final(byte* output, WOLFSSL_MD5_CTX* md5)
- {
- int ret;
- WOLFSSL_ENTER("MD5_Final");
- ret = wc_Md5Final((wc_Md5*)md5, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Md5Free((wc_Md5*)md5);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- /* Apply MD5 transformation to the data */
- int wolfSSL_MD5_Transform(WOLFSSL_MD5_CTX* md5, const unsigned char* data)
- {
- int ret;
- WOLFSSL_ENTER("MD5_Transform");
- /* sanity check */
- if (md5 == NULL || data == NULL) {
- return 0;
- }
- #if defined(BIG_ENDIAN_ORDER)
- {
- ByteReverseWords((word32*)data, (word32*)data, WC_MD5_BLOCK_SIZE);
- }
- #endif
- ret = wc_Md5Transform((wc_Md5*)md5, data);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- else
- return 0;
- }
- unsigned char *wolfSSL_MD5(const unsigned char* data, size_t len,
- unsigned char* hash)
- {
- static unsigned char out[WC_MD5_DIGEST_SIZE];
- WOLFSSL_ENTER("wolfSSL_MD5");
- if (hash == NULL)
- hash = out;
- if (wc_Md5Hash(data, (word32)len, hash) != 0) {
- WOLFSSL_MSG("wc_Md5Hash error");
- return NULL;
- }
- return hash;
- }
- #endif /* !NO_MD5 */
- #ifndef NO_SHA
- int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha)
- {
- int ret;
- typedef char sha_test[sizeof(SHA_CTX) >= sizeof(wc_Sha) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA_Init");
- ret = wc_InitSha((wc_Sha*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA_Update");
- ret = wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA_Final(byte* output, WOLFSSL_SHA_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA_Final");
- ret = wc_ShaFinal((wc_Sha*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_ShaFree((wc_Sha*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #if defined(OPENSSL_EXTRA)
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
- /* Apply SHA1 transformation to the data */
- int wolfSSL_SHA_Transform(WOLFSSL_SHA_CTX* sha,
- const unsigned char* data)
- {
- int ret;
- WOLFSSL_ENTER("SHA_Transform");
- /* sanity check */
- if (sha == NULL || data == NULL) {
- return 0;
- }
- #if defined(LITTLE_ENDIAN_ORDER)
- {
- ByteReverseWords((word32*)data, (word32*)data, WC_SHA_BLOCK_SIZE);
- }
- #endif
- ret = wc_ShaTransform((wc_Sha*)sha, data);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- else
- return 0;
- }
- #endif
- #endif
- int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha)
- {
- WOLFSSL_ENTER("SHA1_Init");
- return SHA_Init(sha);
- }
- int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input,
- unsigned long sz)
- {
- WOLFSSL_ENTER("SHA1_Update");
- return SHA_Update(sha, input, sz);
- }
- int wolfSSL_SHA1_Final(byte* output, WOLFSSL_SHA_CTX* sha)
- {
- WOLFSSL_ENTER("SHA1_Final");
- return SHA_Final(output, sha);
- }
- #if defined(OPENSSL_EXTRA)
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
- /* Apply SHA1 transformation to the data */
- int wolfSSL_SHA1_Transform(WOLFSSL_SHA_CTX* sha,
- const unsigned char* data)
- {
- WOLFSSL_ENTER("SHA1_Transform");
- return (wolfSSL_SHA_Transform(sha, data));
- }
- #endif
- #endif
- #endif /* !NO_SHA */
- #ifdef WOLFSSL_SHA224
- int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha)
- {
- int ret;
- typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA224_Init");
- ret = wc_InitSha224((wc_Sha224*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA224_Update");
- ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA224_Final(byte* output, WOLFSSL_SHA224_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA224_Final");
- ret = wc_Sha224Final((wc_Sha224*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha224Free((wc_Sha224*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #endif /* WOLFSSL_SHA224 */
- int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256)
- {
- int ret;
- typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA256_Init");
- ret = wc_InitSha256((wc_Sha256*)sha256);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA256_Update");
- ret = wc_Sha256Update((wc_Sha256*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA256_Final(byte* output, WOLFSSL_SHA256_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA256_Final");
- ret = wc_Sha256Final((wc_Sha256*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha256Free((wc_Sha256*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #if defined(OPENSSL_EXTRA)
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) && \
- !defined(WOLFSSL_DEVCRYPTO_HASH) && !defined(WOLFSSL_AFALG_HASH)
- /* Apply SHA256 transformation to the data */
- int wolfSSL_SHA256_Transform(WOLFSSL_SHA256_CTX* sha256,
- const unsigned char* data)
- {
- int ret;
- WOLFSSL_ENTER("SHA256_Transform");
- /* sanity check */
- if (sha256 == NULL || data == NULL) {
- return 0;
- }
- #if defined(LITTLE_ENDIAN_ORDER)
- {
- ByteReverseWords((word32*)data, (word32*)data, WC_SHA256_BLOCK_SIZE);
- }
- #endif
- ret = wc_Sha256Transform((wc_Sha256*)sha256, data);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- else
- return 0;
- }
- #endif
- #endif
- #ifdef WOLFSSL_SHA384
- int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha)
- {
- int ret;
- typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA384_Init");
- ret = wc_InitSha384((wc_Sha384*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA384_Update");
- ret = wc_Sha384Update((wc_Sha384*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA384_Final(byte* output, WOLFSSL_SHA384_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA384_Final");
- ret = wc_Sha384Final((wc_Sha384*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha384Free((wc_Sha384*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #endif /* WOLFSSL_SHA384 */
- #ifdef WOLFSSL_SHA512
- int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha)
- {
- int ret;
- typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA512_Init");
- ret = wc_InitSha512((wc_Sha512*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA512_Update");
- ret = wc_Sha512Update((wc_Sha512*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA512_Final(byte* output, WOLFSSL_SHA512_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA512_Final");
- ret = wc_Sha512Final((wc_Sha512*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha512Free((wc_Sha512*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
- /* Apply SHA512 transformation to the data */
- int wolfSSL_SHA512_Transform(WOLFSSL_SHA512_CTX* sha512,
- const unsigned char* data)
- {
- int ret;
- WOLFSSL_ENTER("SHA512_Transform");
- /* sanity check */
- if (sha512 == NULL || data == NULL) {
- return WOLFSSL_FAILURE;
- }
- ret = wc_Sha512Transform((wc_Sha512*)sha512, data);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- else
- return WOLFSSL_FAILURE;
- }
- #endif /* !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2)) */
- #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
- #if !defined(WOLFSSL_NOSHA512_224)
- int wolfSSL_SHA512_224_Init(WOLFSSL_SHA512_224_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_SHA512_224_Init");
- ret = wc_InitSha512_224((wc_Sha512*)sha);
- /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- int wolfSSL_SHA512_224_Update(WOLFSSL_SHA512_224_CTX* sha,
- const void* input, unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_SHA512_224_Update");
- ret = wc_Sha512_224Update((wc_Sha512*)sha, (const byte*)input, (word32)sz);
- /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- int wolfSSL_SHA512_224_Final(byte* output, WOLFSSL_SHA512_224_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_SHA512_224_Final");
- ret = wc_Sha512_224Final((wc_Sha512*)sha, output);
- /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
- /* Apply SHA512 transformation to the data */
- int wolfSSL_SHA512_224_Transform(WOLFSSL_SHA512_CTX* sha512,
- const unsigned char* data)
- {
- int ret;
- WOLFSSL_ENTER("SHA512_224_Transform");
- /* sanity check */
- if (sha512 == NULL || data == NULL) {
- return WOLFSSL_FAILURE;
- }
- ret = wc_Sha512_224Transform((wc_Sha512*)sha512, data);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- else
- return WOLFSSL_FAILURE;
- }
- #endif /* !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2)) */
- #endif /* !WOLFSSL_NOSHA512_224 */
- #if !defined(WOLFSSL_NOSHA512_256)
- int wolfSSL_SHA512_256_Init(WOLFSSL_SHA512_256_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_SHA512_256_Init");
- ret = wc_InitSha512_256((wc_Sha512*)sha);
- /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- int wolfSSL_SHA512_256_Update(WOLFSSL_SHA512_256_CTX* sha,
- const void* input, unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_SHA512_256_Update");
- ret = wc_Sha512_256Update((wc_Sha512*)sha, (const byte*)input, (word32)sz);
- /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- int wolfSSL_SHA512_256_Final(byte* output, WOLFSSL_SHA512_256_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_SHA512_256_Final");
- ret = wc_Sha512_256Final((wc_Sha512*)sha, output);
- /* return WOLFSSL_SUCCESS on success, 0 otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
- /* Apply SHA512 transformation to the data */
- int wolfSSL_SHA512_256_Transform(WOLFSSL_SHA512_CTX* sha512,
- const unsigned char* data)
- {
- int ret;
- WOLFSSL_ENTER("SHA512_256_Transform");
- /* sanity check */
- if (sha512 == NULL || data == NULL) {
- return WOLFSSL_FAILURE;
- }
- ret = wc_Sha512_256Transform((wc_Sha512*)sha512, data);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return WOLFSSL_SUCCESS;
- else
- return WOLFSSL_FAILURE;
- }
- #endif /* !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2)) */
- #endif /* !WOLFSSL_NOSHA512_256 */
- #endif /* !HAVE_FIPS && !HAVE_SELFTEST */
- #endif /* WOLFSSL_SHA512 */
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- int wolfSSL_SHA3_224_Init(WOLFSSL_SHA3_224_CTX* sha)
- {
- int ret;
- typedef char sha_test[sizeof(SHA3_224_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA3_224_Init");
- ret = wc_InitSha3_224((wc_Sha3*)sha, NULL, INVALID_DEVID);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_224_Update(WOLFSSL_SHA3_224_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_224_Update");
- ret = wc_Sha3_224_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_224_Final(byte* output, WOLFSSL_SHA3_224_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_224_Final");
- ret = wc_Sha3_224_Final((wc_Sha3*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha3_224_Free((wc_Sha3*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #endif /* WOLFSSL_NOSHA3_224 */
- #ifndef WOLFSSL_NOSHA3_256
- int wolfSSL_SHA3_256_Init(WOLFSSL_SHA3_256_CTX* sha3_256)
- {
- int ret;
- typedef char sha_test[sizeof(SHA3_256_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA3_256_Init");
- ret = wc_InitSha3_256((wc_Sha3*)sha3_256, NULL, INVALID_DEVID);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_256_Update(WOLFSSL_SHA3_256_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_256_Update");
- ret = wc_Sha3_256_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_256_Final(byte* output, WOLFSSL_SHA3_256_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_256_Final");
- ret = wc_Sha3_256_Final((wc_Sha3*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha3_256_Free((wc_Sha3*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #endif /* WOLFSSL_NOSHA3_256 */
- int wolfSSL_SHA3_384_Init(WOLFSSL_SHA3_384_CTX* sha)
- {
- int ret;
- typedef char sha_test[sizeof(SHA3_384_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA3_384_Init");
- ret = wc_InitSha3_384((wc_Sha3*)sha, NULL, INVALID_DEVID);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_384_Update(WOLFSSL_SHA3_384_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_384_Update");
- ret = wc_Sha3_384_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_384_Final(byte* output, WOLFSSL_SHA3_384_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_384_Final");
- ret = wc_Sha3_384_Final((wc_Sha3*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha3_384_Free((wc_Sha3*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #ifndef WOLFSSL_NOSHA3_512
- int wolfSSL_SHA3_512_Init(WOLFSSL_SHA3_512_CTX* sha)
- {
- int ret;
- typedef char sha_test[sizeof(SHA3_512_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
- (void)sizeof(sha_test);
- WOLFSSL_ENTER("SHA3_512_Init");
- ret = wc_InitSha3_512((wc_Sha3*)sha, NULL, INVALID_DEVID);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_512_Update(WOLFSSL_SHA3_512_CTX* sha, const void* input,
- unsigned long sz)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_512_Update");
- ret = wc_Sha3_512_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- int wolfSSL_SHA3_512_Final(byte* output, WOLFSSL_SHA3_512_CTX* sha)
- {
- int ret;
- WOLFSSL_ENTER("SHA3_512_Final");
- ret = wc_Sha3_512_Final((wc_Sha3*)sha, output);
- /* have to actually free the resources (if any) here, because the
- * OpenSSL API doesn't include SHA*_Free().
- */
- wc_Sha3_512_Free((wc_Sha3*)sha);
- /* return 1 on success, 0 otherwise */
- if (ret == 0)
- return 1;
- return 0;
- }
- #endif /* WOLFSSL_NOSHA3_512 */
- #endif /* WOLFSSL_SHA3 */
- unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key,
- int key_len, const unsigned char* d, int n,
- unsigned char* md, unsigned int* md_len)
- {
- int type;
- int mdlen;
- unsigned char* ret = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- Hmac* hmac = NULL;
- #else
- Hmac hmac[1];
- #endif
- void* heap = NULL;
- WOLFSSL_ENTER("wolfSSL_HMAC");
- if (!md) {
- WOLFSSL_MSG("Static buffer not supported, pass in md buffer");
- return NULL; /* no static buffer support */
- }
- #ifndef NO_MD5
- if (XSTRCMP(evp_md, "MD5") == 0) {
- type = WC_MD5;
- mdlen = WC_MD5_DIGEST_SIZE;
- } else
- #endif
- #ifdef WOLFSSL_SHA224
- if (XSTRCMP(evp_md, "SHA224") == 0) {
- type = WC_SHA224;
- mdlen = WC_SHA224_DIGEST_SIZE;
- } else
- #endif
- #ifndef NO_SHA256
- if (XSTRCMP(evp_md, "SHA256") == 0) {
- type = WC_SHA256;
- mdlen = WC_SHA256_DIGEST_SIZE;
- } else
- #endif
- #ifdef WOLFSSL_SHA384
- if (XSTRCMP(evp_md, "SHA384") == 0) {
- type = WC_SHA384;
- mdlen = WC_SHA384_DIGEST_SIZE;
- } else
- #endif
- #ifdef WOLFSSL_SHA512
- if (XSTRCMP(evp_md, "SHA512") == 0) {
- type = WC_SHA512;
- mdlen = WC_SHA512_DIGEST_SIZE;
- } else
- #endif
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- if (XSTRCMP(evp_md, "SHA3_224") == 0) {
- type = WC_SHA3_224;
- mdlen = WC_SHA3_224_DIGEST_SIZE;
- } else
- #endif
- #ifndef WOLFSSL_NOSHA3_256
- if (XSTRCMP(evp_md, "SHA3_256") == 0) {
- type = WC_SHA3_256;
- mdlen = WC_SHA3_256_DIGEST_SIZE;
- } else
- #endif
- if (XSTRCMP(evp_md, "SHA3_384") == 0) {
- type = WC_SHA3_384;
- mdlen = WC_SHA3_384_DIGEST_SIZE;
- } else
- #ifndef WOLFSSL_NOSHA3_512
- if (XSTRCMP(evp_md, "SHA3_512") == 0) {
- type = WC_SHA3_512;
- mdlen = WC_SHA3_512_DIGEST_SIZE;
- } else
- #endif
- #endif
- #ifndef NO_SHA
- if (XSTRCMP(evp_md, "SHA") == 0) {
- type = WC_SHA;
- mdlen = WC_SHA_DIGEST_SIZE;
- } else
- #endif
- {
- return NULL;
- }
- #ifdef WOLFSSL_SMALL_STACK
- hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
- if (hmac == NULL)
- return NULL;
- #endif
- if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) {
- if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) {
- if (wc_HmacUpdate(hmac, d, n) == 0) {
- if (wc_HmacFinal(hmac, md) == 0) {
- if (md_len)
- *md_len = mdlen;
- ret = md;
- }
- }
- }
- wc_HmacFree(hmac);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
- #endif
- (void)evp_md;
- return ret;
- }
- #ifndef NO_DES3
- /* 0 on ok */
- int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key,
- WOLFSSL_DES_key_schedule* schedule)
- {
- WOLFSSL_ENTER("wolfSSL_DES_key_sched");
- if (key == NULL || schedule == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- }
- else {
- XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock));
- }
- return 0;
- }
- /* intended to behave similar to Kerberos mit_des_cbc_cksum
- * return the last 4 bytes of cipher text */
- WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
- WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc,
- WOLFSSL_const_DES_cblock* iv)
- {
- WOLFSSL_DES_LONG ret;
- unsigned char* tmp;
- unsigned char* data = (unsigned char*)in;
- long dataSz = length;
- byte dynamicFlag = 0; /* when padding the buffer created needs free'd */
- WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum");
- if (in == NULL || out == NULL || sc == NULL || iv == NULL) {
- WOLFSSL_MSG("Bad argument passed in");
- return 0;
- }
- /* if input length is not a multiple of DES_BLOCK_SIZE pad with 0s */
- if (dataSz % DES_BLOCK_SIZE) {
- dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE);
- data = (unsigned char*)XMALLOC(dataSz, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (data == NULL) {
- WOLFSSL_MSG("Issue creating temporary buffer");
- return 0;
- }
- dynamicFlag = 1; /* set to free buffer at end */
- XMEMCPY(data, in, length);
- XMEMSET(data + length, 0, dataSz - length); /* padding */
- }
- tmp = (unsigned char*)XMALLOC(dataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (tmp == NULL) {
- WOLFSSL_MSG("Issue creating temporary buffer");
- if (dynamicFlag == 1) {
- XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- return 0;
- }
- wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc,
- (WOLFSSL_DES_cblock*)iv, 1);
- XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE),
- DES_BLOCK_SIZE);
- ret = (((*((unsigned char*)out + 4) & 0xFF) << 24)|
- ((*((unsigned char*)out + 5) & 0xFF) << 16)|
- ((*((unsigned char*)out + 6) & 0xFF) << 8) |
- (*((unsigned char*)out + 7) & 0xFF));
- XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (dynamicFlag == 1) {
- XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- return ret;
- }
- void wolfSSL_DES_cbc_encrypt(const unsigned char* input,
- unsigned char* output, long length,
- WOLFSSL_DES_key_schedule* schedule,
- WOLFSSL_DES_cblock* ivec, int enc)
- {
- Des myDes;
- byte lastblock[DES_BLOCK_SIZE];
- int lb_sz;
- long blk;
- WOLFSSL_ENTER("DES_cbc_encrypt");
- /* OpenSSL compat, no ret */
- if (wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec,
- !enc) != 0) {
- WOLFSSL_MSG("wc_Des_SetKey return error.");
- return;
- }
- lb_sz = length%DES_BLOCK_SIZE;
- blk = length/DES_BLOCK_SIZE;
- if (enc == DES_ENCRYPT){
- wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
- if(lb_sz){
- XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
- XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
- wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE,
- lastblock, (word32)DES_BLOCK_SIZE);
- }
- }
- else {
- wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
- if(lb_sz){
- wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE);
- XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
- }
- }
- }
- /* WOLFSSL_DES_key_schedule is a unsigned char array of size 8 */
- void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
- unsigned char* output, long sz,
- WOLFSSL_DES_key_schedule* ks1,
- WOLFSSL_DES_key_schedule* ks2,
- WOLFSSL_DES_key_schedule* ks3,
- WOLFSSL_DES_cblock* ivec, int enc)
- {
- int ret;
- Des3 des;
- byte key[24];/* EDE uses 24 size key */
- byte lastblock[DES_BLOCK_SIZE];
- int lb_sz;
- long blk;
- WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt");
- XMEMSET(key, 0, sizeof(key));
- XMEMCPY(key, *ks1, DES_BLOCK_SIZE);
- XMEMCPY(&key[DES_BLOCK_SIZE], *ks2, DES_BLOCK_SIZE);
- XMEMCPY(&key[DES_BLOCK_SIZE * 2], *ks3, DES_BLOCK_SIZE);
- lb_sz = sz%DES_BLOCK_SIZE;
- blk = sz/DES_BLOCK_SIZE;
- /* OpenSSL compat, no ret */
- (void)wc_Des3Init(&des, NULL, INVALID_DEVID);
- if (enc == DES_ENCRYPT) {
- if (wc_Des3_SetKey(&des, key, (const byte*)ivec,
- DES_ENCRYPTION) == 0) {
- ret = wc_Des3_CbcEncrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
- #if defined(WOLFSSL_ASYNC_CRYPT)
- ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
- #endif
- (void)ret; /* ignore return codes for processing */
- if(lb_sz){
- XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
- XMEMCPY(lastblock, input+sz-lb_sz, lb_sz);
- ret = wc_Des3_CbcEncrypt(&des, output+blk*DES_BLOCK_SIZE,
- lastblock, (word32)DES_BLOCK_SIZE);
- #if defined(WOLFSSL_ASYNC_CRYPT)
- ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
- #endif
- (void)ret; /* ignore return codes for processing */
- }
- }
- }
- else {
- if (wc_Des3_SetKey(&des, key, (const byte*)ivec,
- DES_DECRYPTION) == 0) {
- ret = wc_Des3_CbcDecrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
- #if defined(WOLFSSL_ASYNC_CRYPT)
- ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
- #endif
- (void)ret; /* ignore return codes for processing */
- if(lb_sz){
- ret = wc_Des3_CbcDecrypt(&des, lastblock, input+sz-lb_sz, (word32)DES_BLOCK_SIZE);
- #if defined(WOLFSSL_ASYNC_CRYPT)
- ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
- #endif
- (void)ret; /* ignore return codes for processing */
- XMEMCPY(output+sz-lb_sz, lastblock, lb_sz);
- }
- }
- }
- wc_Des3Free(&des);
- }
- /* correctly sets ivec for next call */
- void wolfSSL_DES_ncbc_encrypt(const unsigned char* input,
- unsigned char* output, long length,
- WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
- int enc)
- {
- Des myDes;
- byte lastblock[DES_BLOCK_SIZE];
- int lb_sz;
- long idx = length;
- long blk;
- WOLFSSL_ENTER("DES_ncbc_encrypt");
- /* OpenSSL compat, no ret */
- if (wc_Des_SetKey(&myDes, (const byte*)schedule,
- (const byte*)ivec, !enc) != 0) {
- WOLFSSL_MSG("wc_Des_SetKey return error.");
- return;
- }
- lb_sz = length%DES_BLOCK_SIZE;
- blk = length/DES_BLOCK_SIZE;
- idx -= sizeof(DES_cblock);
- if (lb_sz) {
- idx += DES_BLOCK_SIZE - lb_sz;
- }
- if (enc == DES_ENCRYPT){
- wc_Des_CbcEncrypt(&myDes, output, input,
- (word32)blk * DES_BLOCK_SIZE);
- if (lb_sz){
- XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
- XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
- wc_Des_CbcEncrypt(&myDes, output + blk * DES_BLOCK_SIZE,
- lastblock, (word32)DES_BLOCK_SIZE);
- }
- XMEMCPY(ivec, output + idx, sizeof(DES_cblock));
- } else {
- WOLFSSL_DES_cblock tmp;
- XMEMCPY(tmp, input + idx, sizeof(DES_cblock));
- wc_Des_CbcDecrypt(&myDes, output, input,
- (word32)blk * DES_BLOCK_SIZE);
- if (lb_sz){
- wc_Des_CbcDecrypt(&myDes, lastblock, input + length - lb_sz,
- (word32)DES_BLOCK_SIZE);
- XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
- }
- XMEMCPY(ivec, tmp, sizeof(WOLFSSL_DES_cblock));
- }
- }
- #endif /* NO_DES3 */
- void wolfSSL_ERR_free_strings(void)
- {
- /* handled internally */
- }
- void wolfSSL_cleanup_all_ex_data(void)
- {
- /* nothing to do here */
- }
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
- void wolfSSL_ERR_clear_error(void)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_clear_error");
- wc_ClearErrorNodes();
- }
- #endif
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- int wolfSSL_clear(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_clear");
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (!ssl->options.handShakeDone) {
- /* Only reset the session if we didn't complete a handshake */
- wolfSSL_SESSION_free(ssl->session);
- ssl->session = wolfSSL_NewSession(ssl->heap);
- if (ssl->session == NULL) {
- return WOLFSSL_FAILURE;
- }
- }
- /* reset option bits */
- ssl->options.isClosed = 0;
- ssl->options.connReset = 0;
- ssl->options.sentNotify = 0;
- ssl->options.closeNotify = 0;
- ssl->options.sendVerify = 0;
- ssl->options.serverState = NULL_STATE;
- ssl->options.clientState = NULL_STATE;
- ssl->options.connectState = CONNECT_BEGIN;
- ssl->options.acceptState = ACCEPT_BEGIN;
- ssl->options.handShakeState = NULL_STATE;
- ssl->options.handShakeDone = 0;
- ssl->options.processReply = 0; /* doProcessInit */
- ssl->options.havePeerVerify = 0;
- ssl->options.havePeerCert = 0;
- ssl->options.peerAuthGood = 0;
- ssl->options.tls1_3 = 0;
- ssl->options.haveSessionId = 0;
- ssl->options.tls = 0;
- ssl->options.tls1_1 = 0;
- ssl->options.noPskDheKe = 0;
- #ifdef HAVE_SESSION_TICKET
- #ifdef WOLFSSL_TLS13
- ssl->options.ticketsSent = 0;
- #endif
- ssl->options.rejectTicket = 0;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- ssl->earlyData = no_early_data;
- ssl->earlyDataSz = 0;
- #endif
- #if defined(HAVE_TLS_EXTENSIONS) && !defined(NO_TLS)
- TLSX_FreeAll(ssl->extensions, ssl->heap);
- ssl->extensions = NULL;
- #endif
- ssl->keys.encryptionOn = 0;
- XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
- if (InitHandshakeHashes(ssl) != 0)
- return WOLFSSL_FAILURE;
- #ifdef KEEP_PEER_CERT
- FreeX509(&ssl->peerCert);
- InitX509(&ssl->peerCert, 0, ssl->heap);
- #endif
- #ifdef WOLFSSL_QUIC
- wolfSSL_quic_clear(ssl);
- #endif
- return WOLFSSL_SUCCESS;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode)
- {
- /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
- WOLFSSL_ENTER("SSL_CTX_set_mode");
- switch(mode) {
- case SSL_MODE_ENABLE_PARTIAL_WRITE:
- ctx->partialWrite = 1;
- break;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- case SSL_MODE_RELEASE_BUFFERS:
- WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented.");
- break;
- #endif
- case SSL_MODE_AUTO_RETRY:
- ctx->autoRetry = 1;
- break;
- default:
- WOLFSSL_MSG("Mode Not Implemented");
- }
- /* SSL_MODE_AUTO_RETRY
- * Should not return -1 with renegotiation on read/write */
- return mode;
- }
- long wolfSSL_CTX_clear_mode(WOLFSSL_CTX* ctx, long mode)
- {
- /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
- WOLFSSL_ENTER("SSL_CTX_set_mode");
- switch(mode) {
- case SSL_MODE_ENABLE_PARTIAL_WRITE:
- ctx->partialWrite = 0;
- break;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- case SSL_MODE_RELEASE_BUFFERS:
- WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented.");
- break;
- #endif
- case SSL_MODE_AUTO_RETRY:
- ctx->autoRetry = 0;
- break;
- default:
- WOLFSSL_MSG("Mode Not Implemented");
- }
- /* SSL_MODE_AUTO_RETRY
- * Should not return -1 with renegotiation on read/write */
- return 0;
- }
- #endif
- #ifdef OPENSSL_EXTRA
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_SSL_get_mode(WOLFSSL* ssl)
- {
- /* TODO: */
- (void)ssl;
- WOLFSSL_STUB("SSL_get_mode");
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
- {
- /* TODO: */
- (void)ctx;
- WOLFSSL_STUB("SSL_CTX_get_mode");
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m)
- {
- /* TODO: maybe? */
- (void)ctx;
- (void)m;
- WOLFSSL_STUB("SSL_CTX_set_default_read_ahead");
- }
- #endif
- /* Storing app session context id, this value is inherited by WOLFSSL
- * objects created from WOLFSSL_CTX. Any session that is imported with a
- * different session context id will be rejected.
- *
- * ctx structure to set context in
- * sid_ctx value of context to set
- * sid_ctx_len length of sid_ctx buffer
- *
- * Returns WOLFSSL_SUCCESS in success case and SSL_FAILURE when failing
- */
- int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx,
- const unsigned char* sid_ctx,
- unsigned int sid_ctx_len)
- {
- WOLFSSL_ENTER("SSL_CTX_set_session_id_context");
- /* No application specific context needed for wolfSSL */
- if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) {
- return SSL_FAILURE;
- }
- XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len);
- ctx->sessionCtxSz = (byte)sid_ctx_len;
- return WOLFSSL_SUCCESS;
- }
- /* Storing app session context id. Any session that is imported with a
- * different session context id will be rejected.
- *
- * ssl structure to set context in
- * id value of context to set
- * len length of sid_ctx buffer
- *
- * Returns WOLFSSL_SUCCESS in success case and SSL_FAILURE when failing
- */
- int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id,
- unsigned int len)
- {
- WOLFSSL_ENTER("wolfSSL_set_session_id_context");
- if (len > ID_LEN || ssl == NULL || id == NULL) {
- return SSL_FAILURE;
- }
- XMEMCPY(ssl->sessionCtx, id, len);
- ssl->sessionCtxSz = (byte)len;
- return WOLFSSL_SUCCESS;
- }
- long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx)
- {
- (void)ctx;
- #ifndef NO_SESSION_CACHE
- return (long)(SESSIONS_PER_ROW * SESSION_ROWS);
- #else
- return 0;
- #endif
- }
- /* returns the unsigned error value and increments the pointer into the
- * error queue.
- *
- * file pointer to file name
- * line gets set to line number of error when not NULL
- */
- unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line)
- {
- #ifdef WOLFSSL_HAVE_ERROR_QUEUE
- int ret = wc_PullErrorNode(file, NULL, line);
- if (ret < 0) {
- if (ret == BAD_STATE_E) return 0; /* no errors in queue */
- WOLFSSL_MSG("Issue getting error node");
- WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret);
- ret = 0 - ret; /* return absolute value of error */
- /* panic and try to clear out nodes */
- wc_ClearErrorNodes();
- }
- return (unsigned long)ret;
- #else
- (void)file;
- (void)line;
- return 0;
- #endif
- }
- #if (defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA)) && \
- (!defined(_WIN32) && !defined(NO_ERROR_QUEUE))
- static const char WOLFSSL_SYS_ACCEPT_T[] = "accept";
- static const char WOLFSSL_SYS_BIND_T[] = "bind";
- static const char WOLFSSL_SYS_CONNECT_T[] = "connect";
- static const char WOLFSSL_SYS_FOPEN_T[] = "fopen";
- static const char WOLFSSL_SYS_FREAD_T[] = "fread";
- static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo";
- static const char WOLFSSL_SYS_GETSOCKOPT_T[] = "getsockopt";
- static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname";
- static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname";
- static const char WOLFSSL_SYS_GETNAMEINFO_T[] = "getnameinfo";
- static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname";
- static const char WOLFSSL_SYS_IOCTLSOCKET_T[] = "ioctlsocket";
- static const char WOLFSSL_SYS_LISTEN_T[] = "listen";
- static const char WOLFSSL_SYS_OPENDIR_T[] = "opendir";
- static const char WOLFSSL_SYS_SETSOCKOPT_T[] = "setsockopt";
- static const char WOLFSSL_SYS_SOCKET_T[] = "socket";
- /* switch with int mapped to function name for compatibility */
- static const char* wolfSSL_ERR_sys_func(int fun)
- {
- switch (fun) {
- case WOLFSSL_SYS_ACCEPT: return WOLFSSL_SYS_ACCEPT_T;
- case WOLFSSL_SYS_BIND: return WOLFSSL_SYS_BIND_T;
- case WOLFSSL_SYS_CONNECT: return WOLFSSL_SYS_CONNECT_T;
- case WOLFSSL_SYS_FOPEN: return WOLFSSL_SYS_FOPEN_T;
- case WOLFSSL_SYS_FREAD: return WOLFSSL_SYS_FREAD_T;
- case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T;
- case WOLFSSL_SYS_GETSOCKOPT: return WOLFSSL_SYS_GETSOCKOPT_T;
- case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T;
- case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T;
- case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T;
- case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T;
- case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T;
- case WOLFSSL_SYS_LISTEN: return WOLFSSL_SYS_LISTEN_T;
- case WOLFSSL_SYS_OPENDIR: return WOLFSSL_SYS_OPENDIR_T;
- case WOLFSSL_SYS_SETSOCKOPT: return WOLFSSL_SYS_SETSOCKOPT_T;
- case WOLFSSL_SYS_SOCKET: return WOLFSSL_SYS_SOCKET_T;
- default:
- return "NULL";
- }
- }
- #endif /* DEBUG_WOLFSSL */
- void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file,
- int line)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_put_error");
- #if !defined(DEBUG_WOLFSSL) && !defined(OPENSSL_EXTRA)
- (void)fun;
- (void)err;
- (void)file;
- (void)line;
- WOLFSSL_MSG("Not compiled in debug mode");
- #elif defined(OPENSSL_EXTRA) && \
- (defined(_WIN32) || defined(NO_ERROR_QUEUE))
- (void)fun;
- (void)file;
- (void)line;
- WOLFSSL_ERROR(err);
- #else
- WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line,
- file, NULL);
- #endif
- (void)lib;
- }
- /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for
- * more flexibility.
- *
- * file output pointer to file where error happened
- * line output to line number of error
- * data output data. Is a string if ERR_TXT_STRING flag is used
- * flags output format of output
- *
- * Returns the error value or 0 if no errors are in the queue
- */
- unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line,
- const char** data, int *flags)
- {
- #ifdef WOLFSSL_HAVE_ERROR_QUEUE
- int ret;
- WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data");
- if (flags != NULL)
- *flags = ERR_TXT_STRING; /* Clear the flags */
- ret = wc_PullErrorNode(file, data, line);
- if (ret < 0) {
- if (ret == BAD_STATE_E) return 0; /* no errors in queue */
- WOLFSSL_MSG("Error with pulling error node!");
- WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
- ret = 0 - ret; /* return absolute value of error */
- /* panic and try to clear out nodes */
- wc_ClearErrorNodes();
- }
- return (unsigned long)ret;
- #else
- WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data");
- WOLFSSL_MSG("Error queue turned off, can not get error line");
- (void)file;
- (void)line;
- (void)data;
- (void)flags;
- return 0;
- #endif
- }
- #endif /* OPENSSL_EXTRA */
- #if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \
- (defined(OPENSSL_EXTRA) && defined(SESSION_CERTS))
- /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object.
- *
- * x509 WOLFSSL_X509 object to decode into.
- * in X509 DER data.
- * len Length of the X509 DER data.
- * returns the new certificate on success, otherwise NULL.
- */
- static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len)
- {
- int ret;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert;
- #else
- DecodedCert cert[1];
- #endif
- if (x509 == NULL || in == NULL || len <= 0)
- return BAD_FUNC_ARG;
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
- /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object.
- */
- InitDecodedCert(cert, (byte*)in, len, NULL);
- if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) {
- /* Check if x509 was not previously initialized by wolfSSL_X509_new() */
- if (x509->dynamicMemory != TRUE)
- InitX509(x509, 0, NULL);
- ret = CopyDecodedToX509(x509, cert);
- FreeDecodedCert(cert);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
- #endif
- return ret;
- }
- #endif /* (KEEP_PEER_CERT & SESSION_CERTS) || (OPENSSL_EXTRA & SESSION_CERTS) */
- #ifdef KEEP_PEER_CERT
- WOLFSSL_ABI
- WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
- {
- WOLFSSL_X509* ret = NULL;
- WOLFSSL_ENTER("SSL_get_peer_certificate");
- if (ssl != NULL) {
- if (ssl->peerCert.issuer.sz)
- ret = wolfSSL_X509_dup(&ssl->peerCert);
- #ifdef SESSION_CERTS
- else if (ssl->session->chain.count > 0) {
- if (DecodeToX509(&ssl->peerCert, ssl->session->chain.certs[0].buffer,
- ssl->session->chain.certs[0].length) == 0) {
- ret = wolfSSL_X509_dup(&ssl->peerCert);
- }
- }
- #endif
- }
- WOLFSSL_LEAVE("SSL_get_peer_certificate", ret != NULL);
- return ret;
- }
- #endif /* KEEP_PEER_CERT */
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- /* Return stack of peer certs.
- * Caller does not need to free return. The stack is Free'd when WOLFSSL* ssl is.
- */
- WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain");
- if (ssl == NULL)
- return NULL;
- /* Try to populate if NULL or empty */
- if (ssl->peerCertChain == NULL ||
- wolfSSL_sk_X509_num(ssl->peerCertChain) == 0)
- wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl);
- return ssl->peerCertChain;
- }
- #ifndef WOLFSSL_QT
- static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm,
- WOLFSSL_X509 *x);
- /**
- * Recursively push the issuer CA chain onto the stack
- * @param cm The cert manager that is queried for the issuer
- * @param x This cert's issuer will be queried in cm
- * @param sk The issuer is pushed onto this stack
- * @return WOLFSSL_SUCCESS on success
- * WOLFSSL_FAILURE on no issuer found
- * WOLFSSL_FATAL_ERROR on a fatal error
- */
- static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm,
- WOLFSSL_X509 *x, WOLFSSL_STACK* sk)
- {
- WOLFSSL_X509* issuer[MAX_CHAIN_DEPTH];
- int i;
- int push = 1;
- int ret = WOLFSSL_SUCCESS;
- for (i = 0; i < MAX_CHAIN_DEPTH; i++) {
- if (x509GetIssuerFromCM(&issuer[i], cm, x)
- != WOLFSSL_SUCCESS)
- break;
- x = issuer[i];
- }
- if (i == 0) /* No further chain found */
- return WOLFSSL_FAILURE;
- i--;
- for (; i >= 0; i--) {
- if (push) {
- if (wolfSSL_sk_X509_push(sk, issuer[i]) != WOLFSSL_SUCCESS) {
- wolfSSL_X509_free(issuer[i]);
- ret = WOLFSSL_FATAL_ERROR;
- push = 0; /* Free the rest of the unpushed certs */
- }
- }
- else {
- wolfSSL_X509_free(issuer[i]);
- }
- }
- return ret;
- }
- #endif /* !WOLFSSL_QT */
- /* Builds up and creates a stack of peer certificates for ssl->peerCertChain
- based off of the ssl session chain. Attempts to place CA certificates
- at the bottom of the stack. Returns stack of WOLFSSL_X509 certs or
- NULL on failure */
- WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl)
- {
- WOLFSSL_STACK* sk;
- WOLFSSL_X509* x509;
- int i = 0;
- int ret;
- WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain");
- if ((ssl == NULL) || (ssl->session->chain.count == 0))
- return NULL;
- sk = wolfSSL_sk_X509_new();
- i = ssl->session->chain.count-1;
- for (; i >= 0; i--) {
- x509 = wolfSSL_X509_new();
- if (x509 == NULL) {
- WOLFSSL_MSG("Error Creating X509");
- wolfSSL_sk_X509_pop_free(sk, NULL);
- return NULL;
- }
- ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer,
- ssl->session->chain.certs[i].length);
- #if !defined(WOLFSSL_QT)
- if (ret == 0 && i == ssl->session->chain.count-1) {
- /* On the last element in the chain try to add the CA chain
- * first if we have one for this cert */
- if (PushCAx509Chain(SSL_CM(ssl), x509, sk)
- == WOLFSSL_FATAL_ERROR) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- #endif
- if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error decoding cert");
- wolfSSL_X509_free(x509);
- wolfSSL_sk_X509_pop_free(sk, NULL);
- return NULL;
- }
- }
- if (sk == NULL) {
- WOLFSSL_MSG("Null session chain");
- }
- #if defined(OPENSSL_ALL)
- else if (ssl->options.side == WOLFSSL_SERVER_END) {
- /* to be compliant with openssl
- first element is kept as peer cert on server side.*/
- wolfSSL_sk_X509_shift(sk);
- }
- #endif
- if (ssl->peerCertChain != NULL)
- wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL);
- /* This is Free'd when ssl is Free'd */
- ssl->peerCertChain = sk;
- return sk;
- }
- #endif /* SESSION_CERTS && OPENSSL_EXTRA */
- #ifndef NO_CERTS
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- /* create a generic wolfSSL stack node
- * returns a new WOLFSSL_STACK structure on success */
- WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap)
- {
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_node");
- sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap,
- DYNAMIC_TYPE_OPENSSL);
- if (sk != NULL) {
- XMEMSET(sk, 0, sizeof(*sk));
- sk->heap = heap;
- }
- return sk;
- }
- /* free's node but does not free internal data such as in->data.x509 */
- void wolfSSL_sk_free_node(WOLFSSL_STACK* in)
- {
- if (in != NULL) {
- XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL);
- }
- }
- /* pushes node "in" onto "stack" and returns pointer to the new stack on success
- * also handles internal "num" for number of nodes on stack
- * return WOLFSSL_SUCCESS on success
- */
- int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in)
- {
- if (stack == NULL || in == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (*stack == NULL) {
- in->num = 1;
- *stack = in;
- return WOLFSSL_SUCCESS;
- }
- in->num = (*stack)->num + 1;
- in->next = *stack;
- *stack = in;
- return WOLFSSL_SUCCESS;
- }
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- static WC_INLINE int compare_WOLFSSL_CIPHER(
- WOLFSSL_CIPHER *a,
- WOLFSSL_CIPHER *b)
- {
- if ((a->cipherSuite0 == b->cipherSuite0) &&
- (a->cipherSuite == b->cipherSuite) &&
- (a->ssl == b->ssl) &&
- (XMEMCMP(a->description, b->description, sizeof a->description) == 0) &&
- (a->offset == b->offset) &&
- (a->in_stack == b->in_stack) &&
- (a->bits == b->bits))
- return 0;
- else
- return -1;
- }
- #endif /* OPENSSL_ALL || WOLFSSL_QT */
- /* return 1 on success 0 on fail */
- int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data)
- {
- WOLFSSL_STACK* node;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- WOLFSSL_CIPHER ciph;
- #endif
- WOLFSSL_ENTER("wolfSSL_sk_push");
- if (!sk) {
- return WOLFSSL_FAILURE;
- }
- /* Check if empty data */
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- /* check if entire struct is zero */
- XMEMSET(&ciph, 0, sizeof(WOLFSSL_CIPHER));
- if (compare_WOLFSSL_CIPHER(&sk->data.cipher, &ciph) == 0) {
- sk->data.cipher = *(WOLFSSL_CIPHER*)data;
- sk->num = 1;
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(&sk->data.cipher);
- }
- return WOLFSSL_SUCCESS;
- }
- break;
- #endif
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- /* All other types are pointers */
- if (!sk->data.generic) {
- sk->data.generic = (void*)data;
- sk->num = 1;
- #ifdef OPENSSL_ALL
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(sk->data.generic);
- }
- #endif
- return WOLFSSL_SUCCESS;
- }
- break;
- }
- /* stack already has value(s) create a new node and add more */
- node = wolfSSL_sk_new_node(sk->heap);
- if (!node) {
- WOLFSSL_MSG("Memory error");
- return WOLFSSL_FAILURE;
- }
- /* push new x509 onto head of stack */
- node->next = sk->next;
- node->type = sk->type;
- sk->next = node;
- sk->num += 1;
- #ifdef OPENSSL_ALL
- node->comp = sk->comp;
- node->hash_fn = sk->hash_fn;
- node->hash = sk->hash;
- sk->hash = 0;
- #endif
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- node->data.cipher = sk->data.cipher;
- sk->data.cipher = *(WOLFSSL_CIPHER*)data;
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(&sk->data.cipher);
- }
- break;
- #endif
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- /* All other types are pointers */
- node->data.generic = sk->data.generic;
- sk->data.generic = (void*)data;
- #ifdef OPENSSL_ALL
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(sk->data.generic);
- }
- #endif
- break;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #ifdef OPENSSL_EXTRA
- /* returns the node at index "idx", NULL if not found */
- WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx)
- {
- int i;
- WOLFSSL_STACK* ret = NULL;
- WOLFSSL_STACK* current;
- current = sk;
- for (i = 0; i <= idx && current != NULL; i++) {
- if (i == idx) {
- ret = current;
- break;
- }
- current = current->next;
- }
- return ret;
- }
- #endif /* OPENSSL_EXTRA */
- #ifdef OPENSSL_EXTRA
- #if defined(OPENSSL_ALL)
- void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data)
- {
- unsigned long hash;
- WOLFSSL_ENTER("wolfSSL_lh_retrieve");
- if (!sk || !data) {
- WOLFSSL_MSG("Bad parameters");
- return NULL;
- }
- if (!sk->hash_fn) {
- WOLFSSL_MSG("No hash function defined");
- return NULL;
- }
- hash = sk->hash_fn(data);
- while (sk) {
- /* Calc hash if not done so yet */
- if (!sk->hash) {
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- sk->hash = sk->hash_fn(&sk->data.cipher);
- break;
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- sk->hash = sk->hash_fn(sk->data.generic);
- break;
- }
- }
- if (sk->hash == hash) {
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- return &sk->data.cipher;
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- return sk->data.generic;
- }
- }
- sk = sk->next;
- }
- return NULL;
- }
- #endif /* OPENSSL_ALL */
- #endif /* OPENSSL_EXTRA */
- /* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
- KEEP_OUR_CERT is to insure ability for returning ssl certificate */
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
- defined(KEEP_OUR_CERT)
- WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- return NULL;
- }
- if (ssl->buffers.weOwnCert) {
- if (ssl->ourCert == NULL) {
- if (ssl->buffers.certificate == NULL) {
- WOLFSSL_MSG("Certificate buffer not set!");
- return NULL;
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ssl->ourCert = wolfSSL_X509_d2i(NULL,
- ssl->buffers.certificate->buffer,
- ssl->buffers.certificate->length);
- #endif
- }
- return ssl->ourCert;
- }
- else { /* if cert not owned get parent ctx cert or return null */
- if (ssl->ctx) {
- if (ssl->ctx->ourCert == NULL) {
- if (ssl->ctx->certificate == NULL) {
- WOLFSSL_MSG("Ctx Certificate buffer not set!");
- return NULL;
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL,
- ssl->ctx->certificate->buffer,
- ssl->ctx->certificate->length);
- #endif
- ssl->ctx->ownOurCert = 1;
- }
- return ssl->ctx->ourCert;
- }
- }
- return NULL;
- }
- WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx)
- {
- if (ctx) {
- if (ctx->ourCert == NULL) {
- if (ctx->certificate == NULL) {
- WOLFSSL_MSG("Ctx Certificate buffer not set!");
- return NULL;
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ctx->ourCert = wolfSSL_X509_d2i(NULL,
- ctx->certificate->buffer,
- ctx->certificate->length);
- #endif
- ctx->ownOurCert = 1;
- }
- return ctx->ourCert;
- }
- return NULL;
- }
- #endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
- #endif /* NO_CERTS */
- #if !defined(NO_ASN) && (defined(OPENSSL_EXTRA) || \
- defined(OPENSSL_EXTRA_X509_SMALL))
- void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj)
- {
- if (obj == NULL) {
- return;
- }
- if ((obj->obj != NULL) && ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0)) {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("Freeing ASN1 data");
- #endif
- XFREE((void*)obj->obj, obj->heap, DYNAMIC_TYPE_ASN1);
- obj->obj = NULL;
- }
- #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
- if (obj->pathlen != NULL) {
- wolfSSL_ASN1_INTEGER_free(obj->pathlen);
- obj->pathlen = NULL;
- }
- #endif
- if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC) != 0) {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("Freeing ASN1 OBJECT");
- #endif
- XFREE(obj, NULL, DYNAMIC_TYPE_ASN1);
- }
- }
- WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void)
- {
- WOLFSSL_ASN1_OBJECT* obj;
- obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL,
- DYNAMIC_TYPE_ASN1);
- if (obj == NULL) {
- return NULL;
- }
- XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT));
- obj->d.ia5 = &(obj->d.ia5_internal);
- #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
- obj->d.iPAddress = &(obj->d.iPAddress_internal);
- #endif
- obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
- return obj;
- }
- WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_dup(WOLFSSL_ASN1_OBJECT* obj)
- {
- WOLFSSL_ASN1_OBJECT* dupl = NULL;
- WOLFSSL_ENTER("wolfSSL_ASN1_OBJECT_dup");
- if (!obj) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
- dupl = wolfSSL_ASN1_OBJECT_new();
- if (!dupl) {
- WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new error");
- return NULL;
- }
- /* Copy data */
- XMEMCPY(dupl->sName, obj->sName, WOLFSSL_MAX_SNAME);
- dupl->type = obj->type;
- dupl->grp = obj->grp;
- dupl->nid = obj->nid;
- dupl->objSz = obj->objSz;
- if (obj->obj) {
- dupl->obj = (const unsigned char*)XMALLOC(
- obj->objSz, NULL, DYNAMIC_TYPE_ASN1);
- if (!dupl->obj) {
- WOLFSSL_MSG("ASN1 obj malloc error");
- wolfSSL_ASN1_OBJECT_free(dupl);
- return NULL;
- }
- XMEMCPY((byte*)dupl->obj, obj->obj, obj->objSz);
- dupl->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA;
- }
- return dupl;
- }
- #endif /* !NO_ASN && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
- #ifndef NO_ASN
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- /* Creates and returns a new WOLFSSL_CIPHER stack. */
- WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void)
- {
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_asn1_obj");
- sk = wolfSSL_sk_new_null();
- if (sk == NULL)
- return NULL;
- sk->type = STACK_TYPE_OBJ;
- return sk;
- }
- /* return 1 on success 0 on fail */
- int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
- WOLFSSL_ASN1_OBJECT* obj)
- {
- WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_push");
- if (sk == NULL || obj == NULL) {
- return WOLFSSL_FAILURE;
- }
- return wolfSSL_sk_push(sk, obj);
- }
- WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop(
- WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
- {
- WOLFSSL_STACK* node;
- WOLFSSL_ASN1_OBJECT* obj;
- if (sk == NULL) {
- return NULL;
- }
- node = sk->next;
- obj = sk->data.obj;
- if (node != NULL) { /* update sk and remove node from stack */
- sk->data.obj = node->data.obj;
- sk->next = node->next;
- XFREE(node, NULL, DYNAMIC_TYPE_ASN1);
- }
- else { /* last obj in stack */
- sk->data.obj = NULL;
- }
- if (sk->num > 0) {
- sk->num -= 1;
- }
- return obj;
- }
- /* Free the structure for ASN1_OBJECT stack
- *
- * sk stack to free nodes in
- */
- void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
- {
- wolfSSL_sk_free(sk);
- }
- /* Free's all nodes in ASN1_OBJECT stack.
- * This is different then wolfSSL_ASN1_OBJECT_free in that it allows for
- * choosing the function to use when freeing an ASN1_OBJECT stack.
- *
- * sk stack to free nodes in
- * f X509 free function
- */
- void wolfSSL_sk_ASN1_OBJECT_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
- void (*f) (WOLFSSL_ASN1_OBJECT*))
- {
- WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_pop_free");
- wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #endif /* !NO_ASN */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- #ifndef NO_ASN
- int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in)
- {
- /*
- ASN1_STRING_to_UTF8() converts the string in to UTF8 format,
- the converted data is allocated in a buffer in *out.
- The length of out is returned or a negative error code.
- The buffer *out should be free using OPENSSL_free().
- */
- unsigned char* buf;
- unsigned char* inPtr;
- int inLen;
- if (!out || !in) {
- return -1;
- }
- inPtr = wolfSSL_ASN1_STRING_data(in);
- inLen = wolfSSL_ASN1_STRING_length(in);
- if (!inPtr || inLen < 0) {
- return -1;
- }
- buf = (unsigned char*)XMALLOC(inLen + 1, NULL, DYNAMIC_TYPE_OPENSSL);
- if (!buf) {
- return -1;
- }
- XMEMCPY(buf, inPtr, inLen + 1);
- *out = buf;
- return inLen;
- }
- #endif /* !NO_ASN */
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- #if defined(OPENSSL_EXTRA)
- #ifndef NO_ASN
- int wolfSSL_ASN1_UNIVERSALSTRING_to_string(WOLFSSL_ASN1_STRING *s)
- {
- char *idx;
- char *copy;
- WOLFSSL_ENTER("wolfSSL_ASN1_UNIVERSALSTRING_to_string");
- if (!s) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if (s->type != V_ASN1_UNIVERSALSTRING) {
- WOLFSSL_MSG("Input is not a universal string");
- return WOLFSSL_FAILURE;
- }
- if ((s->length % 4) != 0) {
- WOLFSSL_MSG("Input string must be divisible by 4");
- return WOLFSSL_FAILURE;
- }
- for (idx = s->data; idx < s->data + s->length; idx += 4)
- if ((idx[0] != '\0') || (idx[1] != '\0') || (idx[2] != '\0'))
- break;
- if (idx != s->data + s->length) {
- WOLFSSL_MSG("Wrong string format");
- return WOLFSSL_FAILURE;
- }
- for (copy = idx = s->data; idx < s->data + s->length; idx += 4)
- *copy++ = idx[3];
- *copy = '\0';
- s->length /= 4;
- s->type = V_ASN1_PRINTABLESTRING;
- return WOLFSSL_SUCCESS;
- }
- /* Returns string representation of ASN1_STRING */
- char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method,
- const WOLFSSL_ASN1_STRING *s)
- {
- int i;
- int tmpSz = 100;
- int valSz = 5;
- char* tmp;
- char val[5];
- unsigned char* str;
- WOLFSSL_ENTER("wolfSSL_i2s_ASN1_STRING");
- (void)method;
- if(s == NULL || s->data == NULL) {
- WOLFSSL_MSG("Bad Function Argument");
- return NULL;
- }
- str = (unsigned char*)XMALLOC(s->length, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (str == NULL) {
- WOLFSSL_MSG("Memory Error");
- return NULL;
- }
- XMEMCPY(str, (unsigned char*)s->data, s->length);
- tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (tmp == NULL) {
- WOLFSSL_MSG("Memory Error");
- XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- XMEMSET(tmp, 0, tmpSz);
- for (i = 0; i < tmpSz && i < (s->length - 1); i++) {
- if (XSNPRINTF(val, valSz, "%02X:", str[i])
- >= valSz)
- {
- WOLFSSL_MSG("Buffer overrun");
- XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- XSTRNCAT(tmp, val, valSz);
- }
- if (XSNPRINTF(val, valSz, "%02X", str[i])
- >= valSz)
- {
- WOLFSSL_MSG("Buffer overrun");
- XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- XSTRNCAT(tmp, val, valSz);
- XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return tmp;
- }
- #endif /* NO_ASN */
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- void wolfSSL_set_connect_state(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_set_connect_state");
- if (ssl == NULL) {
- WOLFSSL_MSG("WOLFSSL struct pointer passed in was null");
- return;
- }
- #ifndef NO_DH
- /* client creates its own DH parameters on handshake */
- if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- }
- ssl->buffers.serverDH_P.buffer = NULL;
- if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- }
- ssl->buffers.serverDH_G.buffer = NULL;
- #endif
- if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error initializing client side");
- }
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- int wolfSSL_get_shutdown(const WOLFSSL* ssl)
- {
- int isShutdown = 0;
- WOLFSSL_ENTER("wolfSSL_get_shutdown");
- if (ssl) {
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- if (ssl->options.handShakeState == NULL_STATE) {
- /* The SSL object was possibly cleared with wolfSSL_clear after
- * a successful shutdown. Simulate a response for a full
- * bidirectional shutdown. */
- isShutdown = WOLFSSL_SENT_SHUTDOWN | WOLFSSL_RECEIVED_SHUTDOWN;
- }
- else
- #endif
- {
- /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent *
- * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */
- if (ssl->options.sentNotify)
- isShutdown |= WOLFSSL_SENT_SHUTDOWN;
- if (ssl->options.closeNotify||ssl->options.connReset)
- isShutdown |= WOLFSSL_RECEIVED_SHUTDOWN;
- }
- }
- return isShutdown;
- }
- int wolfSSL_session_reused(WOLFSSL* ssl)
- {
- int resuming = 0;
- WOLFSSL_ENTER("wolfSSL_session_reused");
- if (ssl)
- resuming = ssl->options.resuming;
- WOLFSSL_LEAVE("wolfSSL_session_reused", resuming);
- return resuming;
- }
- /* return a new malloc'd session with default settings on success */
- WOLFSSL_SESSION* wolfSSL_NewSession(void* heap)
- {
- WOLFSSL_SESSION* ret = NULL;
- ret = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), heap,
- DYNAMIC_TYPE_SESSION);
- if (ret != NULL) {
- XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION));
- #ifndef SINGLE_THREADED
- if (wc_InitMutex(&ret->refMutex) != 0) {
- WOLFSSL_MSG("Error setting up session reference mutex");
- XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION);
- return NULL;
- }
- #endif
- ret->refCount = 1;
- #ifndef NO_SESSION_CACHE
- ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */
- #endif
- ret->type = WOLFSSL_SESSION_TYPE_HEAP;
- ret->heap = heap;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("SESSION master secret", ret->masterSecret, SECRET_LEN);
- wc_MemZero_Add("SESSION id", ret->sessionID, ID_LEN);
- #endif
- #ifdef HAVE_SESSION_TICKET
- ret->ticket = ret->staticTicket;
- #endif
- #ifdef HAVE_STUNNEL
- /* stunnel has this funny mechanism of storing the "is_authenticated"
- * session info in the session ex data. This is basically their
- * default so let's just hard code it. */
- if (wolfSSL_SESSION_set_ex_data(ret, 0, (void *)(-1))
- != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error setting up ex data for stunnel");
- XFREE(ret, NULL, DYNAMIC_TYPE_SESSION);
- return NULL;
- }
- #endif
- #ifdef HAVE_EX_DATA
- ret->ownExData = 1;
- #endif
- }
- return ret;
- }
- WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap)
- {
- return wolfSSL_NewSession(heap);
- }
- WOLFSSL_SESSION* wolfSSL_SESSION_new(void)
- {
- return wolfSSL_SESSION_new_ex(NULL);
- }
- /* add one to session reference count
- * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */
- int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session)
- {
- session = ClientSessionToSession(session);
- if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_HEAP)
- return WOLFSSL_FAILURE;
- #ifndef SINGLE_THREADED
- if (wc_LockMutex(&session->refMutex) != 0) {
- WOLFSSL_MSG("Failed to lock session mutex");
- return WOLFSSL_FAILURE;
- }
- #endif
- session->refCount++;
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&session->refMutex);
- #endif
- return WOLFSSL_SUCCESS;
- }
- /**
- * Deep copy the contents from input to output.
- * @param input The source of the copy.
- * @param output The destination of the copy.
- * @param avoidSysCalls If true, then system calls will be avoided or an error
- * will be returned if it is not possible to proceed
- * without a system call. This is useful for fetching
- * sessions from cache. When a cache row is locked, we
- * don't want to block other threads with long running
- * system calls.
- * @return WOLFSSL_SUCCESS on success
- * WOLFSSL_FAILURE on failure
- */
- int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output,
- int avoidSysCalls)
- {
- #ifdef HAVE_SESSION_TICKET
- int ticLenAlloc = 0;
- byte *ticBuff = NULL;
- #endif
- const size_t copyOffset = OFFSETOF(WOLFSSL_SESSION, heap) + sizeof(input->heap);
- int ret = WOLFSSL_SUCCESS;
- (void)avoidSysCalls;
- input = ClientSessionToSession(input);
- output = ClientSessionToSession(output);
- if (input == NULL || output == NULL || input == output) {
- WOLFSSL_MSG("input or output are null or same");
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_SESSION_TICKET
- if (output->ticket != output->staticTicket) {
- ticBuff = output->ticket;
- ticLenAlloc = output->ticketLenAlloc;
- }
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- if (output->peer != NULL) {
- if (avoidSysCalls) {
- WOLFSSL_MSG("Can't free cert when avoiding syscalls");
- return WOLFSSL_FAILURE;
- }
- wolfSSL_X509_free(output->peer);
- output->peer = NULL;
- }
- #endif
- XMEMCPY((byte*)output + copyOffset, (byte*)input + copyOffset,
- sizeof(WOLFSSL_SESSION) - copyOffset);
- /* Set sane values for copy */
- #ifndef NO_SESSION_CACHE
- if (output->type != WOLFSSL_SESSION_TYPE_CACHE)
- output->cacheRow = INVALID_SESSION_ROW;
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- if (input->peer != NULL && input->peer->dynamicMemory) {
- if (wolfSSL_X509_up_ref(input->peer) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Can't increase peer cert ref count");
- output->peer = NULL;
- }
- }
- else if (!avoidSysCalls)
- output->peer = wolfSSL_X509_dup(input->peer);
- else
- /* output->peer is not that important to copy */
- output->peer = NULL;
- #endif
- #ifdef HAVE_SESSION_TICKET
- if (input->ticketLen > SESSION_TICKET_LEN) {
- /* Need dynamic buffer */
- if (ticBuff == NULL || ticLenAlloc < input->ticketLen) {
- /* allocate new one */
- byte* tmp;
- if (avoidSysCalls) {
- WOLFSSL_MSG("Failed to allocate memory for ticket when avoiding"
- " syscalls");
- output->ticket = ticBuff;
- output->ticketLenAlloc = (word16) ticLenAlloc;
- output->ticketLen = 0;
- ret = WOLFSSL_FAILURE;
- }
- else {
- tmp = (byte*)XREALLOC(ticBuff, input->ticketLen,
- output->heap, DYNAMIC_TYPE_SESSION_TICK);
- if (tmp == NULL) {
- WOLFSSL_MSG("Failed to allocate memory for ticket");
- XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK);
- output->ticket = NULL;
- output->ticketLen = 0;
- output->ticketLenAlloc = 0;
- ret = WOLFSSL_FAILURE;
- }
- else {
- ticBuff = tmp;
- ticLenAlloc = input->ticketLen;
- }
- }
- }
- if (ticBuff != NULL && ret == WOLFSSL_SUCCESS) {
- XMEMCPY(ticBuff, input->ticket, input->ticketLen);
- output->ticket = ticBuff;
- output->ticketLenAlloc = (word16) ticLenAlloc;
- }
- }
- else {
- /* Default ticket to non dynamic */
- if (avoidSysCalls) {
- /* Try to use ticBuf if available. Caller can later move it to
- * the static buffer. */
- if (ticBuff != NULL) {
- if (ticLenAlloc >= input->ticketLen) {
- output->ticket = output->staticTicket;
- output->ticketLenAlloc = 0;
- }
- else {
- WOLFSSL_MSG("ticket dynamic buffer too small but we are "
- "avoiding system calls");
- ret = WOLFSSL_FAILURE;
- output->ticket = ticBuff;
- output->ticketLenAlloc = (word16) ticLenAlloc;
- output->ticketLen = 0;
- }
- }
- else {
- output->ticket = output->staticTicket;
- output->ticketLenAlloc = 0;
- }
- }
- else {
- if (ticBuff != NULL)
- XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK);
- output->ticket = output->staticTicket;
- output->ticketLenAlloc = 0;
- }
- if (input->ticketLenAlloc > 0 && ret == WOLFSSL_SUCCESS) {
- /* Shouldn't happen as session should have placed this in
- * the static buffer */
- XMEMCPY(output->ticket, input->ticket,
- input->ticketLen);
- }
- }
- ticBuff = NULL;
- #endif /* HAVE_SESSION_TICKET */
- return ret;
- }
- WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session)
- {
- #ifdef HAVE_EXT_CACHE
- WOLFSSL_SESSION* copy;
- WOLFSSL_ENTER("wolfSSL_SESSION_dup");
- session = ClientSessionToSession(session);
- if (session == NULL)
- return NULL;
- #ifdef HAVE_SESSION_TICKET
- if (session->ticketLenAlloc > 0 && !session->ticket) {
- WOLFSSL_MSG("Session dynamic flag is set but ticket pointer is null");
- return NULL;
- }
- #endif
- copy = wolfSSL_NewSession(session->heap);
- if (copy != NULL &&
- wolfSSL_DupSession(session, copy, 0) != WOLFSSL_SUCCESS) {
- wolfSSL_FreeSession(NULL, copy);
- copy = NULL;
- }
- return copy;
- #else
- WOLFSSL_MSG("wolfSSL_SESSION_dup feature not compiled in");
- (void)session;
- return NULL;
- #endif /* HAVE_EXT_CACHE */
- }
- void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
- {
- session = ClientSessionToSession(session);
- if (session == NULL)
- return;
- (void)ctx;
- /* refCount will always be 1 or more if created externally.
- * Internal cache sessions don't initialize a refMutex. */
- if (session->refCount > 0) {
- #ifndef SINGLE_THREADED
- if (wc_LockMutex(&session->refMutex) != 0) {
- WOLFSSL_MSG("Failed to lock session mutex");
- return;
- }
- #endif
- if (session->refCount > 1) {
- session->refCount--;
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&session->refMutex);
- #endif
- return;
- }
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&session->refMutex);
- wc_FreeMutex(&session->refMutex);
- #endif
- }
- #if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
- if (ctx != NULL && ctx->rem_sess_cb
- #ifdef HAVE_EX_DATA
- && session->ownExData /* This will be true if we are not using the
- * internal cache so it will get called for
- * externally cached sessions as well. */
- #endif
- ) {
- ctx->rem_sess_cb(ctx, session);
- }
- #endif
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data);
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- if (session->peer) {
- wolfSSL_X509_free(session->peer);
- session->peer = NULL;
- }
- #endif
- #ifdef HAVE_SESSION_TICKET
- if (session->ticketLenAlloc > 0) {
- XFREE(session->ticket, session->heap, DYNAMIC_TYPE_SESSION_TICK);
- }
- #endif
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data);
- #endif
- /* Make sure masterSecret is zeroed. */
- ForceZero(session->masterSecret, SECRET_LEN);
- /* Session ID is sensitive information too. */
- ForceZero(session->sessionID, ID_LEN);
- if (session->type == WOLFSSL_SESSION_TYPE_HEAP) {
- XFREE(session, session->heap, DYNAMIC_TYPE_SESSION);
- }
- }
- void wolfSSL_SESSION_free(WOLFSSL_SESSION* session)
- {
- session = ClientSessionToSession(session);
- wolfSSL_FreeSession(NULL, session);
- }
- #ifndef NO_SESSION_CACHE
- int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
- {
- int error = 0;
- const byte* id = NULL;
- byte idSz = 0;
- WOLFSSL_ENTER("wolfSSL_CTX_add_session");
- session = ClientSessionToSession(session);
- if (session == NULL)
- return WOLFSSL_FAILURE;
- /* Session cache is global */
- (void)ctx;
- id = session->sessionID;
- idSz = session->sessionIDSz;
- if (session->haveAltSessionID) {
- id = session->altSessionID;
- idSz = ID_LEN;
- }
- error = AddSessionToCache(ctx, session, id, idSz,
- NULL, session->side,
- #ifdef HAVE_SESSION_TICKET
- session->ticketLen > 0,
- #else
- 0,
- #endif
- NULL);
- return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- #endif
- #if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
- /**
- * set cipher to WOLFSSL_SESSION from WOLFSSL_CIPHER
- * @param session a pointer to WOLFSSL_SESSION structure
- * @param cipher a function pointer to WOLFSSL_CIPHER
- * @return WOLFSSL_SUCCESS on success, otherwise WOLFSSL_FAILURE
- */
- int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session,
- const WOLFSSL_CIPHER* cipher)
- {
- WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher");
- session = ClientSessionToSession(session);
- /* sanity check */
- if (session == NULL || cipher == NULL) {
- WOLFSSL_MSG("bad argument");
- return WOLFSSL_FAILURE;
- }
- session->cipherSuite0 = cipher->cipherSuite0;
- session->cipherSuite = cipher->cipherSuite;
- WOLFSSL_LEAVE("wolfSSL_SESSION_set_cipher", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- #endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */
- /* helper function that takes in a protocol version struct and returns string */
- static const char* wolfSSL_internal_get_version(const ProtocolVersion* version)
- {
- WOLFSSL_ENTER("wolfSSL_get_version");
- if (version == NULL) {
- return "Bad arg";
- }
- if (version->major == SSLv3_MAJOR) {
- switch (version->minor) {
- case SSLv3_MINOR :
- return "SSLv3";
- case TLSv1_MINOR :
- return "TLSv1";
- case TLSv1_1_MINOR :
- return "TLSv1.1";
- case TLSv1_2_MINOR :
- return "TLSv1.2";
- case TLSv1_3_MINOR :
- return "TLSv1.3";
- default:
- return "unknown";
- }
- }
- #ifdef WOLFSSL_DTLS
- else if (version->major == DTLS_MAJOR) {
- switch (version->minor) {
- case DTLS_MINOR :
- return "DTLS";
- case DTLSv1_2_MINOR :
- return "DTLSv1.2";
- case DTLSv1_3_MINOR :
- return "DTLSv1.3";
- default:
- return "unknown";
- }
- }
- #endif /* WOLFSSL_DTLS */
- return "unknown";
- }
- const char* wolfSSL_get_version(const WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument");
- return "unknown";
- }
- return wolfSSL_internal_get_version(&ssl->version);
- }
- /* current library version */
- const char* wolfSSL_lib_version(void)
- {
- return LIBWOLFSSL_VERSION_STRING;
- }
- #ifdef OPENSSL_EXTRA
- #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
- const char* wolfSSL_OpenSSL_version(int a)
- {
- (void)a;
- return "wolfSSL " LIBWOLFSSL_VERSION_STRING;
- }
- #else
- const char* wolfSSL_OpenSSL_version(void)
- {
- return "wolfSSL " LIBWOLFSSL_VERSION_STRING;
- }
- #endif /* WOLFSSL_QT */
- #endif
- /* current library version in hex */
- word32 wolfSSL_lib_version_hex(void)
- {
- return LIBWOLFSSL_VERSION_HEX;
- }
- int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_get_current_cipher_suite");
- if (ssl)
- return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite;
- return 0;
- }
- WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_get_current_cipher");
- if (ssl) {
- ssl->cipher.cipherSuite0 = ssl->options.cipherSuite0;
- ssl->cipher.cipherSuite = ssl->options.cipherSuite;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- ssl->cipher.bits = ssl->specs.key_size * 8;
- #endif
- return &ssl->cipher;
- }
- else
- return NULL;
- }
- const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
- {
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_name");
- if (cipher == NULL) {
- return NULL;
- }
- #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \
- !defined(WOLFSSL_QT)
- return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite);
- #else
- return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0,
- cipher->cipherSuite);
- #endif
- }
- const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher)
- {
- WOLFSSL_ENTER("SSL_CIPHER_get_version");
- if (cipher == NULL || cipher->ssl == NULL) {
- return NULL;
- }
- return wolfSSL_get_version(cipher->ssl);
- }
- const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session)
- {
- session = ClientSessionToSession(session);
- if (session == NULL) {
- return NULL;
- }
- #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
- #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS)
- return GetCipherNameIana(session->cipherSuite0, session->cipherSuite);
- #else
- return GetCipherNameInternal(session->cipherSuite0, session->cipherSuite);
- #endif
- #else
- return NULL;
- #endif
- }
- const char* wolfSSL_get_cipher(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_cipher");
- return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
- }
- /* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */
- const char* wolfSSL_get_cipher_name(WOLFSSL* ssl)
- {
- /* get access to cipher_name_idx in internal.c */
- return wolfSSL_get_cipher_name_internal(ssl);
- }
- const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0,
- const byte cipherSuite)
- {
- return GetCipherNameInternal(cipherSuite0, cipherSuite);
- }
- const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0,
- const byte cipherSuite)
- {
- return GetCipherNameIana(cipherSuite0, cipherSuite);
- }
- int wolfSSL_get_cipher_suite_from_name(const char* name, byte* cipherSuite0,
- byte* cipherSuite, int *flags) {
- if ((name == NULL) ||
- (cipherSuite0 == NULL) ||
- (cipherSuite == NULL) ||
- (flags == NULL))
- return BAD_FUNC_ARG;
- return GetCipherSuiteFromName(name, cipherSuite0, cipherSuite, flags);
- }
- #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
- /* Creates and returns a new WOLFSSL_CIPHER stack. */
- WOLFSSL_STACK* wolfSSL_sk_new_cipher(void)
- {
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_cipher");
- sk = wolfSSL_sk_new_null();
- if (sk == NULL)
- return NULL;
- sk->type = STACK_TYPE_CIPHER;
- return sk;
- }
- /* return 1 on success 0 on fail */
- int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk,
- WOLFSSL_CIPHER* cipher)
- {
- return wolfSSL_sk_push(sk, cipher);
- }
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
- {
- WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop");
- (void)sk;
- return NULL;
- }
- #endif /* NO_WOLFSSL_STUB */
- #endif /* WOLFSSL_QT || OPENSSL_ALL */
- word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher)
- {
- word16 cipher_id = 0;
- WOLFSSL_ENTER("SSL_CIPHER_get_id");
- if (cipher && cipher->ssl) {
- cipher_id = (cipher->ssl->options.cipherSuite0 << 8) |
- cipher->ssl->options.cipherSuite;
- }
- return cipher_id;
- }
- const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value)
- {
- const WOLFSSL_CIPHER* cipher = NULL;
- byte cipherSuite0, cipherSuite;
- WOLFSSL_ENTER("SSL_get_cipher_by_value");
- /* extract cipher id information */
- cipherSuite = (value & 0xFF);
- cipherSuite0 = ((value >> 8) & 0xFF);
- /* TODO: lookup by cipherSuite0 / cipherSuite */
- (void)cipherSuite0;
- (void)cipherSuite;
- return cipher;
- }
- #if defined(OPENSSL_EXTRA)
- /* Free the structure for WOLFSSL_CIPHER stack
- *
- * sk stack to free nodes in
- */
- void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
- {
- WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free");
- wolfSSL_sk_free(sk);
- }
- #endif /* OPENSSL_ALL */
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \
- !defined(NO_DH)
- #ifdef HAVE_FFDHE
- static const char* wolfssl_ffdhe_name(word16 group)
- {
- const char* str = NULL;
- switch (group) {
- case WOLFSSL_FFDHE_2048:
- str = "FFDHE_2048";
- break;
- case WOLFSSL_FFDHE_3072:
- str = "FFDHE_3072";
- break;
- case WOLFSSL_FFDHE_4096:
- str = "FFDHE_4096";
- break;
- case WOLFSSL_FFDHE_6144:
- str = "FFDHE_6144";
- break;
- case WOLFSSL_FFDHE_8192:
- str = "FFDHE_8192";
- break;
- default:
- break;
- }
- return str;
- }
- #endif
- /* Return the name of the curve used for key exchange as a printable string.
- *
- * ssl The SSL/TLS object.
- * returns NULL if ECDH was not used, otherwise the name as a string.
- */
- const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
- {
- const char* cName = NULL;
- if (ssl == NULL)
- return NULL;
- #if defined(WOLFSSL_TLS13) && defined(HAVE_PQC)
- /* Check for post-quantum groups. Return now because we do not want the ECC
- * check to override this result in the case of a hybrid. */
- if (IsAtLeastTLSv1_3(ssl->version)) {
- switch (ssl->namedGroup) {
- #ifdef HAVE_LIBOQS
- case WOLFSSL_KYBER_LEVEL1:
- return "KYBER_LEVEL1";
- case WOLFSSL_KYBER_LEVEL3:
- return "KYBER_LEVEL3";
- case WOLFSSL_KYBER_LEVEL5:
- return "KYBER_LEVEL5";
- case WOLFSSL_NTRU_HPS_LEVEL1:
- return "NTRU_HPS_LEVEL1";
- case WOLFSSL_NTRU_HPS_LEVEL3:
- return "NTRU_HPS_LEVEL3";
- case WOLFSSL_NTRU_HPS_LEVEL5:
- return "NTRU_HPS_LEVEL5";
- case WOLFSSL_NTRU_HRSS_LEVEL3:
- return "NTRU_HRSS_LEVEL3";
- case WOLFSSL_SABER_LEVEL1:
- return "SABER_LEVEL1";
- case WOLFSSL_SABER_LEVEL3:
- return "SABER_LEVEL3";
- case WOLFSSL_SABER_LEVEL5:
- return "SABER_LEVEL5";
- case WOLFSSL_KYBER_90S_LEVEL1:
- return "KYBER_90S_LEVEL1";
- case WOLFSSL_KYBER_90S_LEVEL3:
- return "KYBER_90S_LEVEL3";
- case WOLFSSL_KYBER_90S_LEVEL5:
- return "KYBER_90S_LEVEL5";
- case WOLFSSL_P256_NTRU_HPS_LEVEL1:
- return "P256_NTRU_HPS_LEVEL1";
- case WOLFSSL_P384_NTRU_HPS_LEVEL3:
- return "P384_NTRU_HPS_LEVEL3";
- case WOLFSSL_P521_NTRU_HPS_LEVEL5:
- return "P521_NTRU_HPS_LEVEL5";
- case WOLFSSL_P384_NTRU_HRSS_LEVEL3:
- return "P384_NTRU_HRSS_LEVEL3";
- case WOLFSSL_P256_SABER_LEVEL1:
- return "P256_SABER_LEVEL1";
- case WOLFSSL_P384_SABER_LEVEL3:
- return "P384_SABER_LEVEL3";
- case WOLFSSL_P521_SABER_LEVEL5:
- return "P521_SABER_LEVEL5";
- case WOLFSSL_P256_KYBER_LEVEL1:
- return "P256_KYBER_LEVEL1";
- case WOLFSSL_P384_KYBER_LEVEL3:
- return "P384_KYBER_LEVEL3";
- case WOLFSSL_P521_KYBER_LEVEL5:
- return "P521_KYBER_LEVEL5";
- case WOLFSSL_P256_KYBER_90S_LEVEL1:
- return "P256_KYBER_90S_LEVEL1";
- case WOLFSSL_P384_KYBER_90S_LEVEL3:
- return "P384_KYBER_90S_LEVEL3";
- case WOLFSSL_P521_KYBER_90S_LEVEL5:
- return "P521_KYBER_90S_LEVEL5";
- #elif defined(HAVE_PQM4)
- case WOLFSSL_KYBER_LEVEL1:
- return "KYBER_LEVEL1";
- #endif
- }
- }
- #endif /* WOLFSSL_TLS13 && HAVE_PQC */
- #ifdef HAVE_FFDHE
- if (ssl->namedGroup != 0) {
- cName = wolfssl_ffdhe_name(ssl->namedGroup);
- }
- #endif
- #ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) {
- cName = "X25519";
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) {
- cName = "X448";
- }
- #endif
- #ifdef HAVE_ECC
- if (ssl->ecdhCurveOID != 0 && cName == NULL) {
- cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL,
- NULL));
- }
- #endif
- return cName;
- }
- #endif
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
- defined(OPENSSL_EXTRA_X509_SMALL)
- /* Creates a new WOLFSSL_ASN1_STRING structure.
- *
- * returns a pointer to the new structure created on success or NULL if fail
- */
- WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void)
- {
- WOLFSSL_ASN1_STRING* asn1;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new");
- #endif
- asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (asn1 != NULL) {
- XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING));
- }
- return asn1; /* no check for null because error case is returning null*/
- }
- /**
- * Used to duplicate a passed in WOLFSSL_ASN1_STRING*
- * @param asn1 WOLFSSL_ASN1_STRING* to be duplicated
- * @return WOLFSSL_ASN1_STRING* the duplicate struct or NULL on error
- */
- WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_dup(WOLFSSL_ASN1_STRING* asn1)
- {
- WOLFSSL_ASN1_STRING* dupl = NULL;
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_dup");
- if (!asn1) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
- dupl = wolfSSL_ASN1_STRING_new();
- if (!dupl) {
- WOLFSSL_MSG("wolfSSL_ASN1_STRING_new error");
- return NULL;
- }
- dupl->type = asn1->type;
- dupl->flags = asn1->flags;
- if (wolfSSL_ASN1_STRING_set(dupl, asn1->data, asn1->length)
- != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
- wolfSSL_ASN1_STRING_free(dupl);
- return NULL;
- }
- return dupl;
- }
- /* used to free a WOLFSSL_ASN1_STRING structure */
- void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free");
- #endif
- if (asn1 != NULL) {
- if (asn1->length > 0 && asn1->data != NULL && asn1->isDynamic) {
- XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- int wolfSSL_ASN1_STRING_cmp(const WOLFSSL_ASN1_STRING *a, const WOLFSSL_ASN1_STRING *b)
- {
- int i;
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_cmp");
- if (!a || !b) {
- return WOLFSSL_FATAL_ERROR;
- }
- if (a->length != b->length) {
- return a->length - b->length;
- }
- if ((i = XMEMCMP(a->data, b->data, a->length)) != 0) {
- return i;
- }
- return a->type - b->type;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
- defined(OPENSSL_EXTRA_X509_SMALL))
- int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dest,
- const WOLFSSL_ASN1_STRING* src)
- {
- if (src == NULL || dest == NULL) {
- return WOLFSSL_FAILURE;
- }
- dest->type = src->type;
- if(wolfSSL_ASN1_STRING_set(dest, src->data, src->length)
- != WOLFSSL_SUCCESS) {
- return WOLFSSL_FAILURE;
- }
- dest->flags = src->flags;
- return WOLFSSL_SUCCESS;
- }
- /* Creates a new WOLFSSL_ASN1_STRING structure given the input type.
- *
- * type is the type of set when WOLFSSL_ASN1_STRING is created
- *
- * returns a pointer to the new structure created on success or NULL if fail
- */
- WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type)
- {
- WOLFSSL_ASN1_STRING* asn1;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new");
- #endif
- asn1 = wolfSSL_ASN1_STRING_new();
- if (asn1 == NULL) {
- return NULL;
- }
- asn1->type = type;
- return asn1;
- }
- /******************************************************************************
- * wolfSSL_ASN1_STRING_type - returns the type of <asn1>
- *
- * RETURNS:
- * returns the type set for <asn1>. Otherwise, returns WOLFSSL_FAILURE.
- */
- int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type");
- #endif
- if (asn1 == NULL) {
- return WOLFSSL_FAILURE;
- }
- return asn1->type;
- }
- #endif /* !NO_CERTS && OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
- defined(OPENSSL_EXTRA_X509_SMALL)
- /* if dataSz is negative then use XSTRLEN to find length of data
- * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
- /* `data` can be NULL and only buffer will be allocated */
- int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data,
- int dataSz)
- {
- int sz;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set");
- #endif
- if (asn1 == NULL || (data == NULL && dataSz < 0)) {
- return WOLFSSL_FAILURE;
- }
- if (dataSz < 0) {
- sz = (int)XSTRLEN((const char*)data);
- }
- else {
- sz = dataSz;
- }
- if (sz < 0) {
- return WOLFSSL_FAILURE;
- }
- /* free any existing data before copying */
- if (asn1->data != NULL && asn1->isDynamic) {
- XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
- asn1->data = NULL;
- }
- if (sz + 1 > CTC_NAME_SIZE) { /* account for null char */
- /* create new data buffer and copy over */
- asn1->data = (char*)XMALLOC(sz + 1, NULL, DYNAMIC_TYPE_OPENSSL);
- if (asn1->data == NULL) {
- return WOLFSSL_FAILURE;
- }
- asn1->isDynamic = 1;
- }
- else {
- XMEMSET(asn1->strData, 0, CTC_NAME_SIZE);
- asn1->data = asn1->strData;
- asn1->isDynamic = 0;
- }
- if (data != NULL) {
- XMEMCPY(asn1->data, data, sz);
- asn1->data[sz] = '\0';
- }
- asn1->length = sz;
- return WOLFSSL_SUCCESS;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #ifndef NO_CERTS
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- const unsigned char* wolfSSL_ASN1_STRING_get0_data(
- const WOLFSSL_ASN1_STRING* asn)
- {
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_get0_data");
- if (asn) {
- return (const unsigned char*)asn->data;
- } else {
- return NULL;
- }
- }
- unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data");
- #endif
- if (asn) {
- return (unsigned char*)asn->data;
- }
- else {
- return NULL;
- }
- }
- int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length");
- #endif
- if (asn) {
- return asn->length;
- }
- else {
- return 0;
- }
- }
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- #ifdef OPENSSL_EXTRA
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn,
- const unsigned char **in, long len)
- {
- WOLFSSL_STUB("d2i_DISPLAYTEXT");
- (void)asn;
- (void)in;
- (void)len;
- return NULL;
- }
- #endif
- #endif /* OPENSSL_EXTRA */
- #endif /* !NO_CERTS */
- #ifdef OPENSSL_EXTRA
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- /* return authentication NID corresponding to cipher suite
- * @param cipher a pointer to WOLFSSL_CIPHER
- * return NID if found, NID_undef if not found
- */
- int wolfSSL_CIPHER_get_auth_nid(const WOLFSSL_CIPHER* cipher)
- {
- static const struct authnid {
- const char* alg_name;
- const int nid;
- } authnid_tbl[] = {
- {"RSA", NID_auth_rsa},
- {"PSK", NID_auth_psk},
- {"SRP", NID_auth_srp},
- {"ECDSA", NID_auth_ecdsa},
- {"None", NID_auth_null},
- {NULL, NID_undef}
- };
- const struct authnid* sa;
- const char* authStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
- authStr = GetCipherAuthStr(n);
- if (authStr != NULL) {
- for(sa = authnid_tbl; sa->alg_name != NULL; sa++) {
- if (XSTRCMP(sa->alg_name, authStr) == 0) {
- return sa->nid;
- }
- }
- }
- return NID_undef;
- }
- /* return cipher NID corresponding to cipher suite
- * @param cipher a pointer to WOLFSSL_CIPHER
- * return NID if found, NID_undef if not found
- */
- int wolfSSL_CIPHER_get_cipher_nid(const WOLFSSL_CIPHER* cipher)
- {
- static const struct ciphernid {
- const char* alg_name;
- const int nid;
- } ciphernid_tbl[] = {
- {"AESGCM(256)", NID_aes_256_gcm},
- {"AESGCM(128)", NID_aes_128_gcm},
- {"AESCCM(128)", NID_aes_128_ccm},
- {"AES(128)", NID_aes_128_cbc},
- {"AES(256)", NID_aes_256_cbc},
- {"CAMELLIA(256)", NID_camellia_256_cbc},
- {"CAMELLIA(128)", NID_camellia_128_cbc},
- {"RC4", NID_rc4},
- {"3DES", NID_des_ede3_cbc},
- {"CHACHA20/POLY1305(256)", NID_chacha20_poly1305},
- {"None", NID_undef},
- {NULL, NID_undef}
- };
- const struct ciphernid* c;
- const char* encStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_cipher_nid");
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
- encStr = GetCipherEncStr(n);
- if (encStr != NULL) {
- for(c = ciphernid_tbl; c->alg_name != NULL; c++) {
- if (XSTRCMP(c->alg_name, encStr) == 0) {
- return c->nid;
- }
- }
- }
- return NID_undef;
- }
- /* return digest NID corresponding to cipher suite
- * @param cipher a pointer to WOLFSSL_CIPHER
- * return NID if found, NID_undef if not found
- */
- int wolfSSL_CIPHER_get_digest_nid(const WOLFSSL_CIPHER* cipher)
- {
- static const struct macnid {
- const char* alg_name;
- const int nid;
- } macnid_tbl[] = {
- {"SHA1", NID_sha1},
- {"SHA256", NID_sha256},
- {"SHA384", NID_sha384},
- {NULL, NID_undef}
- };
- const struct macnid* mc;
- const char* name;
- const char* macStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- (void)name;
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_digest_nid");
- if ((name = GetCipherSegment(cipher, n)) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
- /* in MD5 case, NID will be NID_md5 */
- if (XSTRSTR(name, "MD5") != NULL) {
- return NID_md5;
- }
- macStr = GetCipherMacStr(n);
- if (macStr != NULL) {
- for(mc = macnid_tbl; mc->alg_name != NULL; mc++) {
- if (XSTRCMP(mc->alg_name, macStr) == 0) {
- return mc->nid;
- }
- }
- }
- return NID_undef;
- }
- /* return key exchange NID corresponding to cipher suite
- * @param cipher a pointer to WOLFSSL_CIPHER
- * return NID if found, NID_undef if not found
- */
- int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher)
- {
- static const struct kxnid {
- const char* name;
- const int nid;
- } kxnid_table[] = {
- {"ECDHEPSK", NID_kx_ecdhe_psk},
- {"ECDH", NID_kx_ecdhe},
- {"DHEPSK", NID_kx_dhe_psk},
- {"DH", NID_kx_dhe},
- {"RSAPSK", NID_kx_rsa_psk},
- {"SRP", NID_kx_srp},
- {"EDH", NID_kx_dhe},
- {"RSA", NID_kx_rsa},
- {NULL, NID_undef}
- };
- const struct kxnid* k;
- const char* keaStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_kx_nid");
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
- /* in TLS 1.3 case, NID will be NID_kx_any */
- if (XSTRCMP(n[0], "TLS13") == 0) {
- return NID_kx_any;
- }
- keaStr = GetCipherKeaStr(n);
- if (keaStr != NULL) {
- for(k = kxnid_table; k->name != NULL; k++) {
- if (XSTRCMP(k->name, keaStr) == 0) {
- return k->nid;
- }
- }
- }
- return NID_undef;
- }
- /* check if cipher suite is AEAD
- * @param cipher a pointer to WOLFSSL_CIPHER
- * return 1 if cipher is AEAD, 0 otherwise
- */
- int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher)
- {
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead");
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
- return IsCipherAEAD(n);
- }
- /* Creates cipher->description based on cipher->offset
- * cipher->offset is set in wolfSSL_get_ciphers_compat when it is added
- * to a stack of ciphers.
- * @param [in] cipher: A cipher from a stack of ciphers.
- * return WOLFSSL_SUCCESS if cipher->description is set, else WOLFSSL_FAILURE
- */
- int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher)
- {
- int strLen;
- unsigned long offset;
- char* dp;
- const char* name;
- const char *keaStr, *authStr, *encStr, *macStr, *protocol;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- int len = MAX_DESCRIPTION_SZ-1;
- const CipherSuiteInfo* cipher_names;
- ProtocolVersion pv;
- WOLFSSL_ENTER("wolfSSL_sk_CIPHER_description");
- if (cipher == NULL)
- return WOLFSSL_FAILURE;
- dp = cipher->description;
- if (dp == NULL)
- return WOLFSSL_FAILURE;
- cipher_names = GetCipherNames();
- offset = cipher->offset;
- if (offset >= (unsigned long)GetCipherNamesSize())
- return WOLFSSL_FAILURE;
- pv.major = cipher_names[offset].major;
- pv.minor = cipher_names[offset].minor;
- protocol = wolfSSL_internal_get_version(&pv);
- if ((name = GetCipherSegment(cipher, n)) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return WOLFSSL_FAILURE;
- }
- /* keaStr */
- keaStr = GetCipherKeaStr(n);
- /* authStr */
- authStr = GetCipherAuthStr(n);
- /* encStr */
- encStr = GetCipherEncStr(n);
- if ((cipher->bits = SetCipherBits(encStr)) == WOLFSSL_FAILURE) {
- WOLFSSL_MSG("Cipher Bits Not Set.");
- }
- /* macStr */
- macStr = GetCipherMacStr(n);
- /* Build up the string by copying onto the end. */
- XSTRNCPY(dp, name, len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, " ", len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, protocol, len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, " Kx=", len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, keaStr, len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, " Au=", len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, authStr, len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, " Enc=", len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, encStr, len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, " Mac=", len);
- dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
- len -= strLen; dp += strLen;
- XSTRNCPY(dp, macStr, len);
- dp[len-1] = '\0';
- return WOLFSSL_SUCCESS;
- }
- #endif /* OPENSSL_ALL || WOLFSSL_QT */
- static WC_INLINE const char* wolfssl_kea_to_string(int kea)
- {
- const char* keaStr;
- switch (kea) {
- case no_kea:
- keaStr = "None";
- break;
- #ifndef NO_RSA
- case rsa_kea:
- keaStr = "RSA";
- break;
- #endif
- #ifndef NO_DH
- case diffie_hellman_kea:
- keaStr = "DHE";
- break;
- #endif
- case fortezza_kea:
- keaStr = "FZ";
- break;
- #ifndef NO_PSK
- case psk_kea:
- keaStr = "PSK";
- break;
- #ifndef NO_DH
- case dhe_psk_kea:
- keaStr = "DHEPSK";
- break;
- #endif
- #ifdef HAVE_ECC
- case ecdhe_psk_kea:
- keaStr = "ECDHEPSK";
- break;
- #endif
- #endif
- #ifdef HAVE_ECC
- case ecc_diffie_hellman_kea:
- keaStr = "ECDHE";
- break;
- case ecc_static_diffie_hellman_kea:
- keaStr = "ECDH";
- break;
- #endif
- default:
- keaStr = "unknown";
- break;
- }
- return keaStr;
- }
- static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo)
- {
- const char* authStr;
- switch (sig_algo) {
- case anonymous_sa_algo:
- authStr = "None";
- break;
- #ifndef NO_RSA
- case rsa_sa_algo:
- authStr = "RSA";
- break;
- #ifdef WC_RSA_PSS
- case rsa_pss_sa_algo:
- authStr = "RSA-PSS";
- break;
- #endif
- #endif
- #ifndef NO_DSA
- case dsa_sa_algo:
- authStr = "DSA";
- break;
- #endif
- #ifdef HAVE_ECC
- case ecc_dsa_sa_algo:
- authStr = "ECDSA";
- break;
- #endif
- #ifdef HAVE_ED25519
- case ed25519_sa_algo:
- authStr = "Ed25519";
- break;
- #endif
- #ifdef HAVE_ED448
- case ed448_sa_algo:
- authStr = "Ed448";
- break;
- #endif
- default:
- authStr = "unknown";
- break;
- }
- return authStr;
- }
- static WC_INLINE const char* wolfssl_cipher_to_string(int cipher, int key_size)
- {
- const char* encStr;
- (void)key_size;
- switch (cipher) {
- case wolfssl_cipher_null:
- encStr = "None";
- break;
- #ifndef NO_RC4
- case wolfssl_rc4:
- encStr = "RC4(128)";
- break;
- #endif
- #ifndef NO_DES3
- case wolfssl_triple_des:
- encStr = "3DES(168)";
- break;
- #endif
- #ifndef NO_AES
- case wolfssl_aes:
- if (key_size == 128)
- encStr = "AES(128)";
- else if (key_size == 256)
- encStr = "AES(256)";
- else
- encStr = "AES(?)";
- break;
- #ifdef HAVE_AESGCM
- case wolfssl_aes_gcm:
- if (key_size == 128)
- encStr = "AESGCM(128)";
- else if (key_size == 256)
- encStr = "AESGCM(256)";
- else
- encStr = "AESGCM(?)";
- break;
- #endif
- #ifdef HAVE_AESCCM
- case wolfssl_aes_ccm:
- if (key_size == 128)
- encStr = "AESCCM(128)";
- else if (key_size == 256)
- encStr = "AESCCM(256)";
- else
- encStr = "AESCCM(?)";
- break;
- #endif
- #endif
- #ifdef HAVE_CHACHA
- case wolfssl_chacha:
- encStr = "CHACHA20/POLY1305(256)";
- break;
- #endif
- #ifdef HAVE_CAMELLIA
- case wolfssl_camellia:
- if (key_size == 128)
- encStr = "Camellia(128)";
- else if (key_size == 256)
- encStr = "Camellia(256)";
- else
- encStr = "Camellia(?)";
- break;
- #endif
- default:
- encStr = "unknown";
- break;
- }
- return encStr;
- }
- static WC_INLINE const char* wolfssl_mac_to_string(int mac)
- {
- const char* macStr;
- switch (mac) {
- case no_mac:
- macStr = "None";
- break;
- #ifndef NO_MD5
- case md5_mac:
- macStr = "MD5";
- break;
- #endif
- #ifndef NO_SHA
- case sha_mac:
- macStr = "SHA1";
- break;
- #endif
- #ifdef HAVE_SHA224
- case sha224_mac:
- macStr = "SHA224";
- break;
- #endif
- #ifndef NO_SHA256
- case sha256_mac:
- macStr = "SHA256";
- break;
- #endif
- #ifdef HAVE_SHA384
- case sha384_mac:
- macStr = "SHA384";
- break;
- #endif
- #ifdef HAVE_SHA512
- case sha512_mac:
- macStr = "SHA512";
- break;
- #endif
- default:
- macStr = "unknown";
- break;
- }
- return macStr;
- }
- char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in,
- int len)
- {
- char *ret = in;
- const char *keaStr, *authStr, *encStr, *macStr;
- size_t strLen;
- WOLFSSL_ENTER("wolfSSL_CIPHER_description");
- if (cipher == NULL || in == NULL)
- return NULL;
- #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
- /* if cipher is in the stack from wolfSSL_get_ciphers_compat then
- * Return the description based on cipher_names[cipher->offset]
- */
- if (cipher->in_stack == TRUE) {
- wolfSSL_sk_CIPHER_description((WOLFSSL_CIPHER*)cipher);
- XSTRNCPY(in,cipher->description,len);
- return ret;
- }
- #endif
- /* Get the cipher description based on the SSL session cipher */
- keaStr = wolfssl_kea_to_string(cipher->ssl->specs.kea);
- authStr = wolfssl_sigalg_to_string(cipher->ssl->specs.sig_algo);
- encStr = wolfssl_cipher_to_string(cipher->ssl->specs.bulk_cipher_algorithm,
- cipher->ssl->specs.key_size);
- macStr = wolfssl_mac_to_string(cipher->ssl->specs.mac_algorithm);
- /* Build up the string by copying onto the end. */
- XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, " ", len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, " Kx=", len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, keaStr, len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, " Au=", len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, authStr, len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, " Enc=", len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, encStr, len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, " Mac=", len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, macStr, len);
- in[len-1] = '\0';
- return ret;
- }
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path,
- int* ssl)
- {
- (void)url;
- (void)host;
- (void)port;
- (void)path;
- (void)ssl;
- WOLFSSL_STUB("OCSP_parse_url");
- return 0;
- }
- #endif
- #ifndef NO_MD4
- void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX* md4)
- {
- /* make sure we have a big enough buffer */
- typedef char ok[sizeof(md4->buffer) >= sizeof(Md4) ? 1 : -1];
- (void) sizeof(ok);
- WOLFSSL_ENTER("MD4_Init");
- wc_InitMd4((Md4*)md4);
- }
- void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX* md4, const void* data,
- unsigned long len)
- {
- WOLFSSL_ENTER("MD4_Update");
- wc_Md4Update((Md4*)md4, (const byte*)data, (word32)len);
- }
- void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4)
- {
- WOLFSSL_ENTER("MD4_Final");
- wc_Md4Final((Md4*)md4, digest);
- }
- #endif /* NO_MD4 */
- #ifndef NO_WOLFSSL_STUB
- void wolfSSL_RAND_screen(void)
- {
- WOLFSSL_STUB("RAND_screen");
- }
- #endif
- int wolfSSL_RAND_load_file(const char* fname, long len)
- {
- (void)fname;
- /* wolfCrypt provides enough entropy internally or will report error */
- if (len == -1)
- return 1024;
- else
- return (int)len;
- }
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void)
- {
- WOLFSSL_STUB("COMP_zlib");
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void)
- {
- WOLFSSL_STUB("COMP_rle");
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_COMP_add_compression_method(int method, void* data)
- {
- (void)method;
- (void)data;
- WOLFSSL_STUB("COMP_add_compression_method");
- return 0;
- }
- #endif
- /* wolfSSL_set_dynlock_create_callback
- * CRYPTO_set_dynlock_create_callback has been deprecated since openSSL 1.0.1.
- * This function exists for compatibility purposes because wolfSSL satisfies
- * thread safety without relying on the callback.
- */
- void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)(
- const char*, int))
- {
- WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback");
- (void)f;
- }
- /* wolfSSL_set_dynlock_lock_callback
- * CRYPTO_set_dynlock_lock_callback has been deprecated since openSSL 1.0.1.
- * This function exists for compatibility purposes because wolfSSL satisfies
- * thread safety without relying on the callback.
- */
- void wolfSSL_set_dynlock_lock_callback(
- void (*f)(int, WOLFSSL_dynlock_value*, const char*, int))
- {
- WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback");
- (void)f;
- }
- /* wolfSSL_set_dynlock_destroy_callback
- * CRYPTO_set_dynlock_destroy_callback has been deprecated since openSSL 1.0.1.
- * This function exists for compatibility purposes because wolfSSL satisfies
- * thread safety without relying on the callback.
- */
- void wolfSSL_set_dynlock_destroy_callback(
- void (*f)(WOLFSSL_dynlock_value*, const char*, int))
- {
- WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback");
- (void)f;
- }
- #endif /* OPENSSL_EXTRA */
- #ifdef OPENSSL_EXTRA
- #ifndef NO_CERTS
- #if !defined(NO_ASN) && !defined(NO_PWDBASED)
- /* Copies unencrypted DER key buffer into "der". If "der" is null then the size
- * of buffer needed is returned. If *der == NULL then it allocates a buffer.
- * NOTE: This also advances the "der" pointer to be at the end of buffer.
- *
- * Returns size of key buffer on success
- */
- int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der)
- {
- return wolfSSL_EVP_PKEY_get_der(key, der);
- }
- int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
- {
- return wolfSSL_EVP_PKEY_get_der(key, der);
- }
- #endif /* !NO_ASN && !NO_PWDBASED */
- #endif /* !NO_CERTS */
- #endif /* OPENSSL_EXTRA */
- #ifdef OPENSSL_EXTRA
- /******************************************************************************
- * wolfSSL_CTX_set1_param - set a pointer to the SSL verification parameters
- *
- * RETURNS:
- * WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
- * Note: Returns WOLFSSL_SUCCESS, in case either parameter is NULL,
- * same as openssl.
- */
- int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PARAM *vpm)
- {
- if (ctx == NULL || vpm == NULL)
- return WOLFSSL_SUCCESS;
- return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm);
- }
- /******************************************************************************
- * wolfSSL_CTX/_get0_param - return a pointer to the SSL verification parameters
- *
- * RETURNS:
- * returns pointer to the SSL verification parameters on success,
- * otherwise returns NULL
- */
- WOLFSSL_X509_VERIFY_PARAM* wolfSSL_CTX_get0_param(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL) {
- return NULL;
- }
- return ctx->param;
- }
- WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- return NULL;
- }
- return ssl->param;
- }
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA)
- int wolfSSL_i2d_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER* a, unsigned char** out)
- {
- int ret = 0;
- word32 idx = 0;
- int len;
- int preAlloc = 1;
- WOLFSSL_ENTER("wolfSSL_i2d_ASN1_INTEGER");
- if (a == NULL || a->data == NULL || a->length <= 0 || out == NULL) {
- WOLFSSL_MSG("Bad parameter.");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == 0 && *out == NULL) {
- preAlloc = 0;
- *out = (unsigned char*)XMALLOC(a->length, NULL, DYNAMIC_TYPE_ASN1);
- if (*out == NULL) {
- WOLFSSL_MSG("Failed to allocate output buffer.");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 0) {
- /*
- * A WOLFSSL_ASN1_INTEGER stores the DER buffer of the integer in its
- * "data" field, but it's only the magnitude of the number (i.e. the
- * sign isn't encoded). The "negative" field is 1 if the value should
- * be interpreted as negative and 0 otherwise. If the value is negative,
- * we need to output the 2's complement of the value in the DER output.
- */
- XMEMCPY(*out, a->data, a->length);
- if (a->negative) {
- if (GetLength(a->data, &idx, &len, a->length) < 0) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- ++idx;
- for (; (int)idx < a->length; ++idx) {
- (*out)[idx] = ~(*out)[idx];
- }
- do {
- --idx;
- ++(*out)[idx];
- } while ((*out)[idx] == 0);
- }
- }
- }
- if (ret == 0) {
- ret = a->length;
- if (preAlloc) {
- *out += a->length;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_i2d_ASN1_INTEGER", ret);
- return ret;
- }
- WOLFSSL_ASN1_INTEGER* wolfSSL_d2i_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER** a,
- const unsigned char** in,
- long inSz)
- {
- WOLFSSL_ASN1_INTEGER* ret = NULL;
- int err = 0;
- word32 idx = 0;
- int len;
- WOLFSSL_ENTER("wolfSSL_d2i_ASN1_INTEGER");
- if (in == NULL || *in == NULL || inSz <= 0) {
- WOLFSSL_MSG("Bad parameter");
- err = 1;
- }
- if (err == 0 && (*in)[0] != ASN_INTEGER) {
- WOLFSSL_MSG("Tag doesn't indicate integer type.");
- err = 1;
- }
- if (err == 0) {
- ret = wolfSSL_ASN1_INTEGER_new();
- if (ret == NULL) {
- err = 1;
- }
- else {
- ret->type = V_ASN1_INTEGER;
- }
- }
- if (err == 0 && inSz > (long)sizeof(ret->intData)) {
- ret->data = (unsigned char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_ASN1);
- if (ret->data == NULL) {
- err = 1;
- }
- else {
- ret->isDynamic = 1;
- ret->dataMax = (word32)inSz;
- }
- }
- if (err == 0) {
- XMEMCPY(ret->data, *in, inSz);
- ret->length = (word32)inSz;
- /* Advance to the end of the length field.*/
- if (GetLength(*in, &idx, &len, (word32)inSz) < 0) {
- err = 1;
- }
- else {
- /* See 2's complement comment in wolfSSL_d2i_ASN1_INTEGER. */
- ret->negative = (*in)[idx+1] & 0x80;
- if (ret->negative) {
- ++idx;
- for (; (int)idx < inSz; ++idx) {
- ret->data[idx] = ~ret->data[idx];
- }
- do {
- --idx;
- ++ret->data[idx];
- } while (ret->data[idx] == 0);
- ret->type |= V_ASN1_NEG_INTEGER;
- }
- if (a != NULL) {
- *a = ret;
- }
- }
- }
- if (err != 0) {
- wolfSSL_ASN1_INTEGER_free(ret);
- ret = NULL;
- }
- return ret;
- }
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- /* Used to create a new WOLFSSL_ASN1_INTEGER structure.
- * returns a pointer to new structure on success and NULL on failure
- */
- WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void)
- {
- WOLFSSL_ASN1_INTEGER* a;
- a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (a == NULL) {
- return NULL;
- }
- XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER));
- a->data = a->intData;
- a->isDynamic = 0;
- a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
- a->length = 0;
- return a;
- }
- /* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */
- void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in)
- {
- if (in != NULL) {
- if (in->isDynamic) {
- XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- /* Duplicate all WOLFSSL_ASN1_INTEGER members from src to dup
- * src : WOLFSSL_ASN1_INTEGER to duplicate
- * Returns pointer to duplicate WOLFSSL_ASN1_INTEGER
- */
- WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(const WOLFSSL_ASN1_INTEGER* src)
- {
- WOLFSSL_ASN1_INTEGER* copy;
- WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_dup");
- if (!src)
- return NULL;
- copy = wolfSSL_ASN1_INTEGER_new();
- if (copy == NULL)
- return NULL;
- copy->negative = src->negative;
- copy->dataMax = src->dataMax;
- copy->isDynamic = src->isDynamic;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- copy->length = src->length;
- #endif
- XSTRNCPY((char*)copy->intData,(const char*)src->intData,WOLFSSL_ASN1_INTEGER_MAX);
- if (copy->isDynamic && src->data && copy->dataMax) {
- copy->data = (unsigned char*)
- XMALLOC(src->dataMax,NULL,DYNAMIC_TYPE_OPENSSL);
- if (copy->data == NULL) {
- wolfSSL_ASN1_INTEGER_free(copy);
- return NULL;
- }
- XMEMCPY(copy->data, src->data, copy->dataMax);
- }
- return copy;
- }
- /* sets the value of WOLFSSL_ASN1_INTEGER a to the long value v. */
- int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v)
- {
- int ret = WOLFSSL_SUCCESS; /* return 1 for success and 0 for failure */
- int j;
- unsigned int i = 0;
- unsigned char tmp[sizeof(long)+1] = {0};
- int pad = 0;
- if (a != NULL) {
- /* dynamically create data buffer, +2 for type and length */
- a->data = (unsigned char*)XMALLOC((sizeof(long)+1) + 2, NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (a->data == NULL) {
- wolfSSL_ASN1_INTEGER_free(a);
- ret = WOLFSSL_FAILURE;
- }
- else {
- a->dataMax = (int)(sizeof(long)+1) + 2;
- a->isDynamic = 1;
- }
- }
- else {
- /* Invalid parameter */
- ret = WOLFSSL_FAILURE;
- }
- if (ret != WOLFSSL_FAILURE) {
- /* Set type */
- a->data[i++] = ASN_INTEGER;
- /* Check for negative */
- if (v < 0) {
- a->negative = 1;
- v *= -1;
- }
- /* Create char buffer */
- for (j = 0; j < (int)sizeof(long); j++) {
- if (v == 0) {
- break;
- }
- tmp[j] = (unsigned char)(v & 0xff);
- v >>= 8;
- }
- /* 0 pad to indicate positive number when top bit set. */
- if ((!a->negative) && (j > 0) && (tmp[j-1] & 0x80)) {
- pad = 1;
- }
- /* Set length */
- a->data[i++] = (unsigned char)(((j == 0) ? ++j : j) + pad);
- /* +2 for type and length */
- a->length = j + pad + 2;
- /* Add padding if required. */
- if (pad) {
- a->data[i++] = 0;
- }
- /* Copy to data */
- for (; j > 0; j--) {
- a->data[i++] = tmp[j-1];
- }
- }
- return ret;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \
- defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
- #ifndef NO_ASN_TIME
- #ifndef NO_BIO
- int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime)
- {
- char buf[MAX_TIME_STRING_SZ];
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print");
- if (bio == NULL || asnTime == NULL) {
- WOLFSSL_MSG("NULL function argument");
- return WOLFSSL_FAILURE;
- }
- if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf,
- sizeof(buf)) == NULL) {
- XMEMSET(buf, 0, MAX_TIME_STRING_SZ);
- XSTRNCPY(buf, "Bad time value", sizeof(buf)-1);
- ret = WOLFSSL_FAILURE;
- }
- if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) {
- WOLFSSL_MSG("Unable to write to bio");
- return WOLFSSL_FAILURE;
- }
- return ret;
- }
- #endif /* !NO_BIO */
- char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
- {
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string");
- if (t == NULL || buf == NULL || len < 5) {
- WOLFSSL_MSG("Bad argument");
- return NULL;
- }
- if (t->length > len) {
- WOLFSSL_MSG("Length of date is longer then buffer");
- return NULL;
- }
- if (!GetTimeString(t->data, t->type, buf, len)) {
- return NULL;
- }
- return buf;
- }
- /* Converts a WOLFSSL_ASN1_TIME to a struct tm. Returns WOLFSSL_SUCCESS on
- * success and WOLFSSL_FAILURE on failure. */
- static int Asn1TimeToTm(WOLFSSL_ASN1_TIME* asnTime, struct tm* tm)
- {
- unsigned char* asn1TimeBuf;
- int asn1TimeBufLen;
- int i = 0;
- int bytesNeeded = 11;
- if (asnTime == NULL) {
- WOLFSSL_MSG("asnTime is NULL");
- return WOLFSSL_FAILURE;
- }
- if (tm == NULL) {
- WOLFSSL_MSG("tm is NULL");
- return WOLFSSL_FAILURE;
- }
- asn1TimeBuf = wolfSSL_ASN1_TIME_get_data(asnTime);
- if (asn1TimeBuf == NULL) {
- WOLFSSL_MSG("Failed to get WOLFSSL_ASN1_TIME buffer.");
- return WOLFSSL_FAILURE;
- }
- asn1TimeBufLen = wolfSSL_ASN1_TIME_get_length(asnTime);
- if (asn1TimeBufLen <= 0) {
- WOLFSSL_MSG("Failed to get WOLFSSL_ASN1_TIME buffer length.");
- return WOLFSSL_FAILURE;
- }
- XMEMSET(tm, 0, sizeof(struct tm));
- /* Convert ASN1_time to struct tm */
- /* Check type */
- if (asnTime->type == ASN_UTC_TIME) {
- /* 2-digit year */
- bytesNeeded += 2;
- if (bytesNeeded > asn1TimeBufLen) {
- WOLFSSL_MSG("WOLFSSL_ASN1_TIME buffer length is invalid.");
- return WOLFSSL_FAILURE;
- }
- if (asn1TimeBuf[bytesNeeded-1] != 'Z') {
- WOLFSSL_MSG("Expecting UTC time.");
- return WOLFSSL_FAILURE;
- }
- tm->tm_year = (asn1TimeBuf[i] - '0') * 10; i++;
- tm->tm_year += asn1TimeBuf[i] - '0'; i++;
- if (tm->tm_year < 70) {
- tm->tm_year += 100;
- }
- }
- else if (asnTime->type == ASN_GENERALIZED_TIME) {
- /* 4-digit year */
- bytesNeeded += 4;
- if (bytesNeeded > asn1TimeBufLen) {
- WOLFSSL_MSG("WOLFSSL_ASN1_TIME buffer length is invalid.");
- return WOLFSSL_FAILURE;
- }
- if (asn1TimeBuf[bytesNeeded-1] != 'Z') {
- WOLFSSL_MSG("Expecting UTC time.");
- return WOLFSSL_FAILURE;
- }
- tm->tm_year = (asn1TimeBuf[i] - '0') * 1000; i++;
- tm->tm_year += (asn1TimeBuf[i] - '0') * 100; i++;
- tm->tm_year += (asn1TimeBuf[i] - '0') * 10; i++;
- tm->tm_year += asn1TimeBuf[i] - '0'; i++;
- tm->tm_year -= 1900;
- }
- else {
- WOLFSSL_MSG("asnTime->type is invalid.");
- return WOLFSSL_FAILURE;
- }
- tm->tm_mon = (asn1TimeBuf[i] - '0') * 10; i++;
- tm->tm_mon += (asn1TimeBuf[i] - '0') - 1; i++; /* January is 0 not 1 */
- tm->tm_mday = (asn1TimeBuf[i] - '0') * 10; i++;
- tm->tm_mday += (asn1TimeBuf[i] - '0'); i++;
- tm->tm_hour = (asn1TimeBuf[i] - '0') * 10; i++;
- tm->tm_hour += (asn1TimeBuf[i] - '0'); i++;
- tm->tm_min = (asn1TimeBuf[i] - '0') * 10; i++;
- tm->tm_min += (asn1TimeBuf[i] - '0'); i++;
- tm->tm_sec = (asn1TimeBuf[i] - '0') * 10; i++;
- tm->tm_sec += (asn1TimeBuf[i] - '0');
- #ifdef XMKTIME
- /* Call XMKTIME on tm to get the tm_wday and tm_yday fields populated. */
- XMKTIME(tm);
- #endif
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_ASN1_TIME_to_tm(const WOLFSSL_ASN1_TIME* asnTime, struct tm* tm)
- {
- time_t currentTime;
- struct tm *tmpTs;
- #if defined(NEED_TMP_TIME)
- /* for use with gmtime_r */
- struct tm tmpTimeStorage;
- tmpTs = &tmpTimeStorage;
- #else
- tmpTs = NULL;
- #endif
- (void)tmpTs;
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_tm");
- /* If asnTime is NULL, then the current time is converted. */
- if (asnTime == NULL) {
- if (tm == NULL) {
- WOLFSSL_MSG("asnTime and tm are both NULL");
- return WOLFSSL_FAILURE;
- }
- currentTime = wc_Time(0);
- if (currentTime <= 0) {
- WOLFSSL_MSG("Failed to get current time.");
- return WOLFSSL_FAILURE;
- }
- tm = XGMTIME(¤tTime, tmpTs);
- if (tm == NULL) {
- WOLFSSL_MSG("Failed to convert current time to UTC.");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- /* If tm is NULL this function performs a format check on asnTime only. */
- if (tm == NULL) {
- return wolfSSL_ASN1_TIME_check(asnTime);
- }
- return Asn1TimeToTm((WOLFSSL_ASN1_TIME*)asnTime, tm);
- }
- #endif /* !NO_ASN_TIME */
- #endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
- OPENSSL_EXTRA*/
- #ifdef OPENSSL_EXTRA
- int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a,
- const WOLFSSL_ASN1_INTEGER* b)
- {
- int ret = 0;
- WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_cmp");
- if (a == NULL || b == NULL) {
- WOLFSSL_MSG("Bad parameter.");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == 0 && ((a->length != b->length) ||
- ((a->negative == 0) != (b->negative == 0)))) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == 0) {
- ret = XMEMCMP(a->data, b->data, a->length);
- }
- WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_cmp", ret);
- return ret;
- }
- long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* a)
- {
- long ret = 1;
- WOLFSSL_BIGNUM* bn = NULL;
- WOLFSSL_ENTER("ASN1_INTEGER_get");
- if (a == NULL) {
- /* OpenSSL returns 0 when a is NULL and -1 if there is an error. Quoting
- * the documentation:
- *
- * "ASN1_INTEGER_get() also returns the value of a but it returns 0 if a
- * is NULL and -1 on error (which is ambiguous because -1 is a
- * legitimate value for an ASN1_INTEGER). New applications should use
- * ASN1_INTEGER_get_int64() instead."
- * */
- ret = 0;
- }
- if (ret > 0) {
- bn = wolfSSL_ASN1_INTEGER_to_BN(a, NULL);
- if (bn == NULL) {
- ret = -1;
- }
- }
- if (ret > 0) {
- ret = wolfSSL_BN_get_word(bn);
- if (a->negative == 1) {
- ret = -ret;
- }
- }
- if (bn != NULL) {
- wolfSSL_BN_free(bn);
- }
- WOLFSSL_LEAVE("ASN1_INTEGER_get", (int)ret);
- return ret;
- }
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- /* Gets an index to store SSL structure at.
- *
- * Returns positive index on success and negative values on failure
- */
- int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void)
- {
- WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx");
- /* store SSL at index 0 */
- return 0;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #ifdef OPENSSL_EXTRA
- /* Sets a function callback that will send information about the state of all
- * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed
- * in.
- *
- * ctx WOLFSSL_CTX structure to set callback function in
- * f callback function to use
- */
- void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx,
- void (*f)(const WOLFSSL* ssl, int type, int val))
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback");
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad function argument");
- }
- else {
- ctx->CBIS = f;
- }
- }
- unsigned long wolfSSL_ERR_peek_error(void)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_peek_error");
- return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL);
- }
- int wolfSSL_ERR_GET_LIB(unsigned long err)
- {
- unsigned long value;
- value = (err & 0xFFFFFFL);
- switch (value) {
- case -SSL_R_HTTP_REQUEST:
- return ERR_LIB_SSL;
- case PEM_R_NO_START_LINE:
- case PEM_R_PROBLEMS_GETTING_PASSWORD:
- case PEM_R_BAD_PASSWORD_READ:
- case PEM_R_BAD_DECRYPT:
- return ERR_LIB_PEM;
- case EVP_R_BAD_DECRYPT:
- case EVP_R_BN_DECODE_ERROR:
- case EVP_R_DECODE_ERROR:
- case EVP_R_PRIVATE_KEY_DECODE_ERROR:
- return ERR_LIB_EVP;
- case ASN1_R_HEADER_TOO_LONG:
- return ERR_LIB_ASN1;
- default:
- return 0;
- }
- }
- /* This function is to find global error values that are the same through out
- * all library version. With wolfSSL having only one set of error codes the
- * return value is pretty straight forward. The only thing needed is all wolfSSL
- * error values are typically negative.
- *
- * Returns the error reason
- */
- int wolfSSL_ERR_GET_REASON(unsigned long err)
- {
- int ret = (int)err;
- WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON");
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- /* Nginx looks for this error to know to stop parsing certificates. */
- if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE))
- return PEM_R_NO_START_LINE;
- if (err == ((ERR_LIB_SSL << 24) | -SSL_R_HTTP_REQUEST))
- return SSL_R_HTTP_REQUEST;
- #endif
- #if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON)
- if (err == ((ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG))
- return ASN1_R_HEADER_TOO_LONG;
- #endif
- /* check if error value is in range of wolfSSL errors */
- ret = 0 - ret; /* setting as negative value */
- /* wolfCrypt range is less than MAX (-100)
- wolfSSL range is MIN (-300) and lower */
- if (ret < MAX_CODE_E && ret > MIN_CODE_E) {
- return ret;
- }
- else {
- WOLFSSL_MSG("Not in range of typical error values");
- ret = (int)err;
- }
- return ret;
- }
- /* returns a string that describes the alert
- *
- * alertID the alert value to look up
- */
- const char* wolfSSL_alert_type_string_long(int alertID)
- {
- WOLFSSL_ENTER("wolfSSL_alert_type_string_long");
- return AlertTypeToString(alertID);
- }
- const char* wolfSSL_alert_desc_string_long(int alertID)
- {
- WOLFSSL_ENTER("wolfSSL_alert_desc_string_long");
- return AlertTypeToString(alertID);
- }
- #define STATE_STRINGS_PROTO(s) \
- { \
- {"SSLv3 " s, \
- "SSLv3 " s, \
- "SSLv3 " s}, \
- {"TLSv1 " s, \
- "TLSv1 " s, \
- "TLSv1 " s}, \
- {"TLSv1_1 " s, \
- "TLSv1_1 " s, \
- "TLSv1_1 " s}, \
- {"TLSv1_2 " s, \
- "TLSv1_2 " s, \
- "TLSv1_2 " s}, \
- {"TLSv1_3 " s, \
- "TLSv1_3 " s, \
- "TLSv1_3 " s}, \
- {"DTLSv1 " s, \
- "DTLSv1 " s, \
- "DTLSv1 " s}, \
- {"DTLSv1_2 " s, \
- "DTLSv1_2 " s, \
- "DTLSv1_2 " s}, \
- {"DTLSv1_3 " s, \
- "DTLSv1_3 " s, \
- "DTLSv1_3 " s}, \
- }
- #define STATE_STRINGS_PROTO_RW(s) \
- { \
- {"SSLv3 read " s, \
- "SSLv3 write " s, \
- "SSLv3 " s}, \
- {"TLSv1 read " s, \
- "TLSv1 write " s, \
- "TLSv1 " s}, \
- {"TLSv1_1 read " s, \
- "TLSv1_1 write " s, \
- "TLSv1_1 " s}, \
- {"TLSv1_2 read " s, \
- "TLSv1_2 write " s, \
- "TLSv1_2 " s}, \
- {"TLSv1_3 read " s, \
- "TLSv1_3 write " s, \
- "TLSv1_3 " s}, \
- {"DTLSv1 read " s, \
- "DTLSv1 write " s, \
- "DTLSv1 " s}, \
- {"DTLSv1_2 read " s, \
- "DTLSv1_2 write " s, \
- "DTLSv1_2 " s}, \
- {"DTLSv1_3 read " s, \
- "DTLSv1_3 write " s, \
- "DTLSv1_3 " s}, \
- }
- /* Gets the current state of the WOLFSSL structure
- *
- * ssl WOLFSSL structure to get state of
- *
- * Returns a human readable string of the WOLFSSL structure state
- */
- const char* wolfSSL_state_string_long(const WOLFSSL* ssl)
- {
- static const char* OUTPUT_STR[24][8][3] = {
- STATE_STRINGS_PROTO("Initialization"),
- STATE_STRINGS_PROTO_RW("Server Hello Request"),
- STATE_STRINGS_PROTO_RW("Server Hello Verify Request"),
- STATE_STRINGS_PROTO_RW("Server Hello Retry Request"),
- STATE_STRINGS_PROTO_RW("Server Hello"),
- STATE_STRINGS_PROTO_RW("Server Certificate Status"),
- STATE_STRINGS_PROTO_RW("Server Encrypted Extensions"),
- STATE_STRINGS_PROTO_RW("Server Session Ticket"),
- STATE_STRINGS_PROTO_RW("Server Certificate Request"),
- STATE_STRINGS_PROTO_RW("Server Cert"),
- STATE_STRINGS_PROTO_RW("Server Key Exchange"),
- STATE_STRINGS_PROTO_RW("Server Hello Done"),
- STATE_STRINGS_PROTO_RW("Server Change CipherSpec"),
- STATE_STRINGS_PROTO_RW("Server Finished"),
- STATE_STRINGS_PROTO_RW("server Key Update"),
- STATE_STRINGS_PROTO_RW("Client Hello"),
- STATE_STRINGS_PROTO_RW("Client Key Exchange"),
- STATE_STRINGS_PROTO_RW("Client Cert"),
- STATE_STRINGS_PROTO_RW("Client Change CipherSpec"),
- STATE_STRINGS_PROTO_RW("Client Certificate Verify"),
- STATE_STRINGS_PROTO_RW("Client End Of Early Data"),
- STATE_STRINGS_PROTO_RW("Client Finished"),
- STATE_STRINGS_PROTO_RW("Client Key Update"),
- STATE_STRINGS_PROTO("Handshake Done"),
- };
- enum ProtocolVer {
- SSL_V3 = 0,
- TLS_V1,
- TLS_V1_1,
- TLS_V1_2,
- TLS_V1_3,
- DTLS_V1,
- DTLS_V1_2,
- DTLS_V1_3,
- UNKNOWN = 100
- };
- enum IOMode {
- SS_READ = 0,
- SS_WRITE,
- SS_NEITHER
- };
- enum SslState {
- ss_null_state = 0,
- ss_server_hellorequest,
- ss_server_helloverify,
- ss_server_helloretryrequest,
- ss_server_hello,
- ss_server_certificatestatus,
- ss_server_encryptedextensions,
- ss_server_sessionticket,
- ss_server_certrequest,
- ss_server_cert,
- ss_server_keyexchange,
- ss_server_hellodone,
- ss_server_changecipherspec,
- ss_server_finished,
- ss_server_keyupdate,
- ss_client_hello,
- ss_client_keyexchange,
- ss_client_cert,
- ss_client_changecipherspec,
- ss_client_certverify,
- ss_client_endofearlydata,
- ss_client_finished,
- ss_client_keyupdate,
- ss_handshake_done
- };
- int protocol = 0;
- int cbmode = 0;
- int state = 0;
- WOLFSSL_ENTER("wolfSSL_state_string_long");
- if (ssl == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- return NULL;
- }
- /* Get state of callback */
- if (ssl->cbmode == SSL_CB_MODE_WRITE) {
- cbmode = SS_WRITE;
- }
- else if (ssl->cbmode == SSL_CB_MODE_READ) {
- cbmode = SS_READ;
- }
- else {
- cbmode = SS_NEITHER;
- }
- /* Get protocol version */
- switch (ssl->version.major) {
- case SSLv3_MAJOR:
- switch (ssl->version.minor) {
- case SSLv3_MINOR:
- protocol = SSL_V3;
- break;
- case TLSv1_MINOR:
- protocol = TLS_V1;
- break;
- case TLSv1_1_MINOR:
- protocol = TLS_V1_1;
- break;
- case TLSv1_2_MINOR:
- protocol = TLS_V1_2;
- break;
- case TLSv1_3_MINOR:
- protocol = TLS_V1_3;
- break;
- default:
- protocol = UNKNOWN;
- }
- break;
- case DTLS_MAJOR:
- switch (ssl->version.minor) {
- case DTLS_MINOR:
- protocol = DTLS_V1;
- break;
- case DTLSv1_2_MINOR:
- protocol = DTLS_V1_2;
- break;
- case DTLSv1_3_MINOR:
- protocol = DTLS_V1_3;
- break;
- default:
- protocol = UNKNOWN;
- }
- break;
- default:
- protocol = UNKNOWN;
- }
- /* accept process */
- if (ssl->cbmode == SSL_CB_MODE_READ) {
- state = ssl->cbtype;
- switch (state) {
- case hello_request:
- state = ss_server_hellorequest;
- break;
- case client_hello:
- state = ss_client_hello;
- break;
- case server_hello:
- state = ss_server_hello;
- break;
- case hello_verify_request:
- state = ss_server_helloverify;
- break;
- case session_ticket:
- state = ss_server_sessionticket;
- break;
- case end_of_early_data:
- state = ss_client_endofearlydata;
- break;
- case hello_retry_request:
- state = ss_server_helloretryrequest;
- break;
- case encrypted_extensions:
- state = ss_server_encryptedextensions;
- break;
- case certificate:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_cert;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_cert;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- case server_key_exchange:
- state = ss_server_keyexchange;
- break;
- case certificate_request:
- state = ss_server_certrequest;
- break;
- case server_hello_done:
- state = ss_server_hellodone;
- break;
- case certificate_verify:
- state = ss_client_certverify;
- break;
- case client_key_exchange:
- state = ss_client_keyexchange;
- break;
- case finished:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_finished;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_finished;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- case certificate_status:
- state = ss_server_certificatestatus;
- break;
- case key_update:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_keyupdate;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_keyupdate;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- case change_cipher_hs:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_changecipherspec;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_changecipherspec;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- default:
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- }
- else {
- /* Send process */
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ssl->options.serverState;
- else
- state = ssl->options.clientState;
- switch (state) {
- case SERVER_HELLOVERIFYREQUEST_COMPLETE:
- state = ss_server_helloverify;
- break;
- case SERVER_HELLO_RETRY_REQUEST_COMPLETE:
- state = ss_server_helloretryrequest;
- break;
- case SERVER_HELLO_COMPLETE:
- state = ss_server_hello;
- break;
- case SERVER_ENCRYPTED_EXTENSIONS_COMPLETE:
- state = ss_server_encryptedextensions;
- break;
- case SERVER_CERT_COMPLETE:
- state = ss_server_cert;
- break;
- case SERVER_KEYEXCHANGE_COMPLETE:
- state = ss_server_keyexchange;
- break;
- case SERVER_HELLODONE_COMPLETE:
- state = ss_server_hellodone;
- break;
- case SERVER_CHANGECIPHERSPEC_COMPLETE:
- state = ss_server_changecipherspec;
- break;
- case SERVER_FINISHED_COMPLETE:
- state = ss_server_finished;
- break;
- case CLIENT_HELLO_RETRY:
- case CLIENT_HELLO_COMPLETE:
- state = ss_client_hello;
- break;
- case CLIENT_KEYEXCHANGE_COMPLETE:
- state = ss_client_keyexchange;
- break;
- case CLIENT_CHANGECIPHERSPEC_COMPLETE:
- state = ss_client_changecipherspec;
- break;
- case CLIENT_FINISHED_COMPLETE:
- state = ss_client_finished;
- break;
- case HANDSHAKE_DONE:
- state = ss_handshake_done;
- break;
- default:
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- }
- if (protocol == UNKNOWN) {
- WOLFSSL_MSG("Unknown protocol");
- return "";
- }
- else {
- return OUTPUT_STR[state][protocol][cbmode];
- }
- }
- /*
- * Sets default PEM callback password if null is passed into
- * the callback parameter of a PEM_read_bio_* function.
- *
- * Returns callback phrase size on success or WOLFSSL_FAILURE otherwise.
- */
- int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key)
- {
- int sz;
- (void)w;
- WOLFSSL_ENTER("wolfSSL_PEM_def_callback");
- /* We assume that the user passes a default password as userdata */
- if (key) {
- sz = (int)XSTRLEN((const char*)key);
- sz = (sz > num) ? num : sz;
- XMEMCPY(name, key, sz);
- return sz;
- } else {
- WOLFSSL_MSG("Error, default password cannot be created.");
- return WOLFSSL_FAILURE;
- }
- }
- #endif /* OPENSSL_EXTRA */
- static long wolf_set_options(long old_op, long op)
- {
- /* if SSL_OP_ALL then turn all bug workarounds on */
- if ((op & WOLFSSL_OP_ALL) == WOLFSSL_OP_ALL) {
- WOLFSSL_MSG("\tSSL_OP_ALL");
- }
- /* by default cookie exchange is on with DTLS */
- if ((op & WOLFSSL_OP_COOKIE_EXCHANGE) == WOLFSSL_OP_COOKIE_EXCHANGE) {
- WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default");
- }
- if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) {
- WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2");
- }
- #ifdef SSL_OP_NO_TLSv1_3
- if ((op & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) {
- WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3");
- }
- #endif
- if ((op & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) {
- WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2");
- }
- if ((op & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) {
- WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1");
- }
- if ((op & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) {
- WOLFSSL_MSG("\tSSL_OP_NO_TLSv1");
- }
- if ((op & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) {
- WOLFSSL_MSG("\tSSL_OP_NO_SSLv3");
- }
- if ((op & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) ==
- WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) {
- WOLFSSL_MSG("\tWOLFSSL_OP_CIPHER_SERVER_PREFERENCE");
- }
- if ((op & WOLFSSL_OP_NO_COMPRESSION) == WOLFSSL_OP_NO_COMPRESSION) {
- #ifdef HAVE_LIBZ
- WOLFSSL_MSG("SSL_OP_NO_COMPRESSION");
- #else
- WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in");
- #endif
- }
- return old_op | op;
- }
- long wolfSSL_set_options(WOLFSSL* ssl, long op)
- {
- word16 haveRSA = 1;
- word16 havePSK = 0;
- int keySz = 0;
- WOLFSSL_ENTER("wolfSSL_set_options");
- if (ssl == NULL) {
- return 0;
- }
- ssl->options.mask = wolf_set_options(ssl->options.mask, op);
- if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) {
- if (ssl->version.minor == TLSv1_3_MINOR)
- ssl->version.minor = TLSv1_2_MINOR;
- }
- if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) {
- if (ssl->version.minor == TLSv1_2_MINOR)
- ssl->version.minor = TLSv1_1_MINOR;
- }
- if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) {
- if (ssl->version.minor == TLSv1_1_MINOR)
- ssl->version.minor = TLSv1_MINOR;
- }
- if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) {
- if (ssl->version.minor == TLSv1_MINOR)
- ssl->version.minor = SSLv3_MINOR;
- }
- if ((ssl->options.mask & WOLFSSL_OP_NO_COMPRESSION)
- == WOLFSSL_OP_NO_COMPRESSION) {
- #ifdef HAVE_LIBZ
- ssl->options.usingCompression = 0;
- #endif
- }
- /* in the case of a version change the cipher suites should be reset */
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #endif
- #ifdef NO_RSA
- haveRSA = 0;
- #endif
- #ifndef NO_CERTS
- keySz = ssl->buffers.keySz;
- #endif
- if (ssl->suites != NULL && ssl->options.side != WOLFSSL_NEITHER_END)
- InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
- ssl->options.haveDH, ssl->options.haveECDSAsig,
- ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
- ssl->options.haveFalconSig, ssl->options.haveDilithiumSig,
- ssl->options.haveAnon, TRUE, ssl->options.side);
- return ssl->options.mask;
- }
- long wolfSSL_get_options(const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_options");
- if(ssl == NULL)
- return WOLFSSL_FAILURE;
- return ssl->options.mask;
- }
- #if defined(HAVE_SECURE_RENEGOTIATION) \
- || defined(HAVE_SERVER_RENEGOTIATION_INFO)
- /* clears the counter for number of renegotiations done
- * returns the current count before it is cleared */
- long wolfSSL_clear_num_renegotiations(WOLFSSL *s)
- {
- long total;
- WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations");
- if (s == NULL)
- return 0;
- total = s->secure_rene_count;
- s->secure_rene_count = 0;
- return total;
- }
- /* return the number of renegotiations since wolfSSL_new */
- long wolfSSL_total_renegotiations(WOLFSSL *s)
- {
- WOLFSSL_ENTER("wolfSSL_total_renegotiations");
- return wolfSSL_num_renegotiations(s);
- }
- /* return the number of renegotiations since wolfSSL_new */
- long wolfSSL_num_renegotiations(WOLFSSL* s)
- {
- if (s == NULL) {
- return 0;
- }
- return s->secure_rene_count;
- }
- /* Is there a renegotiation currently in progress? */
- int wolfSSL_SSL_renegotiate_pending(WOLFSSL *s)
- {
- return s && s->options.handShakeDone &&
- s->options.handShakeState != HANDSHAKE_DONE ? 1 : 0;
- }
- #endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */
- #ifdef OPENSSL_EXTRA
- long wolfSSL_clear_options(WOLFSSL* ssl, long opt)
- {
- WOLFSSL_ENTER("SSL_clear_options");
- if(ssl == NULL)
- return WOLFSSL_FAILURE;
- ssl->options.mask &= ~opt;
- return ssl->options.mask;
- }
- #ifdef HAVE_PK_CALLBACKS
- long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
- {
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- ssl->loggingCtx = arg;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_PK_CALLBACKS */
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
- const unsigned char *SSL_SESSION_get0_id_context(const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length)
- {
- sess = ClientSessionToSession(sess);
- return wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length);
- }
- #endif
- /*** TBD ***/
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st)
- {
- (void)st;
- WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
- /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */
- return WOLFSSL_FAILURE;
- }
- #endif
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
- {
- WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
- if (s == NULL){
- return BAD_FUNC_ARG;
- }
- if (type == TLSEXT_STATUSTYPE_ocsp){
- int r = TLSX_UseCertificateStatusRequest(&s->extensions, (byte)type, 0, s,
- s->heap, s->devId);
- return (long)r;
- } else {
- WOLFSSL_MSG(
- "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type.");
- return SSL_FAILURE;
- }
- }
- long wolfSSL_get_tlsext_status_type(WOLFSSL *s)
- {
- TLSX* extension;
- if (s == NULL)
- return WOLFSSL_FATAL_ERROR;
- extension = TLSX_Find(s->extensions, TLSX_STATUS_REQUEST);
- return extension != NULL ? TLSEXT_STATUSTYPE_ocsp : WOLFSSL_FATAL_ERROR;
- }
- #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg)
- {
- (void)s;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts");
- return WOLFSSL_FAILURE;
- }
- #endif
- /*** TBD ***/
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg)
- {
- (void)s;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts");
- return WOLFSSL_FAILURE;
- }
- #endif
- /*** TBD ***/
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg)
- {
- (void)s;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids");
- return WOLFSSL_FAILURE;
- }
- #endif
- /*** TBD ***/
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg)
- {
- (void)s;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids");
- return WOLFSSL_FAILURE;
- }
- #endif
- /*** TBD ***/
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len)
- {
- (void)s;
- (void)sid;
- (void)sid_len;
- WOLFSSL_STUB("SSL_SESSION_set1_id");
- return WOLFSSL_FAILURE;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /*** TBD ***/
- WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len)
- {
- (void)s;
- (void)sid_ctx;
- (void)sid_ctx_len;
- WOLFSSL_STUB("SSL_SESSION_set1_id_context");
- return WOLFSSL_FAILURE;
- }
- #endif
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) \
- || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
- /**
- * Set `a` in a smart way.
- *
- * @param a Object to set
- * @param type The type of object in value
- * @param value Object to set
- */
- void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value)
- {
- if (!a) {
- return;
- }
- switch (type) {
- case V_ASN1_NULL:
- a->value.ptr = (char *)value;
- break;
- case V_ASN1_SEQUENCE:
- a->value.asn1_string = (WOLFSSL_ASN1_STRING*)value;
- break;
- case V_ASN1_OBJECT:
- a->value.object = (WOLFSSL_ASN1_OBJECT*)value;
- break;
- case V_ASN1_UTCTIME:
- a->value.utctime = (WOLFSSL_ASN1_TIME*)value;
- break;
- case V_ASN1_GENERALIZEDTIME:
- a->value.generalizedtime = (WOLFSSL_ASN1_TIME*)value;
- break;
- default:
- WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE");
- return;
- }
- a->type = type;
- }
- #endif /* OPENSSL_ALL || WOLFSSL_APACHE_HTTPD || WOLFSSL_HAPROXY || WOLFSSL_WPAS */
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) \
- || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS) \
- || defined(OPENSSL_EXTRA)
- /**
- * Allocate a new WOLFSSL_ASN1_TYPE object.
- *
- * @return New zero'ed WOLFSSL_ASN1_TYPE object
- */
- WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void)
- {
- WOLFSSL_ASN1_TYPE* ret = (WOLFSSL_ASN1_TYPE*)XMALLOC(sizeof(WOLFSSL_ASN1_TYPE),
- NULL, DYNAMIC_TYPE_OPENSSL);
- if (!ret)
- return NULL;
- XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TYPE));
- return ret;
- }
- /**
- * Free WOLFSSL_ASN1_TYPE and all its members.
- *
- * @param at Object to free
- */
- void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at)
- {
- if (at) {
- switch (at->type) {
- case V_ASN1_OBJECT:
- wolfSSL_ASN1_OBJECT_free(at->value.object);
- break;
- case V_ASN1_UTCTIME:
- #ifndef NO_ASN_TIME
- wolfSSL_ASN1_TIME_free(at->value.utctime);
- #endif
- break;
- case V_ASN1_GENERALIZEDTIME:
- #ifndef NO_ASN_TIME
- wolfSSL_ASN1_TIME_free(at->value.generalizedtime);
- #endif
- break;
- case V_ASN1_UTF8STRING:
- case V_ASN1_PRINTABLESTRING:
- case V_ASN1_T61STRING:
- case V_ASN1_IA5STRING:
- case V_ASN1_UNIVERSALSTRING:
- case V_ASN1_SEQUENCE:
- wolfSSL_ASN1_STRING_free(at->value.asn1_string);
- break;
- default:
- WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE");
- break;
- }
- XFREE(at, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- #endif /* OPENSSL_ALL || WOLFSSL_APACHE_HTTPD || WOLFSSL_HAPROXY || WOLFSSL_WPAS
- || OPENSSL_EXTRA */
- #ifndef NO_WOLFSSL_STUB
- /*** TBD ***/
- WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl)
- {
- (void)ssl;
- WOLFSSL_STUB("SSL_get_privatekey");
- return NULL;
- }
- #endif
- /**
- * Get a textual representation of given WOLFSSL_ASN1_OBJECT then write it to
- * buf at most buf_len bytes.
- *
- * params
- * - buf: buffer where the textual representation is to be written to
- * - buf_len: buffer size in bytes
- * - a: WOLFSSL_ASN1_OBJECT
- *
- * return the string length written on success, WOLFSSL_FAILURE on failure.
- */
- WOLFSSL_API int wolfSSL_i2t_ASN1_OBJECT(char *buf, int buf_len,
- WOLFSSL_ASN1_OBJECT *a)
- {
- WOLFSSL_ENTER("wolfSSL_i2t_ASN1_OBJECT");
- return wolfSSL_OBJ_obj2txt(buf, buf_len, a, 0);
- }
- WOLFSSL_ASN1_OBJECT *wolfSSL_d2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a,
- const unsigned char **der,
- long length)
- {
- const unsigned char *d;
- long len;
- int tag, cls;
- WOLFSSL_ASN1_OBJECT* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_d2i_ASN1_OBJECT");
- if (!der || !*der || length <= 0) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
- d = *der;
- if (wolfSSL_ASN1_get_object(&d, &len, &tag, &cls, length) & 0x80) {
- WOLFSSL_MSG("wolfSSL_ASN1_get_object error");
- return NULL;
- }
- /* d now points to value */
- if (tag != ASN_OBJECT_ID) {
- WOLFSSL_MSG("Not an ASN object");
- return NULL;
- }
- ret = wolfSSL_c2i_ASN1_OBJECT(a, &d, len);
- if (ret)
- *der = d;
- return ret;
- }
- /**
- * Parse an ASN1 encoded input and output information about the parsed object
- * @param in ASN1 encoded data. *in is moved to the value of the ASN1 object
- * @param len Length of parsed ASN1 object
- * @param tag Tag value of parsed ASN1 object
- * @param cls Class of parsed ASN1 object
- * @param inLen Length of *in buffer
- * @return int Depends on which bits are set in the returned int:
- * 0x80 an error occurred during parsing
- * 0x20 parsed object is constructed
- * 0x01 the parsed object length is infinite
- */
- int wolfSSL_ASN1_get_object(const unsigned char **in, long *len, int *tag,
- int *cls, long inLen)
- {
- word32 inOutIdx = 0;
- int l;
- byte t;
- int ret = 0x80;
- WOLFSSL_ENTER("wolfSSL_ASN1_get_object");
- if (!in || !*in || !len || !tag || !cls || inLen == 0) {
- WOLFSSL_MSG("Bad parameter");
- return ret;
- }
- if (GetASNTag(*in, &inOutIdx, &t, (word32)inLen) != 0) {
- WOLFSSL_MSG("GetASNTag error");
- return ret;
- }
- if (GetLength(*in, &inOutIdx, &l, (word32)inLen) < 0) {
- WOLFSSL_MSG("GetLength error");
- return ret;
- }
- *tag = t & 0x1F; /* Tag number is 5 lsb */
- *cls = t & 0xC0; /* Class is 2 msb */
- *len = l;
- ret = t & ASN_CONSTRUCTED;
- if (l > (int)(inLen - inOutIdx)) {
- /* Still return other values but indicate error in msb */
- ret |= 0x80;
- }
- *in += inOutIdx;
- return ret;
- }
- WOLFSSL_ASN1_OBJECT *wolfSSL_c2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a,
- const unsigned char **pp, long len)
- {
- WOLFSSL_ASN1_OBJECT* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_c2i_ASN1_OBJECT");
- if (!pp || !*pp || len <= 0) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
- if (!(ret = wolfSSL_ASN1_OBJECT_new())) {
- WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new error");
- return NULL;
- }
- ret->obj = (const unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1);
- if (!ret->obj) {
- WOLFSSL_MSG("error allocating asn data memory");
- wolfSSL_ASN1_OBJECT_free(ret);
- return NULL;
- }
- XMEMCPY((byte*)ret->obj, *pp, len);
- ret->objSz = (unsigned int)len;
- ret->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA;
- *pp += len;
- if (a)
- *a = ret;
- return ret;
- }
- #ifndef NO_BIO
- /* Return number of bytes written to BIO on success. 0 on failure. */
- WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp,
- WOLFSSL_ASN1_OBJECT *a)
- {
- int length = 0;
- word32 idx = 0;
- const char null_str[] = "NULL";
- WOLFSSL_ENTER("wolfSSL_i2a_ASN1_OBJECT");
- if (bp == NULL)
- return WOLFSSL_FAILURE;
- if (a == NULL) {
- /* Write "NULL" */
- if (wolfSSL_BIO_write(bp, null_str, (int)XSTRLEN(null_str)) ==
- (int)XSTRLEN(null_str)) {
- return (int)XSTRLEN(null_str);
- }
- else {
- return WOLFSSL_FAILURE;
- }
- }
- if ((a->obj == NULL) || (a->obj[idx++] != ASN_OBJECT_ID)) {
- WOLFSSL_MSG("Bad ASN1 Object");
- return WOLFSSL_FAILURE;
- }
- if (GetLength((const byte*)a->obj, &idx, &length,
- a->objSz) < 0 || length < 0) {
- return WOLFSSL_FAILURE;
- }
- if (wolfSSL_BIO_write(bp, a->obj + idx, length) == (int)length) {
- return length;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* !NO_BIO */
- /* Returns object data for an ASN1_OBJECT */
- /* If pp is NULL then only the size is returned */
- /* If pp has pointer to pointer then its used directly */
- /* If pp has pointer to pointer that is NULL then new variable is allocated */
- /* Failure returns WOLFSSL_FAILURE (0) */
- int wolfSSL_i2d_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT *a, unsigned char **pp)
- {
- byte *p;
- WOLFSSL_ENTER("wolfSSL_i2d_ASN1_OBJECT");
- if (!a || !a->obj) {
- WOLFSSL_MSG("Bad parameters");
- return WOLFSSL_FAILURE;
- }
- if (!pp)
- return a->objSz;
- if (*pp)
- p = *pp;
- else {
- p = (byte*)XMALLOC(a->objSz, NULL, DYNAMIC_TYPE_OPENSSL);
- if (!p) {
- WOLFSSL_MSG("Bad malloc");
- return WOLFSSL_FAILURE;
- }
- }
- XMEMCPY(p, a->obj, a->objSz);
- *pp = p + a->objSz;
- return a->objSz;
- }
- #ifndef NO_WOLFSSL_STUB
- /*** TBD ***/
- WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength))
- {
- (void)ctx;
- (void)dh;
- WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback");
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /*** TBD ***/
- WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
- {
- WOLFSSL_STUB("SSL_COMP_get_compression_methods");
- return NULL;
- }
- #endif
- int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p)
- {
- WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num");
- if (p == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
- return (int)p->num;
- }
- WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* sk, int i)
- {
- WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value");
- return (WOLFSSL_CIPHER*)wolfSSL_sk_value(sk, i);
- }
- #if !defined(NETOS)
- WOLFSSL_API void ERR_load_SSL_strings(void)
- {
- }
- #endif
- #ifdef HAVE_OCSP
- WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
- {
- if (s == NULL || resp == NULL)
- return 0;
- *resp = s->ocspResp;
- return s->ocspRespSz;
- }
- WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len)
- {
- if (s == NULL)
- return WOLFSSL_FAILURE;
- s->ocspResp = resp;
- s->ocspRespSz = len;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_OCSP */
- #ifdef HAVE_MAX_FRAGMENT
- #ifndef NO_WOLFSSL_CLIENT
- /**
- * Set max fragment tls extension
- * @param c a pointer to WOLFSSL_CTX object
- * @param mode maximum fragment length mode
- * @return 1 on success, otherwise 0 or negative error code
- */
- WOLFSSL_API int wolfSSL_CTX_set_tlsext_max_fragment_length(WOLFSSL_CTX *c,
- unsigned char mode)
- {
- if (c == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 ))
- return BAD_FUNC_ARG;
- return wolfSSL_CTX_UseMaxFragment(c, mode);
- }
- /**
- * Set max fragment tls extension
- * @param c a pointer to WOLFSSL object
- * @param mode maximum fragment length mode
- * @return 1 on success, otherwise 0 or negative error code
- */
- WOLFSSL_API int wolfSSL_set_tlsext_max_fragment_length(WOLFSSL *s,
- unsigned char mode)
- {
- if (s == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 ))
- return BAD_FUNC_ARG;
- return wolfSSL_UseMaxFragment(s, mode);
- }
- #endif /* NO_WOLFSSL_CLIENT */
- #endif /* HAVE_MAX_FRAGMENT */
- #endif /* OPENSSL_EXTRA */
- #ifdef WOLFSSL_HAVE_TLS_UNIQUE
- WOLFSSL_API size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count)
- {
- byte len = 0;
- WOLFSSL_ENTER("SSL_get_finished");
- if (!ssl || !buf || count < TLS_FINISHED_SZ) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- len = ssl->serverFinished_len;
- XMEMCPY(buf, ssl->serverFinished, len);
- }
- else {
- len = ssl->clientFinished_len;
- XMEMCPY(buf, ssl->clientFinished, len);
- }
- return len;
- }
- WOLFSSL_API size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count)
- {
- byte len = 0;
- WOLFSSL_ENTER("SSL_get_peer_finished");
- if (!ssl || !buf || count < TLS_FINISHED_SZ) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- len = ssl->serverFinished_len;
- XMEMCPY(buf, ssl->serverFinished, len);
- }
- else {
- len = ssl->clientFinished_len;
- XMEMCPY(buf, ssl->clientFinished, len);
- }
- return len;
- }
- #endif /* WOLFSSL_HAVE_TLS_UNIQUE */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- long wolfSSL_get_verify_result(const WOLFSSL *ssl)
- {
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- return ssl->peerVerifyRet;
- }
- #endif
- #ifdef OPENSSL_EXTRA
- #ifndef NO_WOLFSSL_STUB
- /* shows the number of accepts attempted by CTX in it's lifetime */
- long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_accept");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /* shows the number of connects attempted CTX in it's lifetime */
- long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_connect");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /* shows the number of accepts completed by CTX in it's lifetime */
- long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /* shows the number of connects completed by CTX in it's lifetime */
- long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /* shows the number of renegotiation accepts attempted by CTX */
- long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /* shows the number of renegotiation accepts attempted by CTX */
- long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_hits");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_misses");
- (void)ctx;
- return 0;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts");
- (void)ctx;
- return 0;
- }
- #endif
- /* Return the total number of sessions */
- long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx)
- {
- word32 total = 0;
- WOLFSSL_ENTER("wolfSSL_CTX_sess_number");
- (void)ctx;
- #if defined(WOLFSSL_SESSION_STATS) && !defined(NO_SESSION_CACHE)
- if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error getting session stats");
- }
- #else
- WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats");
- #endif
- return (long)total;
- }
- #ifndef NO_CERTS
- long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
- {
- byte* chain = NULL;
- long chainSz = 0;
- int derSz;
- const byte* der;
- int ret;
- int idx = 0;
- DerBuffer *derBuffer = NULL;
- WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert");
- if (ctx == NULL || x509 == NULL) {
- WOLFSSL_MSG("Bad Argument");
- return WOLFSSL_FAILURE;
- }
- der = wolfSSL_X509_get_der(x509, &derSz);
- if (der == NULL || derSz <= 0) {
- WOLFSSL_MSG("Error getting X509 DER");
- return WOLFSSL_FAILURE;
- }
- if (ctx->certificate == NULL) {
- WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
- /* Process buffer makes first certificate the leaf. */
- ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
- NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx));
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
- return WOLFSSL_FAILURE;
- }
- }
- else {
- /* TODO: Do this elsewhere. */
- ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap);
- if (ret != 0) {
- WOLFSSL_MSG("Memory Error");
- return WOLFSSL_FAILURE;
- }
- XMEMCPY(derBuffer->buffer, der, derSz);
- ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA,
- GET_VERIFY_SETTING_CTX(ctx));
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
- return WOLFSSL_FAILURE;
- }
- /* adding cert to existing chain */
- if (ctx->certChain != NULL && ctx->certChain->length > 0) {
- chainSz += ctx->certChain->length;
- }
- chainSz += OPAQUE24_LEN + derSz;
- chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER);
- if (chain == NULL) {
- WOLFSSL_MSG("Memory Error");
- return WOLFSSL_FAILURE;
- }
- if (ctx->certChain != NULL && ctx->certChain->length > 0) {
- XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length);
- idx = ctx->certChain->length;
- }
- c32to24(derSz, chain + idx);
- idx += OPAQUE24_LEN;
- XMEMCPY(chain + idx, der, derSz);
- idx += derSz;
- #ifdef WOLFSSL_TLS13
- ctx->certChainCnt++;
- #endif
- FreeDer(&ctx->certChain);
- ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap);
- if (ret == 0) {
- XMEMCPY(ctx->certChain->buffer, chain, idx);
- }
- }
- /* on success WOLFSSL_X509 memory is responsibility of ctx */
- wolfSSL_X509_free(x509);
- if (chain != NULL)
- XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER);
- return WOLFSSL_SUCCESS;
- }
- long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
- {
- if (ctx == NULL || ctx->cm == NULL) {
- return WOLFSSL_FAILURE;
- }
- ctx->cm->ocspIOCtx = arg;
- return WOLFSSL_SUCCESS;
- }
- #endif /* NO_CERTS */
- /* Get the session cache mode for CTX
- *
- * ctx WOLFSSL_CTX struct to get cache mode from
- *
- * Returns a bit mask that has the session cache mode */
- WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx)
- {
- long m = 0;
- WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
- if (ctx == NULL) {
- return m;
- }
- if (ctx->sessionCacheOff != 1) {
- m |= SSL_SESS_CACHE_SERVER;
- }
- if (ctx->sessionCacheFlushOff == 1) {
- m |= SSL_SESS_CACHE_NO_AUTO_CLEAR;
- }
- #ifdef HAVE_EXT_CACHE
- if (ctx->internalCacheOff == 1) {
- m |= SSL_SESS_CACHE_NO_INTERNAL_STORE;
- }
- if (ctx->internalCacheLookupOff == 1) {
- m |= SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
- }
- #endif
- return m;
- }
- int wolfSSL_get_read_ahead(const WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- return ssl->readAhead;
- }
- int wolfSSL_set_read_ahead(WOLFSSL* ssl, int v)
- {
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- ssl->readAhead = (byte)v;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
- return ctx->readAhead;
- }
- int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v)
- {
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
- ctx->readAhead = (byte)v;
- return WOLFSSL_SUCCESS;
- }
- long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
- void* arg)
- {
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
- ctx->userPRFArg = arg;
- return WOLFSSL_SUCCESS;
- }
- #ifndef NO_DES3
- /* 0 on success */
- int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes,
- WOLFSSL_DES_key_schedule* key)
- {
- #ifdef WOLFSSL_CHECK_DESKEY
- return wolfSSL_DES_set_key_checked(myDes, key);
- #else
- wolfSSL_DES_set_key_unchecked(myDes, key);
- return 0;
- #endif
- }
- /* return true in fail case (1) */
- static int DES_check(word32 mask, word32 mask2, unsigned char* key)
- {
- word32 value[2];
- /* sanity check on length made in wolfSSL_DES_set_key_checked */
- value[0] = mask;
- value[1] = mask2;
- return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0;
- }
- /* check that the key is odd parity and is not a weak key
- * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */
- int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes,
- WOLFSSL_DES_key_schedule* key)
- {
- if (myDes == NULL || key == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked");
- return -2;
- }
- else {
- word32 sz = sizeof(WOLFSSL_DES_key_schedule);
- /* sanity check before call to DES_check */
- if (sz != (sizeof(word32) * 2)) {
- WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size");
- return -2;
- }
- /* check odd parity */
- if (wolfSSL_DES_check_key_parity(myDes) != 1) {
- WOLFSSL_MSG("Odd parity test fail");
- return -1;
- }
- if (wolfSSL_DES_is_weak_key(myDes) == 1) {
- WOLFSSL_MSG("Weak key found");
- return -2;
- }
- /* passed tests, now copy over key */
- XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
- return 0;
- }
- }
- /* check is not weak. Weak key list from Nist "Recommendation for the Triple
- * Data Encryption Algorithm (TDEA) Block Cipher"
- *
- * returns 1 if is weak 0 if not
- */
- int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key)
- {
- word32 mask, mask2;
- WOLFSSL_ENTER("wolfSSL_DES_is_weak_key");
- if (key == NULL) {
- WOLFSSL_MSG("NULL key passed in");
- return 1;
- }
- mask = 0x01010101; mask2 = 0x01010101;
- if (DES_check(mask, mask2, *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE;
- if (DES_check(mask, mask2, *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1;
- if (DES_check(mask, mask2, *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E;
- if (DES_check(mask, mask2, *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- /* semi-weak *key check (list from same Nist paper) */
- mask = 0x011F011F; mask2 = 0x010E010E;
- if (DES_check(mask, mask2, *key) ||
- DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- mask = 0x01E001E0; mask2 = 0x01F101F1;
- if (DES_check(mask, mask2, *key) ||
- DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- mask = 0x01FE01FE; mask2 = 0x01FE01FE;
- if (DES_check(mask, mask2, *key) ||
- DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- mask = 0x1FE01FE0; mask2 = 0x0EF10EF1;
- if (DES_check(mask, mask2, *key) ||
- DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- mask = 0x1FFE1FFE; mask2 = 0x0EFE0EFE;
- if (DES_check(mask, mask2, *key) ||
- DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
- WOLFSSL_MSG("Weak key found");
- return 1;
- }
- return 0;
- }
- void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes,
- WOLFSSL_DES_key_schedule* key)
- {
- if (myDes != NULL && key != NULL) {
- XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
- }
- }
- /* Sets the parity of the DES key for use */
- void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes)
- {
- word32 i;
- word32 sz = sizeof(WOLFSSL_DES_cblock);
- WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity");
- for (i = 0; i < sz; i++) {
- unsigned char c = (*myDes)[i];
- if ((
- ((c >> 1) & 0x01) ^
- ((c >> 2) & 0x01) ^
- ((c >> 3) & 0x01) ^
- ((c >> 4) & 0x01) ^
- ((c >> 5) & 0x01) ^
- ((c >> 6) & 0x01) ^
- ((c >> 7) & 0x01)) == (c & 0x01)) {
- WOLFSSL_MSG("Flipping parity bit");
- (*myDes)[i] = c ^ 0x01;
- }
- }
- }
- int wolfSSL_DES_check_key_parity(WOLFSSL_DES_cblock *myDes)
- {
- word32 i;
- word32 sz = sizeof(WOLFSSL_DES_cblock);
- WOLFSSL_ENTER("wolfSSL_DES_check_key_parity");
- for (i = 0; i < sz; i++) {
- unsigned char c = (*myDes)[i];
- if ((
- ((c >> 1) & 0x01) ^
- ((c >> 2) & 0x01) ^
- ((c >> 3) & 0x01) ^
- ((c >> 4) & 0x01) ^
- ((c >> 5) & 0x01) ^
- ((c >> 6) & 0x01) ^
- ((c >> 7) & 0x01)) == (c & 0x01)) {
- return 0;
- }
- }
- return 1;
- }
- #ifdef WOLFSSL_DES_ECB
- /* Encrypt or decrypt input message desa with key and get output in desb.
- * if enc is DES_ENCRYPT,input message is encrypted or
- * if enc is DES_DECRYPT,input message is decrypted.
- * */
- void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa,
- WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc)
- {
- Des myDes;
- WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt");
- if (desa == NULL || key == NULL || desb == NULL ||
- (enc != DES_ENCRYPT && enc != DES_DECRYPT)) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt");
- } else {
- if (wc_Des_SetKey(&myDes, (const byte*) key,
- (const byte*) NULL, !enc) != 0) {
- WOLFSSL_MSG("wc_Des_SetKey return error.");
- return;
- }
- if (enc == DES_ENCRYPT){
- if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, (const byte*) desa,
- sizeof(WOLFSSL_DES_cblock)) != 0){
- WOLFSSL_MSG("wc_Des_EcbEncrypt return error.");
- }
- } else {
- if (wc_Des_EcbDecrypt(&myDes, (byte*) desb, (const byte*) desa,
- sizeof(WOLFSSL_DES_cblock)) != 0){
- WOLFSSL_MSG("wc_Des_EcbDecrpyt return error.");
- }
- }
- }
- }
- #endif
- #endif /* NO_DES3 */
- #ifndef NO_RC4
- /* Set the key state for Arc4 structure.
- *
- * key Arc4 structure to use
- * len length of data buffer
- * data initial state to set Arc4 structure
- */
- void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len,
- const unsigned char* data)
- {
- typedef char rc4_test[sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4) ? 1 : -1];
- (void)sizeof(rc4_test);
- WOLFSSL_ENTER("wolfSSL_RC4_set_key");
- if (key == NULL || len < 0) {
- WOLFSSL_MSG("bad argument passed in");
- return;
- }
- XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY));
- wc_Arc4SetKey((Arc4*)key, data, (word32)len);
- }
- /* Encrypt/decrypt with Arc4 structure.
- *
- * len length of buffer to encrypt/decrypt (in/out)
- * in buffer to encrypt/decrypt
- * out results of encryption/decryption
- */
- void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len,
- const unsigned char* in, unsigned char* out)
- {
- WOLFSSL_ENTER("wolfSSL_RC4");
- if (key == NULL || in == NULL || out == NULL) {
- WOLFSSL_MSG("Bad argument passed in");
- return;
- }
- wc_Arc4Process((Arc4*)key, out, in, (word32)len);
- }
- #endif /* NO_RC4 */
- #ifndef NO_AES
- #ifdef WOLFSSL_AES_DIRECT
- /* AES encrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
- *
- * input Data to encrypt
- * output Encrypted data after done
- * key AES key to use for encryption
- */
- void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output,
- AES_KEY *key)
- {
- WOLFSSL_ENTER("wolfSSL_AES_encrypt");
- if (input == NULL || output == NULL || key == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- return;
- }
- #if !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
- if (wc_AesEncryptDirect((Aes*)key, output, input) != 0) {
- WOLFSSL_MSG("wc_AesEncryptDirect failed");
- return;
- }
- #else
- wc_AesEncryptDirect((Aes*)key, output, input);
- #endif
- }
- /* AES decrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
- *
- * input Data to decrypt
- * output Decrypted data after done
- * key AES key to use for encryption
- */
- void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output,
- AES_KEY *key)
- {
- WOLFSSL_ENTER("wolfSSL_AES_decrypt");
- if (input == NULL || output == NULL || key == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- return;
- }
- #if !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
- if (wc_AesDecryptDirect((Aes*)key, output, input) != 0) {
- WOLFSSL_MSG("wc_AesDecryptDirect failed");
- return;
- }
- #else
- wc_AesDecryptDirect((Aes*)key, output, input);
- #endif
- }
- #endif /* WOLFSSL_AES_DIRECT */
- /* Setup of an AES key to use for encryption.
- *
- * key key in bytes to use for encryption
- * bits size of key in bits
- * aes AES structure to initialize
- */
- int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits,
- AES_KEY *aes)
- {
- typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
- (void)sizeof(aes_test);
- WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key");
- if (key == NULL || aes == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- return -1;
- }
- XMEMSET(aes, 0, sizeof(AES_KEY));
- if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_ENCRYPT) != 0) {
- WOLFSSL_MSG("Error in setting AES key");
- return -1;
- }
- return 0;
- }
- /* Setup of an AES key to use for decryption.
- *
- * key key in bytes to use for decryption
- * bits size of key in bits
- * aes AES structure to initialize
- */
- int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits,
- AES_KEY *aes)
- {
- typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
- (void)sizeof(aes_test);
- WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key");
- if (key == NULL || aes == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- return -1;
- }
- XMEMSET(aes, 0, sizeof(AES_KEY));
- if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_DECRYPT) != 0) {
- WOLFSSL_MSG("Error in setting AES key");
- return -1;
- }
- return 0;
- }
- #ifdef HAVE_AES_ECB
- /* Encrypt/decrypt a 16 byte block of data using the key passed in.
- *
- * in buffer to encrypt/decrypt
- * out buffer to hold result of encryption/decryption
- * key AES structure to use with encryption/decryption
- * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
- */
- void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out,
- AES_KEY *key, const int enc)
- {
- Aes* aes;
- WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt");
- if (key == NULL || in == NULL || out == NULL) {
- WOLFSSL_MSG("Error, Null argument passed in");
- return;
- }
- aes = (Aes*)key;
- if (enc == AES_ENCRYPT) {
- if (wc_AesEcbEncrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
- WOLFSSL_MSG("Error with AES CBC encrypt");
- }
- }
- else {
- #ifdef HAVE_AES_DECRYPT
- if (wc_AesEcbDecrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
- WOLFSSL_MSG("Error with AES CBC decrypt");
- }
- #else
- WOLFSSL_MSG("AES decryption not compiled in");
- #endif
- }
- }
- #endif /* HAVE_AES_ECB */
- #ifdef HAVE_AES_CBC
- /* Encrypt data using key and iv passed in. iv gets updated to most recent iv
- * state after encryption/decryption.
- *
- * in buffer to encrypt/decrypt
- * out buffer to hold result of encryption/decryption
- * len length of input buffer
- * key AES structure to use with encryption/decryption
- * iv iv to use with operation
- * enc 1 for encryption and 0 for decryption
- */
- void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out,
- size_t len, AES_KEY *key, unsigned char* iv, const int enc)
- {
- Aes* aes;
- WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
- if (key == NULL || in == NULL || out == NULL || iv == NULL || len == 0) {
- WOLFSSL_MSG("Error, Null argument passed in");
- return;
- }
- aes = (Aes*)key;
- if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
- WOLFSSL_MSG("Error with setting iv");
- return;
- }
- if (enc == AES_ENCRYPT) {
- if (wc_AesCbcEncrypt(aes, out, in, (word32)len) != 0) {
- WOLFSSL_MSG("Error with AES CBC encrypt");
- return;
- }
- }
- else {
- if (wc_AesCbcDecrypt(aes, out, in, (word32)len) != 0) {
- WOLFSSL_MSG("Error with AES CBC decrypt");
- return;
- }
- }
- /* to be compatible copy iv to iv buffer after completing operation */
- XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
- }
- #endif /* HAVE_AES_CBC */
- /* Encrypt data using CFB mode with key and iv passed in. iv gets updated to
- * most recent iv state after encryption/decryption.
- *
- * in buffer to encrypt/decrypt
- * out buffer to hold result of encryption/decryption
- * len length of input buffer
- * key AES structure to use with encryption/decryption
- * iv iv to use with operation
- * num contains the amount of block used
- * enc AES_ENCRYPT for encryption and AES_DECRYPT for decryption
- */
- void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
- size_t len, AES_KEY *key, unsigned char* iv, int* num,
- const int enc)
- {
- #ifndef WOLFSSL_AES_CFB
- WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB");
- (void)in;
- (void)out;
- (void)len;
- (void)key;
- (void)iv;
- (void)num;
- (void)enc;
- return;
- #else
- Aes* aes;
- WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
- if (key == NULL || in == NULL || out == NULL || iv == NULL) {
- WOLFSSL_MSG("Error, Null argument passed in");
- return;
- }
- aes = (Aes*)key;
- /*
- * We copy the IV directly into reg here because using wc_AesSetIV will
- * clear the leftover bytes field "left", and this function relies on the
- * leftover bytes being preserved between calls.
- */
- XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
- if (enc == AES_ENCRYPT) {
- if (wc_AesCfbEncrypt(aes, out, in, (word32)len) != 0) {
- WOLFSSL_MSG("Error with AES CBC encrypt");
- return;
- }
- }
- else {
- if (wc_AesCfbDecrypt(aes, out, in, (word32)len) != 0) {
- WOLFSSL_MSG("Error with AES CBC decrypt");
- return;
- }
- }
- /* to be compatible copy iv to iv buffer after completing operation */
- XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
- /* store number of left over bytes to num */
- *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0;
- #endif /* WOLFSSL_AES_CFB */
- }
- /* wc_AesKey*Wrap_ex API not available in FIPS and SELFTEST */
- #if defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
- int wolfSSL_AES_wrap_key(AES_KEY *key, const unsigned char *iv,
- unsigned char *out,
- const unsigned char *in, unsigned int inlen)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_AES_wrap_key");
- if (out == NULL || in == NULL) {
- WOLFSSL_MSG("Error, Null argument passed in");
- return WOLFSSL_FAILURE;
- }
- ret = wc_AesKeyWrap_ex((Aes*)key, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv);
- return ret < 0 ? WOLFSSL_FAILURE : ret;
- }
- int wolfSSL_AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
- unsigned char *out,
- const unsigned char *in, unsigned int inlen)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_AES_wrap_key");
- if (out == NULL || in == NULL) {
- WOLFSSL_MSG("Error, Null argument passed in");
- return WOLFSSL_FAILURE;
- }
- ret = wc_AesKeyUnWrap_ex((Aes*)key, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv);
- return ret < 0 ? WOLFSSL_FAILURE : ret;
- }
- #endif /* HAVE_AES_KEYWRAP && !HAVE_FIPS && !HAVE_SELFTEST */
- #ifdef HAVE_CTS
- /*
- * Ciphertext stealing interface compatible with RFC2040 and RFC3962.
- */
- size_t wolfSSL_CRYPTO_cts128_encrypt(const unsigned char *in,
- unsigned char *out, size_t len, const void *key,
- unsigned char *iv, WOLFSSL_CBC128_CB cbc)
- {
- byte lastBlk[WOLFSSL_CTS128_BLOCK_SZ];
- int lastBlkLen = len % WOLFSSL_CTS128_BLOCK_SZ;
- WOLFSSL_ENTER("wolfSSL_CRYPTO_cts128_encrypt");
- if (in == NULL || out == NULL || len < WOLFSSL_CTS128_BLOCK_SZ ||
- cbc == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if (lastBlkLen == 0)
- lastBlkLen = WOLFSSL_CTS128_BLOCK_SZ;
- /* Encrypt data up to last block */
- (*cbc)(in, out, len - lastBlkLen, key, iv, AES_ENCRYPT);
- /* Move to last block */
- in += len - lastBlkLen;
- out += len - lastBlkLen;
- /* RFC2040: Pad Pn with zeros at the end to create P of length BB. */
- XMEMCPY(lastBlk, in, lastBlkLen);
- XMEMSET(lastBlk + lastBlkLen, 0, WOLFSSL_CTS128_BLOCK_SZ - lastBlkLen);
- /* RFC2040: Select the first Ln bytes of En-1 to create Cn */
- XMEMCPY(out, out - WOLFSSL_CTS128_BLOCK_SZ, lastBlkLen);
- (*cbc)(lastBlk, out - WOLFSSL_CTS128_BLOCK_SZ, WOLFSSL_CTS128_BLOCK_SZ,
- key, iv, AES_ENCRYPT);
- return len;
- }
- size_t wolfSSL_CRYPTO_cts128_decrypt(const unsigned char *in,
- unsigned char *out, size_t len, const void *key,
- unsigned char *iv, WOLFSSL_CBC128_CB cbc)
- {
- byte lastBlk[WOLFSSL_CTS128_BLOCK_SZ];
- byte prevBlk[WOLFSSL_CTS128_BLOCK_SZ];
- int lastBlkLen = len % WOLFSSL_CTS128_BLOCK_SZ;
- WOLFSSL_ENTER("wolfSSL_CRYPTO_cts128_decrypt");
- if (in == NULL || out == NULL || len <= WOLFSSL_CTS128_BLOCK_SZ ||
- cbc == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if (lastBlkLen == 0)
- lastBlkLen = WOLFSSL_CTS128_BLOCK_SZ;
- /* Decrypt up to last two blocks */
- (*cbc)(in, out, len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ, key, iv,
- AES_DECRYPTION);
- /* Move to last two blocks */
- in += len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ;
- out += len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ;
- /* RFC2040: Decrypt Cn-1 to create Dn.
- * Use 0 buffer as IV to do straight decryption.
- * This places the Cn-1 block at lastBlk */
- XMEMSET(lastBlk, 0, WOLFSSL_CTS128_BLOCK_SZ);
- (*cbc)(in, prevBlk, WOLFSSL_CTS128_BLOCK_SZ, key, lastBlk, AES_DECRYPT);
- /* RFC2040: Append the tail (BB minus Ln) bytes of Xn to Cn
- * to create En. */
- XMEMCPY(prevBlk, in + WOLFSSL_CTS128_BLOCK_SZ, lastBlkLen);
- /* Cn and Cn-1 can now be decrypted */
- (*cbc)(prevBlk, out, WOLFSSL_CTS128_BLOCK_SZ, key, iv, AES_DECRYPT);
- (*cbc)(lastBlk, lastBlk, WOLFSSL_CTS128_BLOCK_SZ, key, iv, AES_DECRYPT);
- XMEMCPY(out + WOLFSSL_CTS128_BLOCK_SZ, lastBlk, lastBlkLen);
- return len;
- }
- #endif /* HAVE_CTS */
- #endif /* NO_AES */
- #ifndef NO_ASN_TIME
- #ifndef NO_BIO
- int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a)
- {
- WOLFSSL_ENTER("ASN1_UTCTIME_print");
- if (bio == NULL || a == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (a->type != ASN_UTC_TIME) {
- WOLFSSL_MSG("Error, not UTC_TIME");
- return WOLFSSL_FAILURE;
- }
- return wolfSSL_ASN1_TIME_print(bio, a);
- }
- #endif /* !NO_BIO */
- /* Checks the ASN1 syntax of "a"
- * returns WOLFSSL_SUCCESS (1) if correct otherwise WOLFSSL_FAILURE (0) */
- int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a)
- {
- char buf[MAX_TIME_STRING_SZ];
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_check");
- /* if can parse the WOLFSSL_ASN1_TIME passed in then consider syntax good */
- if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)a, buf,
- MAX_TIME_STRING_SZ) == NULL) {
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- /*
- * Convert time to Unix time (GMT).
- */
- static long long TimeToUnixTime(int sec, int min, int hour, int mday, int mon,
- int year)
- {
- /* Number of cumulative days from the previous months, starting from
- * beginning of January. */
- static const int monthDaysCumulative [12] = {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
- };
- int leapDays = year;
- if (mon <= 1) {
- --leapDays;
- }
- leapDays = leapDays / 4 - leapDays / 100 + leapDays / 400 - 1969 / 4 +
- 1969 / 100 - 1969 / 400;
- return ((((long long) (year - 1970) * 365 + leapDays +
- monthDaysCumulative[mon] + mday - 1) * 24 + hour) * 60 + min) * 60 +
- sec;
- }
- int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from,
- const WOLFSSL_ASN1_TIME *to)
- {
- const int SECS_PER_DAY = 24 * 60 * 60;
- struct tm fromTm_s, *fromTmGmt = &fromTm_s;
- struct tm toTm_s, *toTmGmt = &toTm_s;
- time_t currTime;
- long long fromSecs;
- long long toSecs;
- double diffSecs;
- struct tm *tmpTs;
- #if defined(NEED_TMP_TIME)
- /* for use with gmtime_r */
- struct tm tmpTimeStorage;
- tmpTs = &tmpTimeStorage;
- #else
- tmpTs = NULL;
- #endif
- (void)tmpTs;
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_diff");
- if (days == NULL) {
- WOLFSSL_MSG("days is NULL");
- return WOLFSSL_FAILURE;
- }
- if (secs == NULL) {
- WOLFSSL_MSG("secs is NULL");
- return WOLFSSL_FAILURE;
- }
- if (from == NULL && to == NULL) {
- *days = 0;
- *secs = 0;
- return WOLFSSL_SUCCESS;
- }
- if (from == NULL) {
- currTime = wc_Time(0);
- fromTmGmt = XGMTIME(&currTime, tmpTs);
- if (fromTmGmt == NULL) {
- WOLFSSL_MSG("XGMTIME for from time failed.");
- return WOLFSSL_FAILURE;
- }
- }
- else if (wolfSSL_ASN1_TIME_to_tm(from, fromTmGmt) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Failed to convert from time to struct tm.");
- return WOLFSSL_FAILURE;
- }
- /* We use TimeToUnixTime here instead of XMKTIME to avoid the Year 2038
- * Problem on platforms where time_t is 32 bits. struct tm stores the year
- * as years since 1900, so we add 1900 to the year. */
- fromSecs = TimeToUnixTime(fromTmGmt->tm_sec, fromTmGmt->tm_min,
- fromTmGmt->tm_hour, fromTmGmt->tm_mday,
- fromTmGmt->tm_mon, fromTmGmt->tm_year + 1900);
- if (to == NULL) {
- currTime = wc_Time(0);
- toTmGmt = XGMTIME(&currTime, tmpTs);
- if (toTmGmt == NULL) {
- WOLFSSL_MSG("XGMTIME for to time failed.");
- return WOLFSSL_FAILURE;
- }
- }
- else if (wolfSSL_ASN1_TIME_to_tm(to, toTmGmt) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Failed to convert to time to struct tm.");
- return WOLFSSL_FAILURE;
- }
- toSecs = TimeToUnixTime(toTmGmt->tm_sec, toTmGmt->tm_min, toTmGmt->tm_hour,
- toTmGmt->tm_mday, toTmGmt->tm_mon,
- toTmGmt->tm_year + 1900);
- diffSecs = (double)(toSecs - fromSecs);
- *days = (int) (diffSecs / SECS_PER_DAY);
- *secs = (int) (diffSecs - (((double)*days) * SECS_PER_DAY));
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_ASN1_TIME_compare(const WOLFSSL_ASN1_TIME *a,
- const WOLFSSL_ASN1_TIME *b)
- {
- int ret;
- int days;
- int secs;
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_compare");
- if (wolfSSL_ASN1_TIME_diff(&days, &secs, a, b) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Failed to get time difference.");
- ret = -2;
- }
- else {
- if (days == 0 && secs == 0) {
- /* a and b are the same time. */
- ret = 0;
- }
- else if (days >= 0 && secs >= 0) {
- /* a is before b. */
- ret = -1;
- }
- else if (days <= 0 && secs <= 0) {
- /* a is after b. */
- ret = 1;
- }
- else {
- WOLFSSL_MSG("Incoherent time difference.");
- ret = -2;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_ASN1_TIME_compare", ret);
- return ret;
- }
- #endif /* !NO_ASN_TIME */
- #ifndef NO_WOLFSSL_STUB
- WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t)
- {
- WOLFSSL_STUB("wolfSSL_ASN1_TIME_set");
- (void)s;
- (void)t;
- return s;
- }
- #endif /* !NO_WOLFSSL_STUB */
- int wolfSSL_ASN1_TIME_set_string(WOLFSSL_ASN1_TIME *s, const char *str)
- {
- int slen;
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_set_string");
- if (!str) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- slen = (int)XSTRLEN(str)+1;
- if (slen > CTC_DATE_SIZE) {
- WOLFSSL_MSG("Date string too long");
- return WOLFSSL_FAILURE;
- }
- if (s) {
- XMEMCPY(s->data, str, slen);
- s->length = slen - 1; /* do not include null terminator in length */
- s->type = slen == ASN_UTC_TIME_SIZE ? V_ASN1_UTCTIME :
- V_ASN1_GENERALIZEDTIME;
- }
- return WOLFSSL_SUCCESS;
- }
- #ifndef NO_BIO
- /* Return the month as a string.
- *
- * n The number of the month as a two characters (1 based).
- * returns the month as a string.
- */
- static WC_INLINE const char* MonthStr(const char* n)
- {
- static const char monthStr[12][4] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
- return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1];
- }
- int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio,
- const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime)
- {
- const char* p;
- WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print");
- if (bio == NULL || asnTime == NULL)
- return BAD_FUNC_ARG;
- if (asnTime->type != ASN_GENERALIZED_TIME) {
- WOLFSSL_MSG("Error, not GENERALIZED_TIME");
- return WOLFSSL_FAILURE;
- }
- p = (const char *)(asnTime->data);
- /* GetTimeString not always available. */
- if (wolfSSL_BIO_write(bio, MonthStr(p + 4), 3) <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_write(bio, " ", 1) <= 0)
- return WOLFSSL_FAILURE;
- /* Day */
- if (wolfSSL_BIO_write(bio, p + 6, 2) <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_write(bio, " ", 1) <= 0)
- return WOLFSSL_FAILURE;
- /* Hour */
- if (wolfSSL_BIO_write(bio, p + 8, 2) <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_write(bio, ":", 1) <= 0)
- return WOLFSSL_FAILURE;
- /* Min */
- if (wolfSSL_BIO_write(bio, p + 10, 2) <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_write(bio, ":", 1) <= 0)
- return WOLFSSL_FAILURE;
- /* Secs */
- if (wolfSSL_BIO_write(bio, p + 12, 2) <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_write(bio, " ", 1) <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_write(bio, p, 4) <= 0)
- return WOLFSSL_FAILURE;
- return 0;
- }
- #endif /* !NO_BIO */
- void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time)
- {
- WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free");
- if (asn1Time == NULL)
- return;
- XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data));
- }
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- int wolfSSL_sk_num(const WOLFSSL_STACK* sk)
- {
- WOLFSSL_ENTER("wolfSSL_sk_num");
- if (sk == NULL)
- return 0;
- return (int)sk->num;
- }
- void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i)
- {
- WOLFSSL_ENTER("wolfSSL_sk_value");
- for (; sk != NULL && i > 0; i--)
- sk = sk->next;
- if (sk == NULL)
- return NULL;
- switch (sk->type) {
- case STACK_TYPE_X509:
- return (void*)sk->data.x509;
- case STACK_TYPE_GEN_NAME:
- return (void*)sk->data.gn;
- case STACK_TYPE_BIO:
- return (void*)sk->data.bio;
- case STACK_TYPE_OBJ:
- return (void*)sk->data.obj;
- case STACK_TYPE_STRING:
- return (void*)sk->data.string;
- case STACK_TYPE_CIPHER:
- return (void*)&sk->data.cipher;
- case STACK_TYPE_ACCESS_DESCRIPTION:
- return (void*)sk->data.access;
- case STACK_TYPE_X509_EXT:
- return (void*)sk->data.ext;
- case STACK_TYPE_X509_REQ_ATTR:
- return (void*)sk->data.generic;
- case STACK_TYPE_NULL:
- return (void*)sk->data.generic;
- case STACK_TYPE_X509_NAME:
- return (void*)sk->data.name;
- case STACK_TYPE_X509_NAME_ENTRY:
- return (void*)sk->data.name_entry;
- case STACK_TYPE_CONF_VALUE:
- #ifdef OPENSSL_EXTRA
- return (void*)sk->data.conf;
- #else
- return NULL;
- #endif
- case STACK_TYPE_X509_INFO:
- return (void*)sk->data.info;
- case STACK_TYPE_BY_DIR_entry:
- return (void*)sk->data.dir_entry;
- case STACK_TYPE_BY_DIR_hash:
- return (void*)sk->data.dir_hash;
- case STACK_TYPE_X509_OBJ:
- return (void*)sk->data.x509_obj;
- case STACK_TYPE_DIST_POINT:
- return (void*)sk->data.dp;
- case STACK_TYPE_X509_CRL:
- return (void*)sk->data.crl;
- default:
- return (void*)sk->data.generic;
- }
- }
- /* copies over data of "in" to "out" */
- static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out)
- {
- if (in == NULL || out == NULL)
- return;
- *out = *in;
- }
- WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk)
- {
- WOLFSSL_STACK* ret = NULL;
- WOLFSSL_STACK* last = NULL;
- WOLFSSL_ENTER("wolfSSL_sk_dup");
- while (sk) {
- WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap);
- if (!cur) {
- WOLFSSL_MSG("wolfSSL_sk_new_node error");
- goto error;
- }
- if (!ret) {
- /* Set first node */
- ret = cur;
- }
- if (last) {
- last->next = cur;
- }
- XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK));
- /* We will allocate new memory for this */
- XMEMSET(&cur->data, 0, sizeof(cur->data));
- cur->next = NULL;
- switch (sk->type) {
- case STACK_TYPE_X509:
- if (!sk->data.x509)
- break;
- cur->data.x509 = wolfSSL_X509_dup(sk->data.x509);
- if (!cur->data.x509) {
- WOLFSSL_MSG("wolfSSL_X509_dup error");
- goto error;
- }
- break;
- case STACK_TYPE_CIPHER:
- wolfSSL_CIPHER_copy(&sk->data.cipher, &cur->data.cipher);
- break;
- case STACK_TYPE_GEN_NAME:
- if (!sk->data.gn)
- break;
- cur->data.gn = wolfSSL_GENERAL_NAME_dup(sk->data.gn);
- if (!cur->data.gn) {
- WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error");
- goto error;
- }
- break;
- case STACK_TYPE_OBJ:
- if (!sk->data.obj)
- break;
- cur->data.obj = wolfSSL_ASN1_OBJECT_dup(sk->data.obj);
- if (!cur->data.obj) {
- WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup error");
- goto error;
- }
- break;
- case STACK_TYPE_BIO:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- WOLFSSL_MSG("Unsupported stack type");
- goto error;
- }
- sk = sk->next;
- last = cur;
- }
- return ret;
- error:
- if (ret) {
- wolfSSL_sk_GENERAL_NAME_free(ret);
- }
- return NULL;
- }
- /* Free the just the stack structure */
- void wolfSSL_sk_free(WOLFSSL_STACK* sk)
- {
- WOLFSSL_ENTER("wolfSSL_sk_free");
- while (sk != NULL) {
- WOLFSSL_STACK* next = sk->next;
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = next;
- }
- }
- /* Frees each node in the stack and frees the stack.
- */
- void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk,
- void (*f) (void*))
- {
- WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free");
- wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
- }
- /* return 1 on success 0 on fail */
- int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic)
- {
- WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push");
- return wolfSSL_sk_push(sk, generic);
- }
- void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk)
- {
- wolfSSL_sk_free(sk);
- }
- /* Free all nodes in a stack including the pushed objects */
- void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
- wolfSSL_sk_freefunc func)
- {
- WOLFSSL_ENTER("wolfSSL_sk_pop_free");
- if (sk == NULL) {
- /* pop_free can be called with NULL, do not print bad argument */
- return;
- }
- #if defined(WOLFSSL_QT)
- /* In Qt v15.5, it calls OPENSSL_sk_free(xxx, OPENSSL_sk_free).
- * By using OPENSSL_sk_free for free causes access violation.
- * Therefore, switching free func to wolfSSL_ACCESS_DESCRIPTION_free
- * is needed even the func isn't NULL.
- */
- if (sk->type == STACK_TYPE_ACCESS_DESCRIPTION) {
- func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
- }
- #endif
- if (func == NULL) {
- switch(sk->type) {
- case STACK_TYPE_ACCESS_DESCRIPTION:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
- #endif
- break;
- case STACK_TYPE_X509:
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_free;
- break;
- case STACK_TYPE_X509_OBJ:
- #ifdef OPENSSL_ALL
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_OBJECT_free;
- #endif
- break;
- case STACK_TYPE_OBJ:
- func = (wolfSSL_sk_freefunc)wolfSSL_ASN1_OBJECT_free;
- break;
- case STACK_TYPE_DIST_POINT:
- #ifdef OPENSSL_EXTRA
- func = (wolfSSL_sk_freefunc)wolfSSL_DIST_POINT_free;
- #endif
- break;
- case STACK_TYPE_GEN_NAME:
- func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free;
- break;
- case STACK_TYPE_STRING:
- #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
- defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_WOLFSSL_STRING_free;
- #endif
- break;
- case STACK_TYPE_X509_NAME:
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
- && !defined(WOLFCRYPT_ONLY)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_free;
- #endif
- break;
- case STACK_TYPE_X509_NAME_ENTRY:
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
- && !defined(WOLFCRYPT_ONLY)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_ENTRY_free;
- #endif
- break;
- case STACK_TYPE_X509_EXT:
- #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_EXTENSION_free;
- #endif
- break;
- case STACK_TYPE_X509_REQ_ATTR:
- #if defined(OPENSSL_ALL) && \
- (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_ATTRIBUTE_free;
- #endif
- break;
- case STACK_TYPE_CONF_VALUE:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509V3_conf_free;
- #endif
- break;
- case STACK_TYPE_X509_INFO:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_INFO_free;
- #endif
- break;
- case STACK_TYPE_BIO:
- #if !defined(NO_BIO) && defined(OPENSSL_EXTRA)
- func = (wolfSSL_sk_freefunc)wolfSSL_BIO_vfree;
- #endif
- break;
- case STACK_TYPE_BY_DIR_entry:
- #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
- func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_entry_free;
- #endif
- break;
- case STACK_TYPE_BY_DIR_hash:
- #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
- func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_HASH_free;
- #endif
- break;
- case STACK_TYPE_X509_CRL:
- #if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_CRL_free;
- #endif
- break;
- case STACK_TYPE_CIPHER:
- case STACK_TYPE_NULL:
- default:
- break;
- }
- }
- while (sk != NULL) {
- WOLFSSL_STACK* next = sk->next;
- if (func != NULL) {
- if (sk->type != STACK_TYPE_CIPHER)
- func(sk->data.generic);
- }
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = next;
- }
- }
- /* Creates and returns a new null stack. */
- WOLFSSL_STACK* wolfSSL_sk_new_null(void)
- {
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_null");
- sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (sk == NULL) {
- WOLFSSL_MSG("WOLFSSL_STACK memory error");
- return NULL;
- }
- XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
- sk->type = STACK_TYPE_NULL;
- return sk;
- }
- int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk)
- {
- if (sk == NULL)
- return 0;
- return (int)sk->num;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- #if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \
- defined(HAVE_EXT_CACHE))
- /* stunnel 4.28 needs
- *
- * Callback that is called if a session tries to resume but could not find
- * the session to resume it.
- */
- void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
- WOLFSSL_SESSION*(*f)(WOLFSSL*, const unsigned char*, int, int*))
- {
- if (ctx == NULL)
- return;
- #ifdef HAVE_EXT_CACHE
- ctx->get_sess_cb = f;
- #else
- (void)f;
- #endif
- }
- void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx,
- int (*f)(WOLFSSL*, WOLFSSL_SESSION*))
- {
- if (ctx == NULL)
- return;
- #ifdef HAVE_EXT_CACHE
- ctx->new_sess_cb = f;
- #else
- (void)f;
- #endif
- }
- void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*,
- WOLFSSL_SESSION*))
- {
- if (ctx == NULL)
- return;
- #if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
- ctx->rem_sess_cb = f;
- #else
- (void)f;
- #endif
- }
- /*
- *
- * Note: It is expected that the importing and exporting function have been
- * built with the same settings. For example if session tickets was
- * enabled with the wolfSSL library exporting a session then it is
- * expected to be turned on with the wolfSSL library importing the session.
- */
- int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p)
- {
- int size = 0;
- #ifdef HAVE_EXT_CACHE
- int idx = 0;
- #ifdef SESSION_CERTS
- int i;
- #endif
- unsigned char *data;
- WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION");
- sess = ClientSessionToSession(sess);
- if (sess == NULL) {
- return BAD_FUNC_ARG;
- }
- /* side | bornOn | timeout | sessionID len | sessionID | masterSecret |
- * haveEMS */
- size += OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN +
- sess->sessionIDSz + SECRET_LEN + OPAQUE8_LEN;
- /* altSessionID */
- size += OPAQUE8_LEN + (sess->haveAltSessionID ? ID_LEN : 0);
- #ifdef SESSION_CERTS
- /* Peer chain */
- size += OPAQUE8_LEN;
- for (i = 0; i < sess->chain.count; i++)
- size += OPAQUE16_LEN + sess->chain.certs[i].length;
- #endif
- #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
- defined(HAVE_SESSION_TICKET))
- /* Protocol version */
- size += OPAQUE16_LEN;
- #endif
- #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
- /* cipher suite */
- size += OPAQUE16_LEN;
- #endif
- #ifndef NO_CLIENT_CACHE
- /* ServerID len | ServerID */
- size += OPAQUE16_LEN + sess->idLen;
- #endif
- #ifdef OPENSSL_EXTRA
- /* session context ID len | session context ID */
- size += OPAQUE8_LEN + sess->sessionCtxSz;
- #endif
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- /* peerVerifyRet */
- size += OPAQUE8_LEN;
- #endif
- #ifdef WOLFSSL_TLS13
- /* namedGroup */
- size += OPAQUE16_LEN;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- #ifdef WOLFSSL_TLS13
- /* ticketSeen | ticketAdd */
- size += OPAQUE32_LEN + OPAQUE32_LEN;
- /* ticketNonce */
- size += OPAQUE8_LEN + sess->ticketNonce.len;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- size += OPAQUE32_LEN;
- #endif
- #endif
- #ifdef HAVE_SESSION_TICKET
- /* ticket len | ticket */
- size += OPAQUE16_LEN + sess->ticketLen;
- #endif
- if (p != NULL) {
- if (*p == NULL)
- *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL);
- if (*p == NULL)
- return 0;
- data = *p;
- data[idx++] = sess->side;
- c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN;
- c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN;
- data[idx++] = sess->sessionIDSz;
- XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz);
- idx += sess->sessionIDSz;
- XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN;
- data[idx++] = (byte)sess->haveEMS;
- data[idx++] = sess->haveAltSessionID ? ID_LEN : 0;
- if (sess->haveAltSessionID) {
- XMEMCPY(data + idx, sess->altSessionID, ID_LEN);
- idx += ID_LEN;
- }
- #ifdef SESSION_CERTS
- data[idx++] = (byte)sess->chain.count;
- for (i = 0; i < sess->chain.count; i++) {
- c16toa((word16)sess->chain.certs[i].length, data + idx);
- idx += OPAQUE16_LEN;
- XMEMCPY(data + idx, sess->chain.certs[i].buffer,
- sess->chain.certs[i].length);
- idx += sess->chain.certs[i].length;
- }
- #endif
- #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
- defined(HAVE_SESSION_TICKET))
- data[idx++] = sess->version.major;
- data[idx++] = sess->version.minor;
- #endif
- #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
- data[idx++] = sess->cipherSuite0;
- data[idx++] = sess->cipherSuite;
- #endif
- #ifndef NO_CLIENT_CACHE
- c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN;
- XMEMCPY(data + idx, sess->serverID, sess->idLen);
- idx += sess->idLen;
- #endif
- #ifdef OPENSSL_EXTRA
- data[idx++] = sess->sessionCtxSz;
- XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz);
- idx += sess->sessionCtxSz;
- #endif
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- data[idx++] = sess->peerVerifyRet;
- #endif
- #ifdef WOLFSSL_TLS13
- c16toa(sess->namedGroup, data + idx);
- idx += OPAQUE16_LEN;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- #ifdef WOLFSSL_TLS13
- c32toa(sess->ticketSeen, data + idx);
- idx += OPAQUE32_LEN;
- c32toa(sess->ticketAdd, data + idx);
- idx += OPAQUE32_LEN;
- data[idx++] = sess->ticketNonce.len;
- XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len);
- idx += sess->ticketNonce.len;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- c32toa(sess->maxEarlyDataSz, data + idx);
- idx += OPAQUE32_LEN;
- #endif
- #endif
- #ifdef HAVE_SESSION_TICKET
- c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN;
- XMEMCPY(data + idx, sess->ticket, sess->ticketLen);
- idx += sess->ticketLen;
- #endif
- }
- #endif
- (void)sess;
- (void)p;
- #ifdef HAVE_EXT_CACHE
- (void)idx;
- #endif
- return size;
- }
- /* TODO: no function to free new session.
- *
- * Note: It is expected that the importing and exporting function have been
- * built with the same settings. For example if session tickets was
- * enabled with the wolfSSL library exporting a session then it is
- * expected to be turned on with the wolfSSL library importing the session.
- */
- WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
- const unsigned char** p, long i)
- {
- WOLFSSL_SESSION* s = NULL;
- int ret = 0;
- #if defined(HAVE_EXT_CACHE)
- int idx;
- byte* data;
- #ifdef SESSION_CERTS
- int j;
- word16 length;
- #endif
- #endif /* HAVE_EXT_CACHE */
- (void)p;
- (void)i;
- (void)ret;
- (void)sess;
- #ifdef HAVE_EXT_CACHE
- if (p == NULL || *p == NULL)
- return NULL;
- s = wolfSSL_SESSION_new();
- if (s == NULL)
- return NULL;
- idx = 0;
- data = (byte*)*p;
- /* side | bornOn | timeout | sessionID len */
- if (i < OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->side = data[idx++];
- ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN;
- ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN;
- s->sessionIDSz = data[idx++];
- /* sessionID | secret | haveEMS | haveAltSessionID */
- if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN + OPAQUE8_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->sessionID, data + idx, s->sessionIDSz);
- idx += s->sessionIDSz;
- XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN;
- s->haveEMS = data[idx++];
- if (data[idx] != ID_LEN && data[idx] != 0) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->haveAltSessionID = data[idx++] == ID_LEN;
- /* altSessionID */
- if (s->haveAltSessionID) {
- if (i - idx < ID_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->altSessionID, data + idx, ID_LEN); idx += ID_LEN;
- }
- #ifdef SESSION_CERTS
- /* Certificate chain */
- if (i - idx == 0) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->chain.count = data[idx++];
- for (j = 0; j < s->chain.count; j++) {
- if (i - idx < OPAQUE16_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- ato16(data + idx, &length); idx += OPAQUE16_LEN;
- s->chain.certs[j].length = length;
- if (i - idx < length) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->chain.certs[j].buffer, data + idx, length);
- idx += length;
- }
- #endif
- #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
- defined(HAVE_SESSION_TICKET))
- /* Protocol Version */
- if (i - idx < OPAQUE16_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->version.major = data[idx++];
- s->version.minor = data[idx++];
- #endif
- #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
- /* Cipher suite */
- if (i - idx < OPAQUE16_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->cipherSuite0 = data[idx++];
- s->cipherSuite = data[idx++];
- #endif
- #ifndef NO_CLIENT_CACHE
- /* ServerID len */
- if (i - idx < OPAQUE16_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN;
- /* ServerID */
- if (i - idx < s->idLen) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen;
- #endif
- #ifdef OPENSSL_EXTRA
- /* byte for length of session context ID */
- if (i - idx < OPAQUE8_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->sessionCtxSz = data[idx++];
- /* app session context ID */
- if (i - idx < s->sessionCtxSz) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz;
- #endif
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- /* byte for peerVerifyRet */
- if (i - idx < OPAQUE8_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->peerVerifyRet = data[idx++];
- #endif
- #ifdef WOLFSSL_TLS13
- if (i - idx < OPAQUE16_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- ato16(data + idx, &s->namedGroup);
- idx += OPAQUE16_LEN;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- #ifdef WOLFSSL_TLS13
- if (i - idx < (OPAQUE32_LEN * 2)) {
- ret = BUFFER_ERROR;
- goto end;
- }
- ato32(data + idx, &s->ticketSeen);
- idx += OPAQUE32_LEN;
- ato32(data + idx, &s->ticketAdd);
- idx += OPAQUE32_LEN;
- if (i - idx < OPAQUE8_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- s->ticketNonce.len = data[idx++];
- if (i - idx < s->ticketNonce.len) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->ticketNonce.data, data + idx, s->ticketNonce.len);
- idx += s->ticketNonce.len;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- if (i - idx < OPAQUE32_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- ato32(data + idx, &s->maxEarlyDataSz);
- idx += OPAQUE32_LEN;
- #endif
- #endif
- #ifdef HAVE_SESSION_TICKET
- /* ticket len */
- if (i - idx < OPAQUE16_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN;
- /* Dispose of ol dynamic ticket and ensure space for new ticket. */
- if (s->ticketLenAlloc > 0) {
- XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
- }
- if (s->ticketLen <= SESSION_TICKET_LEN)
- s->ticket = s->staticTicket;
- else {
- s->ticket = (byte*)XMALLOC(s->ticketLen, NULL,
- DYNAMIC_TYPE_SESSION_TICK);
- if (s->ticket == NULL) {
- ret = MEMORY_ERROR;
- goto end;
- }
- s->ticketLenAlloc = (word16)s->ticketLen;
- }
- /* ticket */
- if (i - idx < s->ticketLen) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen;
- #endif
- (void)idx;
- if (sess != NULL) {
- *sess = s;
- }
- *p += idx;
- end:
- if (ret != 0 && (sess == NULL || *sess != s)) {
- wolfSSL_SESSION_free(s);
- s = NULL;
- }
- #endif /* HAVE_EXT_CACHE */
- return s;
- }
- /* Check if there is a session ticket associated with this WOLFSSL_SESSION.
- *
- * sess - pointer to WOLFSSL_SESSION struct
- *
- * Returns 1 if has session ticket, otherwise 0 */
- int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess)
- {
- WOLFSSL_ENTER("wolfSSL_SESSION_has_ticket");
- #ifdef HAVE_SESSION_TICKET
- sess = ClientSessionToSession(sess);
- if (sess) {
- if ((sess->ticketLen > 0) && (sess->ticket != NULL)) {
- return WOLFSSL_SUCCESS;
- }
- }
- #else
- (void)sess;
- #endif
- return WOLFSSL_FAILURE;
- }
- unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint(
- const WOLFSSL_SESSION* sess)
- {
- WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint");
- sess = ClientSessionToSession(sess);
- if (sess) {
- return sess->timeout;
- }
- return 0;
- }
- long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess)
- {
- long timeout = 0;
- WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout");
- sess = ClientSessionToSession(sess);
- if (sess)
- timeout = sess->timeout;
- return timeout;
- }
- long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
- {
- long bornOn = 0;
- WOLFSSL_ENTER("wolfSSL_SESSION_get_time");
- sess = ClientSessionToSession(sess);
- if (sess)
- bornOn = sess->bornOn;
- return bornOn;
- }
- long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
- {
- word32 tmptime;
- ses = ClientSessionToSession(ses);
- if (ses == NULL || t < 0) {
- return BAD_FUNC_ARG;
- }
- tmptime = t & 0xFFFFFFFF;
- ses->timeout = tmptime;
- return WOLFSSL_SUCCESS;
- }
- #endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */
- #ifdef OPENSSL_EXTRA
- #if defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM)
- int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
- {
- int ret = WOLFSSL_FATAL_ERROR;
- WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file");
- if (ssl != NULL && fname != NULL)
- {
- #ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
- #else
- byte staticBuffer[FILE_BUFFER_SIZE];
- #endif
- byte* myBuffer = staticBuffer;
- int dynamic = 0;
- XFILE file;
- long sz = 0;
- WOLFSSL_CTX* ctx = ssl->ctx;
- WOLFSSL_X509* peer_cert = &ssl->peerCert;
- DerBuffer* fileDer = NULL;
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE)
- return WOLFSSL_BAD_FILE;
- if (XFSEEK(file, 0, XSEEK_END) != 0) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- sz = XFTELL(file);
- XREWIND(file);
- if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
- WOLFSSL_MSG("cmp_peer_cert_to_file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- if (sz > (long)sizeof(staticBuffer)) {
- WOLFSSL_MSG("Getting dynamic buffer");
- myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
- dynamic = 1;
- }
- if ((myBuffer != NULL) &&
- (sz > 0) &&
- (XFREAD(myBuffer, 1, sz, file) == (size_t)sz) &&
- (PemToDer(myBuffer, (long)sz, CERT_TYPE,
- &fileDer, ctx->heap, NULL, NULL) == 0) &&
- (fileDer->length != 0) &&
- (fileDer->length == peer_cert->derCert->length) &&
- (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer,
- fileDer->length) == 0))
- {
- ret = 0;
- }
- FreeDer(&fileDer);
- if (dynamic)
- XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
- XFCLOSE(file);
- }
- return ret;
- }
- #endif
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
- #ifndef NO_CERTS
- /* oidCertExtType */
- { NID_basic_constraints, BASIC_CA_OID, oidCertExtType, "basicConstraints",
- "X509v3 Basic Constraints"},
- { NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName",
- "X509v3 Subject Alternative Name"},
- { NID_crl_distribution_points, CRL_DIST_OID, oidCertExtType, "crlDistributionPoints",
- "X509v3 CRL Distribution Points"},
- { NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess",
- "Authority Information Access"},
- { NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType,
- "authorityKeyIdentifier", "X509v3 Authority Key Identifier"},
- { NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType,
- "subjectKeyIdentifier", "X509v3 Subject Key Identifier"},
- { NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage",
- "X509v3 Key Usage"},
- { NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType,
- "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"},
- { NID_ext_key_usage, EXT_KEY_USAGE_OID, oidCertExtType,
- "extendedKeyUsage", "X509v3 Extended Key Usage"},
- { NID_name_constraints, NAME_CONS_OID, oidCertExtType,
- "nameConstraints", "X509v3 Name Constraints"},
- { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType,
- "certificatePolicies", "X509v3 Certificate Policies"},
- /* oidCertAuthInfoType */
- { NID_ad_OCSP, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP",
- "OCSP"},
- { NID_ad_ca_issuers, AIA_CA_ISSUER_OID, oidCertAuthInfoType,
- "caIssuers", "CA Issuers"},
- /* oidCertPolicyType */
- { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy",
- "X509v3 Any Policy"},
- /* oidCertAltNameType */
- { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""},
- /* oidCertKeyUseType */
- { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType,
- "anyExtendedKeyUsage", "Any Extended Key Usage"},
- { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType,
- "serverAuth", "TLS Web Server Authentication"},
- { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType,
- "clientAuth", "TLS Web Client Authentication"},
- { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType,
- "OCSPSigning", "OCSP Signing"},
- /* oidCertNameType */
- { NID_commonName, NID_commonName, oidCertNameType, "CN", "commonName"},
- { NID_surname, NID_surname, oidCertNameType, "SN", "surname"},
- { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber",
- "serialNumber"},
- { NID_userId, NID_userId, oidCertNameType, "UID", "userid"},
- { NID_countryName, NID_countryName, oidCertNameType, "C", "countryName"},
- { NID_localityName, NID_localityName, oidCertNameType, "L", "localityName"},
- { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, "ST",
- "stateOrProvinceName"},
- { NID_streetAddress, NID_streetAddress, oidCertNameType, "street",
- "streetAddress"},
- { NID_organizationName, NID_organizationName, oidCertNameType, "O",
- "organizationName"},
- { NID_organizationalUnitName, NID_organizationalUnitName, oidCertNameType,
- "OU", "organizationalUnitName"},
- { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress",
- "emailAddress"},
- { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC",
- "domainComponent"},
- { NID_favouriteDrink, NID_favouriteDrink, oidCertNameType, "favouriteDrink",
- "favouriteDrink"},
- { NID_businessCategory, NID_businessCategory, oidCertNameType, "businessCategory",
- "businessCategory"},
- { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, "jurisdictionC",
- "jurisdictionCountryName"},
- { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName,
- oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"},
- { NID_postalCode, NID_postalCode, oidCertNameType, "postalCode", "postalCode"},
- { NID_userId, NID_userId, oidCertNameType, "UID", "userId"},
- #ifdef WOLFSSL_CERT_REQ
- { NID_pkcs9_challengePassword, CHALLENGE_PASSWORD_OID,
- oidCsrAttrType, "challengePassword", "challengePassword"},
- { NID_pkcs9_contentType, PKCS9_CONTENT_TYPE_OID,
- oidCsrAttrType, "contentType", "contentType" },
- { NID_pkcs9_unstructuredName, UNSTRUCTURED_NAME_OID,
- oidCsrAttrType, "unstructuredName", "unstructuredName" },
- { NID_name, NAME_OID, oidCsrAttrType, "name", "name" },
- { NID_surname, SURNAME_OID,
- oidCsrAttrType, "surname", "surname" },
- { NID_givenName, GIVEN_NAME_OID,
- oidCsrAttrType, "givenName", "givenName" },
- { NID_initials, INITIALS_OID,
- oidCsrAttrType, "initials", "initials" },
- { NID_dnQualifier, DNQUALIFIER_OID,
- oidCsrAttrType, "dnQualifer", "dnQualifier" },
- #endif
- #endif
- #ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */
- /* oidHashType */
- #ifdef WOLFSSL_MD2
- { NID_md2, MD2h, oidHashType, "MD2", "md2"},
- #endif
- #ifdef WOLFSSL_MD5
- { NID_md5, MD5h, oidHashType, "MD5", "md5"},
- #endif
- #ifndef NO_SHA
- { NID_sha1, SHAh, oidHashType, "SHA1", "sha1"},
- #endif
- #ifdef WOLFSSL_SHA224
- { NID_sha224, SHA224h, oidHashType, "SHA224", "sha224"},
- #endif
- #ifndef NO_SHA256
- { NID_sha256, SHA256h, oidHashType, "SHA256", "sha256"},
- #endif
- #ifdef WOLFSSL_SHA384
- { NID_sha384, SHA384h, oidHashType, "SHA384", "sha384"},
- #endif
- #ifdef WOLFSSL_SHA512
- { NID_sha512, SHA512h, oidHashType, "SHA512", "sha512"},
- #endif
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- { NID_sha3_224, SHA3_224h, oidHashType, "SHA3-224", "sha3-224"},
- #endif
- #ifndef WOLFSSL_NOSHA3_256
- { NID_sha3_256, SHA3_256h, oidHashType, "SHA3-256", "sha3-256"},
- #endif
- #ifndef WOLFSSL_NOSHA3_384
- { NID_sha3_384, SHA3_384h, oidHashType, "SHA3-384", "sha3-384"},
- #endif
- #ifndef WOLFSSL_NOSHA3_512
- { NID_sha3_512, SHA3_512h, oidHashType, "SHA3-512", "sha3-512"},
- #endif
- #endif /* WOLFSSL_SHA3 */
- /* oidSigType */
- #ifndef NO_DSA
- #ifndef NO_SHA
- { NID_dsaWithSHA1, CTC_SHAwDSA, oidSigType, "DSA-SHA1", "dsaWithSHA1"},
- { NID_dsa_with_SHA256, CTC_SHA256wDSA, oidSigType, "dsa_with_SHA256",
- "dsa_with_SHA256"},
- #endif
- #endif /* NO_DSA */
- #ifndef NO_RSA
- #ifdef WOLFSSL_MD2
- { NID_md2WithRSAEncryption, CTC_MD2wRSA, oidSigType, "RSA-MD2",
- "md2WithRSAEncryption"},
- #endif
- #ifndef NO_MD5
- { NID_md5WithRSAEncryption, CTC_MD5wRSA, oidSigType, "RSA-MD5",
- "md5WithRSAEncryption"},
- #endif
- #ifndef NO_SHA
- { NID_sha1WithRSAEncryption, CTC_SHAwRSA, oidSigType, "RSA-SHA1",
- "sha1WithRSAEncryption"},
- #endif
- #ifdef WOLFSSL_SHA224
- { NID_sha224WithRSAEncryption, CTC_SHA224wRSA, oidSigType, "RSA-SHA224",
- "sha224WithRSAEncryption"},
- #endif
- #ifndef NO_SHA256
- { NID_sha256WithRSAEncryption, CTC_SHA256wRSA, oidSigType, "RSA-SHA256",
- "sha256WithRSAEncryption"},
- #endif
- #ifdef WOLFSSL_SHA384
- { NID_sha384WithRSAEncryption, CTC_SHA384wRSA, oidSigType, "RSA-SHA384",
- "sha384WithRSAEncryption"},
- #endif
- #ifdef WOLFSSL_SHA512
- { NID_sha512WithRSAEncryption, CTC_SHA512wRSA, oidSigType, "RSA-SHA512",
- "sha512WithRSAEncryption"},
- #endif
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- { NID_RSA_SHA3_224, CTC_SHA3_224wRSA, oidSigType, "RSA-SHA3-224",
- "sha3-224WithRSAEncryption"},
- #endif
- #ifndef WOLFSSL_NOSHA3_256
- { NID_RSA_SHA3_256, CTC_SHA3_256wRSA, oidSigType, "RSA-SHA3-256",
- "sha3-256WithRSAEncryption"},
- #endif
- #ifndef WOLFSSL_NOSHA3_384
- { NID_RSA_SHA3_384, CTC_SHA3_384wRSA, oidSigType, "RSA-SHA3-384",
- "sha3-384WithRSAEncryption"},
- #endif
- #ifndef WOLFSSL_NOSHA3_512
- { NID_RSA_SHA3_512, CTC_SHA3_512wRSA, oidSigType, "RSA-SHA3-512",
- "sha3-512WithRSAEncryption"},
- #endif
- #endif
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- #ifndef NO_SHA
- { NID_ecdsa_with_SHA1, CTC_SHAwECDSA, oidSigType, "ecdsa-with-SHA1", "shaWithECDSA"},
- #endif
- #ifdef WOLFSSL_SHA224
- { NID_ecdsa_with_SHA224, CTC_SHA224wECDSA, oidSigType, "ecdsa-with-SHA224","sha224WithECDSA"},
- #endif
- #ifndef NO_SHA256
- { NID_ecdsa_with_SHA256, CTC_SHA256wECDSA, oidSigType, "ecdsa-with-SHA256","sha256WithECDSA"},
- #endif
- #ifdef WOLFSSL_SHA384
- { NID_ecdsa_with_SHA384, CTC_SHA384wECDSA, oidSigType, "ecdsa-with-SHA384","sha384WithECDSA"},
- #endif
- #ifdef WOLFSSL_SHA512
- { NID_ecdsa_with_SHA512, CTC_SHA512wECDSA, oidSigType, "ecdsa-with-SHA512","sha512WithECDSA"},
- #endif
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- { NID_ecdsa_with_SHA3_224, CTC_SHA3_224wECDSA, oidSigType, "id-ecdsa-with-SHA3-224",
- "ecdsa_with_SHA3-224"},
- #endif
- #ifndef WOLFSSL_NOSHA3_256
- { NID_ecdsa_with_SHA3_256, CTC_SHA3_256wECDSA, oidSigType, "id-ecdsa-with-SHA3-256",
- "ecdsa_with_SHA3-256"},
- #endif
- #ifndef WOLFSSL_NOSHA3_384
- { NID_ecdsa_with_SHA3_384, CTC_SHA3_384wECDSA, oidSigType, "id-ecdsa-with-SHA3-384",
- "ecdsa_with_SHA3-384"},
- #endif
- #ifndef WOLFSSL_NOSHA3_512
- { NID_ecdsa_with_SHA3_512, CTC_SHA3_512wECDSA, oidSigType, "id-ecdsa-with-SHA3-512",
- "ecdsa_with_SHA3-512"},
- #endif
- #endif
- #endif /* HAVE_ECC */
- /* oidKeyType */
- #ifndef NO_DSA
- { NID_dsa, DSAk, oidKeyType, "DSA", "dsaEncryption"},
- #endif /* NO_DSA */
- #ifndef NO_RSA
- { NID_rsaEncryption, RSAk, oidKeyType, "rsaEncryption", "rsaEncryption"},
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- { NID_X9_62_id_ecPublicKey, ECDSAk, oidKeyType, "id-ecPublicKey",
- "id-ecPublicKey"},
- #endif /* HAVE_ECC */
- #ifndef NO_DH
- { NID_dhKeyAgreement, DHk, oidKeyType, "dhKeyAgreement", "dhKeyAgreement"},
- #endif
- #ifdef HAVE_ED448
- { NID_ED448, ED448k, oidKeyType, "ED448", "ED448"},
- #endif
- #ifdef HAVE_ED25519
- { NID_ED25519, ED25519k, oidKeyType, "ED25519", "ED25519"},
- #endif
- #ifdef HAVE_PQC
- #ifdef HAVE_FALCON
- { CTC_FALCON_LEVEL1, FALCON_LEVEL1k, oidKeyType, "Falcon Level 1",
- "Falcon Level 1"},
- { CTC_FALCON_LEVEL5, FALCON_LEVEL5k, oidKeyType, "Falcon Level 5",
- "Falcon Level 5"},
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- { CTC_DILITHIUM_LEVEL2, DILITHIUM_LEVEL2k, oidKeyType,
- "Dilithium Level 2", "Dilithium Level 2"},
- { CTC_DILITHIUM_LEVEL3, DILITHIUM_LEVEL3k, oidKeyType,
- "Dilithium Level 3", "Dilithium Level 3"},
- { CTC_DILITHIUM_LEVEL5, DILITHIUM_LEVEL5k, oidKeyType,
- "Dilithium Level 5", "Dilithium Level 5"},
- { CTC_DILITHIUM_AES_LEVEL2, DILITHIUM_AES_LEVEL2k, oidKeyType,
- "Dilithium AES Level 2", "Dilithium AES Level 2"},
- { CTC_DILITHIUM_AES_LEVEL3, DILITHIUM_AES_LEVEL3k, oidKeyType,
- "Dilithium AES Level 3", "Dilithium AES Level 3"},
- { CTC_DILITHIUM_AES_LEVEL5, DILITHIUM_AES_LEVEL5k, oidKeyType,
- "Dilithium AES Level 5", "Dilithium AES Level 5"},
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- /* oidCurveType */
- #ifdef HAVE_ECC
- { NID_X9_62_prime192v1, ECC_SECP192R1_OID, oidCurveType, "prime192v1", "prime192v1"},
- { NID_X9_62_prime192v2, ECC_PRIME192V2_OID, oidCurveType, "prime192v2", "prime192v2"},
- { NID_X9_62_prime192v3, ECC_PRIME192V3_OID, oidCurveType, "prime192v3", "prime192v3"},
- { NID_X9_62_prime239v1, ECC_PRIME239V1_OID, oidCurveType, "prime239v1", "prime239v1"},
- { NID_X9_62_prime239v2, ECC_PRIME239V2_OID, oidCurveType, "prime239v2", "prime239v2"},
- { NID_X9_62_prime239v3, ECC_PRIME239V3_OID, oidCurveType, "prime239v3", "prime239v3"},
- { NID_X9_62_prime256v1, ECC_SECP256R1_OID, oidCurveType, "prime256v1", "prime256v1"},
- { NID_secp112r1, ECC_SECP112R1_OID, oidCurveType, "secp112r1", "secp112r1"},
- { NID_secp112r2, ECC_SECP112R2_OID, oidCurveType, "secp112r2", "secp112r2"},
- { NID_secp128r1, ECC_SECP128R1_OID, oidCurveType, "secp128r1", "secp128r1"},
- { NID_secp128r2, ECC_SECP128R2_OID, oidCurveType, "secp128r2", "secp128r2"},
- { NID_secp160r1, ECC_SECP160R1_OID, oidCurveType, "secp160r1", "secp160r1"},
- { NID_secp160r2, ECC_SECP160R2_OID, oidCurveType, "secp160r2", "secp160r2"},
- { NID_secp224r1, ECC_SECP224R1_OID, oidCurveType, "secp224r1", "secp224r1"},
- { NID_secp384r1, ECC_SECP384R1_OID, oidCurveType, "secp384r1", "secp384r1"},
- { NID_secp521r1, ECC_SECP521R1_OID, oidCurveType, "secp521r1", "secp521r1"},
- { NID_secp160k1, ECC_SECP160K1_OID, oidCurveType, "secp160k1", "secp160k1"},
- { NID_secp192k1, ECC_SECP192K1_OID, oidCurveType, "secp192k1", "secp192k1"},
- { NID_secp224k1, ECC_SECP224K1_OID, oidCurveType, "secp224k1", "secp224k1"},
- { NID_secp256k1, ECC_SECP256K1_OID, oidCurveType, "secp256k1", "secp256k1"},
- { NID_brainpoolP160r1, ECC_BRAINPOOLP160R1_OID, oidCurveType, "brainpoolP160r1", "brainpoolP160r1"},
- { NID_brainpoolP192r1, ECC_BRAINPOOLP192R1_OID, oidCurveType, "brainpoolP192r1", "brainpoolP192r1"},
- { NID_brainpoolP224r1, ECC_BRAINPOOLP224R1_OID, oidCurveType, "brainpoolP224r1", "brainpoolP224r1"},
- { NID_brainpoolP256r1, ECC_BRAINPOOLP256R1_OID, oidCurveType, "brainpoolP256r1", "brainpoolP256r1"},
- { NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID, oidCurveType, "brainpoolP320r1", "brainpoolP320r1"},
- { NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID, oidCurveType, "brainpoolP384r1", "brainpoolP384r1"},
- { NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID, oidCurveType, "brainpoolP512r1", "brainpoolP512r1"},
- #endif /* HAVE_ECC */
- /* oidBlkType */
- #ifdef WOLFSSL_AES_128
- { AES128CBCb, AES128CBCb, oidBlkType, "AES-128-CBC", "aes-128-cbc"},
- #endif
- #ifdef WOLFSSL_AES_192
- { AES192CBCb, AES192CBCb, oidBlkType, "AES-192-CBC", "aes-192-cbc"},
- #endif
- #ifdef WOLFSSL_AES_256
- { AES256CBCb, AES256CBCb, oidBlkType, "AES-256-CBC", "aes-256-cbc"},
- #endif
- #ifndef NO_DES3
- { NID_des, DESb, oidBlkType, "DES-CBC", "des-cbc"},
- { NID_des3, DES3b, oidBlkType, "DES-EDE3-CBC", "des-ede3-cbc"},
- #endif /* !NO_DES3 */
- #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
- { NID_chacha20_poly1305, NID_chacha20_poly1305, oidBlkType, "ChaCha20-Poly1305", "chacha20-poly1305"},
- #endif
- /* oidOcspType */
- #ifdef HAVE_OCSP
- { NID_id_pkix_OCSP_basic, OCSP_BASIC_OID, oidOcspType, "basicOCSPResponse",
- "Basic OCSP Response"},
- { OCSP_NONCE_OID, OCSP_NONCE_OID, oidOcspType, "Nonce",
- "OCSP Nonce"},
- #endif /* HAVE_OCSP */
- #ifndef NO_PWDBASED
- /* oidKdfType */
- { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"},
- /* oidPBEType */
- { PBE_SHA1_RC4_128, PBE_SHA1_RC4_128, oidPBEType,
- "PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4"},
- { PBE_SHA1_DES, PBE_SHA1_DES, oidPBEType, "PBE-SHA1-DES",
- "pbeWithSHA1AndDES-CBC"},
- { PBE_SHA1_DES3, PBE_SHA1_DES3, oidPBEType, "PBE-SHA1-3DES",
- "pbeWithSHA1And3-KeyTripleDES-CBC"},
- #endif
- /* oidKeyWrapType */
- #ifdef WOLFSSL_AES_128
- { AES128_WRAP, AES128_WRAP, oidKeyWrapType, "AES-128 wrap", "aes128-wrap"},
- #endif
- #ifdef WOLFSSL_AES_192
- { AES192_WRAP, AES192_WRAP, oidKeyWrapType, "AES-192 wrap", "aes192-wrap"},
- #endif
- #ifdef WOLFSSL_AES_256
- { AES256_WRAP, AES256_WRAP, oidKeyWrapType, "AES-256 wrap", "aes256-wrap"},
- #endif
- #ifndef NO_PKCS7
- #ifndef NO_DH
- /* oidCmsKeyAgreeType */
- #ifndef NO_SHA
- { dhSinglePass_stdDH_sha1kdf_scheme, dhSinglePass_stdDH_sha1kdf_scheme,
- oidCmsKeyAgreeType, "dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme"},
- #endif
- #ifdef WOLFSSL_SHA224
- { dhSinglePass_stdDH_sha224kdf_scheme,
- dhSinglePass_stdDH_sha224kdf_scheme, oidCmsKeyAgreeType,
- "dhSinglePass-stdDH-sha224kdf-scheme", "dhSinglePass-stdDH-sha224kdf-scheme"},
- #endif
- #ifndef NO_SHA256
- { dhSinglePass_stdDH_sha256kdf_scheme,
- dhSinglePass_stdDH_sha256kdf_scheme, oidCmsKeyAgreeType,
- "dhSinglePass-stdDH-sha256kdf-scheme", "dhSinglePass-stdDH-sha256kdf-scheme"},
- #endif
- #ifdef WOLFSSL_SHA384
- { dhSinglePass_stdDH_sha384kdf_scheme,
- dhSinglePass_stdDH_sha384kdf_scheme, oidCmsKeyAgreeType,
- "dhSinglePass-stdDH-sha384kdf-scheme", "dhSinglePass-stdDH-sha384kdf-scheme"},
- #endif
- #ifdef WOLFSSL_SHA512
- { dhSinglePass_stdDH_sha512kdf_scheme,
- dhSinglePass_stdDH_sha512kdf_scheme, oidCmsKeyAgreeType,
- "dhSinglePass-stdDH-sha512kdf-scheme", "dhSinglePass-stdDH-sha512kdf-scheme"},
- #endif
- #endif
- #endif
- #if defined(WOLFSSL_APACHE_HTTPD)
- /* "1.3.6.1.5.5.7.8.7" */
- { NID_id_on_dnsSRV, NID_id_on_dnsSRV, oidCertNameType,
- WOLFSSL_SN_DNS_SRV, WOLFSSL_LN_DNS_SRV },
- /* "1.3.6.1.4.1.311.20.2.3" */
- { NID_ms_upn, WOLFSSL_MS_UPN_SUM, oidCertExtType, WOLFSSL_SN_MS_UPN,
- WOLFSSL_LN_MS_UPN },
- /* "1.3.6.1.5.5.7.1.24" */
- { NID_tlsfeature, WOLFSSL_TLS_FEATURE_SUM, oidTlsExtType,
- WOLFSSL_SN_TLS_FEATURE, WOLFSSL_LN_TLS_FEATURE },
- #endif
- #endif /* OPENSSL_EXTRA */
- };
- #define WOLFSSL_OBJECT_INFO_SZ \
- (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info))
- const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ;
- #endif
- #ifdef OPENSSL_EXTRA
- WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, WOLFSSL_ASN1_INTEGER *ai)
- {
- WOLFSSL_ASN1_INTEGER* a;
- int len;
- const int extraTagSz = MAX_LENGTH_SZ + 1;
- byte intTag[MAX_LENGTH_SZ + 1];
- int idx = 0;
- WOLFSSL_ENTER("wolfSSL_BN_to_ASN1_INTEGER");
- if (ai == NULL) {
- a = wolfSSL_ASN1_INTEGER_new();
- if (a == NULL)
- return NULL;
- a->type = V_ASN1_INTEGER;
- }
- else {
- a = ai;
- }
- if (a) {
- if (wolfSSL_BN_is_negative(bn) && !wolfSSL_BN_is_zero(bn)) {
- a->type |= V_ASN1_NEG_INTEGER;
- a->negative = 1;
- }
- len = wolfSSL_BN_num_bytes(bn);
- if (len == 0)
- len = 1;
- /* allocate buffer */
- if (len + extraTagSz > (int)sizeof(a->intData)) {
- /* create new data buffer and copy over */
- a->data = (byte*)XMALLOC(len + extraTagSz, NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (a->data == NULL) {
- if (a != ai)
- wolfSSL_ASN1_INTEGER_free(a);
- return NULL;
- }
- a->isDynamic = 1;
- }
- else {
- XMEMSET(a->intData, 0, sizeof(a->intData));
- a->data = a->intData;
- a->isDynamic = 0;
- }
- /* populate data */
- if (wolfSSL_BN_is_zero(bn)) {
- a->data[0] = 0;
- }
- else {
- len = wolfSSL_BN_bn2bin(bn, a->data);
- if (len < 0) {
- wolfSSL_ASN1_INTEGER_free(a);
- return NULL;
- }
- }
- a->length = len;
- /* Write ASN tag */
- idx = SetASNInt(a->length, a->data[0], intTag);
- XMEMMOVE(a->data + idx, a->data, a->length);
- XMEMCPY(a->data, intTag, idx);
- a->dataMax = a->length += idx;
- }
- return a;
- }
- #ifdef OPENSSL_ALL
- void *wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM *tpl)
- {
- void *ret = NULL;
- const WOLFSSL_ASN1_TEMPLATE *member = NULL;
- size_t i;
- WOLFSSL_ENTER("wolfSSL_ASN1_item_new");
- if (!tpl) {
- return NULL;
- }
- if (!(ret = (void *)XMALLOC(tpl->size, NULL, DYNAMIC_TYPE_OPENSSL))) {
- return NULL;
- }
- XMEMSET(ret, 0, tpl->size);
- for (member = tpl->members, i = 0; i < tpl->mcount;
- member++, i++) {
- switch (member->type) {
- case WOLFSSL_X509_ALGOR_ASN1:
- {
- WOLFSSL_X509_ALGOR* algor = wolfSSL_X509_ALGOR_new();
- if (!algor) {
- goto error;
- }
- *(WOLFSSL_X509_ALGOR**)(((byte*)ret) + member->offset) = algor;
- break;
- }
- case WOLFSSL_ASN1_BIT_STRING_ASN1:
- {
- WOLFSSL_ASN1_BIT_STRING* bit_str = wolfSSL_ASN1_BIT_STRING_new();
- if (!bit_str) {
- goto error;
- }
- *(WOLFSSL_ASN1_BIT_STRING**)(((byte*)ret) + member->offset) = bit_str;
- break;
- }
- default:
- WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_new");
- goto error;
- }
- }
- return ret;
- error:
- wolfSSL_ASN1_item_free(ret, tpl);
- return NULL;
- }
- void wolfSSL_ASN1_item_free(void *val, const WOLFSSL_ASN1_ITEM *tpl)
- {
- const WOLFSSL_ASN1_TEMPLATE *member = NULL;
- size_t i;
- WOLFSSL_ENTER("wolfSSL_ASN1_item_free");
- if (val) {
- for (member = tpl->members, i = 0; i < tpl->mcount;
- member++, i++) {
- switch (member->type) {
- case WOLFSSL_X509_ALGOR_ASN1:
- {
- WOLFSSL_X509_ALGOR* algor = *(WOLFSSL_X509_ALGOR**)
- (((byte*)val) + member->offset);
- if (algor) {
- wolfSSL_X509_ALGOR_free(algor);
- }
- break;
- }
- case WOLFSSL_ASN1_BIT_STRING_ASN1:
- {
- WOLFSSL_ASN1_BIT_STRING* bit_str = *(WOLFSSL_ASN1_BIT_STRING**)
- (((byte*)val) + member->offset);
- if (bit_str) {
- wolfSSL_ASN1_BIT_STRING_free(bit_str);
- }
- break;
- }
- default:
- WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_free");
- }
- }
- XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- #define bufLenOrNull(buf, len) ((buf) ? (buf) + (len) : NULL)
- static int i2dProcessMembers(const void *src, byte *buf,
- const WOLFSSL_ASN1_TEMPLATE *members, size_t mcount)
- {
- const WOLFSSL_ASN1_TEMPLATE *member = NULL;
- int len = 0, ret;
- size_t i;
- WOLFSSL_ENTER("processMembers");
- for (member = members, i = 0; i < mcount; member++, i++) {
- switch (member->type) {
- case WOLFSSL_X509_ALGOR_ASN1:
- {
- word32 oid = 0;
- word32 idx = 0;
- const WOLFSSL_X509_ALGOR* algor = *(const WOLFSSL_X509_ALGOR**)
- (((byte*)src) + member->offset);
- if (!algor->algorithm) {
- WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE);
- return WOLFSSL_FAILURE;
- }
- if (GetObjectId(algor->algorithm->obj, &idx, &oid,
- algor->algorithm->grp, algor->algorithm->objSz) < 0) {
- WOLFSSL_MSG("Issue getting OID of object");
- return -1;
- }
- ret = SetAlgoID(oid, bufLenOrNull(buf, len),
- algor->algorithm->grp, 0);
- if (!ret) {
- return WOLFSSL_FAILURE;
- }
- len += ret;
- break;
- }
- case WOLFSSL_ASN1_BIT_STRING_ASN1:
- {
- const WOLFSSL_ASN1_BIT_STRING* bit_str;
- bit_str = *(const WOLFSSL_ASN1_BIT_STRING**)
- (((byte*)src) + member->offset);
- len += SetBitString(bit_str->length, 0, bufLenOrNull(buf, len));
- if (buf && bit_str->data) {
- XMEMCPY(buf + len, bit_str->data, bit_str->length);
- }
- len += bit_str->length;
- break;
- }
- default:
- WOLFSSL_MSG("Type not support in processMembers");
- WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE);
- return WOLFSSL_FAILURE;
- }
- }
- WOLFSSL_LEAVE("processMembers", len);
- return len;
- }
- static int wolfSSL_ASN1_item_i2d_1(const void *src, byte *buf,
- const WOLFSSL_ASN1_ITEM *tpl, int *len)
- {
- *len = 0;
- switch (tpl->type) {
- case ASN_SEQUENCE:
- {
- int seq_len = i2dProcessMembers(src, NULL, tpl->members,
- tpl->mcount);
- if (seq_len == WOLFSSL_FAILURE)
- return WOLFSSL_FAILURE;
- *len += SetSequence(seq_len, bufLenOrNull(buf, *len));
- if (buf) {
- if (i2dProcessMembers(src, bufLenOrNull(buf, *len), tpl->members,
- tpl->mcount) != seq_len) {
- WOLFSSL_MSG("Inconsistent sequence length");
- return WOLFSSL_FAILURE;
- }
- }
- *len += seq_len;
- break;
- }
- default:
- WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_i2d");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_ASN1_item_i2d(const void *src, byte **dest,
- const WOLFSSL_ASN1_ITEM *tpl)
- {
- int len;
- byte *buf = NULL;
- WOLFSSL_ENTER("wolfSSL_ASN1_item_i2d");
- if ((src == NULL) || (tpl == NULL))
- goto error;
- if (wolfSSL_ASN1_item_i2d_1(src, NULL, tpl, &len) != WOLFSSL_SUCCESS)
- goto error;
- if (dest == NULL) {
- WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_SUCCESS);
- return len;
- }
- if (*dest == NULL) {
- buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1);
- if (buf == NULL)
- goto error;
- } else
- buf = *dest;
- if (wolfSSL_ASN1_item_i2d_1(src, buf, tpl, &len) != WOLFSSL_SUCCESS)
- goto error;
- if (*dest == NULL)
- *dest = buf;
- else {
- /* XXX *dest length is not checked because the user is responsible
- * for providing a long enough buffer
- */
- XMEMCPY(*dest, buf, len);
- }
- WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", len);
- return len;
- error:
- if (buf) {
- XFREE(buf, NULL, DYNAMIC_TYPE_ASN1);
- }
- WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE);
- return WOLFSSL_FAILURE;
- }
- #endif /* OPENSSL_ALL */
- #endif /* OPENSSL_EXTRA */
- #ifdef OPENSSL_EXTRA
- WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void)
- {
- WOLFSSL_HMAC_CTX* hmac_ctx = (WOLFSSL_HMAC_CTX*)XMALLOC(
- sizeof(WOLFSSL_HMAC_CTX), NULL, DYNAMIC_TYPE_OPENSSL);
- if (hmac_ctx != NULL) {
- XMEMSET(hmac_ctx, 0, sizeof(WOLFSSL_HMAC_CTX));
- }
- return hmac_ctx;
- }
- int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx)
- {
- WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init");
- if (ctx != NULL) {
- /* wc_HmacSetKey sets up ctx->hmac */
- XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX));
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key,
- int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e)
- {
- WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex");
- /* WOLFSSL_ENGINE not used, call wolfSSL_HMAC_Init */
- (void)e;
- return wolfSSL_HMAC_Init(ctx, key, keylen, type);
- }
- /* helper function for Deep copy of internal wolfSSL hmac structure
- * returns WOLFSSL_SUCCESS on success */
- int wolfSSL_HmacCopy(Hmac* des, Hmac* src)
- {
- void* heap;
- int ret;
- #ifndef HAVE_FIPS
- heap = src->heap;
- #else
- heap = NULL;
- #endif
- if (wc_HmacInit(des, heap, 0) != 0) {
- return WOLFSSL_FAILURE;
- }
- /* requires that hash structures have no dynamic parts to them */
- switch (src->macType) {
- #ifndef NO_MD5
- case WC_MD5:
- ret = wc_Md5Copy(&src->hash.md5, &des->hash.md5);
- break;
- #endif /* !NO_MD5 */
- #ifndef NO_SHA
- case WC_SHA:
- ret = wc_ShaCopy(&src->hash.sha, &des->hash.sha);
- break;
- #endif /* !NO_SHA */
- #ifdef WOLFSSL_SHA224
- case WC_SHA224:
- ret = wc_Sha224Copy(&src->hash.sha224, &des->hash.sha224);
- break;
- #endif /* WOLFSSL_SHA224 */
- #ifndef NO_SHA256
- case WC_SHA256:
- ret = wc_Sha256Copy(&src->hash.sha256, &des->hash.sha256);
- break;
- #endif /* !NO_SHA256 */
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- ret = wc_Sha384Copy(&src->hash.sha384, &des->hash.sha384);
- break;
- #endif /* WOLFSSL_SHA384 */
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- ret = wc_Sha512Copy(&src->hash.sha512, &des->hash.sha512);
- break;
- #endif /* WOLFSSL_SHA512 */
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- case WC_SHA3_224:
- ret = wc_Sha3_224_Copy(&src->hash.sha3, &des->hash.sha3);
- break;
- #endif /* WOLFSSL_NO_SHA3_224 */
- #ifndef WOLFSSL_NOSHA3_256
- case WC_SHA3_256:
- ret = wc_Sha3_256_Copy(&src->hash.sha3, &des->hash.sha3);
- break;
- #endif /* WOLFSSL_NO_SHA3_256 */
- #ifndef WOLFSSL_NOSHA3_384
- case WC_SHA3_384:
- ret = wc_Sha3_384_Copy(&src->hash.sha3, &des->hash.sha3);
- break;
- #endif /* WOLFSSL_NO_SHA3_384 */
- #ifndef WOLFSSL_NOSHA3_512
- case WC_SHA3_512:
- ret = wc_Sha3_512_Copy(&src->hash.sha3, &des->hash.sha3);
- break;
- #endif /* WOLFSSL_NO_SHA3_512 */
- #endif /* WOLFSSL_SHA3 */
- default:
- return WOLFSSL_FAILURE;
- }
- if (ret != 0)
- return WOLFSSL_FAILURE;
- XMEMCPY((byte*)des->ipad, (byte*)src->ipad, WC_HMAC_BLOCK_SIZE);
- XMEMCPY((byte*)des->opad, (byte*)src->opad, WC_HMAC_BLOCK_SIZE);
- XMEMCPY((byte*)des->innerHash, (byte*)src->innerHash, WC_MAX_DIGEST_SIZE);
- #ifndef HAVE_FIPS
- des->heap = heap;
- #endif
- des->macType = src->macType;
- des->innerHashKeyed = src->innerHashKeyed;
- #ifdef WOLFSSL_ASYNC_CRYPT
- XMEMCPY(&des->asyncDev, &src->asyncDev, sizeof(WC_ASYNC_DEV));
- des->keyLen = src->keyLen;
- #ifdef HAVE_CAVIUM
- des->data = (byte*)XMALLOC(src->dataLen, des->heap,
- DYNAMIC_TYPE_HMAC);
- if (des->data == NULL) {
- return BUFFER_E;
- }
- XMEMCPY(des->data, src->data, src->dataLen);
- des->dataLen = src->dataLen;
- #endif /* HAVE_CAVIUM */
- #endif /* WOLFSSL_ASYNC_CRYPT */
- return WOLFSSL_SUCCESS;
- }
- /* Deep copy of information from src to des structure
- *
- * des destination to copy information to
- * src structure to get information from
- *
- * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error
- */
- int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, WOLFSSL_HMAC_CTX* src)
- {
- WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy");
- if (des == NULL || src == NULL) {
- return WOLFSSL_FAILURE;
- }
- des->type = src->type;
- XMEMCPY((byte *)&des->save_ipad, (byte *)&src->hmac.ipad,
- WC_HMAC_BLOCK_SIZE);
- XMEMCPY((byte *)&des->save_opad, (byte *)&src->hmac.opad,
- WC_HMAC_BLOCK_SIZE);
- return wolfSSL_HmacCopy(&des->hmac, &src->hmac);
- }
- #if defined(HAVE_FIPS) && \
- (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
- static int _HMAC_Init(Hmac* hmac, int type, void* heap)
- {
- int ret = 0;
- switch (type) {
- #ifndef NO_MD5
- case WC_MD5:
- ret = wc_InitMd5(&hmac->hash.md5);
- break;
- #endif /* !NO_MD5 */
- #ifndef NO_SHA
- case WC_SHA:
- ret = wc_InitSha(&hmac->hash.sha);
- break;
- #endif /* !NO_SHA */
- #ifdef WOLFSSL_SHA224
- case WC_SHA224:
- ret = wc_InitSha224(&hmac->hash.sha224);
- break;
- #endif /* WOLFSSL_SHA224 */
- #ifndef NO_SHA256
- case WC_SHA256:
- ret = wc_InitSha256(&hmac->hash.sha256);
- break;
- #endif /* !NO_SHA256 */
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- ret = wc_InitSha384(&hmac->hash.sha384);
- break;
- #endif /* WOLFSSL_SHA384 */
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- ret = wc_InitSha512(&hmac->hash.sha512);
- break;
- #endif /* WOLFSSL_SHA512 */
- #ifdef WOLFSSL_SHA3
- case WC_SHA3_224:
- ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
- break;
- case WC_SHA3_256:
- ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
- break;
- case WC_SHA3_384:
- ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
- break;
- case WC_SHA3_512:
- ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
- break;
- #endif
- default:
- ret = BAD_FUNC_ARG;
- break;
- }
- (void)heap;
- return ret;
- }
- #else
- #define _HMAC_Init _InitHmac
- #endif
- int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen,
- const EVP_MD* type)
- {
- int hmac_error = 0;
- void* heap = NULL;
- int inited;
- WOLFSSL_MSG("wolfSSL_HMAC_Init");
- if (ctx == NULL) {
- WOLFSSL_MSG("no ctx on init");
- return WOLFSSL_FAILURE;
- }
- #ifndef HAVE_FIPS
- heap = ctx->hmac.heap;
- #endif
- if (type) {
- WOLFSSL_MSG("init has type");
- #ifndef NO_MD5
- if (XSTRNCMP(type, "MD5", 3) == 0) {
- WOLFSSL_MSG("md5 hmac");
- ctx->type = WC_MD5;
- }
- else
- #endif
- #ifdef WOLFSSL_SHA224
- if (XSTRNCMP(type, "SHA224", 6) == 0) {
- WOLFSSL_MSG("sha224 hmac");
- ctx->type = WC_SHA224;
- }
- else
- #endif
- #ifndef NO_SHA256
- if (XSTRNCMP(type, "SHA256", 6) == 0) {
- WOLFSSL_MSG("sha256 hmac");
- ctx->type = WC_SHA256;
- }
- else
- #endif
- #ifdef WOLFSSL_SHA384
- if (XSTRNCMP(type, "SHA384", 6) == 0) {
- WOLFSSL_MSG("sha384 hmac");
- ctx->type = WC_SHA384;
- }
- else
- #endif
- #ifdef WOLFSSL_SHA512
- if (XSTRNCMP(type, "SHA512", 6) == 0) {
- WOLFSSL_MSG("sha512 hmac");
- ctx->type = WC_SHA512;
- }
- else
- #endif
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- if (XSTRNCMP(type, "SHA3_224", 8) == 0) {
- WOLFSSL_MSG("sha3_224 hmac");
- ctx->type = WC_SHA3_224;
- }
- else
- #endif
- #ifndef WOLFSSL_NOSHA3_256
- if (XSTRNCMP(type, "SHA3_256", 8) == 0) {
- WOLFSSL_MSG("sha3_256 hmac");
- ctx->type = WC_SHA3_256;
- }
- else
- #endif
- if (XSTRNCMP(type, "SHA3_384", 8) == 0) {
- WOLFSSL_MSG("sha3_384 hmac");
- ctx->type = WC_SHA3_384;
- }
- else
- #ifndef WOLFSSL_NOSHA3_512
- if (XSTRNCMP(type, "SHA3_512", 8) == 0) {
- WOLFSSL_MSG("sha3_512 hmac");
- ctx->type = WC_SHA3_512;
- }
- else
- #endif
- #endif
- #ifndef NO_SHA
- /* has to be last since would pick or 256, 384, or 512 too */
- if (XSTRNCMP(type, "SHA", 3) == 0) {
- WOLFSSL_MSG("sha hmac");
- ctx->type = WC_SHA;
- }
- else
- #endif
- {
- WOLFSSL_MSG("bad init type");
- return WOLFSSL_FAILURE;
- }
- }
- /* Check if init has been called before */
- inited = (ctx->hmac.macType != WC_HASH_TYPE_NONE);
- /* Free if needed */
- if (inited) {
- wc_HmacFree(&ctx->hmac);
- }
- if (key != NULL) {
- WOLFSSL_MSG("keying hmac");
- if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
- hmac_error = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key,
- (word32)keylen);
- if (hmac_error < 0){
- /* in FIPS mode a key < 14 characters will fail here */
- WOLFSSL_MSG("hmac set key error");
- WOLFSSL_ERROR(hmac_error);
- wc_HmacFree(&ctx->hmac);
- return WOLFSSL_FAILURE;
- }
- XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad,
- WC_HMAC_BLOCK_SIZE);
- XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad,
- WC_HMAC_BLOCK_SIZE);
- }
- /* OpenSSL compat, no error */
- }
- else if (!inited) {
- return WOLFSSL_FAILURE;
- }
- else if (ctx->type >= 0) { /* MD5 == 0 */
- WOLFSSL_MSG("recover hmac");
- if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
- ctx->hmac.macType = (byte)ctx->type;
- ctx->hmac.innerHashKeyed = 0;
- XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad,
- WC_HMAC_BLOCK_SIZE);
- XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad,
- WC_HMAC_BLOCK_SIZE);
- if ((hmac_error = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap))
- !=0) {
- WOLFSSL_MSG("hmac init error");
- WOLFSSL_ERROR(hmac_error);
- return WOLFSSL_FAILURE;
- }
- }
- }
- (void)hmac_error;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data,
- int len)
- {
- int hmac_error = 0;
- WOLFSSL_MSG("wolfSSL_HMAC_Update");
- if (ctx == NULL) {
- WOLFSSL_MSG("no ctx");
- return WOLFSSL_FAILURE;
- }
- if (data) {
- WOLFSSL_MSG("updating hmac");
- hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len);
- if (hmac_error < 0){
- WOLFSSL_MSG("hmac update error");
- return WOLFSSL_FAILURE;
- }
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
- unsigned int* len)
- {
- int hmac_error;
- WOLFSSL_MSG("wolfSSL_HMAC_Final");
- /* "len" parameter is optional. */
- if (ctx == NULL || hash == NULL) {
- WOLFSSL_MSG("invalid parameter");
- return WOLFSSL_FAILURE;
- }
- WOLFSSL_MSG("final hmac");
- hmac_error = wc_HmacFinal(&ctx->hmac, hash);
- if (hmac_error < 0){
- WOLFSSL_MSG("final hmac error");
- return WOLFSSL_FAILURE;
- }
- if (len) {
- WOLFSSL_MSG("setting output len");
- switch (ctx->type) {
- #ifndef NO_MD5
- case WC_MD5:
- *len = WC_MD5_DIGEST_SIZE;
- break;
- #endif
- #ifndef NO_SHA
- case WC_SHA:
- *len = WC_SHA_DIGEST_SIZE;
- break;
- #endif
- #ifdef WOLFSSL_SHA224
- case WC_SHA224:
- *len = WC_SHA224_DIGEST_SIZE;
- break;
- #endif
- #ifndef NO_SHA256
- case WC_SHA256:
- *len = WC_SHA256_DIGEST_SIZE;
- break;
- #endif
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- *len = WC_SHA384_DIGEST_SIZE;
- break;
- #endif
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- *len = WC_SHA512_DIGEST_SIZE;
- break;
- #endif
- #ifdef WOLFSSL_SHA3
- #ifndef WOLFSSL_NOSHA3_224
- case WC_SHA3_224:
- *len = WC_SHA3_224_DIGEST_SIZE;
- break;
- #endif
- #ifndef WOLFSSL_NOSHA3_256
- case WC_SHA3_256:
- *len = WC_SHA3_256_DIGEST_SIZE;
- break;
- #endif
- #ifndef WOLFSSL_NOSHA3_384
- case WC_SHA3_384:
- *len = WC_SHA3_384_DIGEST_SIZE;
- break;
- #endif
- #ifndef WOLFSSL_NOSHA3_512
- case WC_SHA3_512:
- *len = WC_SHA3_512_DIGEST_SIZE;
- break;
- #endif
- #endif
- default:
- WOLFSSL_MSG("bad hmac type");
- return WOLFSSL_FAILURE;
- }
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx)
- {
- WOLFSSL_MSG("wolfSSL_HMAC_cleanup");
- if (ctx) {
- wc_HmacFree(&ctx->hmac);
- }
- return WOLFSSL_SUCCESS;
- }
- void wolfSSL_HMAC_CTX_cleanup(WOLFSSL_HMAC_CTX* ctx)
- {
- if (ctx) {
- wolfSSL_HMAC_cleanup(ctx);
- }
- }
- void wolfSSL_HMAC_CTX_free(WOLFSSL_HMAC_CTX* ctx)
- {
- if (ctx) {
- wolfSSL_HMAC_CTX_cleanup(ctx);
- XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- size_t wolfSSL_HMAC_size(const WOLFSSL_HMAC_CTX *ctx)
- {
- if (!ctx) {
- return 0;
- }
- return (size_t)wc_HashGetDigestSize((enum wc_HashType)ctx->hmac.macType);
- }
- const WOLFSSL_EVP_MD *wolfSSL_HMAC_CTX_get_md(const WOLFSSL_HMAC_CTX *ctx)
- {
- if (!ctx) {
- return NULL;
- }
- return wolfSSL_macType2EVP_md((enum wc_HashType)ctx->type);
- }
- #if defined(WOLFSSL_CMAC) && defined(OPENSSL_EXTRA) && \
- defined(WOLFSSL_AES_DIRECT)
- WOLFSSL_CMAC_CTX* wolfSSL_CMAC_CTX_new(void)
- {
- WOLFSSL_CMAC_CTX* ctx = NULL;
- ctx = (WOLFSSL_CMAC_CTX*)XMALLOC(sizeof(WOLFSSL_CMAC_CTX), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (ctx != NULL) {
- ctx->internal = (Cmac*)XMALLOC(sizeof(Cmac), NULL, DYNAMIC_TYPE_CMAC);
- if (ctx->internal == NULL) {
- XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
- ctx = NULL;
- }
- }
- if (ctx != NULL) {
- ctx->cctx = wolfSSL_EVP_CIPHER_CTX_new();
- if (ctx->cctx == NULL) {
- XFREE(ctx->internal, NULL, DYNAMIC_TYPE_CMAC);
- XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
- ctx = NULL;
- }
- }
- return ctx;
- }
- void wolfSSL_CMAC_CTX_free(WOLFSSL_CMAC_CTX *ctx)
- {
- if (ctx != NULL) {
- if (ctx->internal != NULL) {
- XFREE(ctx->internal, NULL, DYNAMIC_TYPE_CMAC);
- }
- if (ctx->cctx != NULL) {
- wolfSSL_EVP_CIPHER_CTX_free(ctx->cctx);
- }
- XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- WOLFSSL_EVP_CIPHER_CTX* wolfSSL_CMAC_CTX_get0_cipher_ctx(WOLFSSL_CMAC_CTX* ctx)
- {
- WOLFSSL_EVP_CIPHER_CTX* cctx = NULL;
- if (ctx != NULL) {
- cctx = ctx->cctx;
- }
- return cctx;
- }
- int wolfSSL_CMAC_Init(WOLFSSL_CMAC_CTX* ctx, const void *key, size_t keyLen,
- const WOLFSSL_EVP_CIPHER* cipher, WOLFSSL_ENGINE* engine)
- {
- int ret = WOLFSSL_SUCCESS;
- (void)engine;
- WOLFSSL_ENTER("wolfSSL_CMAC_Init");
- if (ctx == NULL || cipher == NULL || (
- cipher != EVP_AES_128_CBC &&
- cipher != EVP_AES_192_CBC &&
- cipher != EVP_AES_256_CBC)) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- ret = wc_InitCmac((Cmac*)ctx->internal, (const byte*)key,
- (word32)keyLen, WC_CMAC_AES, NULL);
- if (ret != 0) {
- ret = WOLFSSL_FAILURE;
- }
- else {
- ret = WOLFSSL_SUCCESS;
- }
- }
- if (ret == WOLFSSL_SUCCESS) {
- ret = wolfSSL_EVP_CipherInit(ctx->cctx, cipher, (const byte*)key, NULL,
- 1);
- }
- WOLFSSL_LEAVE("wolfSSL_CMAC_Init", ret);
- return ret;
- }
- int wolfSSL_CMAC_Update(WOLFSSL_CMAC_CTX* ctx, const void* data, size_t len)
- {
- int ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CMAC_Update");
- if (ctx == NULL || ctx->internal == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (data) {
- ret = wc_CmacUpdate((Cmac*)ctx->internal, (const byte*)data,
- (word32)len);
- if (ret != 0){
- ret = WOLFSSL_FAILURE;
- }
- else {
- ret = WOLFSSL_SUCCESS;
- }
- }
- }
- WOLFSSL_LEAVE("wolfSSL_CMAC_Update", ret);
- return ret;
- }
- int wolfSSL_CMAC_Final(WOLFSSL_CMAC_CTX* ctx, unsigned char* out,
- size_t* len)
- {
- int ret = WOLFSSL_SUCCESS;
- int blockSize;
- WOLFSSL_ENTER("wolfSSL_CMAC_Final");
- if (ctx == NULL || ctx->cctx == NULL || ctx->internal == NULL ||
- len == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- blockSize = EVP_CIPHER_CTX_block_size(ctx->cctx);
- if (blockSize <= 0) {
- ret = WOLFSSL_FAILURE;
- }
- else {
- *len = blockSize;
- }
- }
- if (ret == WOLFSSL_SUCCESS) {
- word32 len32 = (word32)*len;
- ret = wc_CmacFinal((Cmac*)ctx->internal, out, &len32);
- *len = (size_t)len32;
- if (ret != 0) {
- ret = WOLFSSL_FAILURE;
- }
- else {
- ret = WOLFSSL_SUCCESS;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_CMAC_Final", ret);
- return ret;
- }
- #endif /* WOLFSSL_CMAC && OPENSSL_EXTRA && WOLFSSL_AES_DIRECT */
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- /* Free the dynamically allocated data.
- *
- * p Pointer to dynamically allocated memory.
- */
- void wolfSSL_OPENSSL_free(void* p)
- {
- WOLFSSL_MSG("wolfSSL_OPENSSL_free");
- XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- #ifdef OPENSSL_EXTRA
- void *wolfSSL_OPENSSL_malloc(size_t a)
- {
- return (void *)XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- int wolfSSL_OPENSSL_hexchar2int(unsigned char c)
- {
- /* 'char' is unsigned on some platforms. */
- return (int)(signed char)HexCharToByte((char)c);
- }
- unsigned char *wolfSSL_OPENSSL_hexstr2buf(const char *str, long *len)
- {
- unsigned char* targetBuf;
- int srcDigitHigh = 0;
- int srcDigitLow = 0;
- size_t srcLen;
- size_t srcIdx = 0;
- long targetIdx = 0;
- srcLen = XSTRLEN(str);
- targetBuf = (unsigned char*)XMALLOC(srcLen / 2, NULL, DYNAMIC_TYPE_OPENSSL);
- if (targetBuf == NULL) {
- return NULL;
- }
- while (srcIdx < srcLen) {
- if (str[srcIdx] == ':') {
- srcIdx++;
- continue;
- }
- srcDigitHigh = wolfSSL_OPENSSL_hexchar2int(str[srcIdx++]);
- srcDigitLow = wolfSSL_OPENSSL_hexchar2int(str[srcIdx++]);
- if (srcDigitHigh < 0 || srcDigitLow < 0) {
- WOLFSSL_MSG("Invalid hex character.");
- XFREE(targetBuf, NULL, DYNAMIC_TYPE_OPENSSL);
- return NULL;
- }
- targetBuf[targetIdx++] = (unsigned char)((srcDigitHigh << 4) | srcDigitLow);
- }
- if (len != NULL)
- *len = targetIdx;
- return targetBuf;
- }
- int wolfSSL_OPENSSL_init_ssl(word64 opts, const OPENSSL_INIT_SETTINGS *settings)
- {
- (void)opts;
- (void)settings;
- return wolfSSL_library_init();
- }
- int wolfSSL_OPENSSL_init_crypto(word64 opts, const OPENSSL_INIT_SETTINGS* settings)
- {
- (void)opts;
- (void)settings;
- return wolfSSL_library_init();
- }
- #if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER)
- int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher,
- unsigned char* passwd, int passwdSz, byte **cipherInfo,
- int maxDerSz)
- {
- int ret, paddingSz;
- word32 idx, cipherInfoSz;
- #ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
- #else
- EncryptedInfo info[1];
- #endif
- WOLFSSL_ENTER("EncryptDerKey");
- if (der == NULL || derSz == NULL || cipher == NULL ||
- passwd == NULL || cipherInfo == NULL)
- return BAD_FUNC_ARG;
- #ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_ENCRYPTEDINFO);
- if (info == NULL) {
- WOLFSSL_MSG("malloc failed");
- return WOLFSSL_FAILURE;
- }
- #endif
- XMEMSET(info, 0, sizeof(EncryptedInfo));
- /* set the cipher name on info */
- XSTRNCPY(info->name, cipher, NAME_SZ-1);
- info->name[NAME_SZ-1] = '\0'; /* null term */
- ret = wc_EncryptedInfoGet(info, info->name);
- if (ret != 0) {
- WOLFSSL_MSG("unsupported cipher");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- return WOLFSSL_FAILURE;
- }
- /* Generate a random salt */
- if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("generate iv failed");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- return WOLFSSL_FAILURE;
- }
- /* add the padding before encryption */
- paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz);
- if (paddingSz == 0)
- paddingSz = info->ivSz;
- if (maxDerSz < *derSz + paddingSz) {
- WOLFSSL_MSG("not enough DER buffer allocated");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- return WOLFSSL_FAILURE;
- }
- XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz);
- (*derSz) += paddingSz;
- /* encrypt buffer */
- if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) {
- WOLFSSL_MSG("encrypt key failed");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- return WOLFSSL_FAILURE;
- }
- /* create cipher info : 'cipher_name,Salt(hex)' */
- cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2);
- *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL,
- DYNAMIC_TYPE_STRING);
- if (*cipherInfo == NULL) {
- WOLFSSL_MSG("malloc failed");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- return WOLFSSL_FAILURE;
- }
- XSTRLCPY((char*)*cipherInfo, info->name, cipherInfoSz);
- XSTRLCAT((char*)*cipherInfo, ",", cipherInfoSz);
- idx = (word32)XSTRLEN((char*)*cipherInfo);
- cipherInfoSz -= idx;
- ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
- if (ret != 0) {
- WOLFSSL_MSG("Base16_Encode failed");
- XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING);
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */
- #ifndef NO_BIO
- static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
- {
- int ret;
- int pemSz;
- byte* pemBuf;
- int derSz = 0;
- byte* derBuf = NULL;
- if (bio == NULL || key == NULL) {
- WOLFSSL_MSG("Bad parameters");
- return WOLFSSL_FAILURE;
- }
- switch (key->type) {
- #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
- case EVP_PKEY_RSA:
- if ((derSz = wolfSSL_RSA_To_Der(key->rsa, &derBuf, 1, bio->heap))
- < 0) {
- WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
- break;
- }
- break;
- #endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA */
- #if !defined(NO_DSA) && !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \
- defined(WOLFSSL_CERT_GEN))
- case EVP_PKEY_DSA:
- if (key->dsa == NULL) {
- WOLFSSL_MSG("key->dsa is null");
- break;
- }
- derSz = MAX_DSA_PUBKEY_SZ;
- derBuf = (byte*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (derBuf == NULL) {
- WOLFSSL_MSG("malloc failed");
- break;
- }
- /* Key to DER */
- derSz = wc_DsaKeyToPublicDer((DsaKey*)key->dsa->internal, derBuf,
- derSz);
- if (derSz < 0) {
- WOLFSSL_MSG("wc_DsaKeyToDer failed");
- break;
- }
- break;
- #endif /* !NO_DSA && !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) */
- #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
- case EVP_PKEY_EC:
- {
- if (key->ecc == NULL) {
- WOLFSSL_MSG("key->ecc is null");
- break;
- }
- derSz = wc_EccPublicKeyDerSize((ecc_key*)key->ecc->internal, 1);
- if (derSz <= 0) {
- WOLFSSL_MSG("wc_EccPublicKeyDerSize failed");
- break;
- }
- derBuf = (byte*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (derBuf == NULL) {
- WOLFSSL_MSG("malloc failed");
- break;
- }
- derSz = wc_EccPublicKeyToDer((ecc_key*)key->ecc->internal, derBuf,
- derSz, 1);
- if (derSz < 0) {
- WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
- break;
- }
- break;
- }
- #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
- #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
- case EVP_PKEY_DH:
- WOLFSSL_MSG("Writing DH PUBKEY not supported!");
- break;
- #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
- default:
- WOLFSSL_MSG("Unknown Key type!");
- break;
- }
- if (derBuf == NULL || derSz <= 0) {
- if (derBuf != NULL)
- XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
- return WOLFSSL_FAILURE;
- }
- pemSz = wc_DerToPem(derBuf, derSz, NULL, 0, PUBLICKEY_TYPE);
- if (pemSz < 0) {
- WOLFSSL_LEAVE("pem_write_bio_pubkey", pemSz);
- XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
- return WOLFSSL_FAILURE;
- }
- pemBuf = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (pemBuf == NULL) {
- WOLFSSL_LEAVE("pem_write_bio_pubkey", pemSz);
- XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
- return WOLFSSL_FAILURE;
- }
- ret = wc_DerToPem(derBuf, derSz, pemBuf, pemSz, PUBLICKEY_TYPE);
- XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
- if (ret < 0) {
- WOLFSSL_LEAVE("pem_write_bio_pubkey", ret);
- XFREE(pemBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_FAILURE;
- }
- ret = wolfSSL_BIO_write(bio, pemBuf, pemSz);
- XFREE(pemBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret != pemSz) {
- WOLFSSL_MSG("Unable to write full PEM to BIO");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- /* Takes a public key and writes it out to a WOLFSSL_BIO
- * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
- */
- int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
- {
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PUBKEY");
- return pem_write_bio_pubkey(bio, key);
- }
- /* Takes a private key and writes it out to a WOLFSSL_BIO
- * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
- */
- int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
- const WOLFSSL_EVP_CIPHER* cipher,
- unsigned char* passwd, int len,
- wc_pem_password_cb* cb, void* arg)
- {
- byte* keyDer;
- int pemSz;
- int type;
- int ret;
- byte* tmp;
- (void)cipher;
- (void)passwd;
- (void)len;
- (void)cb;
- (void)arg;
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey");
- if (bio == NULL || key == NULL) {
- WOLFSSL_MSG("Bad Function Arguments");
- return WOLFSSL_FAILURE;
- }
- keyDer = (byte*)key->pkey.ptr;
- switch (key->type) {
- #ifndef NO_RSA
- case EVP_PKEY_RSA:
- type = PRIVATEKEY_TYPE;
- break;
- #endif
- #ifndef NO_DSA
- case EVP_PKEY_DSA:
- type = DSA_PRIVATEKEY_TYPE;
- break;
- #endif
- #ifdef HAVE_ECC
- case EVP_PKEY_EC:
- type = ECC_PRIVATEKEY_TYPE;
- break;
- #endif
- #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
- case EVP_PKEY_DH:
- type = DH_PRIVATEKEY_TYPE;
- break;
- #endif
- default:
- WOLFSSL_MSG("Unknown Key type!");
- type = PRIVATEKEY_TYPE;
- }
- pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type);
- if (pemSz < 0) {
- WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz);
- return WOLFSSL_FAILURE;
- }
- tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
- if (tmp == NULL) {
- return MEMORY_E;
- }
- ret = wc_DerToPem(keyDer, key->pkey_sz, tmp, pemSz, type);
- if (ret < 0) {
- WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret);
- XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return WOLFSSL_FAILURE;
- }
- ret = wolfSSL_BIO_write(bio, tmp, pemSz);
- XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
- if (ret != pemSz) {
- WOLFSSL_MSG("Unable to write full PEM to BIO");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* !NO_BIO */
- /* Colon separated list of <public key>+<digest> algorithms.
- * Replaces list in context.
- */
- int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, const char* list)
- {
- WOLFSSL_MSG("wolfSSL_CTX_set1_sigalg_list");
- if (ctx == NULL || list == NULL) {
- WOLFSSL_MSG("Bad function arguments");
- return WOLFSSL_FAILURE;
- }
- /* alloc/init on demand only */
- if (ctx->suites == NULL) {
- ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap,
- DYNAMIC_TYPE_SUITES);
- if (ctx->suites == NULL) {
- WOLFSSL_MSG("Memory alloc for Suites failed");
- return WOLFSSL_FAILURE;
- }
- XMEMSET(ctx->suites, 0, sizeof(Suites));
- }
- return SetSuitesHashSigAlgo(ctx->suites, list);
- }
- /* Colon separated list of <public key>+<digest> algorithms.
- * Replaces list in SSL.
- */
- int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list)
- {
- WOLFSSL_MSG("wolfSSL_set1_sigalg_list");
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad function arguments");
- return WOLFSSL_FAILURE;
- }
- #ifdef SINGLE_THREADED
- if (ssl->ctx->suites == ssl->suites) {
- ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
- DYNAMIC_TYPE_SUITES);
- if (ssl->suites == NULL) {
- WOLFSSL_MSG("Suites Memory error");
- return MEMORY_E;
- }
- *ssl->suites = *ssl->ctx->suites;
- ssl->options.ownSuites = 1;
- }
- #endif
- if (ssl == NULL || list == NULL) {
- WOLFSSL_MSG("Bad function arguments");
- return WOLFSSL_FAILURE;
- }
- return SetSuitesHashSigAlgo(ssl->suites, list);
- }
- struct WOLFSSL_HashSigInfo {
- int hashAlgo;
- int sigAlgo;
- int nid;
- } wolfssl_hash_sig_info[] =
- {
- #ifndef NO_RSA
- #ifndef NO_SHA256
- { sha256_mac, rsa_sa_algo, CTC_SHA256wRSA },
- #endif
- #ifdef WOLFSSL_SHA384
- { sha384_mac, rsa_sa_algo, CTC_SHA384wRSA },
- #endif
- #ifdef WOLFSSL_SHA512
- { sha512_mac, rsa_sa_algo, CTC_SHA512wRSA },
- #endif
- #ifdef WOLFSSL_SHA224
- { sha224_mac, rsa_sa_algo, CTC_SHA224wRSA },
- #endif
- #ifndef NO_SHA
- { sha_mac, rsa_sa_algo, CTC_SHAwRSA },
- #endif
- #ifdef WC_RSA_PSS
- #ifndef NO_SHA256
- { sha256_mac, rsa_pss_sa_algo, CTC_SHA256wRSA },
- #endif
- #ifdef WOLFSSL_SHA384
- { sha384_mac, rsa_pss_sa_algo, CTC_SHA384wRSA },
- #endif
- #ifdef WOLFSSL_SHA512
- { sha512_mac, rsa_pss_sa_algo, CTC_SHA512wRSA },
- #endif
- #ifdef WOLFSSL_SHA224
- { sha224_mac, rsa_pss_sa_algo, CTC_SHA224wRSA },
- #endif
- #endif
- #endif
- #ifdef HAVE_ECC
- #ifndef NO_SHA256
- { sha256_mac, ecc_dsa_sa_algo, CTC_SHA256wECDSA },
- #endif
- #ifdef WOLFSSL_SHA384
- { sha384_mac, ecc_dsa_sa_algo, CTC_SHA384wECDSA },
- #endif
- #ifdef WOLFSSL_SHA512
- { sha512_mac, ecc_dsa_sa_algo, CTC_SHA512wECDSA },
- #endif
- #ifdef WOLFSSL_SHA224
- { sha224_mac, ecc_dsa_sa_algo, CTC_SHA224wECDSA },
- #endif
- #ifndef NO_SHA
- { sha_mac, ecc_dsa_sa_algo, CTC_SHAwECDSA },
- #endif
- #endif
- #ifdef HAVE_ED25519
- { no_mac, ed25519_sa_algo, CTC_ED25519 },
- #endif
- #ifdef HAVE_ED448
- { no_mac, ed448_sa_algo, CTC_ED448 },
- #endif
- #ifdef HAVE_PQC
- #ifdef HAVE_FALCON
- { no_mac, falcon_level1_sa_algo, CTC_FALCON_LEVEL1 },
- { no_mac, falcon_level5_sa_algo, CTC_FALCON_LEVEL5 },
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- { no_mac, dilithium_level2_sa_algo, CTC_DILITHIUM_LEVEL2 },
- { no_mac, dilithium_level3_sa_algo, CTC_DILITHIUM_LEVEL3 },
- { no_mac, dilithium_level5_sa_algo, CTC_DILITHIUM_LEVEL5 },
- { no_mac, dilithium_aes_level2_sa_algo, CTC_DILITHIUM_AES_LEVEL2 },
- { no_mac, dilithium_aes_level3_sa_algo, CTC_DILITHIUM_AES_LEVEL3 },
- { no_mac, dilithium_aes_level5_sa_algo, CTC_DILITHIUM_AES_LEVEL5 },
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
- #ifndef NO_DSA
- #ifndef NO_SHA
- { sha_mac, dsa_sa_algo, CTC_SHAwDSA },
- #endif
- #endif
- };
- #define WOLFSSL_HASH_SIG_INFO_SZ \
- (int)(sizeof(wolfssl_hash_sig_info)/sizeof(*wolfssl_hash_sig_info))
- int wolfSSL_get_signature_nid(WOLFSSL *ssl, int* nid)
- {
- int i;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_MSG("wolfSSL_get_signature_nid");
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad function arguments");
- return WOLFSSL_FAILURE;
- }
- for (i = 0; i < WOLFSSL_HASH_SIG_INFO_SZ; i++) {
- if (ssl->suites->hashAlgo == wolfssl_hash_sig_info[i].hashAlgo &&
- ssl->suites->sigAlgo == wolfssl_hash_sig_info[i].sigAlgo) {
- *nid = wolfssl_hash_sig_info[i].nid;
- ret = WOLFSSL_SUCCESS;
- break;
- }
- }
- return ret;
- }
- #ifdef HAVE_ECC
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
- static int populate_groups(int* groups, int max_count, char *list)
- {
- char *end;
- int len;
- int count = 0;
- const WOLF_EC_NIST_NAME* nist_name;
- if (!groups || !list) {
- return -1;
- }
- for (end = list; ; list = ++end) {
- if (count > max_count) {
- WOLFSSL_MSG("Too many curves in list");
- return -1;
- }
- while (*end != ':' && *end != '\0') end++;
- len = (int)(end - list); /* end points to char after end
- * of curve name so no need for -1 */
- if ((len < kNistCurves_MIN_NAME_LEN) ||
- (len > kNistCurves_MAX_NAME_LEN)) {
- WOLFSSL_MSG("Unrecognized curve name in list");
- return -1;
- }
- for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
- if (len == nist_name->name_len &&
- XSTRNCMP(list, nist_name->name, nist_name->name_len) == 0) {
- break;
- }
- }
- if (!nist_name->name) {
- WOLFSSL_MSG("Unrecognized curve name in list");
- return -1;
- }
- groups[count++] = nist_name->nid;
- if (*end == '\0') break;
- }
- return count;
- }
- int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, char *list)
- {
- int groups[WOLFSSL_MAX_GROUP_COUNT];
- int count;
- if (!ctx || !list) {
- return WOLFSSL_FAILURE;
- }
- if ((count = populate_groups(groups,
- WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
- return WOLFSSL_FAILURE;
- }
- return wolfSSL_CTX_set1_groups(ctx, groups, count);
- }
- int wolfSSL_set1_groups_list(WOLFSSL *ssl, char *list)
- {
- int groups[WOLFSSL_MAX_GROUP_COUNT];
- int count;
- if (!ssl || !list) {
- return WOLFSSL_FAILURE;
- }
- if ((count = populate_groups(groups,
- WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
- return WOLFSSL_FAILURE;
- }
- return wolfSSL_set1_groups(ssl, groups, count);
- }
- #endif /* WOLFSSL_TLS13 */
- #endif /* HAVE_ECC */
- #ifndef NO_BIO
- /* Number of bytes to read from a file at a time. */
- #define PEM_READ_FILE_CHUNK_SZ 100
- static int pem_read_bio_file(WOLFSSL_BIO* bio, char** pem)
- {
- int ret = 0;
- int idx = 0;
- int sz = PEM_READ_FILE_CHUNK_SZ; /* read from file by chunks */
- int memSz = 0;
- char* mem = NULL;
- char* tmp;
- /* Allocate a chunk to read into. */
- tmp = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL);
- if (tmp == NULL) {
- WOLFSSL_MSG("Memory error");
- ret = MEMORY_E;
- }
- while (ret == 0 && (sz = wolfSSL_BIO_read(bio, tmp, sz)) > 0) {
- char* newMem;
- /* sanity check for signed overflow */
- if (memSz + sz < 0) {
- break;
- }
- /* Reallocate to make space for read data. */
- newMem = (char*)XREALLOC(mem, memSz + sz, bio->heap,
- DYNAMIC_TYPE_OPENSSL);
- if (newMem == NULL) {
- WOLFSSL_MSG("Memory error");
- ret = MEMORY_E;
- break;
- }
- mem = newMem;
- /* Copy in new data. */
- XMEMCPY(mem + idx, tmp, sz);
- memSz += sz;
- idx += sz;
- sz = PEM_READ_FILE_CHUNK_SZ; /* read another chunk from file */
- }
- XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
- tmp = NULL;
- if (ret == 0) {
- /* Check data was read. */
- if (memSz <= 0) {
- WOLFSSL_MSG("No data to read from bio");
- ret = BUFFER_E;
- }
- else {
- /* Return size of data read. */
- ret = memSz;
- }
- }
- /* Dispose of any allocated memory on error. */
- if (ret < 0) {
- XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
- mem = NULL;
- }
- *pem = mem;
- return ret;
- }
- static int pem_read_bio_pending(WOLFSSL_BIO* bio, int pendingSz, char** pem)
- {
- int ret = 0;
- char* mem;
- /* Allocate buffer to hold pending data. */
- mem = (char*)XMALLOC(pendingSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
- if (mem == NULL) {
- WOLFSSL_MSG("Memory error");
- ret = MEMORY_E;
- }
- else if ((ret = wolfSSL_BIO_read(bio, mem, pendingSz)) <= 0) {
- /* Pending data not read. */
- XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
- mem = NULL;
- ret = MEMORY_E;
- }
- *pem = mem;
- return ret;
- }
- static int pem_read_bio_key(WOLFSSL_BIO* bio, wc_pem_password_cb* cb,
- void* pass, int keyType, int* eccFlag,
- DerBuffer** der)
- {
- #ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
- #else
- EncryptedInfo info[1];
- #endif /* WOLFSSL_SMALL_STACK */
- wc_pem_password_cb* localCb = NULL;
- char* mem = NULL;
- int ret;
- if (cb != NULL) {
- localCb = cb;
- }
- else if (pass != NULL) {
- localCb = wolfSSL_PEM_def_callback;
- }
- if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
- ret = pem_read_bio_pending(bio, ret, &mem);
- }
- else if (bio->type == WOLFSSL_BIO_FILE) {
- ret = pem_read_bio_file(bio, &mem);
- }
- else {
- WOLFSSL_MSG("No data to read from bio");
- ret = NOT_COMPILED_IN;
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (ret >= 0) {
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL) {
- WOLFSSL_MSG("Error getting memory for EncryptedInfo structure");
- XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
- mem = NULL;
- ret = MEMORY_E;
- }
- }
- #endif /* WOLFSSL_SMALL_STACK */
- if (ret >= 0) {
- int memSz = ret;
- XMEMSET(info, 0, sizeof(EncryptedInfo));
- info->passwd_cb = localCb;
- info->passwd_userdata = pass;
- /* Do not strip PKCS8 header */
- ret = PemToDer((const unsigned char*)mem, memSz, keyType, der, NULL,
- info, eccFlag);
- if (ret < 0) {
- WOLFSSL_MSG("Bad PEM To DER");
- }
- /* Write left over data back to BIO if not a file BIO */
- else if ((memSz - (int)info->consumed) > 0 &&
- bio->type != WOLFSSL_BIO_FILE) {
- if (wolfSSL_BIO_write(bio, mem + (int)info->consumed,
- memSz - (int)info->consumed) <= 0) {
- WOLFSSL_MSG("Unable to advance bio read pointer");
- }
- }
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return ret;
- }
- WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** key,
- wc_pem_password_cb* cb,
- void* pass)
- {
- WOLFSSL_EVP_PKEY* pkey = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
- int type = -1;
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey");
- if (bio == NULL)
- return pkey;
- if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &keyFormat,
- &der) >= 0) {
- const unsigned char* ptr = der->buffer;
- if (keyFormat) {
- /* keyFormat is Key_Sum enum */
- if (keyFormat == RSAk)
- type = EVP_PKEY_RSA;
- else if (keyFormat == ECDSAk)
- type = EVP_PKEY_EC;
- else if (keyFormat == DSAk)
- type = EVP_PKEY_DSA;
- else if (keyFormat == DHk)
- type = EVP_PKEY_DH;
- }
- else {
- /* Default to RSA if format is not set */
- type = EVP_PKEY_RSA;
- }
- /* handle case where reuse is attempted */
- if (key != NULL && *key != NULL)
- pkey = *key;
- wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length);
- if (pkey == NULL) {
- WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
- }
- }
- FreeDer(&der);
- if (key != NULL && pkey != NULL)
- *key = pkey;
- WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", 0);
- return pkey;
- }
- WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY **key,
- wc_pem_password_cb *cb,
- void *pass)
- {
- WOLFSSL_EVP_PKEY* pkey = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY");
- if (bio == NULL)
- return pkey;
- if (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der) >= 0) {
- const unsigned char* ptr = der->buffer;
- /* handle case where reuse is attempted */
- if (key != NULL && *key != NULL)
- pkey = *key;
- wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length);
- if (pkey == NULL) {
- WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
- }
- }
- FreeDer(&der);
- if (key != NULL && pkey != NULL)
- *key = pkey;
- WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 0);
- return pkey;
- }
- #if !defined(NO_FILESYSTEM)
- WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY **x,
- wc_pem_password_cb *cb, void *u)
- {
- int err = 0;
- WOLFSSL_EVP_PKEY* ret = NULL;
- WOLFSSL_BIO* bio = NULL;
- WOLFSSL_ENTER("wolfSSL_PEM_read_PUBKEY");
- if (fp == XBADFILE) {
- err = 1;
- }
- if (err == 0) {
- bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
- err = bio == NULL;
- }
- if (err == 0) {
- err = wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS;
- }
- if (err == 0) {
- ret = wolfSSL_PEM_read_bio_PUBKEY(bio, x, cb, u);
- }
- if (bio != NULL) {
- wolfSSL_BIO_free(bio);
- }
- WOLFSSL_LEAVE("wolfSSL_PEM_read_PUBKEY", 0);
- return ret;
- }
- #endif /* NO_FILESYSTEM */
- #endif /* !NO_BIO */
- #endif /* OPENSSL_EXTRA */
- #ifdef WOLFSSL_ALT_CERT_CHAINS
- int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl)
- {
- int isUsing = 0;
- if (ssl)
- isUsing = ssl->options.usingAltCertChain;
- return isUsing;
- }
- #endif /* WOLFSSL_ALT_CERT_CHAINS */
- #ifdef SESSION_CERTS
- #ifdef WOLFSSL_ALT_CERT_CHAINS
- /* Get peer's alternate certificate chain */
- WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain");
- if (ssl)
- return &ssl->session->altChain;
- return 0;
- }
- #endif /* WOLFSSL_ALT_CERT_CHAINS */
- /* Get peer's certificate chain */
- WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_peer_chain");
- if (ssl)
- return &ssl->session->chain;
- return 0;
- }
- /* Get peer's certificate chain total count */
- int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
- {
- WOLFSSL_ENTER("wolfSSL_get_chain_count");
- if (chain)
- return chain->count;
- return 0;
- }
- /* Get peer's ASN.1 DER certificate at index (idx) length in bytes */
- int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
- {
- WOLFSSL_ENTER("wolfSSL_get_chain_length");
- if (chain)
- return chain->certs[idx].length;
- return 0;
- }
- /* Get peer's ASN.1 DER certificate at index (idx) */
- byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
- {
- WOLFSSL_ENTER("wolfSSL_get_chain_cert");
- if (chain)
- return chain->certs[idx].buffer;
- return 0;
- }
- /* Get peer's wolfSSL X509 certificate at index (idx) */
- WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
- {
- int ret;
- WOLFSSL_X509* x509 = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_get_chain_X509");
- if (chain != NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_DCERT);
- if (cert != NULL)
- #endif
- {
- InitDecodedCert(cert, chain->certs[idx].buffer,
- chain->certs[idx].length, NULL);
- if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) {
- WOLFSSL_MSG("Failed to parse cert");
- }
- else {
- x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
- DYNAMIC_TYPE_X509);
- if (x509 == NULL) {
- WOLFSSL_MSG("Failed alloc X509");
- }
- else {
- InitX509(x509, 1, NULL);
- if ((ret = CopyDecodedToX509(x509, cert)) != 0) {
- WOLFSSL_MSG("Failed to copy decoded");
- wolfSSL_X509_free(x509);
- x509 = NULL;
- }
- }
- }
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
- #endif
- }
- }
- (void)ret;
- return x509;
- }
- /* Get peer's PEM certificate at index (idx), output to buffer if inLen big
- enough else return error (-1). If buffer is NULL only calculate
- outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */
- int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
- unsigned char* buf, int inLen, int* outLen)
- {
- #if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
- const char* header = NULL;
- const char* footer = NULL;
- int headerLen;
- int footerLen;
- int i;
- int err;
- word32 szNeeded = 0;
- WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem");
- if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain))
- return BAD_FUNC_ARG;
- err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer);
- if (err != 0)
- return err;
- headerLen = (int)XSTRLEN(header);
- footerLen = (int)XSTRLEN(footer);
- /* Null output buffer return size needed in outLen */
- if(!buf) {
- if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length,
- NULL, &szNeeded) != LENGTH_ONLY_E)
- return WOLFSSL_FAILURE;
- *outLen = szNeeded + headerLen + footerLen;
- return LENGTH_ONLY_E;
- }
- /* don't even try if inLen too short */
- if (inLen < headerLen + footerLen + chain->certs[idx].length)
- return BAD_FUNC_ARG;
- /* header */
- if (XMEMCPY(buf, header, headerLen) == NULL)
- return WOLFSSL_FATAL_ERROR;
- i = headerLen;
- /* body */
- *outLen = inLen; /* input to Base64_Encode */
- if ( (err = Base64_Encode(chain->certs[idx].buffer,
- chain->certs[idx].length, buf + i, (word32*)outLen)) < 0)
- return err;
- i += *outLen;
- /* footer */
- if ( (i + footerLen) > inLen)
- return BAD_FUNC_ARG;
- if (XMEMCPY(buf + i, footer, footerLen) == NULL)
- return WOLFSSL_FATAL_ERROR;
- *outLen += headerLen + footerLen;
- return WOLFSSL_SUCCESS;
- #else
- (void)chain;
- (void)idx;
- (void)buf;
- (void)inLen;
- (void)outLen;
- return WOLFSSL_FAILURE;
- #endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
- }
- /* get session ID */
- WOLFSSL_ABI
- const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session)
- {
- WOLFSSL_ENTER("wolfSSL_get_sessionID");
- session = ClientSessionToSession(session);
- if (session)
- return session->sessionID;
- return NULL;
- }
- #endif /* SESSION_CERTS */
- #ifdef HAVE_FUZZER
- void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
- {
- if (ssl) {
- ssl->fuzzerCb = cbf;
- ssl->fuzzerCtx = fCtx;
- }
- }
- #endif
- #ifndef NO_CERTS
- #ifdef HAVE_PK_CALLBACKS
- #ifdef HAVE_ECC
- void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
- {
- if (ctx)
- ctx->EccKeyGenCb = cb;
- }
- void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->EccKeyGenCtx = ctx;
- }
- void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->EccKeyGenCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetEccSignCtx(WOLFSSL_CTX* ctx, void *userCtx)
- {
- if (ctx)
- ctx->EccSignCtx = userCtx;
- }
- void* wolfSSL_CTX_GetEccSignCtx(WOLFSSL_CTX* ctx)
- {
- if (ctx)
- return ctx->EccSignCtx;
- return NULL;
- }
- WOLFSSL_ABI
- void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
- {
- if (ctx)
- ctx->EccSignCb = cb;
- }
- void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->EccSignCtx = ctx;
- }
- void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->EccSignCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
- {
- if (ctx)
- ctx->EccVerifyCb = cb;
- }
- void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->EccVerifyCtx = ctx;
- }
- void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->EccVerifyCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb)
- {
- if (ctx)
- ctx->EccSharedSecretCb = cb;
- }
- void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->EccSharedSecretCtx = ctx;
- }
- void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->EccSharedSecretCtx;
- return NULL;
- }
- #endif /* HAVE_ECC */
- #ifdef HAVE_ED25519
- void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb)
- {
- if (ctx)
- ctx->Ed25519SignCb = cb;
- }
- void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->Ed25519SignCtx = ctx;
- }
- void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->Ed25519SignCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
- {
- if (ctx)
- ctx->Ed25519VerifyCb = cb;
- }
- void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->Ed25519VerifyCtx = ctx;
- }
- void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->Ed25519VerifyCtx;
- return NULL;
- }
- #endif /* HAVE_ED25519 */
- #ifdef HAVE_CURVE25519
- void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx,
- CallbackX25519KeyGen cb)
- {
- if (ctx)
- ctx->X25519KeyGenCb = cb;
- }
- void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->X25519KeyGenCtx = ctx;
- }
- void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->X25519KeyGenCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
- CallbackX25519SharedSecret cb)
- {
- if (ctx)
- ctx->X25519SharedSecretCb = cb;
- }
- void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->X25519SharedSecretCtx = ctx;
- }
- void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->X25519SharedSecretCtx;
- return NULL;
- }
- #endif /* HAVE_CURVE25519 */
- #ifdef HAVE_ED448
- void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb)
- {
- if (ctx)
- ctx->Ed448SignCb = cb;
- }
- void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->Ed448SignCtx = ctx;
- }
- void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->Ed448SignCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb)
- {
- if (ctx)
- ctx->Ed448VerifyCb = cb;
- }
- void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->Ed448VerifyCtx = ctx;
- }
- void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->Ed448VerifyCtx;
- return NULL;
- }
- #endif /* HAVE_ED448 */
- #ifdef HAVE_CURVE448
- void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx,
- CallbackX448KeyGen cb)
- {
- if (ctx)
- ctx->X448KeyGenCb = cb;
- }
- void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->X448KeyGenCtx = ctx;
- }
- void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->X448KeyGenCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx,
- CallbackX448SharedSecret cb)
- {
- if (ctx)
- ctx->X448SharedSecretCb = cb;
- }
- void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->X448SharedSecretCtx = ctx;
- }
- void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->X448SharedSecretCtx;
- return NULL;
- }
- #endif /* HAVE_CURVE448 */
- #ifndef NO_RSA
- void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
- {
- if (ctx)
- ctx->RsaSignCb = cb;
- }
- void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
- {
- if (ctx)
- ctx->RsaSignCheckCb = cb;
- }
- void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->RsaSignCtx = ctx;
- }
- void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->RsaSignCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
- {
- if (ctx)
- ctx->RsaVerifyCb = cb;
- }
- void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->RsaVerifyCtx = ctx;
- }
- void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->RsaVerifyCtx;
- return NULL;
- }
- #ifdef WC_RSA_PSS
- void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb)
- {
- if (ctx)
- ctx->RsaPssSignCb = cb;
- }
- void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
- {
- if (ctx)
- ctx->RsaPssSignCheckCb = cb;
- }
- void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->RsaPssSignCtx = ctx;
- }
- void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->RsaPssSignCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
- {
- if (ctx)
- ctx->RsaPssVerifyCb = cb;
- }
- void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->RsaPssVerifyCtx = ctx;
- }
- void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->RsaPssVerifyCtx;
- return NULL;
- }
- #endif /* WC_RSA_PSS */
- void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
- {
- if (ctx)
- ctx->RsaEncCb = cb;
- }
- void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->RsaEncCtx = ctx;
- }
- void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->RsaEncCtx;
- return NULL;
- }
- void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb)
- {
- if (ctx)
- ctx->RsaDecCb = cb;
- }
- void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->RsaDecCtx = ctx;
- }
- void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->RsaDecCtx;
- return NULL;
- }
- #endif /* NO_RSA */
- /* callback for premaster secret generation */
- void wolfSSL_CTX_SetGenPreMasterCb(WOLFSSL_CTX* ctx, CallbackGenPreMaster cb)
- {
- if (ctx)
- ctx->GenPreMasterCb = cb;
- }
- /* Set premaster secret generation callback context */
- void wolfSSL_SetGenPreMasterCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->GenPreMasterCtx = ctx;
- }
- /* Get premaster secret generation callback context */
- void* wolfSSL_GetGenPreMasterCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->GenPreMasterCtx;
- return NULL;
- }
- /* callback for master secret generation */
- void wolfSSL_CTX_SetGenMasterSecretCb(WOLFSSL_CTX* ctx, CallbackGenMasterSecret cb)
- {
- if (ctx)
- ctx->GenMasterCb = cb;
- }
- /* Set master secret generation callback context */
- void wolfSSL_SetGenMasterSecretCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->GenMasterCtx = ctx;
- }
- /* Get master secret generation callback context */
- void* wolfSSL_GetGenMasterSecretCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->GenMasterCtx;
- return NULL;
- }
- /* callback for session key generation */
- void wolfSSL_CTX_SetGenSessionKeyCb(WOLFSSL_CTX* ctx, CallbackGenSessionKey cb)
- {
- if (ctx)
- ctx->GenSessionKeyCb = cb;
- }
- /* Set session key generation callback context */
- void wolfSSL_SetGenSessionKeyCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->GenSessionKeyCtx = ctx;
- }
- /* Get session key generation callback context */
- void* wolfSSL_GetGenSessionKeyCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->GenSessionKeyCtx;
- return NULL;
- }
- /* callback for setting encryption keys */
- void wolfSSL_CTX_SetEncryptKeysCb(WOLFSSL_CTX* ctx, CallbackEncryptKeys cb)
- {
- if (ctx)
- ctx->EncryptKeysCb = cb;
- }
- /* Set encryption keys callback context */
- void wolfSSL_SetEncryptKeysCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->EncryptKeysCtx = ctx;
- }
- /* Get encryption keys callback context */
- void* wolfSSL_GetEncryptKeysCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->EncryptKeysCtx;
- return NULL;
- }
- /* callback for Tls finished */
- /* the callback can be used to build TLS Finished message if enabled */
- void wolfSSL_CTX_SetTlsFinishedCb(WOLFSSL_CTX* ctx, CallbackTlsFinished cb)
- {
- if (ctx)
- ctx->TlsFinishedCb = cb;
- }
- /* Set Tls finished callback context */
- void wolfSSL_SetTlsFinishedCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->TlsFinishedCtx = ctx;
- }
- /* Get Tls finished callback context */
- void* wolfSSL_GetTlsFinishedCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->TlsFinishedCtx;
- return NULL;
- }
- #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY)
- /* callback for verify data */
- void wolfSSL_CTX_SetVerifyMacCb(WOLFSSL_CTX* ctx, CallbackVerifyMac cb)
- {
- if (ctx)
- ctx->VerifyMacCb = cb;
- }
- /* Set set keys callback context */
- void wolfSSL_SetVerifyMacCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->VerifyMacCtx = ctx;
- }
- /* Get set keys callback context */
- void* wolfSSL_GetVerifyMacCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->VerifyMacCtx;
- return NULL;
- }
- #endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
- #endif /* HAVE_PK_CALLBACKS */
- #endif /* NO_CERTS */
- #if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
- void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
- {
- if (ctx)
- ctx->DhAgreeCb = cb;
- }
- void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->DhAgreeCtx = ctx;
- }
- void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->DhAgreeCtx;
- return NULL;
- }
- #endif /* HAVE_PK_CALLBACKS && !NO_DH */
- #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_HKDF)
- void wolfSSL_CTX_SetHKDFExtractCb(WOLFSSL_CTX* ctx, CallbackHKDFExtract cb)
- {
- if (ctx)
- ctx->HkdfExtractCb = cb;
- }
- void wolfSSL_SetHKDFExtractCtx(WOLFSSL* ssl, void *ctx)
- {
- if (ssl)
- ssl->HkdfExtractCtx = ctx;
- }
- void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl)
- {
- if (ssl)
- return ssl->HkdfExtractCtx;
- return NULL;
- }
- #endif /* HAVE_PK_CALLBACKS && HAVE_HKDF */
- #ifdef WOLFSSL_HAVE_WOLFSCEP
- /* Used by autoconf to see if wolfSCEP is available */
- void wolfSSL_wolfSCEP(void) {}
- #endif
- #ifdef WOLFSSL_HAVE_CERT_SERVICE
- /* Used by autoconf to see if cert service is available */
- void wolfSSL_cert_service(void) {}
- #endif
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
- !defined(WOLFCRYPT_ONLY)
- #ifndef NO_CERTS
- #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- /* Convert ASN1 input string into canonical ASN1 string */
- /* , which has the following rules: */
- /* convert to UTF8 */
- /* convert to lower case */
- /* multi-spaces collapsed */
- /* @param asn_out a pointer to ASN1_STRING to be converted */
- /* @param asn_in a pointer to input ASN1_STRING */
- /* @return WOLFSSL_SUCCESS on successful converted, otherwise <=0 error code*/
- int wolfSSL_ASN1_STRING_canon(WOLFSSL_ASN1_STRING* asn_out,
- const WOLFSSL_ASN1_STRING* asn_in)
- {
- char* dst;
- char* src;
- int i, len;
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_canon");
- /* sanity check */
- if (asn_out == NULL || asn_in == NULL) {
- WOLFSSL_MSG("invalid function arguments");
- return BAD_FUNC_ARG;
- }
- switch (asn_in->type) {
- case MBSTRING_UTF8:
- case V_ASN1_PRINTABLESTRING:
- break;
- default:
- WOLFSSL_MSG("just copy string");
- return wolfSSL_ASN1_STRING_copy(asn_out, asn_in);
- }
- /* type is set as UTF8 */
- asn_out->type = MBSTRING_UTF8;
- asn_out->length = wolfSSL_ASN1_STRING_to_UTF8(
- (unsigned char**)&asn_out->data, (WOLFSSL_ASN1_STRING*)asn_in);
- if (asn_out->length < 0) {
- return WOLFSSL_FAILURE;
- }
- /* point to the last */
- dst = asn_out->data + asn_out->length;
- /* point to the start */
- src = asn_out->data;
- len = asn_out->length;
- /* trimming spaces at the head and tail */
- dst--;
- for (; (len > 0 && XISSPACE(*dst)); len--) {
- dst--;
- }
- for (; (len > 0 && XISSPACE(*src)); len--) {
- src++;
- }
- /* point to the start */
- dst = asn_out->data;
- for (i = 0; i < len; dst++, i++) {
- if (!XISASCII(*src)) {
- /* keep non-ascii code */
- *dst = *src++;
- } else if (XISSPACE(*src)) {
- *dst = 0x20; /* space */
- /* remove the rest of spaces */
- while (XISSPACE(*++src) && i++ < len);
- } else {
- *dst = (char)XTOLOWER((unsigned char)*src++);
- }
- }
- /* put actual length */
- asn_out->length = (int)(dst - asn_out->data);
- return WOLFSSL_SUCCESS;
- }
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
- #if !defined(NO_FILESYSTEM)
- #ifndef NO_BIO
- WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_PrivateKey(XFILE fp,
- WOLFSSL_EVP_PKEY **x, wc_pem_password_cb *cb, void *u)
- {
- int err = 0;
- WOLFSSL_EVP_PKEY* ret = NULL;
- WOLFSSL_BIO* bio = NULL;
- WOLFSSL_ENTER("wolfSSL_PEM_read_PrivateKey");
- if (fp == XBADFILE) {
- err = 1;
- }
- if (err == 0) {
- bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
- err = bio == NULL;
- }
- if (err == 0) {
- err = wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS;
- }
- if (err == 0) {
- ret = wolfSSL_PEM_read_bio_PrivateKey(bio, x, cb, u);
- }
- if (bio != NULL) {
- wolfSSL_BIO_free(bio);
- }
- return ret;
- }
- #endif
- #endif
- #endif
- #endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL*/
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
- #define PEM_BEGIN "-----BEGIN "
- #define PEM_BEGIN_SZ 11
- #define PEM_END "-----END "
- #define PEM_END_SZ 9
- #define PEM_HDR_FIN "-----"
- #define PEM_HDR_FIN_SZ 5
- #define PEM_HDR_FIN_EOL_NEWLINE "-----\n"
- #define PEM_HDR_FIN_EOL_NULL_TERM "-----\0"
- #define PEM_HDR_FIN_EOL_SZ 6
- #ifndef NO_BIO
- int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header,
- unsigned char **data, long *len)
- {
- int ret = WOLFSSL_SUCCESS;
- char pem[256];
- int pemLen;
- char* p;
- char* nameStr = NULL;
- int nameLen = 0;
- char* headerStr = NULL;
- int headerLen;
- int headerFound = 0;
- unsigned char* der = NULL;
- word32 derLen = 0;
- if (bio == NULL || name == NULL || header == NULL || data == NULL ||
- len == NULL) {
- return WOLFSSL_FAILURE;
- }
- /* Find header line. */
- pem[sizeof(pem) - 1] = '\0';
- while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
- if (XSTRNCMP(pem, PEM_BEGIN, PEM_BEGIN_SZ) == 0)
- break;
- }
- if (pemLen <= 0)
- ret = WOLFSSL_FAILURE;
- /* Have a header line. */
- if (ret == WOLFSSL_SUCCESS) {
- while (pem[pemLen - 1] == '\r' || pem[pemLen - 1] == '\n')
- pemLen--;
- pem[pemLen] = '\0';
- if (XSTRNCMP(pem + pemLen - PEM_HDR_FIN_SZ, PEM_HDR_FIN,
- PEM_HDR_FIN_SZ) != 0) {
- ret = WOLFSSL_FAILURE;
- }
- }
- /* Get out name. */
- if (ret == WOLFSSL_SUCCESS) {
- nameLen = pemLen - PEM_BEGIN_SZ - PEM_HDR_FIN_SZ;
- nameStr = (char*)XMALLOC(nameLen + 1, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (nameStr == NULL)
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- XSTRNCPY(nameStr, pem + PEM_BEGIN_SZ, nameLen);
- nameStr[nameLen] = '\0';
- /* Get header of PEM - encryption header. */
- headerLen = 0;
- while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
- while (pemLen > 0 && (pem[pemLen - 1] == '\r' ||
- pem[pemLen - 1] == '\n')) {
- pemLen--;
- }
- pem[pemLen++] = '\n';
- pem[pemLen] = '\0';
- /* Header separator is a blank line. */
- if (pem[0] == '\n') {
- headerFound = 1;
- break;
- }
- /* Didn't find a blank line - no header. */
- if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) {
- der = (unsigned char*)headerStr;
- derLen = headerLen;
- /* Empty header - empty string. */
- headerStr = (char*)XMALLOC(1, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (headerStr == NULL)
- ret = WOLFSSL_FAILURE;
- else
- headerStr[0] = '\0';
- break;
- }
- p = (char*)XREALLOC(headerStr, headerLen + pemLen + 1, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (p == NULL) {
- ret = WOLFSSL_FAILURE;
- break;
- }
- headerStr = p;
- XMEMCPY(headerStr + headerLen, pem, pemLen + 1);
- headerLen += pemLen;
- }
- if (pemLen <= 0)
- ret = WOLFSSL_FAILURE;
- }
- /* Get body of PEM - if there was a header */
- if (ret == WOLFSSL_SUCCESS && headerFound) {
- derLen = 0;
- while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
- while (pemLen > 0 && (pem[pemLen - 1] == '\r' ||
- pem[pemLen - 1] == '\n')) {
- pemLen--;
- }
- pem[pemLen++] = '\n';
- pem[pemLen] = '\0';
- if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0)
- break;
- p = (char*)XREALLOC(der, derLen + pemLen + 1, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (p == NULL) {
- ret = WOLFSSL_FAILURE;
- break;
- }
- der = (unsigned char*)p;
- XMEMCPY(der + derLen, pem, pemLen + 1);
- derLen += pemLen;
- }
- if (pemLen <= 0)
- ret = WOLFSSL_FAILURE;
- }
- /* Check trailer. */
- if (ret == WOLFSSL_SUCCESS) {
- if (XSTRNCMP(pem + PEM_END_SZ, nameStr, nameLen) != 0)
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (XSTRNCMP(pem + PEM_END_SZ + nameLen,
- PEM_HDR_FIN_EOL_NEWLINE,
- PEM_HDR_FIN_EOL_SZ) != 0 &&
- XSTRNCMP(pem + PEM_END_SZ + nameLen,
- PEM_HDR_FIN_EOL_NULL_TERM,
- PEM_HDR_FIN_EOL_SZ) != 0) {
- ret = WOLFSSL_FAILURE;
- }
- }
- /* Base64 decode body. */
- if (ret == WOLFSSL_SUCCESS) {
- if (Base64_Decode(der, derLen, der, &derLen) != 0)
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- *name = nameStr;
- *header = headerStr;
- *data = der;
- *len = derLen;
- nameStr = NULL;
- headerStr = NULL;
- der = NULL;
- }
- if (nameStr != NULL)
- XFREE(nameStr, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (headerStr != NULL)
- XFREE(headerStr, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (der != NULL)
- XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name,
- const char *header, const unsigned char *data,
- long len)
- {
- int err = 0;
- int outSz = 0;
- int nameLen;
- int headerLen;
- byte* pem = NULL;
- word32 pemLen;
- word32 derLen = (word32)len;
- if (bio == NULL || name == NULL || header == NULL || data == NULL)
- return 0;
- nameLen = (int)XSTRLEN(name);
- headerLen = (int)XSTRLEN(header);
- pemLen = (derLen + 2) / 3 * 4;
- pemLen += (pemLen + 63) / 64;
- pem = (byte*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- err = pem == NULL;
- if (!err)
- err = Base64_Encode(data, derLen, pem, &pemLen) != 0;
- if (!err) {
- err = wolfSSL_BIO_write(bio, PEM_BEGIN, PEM_BEGIN_SZ) !=
- (int)PEM_BEGIN_SZ;
- }
- if (!err)
- err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen;
- if (!err) {
- err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE,
- PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ;
- }
- if (!err && headerLen > 0) {
- err = wolfSSL_BIO_write(bio, header, headerLen) != headerLen;
- /* Blank line after a header and before body. */
- if (!err)
- err = wolfSSL_BIO_write(bio, "\n", 1) != 1;
- headerLen++;
- }
- if (!err)
- err = wolfSSL_BIO_write(bio, pem, pemLen) != (int)pemLen;
- if (!err)
- err = wolfSSL_BIO_write(bio, PEM_END, PEM_END_SZ) !=
- (int)PEM_END_SZ;
- if (!err)
- err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen;
- if (!err) {
- err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE,
- PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ;
- }
- if (!err) {
- outSz = PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ + headerLen +
- pemLen + PEM_END_SZ + nameLen + PEM_HDR_FIN_EOL_SZ;
- }
- if (pem != NULL)
- XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return outSz;
- }
- #if !defined(NO_FILESYSTEM)
- int wolfSSL_PEM_read(XFILE fp, char **name, char **header,
- unsigned char **data, long *len)
- {
- int ret;
- WOLFSSL_BIO* bio;
- if (name == NULL || header == NULL || data == NULL || len == NULL)
- return WOLFSSL_FAILURE;
- bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
- if (bio == NULL)
- return 0;
- if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
- wolfSSL_BIO_free(bio);
- bio = NULL;
- }
- ret = wolfSSL_PEM_read_bio(bio, name, header, data, len);
- if (bio != NULL)
- wolfSSL_BIO_free(bio);
- return ret;
- }
- int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header,
- const unsigned char *data, long len)
- {
- int ret;
- WOLFSSL_BIO* bio;
- if (name == NULL || header == NULL || data == NULL)
- return 0;
- bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
- if (bio == NULL)
- return 0;
- if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
- wolfSSL_BIO_free(bio);
- bio = NULL;
- }
- ret = wolfSSL_PEM_write_bio(bio, name, header, data, len);
- if (bio != NULL)
- wolfSSL_BIO_free(bio);
- return ret;
- }
- #endif
- #endif /* !NO_BIO */
- int wolfSSL_PEM_get_EVP_CIPHER_INFO(const char* header,
- EncryptedInfo* cipher)
- {
- if (header == NULL || cipher == NULL)
- return WOLFSSL_FAILURE;
- XMEMSET(cipher, 0, sizeof(*cipher));
- if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0)
- return WOLFSSL_FAILURE;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data,
- long* len, wc_pem_password_cb* callback,
- void* ctx)
- {
- int ret = WOLFSSL_SUCCESS;
- char password[NAME_SZ];
- int passwordSz;
- if (cipher == NULL || data == NULL || len == NULL || callback == NULL)
- return WOLFSSL_FAILURE;
- passwordSz = callback(password, sizeof(password), PEM_PASS_READ, ctx);
- if (passwordSz < 0)
- ret = WOLFSSL_FAILURE;
- if (ret == WOLFSSL_SUCCESS) {
- if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password,
- passwordSz, WC_MD5) != 0) {
- ret = WOLFSSL_FAILURE;
- }
- }
- if (passwordSz > 0)
- XMEMSET(password, 0, passwordSz);
- return ret;
- }
- #ifndef NO_BIO
- /*
- * bp : bio to read X509 from
- * x : x509 to write to
- * cb : password call back for reading PEM
- * u : password
- * _AUX is for working with a trusted X509 certificate
- */
- WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp,
- WOLFSSL_X509 **x, wc_pem_password_cb *cb,
- void *u)
- {
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
- /* AUX info is; trusted/rejected uses, friendly name, private key id,
- * and potentially a stack of "other" info. wolfSSL does not store
- * friendly name or private key id yet in WOLFSSL_X509 for human
- * readability and does not support extra trusted/rejected uses for
- * root CA. */
- return wolfSSL_PEM_read_bio_X509(bp, x, cb, u);
- }
- #endif /* !NO_BIO */
- #endif /* OPENSSL_EXTRA || OPENSSL_ALL */
- #endif /* !NO_CERTS */
- /* NID variables are dependent on compatibility header files currently
- *
- * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL
- * on fail
- */
- WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id)
- {
- return wolfSSL_OBJ_nid2obj_ex(id, NULL);
- }
- WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int id,
- WOLFSSL_ASN1_OBJECT* arg_obj)
- {
- word32 oidSz = 0;
- int nid = 0;
- const byte* oid;
- word32 type = 0;
- WOLFSSL_ASN1_OBJECT* obj = arg_obj;
- byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */
- word32 objSz = 0;
- const char* sName = NULL;
- int i;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj()");
- #endif
- for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) {
- if (wolfssl_object_info[i].nid == id) {
- nid = id;
- id = wolfssl_object_info[i].id;
- sName = wolfssl_object_info[i].sName;
- type = wolfssl_object_info[i].type;
- break;
- }
- }
- if (i == (int)WOLFSSL_OBJECT_INFO_SZ) {
- WOLFSSL_MSG("NID not in table");
- #ifdef WOLFSSL_QT
- sName = NULL;
- type = id;
- #else
- return NULL;
- #endif
- }
- #ifdef HAVE_ECC
- if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) {
- type = oidCurveType;
- }
- #endif /* HAVE_ECC */
- if (sName != NULL) {
- if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) {
- WOLFSSL_MSG("Attempted short name is too large");
- return NULL;
- }
- }
- oid = OidFromId(id, type, &oidSz);
- /* set object ID to buffer */
- if (obj == NULL){
- obj = wolfSSL_ASN1_OBJECT_new();
- if (obj == NULL) {
- WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
- return NULL;
- }
- }
- obj->nid = nid;
- obj->type = id;
- obj->grp = type;
- obj->sName[0] = '\0';
- if (sName != NULL) {
- XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName));
- }
- objBuf[0] = ASN_OBJECT_ID; objSz++;
- objSz += SetLength(oidSz, objBuf + 1);
- if (oidSz) {
- XMEMCPY(objBuf + objSz, oid, oidSz);
- objSz += oidSz;
- }
- if (obj->objSz == 0 || objSz != obj->objSz) {
- obj->objSz = objSz;
- if(((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
- (obj->obj == NULL)) {
- if (obj->obj != NULL)
- XFREE((byte*)obj->obj, NULL, DYNAMIC_TYPE_ASN1);
- obj->obj = (byte*)XMALLOC(obj->objSz, NULL, DYNAMIC_TYPE_ASN1);
- if (obj->obj == NULL) {
- wolfSSL_ASN1_OBJECT_free(obj);
- return NULL;
- }
- obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ;
- }
- else {
- obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ;
- }
- }
- XMEMCPY((byte*)obj->obj, objBuf, obj->objSz);
- (void)type;
- return obj;
- }
- static const char* oid_translate_num_to_str(const char* oid)
- {
- const struct oid_dict {
- const char* num;
- const char* desc;
- } oid_dict[] = {
- { "2.5.29.37.0", "Any Extended Key Usage" },
- { "1.3.6.1.5.5.7.3.1", "TLS Web Server Authentication" },
- { "1.3.6.1.5.5.7.3.2", "TLS Web Client Authentication" },
- { "1.3.6.1.5.5.7.3.3", "Code Signing" },
- { "1.3.6.1.5.5.7.3.4", "E-mail Protection" },
- { "1.3.6.1.5.5.7.3.8", "Time Stamping" },
- { "1.3.6.1.5.5.7.3.9", "OCSP Signing" },
- { NULL, NULL }
- };
- const struct oid_dict* idx;
- for (idx = oid_dict; idx->num != NULL; idx++) {
- if (!XSTRCMP(oid, idx->num)) {
- return idx->desc;
- }
- }
- return NULL;
- }
- static int wolfssl_obj2txt_numeric(char *buf, int bufLen,
- const WOLFSSL_ASN1_OBJECT *a)
- {
- int bufSz;
- int length;
- word32 idx = 0;
- byte tag;
- if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) {
- return WOLFSSL_FAILURE;
- }
- if (tag != ASN_OBJECT_ID) {
- WOLFSSL_MSG("Bad ASN1 Object");
- return WOLFSSL_FAILURE;
- }
- if (GetLength((const byte*)a->obj, &idx, &length,
- a->objSz) < 0 || length < 0) {
- return ASN_PARSE_E;
- }
- if (bufLen < MAX_OID_STRING_SZ) {
- bufSz = bufLen - 1;
- }
- else {
- bufSz = MAX_OID_STRING_SZ;
- }
- if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx,
- (word32)length)) <= 0) {
- WOLFSSL_MSG("Error decoding OID");
- return WOLFSSL_FAILURE;
- }
- buf[bufSz] = '\0';
- return bufSz;
- }
- /* If no_name is one then use numerical form, otherwise short name.
- *
- * Returns the buffer size on success, WOLFSSL_FAILURE on error
- */
- int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, const WOLFSSL_ASN1_OBJECT *a,
- int no_name)
- {
- int bufSz;
- const char* desc;
- const char* name;
- WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt()");
- if (buf == NULL || bufLen <= 1 || a == NULL) {
- WOLFSSL_MSG("Bad input argument");
- return WOLFSSL_FAILURE;
- }
- if (no_name == 1) {
- return wolfssl_obj2txt_numeric(buf, bufLen, a);
- }
- /* return long name unless using x509small, then return short name */
- #if defined(OPENSSL_EXTRA_X509_SMALL) && !defined(OPENSSL_EXTRA)
- name = a->sName;
- #else
- name = wolfSSL_OBJ_nid2ln(wolfSSL_OBJ_obj2nid(a));
- #endif
- if (name == NULL) {
- WOLFSSL_MSG("Name not found");
- bufSz = 0;
- }
- else if (XSTRLEN(name) + 1 < (word32)bufLen - 1) {
- bufSz = (int)XSTRLEN(name);
- }
- else {
- bufSz = bufLen - 1;
- }
- if (bufSz) {
- XMEMCPY(buf, name, bufSz);
- }
- else if (a->type == GEN_DNS || a->type == GEN_EMAIL ||
- a->type == GEN_URI) {
- bufSz = (int)XSTRLEN((const char*)a->obj);
- XMEMCPY(buf, a->obj, min(bufSz, bufLen));
- }
- else if ((bufSz = wolfssl_obj2txt_numeric(buf, bufLen, a)) > 0) {
- if ((desc = oid_translate_num_to_str(buf))) {
- bufSz = (int)XSTRLEN(desc);
- bufSz = min(bufSz, bufLen - 1);
- XMEMCPY(buf, desc, bufSz);
- }
- }
- buf[bufSz] = '\0';
- return bufSz;
- }
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- #if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
- defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS_SMALL)
- /* Returns the long name that corresponds with an ASN1_OBJECT nid value.
- * n : NID value of ASN1_OBJECT to search */
- const char* wolfSSL_OBJ_nid2ln(int n)
- {
- const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
- size_t i;
- WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln");
- for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
- if (obj_info->nid == n) {
- return obj_info->lName;
- }
- }
- WOLFSSL_MSG("NID not found in table");
- return NULL;
- }
- #endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL,
- WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY, WOLFSSL_WPAS_SMALL */
- #if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
- defined(WOLFSSL_HAPROXY)
- char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate");
- if (!ctx || !x || !x->derCert) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- FreeDer(&ctx->certificate); /* Make sure previous is free'd */
- ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE,
- ctx->heap);
- if (ret != 0)
- return WOLFSSL_FAILURE;
- XMEMCPY(ctx->certificate->buffer, x->derCert->buffer,
- x->derCert->length);
- #ifdef KEEP_OUR_CERT
- if (ctx->ourCert != NULL && ctx->ownOurCert) {
- wolfSSL_X509_free(ctx->ourCert);
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ctx->ourCert = x;
- if (wolfSSL_X509_up_ref(x) != 1) {
- return WOLFSSL_FAILURE;
- }
- #else
- ctx->ourCert = wolfSSL_X509_d2i(NULL, x->derCert->buffer,x->derCert->length);
- if(ctx->ourCert == NULL){
- return WOLFSSL_FAILURE;
- }
- #endif
- /* We own the cert because either we up its reference counter
- * or we create our own copy of the cert object. */
- ctx->ownOurCert = 1;
- #endif
- /* Update the available options with public keys. */
- switch (x->pubKeyOID) {
- #ifndef NO_RSA
- #ifdef WC_RSA_PSS
- case RSAPSSk:
- #endif
- case RSAk:
- ctx->haveRSA = 1;
- break;
- #endif
- #ifdef HAVE_ED25519
- case ED25519k:
- #endif
- #ifdef HAVE_ED448
- case ED448k:
- #endif
- case ECDSAk:
- ctx->haveECC = 1;
- #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
- ctx->pkCurveOID = x->pkCurveOID;
- #endif
- break;
- }
- return WOLFSSL_SUCCESS;
- }
- static int PushCertToDerBuffer(DerBuffer** inOutDer, int weOwn,
- byte* cert, word32 certSz, void* heap)
- {
- int ret;
- DerBuffer* inChain = NULL;
- DerBuffer* der = NULL;
- word32 len = 0;
- if (inOutDer == NULL)
- return BAD_FUNC_ARG;
- inChain = *inOutDer;
- if (inChain != NULL)
- len = inChain->length;
- ret = AllocDer(&der, len + CERT_HEADER_SZ + certSz, CERT_TYPE,
- heap);
- if (ret != 0) {
- WOLFSSL_MSG("AllocDer error");
- return ret;
- }
- if (inChain != NULL)
- XMEMCPY(der->buffer, inChain->buffer, len);
- c32to24(certSz, der->buffer + len);
- XMEMCPY(der->buffer + len + CERT_HEADER_SZ, cert, certSz);
- if (weOwn)
- FreeDer(inOutDer);
- *inOutDer = der;
- return WOLFSSL_SUCCESS;
- }
- /**
- * wolfSSL_CTX_add1_chain_cert makes a copy of the cert so we free it
- * on success
- */
- int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_add0_chain_cert");
- if (wolfSSL_CTX_add1_chain_cert(ctx, x509) != WOLFSSL_SUCCESS) {
- return WOLFSSL_FAILURE;
- }
- wolfSSL_X509_free(x509);
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_CTX_add1_chain_cert");
- if (ctx == NULL || x509 == NULL || x509->derCert == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (ctx->certificate == NULL)
- ret = (int)wolfSSL_CTX_use_certificate(ctx, x509);
- else {
- if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_up_ref error");
- return WOLFSSL_FAILURE;
- }
- ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer,
- x509->derCert->length, WOLFSSL_FILETYPE_ASN1);
- if (ret == WOLFSSL_SUCCESS) {
- /* push to ctx->certChain */
- ret = PushCertToDerBuffer(&ctx->certChain, 1,
- x509->derCert->buffer, x509->derCert->length, ctx->heap);
- }
- /* Store cert to free it later */
- if (ret == WOLFSSL_SUCCESS && ctx->x509Chain == NULL) {
- ctx->x509Chain = wolfSSL_sk_X509_new();
- if (ctx->x509Chain == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_new error");
- ret = WOLFSSL_FAILURE;
- }
- }
- if (ret == WOLFSSL_SUCCESS &&
- wolfSSL_sk_X509_push(ctx->x509Chain, x509)
- != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_sk_X509_push error");
- ret = WOLFSSL_FAILURE;
- }
- if (ret != WOLFSSL_SUCCESS)
- wolfSSL_X509_free(x509); /* Decrease ref counter */
- }
- return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- #ifdef KEEP_OUR_CERT
- int wolfSSL_add0_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_add0_chain_cert");
- if (ssl == NULL || ssl->ctx == NULL || x509 == NULL ||
- x509->derCert == NULL)
- return WOLFSSL_FAILURE;
- if (ssl->buffers.certificate == NULL) {
- ret = wolfSSL_use_certificate(ssl, x509);
- /* Store cert to free it later */
- if (ret == WOLFSSL_SUCCESS) {
- if (ssl->buffers.weOwnCert)
- wolfSSL_X509_free(ssl->ourCert);
- ssl->ourCert = x509;
- ssl->buffers.weOwnCert = 1;
- }
- }
- else {
- ret = PushCertToDerBuffer(&ssl->buffers.certChain,
- ssl->buffers.weOwnCertChain, x509->derCert->buffer,
- x509->derCert->length, ssl->heap);
- if (ret == WOLFSSL_SUCCESS) {
- ssl->buffers.weOwnCertChain = 1;
- /* Store cert to free it later */
- if (ssl->ourCertChain == NULL) {
- ssl->ourCertChain = wolfSSL_sk_X509_new();
- if (ssl->ourCertChain == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_new error");
- return WOLFSSL_FAILURE;
- }
- }
- if (wolfSSL_sk_X509_push(ssl->ourCertChain, x509)
- != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_sk_X509_push error");
- return WOLFSSL_FAILURE;
- }
- }
- }
- return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- int wolfSSL_add1_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_add1_chain_cert");
- if (ssl == NULL || ssl->ctx == NULL || x509 == NULL ||
- x509->derCert == NULL)
- return WOLFSSL_FAILURE;
- if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_up_ref error");
- return WOLFSSL_FAILURE;
- }
- ret = wolfSSL_add0_chain_cert(ssl, x509);
- /* Decrease ref counter on error */
- if (ret != WOLFSSL_SUCCESS)
- wolfSSL_X509_free(x509);
- return ret;
- }
- #endif
- /* Return the corresponding short name for the nid <n>.
- * or NULL if short name can't be found.
- */
- const char * wolfSSL_OBJ_nid2sn(int n) {
- const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
- size_t i;
- WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn");
- if (n == NID_md5) {
- /* NID_surname == NID_md5 and NID_surname comes before NID_md5 in
- * wolfssl_object_info. As a result, the loop below will incorrectly
- * return "SN" instead of "MD5." NID_surname isn't the true OpenSSL
- * NID, but other functions rely on this table and modifying it to
- * conform with OpenSSL's NIDs isn't trivial. */
- return "MD5";
- }
- for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
- if (obj_info->nid == n) {
- return obj_info->sName;
- }
- }
- WOLFSSL_MSG("SN not found");
- return NULL;
- }
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- int wolfSSL_OBJ_sn2nid(const char *sn) {
- WOLFSSL_ENTER("wolfSSL_OBJ_sn2nid");
- if (sn == NULL)
- return NID_undef;
- return wc_OBJ_sn2nid(sn);
- }
- #endif
- size_t wolfSSL_OBJ_length(const WOLFSSL_ASN1_OBJECT* o)
- {
- size_t ret = 0;
- int err = 0;
- word32 idx = 0;
- int len = 0;
- WOLFSSL_ENTER("wolfSSL_OBJ_length");
- if (o == NULL || o->obj == NULL) {
- WOLFSSL_MSG("Bad argument.");
- err = 1;
- }
- if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) {
- WOLFSSL_MSG("Error parsing ASN.1 header.");
- err = 1;
- }
- if (err == 0) {
- ret = len;
- }
- WOLFSSL_LEAVE("wolfSSL_OBJ_length", (int)ret);
- return ret;
- }
- const unsigned char* wolfSSL_OBJ_get0_data(const WOLFSSL_ASN1_OBJECT* o)
- {
- const unsigned char* ret = NULL;
- int err = 0;
- word32 idx = 0;
- int len = 0;
- WOLFSSL_ENTER("wolfSSL_OBJ_get0_data");
- if (o == NULL || o->obj == NULL) {
- WOLFSSL_MSG("Bad argument.");
- err = 1;
- }
- if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) {
- WOLFSSL_MSG("Error parsing ASN.1 header.");
- err = 1;
- }
- if (err == 0) {
- ret = o->obj + idx;
- }
- return ret;
- }
- /* Gets the NID value that corresponds with the ASN1 object.
- *
- * o ASN1 object to get NID of
- *
- * Return NID on success and a negative value on failure
- */
- int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o)
- {
- word32 oid = 0;
- word32 idx = 0;
- int ret;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid");
- #endif
- if (o == NULL) {
- return -1;
- }
- #ifdef WOLFSSL_QT
- if (o->grp == oidCertExtType) {
- /* If nid is an unknown extension, return NID_undef */
- if (wolfSSL_OBJ_nid2sn(o->nid) == NULL)
- return NID_undef;
- }
- #endif
- if (o->nid > 0)
- return o->nid;
- if ((ret = GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz)) < 0) {
- if (ret == ASN_OBJECT_ID_E) {
- /* Put ASN object tag in front and try again */
- int len = SetObjectId(o->objSz, NULL) + o->objSz;
- byte* buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (!buf) {
- WOLFSSL_MSG("malloc error");
- return -1;
- }
- idx = SetObjectId(o->objSz, buf);
- XMEMCPY(buf + idx, o->obj, o->objSz);
- idx = 0;
- ret = GetObjectId(buf, &idx, &oid, o->grp, len);
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret < 0) {
- WOLFSSL_MSG("Issue getting OID of object");
- return -1;
- }
- }
- else {
- WOLFSSL_MSG("Issue getting OID of object");
- return -1;
- }
- }
- return oid2nid(oid, o->grp);
- }
- /* Return the corresponding NID for the long name <ln>
- * or NID_undef if NID can't be found.
- */
- int wolfSSL_OBJ_ln2nid(const char *ln)
- {
- const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
- size_t i, lnlen;
- WOLFSSL_ENTER("wolfSSL_OBJ_ln2nid");
- if (ln && (lnlen = XSTRLEN(ln)) > 0) {
- /* Accept input like "/commonName=" */
- if (ln[0] == '/') {
- ln++;
- lnlen--;
- }
- if (lnlen) {
- if (ln[lnlen-1] == '=') {
- lnlen--;
- }
- for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
- if (lnlen == XSTRLEN(obj_info->lName) &&
- XSTRNCMP(ln, obj_info->lName, lnlen) == 0) {
- return obj_info->nid;
- }
- }
- }
- }
- return NID_undef;
- }
- /* compares two objects, return 0 if equal */
- int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a,
- const WOLFSSL_ASN1_OBJECT* b)
- {
- WOLFSSL_ENTER("wolfSSL_OBJ_cmp");
- if (a && b && a->obj && b->obj) {
- if (a->objSz == b->objSz) {
- return XMEMCMP(a->obj, b->obj, a->objSz);
- }
- else if (a->type == EXT_KEY_USAGE_OID ||
- b->type == EXT_KEY_USAGE_OID) {
- /* Special case for EXT_KEY_USAGE_OID so that
- * cmp will be treated as a substring search */
- /* Used in libest to check for id-kp-cmcRA in
- * EXT_KEY_USAGE extension */
- unsigned int idx;
- const byte* s; /* shorter */
- unsigned int sLen;
- const byte* l; /* longer */
- unsigned int lLen;
- if (a->objSz > b->objSz) {
- s = b->obj; sLen = b->objSz;
- l = a->obj; lLen = a->objSz;
- }
- else {
- s = a->obj; sLen = a->objSz;
- l = b->obj; lLen = b->objSz;
- }
- for (idx = 0; idx <= lLen - sLen; idx++) {
- if (XMEMCMP(l + idx, s, sLen) == 0) {
- /* Found substring */
- return 0;
- }
- }
- }
- }
- return WOLFSSL_FATAL_ERROR;
- }
- #endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL,
- WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
- defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
- defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
- defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY)
- /* Gets the NID value that is related to the OID string passed in. Example
- * string would be "2.5.29.14" for subject key ID.
- *
- * returns NID value on success and NID_undef on error
- */
- int wolfSSL_OBJ_txt2nid(const char* s)
- {
- unsigned int i;
- #ifdef WOLFSSL_CERT_EXT
- int ret;
- unsigned int sum = 0;
- unsigned int outSz = MAX_OID_SZ;
- unsigned char out[MAX_OID_SZ];
- #endif
- WOLFSSL_ENTER("OBJ_txt2nid");
- if (s == NULL) {
- return NID_undef;
- }
- #ifdef WOLFSSL_CERT_EXT
- ret = EncodePolicyOID(out, &outSz, s, NULL);
- if (ret == 0) {
- /* sum OID */
- for (i = 0; i < outSz; i++) {
- sum += out[i];
- }
- }
- #endif /* WOLFSSL_CERT_EXT */
- /* get the group that the OID's sum is in
- * @TODO possible conflict with multiples */
- for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) {
- int len;
- #ifdef WOLFSSL_CERT_EXT
- if (ret == 0) {
- if (wolfssl_object_info[i].id == (int)sum) {
- return wolfssl_object_info[i].nid;
- }
- }
- #endif
- /* try as a short name */
- len = (int)XSTRLEN(s);
- if ((int)XSTRLEN(wolfssl_object_info[i].sName) == len &&
- XSTRNCMP(wolfssl_object_info[i].sName, s, len) == 0) {
- return wolfssl_object_info[i].nid;
- }
- /* try as a long name */
- if ((int)XSTRLEN(wolfssl_object_info[i].lName) == len &&
- XSTRNCMP(wolfssl_object_info[i].lName, s, len) == 0) {
- return wolfssl_object_info[i].nid;
- }
- }
- return NID_undef;
- }
- #endif
- #if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
- defined(WOLFSSL_HAPROXY)
- /* Creates new ASN1_OBJECT from short name, long name, or text
- * representation of oid. If no_name is 0, then short name, long name, and
- * numerical value of oid are interpreted. If no_name is 1, then only the
- * numerical value of the oid is interpreted.
- *
- * Returns pointer to ASN1_OBJECT on success, or NULL on error.
- */
- #if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)
- WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name)
- {
- int i, ret;
- int nid = NID_undef;
- unsigned int outSz = MAX_OID_SZ;
- unsigned char out[MAX_OID_SZ];
- WOLFSSL_ASN1_OBJECT* obj;
- WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj");
- if (s == NULL)
- return NULL;
- /* If s is numerical value, try to sum oid */
- ret = EncodePolicyOID(out, &outSz, s, NULL);
- if (ret == 0 && outSz > 0) {
- /* If numerical encode succeeded then just
- * create object from that because sums are
- * not unique and can cause confusion. */
- obj = wolfSSL_ASN1_OBJECT_new();
- if (obj == NULL) {
- WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
- return NULL;
- }
- obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
- obj->obj = (byte*)XMALLOC(1 + MAX_LENGTH_SZ + outSz, NULL,
- DYNAMIC_TYPE_ASN1);
- if (obj->obj == NULL) {
- wolfSSL_ASN1_OBJECT_free(obj);
- return NULL;
- }
- obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ;
- i = SetObjectId(outSz, (byte*)obj->obj);
- XMEMCPY((byte*)obj->obj + i, out, outSz);
- obj->objSz = i + outSz;
- return obj;
- }
- /* TODO: update short names in wolfssl_object_info and check OID sums
- are correct */
- for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) {
- /* Short name, long name, and numerical value are interpreted */
- if (no_name == 0 &&
- ((XSTRCMP(s, wolfssl_object_info[i].sName) == 0) ||
- (XSTRCMP(s, wolfssl_object_info[i].lName) == 0)))
- {
- nid = wolfssl_object_info[i].nid;
- }
- }
- if (nid != NID_undef)
- return wolfSSL_OBJ_nid2obj(nid);
- return NULL;
- }
- #endif
- /* compatibility function. Its intended use is to remove OID's from an
- * internal table that have been added with OBJ_create. wolfSSL manages its
- * own internal OID values and does not currently support OBJ_create. */
- void wolfSSL_OBJ_cleanup(void)
- {
- WOLFSSL_ENTER("wolfSSL_OBJ_cleanup()");
- }
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln)
- {
- (void)oid;
- (void)sn;
- (void)ln;
- WOLFSSL_STUB("wolfSSL_OBJ_create");
- return WOLFSSL_FAILURE;
- }
- #endif
- void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth)
- {
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- WOLFSSL_ENTER("wolfSSL_set_verify_depth");
- ssl->options.verifyDepth = (byte)depth;
- #endif
- }
- #endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE ||
- HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
- defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
- defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
- defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY)
- WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne)
- {
- WOLFSSL_ASN1_OBJECT* obj = NULL;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object");
- #endif
- if (ne == NULL) return NULL;
- obj = wolfSSL_OBJ_nid2obj_ex(ne->nid, ne->object);
- if (obj != NULL) {
- obj->nid = ne->nid;
- return obj;
- }
- return NULL;
- }
- #endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE ||
- HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
- #ifdef OPENSSL_EXTRA
- /* wolfSSL uses negative values for error states. This function returns an
- * unsigned type so the value returned is the absolute value of the error.
- */
- unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
- (void)line;
- (void)file;
- #ifdef WOLFSSL_HAVE_ERROR_QUEUE
- {
- int ret;
- if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
- WOLFSSL_MSG("Issue peeking at error node in queue");
- return 0;
- }
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
- if (ret == -ASN_NO_PEM_HEADER)
- return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
- #endif
- #if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON)
- if (ret == ASN1_R_HEADER_TOO_LONG) {
- return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG;
- }
- #endif
- return (unsigned long)ret;
- }
- #else
- return (unsigned long)(0 - NOT_COMPILED_IN);
- #endif
- }
- #ifndef NO_CERTS
- int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey");
- if (ctx == NULL || pkey == NULL) {
- return WOLFSSL_FAILURE;
- }
- switch (pkey->type) {
- #if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) && !defined(NO_RSA)
- case EVP_PKEY_RSA:
- WOLFSSL_MSG("populating RSA key");
- if (PopulateRSAEvpPkeyDer(pkey) != WOLFSSL_SUCCESS)
- return WOLFSSL_FAILURE;
- break;
- #endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA */
- #if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \
- defined(WOLFSSL_CERT_GEN)) && !defined(NO_DSA)
- case EVP_PKEY_DSA:
- break;
- #endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) && !NO_DSA */
- #ifdef HAVE_ECC
- case EVP_PKEY_EC:
- WOLFSSL_MSG("populating ECC key");
- if (ECC_populate_EVP_PKEY(pkey, pkey->ecc)
- != WOLFSSL_SUCCESS)
- return WOLFSSL_FAILURE;
- break;
- #endif
- default:
- return WOLFSSL_FAILURE;
- }
- if (pkey->pkey.ptr != NULL) {
- /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */
- return wolfSSL_CTX_use_PrivateKey_buffer(ctx,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, SSL_FILETYPE_ASN1);
- }
- WOLFSSL_MSG("wolfSSL private key not set");
- return BAD_FUNC_ARG;
- }
- #endif /* !NO_CERTS */
- #endif /* OPENSSL_EXTRA */
- #if defined(HAVE_EX_DATA) && \
- (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
- defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \
- defined(HAVE_LIGHTY)) || defined(HAVE_EX_DATA) || \
- defined(WOLFSSL_WPAS_SMALL)
- /**
- * get_ex_new_index is a helper function for the following
- * xx_get_ex_new_index functions:
- * - wolfSSL_CRYPTO_get_ex_new_index
- * - wolfSSL_CTX_get_ex_new_index
- * - wolfSSL_get_ex_new_index
- * Issues a unique index number for the specified class-index.
- * Returns an index number greater or equal to zero on success,
- * -1 on failure.
- */
- int wolfssl_get_ex_new_index(int class_index)
- {
- /* index counter for each class index*/
- static int ctx_idx = 0;
- static int ssl_idx = 0;
- static int ssl_session_idx = 0;
- static int x509_idx = 0;
- int idx = -1;
- switch(class_index) {
- case WOLF_CRYPTO_EX_INDEX_SSL:
- idx = ssl_idx++;
- break;
- case WOLF_CRYPTO_EX_INDEX_SSL_CTX:
- idx = ctx_idx++;
- break;
- case WOLF_CRYPTO_EX_INDEX_X509:
- idx = x509_idx++;
- break;
- case WOLF_CRYPTO_EX_INDEX_SSL_SESSION:
- idx = ssl_session_idx++;
- break;
- /* following class indexes are not supoprted */
- case WOLF_CRYPTO_EX_INDEX_X509_STORE:
- case WOLF_CRYPTO_EX_INDEX_X509_STORE_CTX:
- case WOLF_CRYPTO_EX_INDEX_DH:
- case WOLF_CRYPTO_EX_INDEX_DSA:
- case WOLF_CRYPTO_EX_INDEX_EC_KEY:
- case WOLF_CRYPTO_EX_INDEX_RSA:
- case WOLF_CRYPTO_EX_INDEX_ENGINE:
- case WOLF_CRYPTO_EX_INDEX_UI:
- case WOLF_CRYPTO_EX_INDEX_BIO:
- case WOLF_CRYPTO_EX_INDEX_APP:
- case WOLF_CRYPTO_EX_INDEX_UI_METHOD:
- case WOLF_CRYPTO_EX_INDEX_DRBG:
- default:
- break;
- }
- return idx;
- }
- #endif /* HAVE_EX_DATA || WOLFSSL_WPAS_SMALL */
- #if defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL)
- void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
- #ifdef HAVE_EX_DATA
- if(ctx != NULL) {
- return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx);
- }
- #else
- (void)ctx;
- (void)idx;
- #endif
- return NULL;
- }
- int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b,
- void* c)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index");
- WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(idx, arg, a, b, c);
- return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_CTX);
- }
- /* Return the index that can be used for the WOLFSSL structure to store
- * application data.
- *
- */
- int wolfSSL_get_ex_new_index(long argValue, void* arg,
- WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2,
- WOLFSSL_CRYPTO_EX_free* cb3)
- {
- WOLFSSL_ENTER("wolfSSL_get_ex_new_index");
- WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(argValue, arg, cb1, cb2, cb3);
- return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL);
- }
- int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data");
- #ifdef HAVE_EX_DATA
- if (ctx != NULL)
- {
- return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
- }
- #else
- (void)ctx;
- (void)idx;
- (void)data;
- #endif
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- int wolfSSL_CTX_set_ex_data_with_cleanup(
- WOLFSSL_CTX* ctx,
- int idx,
- void* data,
- wolfSSL_ex_data_cleanup_routine_t cleanup_routine)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data_with_cleanup");
- if (ctx != NULL)
- {
- return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx, data,
- cleanup_routine);
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
- #endif /* defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL) */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- /* Returns char* to app data stored in ex[0].
- *
- * ssl WOLFSSL structure to get app data from
- */
- void* wolfSSL_get_app_data(const WOLFSSL *ssl)
- {
- /* checkout exdata stuff... */
- WOLFSSL_ENTER("wolfSSL_get_app_data");
- return wolfSSL_get_ex_data(ssl, 0);
- }
- /* Set ex array 0 to have app data
- *
- * ssl WOLFSSL struct to set app data in
- * arg data to be stored
- *
- * Returns WOLFSSL_SUCCESS on success and SSL_FAILURE on failure
- */
- int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) {
- WOLFSSL_ENTER("wolfSSL_set_app_data");
- return wolfSSL_set_ex_data(ssl, 0, arg);
- }
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- #if defined(HAVE_EX_DATA) || defined(OPENSSL_EXTRA) || \
- defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL)
- int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data)
- {
- WOLFSSL_ENTER("wolfSSL_set_ex_data");
- #ifdef HAVE_EX_DATA
- if (ssl != NULL)
- {
- return wolfSSL_CRYPTO_set_ex_data(&ssl->ex_data, idx, data);
- }
- #else
- WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
- (void)ssl;
- (void)idx;
- (void)data;
- #endif
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- int wolfSSL_set_ex_data_with_cleanup(
- WOLFSSL* ssl,
- int idx,
- void* data,
- wolfSSL_ex_data_cleanup_routine_t cleanup_routine)
- {
- WOLFSSL_ENTER("wolfSSL_set_ex_data_with_cleanup");
- if (ssl != NULL)
- {
- return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ssl->ex_data, idx, data,
- cleanup_routine);
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
- void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx)
- {
- WOLFSSL_ENTER("wolfSSL_get_ex_data");
- #ifdef HAVE_EX_DATA
- if (ssl != NULL) {
- return wolfSSL_CRYPTO_get_ex_data(&ssl->ex_data, idx);
- }
- #else
- WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
- (void)ssl;
- (void)idx;
- #endif
- return 0;
- }
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL */
- #if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \
- || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA)
- #if defined(OPENSSL_EXTRA) && !defined(NO_DH)
- /* Initialize ctx->dh with dh's params. Return WOLFSSL_SUCCESS on ok */
- long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh)
- {
- int pSz, gSz;
- byte *p, *g;
- int ret=0;
- WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh");
- if(!ctx || !dh)
- return BAD_FUNC_ARG;
- /* Get needed size for p and g */
- pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
- gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
- if(pSz <= 0 || gSz <= 0)
- return WOLFSSL_FATAL_ERROR;
- p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if(!p)
- return MEMORY_E;
- g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if(!g) {
- XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- return MEMORY_E;
- }
- pSz = wolfSSL_BN_bn2bin(dh->p, p);
- gSz = wolfSSL_BN_bn2bin(dh->g, g);
- if(pSz >= 0 && gSz >= 0) /* Conversion successful */
- ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
- XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
- }
- #endif /* OPENSSL_EXTRA && !NO_DH */
- /* returns the enum value associated with handshake state
- *
- * ssl the WOLFSSL structure to get state of
- */
- int wolfSSL_get_state(const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_state");
- if (ssl == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- return SSL_FAILURE;
- }
- return ssl->options.handShakeState;
- }
- #endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */
- #ifdef OPENSSL_EXTRA
- void wolfSSL_certs_clear(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_certs_clear()");
- if (ssl == NULL)
- return;
- /* ctx still owns certificate, certChain, key, dh, and cm */
- if (ssl->buffers.weOwnCert)
- FreeDer(&ssl->buffers.certificate);
- ssl->buffers.certificate = NULL;
- if (ssl->buffers.weOwnCertChain)
- FreeDer(&ssl->buffers.certChain);
- ssl->buffers.certChain = NULL;
- #ifdef WOLFSSL_TLS13
- ssl->buffers.certChainCnt = 0;
- #endif
- if (ssl->buffers.weOwnKey)
- FreeDer(&ssl->buffers.key);
- ssl->buffers.key = NULL;
- ssl->buffers.keyType = 0;
- ssl->buffers.keyId = 0;
- ssl->buffers.keyLabel = 0;
- ssl->buffers.keySz = 0;
- ssl->buffers.keyDevId = 0;
- }
- #endif
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
- || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
- long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt)
- {
- WOLFSSL_ENTER("wolfSSL_ctrl");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- switch (cmd) {
- #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
- #ifdef HAVE_SNI
- case SSL_CTRL_SET_TLSEXT_HOSTNAME:
- WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TLSEXT_HOSTNAME.");
- if (pt == NULL) {
- WOLFSSL_MSG("Passed in NULL Host Name.");
- break;
- }
- return wolfSSL_set_tlsext_host_name(ssl, (const char*) pt);
- #endif /* HAVE_SNI */
- #endif /* WOLFSSL_NGINX || WOLFSSL_QT || OPENSSL_ALL */
- default:
- WOLFSSL_MSG("Case not implemented.");
- }
- (void)opt;
- (void)pt;
- return WOLFSSL_FAILURE;
- }
- long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt)
- {
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- long ctrl_opt;
- #endif
- long ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CTX_ctrl");
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
- switch (cmd) {
- case SSL_CTRL_CHAIN:
- #ifdef SESSION_CERTS
- {
- /*
- * We don't care about opt here because a copy of the certificate is
- * stored anyway so increasing the reference counter is not necessary.
- * Just check to make sure that it is set to one of the correct values.
- */
- WOLF_STACK_OF(WOLFSSL_X509)* sk = (WOLF_STACK_OF(WOLFSSL_X509)*) pt;
- WOLFSSL_X509* x509;
- int i;
- if (opt != 0 && opt != 1) {
- ret = WOLFSSL_FAILURE;
- break;
- }
- /* Clear certificate chain */
- FreeDer(&ctx->certChain);
- if (sk) {
- for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
- x509 = wolfSSL_sk_X509_value(sk, i);
- /* Prevent wolfSSL_CTX_add_extra_chain_cert from freeing cert */
- if (wolfSSL_X509_up_ref(x509) != 1) {
- WOLFSSL_MSG("Error increasing reference count");
- continue;
- }
- if (wolfSSL_CTX_add_extra_chain_cert(ctx, x509) !=
- WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error adding certificate to context");
- /* Decrease reference count on failure */
- wolfSSL_X509_free(x509);
- }
- }
- }
- /* Free previous chain */
- wolfSSL_sk_X509_pop_free(ctx->x509Chain, NULL);
- ctx->x509Chain = sk;
- if (sk && opt == 1) {
- /* up all refs when opt == 1 */
- for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
- x509 = wolfSSL_sk_X509_value(sk, i);
- if (wolfSSL_X509_up_ref(x509) != 1) {
- WOLFSSL_MSG("Error increasing reference count");
- continue;
- }
- }
- }
- }
- #else
- WOLFSSL_MSG("Session certificates not compiled in");
- ret = WOLFSSL_FAILURE;
- #endif
- break;
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- case SSL_CTRL_OPTIONS:
- WOLFSSL_MSG("Entering Case: SSL_CTRL_OPTIONS.");
- ctrl_opt = wolfSSL_CTX_set_options(ctx, opt);
- #ifdef WOLFSSL_QT
- /* Set whether to use client or server cipher preference */
- if ((ctrl_opt & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE)
- == WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) {
- WOLFSSL_MSG("Using Server's Cipher Preference.");
- ctx->useClientOrder = FALSE;
- } else {
- WOLFSSL_MSG("Using Client's Cipher Preference.");
- ctx->useClientOrder = TRUE;
- }
- #endif /* WOLFSSL_QT */
- return ctrl_opt;
- #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
- case SSL_CTRL_EXTRA_CHAIN_CERT:
- WOLFSSL_MSG("Entering Case: SSL_CTRL_EXTRA_CHAIN_CERT.");
- if (pt == NULL) {
- WOLFSSL_MSG("Passed in x509 pointer NULL.");
- ret = WOLFSSL_FAILURE;
- break;
- }
- return wolfSSL_CTX_add_extra_chain_cert(ctx, (WOLFSSL_X509*)pt);
- #ifndef NO_DH
- case SSL_CTRL_SET_TMP_DH:
- WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_DH.");
- if (pt == NULL) {
- WOLFSSL_MSG("Passed in DH pointer NULL.");
- ret = WOLFSSL_FAILURE;
- break;
- }
- return wolfSSL_CTX_set_tmp_dh(ctx, (WOLFSSL_DH*)pt);
- #endif
- #ifdef HAVE_ECC
- case SSL_CTRL_SET_TMP_ECDH:
- WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_ECDH.");
- if (pt == NULL) {
- WOLFSSL_MSG("Passed in ECDH pointer NULL.");
- ret = WOLFSSL_FAILURE;
- break;
- }
- return wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, (WOLFSSL_EC_KEY*)pt);
- #endif
- case SSL_CTRL_MODE:
- wolfSSL_CTX_set_mode(ctx,opt);
- break;
- case SSL_CTRL_SET_MIN_PROTO_VERSION:
- WOLFSSL_MSG("set min proto version");
- return wolfSSL_CTX_set_min_proto_version(ctx, (int)opt);
- case SSL_CTRL_SET_MAX_PROTO_VERSION:
- WOLFSSL_MSG("set max proto version");
- return wolfSSL_CTX_set_max_proto_version(ctx, (int)opt);
- case SSL_CTRL_GET_MIN_PROTO_VERSION:
- WOLFSSL_MSG("get min proto version");
- return wolfSSL_CTX_get_min_proto_version(ctx);
- case SSL_CTRL_GET_MAX_PROTO_VERSION:
- WOLFSSL_MSG("get max proto version");
- return wolfSSL_CTX_get_max_proto_version(ctx);
- default:
- WOLFSSL_MSG("CTX_ctrl cmd not implemented");
- ret = WOLFSSL_FAILURE;
- break;
- }
- (void)ctx;
- (void)cmd;
- (void)opt;
- (void)pt;
- WOLFSSL_LEAVE("wolfSSL_CTX_ctrl", (int)ret);
- return ret;
- }
- #ifndef WOLFSSL_NO_STUB
- long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void))
- {
- (void) ctx;
- (void) cmd;
- (void) fp;
- WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl");
- return WOLFSSL_FAILURE;
- }
- #endif /* WOLFSSL_NO_STUB */
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx)
- {
- return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0L, NULL);
- }
- #endif
- /* Returns the verifyCallback from the ssl structure if successful.
- Returns NULL otherwise. */
- VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_verify_callback()");
- if (ssl) {
- return ssl->verifyCallback;
- }
- return NULL;
- }
- /* Adds the ASN1 certificate to the user ctx.
- Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
- int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz,
- const unsigned char *der)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1()");
- if (der != NULL && ctx != NULL) {
- if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz,
- WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
- }
- return WOLFSSL_FAILURE;
- }
- #if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
- !defined(NO_RSA) && !defined(HAVE_USER_RSA)
- /* Adds the rsa private key to the user ctx.
- Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
- int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
- {
- int ret;
- int derSize;
- unsigned char *maxDerBuf;
- unsigned char* key = NULL;
- WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey()");
- if (ctx == NULL || rsa == NULL) {
- WOLFSSL_MSG("one or more inputs were NULL");
- return BAD_FUNC_ARG;
- }
- maxDerBuf = (unsigned char*)XMALLOC(4096, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (maxDerBuf == NULL) {
- WOLFSSL_MSG("Malloc failure");
- return MEMORY_E;
- }
- key = maxDerBuf;
- /* convert RSA struct to der encoded buffer and get the size */
- if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) {
- WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure");
- XFREE(maxDerBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_FAILURE;
- }
- ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf,
- derSize, SSL_FILETYPE_ASN1);
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure");
- XFREE(maxDerBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_FAILURE;
- }
- XFREE(maxDerBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- #endif /* NO_RSA && !HAVE_FAST_RSA */
- #ifndef NO_BIO
- /* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure.
- Returns pointer to private EVP_PKEY struct upon success, NULL if there
- is a failure.*/
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** out)
- {
- unsigned char* mem = NULL;
- int memSz = 0;
- WOLFSSL_EVP_PKEY* key = NULL;
- int i = 0, j = 0;
- unsigned char* extraBioMem = NULL;
- int extraBioMemSz = 0;
- int derLength = 0;
- WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio()");
- if (bio == NULL) {
- return NULL;
- }
- (void)out;
- memSz = wolfSSL_BIO_get_len(bio);
- if (memSz <= 0) {
- WOLFSSL_MSG("wolfSSL_BIO_get_len() failure");
- return NULL;
- }
- mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_MSG("Malloc failure");
- return NULL;
- }
- if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
- /* Determines key type and returns the new private EVP_PKEY object */
- if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) {
- WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure");
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- /* Write extra data back into bio object if necessary. */
- derLength = key->pkey_sz;
- extraBioMemSz = (memSz - derLength);
- if (extraBioMemSz > 0) {
- extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (extraBioMem == NULL) {
- WOLFSSL_MSG("Malloc failure");
- XFREE((unsigned char*)extraBioMem, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- for (i = derLength; i < memSz; i++) {
- *(extraBioMem + j) = *(mem + i);
- j++;
- }
- wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
- if (wolfSSL_BIO_get_len(bio) <= 0) {
- WOLFSSL_MSG("Failed to write memory to bio");
- XFREE((unsigned char*)extraBioMem, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- XFREE((unsigned char*)extraBioMem, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (out != NULL) {
- *out = key;
- }
- }
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return key;
- }
- #endif /* !NO_BIO */
- #endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) || \
- defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL)
- /* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
- * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
- * on fail */
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
- unsigned char** in, long inSz)
- {
- WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP");
- return d2iGenericKey(out, (const unsigned char**)in, inSz, 1);
- }
- #endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT || WOLFSSL_WPAS_SMALL*/
- /* stunnel compatibility functions*/
- #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
- void wolfSSL_ERR_remove_thread_state(void* pid)
- {
- (void) pid;
- return;
- }
- #ifndef NO_FILESYSTEM
- /***TBD ***/
- void wolfSSL_print_all_errors_fp(XFILE fp)
- {
- (void)fp;
- }
- #endif /* !NO_FILESYSTEM */
- #endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX ||
- HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
- defined(HAVE_EX_DATA)
- #if defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE)
- static void SESSION_ex_data_cache_update(WOLFSSL_SESSION* session, int idx,
- void* data, byte get, void** getRet, int* setRet)
- {
- int row;
- int i;
- int error = 0;
- SessionRow* sessRow = NULL;
- const byte* id;
- byte foundCache = 0;
- if (getRet != NULL)
- *getRet = NULL;
- if (setRet != NULL)
- *setRet = WOLFSSL_FAILURE;
- id = session->sessionID;
- if (session->haveAltSessionID)
- id = session->altSessionID;
- row = (int)(HashObject(id, ID_LEN, &error) % SESSION_ROWS);
- if (error != 0) {
- WOLFSSL_MSG("Hash session failed");
- return;
- }
- sessRow = &SessionCache[row];
- if (SESSION_ROW_LOCK(sessRow) != 0) {
- WOLFSSL_MSG("Session row lock failed");
- return;
- }
- for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) {
- if (XMEMCMP(id, sessRow->Sessions[i].sessionID, ID_LEN) == 0
- && session->side == sessRow->Sessions[i].side) {
- if (get) {
- *getRet = wolfSSL_CRYPTO_get_ex_data(
- &sessRow->Sessions[i].ex_data, idx);
- }
- else {
- *setRet = wolfSSL_CRYPTO_set_ex_data(
- &sessRow->Sessions[i].ex_data, idx, data);
- }
- foundCache = 1;
- break;
- }
- }
- SESSION_ROW_UNLOCK(sessRow);
- /* If we don't have a session in cache then clear the ex_data and
- * own it */
- if (!foundCache) {
- XMEMSET(&session->ex_data, 0, sizeof(WOLFSSL_CRYPTO_EX_DATA));
- session->ownExData = 1;
- if (!get) {
- *setRet = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx,
- data);
- }
- }
- }
- #endif
- int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data)
- {
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data");
- #ifdef HAVE_EX_DATA
- session = ClientSessionToSession(session);
- if (session != NULL) {
- #ifndef NO_SESSION_CACHE
- if (!session->ownExData) {
- /* Need to update in cache */
- SESSION_ex_data_cache_update(session, idx, data, 0, NULL, &ret);
- }
- else
- #endif
- {
- ret = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data);
- }
- }
- #else
- (void)session;
- (void)idx;
- (void)data;
- #endif
- return ret;
- }
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- int wolfSSL_SESSION_set_ex_data_with_cleanup(
- WOLFSSL_SESSION* session,
- int idx,
- void* data,
- wolfSSL_ex_data_cleanup_routine_t cleanup_routine)
- {
- WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data_with_cleanup");
- session = ClientSessionToSession(session);
- if(session != NULL) {
- return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&session->ex_data, idx,
- data, cleanup_routine);
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
- void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx)
- {
- void* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data");
- #ifdef HAVE_EX_DATA
- session = ClientSessionToSession(session);
- if (session != NULL) {
- #ifndef NO_SESSION_CACHE
- if (!session->ownExData) {
- /* Need to retrieve the data from the session cache */
- SESSION_ex_data_cache_update((WOLFSSL_SESSION*)session, idx, NULL,
- 1, &ret, NULL);
- }
- else
- #endif
- {
- ret = wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx);
- }
- }
- #else
- (void)session;
- (void)idx;
- #endif
- return ret;
- }
- #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_EX_DATA */
- /* Note: This is a huge section of API's - through
- * wolfSSL_X509_OBJECT_get0_X509_CRL */
- #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
- (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
- defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
- defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB)))
- #ifdef HAVE_EX_DATA
- int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1,
- void* cb2, CRYPTO_free_func* cb3)
- {
- WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index");
- WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(idx, data, cb1, cb2, cb3);
- return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_SESSION);
- }
- #endif
- #if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY)
- static wolfSSL_OSSL_Malloc_cb ossl_malloc = NULL;
- static wolfSSL_OSSL_Free_cb ossl_free = NULL;
- static wolfSSL_OSSL_Realloc_cb ossl_realloc = NULL;
- static void* OSSL_Malloc(size_t size)
- {
- if (ossl_malloc != NULL)
- return ossl_malloc(size, NULL, 0);
- else
- return NULL;
- }
- static void OSSL_Free(void *ptr)
- {
- if (ossl_free != NULL)
- ossl_free(ptr, NULL, 0);
- }
- static void* OSSL_Realloc(void *ptr, size_t size)
- {
- if (ossl_realloc != NULL)
- return ossl_realloc(ptr, size, NULL, 0);
- else
- return NULL;
- }
- #endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_DEBUG_MEMORY */
- int wolfSSL_CRYPTO_set_mem_functions(
- wolfSSL_OSSL_Malloc_cb m,
- wolfSSL_OSSL_Realloc_cb r,
- wolfSSL_OSSL_Free_cb f)
- {
- #ifdef USE_WOLFSSL_MEMORY
- #ifdef WOLFSSL_DEBUG_MEMORY
- WOLFSSL_MSG("mem functions will receive function name instead of "
- "file name");
- if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)m, (wolfSSL_Free_cb)f,
- (wolfSSL_Realloc_cb)r) == 0)
- return WOLFSSL_SUCCESS;
- #else
- WOLFSSL_MSG("wolfSSL was compiled without WOLFSSL_DEBUG_MEMORY. mem "
- "functions will receive a NULL file name and 0 for the "
- "line number.");
- if (wolfSSL_SetAllocators(OSSL_Malloc, OSSL_Free, OSSL_Realloc) == 0) {
- ossl_malloc = m;
- ossl_free = f;
- ossl_realloc = r;
- return WOLFSSL_SUCCESS;
- }
- #endif
- else
- return WOLFSSL_FAILURE;
- #else
- (void)m;
- (void)r;
- (void)f;
- WOLFSSL_MSG("wolfSSL allocator callback functions not compiled in");
- return WOLFSSL_FAILURE;
- #endif
- }
- int wolfSSL_ERR_load_ERR_strings(void)
- {
- return WOLFSSL_SUCCESS;
- }
- void wolfSSL_ERR_load_crypto_strings(void)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings");
- /* Do nothing */
- return;
- }
- int wolfSSL_FIPS_mode(void)
- {
- #ifdef HAVE_FIPS
- return 1;
- #else
- return 0;
- #endif
- }
- int wolfSSL_FIPS_mode_set(int r)
- {
- #ifdef HAVE_FIPS
- if (r == 0) {
- WOLFSSL_MSG("Cannot disable FIPS at runtime.");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- #else
- if (r == 0) {
- return WOLFSSL_SUCCESS;
- }
- WOLFSSL_MSG("Cannot enable FIPS. This isn't the wolfSSL FIPS code.");
- return WOLFSSL_FAILURE;
- #endif
- }
- int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits)
- {
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits");
- #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
- (void)alg_bits;
- if (c!= NULL)
- ret = c->bits;
- #else
- if (c != NULL && c->ssl != NULL) {
- ret = 8 * c->ssl->specs.key_size;
- if (alg_bits != NULL) {
- *alg_bits = ret;
- }
- }
- #endif
- return ret;
- }
- /* returns value less than 0 on fail to match
- * On a successful match the priority level found is returned
- */
- int wolfSSL_sk_SSL_CIPHER_find(
- WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind)
- {
- WOLFSSL_STACK* next;
- int i, sz;
- if (sk == NULL || toFind == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
- sz = wolfSSL_sk_SSL_CIPHER_num(sk);
- next = sk;
- for (i = 0; i < sz && next != NULL; i++) {
- if (next->data.cipher.cipherSuite0 == toFind->cipherSuite0 &&
- next->data.cipher.cipherSuite == toFind->cipherSuite) {
- return sz - i; /* reverse because stack pushed highest on first */
- }
- next = next->next;
- }
- return WOLFSSL_FATAL_ERROR;
- }
- /* free's all nodes in the stack and there data */
- void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
- {
- WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_free");
- wolfSSL_sk_free(sk);
- }
- #ifdef HAVE_SNI
- int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name");
- ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME,
- host_name, (word16)XSTRLEN(host_name));
- WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret);
- return ret;
- }
- #ifndef NO_WOLFSSL_SERVER
- const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
- {
- void * serverName = NULL;
- if (ssl == NULL)
- return NULL;
- TLSX_SNI_GetRequest(ssl->extensions, type, &serverName);
- return (const char *)serverName;
- }
- #endif /* NO_WOLFSSL_SERVER */
- #endif /* HAVE_SNI */
- WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
- {
- if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS)
- return ssl->ctx;
- return NULL;
- }
- VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback");
- if(ctx)
- return ctx->verifyCallback;
- return NULL;
- }
- #ifdef HAVE_SNI
- void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
- if (ctx)
- ctx->sniRecvCb = cb;
- }
- int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
- CallbackSniRecv cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback");
- if (ctx) {
- ctx->sniRecvCb = cb;
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
- if (ctx) {
- ctx->sniRecvCbArg = arg;
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* HAVE_SNI */
- #ifndef NO_BIO
- void wolfSSL_ERR_load_BIO_strings(void) {
- WOLFSSL_ENTER("ERR_load_BIO_strings");
- /* do nothing */
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- /* Set THREADID callback, return 1 on success, 0 on error */
- int wolfSSL_THREADID_set_callback(
- void(*threadid_func)(WOLFSSL_CRYPTO_THREADID*))
- {
- WOLFSSL_ENTER("wolfSSL_THREADID_set_callback");
- WOLFSSL_STUB("CRYPTO_THREADID_set_callback");
- (void)threadid_func;
- return 1;
- }
- #endif
- #ifndef NO_WOLFSSL_STUB
- void wolfSSL_THREADID_set_numeric(void* id, unsigned long val)
- {
- WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric");
- WOLFSSL_STUB("CRYPTO_THREADID_set_numeric");
- (void)id;
- (void)val;
- return;
- }
- #endif
- #endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX ||
- * HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH ||
- * HAVE_SBLIM_SFCB)) */
- #if defined(OPENSSL_EXTRA)
- int wolfSSL_CRYPTO_memcmp(const void *a, const void *b, size_t size)
- {
- if (!a || !b)
- return 0;
- return ConstantCompare((const byte*)a, (const byte*)b, (int)size);
- }
- unsigned long wolfSSL_ERR_peek_last_error(void)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
- #ifdef WOLFSSL_HAVE_ERROR_QUEUE
- {
- int ret;
- if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) {
- WOLFSSL_MSG("Issue peeking at error node in queue");
- return 0;
- }
- if (ret == -ASN_NO_PEM_HEADER)
- return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
- #if defined(WOLFSSL_PYTHON)
- if (ret == ASN1_R_HEADER_TOO_LONG)
- return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG;
- #endif
- return (unsigned long)ret;
- }
- #else
- return (unsigned long)(0 - NOT_COMPILED_IN);
- #endif
- }
- #endif /* OPENSSL_EXTRA */
- int wolfSSL_version(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_version");
- if (ssl->version.major == SSLv3_MAJOR) {
- switch (ssl->version.minor) {
- case SSLv3_MINOR :
- return SSL3_VERSION;
- case TLSv1_MINOR :
- return TLS1_VERSION;
- case TLSv1_1_MINOR :
- return TLS1_1_VERSION;
- case TLSv1_2_MINOR :
- return TLS1_2_VERSION;
- case TLSv1_3_MINOR :
- return TLS1_3_VERSION;
- default:
- return WOLFSSL_FAILURE;
- }
- }
- else if (ssl->version.major == DTLS_MAJOR) {
- switch (ssl->version.minor) {
- case DTLS_MINOR :
- return DTLS1_VERSION;
- case DTLSv1_2_MINOR :
- return DTLS1_2_VERSION;
- default:
- return WOLFSSL_FAILURE;
- }
- }
- return WOLFSSL_FAILURE;
- }
- WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_SSL_CTX");
- return ssl->ctx;
- }
- #if defined(OPENSSL_ALL) || \
- defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- const byte* wolfSSL_SESSION_get_id(const WOLFSSL_SESSION* sess,
- unsigned int* idLen)
- {
- WOLFSSL_ENTER("wolfSSL_SESSION_get_id");
- sess = ClientSessionToSession(sess);
- if (sess == NULL || idLen == NULL) {
- WOLFSSL_MSG("Bad func args. Please provide idLen");
- return NULL;
- }
- *idLen = sess->sessionIDSz;
- return sess->sessionID;
- }
- #if (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \
- !defined(NO_FILESYSTEM)
- #ifndef NO_BIO
- #if defined(SESSION_CERTS) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
- /* returns a pointer to the protocol used by the session */
- static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in)
- {
- in = ClientSessionToSession(in);
- return wolfSSL_internal_get_version((ProtocolVersion*)&in->version);
- }
- #endif
- /* returns true (non 0) if the session has EMS (extended master secret) */
- static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in)
- {
- in = ClientSessionToSession(in);
- if (in == NULL)
- return 0;
- return in->haveEMS;
- }
- #if defined(HAVE_SESSION_TICKET)
- /* prints out the ticket to bio passed in
- * return WOLFSSL_SUCCESS on success
- */
- static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio,
- const WOLFSSL_SESSION* in, const char* tab)
- {
- unsigned short i, j, z, sz;
- short tag = 0;
- byte* pt;
- in = ClientSessionToSession(in);
- if (in == NULL || bio == NULL) {
- return BAD_FUNC_ARG;
- }
- sz = in->ticketLen;
- pt = in->ticket;
- if (wolfSSL_BIO_printf(bio, "%s\n", (sz == 0)? " NONE": "") <= 0)
- return WOLFSSL_FAILURE;
- for (i = 0; i < sz;) {
- char asc[16];
- if (sz - i < 16) {
- if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag + (sz - i)) <= 0)
- return WOLFSSL_FAILURE;
- }
- else {
- if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag) <= 0)
- return WOLFSSL_FAILURE;
- }
- for (j = 0; i < sz && j < 8; j++,i++) {
- asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
- if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0)
- return WOLFSSL_FAILURE;
- }
- if (i < sz) {
- asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
- if (wolfSSL_BIO_printf(bio, "-%02X", pt[i]) <= 0)
- return WOLFSSL_FAILURE;
- j++;
- i++;
- }
- for (; i < sz && j < 16; j++,i++) {
- asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
- if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0)
- return WOLFSSL_FAILURE;
- }
- /* pad out spacing */
- for (z = j; z < 17; z++) {
- if (wolfSSL_BIO_printf(bio, " ") <= 0)
- return WOLFSSL_FAILURE;
- }
- for (z = 0; z < j; z++) {
- if (wolfSSL_BIO_printf(bio, "%c", asc[z]) <= 0)
- return WOLFSSL_FAILURE;
- }
- if (wolfSSL_BIO_printf(bio, "\n") <= 0)
- return WOLFSSL_FAILURE;
- tag += 16;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_SESSION_TICKET */
- /* prints out the session information in human readable form
- * return WOLFSSL_SUCCESS on success
- */
- int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *session)
- {
- const unsigned char* pt;
- unsigned char buf[SECRET_LEN];
- unsigned int sz = 0, i;
- int ret;
- session = ClientSessionToSession(session);
- if (session == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (wolfSSL_BIO_printf(bp, "%s\n", "SSL-Session:") <= 0)
- return WOLFSSL_FAILURE;
- #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
- defined(HAVE_SESSION_TICKET))
- if (wolfSSL_BIO_printf(bp, " Protocol : %s\n",
- wolfSSL_SESSION_get_protocol(session)) <= 0)
- return WOLFSSL_FAILURE;
- #endif
- if (wolfSSL_BIO_printf(bp, " Cipher : %s\n",
- wolfSSL_SESSION_CIPHER_get_name(session)) <= 0)
- return WOLFSSL_FAILURE;
- pt = wolfSSL_SESSION_get_id(session, &sz);
- if (wolfSSL_BIO_printf(bp, " Session-ID: ") <= 0)
- return WOLFSSL_FAILURE;
- for (i = 0; i < sz; i++) {
- if (wolfSSL_BIO_printf(bp, "%02X", pt[i]) <= 0)
- return WOLFSSL_FAILURE;
- }
- if (wolfSSL_BIO_printf(bp, "\n") <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_printf(bp, " Session-ID-ctx: \n") <= 0)
- return WOLFSSL_FAILURE;
- ret = wolfSSL_SESSION_get_master_key(session, buf, sizeof(buf));
- if (wolfSSL_BIO_printf(bp, " Master-Key: ") <= 0)
- return WOLFSSL_FAILURE;
- if (ret > 0) {
- sz = (unsigned int)ret;
- for (i = 0; i < sz; i++) {
- if (wolfSSL_BIO_printf(bp, "%02X", buf[i]) <= 0)
- return WOLFSSL_FAILURE;
- }
- }
- if (wolfSSL_BIO_printf(bp, "\n") <= 0)
- return WOLFSSL_FAILURE;
- /* @TODO PSK identity hint and SRP */
- if (wolfSSL_BIO_printf(bp, " TLS session ticket:") <= 0)
- return WOLFSSL_FAILURE;
- #ifdef HAVE_SESSION_TICKET
- if (wolfSSL_SESSION_print_ticket(bp, session, " ") != WOLFSSL_SUCCESS)
- return WOLFSSL_FAILURE;
- #endif
- #if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \
- defined(HAVE_EXT_CACHE))
- if (wolfSSL_BIO_printf(bp, " Start Time: %ld\n",
- wolfSSL_SESSION_get_time(session)) <= 0)
- return WOLFSSL_FAILURE;
- if (wolfSSL_BIO_printf(bp, " Timeout : %ld (sec)\n",
- wolfSSL_SESSION_get_timeout(session)) <= 0)
- return WOLFSSL_FAILURE;
- #endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */
- /* @TODO verify return code print */
- if (wolfSSL_BIO_printf(bp, " Extended master secret: %s\n",
- (wolfSSL_SESSION_haveEMS(session) == 0)? "no" : "yes") <= 0)
- return WOLFSSL_FAILURE;
- return WOLFSSL_SUCCESS;
- }
- #endif /* !NO_BIO */
- #endif /* (HAVE_SESSION_TICKET || SESSION_CERTS) && !NO_FILESYSTEM */
- #endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
- #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \
- || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX)
- /* TODO: Doesn't currently track SSL_VERIFY_CLIENT_ONCE */
- int wolfSSL_get_verify_mode(const WOLFSSL* ssl) {
- int mode = 0;
- WOLFSSL_ENTER("wolfSSL_get_verify_mode");
- if (!ssl) {
- return WOLFSSL_FAILURE;
- }
- if (ssl->options.verifyNone) {
- mode = WOLFSSL_VERIFY_NONE;
- }
- else {
- if (ssl->options.verifyPeer) {
- mode |= WOLFSSL_VERIFY_PEER;
- }
- if (ssl->options.failNoCert) {
- mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- }
- if (ssl->options.failNoCertxPSK) {
- mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
- }
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- if (ssl->options.verifyPostHandshake) {
- mode |= WOLFSSL_VERIFY_POST_HANDSHAKE;
- }
- #endif
- }
- WOLFSSL_LEAVE("wolfSSL_get_verify_mode", mode);
- return mode;
- }
- int wolfSSL_CTX_get_verify_mode(const WOLFSSL_CTX* ctx)
- {
- int mode = 0;
- WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode");
- if (!ctx) {
- return WOLFSSL_FAILURE;
- }
- if (ctx->verifyNone) {
- mode = WOLFSSL_VERIFY_NONE;
- }
- else {
- if (ctx->verifyPeer) {
- mode |= WOLFSSL_VERIFY_PEER;
- }
- if (ctx->failNoCert) {
- mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- }
- if (ctx->failNoCertxPSK) {
- mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
- }
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- if (ctx->verifyPostHandshake) {
- mode |= WOLFSSL_VERIFY_POST_HANDSHAKE;
- }
- #endif
- }
- WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode);
- return mode;
- }
- #endif
- #if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519)
- /* return 1 if success, 0 if error
- * output keys are little endian format
- */
- int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
- unsigned char *pub, unsigned int *pubSz)
- {
- #ifndef WOLFSSL_KEY_GEN
- WOLFSSL_MSG("No Key Gen built in");
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #else /* WOLFSSL_KEY_GEN */
- int ret = WOLFSSL_FAILURE;
- int initTmpRng = 0;
- WC_RNG *rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG *tmpRNG = NULL;
- #else
- WC_RNG tmpRNG[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_EC25519_generate_key");
- if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE ||
- pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRNG == NULL)
- return WOLFSSL_FAILURE;
- #endif
- if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else {
- WOLFSSL_MSG("Bad RNG Init, trying global");
- if (initGlobalRNG == 0)
- WOLFSSL_MSG("Global RNG no Init");
- else
- rng = &globalRNG;
- }
- if (rng) {
- curve25519_key key;
- if (wc_curve25519_init(&key) != MP_OKAY)
- WOLFSSL_MSG("wc_curve25519_init failed");
- else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY)
- WOLFSSL_MSG("wc_curve25519_make_key failed");
- /* export key pair */
- else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub,
- pubSz, EC25519_LITTLE_ENDIAN)
- != MP_OKAY)
- WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_curve25519_free(&key);
- }
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
- #endif
- return ret;
- #endif /* WOLFSSL_KEY_GEN */
- }
- /* return 1 if success, 0 if error
- * input and output keys are little endian format
- */
- int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
- const unsigned char *priv, unsigned int privSz,
- const unsigned char *pub, unsigned int pubSz)
- {
- #ifndef WOLFSSL_KEY_GEN
- WOLFSSL_MSG("No Key Gen built in");
- (void) shared;
- (void) sharedSz;
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #else /* WOLFSSL_KEY_GEN */
- int ret = WOLFSSL_FAILURE;
- curve25519_key privkey, pubkey;
- WOLFSSL_ENTER("wolfSSL_EC25519_shared_key");
- if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE ||
- priv == NULL || privSz < CURVE25519_KEYSIZE ||
- pub == NULL || pubSz < CURVE25519_KEYSIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- /* import private key */
- if (wc_curve25519_init(&privkey) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve25519_init privkey failed");
- return ret;
- }
- if (wc_curve25519_import_private_ex(priv, privSz, &privkey,
- EC25519_LITTLE_ENDIAN) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve25519_import_private_ex failed");
- wc_curve25519_free(&privkey);
- return ret;
- }
- /* import public key */
- if (wc_curve25519_init(&pubkey) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve25519_init pubkey failed");
- wc_curve25519_free(&privkey);
- return ret;
- }
- if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey,
- EC25519_LITTLE_ENDIAN) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve25519_import_public_ex failed");
- wc_curve25519_free(&privkey);
- wc_curve25519_free(&pubkey);
- return ret;
- }
- if (wc_curve25519_shared_secret_ex(&privkey, &pubkey,
- shared, sharedSz,
- EC25519_LITTLE_ENDIAN) != MP_OKAY)
- WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_curve25519_free(&privkey);
- wc_curve25519_free(&pubkey);
- return ret;
- #endif /* WOLFSSL_KEY_GEN */
- }
- #endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */
- #if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
- /* return 1 if success, 0 if error
- * output keys are little endian format
- */
- int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
- unsigned char *pub, unsigned int *pubSz)
- {
- #ifndef WOLFSSL_KEY_GEN
- WOLFSSL_MSG("No Key Gen built in");
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #elif !defined(HAVE_ED25519_KEY_EXPORT)
- WOLFSSL_MSG("No ED25519 key export built in");
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #else /* WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_EXPORT */
- int ret = WOLFSSL_FAILURE;
- int initTmpRng = 0;
- WC_RNG *rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG *tmpRNG = NULL;
- #else
- WC_RNG tmpRNG[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_ED25519_generate_key");
- if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE ||
- pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRNG == NULL)
- return WOLFSSL_FATAL_ERROR;
- #endif
- if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else {
- WOLFSSL_MSG("Bad RNG Init, trying global");
- if (initGlobalRNG == 0)
- WOLFSSL_MSG("Global RNG no Init");
- else
- rng = &globalRNG;
- }
- if (rng) {
- ed25519_key key;
- if (wc_ed25519_init(&key) != MP_OKAY)
- WOLFSSL_MSG("wc_ed25519_init failed");
- else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY)
- WOLFSSL_MSG("wc_ed25519_make_key failed");
- /* export private key */
- else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY)
- WOLFSSL_MSG("wc_ed25519_export_key failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_ed25519_free(&key);
- }
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
- #endif
- return ret;
- #endif /* WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_EXPORT */
- }
- /* return 1 if success, 0 if error
- * input and output keys are little endian format
- * priv is a buffer containing private and public part of key
- */
- int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
- const unsigned char *priv, unsigned int privSz,
- unsigned char *sig, unsigned int *sigSz)
- {
- #if !defined(HAVE_ED25519_SIGN) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED25519_KEY_IMPORT)
- #if !defined(HAVE_ED25519_SIGN)
- WOLFSSL_MSG("No ED25519 sign built in");
- #elif !defined(WOLFSSL_KEY_GEN)
- WOLFSSL_MSG("No Key Gen built in");
- #elif !defined(HAVE_ED25519_KEY_IMPORT)
- WOLFSSL_MSG("No ED25519 Key import built in");
- #endif
- (void) msg;
- (void) msgSz;
- (void) priv;
- (void) privSz;
- (void) sig;
- (void) sigSz;
- return WOLFSSL_FAILURE;
- #else /* HAVE_ED25519_SIGN && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */
- ed25519_key key;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_ED25519_sign");
- if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE ||
- msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- /* import key */
- if (wc_ed25519_init(&key) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve25519_init failed");
- return ret;
- }
- if (wc_ed25519_import_private_key(priv, privSz/2,
- priv+(privSz/2), ED25519_PUB_KEY_SIZE,
- &key) != MP_OKAY){
- WOLFSSL_MSG("wc_ed25519_import_private failed");
- wc_ed25519_free(&key);
- return ret;
- }
- if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
- WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_ed25519_free(&key);
- return ret;
- #endif /* HAVE_ED25519_SIGN && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */
- }
- /* return 1 if success, 0 if error
- * input and output keys are little endian format
- * pub is a buffer containing public part of key
- */
- int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
- const unsigned char *pub, unsigned int pubSz,
- const unsigned char *sig, unsigned int sigSz)
- {
- #if !defined(HAVE_ED25519_VERIFY) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED25519_KEY_IMPORT)
- #if !defined(HAVE_ED25519_VERIFY)
- WOLFSSL_MSG("No ED25519 verify built in");
- #elif !defined(WOLFSSL_KEY_GEN)
- WOLFSSL_MSG("No Key Gen built in");
- #elif !defined(HAVE_ED25519_KEY_IMPORT)
- WOLFSSL_MSG("No ED25519 Key import built in");
- #endif
- (void) msg;
- (void) msgSz;
- (void) pub;
- (void) pubSz;
- (void) sig;
- (void) sigSz;
- return WOLFSSL_FAILURE;
- #else /* HAVE_ED25519_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */
- ed25519_key key;
- int ret = WOLFSSL_FAILURE, check = 0;
- WOLFSSL_ENTER("wolfSSL_ED25519_verify");
- if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE ||
- msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- /* import key */
- if (wc_ed25519_init(&key) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve25519_init failed");
- return ret;
- }
- if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){
- WOLFSSL_MSG("wc_ed25519_import_public failed");
- wc_ed25519_free(&key);
- return ret;
- }
- if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz,
- &check, &key)) != MP_OKAY) {
- WOLFSSL_MSG("wc_ed25519_verify_msg failed");
- }
- else if (!check)
- WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)");
- else
- ret = WOLFSSL_SUCCESS;
- wc_ed25519_free(&key);
- return ret;
- #endif /* HAVE_ED25519_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */
- }
- #endif /* OPENSSL_EXTRA && HAVE_ED25519 */
- #if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE448)
- /* return 1 if success, 0 if error
- * output keys are little endian format
- */
- int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz,
- unsigned char *pub, unsigned int *pubSz)
- {
- #ifndef WOLFSSL_KEY_GEN
- WOLFSSL_MSG("No Key Gen built in");
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #else /* WOLFSSL_KEY_GEN */
- int ret = WOLFSSL_FAILURE;
- int initTmpRng = 0;
- WC_RNG *rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG *tmpRNG = NULL;
- #else
- WC_RNG tmpRNG[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_EC448_generate_key");
- if (priv == NULL || privSz == NULL || *privSz < CURVE448_KEY_SIZE ||
- pub == NULL || pubSz == NULL || *pubSz < CURVE448_KEY_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRNG == NULL)
- return WOLFSSL_FAILURE;
- #endif
- if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else {
- WOLFSSL_MSG("Bad RNG Init, trying global");
- if (initGlobalRNG == 0)
- WOLFSSL_MSG("Global RNG no Init");
- else
- rng = &globalRNG;
- }
- if (rng) {
- curve448_key key;
- if (wc_curve448_init(&key) != MP_OKAY)
- WOLFSSL_MSG("wc_curve448_init failed");
- else if (wc_curve448_make_key(rng, CURVE448_KEY_SIZE, &key)!=MP_OKAY)
- WOLFSSL_MSG("wc_curve448_make_key failed");
- /* export key pair */
- else if (wc_curve448_export_key_raw_ex(&key, priv, privSz, pub, pubSz,
- EC448_LITTLE_ENDIAN)
- != MP_OKAY)
- WOLFSSL_MSG("wc_curve448_export_key_raw_ex failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_curve448_free(&key);
- }
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
- #endif
- return ret;
- #endif /* WOLFSSL_KEY_GEN */
- }
- /* return 1 if success, 0 if error
- * input and output keys are little endian format
- */
- int wolfSSL_EC448_shared_key(unsigned char *shared, unsigned int *sharedSz,
- const unsigned char *priv, unsigned int privSz,
- const unsigned char *pub, unsigned int pubSz)
- {
- #ifndef WOLFSSL_KEY_GEN
- WOLFSSL_MSG("No Key Gen built in");
- (void) shared;
- (void) sharedSz;
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #else /* WOLFSSL_KEY_GEN */
- int ret = WOLFSSL_FAILURE;
- curve448_key privkey, pubkey;
- WOLFSSL_ENTER("wolfSSL_EC448_shared_key");
- if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE448_KEY_SIZE ||
- priv == NULL || privSz < CURVE448_KEY_SIZE ||
- pub == NULL || pubSz < CURVE448_KEY_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- /* import private key */
- if (wc_curve448_init(&privkey) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve448_init privkey failed");
- return ret;
- }
- if (wc_curve448_import_private_ex(priv, privSz, &privkey,
- EC448_LITTLE_ENDIAN) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve448_import_private_ex failed");
- wc_curve448_free(&privkey);
- return ret;
- }
- /* import public key */
- if (wc_curve448_init(&pubkey) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve448_init pubkey failed");
- wc_curve448_free(&privkey);
- return ret;
- }
- if (wc_curve448_import_public_ex(pub, pubSz, &pubkey,
- EC448_LITTLE_ENDIAN) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve448_import_public_ex failed");
- wc_curve448_free(&privkey);
- wc_curve448_free(&pubkey);
- return ret;
- }
- if (wc_curve448_shared_secret_ex(&privkey, &pubkey, shared, sharedSz,
- EC448_LITTLE_ENDIAN) != MP_OKAY)
- WOLFSSL_MSG("wc_curve448_shared_secret_ex failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_curve448_free(&privkey);
- wc_curve448_free(&pubkey);
- return ret;
- #endif /* WOLFSSL_KEY_GEN */
- }
- #endif /* OPENSSL_EXTRA && HAVE_CURVE448 */
- #if defined(OPENSSL_EXTRA) && defined(HAVE_ED448)
- /* return 1 if success, 0 if error
- * output keys are little endian format
- */
- int wolfSSL_ED448_generate_key(unsigned char *priv, unsigned int *privSz,
- unsigned char *pub, unsigned int *pubSz)
- {
- #ifndef WOLFSSL_KEY_GEN
- WOLFSSL_MSG("No Key Gen built in");
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #elif !defined(HAVE_ED448_KEY_EXPORT)
- WOLFSSL_MSG("No ED448 key export built in");
- (void) priv;
- (void) privSz;
- (void) pub;
- (void) pubSz;
- return WOLFSSL_FAILURE;
- #else /* WOLFSSL_KEY_GEN && HAVE_ED448_KEY_EXPORT */
- int ret = WOLFSSL_FAILURE;
- int initTmpRng = 0;
- WC_RNG *rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG *tmpRNG = NULL;
- #else
- WC_RNG tmpRNG[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_ED448_generate_key");
- if (priv == NULL || privSz == NULL || *privSz < ED448_PRV_KEY_SIZE ||
- pub == NULL || pubSz == NULL || *pubSz < ED448_PUB_KEY_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRNG == NULL)
- return WOLFSSL_FATAL_ERROR;
- #endif
- if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else {
- WOLFSSL_MSG("Bad RNG Init, trying global");
- if (initGlobalRNG == 0)
- WOLFSSL_MSG("Global RNG no Init");
- else
- rng = &globalRNG;
- }
- if (rng) {
- ed448_key key;
- if (wc_ed448_init(&key) != MP_OKAY)
- WOLFSSL_MSG("wc_ed448_init failed");
- else if (wc_ed448_make_key(rng, ED448_KEY_SIZE, &key) != MP_OKAY)
- WOLFSSL_MSG("wc_ed448_make_key failed");
- /* export private key */
- else if (wc_ed448_export_key(&key, priv, privSz, pub, pubSz) != MP_OKAY)
- WOLFSSL_MSG("wc_ed448_export_key failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_ed448_free(&key);
- }
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
- #endif
- return ret;
- #endif /* WOLFSSL_KEY_GEN && HAVE_ED448_KEY_EXPORT */
- }
- /* return 1 if success, 0 if error
- * input and output keys are little endian format
- * priv is a buffer containing private and public part of key
- */
- int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz,
- const unsigned char *priv, unsigned int privSz,
- unsigned char *sig, unsigned int *sigSz)
- {
- #if !defined(HAVE_ED448_SIGN) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED448_KEY_IMPORT)
- #if !defined(HAVE_ED448_SIGN)
- WOLFSSL_MSG("No ED448 sign built in");
- #elif !defined(WOLFSSL_KEY_GEN)
- WOLFSSL_MSG("No Key Gen built in");
- #elif !defined(HAVE_ED448_KEY_IMPORT)
- WOLFSSL_MSG("No ED448 Key import built in");
- #endif
- (void) msg;
- (void) msgSz;
- (void) priv;
- (void) privSz;
- (void) sig;
- (void) sigSz;
- return WOLFSSL_FAILURE;
- #else /* HAVE_ED448_SIGN && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */
- ed448_key key;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_ED448_sign");
- if (priv == NULL || privSz != ED448_PRV_KEY_SIZE || msg == NULL ||
- sig == NULL || *sigSz < ED448_SIG_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- /* import key */
- if (wc_ed448_init(&key) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve448_init failed");
- return ret;
- }
- if (wc_ed448_import_private_key(priv, privSz/2, priv+(privSz/2),
- ED448_PUB_KEY_SIZE, &key) != MP_OKAY){
- WOLFSSL_MSG("wc_ed448_import_private failed");
- wc_ed448_free(&key);
- return ret;
- }
- if (wc_ed448_sign_msg(msg, msgSz, sig, sigSz, &key, NULL, 0) != MP_OKAY)
- WOLFSSL_MSG("wc_curve448_shared_secret_ex failed");
- else
- ret = WOLFSSL_SUCCESS;
- wc_ed448_free(&key);
- return ret;
- #endif /* HAVE_ED448_SIGN && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */
- }
- /* return 1 if success, 0 if error
- * input and output keys are little endian format
- * pub is a buffer containing public part of key
- */
- int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
- const unsigned char *pub, unsigned int pubSz,
- const unsigned char *sig, unsigned int sigSz)
- {
- #if !defined(HAVE_ED448_VERIFY) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED448_KEY_IMPORT)
- #if !defined(HAVE_ED448_VERIFY)
- WOLFSSL_MSG("No ED448 verify built in");
- #elif !defined(WOLFSSL_KEY_GEN)
- WOLFSSL_MSG("No Key Gen built in");
- #elif !defined(HAVE_ED448_KEY_IMPORT)
- WOLFSSL_MSG("No ED448 Key import built in");
- #endif
- (void) msg;
- (void) msgSz;
- (void) pub;
- (void) pubSz;
- (void) sig;
- (void) sigSz;
- return WOLFSSL_FAILURE;
- #else /* HAVE_ED448_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */
- ed448_key key;
- int ret = WOLFSSL_FAILURE, check = 0;
- WOLFSSL_ENTER("wolfSSL_ED448_verify");
- if (pub == NULL || pubSz != ED448_PUB_KEY_SIZE || msg == NULL ||
- sig == NULL || sigSz != ED448_SIG_SIZE) {
- WOLFSSL_MSG("Bad arguments");
- return WOLFSSL_FAILURE;
- }
- /* import key */
- if (wc_ed448_init(&key) != MP_OKAY) {
- WOLFSSL_MSG("wc_curve448_init failed");
- return ret;
- }
- if (wc_ed448_import_public(pub, pubSz, &key) != MP_OKAY){
- WOLFSSL_MSG("wc_ed448_import_public failed");
- wc_ed448_free(&key);
- return ret;
- }
- if ((ret = wc_ed448_verify_msg((byte*)sig, sigSz, msg, msgSz, &check,
- &key, NULL, 0)) != MP_OKAY) {
- WOLFSSL_MSG("wc_ed448_verify_msg failed");
- }
- else if (!check)
- WOLFSSL_MSG("wc_ed448_verify_msg failed (signature invalid)");
- else
- ret = WOLFSSL_SUCCESS;
- wc_ed448_free(&key);
- return ret;
- #endif /* HAVE_ED448_VERIFY && WOLFSSL_KEY_GEN */
- }
- #endif /* OPENSSL_EXTRA && HAVE_ED448 */
- #ifdef WOLFSSL_JNI
- int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr)
- {
- WOLFSSL_ENTER("wolfSSL_set_jobject");
- if (ssl != NULL)
- {
- ssl->jObjectRef = objPtr;
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- void* wolfSSL_get_jobject(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_jobject");
- if (ssl != NULL)
- return ssl->jObjectRef;
- return NULL;
- }
- #endif /* WOLFSSL_JNI */
- #ifdef WOLFSSL_ASYNC_CRYPT
- int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
- WOLF_EVENT_FLAG flags, int* eventCount)
- {
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL,
- events, maxEvents, flags, eventCount);
- }
- int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags)
- {
- int ret, eventCount = 0;
- WOLF_EVENT* events[1];
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
- ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl,
- events, sizeof(events)/sizeof(events[0]), flags, &eventCount);
- if (ret == 0) {
- ret = eventCount;
- }
- return ret;
- }
- #endif /* WOLFSSL_ASYNC_CRYPT */
- #ifdef OPENSSL_EXTRA
- unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line,
- const char **data, int *flags)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data");
- (void)line;
- (void)file;
- /* No data or flags stored - error display only in Nginx. */
- if (data != NULL) {
- *data = "";
- }
- if (flags != NULL) {
- *flags = 0;
- }
- #ifdef WOLFSSL_HAVE_ERROR_QUEUE
- {
- int ret = 0;
- while (1) {
- ret = wc_PeekErrorNode(0, file, NULL, line);
- if (ret == BAD_MUTEX_E || ret == BAD_FUNC_ARG || ret == BAD_STATE_E) {
- WOLFSSL_MSG("Issue peeking at error node in queue");
- return 0;
- }
- /* OpenSSL uses positive error codes */
- if (ret < 0) {
- ret = -ret;
- }
- if (ret == -ASN_NO_PEM_HEADER)
- return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
- #ifdef OPENSSL_ALL
- /* PARSE_ERROR is returned if an HTTP request is detected. */
- if (ret == -SSL_R_HTTP_REQUEST)
- return (ERR_LIB_SSL << 24) | -SSL_R_HTTP_REQUEST;
- #endif
- #if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON)
- if (ret == ASN1_R_HEADER_TOO_LONG) {
- return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG;
- }
- #endif
- if (ret != -WANT_READ && ret != -WANT_WRITE &&
- ret != -ZERO_RETURN && ret != -WOLFSSL_ERROR_ZERO_RETURN &&
- ret != -SOCKET_PEER_CLOSED_E && ret != -SOCKET_ERROR_E)
- break;
- wc_RemoveErrorNode(0);
- }
- return (unsigned long)ret;
- }
- #else
- return (unsigned long)(0 - NOT_COMPILED_IN);
- #endif
- }
- #endif
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- #if !defined(WOLFSSL_USER_IO)
- /* converts an IPv6 or IPv4 address into an octet string for use with rfc3280
- * example input would be "127.0.0.1" and the returned value would be 7F000001
- */
- WOLFSSL_ASN1_STRING* wolfSSL_a2i_IPADDRESS(const char* ipa)
- {
- int ipaSz = WOLFSSL_IP4_ADDR_LEN;
- char buf[WOLFSSL_IP6_ADDR_LEN + 1]; /* plus 1 for terminator */
- int af = WOLFSSL_IP4;
- WOLFSSL_ASN1_STRING *ret = NULL;
- if (ipa == NULL)
- return NULL;
- if (XSTRSTR(ipa, ":") != NULL) {
- af = WOLFSSL_IP6;
- ipaSz = WOLFSSL_IP6_ADDR_LEN;
- }
- buf[WOLFSSL_IP6_ADDR_LEN] = '\0';
- if (XINET_PTON(af, ipa, (void*)buf) != 1) {
- WOLFSSL_MSG("Error parsing IP address");
- return NULL;
- }
- ret = wolfSSL_ASN1_STRING_new();
- if (ret != NULL) {
- if (wolfSSL_ASN1_STRING_set(ret, buf, ipaSz) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error setting the string");
- wolfSSL_ASN1_STRING_free(ret);
- ret = NULL;
- }
- }
- return ret;
- }
- #endif /* !WOLFSSL_USER_IO */
- /* Is the specified cipher suite a fake one used an an extension proxy? */
- static WC_INLINE int SCSV_Check(byte suite0, byte suite)
- {
- (void)suite0;
- (void)suite;
- #ifdef HAVE_RENEGOTIATION_INDICATION
- if (suite0 == CIPHER_BYTE && suite == TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
- return 1;
- #endif
- return 0;
- }
- static WC_INLINE int sslCipherMinMaxCheck(const WOLFSSL *ssl, byte suite0,
- byte suite)
- {
- const CipherSuiteInfo* cipher_names = GetCipherNames();
- int cipherSz = GetCipherNamesSize();
- int i;
- for (i = 0; i < cipherSz; i++)
- if (cipher_names[i].cipherSuite0 == suite0 &&
- cipher_names[i].cipherSuite == suite)
- break;
- if (i == cipherSz)
- return 1;
- /* Check min version */
- if (cipher_names[i].minor < ssl->options.minDowngrade) {
- if (ssl->options.minDowngrade <= TLSv1_2_MINOR &&
- cipher_names[i].minor >= TLSv1_MINOR)
- /* 1.0 ciphersuites are in general available in 1.1 and
- * 1.1 ciphersuites are in general available in 1.2 */
- return 0;
- return 1;
- }
- /* Check max version */
- switch (cipher_names[i].minor) {
- case SSLv3_MINOR :
- return ssl->options.mask & WOLFSSL_OP_NO_SSLv3;
- case TLSv1_MINOR :
- return ssl->options.mask & WOLFSSL_OP_NO_TLSv1;
- case TLSv1_1_MINOR :
- return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1;
- case TLSv1_2_MINOR :
- return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2;
- case TLSv1_3_MINOR :
- return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3;
- default:
- WOLFSSL_MSG("Unrecognized minor version");
- return 1;
- }
- }
- /* returns a pointer to internal cipher suite list. Should not be free'd by
- * caller.
- */
- WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl)
- {
- WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL;
- Suites* suites;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- const CipherSuiteInfo* cipher_names = GetCipherNames();
- int cipherSz = GetCipherNamesSize();
- #endif
- WOLFSSL_ENTER("wolfSSL_get_ciphers_compat");
- if (ssl == NULL || (ssl->suites == NULL && ssl->ctx->suites == NULL)) {
- return NULL;
- }
- if (ssl->suites != NULL) {
- if (ssl->suites->suiteSz == 0 &&
- InitSSL_Suites((WOLFSSL*)ssl) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Suite initialization failure");
- return NULL;
- }
- suites = ssl->suites;
- }
- else {
- suites = ssl->ctx->suites;
- }
- /* check if stack needs populated */
- if (suites->stack == NULL) {
- int i;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- int j;
- /* higher priority of cipher suite will be on top of stack */
- for (i = suites->suiteSz - 2; i >=0; i-=2) {
- #else
- for (i = 0; i < suites->suiteSz; i+=2) {
- #endif
- WOLFSSL_STACK* add;
- /* A couple of suites are placeholders for special options,
- * skip those. */
- if (SCSV_Check(suites->suites[i], suites->suites[i+1])
- || sslCipherMinMaxCheck(ssl, suites->suites[i],
- suites->suites[i+1])) {
- continue;
- }
- add = wolfSSL_sk_new_node(ssl->heap);
- if (add != NULL) {
- add->type = STACK_TYPE_CIPHER;
- add->data.cipher.cipherSuite0 = suites->suites[i];
- add->data.cipher.cipherSuite = suites->suites[i+1];
- add->data.cipher.ssl = ssl;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- for (j = 0; j < cipherSz; j++) {
- if (cipher_names[j].cipherSuite0 ==
- add->data.cipher.cipherSuite0 &&
- cipher_names[j].cipherSuite ==
- add->data.cipher.cipherSuite) {
- add->data.cipher.offset = j;
- break;
- }
- }
- #endif
- #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
- /* in_stack is checked in wolfSSL_CIPHER_description */
- add->data.cipher.in_stack = 1;
- #endif
- add->next = ret;
- if (ret != NULL) {
- add->num = ret->num + 1;
- }
- else {
- add->num = 1;
- }
- ret = add;
- }
- }
- suites->stack = ret;
- }
- return suites->stack;
- }
- #endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
- || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || defined(HAVE_SECRET_CALLBACK)
- long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout");
- if (ctx == NULL)
- return 0;
- return ctx->timeout;
- }
- /* returns the time in seconds of the current timeout */
- long wolfSSL_get_timeout(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_timeout");
- if (ssl == NULL)
- return 0;
- return ssl->timeout;
- }
- #endif
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
- || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
- #ifdef HAVE_ECC
- int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh");
- if (ctx == NULL || ecdh == NULL)
- return BAD_FUNC_ARG;
- ctx->ecdhCurveOID = ecdh->group->curve_oid;
- return WOLFSSL_SUCCESS;
- }
- #endif
- /* Assumes that the session passed in is from the cache. */
- int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session");
- s = ClientSessionToSession(s);
- if (ctx == NULL || s == NULL)
- return BAD_FUNC_ARG;
- #ifdef HAVE_EXT_CACHE
- if (!ctx->internalCacheOff)
- #endif
- {
- /* Don't remove session just timeout session. */
- s->timeout = 0;
- #ifndef NO_SESSION_CACHE
- /* Clear the timeout in the cache */
- {
- int row;
- int i;
- SessionRow* sessRow = NULL;
- WOLFSSL_SESSION *cacheSession;
- const byte* id;
- int ret = 0;
- id = s->sessionID;
- if (s->haveAltSessionID)
- id = s->altSessionID;
- row = (int)(HashObject(id, ID_LEN, &ret) % SESSION_ROWS);
- if (ret != 0) {
- WOLFSSL_MSG("Hash session failed");
- return ret;
- }
- sessRow = &SessionCache[row];
- if (SESSION_ROW_LOCK(sessRow) != 0) {
- WOLFSSL_MSG("Session row lock failed");
- return BAD_MUTEX_E;
- }
- for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) {
- cacheSession = &sessRow->Sessions[i];
- if (XMEMCMP(id, cacheSession->sessionID, ID_LEN) == 0) {
- if (ctx->method->side != cacheSession->side)
- continue;
- cacheSession->timeout = 0;
- #ifdef HAVE_EX_DATA
- if (cacheSession->ownExData) {
- /* Most recent version of ex data is in cache. Copy it
- * over so the user can free it. */
- XMEMCPY(&s->ex_data, &cacheSession->ex_data,
- sizeof(WOLFSSL_CRYPTO_EX_DATA));
- }
- cacheSession->ownExData = 0; /* We clear below */
- s->ownExData = 1;
- #endif
- break;
- }
- }
- SESSION_ROW_UNLOCK(sessRow);
- }
- #endif
- }
- #if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
- if (ctx->rem_sess_cb != NULL) {
- ctx->rem_sess_cb(ctx, s);
- }
- #endif
- return 0;
- }
- #ifndef NO_BIO
- BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_get_rbio");
- /* Nginx sets the buffer size if the read BIO is different to write BIO.
- * The setting buffer size doesn't do anything so return NULL for both.
- */
- if (s == NULL)
- return NULL;
- return s->biord;
- }
- BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_get_wbio");
- (void)s;
- /* Nginx sets the buffer size if the read BIO is different to write BIO.
- * The setting buffer size doesn't do anything so return NULL for both.
- */
- if (s == NULL)
- return NULL;
- return s->biowr;
- }
- #endif /* !NO_BIO */
- int wolfSSL_SSL_do_handshake(WOLFSSL *s)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_do_handshake");
- if (s == NULL)
- return WOLFSSL_FAILURE;
- if (s->options.side == WOLFSSL_CLIENT_END) {
- #ifndef NO_WOLFSSL_CLIENT
- return wolfSSL_connect(s);
- #else
- WOLFSSL_MSG("Client not compiled in");
- return WOLFSSL_FAILURE;
- #endif
- }
- #ifndef NO_WOLFSSL_SERVER
- return wolfSSL_accept(s);
- #else
- WOLFSSL_MSG("Server not compiled in");
- return WOLFSSL_FAILURE;
- #endif
- }
- #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
- int wolfSSL_SSL_in_init(const WOLFSSL *ssl)
- #else
- int wolfSSL_SSL_in_init(WOLFSSL *ssl)
- #endif
- {
- WOLFSSL_ENTER("SSL_in_init");
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- return ssl->options.connectState < SECOND_REPLY_DONE;
- }
- return ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
- }
- int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("SSL_connect_init");
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- return ssl->options.connectState > CONNECT_BEGIN &&
- ssl->options.connectState < SECOND_REPLY_DONE;
- }
- return ssl->options.acceptState > ACCEPT_BEGIN &&
- ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
- }
- #ifndef NO_SESSION_CACHE
- WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl)
- {
- WOLFSSL_ENTER("wolfSSL_SSL_get0_session");
- return ssl->session;
- }
- #endif /* NO_SESSION_CACHE */
- #ifndef NO_BIO
- int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1,
- char *buf, int size)
- {
- int readNextLine;
- int lineLen;
- int len;
- byte isNumCheck;
- word32 outLen;
- const int extraTagSz = MAX_LENGTH_SZ + 1;
- byte intTag[MAX_LENGTH_SZ + 1];
- int idx = 0;
- WOLFSSL_ENTER("wolfSSL_a2i_ASN1_INTEGER");
- if (!bio || !asn1 || !buf || size <= 0) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- /* Reset asn1 */
- if (asn1->isDynamic && asn1->data) {
- XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- XMEMSET(asn1->intData, 0, WOLFSSL_ASN1_INTEGER_MAX);
- asn1->data = asn1->intData;
- asn1->isDynamic = 0;
- asn1->length = 0;
- asn1->negative = 0;
- asn1->type = V_ASN1_INTEGER;
- lineLen = wolfSSL_BIO_gets(bio, buf, size);
- do {
- readNextLine = 0;
- if (lineLen <= 0) {
- WOLFSSL_MSG("wolfSSL_BIO_gets error");
- return WOLFSSL_FAILURE;
- }
- while (lineLen && (buf[lineLen-1] == '\n' || buf[lineLen-1] == '\r'))
- lineLen--;
- if (buf[lineLen-1] == '\\')
- readNextLine = 1;
- /* Ignore none-hex chars at the end of the line */
- outLen = 1;
- while (lineLen && Base16_Decode((byte*)buf + lineLen - 1, 1,
- &isNumCheck, &outLen) == ASN_INPUT_E)
- lineLen--;
- if (!lineLen || lineLen % 2) {
- WOLFSSL_MSG("Invalid line length");
- return WOLFSSL_FAILURE;
- }
- len = asn1->length + (lineLen/2);
- /* Check if it will fit in static memory and
- * save space for the ASN tag in front */
- if (len > (int)(WOLFSSL_ASN1_INTEGER_MAX - extraTagSz)) {
- /* Allocate mem for data */
- if (asn1->isDynamic) {
- byte* tmp = (byte*)XREALLOC(asn1->data, len + extraTagSz, NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (!tmp) {
- WOLFSSL_MSG("realloc error");
- return WOLFSSL_FAILURE;
- }
- asn1->data = tmp;
- }
- else {
- /* Up to this point asn1->data pointed to asn1->intData.
- * Now that the size has grown larger than intData can handle
- * the asn1 structure moves to a dynamic type with isDynamic
- * flag being set and asn1->data being malloc'd. */
- asn1->data = (byte*)XMALLOC(len + extraTagSz, NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (!asn1->data) {
- WOLFSSL_MSG("malloc error");
- return WOLFSSL_FAILURE;
- }
- asn1->isDynamic = 1;
- XMEMCPY(asn1->data, asn1->intData, asn1->length);
- }
- }
- len = lineLen/2;
- if (Base16_Decode((byte*)buf, lineLen, asn1->data + asn1->length,
- (word32*)&len) != 0) {
- WOLFSSL_MSG("Base16_Decode error");
- return WOLFSSL_FAILURE;
- }
- asn1->length += len;
- } while (readNextLine);
- /* Write ASN tag */
- idx = SetASNInt(asn1->length, asn1->data[0], intTag);
- XMEMMOVE(asn1->data + idx, asn1->data, asn1->length);
- XMEMCPY(asn1->data, intTag, idx);
- asn1->dataMax = asn1->length += idx;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a)
- {
- word32 idx = 1;
- int len = 0;
- byte buf[512];
- word32 bufLen = 512;
- WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER");
- if (bp == NULL || a == NULL)
- return WOLFSSL_FAILURE;
- /* Skip ASN.1 INTEGER (type) byte. */
- if (a->data[idx] == 0x80 || /* Indefinite length, can't determine length */
- GetLength(a->data, &idx, &len, a->length) < 0) {
- return 0;
- }
- /* Zero length integer is the value zero. */
- if (len == 0) {
- return wolfSSL_BIO_write(bp, "00", 2);
- }
- if (Base16_Encode(a->data + idx, len, buf, &bufLen) != 0 ||
- bufLen == 0) {
- return 0;
- }
- return wolfSSL_BIO_write(bp, buf, bufLen - 1); /* Don't write out NULL char */
- }
- #endif /* !NO_BIO */
- #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
- /* Expected return values from implementations of OpenSSL ticket key callback.
- */
- #define TICKET_KEY_CB_RET_FAILURE (-1)
- #define TICKET_KEY_CB_RET_NOT_FOUND 0
- #define TICKET_KEY_CB_RET_OK 1
- #define TICKET_KEY_CB_RET_RENEW 2
- /* Implementation of session ticket encryption/decryption using OpenSSL
- * callback to initialize the cipher and HMAC.
- *
- * ssl The SSL/TLS object.
- * keyName The key name - used to identify the key to be used.
- * iv The IV to use.
- * mac The MAC of the encrypted data.
- * enc Encrypt ticket.
- * encTicket The ticket data.
- * encTicketLen The length of the ticket data.
- * encLen The encrypted/decrypted ticket length - output length.
- * ctx Ignored. Application specific data.
- * returns WOLFSSL_TICKET_RET_OK to indicate success,
- * WOLFSSL_TICKET_RET_CREATE if a new ticket is required and
- * WOLFSSL_TICKET_RET_FATAL on error.
- */
- static int wolfSSL_TicketKeyCb(WOLFSSL* ssl,
- unsigned char keyName[WOLFSSL_TICKET_NAME_SZ],
- unsigned char iv[WOLFSSL_TICKET_IV_SZ],
- unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
- int enc, unsigned char* encTicket,
- int encTicketLen, int* encLen, void* ctx)
- {
- byte digest[WC_MAX_DIGEST_SIZE];
- #ifdef WOLFSSL_SMALL_STACK
- WOLFSSL_EVP_CIPHER_CTX *evpCtx;
- #else
- WOLFSSL_EVP_CIPHER_CTX evpCtx[1];
- #endif
- WOLFSSL_HMAC_CTX hmacCtx;
- unsigned int mdSz = 0;
- int len = 0;
- int ret = WOLFSSL_TICKET_RET_FATAL;
- int res;
- int totalSz = 0;
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_TicketKeyCb");
- if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketEncWrapCb == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_TICKET_RET_FATAL;
- }
- #ifdef WOLFSSL_SMALL_STACK
- evpCtx = (WOLFSSL_EVP_CIPHER_CTX *)XMALLOC(sizeof(*evpCtx), ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (evpCtx == NULL) {
- WOLFSSL_MSG("out of memory");
- return WOLFSSL_TICKET_RET_FATAL;
- }
- #endif
- /* Initialize the cipher and HMAC. */
- wolfSSL_EVP_CIPHER_CTX_init(evpCtx);
- if (wolfSSL_HMAC_CTX_Init(&hmacCtx) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init error");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return WOLFSSL_TICKET_RET_FATAL;
- }
- res = ssl->ctx->ticketEncWrapCb(ssl, keyName,
- iv, evpCtx, &hmacCtx, enc);
- if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) {
- WOLFSSL_MSG("Ticket callback error");
- ret = WOLFSSL_TICKET_RET_FATAL;
- goto end;
- }
- if (wolfSSL_HMAC_size(&hmacCtx) > WOLFSSL_TICKET_MAC_SZ) {
- WOLFSSL_MSG("Ticket cipher MAC size error");
- goto end;
- }
- if (enc)
- {
- /* Encrypt in place. */
- if (!wolfSSL_EVP_CipherUpdate(evpCtx, encTicket, &len,
- encTicket, encTicketLen))
- goto end;
- totalSz = len;
- if (totalSz > *encLen)
- goto end;
- if (!wolfSSL_EVP_EncryptFinal(evpCtx, &encTicket[len], &len))
- goto end;
- /* Total length of encrypted data. */
- totalSz += len;
- if (totalSz > *encLen)
- goto end;
- /* HMAC the encrypted data into the parameter 'mac'. */
- if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, totalSz))
- goto end;
- if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz))
- goto end;
- }
- else
- {
- /* HMAC the encrypted data and compare it to the passed in data. */
- if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
- goto end;
- if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz))
- goto end;
- if (XMEMCMP(mac, digest, mdSz) != 0)
- goto end;
- /* Decrypt the ticket data in place. */
- if (!wolfSSL_EVP_CipherUpdate(evpCtx, encTicket, &len,
- encTicket, encTicketLen))
- goto end;
- totalSz = len;
- if (totalSz > encTicketLen)
- goto end;
- if (!wolfSSL_EVP_DecryptFinal(evpCtx, &encTicket[len], &len))
- goto end;
- /* Total length of decrypted data. */
- totalSz += len;
- if (totalSz > encTicketLen)
- goto end;
- }
- *encLen = totalSz;
- if (res == TICKET_KEY_CB_RET_RENEW && !IsAtLeastTLSv1_3(ssl->version)
- && !enc)
- ret = WOLFSSL_TICKET_RET_CREATE;
- else
- ret = WOLFSSL_TICKET_RET_OK;
- end:
- (void)wc_HmacFree(&hmacCtx.hmac);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
- /* Set the callback to use when encrypting/decrypting tickets.
- *
- * ctx The SSL/TLS context object.
- * cb The OpenSSL session ticket callback.
- * returns WOLFSSL_SUCCESS to indicate success.
- */
- int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, ticketCompatCb cb)
- {
- /* Set the ticket encryption callback to be a wrapper around OpenSSL
- * callback.
- */
- ctx->ticketEncCb = wolfSSL_TicketKeyCb;
- ctx->ticketEncWrapCb = cb;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_SESSION_TICKET */
- #endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
- OPENSSL_EXTRA || HAVE_LIGHTY */
- #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
- !defined(NO_WOLFSSL_SERVER)
- /* Serialize the session ticket encryption keys.
- *
- * @param [in] ctx SSL/TLS context object.
- * @param [in] keys Buffer to hold session ticket keys.
- * @param [in] keylen Length of buffer.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the
- * correct length.
- */
- long wolfSSL_CTX_get_tlsext_ticket_keys(WOLFSSL_CTX *ctx,
- unsigned char *keys, int keylen)
- {
- if (ctx == NULL || keys == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (keylen != WOLFSSL_TICKET_KEYS_SZ) {
- return WOLFSSL_FAILURE;
- }
- XMEMCPY(keys, ctx->ticketKeyCtx.name, WOLFSSL_TICKET_NAME_SZ);
- keys += WOLFSSL_TICKET_NAME_SZ;
- XMEMCPY(keys, ctx->ticketKeyCtx.key[0], WOLFSSL_TICKET_KEY_SZ);
- keys += WOLFSSL_TICKET_KEY_SZ;
- XMEMCPY(keys, ctx->ticketKeyCtx.key[1], WOLFSSL_TICKET_KEY_SZ);
- keys += WOLFSSL_TICKET_KEY_SZ;
- c32toa(ctx->ticketKeyCtx.expirary[0], keys);
- keys += OPAQUE32_LEN;
- c32toa(ctx->ticketKeyCtx.expirary[1], keys);
- return WOLFSSL_SUCCESS;
- }
- /* Deserialize the session ticket encryption keys.
- *
- * @param [in] ctx SSL/TLS context object.
- * @param [in] keys Session ticket keys.
- * @param [in] keylen Length of data.
- * @return WOLFSSL_SUCCESS on success.
- * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the
- * correct length.
- */
- long wolfSSL_CTX_set_tlsext_ticket_keys(WOLFSSL_CTX *ctx,
- unsigned char *keys, int keylen)
- {
- if (ctx == NULL || keys == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (keylen != WOLFSSL_TICKET_KEYS_SZ) {
- return WOLFSSL_FAILURE;
- }
- XMEMCPY(ctx->ticketKeyCtx.name, keys, WOLFSSL_TICKET_NAME_SZ);
- keys += WOLFSSL_TICKET_NAME_SZ;
- XMEMCPY(ctx->ticketKeyCtx.key[0], keys, WOLFSSL_TICKET_KEY_SZ);
- keys += WOLFSSL_TICKET_KEY_SZ;
- XMEMCPY(ctx->ticketKeyCtx.key[1], keys, WOLFSSL_TICKET_KEY_SZ);
- keys += WOLFSSL_TICKET_KEY_SZ;
- ato32(keys, &ctx->ticketKeyCtx.expirary[0]);
- keys += OPAQUE32_LEN;
- ato32(keys, &ctx->ticketKeyCtx.expirary[1]);
- return WOLFSSL_SUCCESS;
- }
- #endif
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- #ifdef HAVE_OCSP
- /* Not an OpenSSL API. */
- int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response)
- {
- *response = ssl->ocspResp;
- return ssl->ocspRespSz;
- }
- /* Not an OpenSSL API. */
- char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
- {
- return ssl->url;
- }
- /* Not an OpenSSL API. */
- int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
- {
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- ssl->url = url;
- return WOLFSSL_SUCCESS;
- }
- #endif /* OCSP */
- #endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
- #if defined(HAVE_OCSP) && !defined(NO_ASN_TIME)
- int wolfSSL_get_ocsp_producedDate(
- WOLFSSL *ssl,
- byte *producedDate,
- size_t producedDate_space,
- int *producedDateFormat)
- {
- if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
- (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
- return BAD_FUNC_ARG;
- if ((producedDate == NULL) || (producedDateFormat == NULL))
- return BAD_FUNC_ARG;
- if (XSTRLEN((char *)ssl->ocspProducedDate) >= producedDate_space)
- return BUFFER_E;
- XSTRNCPY((char *)producedDate, (const char *)ssl->ocspProducedDate, producedDate_space);
- *producedDateFormat = ssl->ocspProducedDateFormat;
- return 0;
- }
- int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) {
- int idx = 0;
- if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
- (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
- return BAD_FUNC_ARG;
- if (produced_tm == NULL)
- return BAD_FUNC_ARG;
- if (ExtractDate(ssl->ocspProducedDate,
- (unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx))
- return 0;
- else
- return ASN_PARSE_E;
- }
- #endif
- #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
- defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
- int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain)
- {
- word32 idx;
- word32 length;
- WOLFSSL_STACK* node;
- WOLFSSL_STACK* last = NULL;
- if (ctx == NULL || chain == NULL) {
- chain = NULL;
- return WOLFSSL_FAILURE;
- }
- if (ctx->x509Chain != NULL) {
- *chain = ctx->x509Chain;
- return WOLFSSL_SUCCESS;
- }
- /* If there are no chains then success! */
- *chain = NULL;
- if (ctx->certChain == NULL || ctx->certChain->length == 0) {
- return WOLFSSL_SUCCESS;
- }
- /* Create a new stack of WOLFSSL_X509 object from chain buffer. */
- for (idx = 0; idx < ctx->certChain->length; ) {
- node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (node == NULL)
- return WOLFSSL_FAILURE;
- node->next = NULL;
- /* 3 byte length | X509 DER data */
- ato24(ctx->certChain->buffer + idx, &length);
- idx += 3;
- /* Create a new X509 from DER encoded data. */
- node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx,
- length);
- if (node->data.x509 == NULL) {
- XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
- /* Return as much of the chain as we created. */
- ctx->x509Chain = *chain;
- return WOLFSSL_FAILURE;
- }
- idx += length;
- /* Add object to the end of the stack. */
- if (last == NULL) {
- node->num = 1;
- *chain = node;
- }
- else {
- (*chain)->num++;
- last->next = node;
- }
- last = node;
- }
- ctx->x509Chain = *chain;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_get_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb* cb)
- {
- if (ctx == NULL || ctx->cm == NULL || cb == NULL)
- return WOLFSSL_FAILURE;
- #if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
- if (ctx->cm->ocsp_stapling == NULL)
- return WOLFSSL_FAILURE;
- *cb = ctx->cm->ocsp_stapling->statusCb;
- #else
- (void)cb;
- *cb = NULL;
- #endif
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb)
- {
- if (ctx == NULL || ctx->cm == NULL)
- return WOLFSSL_FAILURE;
- #if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
- /* Ensure stapling is on for callback to be used. */
- wolfSSL_CTX_EnableOCSPStapling(ctx);
- if (ctx->cm->ocsp_stapling == NULL)
- return WOLFSSL_FAILURE;
- ctx->cm->ocsp_stapling->statusCb = cb;
- #else
- (void)cb;
- #endif
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx,
- WOLF_STACK_OF(WOLFSSL_X509) **sk)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get0_chain_certs");
- if (ctx == NULL || sk == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- *sk = ctx->x509Chain;
- return WOLFSSL_SUCCESS;
- }
- #ifdef KEEP_OUR_CERT
- int wolfSSL_get0_chain_certs(WOLFSSL *ssl,
- WOLF_STACK_OF(WOLFSSL_X509) **sk)
- {
- WOLFSSL_ENTER("wolfSSL_get0_chain_certs");
- if (ssl == NULL || sk == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- *sk = ssl->ourCertChain;
- return WOLFSSL_SUCCESS;
- }
- #endif
- WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void)
- {
- WOLF_STACK_OF(WOLFSSL_STRING)* ret = wolfSSL_sk_new_node(NULL);
- if (ret) {
- ret->type = STACK_TYPE_STRING;
- }
- return ret;
- }
- void wolfSSL_WOLFSSL_STRING_free(WOLFSSL_STRING s)
- {
- WOLFSSL_ENTER("wolfSSL_WOLFSSL_STRING_free");
- if (s != NULL)
- XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* sk)
- {
- WOLFSSL_STACK* tmp;
- WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_STRING_free");
- if (sk == NULL)
- return;
- /* parse through stack freeing each node */
- while (sk) {
- tmp = sk->next;
- XFREE(sk->data.string, NULL, DYNAMIC_TYPE_OPENSSL);
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = tmp;
- }
- }
- WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value(WOLF_STACK_OF(WOLFSSL_STRING)* strings,
- int idx)
- {
- for (; idx > 0 && strings != NULL; idx--)
- strings = strings->next;
- if (strings == NULL)
- return NULL;
- return strings->data.string;
- }
- int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings)
- {
- if (strings)
- return (int)strings->num;
- return 0;
- }
- #endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
- defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_QUIC)
- #ifdef HAVE_ALPN
- void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data,
- unsigned int *len)
- {
- word16 nameLen;
- if (ssl != NULL && data != NULL && len != NULL) {
- TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen);
- *len = nameLen;
- }
- }
- int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen,
- const unsigned char *in, unsigned int inLen,
- const unsigned char *clientNames,
- unsigned int clientLen)
- {
- unsigned int i, j;
- byte lenIn, lenClient;
- if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL)
- return OPENSSL_NPN_UNSUPPORTED;
- for (i = 0; i < inLen; i += lenIn) {
- lenIn = in[i++];
- for (j = 0; j < clientLen; j += lenClient) {
- lenClient = clientNames[j++];
- if (lenIn != lenClient)
- continue;
- if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) {
- *out = (unsigned char *)(in + i);
- *outLen = lenIn;
- return OPENSSL_NPN_NEGOTIATED;
- }
- }
- }
- *out = (unsigned char *)clientNames + 1;
- *outLen = clientNames[0];
- return OPENSSL_NPN_NO_OVERLAP;
- }
- void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
- int (*cb) (WOLFSSL *ssl,
- const unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg), void *arg)
- {
- if (ctx != NULL) {
- ctx->alpnSelect = cb;
- ctx->alpnSelectArg = arg;
- }
- }
- void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
- int (*cb) (WOLFSSL *ssl,
- const unsigned char
- **out,
- unsigned int *outlen,
- void *arg), void *arg)
- {
- (void)s;
- (void)cb;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb");
- }
- void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
- int (*cb) (WOLFSSL *ssl,
- unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg), void *arg)
- {
- (void)s;
- (void)cb;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb");
- }
- void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
- unsigned *len)
- {
- (void)s;
- (void)data;
- (void)len;
- WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated");
- }
- #endif /* HAVE_ALPN */
- #endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */
- #ifdef OPENSSL_EXTRA
- int wolfSSL_curve_is_disabled(WOLFSSL* ssl, word16 curve_id)
- {
- return (curve_id <= WOLFSSL_ECC_MAX &&
- ssl->disabledCurves &&
- ssl->disabledCurves & (1 << curve_id));
- }
- #endif
- #if defined(OPENSSL_EXTRA) && (defined(HAVE_ECC) || \
- defined(HAVE_CURVE25519) || defined(HAVE_CURVE448))
- static int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names)
- {
- int idx, start = 0, len;
- word16 curve;
- word32 disabled;
- char name[MAX_CURVE_NAME_SZ];
- /* Disable all curves so that only the ones the user wants are enabled. */
- disabled = 0xFFFFFFFFUL;
- for (idx = 1; names[idx-1] != '\0'; idx++) {
- if (names[idx] != ':' && names[idx] != '\0')
- continue;
- len = idx - start;
- if (len > MAX_CURVE_NAME_SZ - 1)
- return WOLFSSL_FAILURE;
- XMEMCPY(name, names + start, len);
- name[len] = 0;
- if ((XSTRCMP(name, "prime256v1") == 0) ||
- (XSTRCMP(name, "secp256r1") == 0) ||
- (XSTRCMP(name, "P-256") == 0))
- {
- curve = WOLFSSL_ECC_SECP256R1;
- }
- else if ((XSTRCMP(name, "secp384r1") == 0) ||
- (XSTRCMP(name, "P-384") == 0))
- {
- curve = WOLFSSL_ECC_SECP384R1;
- }
- else if ((XSTRCMP(name, "secp521r1") == 0) ||
- (XSTRCMP(name, "P-521") == 0))
- {
- curve = WOLFSSL_ECC_SECP521R1;
- }
- #ifdef HAVE_CURVE25519
- else if (XSTRCMP(name, "X25519") == 0)
- {
- curve = WOLFSSL_ECC_X25519;
- }
- #endif
- #ifdef HAVE_CURVE448
- else if (XSTRCMP(name, "X448") == 0)
- {
- curve = WOLFSSL_ECC_X448;
- }
- #endif
- else {
- #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
- int ret;
- const ecc_set_type *eccSet;
- ret = wc_ecc_get_curve_idx_from_name(name);
- if (ret < 0) {
- WOLFSSL_MSG("Could not find name in set");
- return WOLFSSL_FAILURE;
- }
- eccSet = wc_ecc_get_curve_params(ret);
- if (eccSet == NULL) {
- WOLFSSL_MSG("NULL set returned");
- return WOLFSSL_FAILURE;
- }
- curve = GetCurveByOID(eccSet->oidSum);
- #else
- WOLFSSL_MSG("API not present to search farther using name");
- return WOLFSSL_FAILURE;
- #endif
- }
- if (curve >= (sizeof(word32) * WOLFSSL_BIT_SIZE)) {
- /* shift left more than size of ctx->disabledCurves causes static
- * analysis report */
- WOLFSSL_MSG("curve value is too large for upcoming shift");
- return WOLFSSL_FAILURE;
- }
- #if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT)
- /* set the supported curve so client TLS extension contains only the
- * desired curves */
- if ((ssl
- && wolfSSL_UseSupportedCurve(ssl, curve) != WOLFSSL_SUCCESS)
- || (ctx
- && wolfSSL_CTX_UseSupportedCurve(ctx, curve) != WOLFSSL_SUCCESS)) {
- WOLFSSL_MSG("Unable to set supported curve");
- return WOLFSSL_FAILURE;
- }
- #endif
- /* Switch the bit to off and therefore is enabled. */
- disabled &= ~(1U << curve);
- start = idx + 1;
- }
- if (ssl)
- ssl->disabledCurves = disabled;
- else
- ctx->disabledCurves = disabled;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names)
- {
- if (ctx == NULL || names == NULL) {
- WOLFSSL_MSG("ctx or names was NULL");
- return WOLFSSL_FAILURE;
- }
- return set_curves_list(NULL, ctx, names);
- }
- int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names)
- {
- if (ssl == NULL || names == NULL) {
- WOLFSSL_MSG("ssl or names was NULL");
- return WOLFSSL_FAILURE;
- }
- return set_curves_list(ssl, NULL, names);
- }
- #endif /* OPENSSL_EXTRA && (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) */
- #ifdef OPENSSL_EXTRA
- /* Sets a callback for when sending and receiving protocol messages.
- * This callback is copied to all WOLFSSL objects created from the ctx.
- *
- * ctx WOLFSSL_CTX structure to set callback in
- * cb callback to use
- *
- * return WOLFSSL_SUCCESS on success and SSL_FAILURE with error case
- */
- int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback");
- if (ctx == NULL) {
- WOLFSSL_MSG("Null ctx passed in");
- return WOLFSSL_FAILURE;
- }
- ctx->protoMsgCb = cb;
- return WOLFSSL_SUCCESS;
- }
- /* Sets a callback for when sending and receiving protocol messages.
- *
- * ssl WOLFSSL structure to set callback in
- * cb callback to use
- *
- * return WOLFSSL_SUCCESS on success and SSL_FAILURE with error case
- */
- int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb)
- {
- WOLFSSL_ENTER("wolfSSL_set_msg_callback");
- if (ssl == NULL) {
- return SSL_FAILURE;
- }
- if (cb != NULL) {
- ssl->toInfoOn = 1;
- }
- ssl->protoMsgCb = cb;
- return WOLFSSL_SUCCESS;
- }
- /* set the user argument to pass to the msg callback when called
- * return WOLFSSL_SUCCESS on success */
- int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback_arg");
- if (ctx == NULL) {
- WOLFSSL_MSG("Null WOLFSSL_CTX passed in");
- return WOLFSSL_FAILURE;
- }
- ctx->protoMsgCtx = arg;
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg)
- {
- WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg");
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
- ssl->protoMsgCtx = arg;
- return WOLFSSL_SUCCESS;
- }
- void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line)
- {
- void *ret;
- (void)file;
- (void)line;
- if (data == NULL || siz >= INT_MAX)
- return NULL;
- ret = OPENSSL_malloc(siz);
- if (ret == NULL) {
- return NULL;
- }
- return XMEMCPY(ret, data, siz);
- }
- void wolfSSL_OPENSSL_cleanse(void *ptr, size_t len)
- {
- if (ptr)
- ForceZero(ptr, (word32)len);
- }
- int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p,
- unsigned int p_len)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- if (ctx->alpn_cli_protos != NULL) {
- XFREE((void*)ctx->alpn_cli_protos, ctx->heap, DYNAMIC_TYPE_OPENSSL);
- }
- ctx->alpn_cli_protos = (const unsigned char*)XMALLOC(p_len,
- ctx->heap, DYNAMIC_TYPE_OPENSSL);
- if (ctx->alpn_cli_protos == NULL) {
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- /* 0 on success in OpenSSL, non-0 on failure in OpenSSL
- * the function reverses the return value convention.
- */
- return 1;
- #else
- return WOLFSSL_FAILURE;
- #endif
- }
- XMEMCPY((void*)ctx->alpn_cli_protos, p, p_len);
- ctx->alpn_cli_protos_len = p_len;
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- /* 0 on success in OpenSSL, non-0 on failure in OpenSSL
- * the function reverses the return value convention.
- */
- return 0;
- #else
- return WOLFSSL_SUCCESS;
- #endif
- }
- #ifdef HAVE_ALPN
- #ifndef NO_BIO
- /* Sets the ALPN extension protos
- *
- * example format is
- * unsigned char p[] = {
- * 8, 'h', 't', 't', 'p', '/', '1', '.', '1'
- * };
- *
- * returns WOLFSSL_SUCCESS on success */
- int wolfSSL_set_alpn_protos(WOLFSSL* ssl,
- const unsigned char* p, unsigned int p_len)
- {
- WOLFSSL_BIO* bio;
- char* pt;
- unsigned int sz;
- unsigned int idx = 0;
- int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
- WOLFSSL_ENTER("wolfSSL_set_alpn_protos");
- if (ssl == NULL || p_len <= 1) {
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- /* 0 on success in OpenSSL, non-0 on failure in OpenSSL
- * the function reverses the return value convention.
- */
- return 1;
- #else
- return WOLFSSL_FAILURE;
- #endif
- }
- bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
- if (bio == NULL) {
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- /* 0 on success in OpenSSL, non-0 on failure in OpenSSL
- * the function reverses the return value convention.
- */
- return 1;
- #else
- return WOLFSSL_FAILURE;
- #endif
- }
- /* convert into comma separated list */
- while (idx < p_len - 1) {
- unsigned int i;
- sz = p[idx++];
- if (idx + sz > p_len) {
- WOLFSSL_MSG("Bad list format");
- wolfSSL_BIO_free(bio);
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- /* 0 on success in OpenSSL, non-0 on failure in OpenSSL
- * the function reverses the return value convention.
- */
- return 1;
- #else
- return WOLFSSL_FAILURE;
- #endif
- }
- if (sz > 0) {
- for (i = 0; i < sz; i++) {
- wolfSSL_BIO_write(bio, &p[idx++], 1);
- }
- if (idx < p_len - 1)
- wolfSSL_BIO_write(bio, ",", 1);
- }
- }
- wolfSSL_BIO_write(bio, "\0", 1);
- /* clears out all current ALPN extensions set */
- TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap);
- if ((sz = wolfSSL_BIO_get_mem_data(bio, &pt)) > 0) {
- wolfSSL_UseALPN(ssl, pt, sz, (byte) alpn_opt);
- }
- wolfSSL_BIO_free(bio);
- #if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- /* 0 on success in OpenSSL, non-0 on failure in OpenSSL
- * the function reverses the return value convention.
- */
- return 0;
- #else
- return WOLFSSL_SUCCESS;
- #endif
- }
- #endif /* !NO_BIO */
- #endif /* HAVE_ALPN */
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA)
- #ifndef NO_BIO
- #define WOLFSSL_BIO_INCLUDED
- #include "src/bio.c"
- #endif
- word32 nid2oid(int nid, int grp)
- {
- /* get OID type */
- switch (grp) {
- /* oidHashType */
- case oidHashType:
- switch (nid) {
- #ifdef WOLFSSL_MD2
- case NID_md2:
- return MD2h;
- #endif
- #ifndef NO_MD5
- case NID_md5:
- return MD5h;
- #endif
- #ifndef NO_SHA
- case NID_sha1:
- return SHAh;
- #endif
- case NID_sha224:
- return SHA224h;
- #ifndef NO_SHA256
- case NID_sha256:
- return SHA256h;
- #endif
- #ifdef WOLFSSL_SHA384
- case NID_sha384:
- return SHA384h;
- #endif
- #ifdef WOLFSSL_SHA512
- case NID_sha512:
- return SHA512h;
- #endif
- #ifndef WOLFSSL_NOSHA3_224
- case NID_sha3_224:
- return SHA3_224h;
- #endif
- #ifndef WOLFSSL_NOSHA3_256
- case NID_sha3_256:
- return SHA3_256h;
- #endif
- #ifndef WOLFSSL_NOSHA3_384
- case NID_sha3_384:
- return SHA3_384h;
- #endif
- #ifndef WOLFSSL_NOSHA3_512
- case NID_sha3_512:
- return SHA3_512h;
- #endif
- }
- break;
- /* oidSigType */
- case oidSigType:
- switch (nid) {
- #ifndef NO_DSA
- case NID_dsaWithSHA1:
- return CTC_SHAwDSA;
- case NID_dsa_with_SHA256:
- return CTC_SHA256wDSA;
- #endif /* NO_DSA */
- #ifndef NO_RSA
- case NID_md2WithRSAEncryption:
- return CTC_MD2wRSA;
- case NID_md5WithRSAEncryption:
- return CTC_MD5wRSA;
- case NID_sha1WithRSAEncryption:
- return CTC_SHAwRSA;
- case NID_sha224WithRSAEncryption:
- return CTC_SHA224wRSA;
- case NID_sha256WithRSAEncryption:
- return CTC_SHA256wRSA;
- case NID_sha384WithRSAEncryption:
- return CTC_SHA384wRSA;
- case NID_sha512WithRSAEncryption:
- return CTC_SHA512wRSA;
- #ifdef WOLFSSL_SHA3
- case NID_RSA_SHA3_224:
- return CTC_SHA3_224wRSA;
- case NID_RSA_SHA3_256:
- return CTC_SHA3_256wRSA;
- case NID_RSA_SHA3_384:
- return CTC_SHA3_384wRSA;
- case NID_RSA_SHA3_512:
- return CTC_SHA3_512wRSA;
- #endif
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case NID_ecdsa_with_SHA1:
- return CTC_SHAwECDSA;
- case NID_ecdsa_with_SHA224:
- return CTC_SHA224wECDSA;
- case NID_ecdsa_with_SHA256:
- return CTC_SHA256wECDSA;
- case NID_ecdsa_with_SHA384:
- return CTC_SHA384wECDSA;
- case NID_ecdsa_with_SHA512:
- return CTC_SHA512wECDSA;
- #ifdef WOLFSSL_SHA3
- case NID_ecdsa_with_SHA3_224:
- return CTC_SHA3_224wECDSA;
- case NID_ecdsa_with_SHA3_256:
- return CTC_SHA3_256wECDSA;
- case NID_ecdsa_with_SHA3_384:
- return CTC_SHA3_384wECDSA;
- case NID_ecdsa_with_SHA3_512:
- return CTC_SHA3_512wECDSA;
- #endif
- #endif /* HAVE_ECC */
- }
- break;
- /* oidKeyType */
- case oidKeyType:
- switch (nid) {
- #ifndef NO_DSA
- case NID_dsa:
- return DSAk;
- #endif /* NO_DSA */
- #ifndef NO_RSA
- case NID_rsaEncryption:
- return RSAk;
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case NID_X9_62_id_ecPublicKey:
- return ECDSAk;
- #endif /* HAVE_ECC */
- }
- break;
- #ifdef HAVE_ECC
- case oidCurveType:
- switch (nid) {
- case NID_X9_62_prime192v1:
- return ECC_SECP192R1_OID;
- case NID_X9_62_prime192v2:
- return ECC_PRIME192V2_OID;
- case NID_X9_62_prime192v3:
- return ECC_PRIME192V3_OID;
- case NID_X9_62_prime239v1:
- return ECC_PRIME239V1_OID;
- case NID_X9_62_prime239v2:
- return ECC_PRIME239V2_OID;
- case NID_X9_62_prime239v3:
- return ECC_PRIME239V3_OID;
- case NID_X9_62_prime256v1:
- return ECC_SECP256R1_OID;
- case NID_secp112r1:
- return ECC_SECP112R1_OID;
- case NID_secp112r2:
- return ECC_SECP112R2_OID;
- case NID_secp128r1:
- return ECC_SECP128R1_OID;
- case NID_secp128r2:
- return ECC_SECP128R2_OID;
- case NID_secp160r1:
- return ECC_SECP160R1_OID;
- case NID_secp160r2:
- return ECC_SECP160R2_OID;
- case NID_secp224r1:
- return ECC_SECP224R1_OID;
- case NID_secp384r1:
- return ECC_SECP384R1_OID;
- case NID_secp521r1:
- return ECC_SECP521R1_OID;
- case NID_secp160k1:
- return ECC_SECP160K1_OID;
- case NID_secp192k1:
- return ECC_SECP192K1_OID;
- case NID_secp224k1:
- return ECC_SECP224K1_OID;
- case NID_secp256k1:
- return ECC_SECP256K1_OID;
- case NID_brainpoolP160r1:
- return ECC_BRAINPOOLP160R1_OID;
- case NID_brainpoolP192r1:
- return ECC_BRAINPOOLP192R1_OID;
- case NID_brainpoolP224r1:
- return ECC_BRAINPOOLP224R1_OID;
- case NID_brainpoolP256r1:
- return ECC_BRAINPOOLP256R1_OID;
- case NID_brainpoolP320r1:
- return ECC_BRAINPOOLP320R1_OID;
- case NID_brainpoolP384r1:
- return ECC_BRAINPOOLP384R1_OID;
- case NID_brainpoolP512r1:
- return ECC_BRAINPOOLP512R1_OID;
- }
- break;
- #endif /* HAVE_ECC */
- /* oidBlkType */
- case oidBlkType:
- switch (nid) {
- #ifdef WOLFSSL_AES_128
- case AES128CBCb:
- return AES128CBCb;
- #endif
- #ifdef WOLFSSL_AES_192
- case AES192CBCb:
- return AES192CBCb;
- #endif
- #ifdef WOLFSSL_AES_256
- case AES256CBCb:
- return AES256CBCb;
- #endif
- #ifndef NO_DES3
- case NID_des:
- return DESb;
- case NID_des3:
- return DES3b;
- #endif
- }
- break;
- #ifdef HAVE_OCSP
- case oidOcspType:
- switch (nid) {
- case NID_id_pkix_OCSP_basic:
- return OCSP_BASIC_OID;
- case OCSP_NONCE_OID:
- return OCSP_NONCE_OID;
- }
- break;
- #endif /* HAVE_OCSP */
- /* oidCertExtType */
- case oidCertExtType:
- switch (nid) {
- case NID_basic_constraints:
- return BASIC_CA_OID;
- case NID_subject_alt_name:
- return ALT_NAMES_OID;
- case NID_crl_distribution_points:
- return CRL_DIST_OID;
- case NID_info_access:
- return AUTH_INFO_OID;
- case NID_authority_key_identifier:
- return AUTH_KEY_OID;
- case NID_subject_key_identifier:
- return SUBJ_KEY_OID;
- case NID_inhibit_any_policy:
- return INHIBIT_ANY_OID;
- case NID_key_usage:
- return KEY_USAGE_OID;
- case NID_name_constraints:
- return NAME_CONS_OID;
- case NID_certificate_policies:
- return CERT_POLICY_OID;
- case NID_ext_key_usage:
- return EXT_KEY_USAGE_OID;
- }
- break;
- /* oidCertAuthInfoType */
- case oidCertAuthInfoType:
- switch (nid) {
- case NID_ad_OCSP:
- return AIA_OCSP_OID;
- case NID_ad_ca_issuers:
- return AIA_CA_ISSUER_OID;
- }
- break;
- /* oidCertPolicyType */
- case oidCertPolicyType:
- switch (nid) {
- case NID_any_policy:
- return CP_ANY_OID;
- }
- break;
- /* oidCertAltNameType */
- case oidCertAltNameType:
- switch (nid) {
- case NID_hw_name_oid:
- return HW_NAME_OID;
- }
- break;
- /* oidCertKeyUseType */
- case oidCertKeyUseType:
- switch (nid) {
- case NID_anyExtendedKeyUsage:
- return EKU_ANY_OID;
- case EKU_SERVER_AUTH_OID:
- return EKU_SERVER_AUTH_OID;
- case EKU_CLIENT_AUTH_OID:
- return EKU_CLIENT_AUTH_OID;
- case EKU_OCSP_SIGN_OID:
- return EKU_OCSP_SIGN_OID;
- }
- break;
- /* oidKdfType */
- case oidKdfType:
- switch (nid) {
- case PBKDF2_OID:
- return PBKDF2_OID;
- }
- break;
- /* oidPBEType */
- case oidPBEType:
- switch (nid) {
- case PBE_SHA1_RC4_128:
- return PBE_SHA1_RC4_128;
- case PBE_SHA1_DES:
- return PBE_SHA1_DES;
- case PBE_SHA1_DES3:
- return PBE_SHA1_DES3;
- }
- break;
- /* oidKeyWrapType */
- case oidKeyWrapType:
- switch (nid) {
- #ifdef WOLFSSL_AES_128
- case AES128_WRAP:
- return AES128_WRAP;
- #endif
- #ifdef WOLFSSL_AES_192
- case AES192_WRAP:
- return AES192_WRAP;
- #endif
- #ifdef WOLFSSL_AES_256
- case AES256_WRAP:
- return AES256_WRAP;
- #endif
- }
- break;
- /* oidCmsKeyAgreeType */
- case oidCmsKeyAgreeType:
- switch (nid) {
- #ifndef NO_SHA
- case dhSinglePass_stdDH_sha1kdf_scheme:
- return dhSinglePass_stdDH_sha1kdf_scheme;
- #endif
- #ifdef WOLFSSL_SHA224
- case dhSinglePass_stdDH_sha224kdf_scheme:
- return dhSinglePass_stdDH_sha224kdf_scheme;
- #endif
- #ifndef NO_SHA256
- case dhSinglePass_stdDH_sha256kdf_scheme:
- return dhSinglePass_stdDH_sha256kdf_scheme;
- #endif
- #ifdef WOLFSSL_SHA384
- case dhSinglePass_stdDH_sha384kdf_scheme:
- return dhSinglePass_stdDH_sha384kdf_scheme;
- #endif
- #ifdef WOLFSSL_SHA512
- case dhSinglePass_stdDH_sha512kdf_scheme:
- return dhSinglePass_stdDH_sha512kdf_scheme;
- #endif
- }
- break;
- default:
- WOLFSSL_MSG("NID not in table");
- /* MSVC warns without the cast */
- return (word32)-1;
- }
- /* MSVC warns without the cast */
- return (word32)-1;
- }
- int oid2nid(word32 oid, int grp)
- {
- size_t i;
- /* get OID type */
- switch (grp) {
- /* oidHashType */
- case oidHashType:
- switch (oid) {
- #ifdef WOLFSSL_MD2
- case MD2h:
- return NID_md2;
- #endif
- #ifndef NO_MD5
- case MD5h:
- return NID_md5;
- #endif
- #ifndef NO_SHA
- case SHAh:
- return NID_sha1;
- #endif
- case SHA224h:
- return NID_sha224;
- #ifndef NO_SHA256
- case SHA256h:
- return NID_sha256;
- #endif
- #ifdef WOLFSSL_SHA384
- case SHA384h:
- return NID_sha384;
- #endif
- #ifdef WOLFSSL_SHA512
- case SHA512h:
- return NID_sha512;
- #endif
- }
- break;
- /* oidSigType */
- case oidSigType:
- switch (oid) {
- #ifndef NO_DSA
- case CTC_SHAwDSA:
- return NID_dsaWithSHA1;
- case CTC_SHA256wDSA:
- return NID_dsa_with_SHA256;
- #endif /* NO_DSA */
- #ifndef NO_RSA
- case CTC_MD2wRSA:
- return NID_md2WithRSAEncryption;
- case CTC_MD5wRSA:
- return NID_md5WithRSAEncryption;
- case CTC_SHAwRSA:
- return NID_sha1WithRSAEncryption;
- case CTC_SHA224wRSA:
- return NID_sha224WithRSAEncryption;
- case CTC_SHA256wRSA:
- return NID_sha256WithRSAEncryption;
- case CTC_SHA384wRSA:
- return NID_sha384WithRSAEncryption;
- case CTC_SHA512wRSA:
- return NID_sha512WithRSAEncryption;
- #ifdef WOLFSSL_SHA3
- case CTC_SHA3_224wRSA:
- return NID_RSA_SHA3_224;
- case CTC_SHA3_256wRSA:
- return NID_RSA_SHA3_256;
- case CTC_SHA3_384wRSA:
- return NID_RSA_SHA3_384;
- case CTC_SHA3_512wRSA:
- return NID_RSA_SHA3_512;
- #endif
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case CTC_SHAwECDSA:
- return NID_ecdsa_with_SHA1;
- case CTC_SHA224wECDSA:
- return NID_ecdsa_with_SHA224;
- case CTC_SHA256wECDSA:
- return NID_ecdsa_with_SHA256;
- case CTC_SHA384wECDSA:
- return NID_ecdsa_with_SHA384;
- case CTC_SHA512wECDSA:
- return NID_ecdsa_with_SHA512;
- #ifdef WOLFSSL_SHA3
- case CTC_SHA3_224wECDSA:
- return NID_ecdsa_with_SHA3_224;
- case CTC_SHA3_256wECDSA:
- return NID_ecdsa_with_SHA3_256;
- case CTC_SHA3_384wECDSA:
- return NID_ecdsa_with_SHA3_384;
- case CTC_SHA3_512wECDSA:
- return NID_ecdsa_with_SHA3_512;
- #endif
- #endif /* HAVE_ECC */
- }
- break;
- /* oidKeyType */
- case oidKeyType:
- switch (oid) {
- #ifndef NO_DSA
- case DSAk:
- return NID_dsa;
- #endif /* NO_DSA */
- #ifndef NO_RSA
- case RSAk:
- return NID_rsaEncryption;
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- return NID_X9_62_id_ecPublicKey;
- #endif /* HAVE_ECC */
- }
- break;
- #ifdef HAVE_ECC
- case oidCurveType:
- switch (oid) {
- case ECC_SECP192R1_OID:
- return NID_X9_62_prime192v1;
- case ECC_PRIME192V2_OID:
- return NID_X9_62_prime192v2;
- case ECC_PRIME192V3_OID:
- return NID_X9_62_prime192v3;
- case ECC_PRIME239V1_OID:
- return NID_X9_62_prime239v1;
- case ECC_PRIME239V2_OID:
- return NID_X9_62_prime239v2;
- case ECC_PRIME239V3_OID:
- return NID_X9_62_prime239v3;
- case ECC_SECP256R1_OID:
- return NID_X9_62_prime256v1;
- case ECC_SECP112R1_OID:
- return NID_secp112r1;
- case ECC_SECP112R2_OID:
- return NID_secp112r2;
- case ECC_SECP128R1_OID:
- return NID_secp128r1;
- case ECC_SECP128R2_OID:
- return NID_secp128r2;
- case ECC_SECP160R1_OID:
- return NID_secp160r1;
- case ECC_SECP160R2_OID:
- return NID_secp160r2;
- case ECC_SECP224R1_OID:
- return NID_secp224r1;
- case ECC_SECP384R1_OID:
- return NID_secp384r1;
- case ECC_SECP521R1_OID:
- return NID_secp521r1;
- case ECC_SECP160K1_OID:
- return NID_secp160k1;
- case ECC_SECP192K1_OID:
- return NID_secp192k1;
- case ECC_SECP224K1_OID:
- return NID_secp224k1;
- case ECC_SECP256K1_OID:
- return NID_secp256k1;
- case ECC_BRAINPOOLP160R1_OID:
- return NID_brainpoolP160r1;
- case ECC_BRAINPOOLP192R1_OID:
- return NID_brainpoolP192r1;
- case ECC_BRAINPOOLP224R1_OID:
- return NID_brainpoolP224r1;
- case ECC_BRAINPOOLP256R1_OID:
- return NID_brainpoolP256r1;
- case ECC_BRAINPOOLP320R1_OID:
- return NID_brainpoolP320r1;
- case ECC_BRAINPOOLP384R1_OID:
- return NID_brainpoolP384r1;
- case ECC_BRAINPOOLP512R1_OID:
- return NID_brainpoolP512r1;
- }
- break;
- #endif /* HAVE_ECC */
- /* oidBlkType */
- case oidBlkType:
- switch (oid) {
- #ifdef WOLFSSL_AES_128
- case AES128CBCb:
- return AES128CBCb;
- #endif
- #ifdef WOLFSSL_AES_192
- case AES192CBCb:
- return AES192CBCb;
- #endif
- #ifdef WOLFSSL_AES_256
- case AES256CBCb:
- return AES256CBCb;
- #endif
- #ifndef NO_DES3
- case DESb:
- return NID_des;
- case DES3b:
- return NID_des3;
- #endif
- }
- break;
- #ifdef HAVE_OCSP
- case oidOcspType:
- switch (oid) {
- case OCSP_BASIC_OID:
- return NID_id_pkix_OCSP_basic;
- case OCSP_NONCE_OID:
- return OCSP_NONCE_OID;
- }
- break;
- #endif /* HAVE_OCSP */
- /* oidCertExtType */
- case oidCertExtType:
- switch (oid) {
- case BASIC_CA_OID:
- return NID_basic_constraints;
- case ALT_NAMES_OID:
- return NID_subject_alt_name;
- case CRL_DIST_OID:
- return NID_crl_distribution_points;
- case AUTH_INFO_OID:
- return NID_info_access;
- case AUTH_KEY_OID:
- return NID_authority_key_identifier;
- case SUBJ_KEY_OID:
- return NID_subject_key_identifier;
- case INHIBIT_ANY_OID:
- return NID_inhibit_any_policy;
- case KEY_USAGE_OID:
- return NID_key_usage;
- case NAME_CONS_OID:
- return NID_name_constraints;
- case CERT_POLICY_OID:
- return NID_certificate_policies;
- case EXT_KEY_USAGE_OID:
- return NID_ext_key_usage;
- }
- break;
- /* oidCertAuthInfoType */
- case oidCertAuthInfoType:
- switch (oid) {
- case AIA_OCSP_OID:
- return NID_ad_OCSP;
- case AIA_CA_ISSUER_OID:
- return NID_ad_ca_issuers;
- }
- break;
- /* oidCertPolicyType */
- case oidCertPolicyType:
- switch (oid) {
- case CP_ANY_OID:
- return NID_any_policy;
- }
- break;
- /* oidCertAltNameType */
- case oidCertAltNameType:
- switch (oid) {
- case HW_NAME_OID:
- return NID_hw_name_oid;
- }
- break;
- /* oidCertKeyUseType */
- case oidCertKeyUseType:
- switch (oid) {
- case EKU_ANY_OID:
- return NID_anyExtendedKeyUsage;
- case EKU_SERVER_AUTH_OID:
- return EKU_SERVER_AUTH_OID;
- case EKU_CLIENT_AUTH_OID:
- return EKU_CLIENT_AUTH_OID;
- case EKU_OCSP_SIGN_OID:
- return EKU_OCSP_SIGN_OID;
- }
- break;
- /* oidKdfType */
- case oidKdfType:
- switch (oid) {
- case PBKDF2_OID:
- return PBKDF2_OID;
- }
- break;
- /* oidPBEType */
- case oidPBEType:
- switch (oid) {
- case PBE_SHA1_RC4_128:
- return PBE_SHA1_RC4_128;
- case PBE_SHA1_DES:
- return PBE_SHA1_DES;
- case PBE_SHA1_DES3:
- return PBE_SHA1_DES3;
- }
- break;
- /* oidKeyWrapType */
- case oidKeyWrapType:
- switch (oid) {
- #ifdef WOLFSSL_AES_128
- case AES128_WRAP:
- return AES128_WRAP;
- #endif
- #ifdef WOLFSSL_AES_192
- case AES192_WRAP:
- return AES192_WRAP;
- #endif
- #ifdef WOLFSSL_AES_256
- case AES256_WRAP:
- return AES256_WRAP;
- #endif
- }
- break;
- /* oidCmsKeyAgreeType */
- case oidCmsKeyAgreeType:
- switch (oid) {
- #ifndef NO_SHA
- case dhSinglePass_stdDH_sha1kdf_scheme:
- return dhSinglePass_stdDH_sha1kdf_scheme;
- #endif
- #ifdef WOLFSSL_SHA224
- case dhSinglePass_stdDH_sha224kdf_scheme:
- return dhSinglePass_stdDH_sha224kdf_scheme;
- #endif
- #ifndef NO_SHA256
- case dhSinglePass_stdDH_sha256kdf_scheme:
- return dhSinglePass_stdDH_sha256kdf_scheme;
- #endif
- #ifdef WOLFSSL_SHA384
- case dhSinglePass_stdDH_sha384kdf_scheme:
- return dhSinglePass_stdDH_sha384kdf_scheme;
- #endif
- #ifdef WOLFSSL_SHA512
- case dhSinglePass_stdDH_sha512kdf_scheme:
- return dhSinglePass_stdDH_sha512kdf_scheme;
- #endif
- }
- break;
- #ifdef WOLFSSL_CERT_REQ
- case oidCsrAttrType:
- switch (oid) {
- case PKCS9_CONTENT_TYPE_OID:
- return NID_pkcs9_contentType;
- case CHALLENGE_PASSWORD_OID:
- return NID_pkcs9_challengePassword;
- case SERIAL_NUMBER_OID:
- return NID_serialNumber;
- case USER_ID_OID:
- return NID_userId;
- }
- break;
- #endif
- default:
- WOLFSSL_MSG("NID not in table");
- }
- /* If not found in above switch then try the table */
- for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) {
- if (wolfssl_object_info[i].id == (int)oid) {
- return wolfssl_object_info[i].nid;
- }
- }
- return -1;
- }
- /* when calling SetIndividualInternal, mpi should be cleared by caller if no
- * longer used. ie mp_free(mpi). This is to free data when fastmath is
- * disabled since a copy of mpi is made by this function and placed into bn.
- */
- int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi)
- {
- WOLFSSL_MSG("Entering SetIndividualInternal");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FATAL_ERROR;
- }
- if (mpi == NULL) {
- WOLFSSL_MSG("mpi NULL error");
- return WOLFSSL_FATAL_ERROR;
- }
- if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- return WOLFSSL_FATAL_ERROR;
- }
- return WOLFSSL_SUCCESS;
- }
- #ifndef NO_ASN
- WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
- WOLFSSL_BIGNUM *bn)
- {
- #ifdef WOLFSSL_SMALL_STACK
- mp_int* mpi = NULL;
- #else
- mp_int mpi[1];
- #endif
- word32 idx = 0;
- int ret;
- WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN");
- if (ai == NULL) {
- return NULL;
- }
- #ifdef WOLFSSL_SMALL_STACK
- mpi = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (mpi == NULL) {
- return NULL;
- }
- #endif
- ret = GetInt(mpi, ai->data, &idx, ai->dataMax);
- if (ret != 0) {
- #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY)
- ret = mp_init(mpi); /* must init mpi */
- if (ret != MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- return NULL;
- }
- /* Serial number in QT starts at index 0 of data */
- if (mp_read_unsigned_bin(mpi, (byte*)ai->data, ai->length) != 0) {
- mp_clear(mpi);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- return NULL;
- }
- #else
- /* expecting ASN1 format for INTEGER */
- WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- return NULL;
- #endif
- }
- /* mp_clear needs called because mpi is copied and causes memory leak with
- * --disable-fastmath */
- ret = SetIndividualExternal(&bn, mpi);
- mp_clear(mpi);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- if (ret != WOLFSSL_SUCCESS) {
- return NULL;
- }
- return bn;
- }
- #endif /* !NO_ASN */
- /* frees all nodes in the current threads error queue
- *
- * id thread id. ERR_remove_state is depreciated and id is ignored. The
- * current threads queue will be free'd.
- */
- void wolfSSL_ERR_remove_state(unsigned long id)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_remove_state");
- (void)id;
- if (wc_ERR_remove_state() != 0) {
- WOLFSSL_MSG("Error with removing the state");
- }
- }
- WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
- {
- static int ctx; /* wolfcrypt doesn't now need ctx */
- WOLFSSL_MSG("wolfSSL_BN_CTX_new");
- return (WOLFSSL_BN_CTX*)&ctx;
- }
- void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
- {
- (void)ctx;
- WOLFSSL_MSG("wolfSSL_BN_CTX_init");
- }
- void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
- {
- (void)ctx;
- WOLFSSL_MSG("wolfSSL_BN_CTX_free");
- /* do free since static ctx that does nothing */
- }
- /* WOLFSSL_SUCCESS on ok */
- int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
- const WOLFSSL_BIGNUM* b)
- {
- WOLFSSL_MSG("wolfSSL_BN_sub");
- if (r == NULL || a == NULL || b == NULL)
- return 0;
- if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal,
- (mp_int*)r->internal) == MP_OKAY)
- return WOLFSSL_SUCCESS;
- WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed");
- return 0;
- }
- WOLFSSL_API int wolfSSL_BN_mul(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b,
- WOLFSSL_BN_CTX *ctx)
- {
- int ret = WOLFSSL_SUCCESS;
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_mul");
- if (r == NULL || a == NULL || b == NULL || r->internal == NULL ||
- a->internal == NULL || b->internal == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- ret = mp_mul((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)r->internal);
- if (ret == MP_OKAY) {
- ret = WOLFSSL_SUCCESS;
- }
- else {
- ret = WOLFSSL_FAILURE;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_BN_mul", ret);
- return ret;
- }
- #ifndef WOLFSSL_SP_MATH
- int wolfSSL_BN_div(WOLFSSL_BIGNUM* dv, WOLFSSL_BIGNUM* rem,
- const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* d,
- WOLFSSL_BN_CTX* ctx)
- {
- int ret = WOLFSSL_SUCCESS;
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_div");
- if (dv == NULL || rem == NULL || a == NULL || d == NULL ||
- dv->internal == NULL || rem->internal == NULL || a->internal == NULL ||
- d->internal == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- ret = mp_div((mp_int*)a->internal, (mp_int*)d->internal,
- (mp_int*)dv->internal, (mp_int*)rem->internal);
- if (ret == MP_OKAY) {
- ret = WOLFSSL_SUCCESS;
- }
- else {
- ret = WOLFSSL_FAILURE;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_BN_div", ret);
- return ret;
- }
- #endif
- #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* Needed to get mp_gcd. */
- int wolfSSL_BN_gcd(WOLFSSL_BIGNUM* r, WOLFSSL_BIGNUM* a, WOLFSSL_BIGNUM* b,
- WOLFSSL_BN_CTX* ctx)
- {
- int ret = WOLFSSL_SUCCESS;
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_gcd");
- if (r == NULL || a == NULL || b == NULL || r->internal == NULL ||
- a->internal == NULL || b->internal == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- ret = mp_gcd((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)r->internal);
- if (ret == MP_OKAY) {
- ret = WOLFSSL_SUCCESS;
- }
- else {
- ret = WOLFSSL_FAILURE;
- }
- }
- WOLFSSL_LEAVE("wolfSSL_BN_gcd", ret);
- return ret;
- }
- #endif /* !NO_RSA && WOLFSSL_KEY_GEN */
- /* WOLFSSL_SUCCESS on ok */
- int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
- const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c)
- {
- (void)c;
- WOLFSSL_MSG("wolfSSL_BN_mod");
- if (r == NULL || a == NULL || b == NULL)
- return 0;
- if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal,
- (mp_int*)r->internal) == MP_OKAY)
- return WOLFSSL_SUCCESS;
- WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed");
- return 0;
- }
- /* r = (a^p) % m */
- int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_mod_exp");
- (void) ctx;
- if (r == NULL || a == NULL || p == NULL || m == NULL) {
- WOLFSSL_MSG("Bad Argument");
- return WOLFSSL_FAILURE;
- }
- if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal,
- (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
- return WOLFSSL_SUCCESS;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret);
- (void)ret;
- return WOLFSSL_FAILURE;
- }
- /* r = (a * p) % m */
- int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_mod_mul");
- (void) ctx;
- if (r == NULL || a == NULL || p == NULL || m == NULL) {
- WOLFSSL_MSG("Bad Argument");
- return SSL_FAILURE;
- }
- if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal,
- (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
- return WOLFSSL_SUCCESS;
- }
- WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret);
- (void)ret;
- return SSL_FAILURE;
- }
- const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
- {
- WOLFSSL_MSG("wolfSSL_BN_value_one");
- if (bn_one == NULL) {
- bn_one = wolfSSL_BN_new();
- if (bn_one) {
- if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) {
- /* handle error by freeing BN and returning NULL */
- wolfSSL_BN_free(bn_one);
- bn_one = NULL;
- }
- }
- }
- return bn_one;
- }
- /* return compliant with OpenSSL
- * size of BIGNUM in bytes, 0 if error */
- int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_ENTER("wolfSSL_BN_num_bytes");
- if (bn == NULL || bn->internal == NULL)
- return WOLFSSL_FAILURE;
- return mp_unsigned_bin_size((mp_int*)bn->internal);
- }
- /* return compliant with OpenSSL
- * size of BIGNUM in bits, 0 if error */
- int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_ENTER("wolfSSL_BN_num_bits");
- if (bn == NULL || bn->internal == NULL)
- return WOLFSSL_FAILURE;
- return mp_count_bits((mp_int*)bn->internal);
- }
- int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn)
- {
- if (bn == NULL)
- return WOLFSSL_FAILURE;
- return mp_isneg((mp_int*)bn->internal);
- }
- WOLFSSL_API void wolfSSL_BN_zero(WOLFSSL_BIGNUM* bn)
- {
- if (bn == NULL || bn->internal == NULL) {
- return;
- }
- mp_zero((mp_int*)bn->internal);
- }
- WOLFSSL_API int wolfSSL_BN_one(WOLFSSL_BIGNUM* bn)
- {
- int ret = WOLFSSL_SUCCESS;
- if (bn == NULL || bn->internal == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- ret = wolfSSL_BN_set_word(bn, 1);
- }
- return ret;
- }
- /* return compliant with OpenSSL
- * 1 if BIGNUM is zero, 0 else */
- int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_MSG("wolfSSL_BN_is_zero");
- if (bn == NULL || bn->internal == NULL)
- return WOLFSSL_FAILURE;
- if (mp_iszero((mp_int*)bn->internal) == MP_YES)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- /* return compliant with OpenSSL
- * 1 if BIGNUM is one, 0 else */
- int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_MSG("wolfSSL_BN_is_one");
- if (bn == NULL || bn->internal == NULL)
- return WOLFSSL_FAILURE;
- if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- /* return compliant with OpenSSL
- * 1 if BIGNUM is odd, 0 else */
- int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_MSG("wolfSSL_BN_is_odd");
- if (bn == NULL || bn->internal == NULL)
- return WOLFSSL_FAILURE;
- if (mp_isodd((mp_int*)bn->internal) == MP_YES)
- return WOLFSSL_SUCCESS;
- return WOLFSSL_FAILURE;
- }
- /* return compliant with OpenSSL
- * 1 if BIGNUM is word, 0 else */
- int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
- {
- WOLFSSL_MSG("wolfSSL_BN_is_word");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- if (w <= (WOLFSSL_BN_ULONG)MP_MASK) {
- if (mp_isword((mp_int*)bn->internal, (mp_digit)w) == MP_YES) {
- return WOLFSSL_SUCCESS;
- }
- } else {
- int ret;
- mp_int w_mp;
- if (mp_init(&w_mp) != MP_OKAY)
- return WOLFSSL_FAILURE;
- if (mp_set_int(&w_mp, w) != MP_OKAY)
- return WOLFSSL_FAILURE;
- ret = mp_cmp((mp_int *)bn->internal, &w_mp);
- mp_free(&w_mp);
- if (ret == MP_EQ)
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- /* return compliant with OpenSSL
- * -1 if a < b, 0 if a == b and 1 if a > b
- */
- int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
- {
- int ret;
- WOLFSSL_MSG("wolfSSL_BN_cmp");
- if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL)
- return WOLFSSL_FATAL_ERROR;
- ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
- return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1));
- }
- /* return compliant with OpenSSL
- * length of BIGNUM in bytes, -1 if error */
- int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
- {
- WOLFSSL_MSG("wolfSSL_BN_bn2bin");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("NULL bn error");
- return WOLFSSL_FATAL_ERROR;
- }
- if (r == NULL)
- return mp_unsigned_bin_size((mp_int*)bn->internal);
- if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) {
- WOLFSSL_MSG("mp_to_unsigned_bin error");
- return WOLFSSL_FATAL_ERROR;
- }
- return mp_unsigned_bin_size((mp_int*)bn->internal);
- }
- WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len,
- WOLFSSL_BIGNUM* ret)
- {
- int weOwn = 0;
- WOLFSSL_MSG("wolfSSL_BN_bin2bn");
- /* if ret is null create a BN */
- if (ret == NULL) {
- ret = wolfSSL_BN_new();
- weOwn = 1;
- if (ret == NULL)
- return NULL;
- }
- /* check ret and ret->internal then read in value */
- if (ret && ret->internal) {
- if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) {
- WOLFSSL_MSG("mp_read_unsigned_bin failure");
- if (weOwn)
- wolfSSL_BN_free(ret);
- return NULL;
- }
- } else {
- /* This may be overly defensive */
- if (weOwn)
- wolfSSL_BN_free(ret);
- return NULL;
- }
- return ret;
- }
- /* return compliant with OpenSSL
- * 1 if success, 0 if error */
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
- {
- (void)bn;
- (void)n;
- WOLFSSL_ENTER("wolfSSL_BN_mask_bits");
- WOLFSSL_STUB("BN_mask_bits");
- return SSL_FAILURE;
- }
- #endif
- /* WOLFSSL_SUCCESS on ok */
- int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
- {
- int ret = WOLFSSL_SUCCESS;
- int len = (bits + 7) / 8;
- WC_RNG* rng = &globalRNG;
- byte* buff = NULL;
- WOLFSSL_ENTER("wolfSSL_BN_rand");
- if ((bn == NULL || bn->internal == NULL) || bits < 0 ||
- (bits == 0 && (bottom != 0 || top != -1)) || (bits == 1 && top > 0)) {
- WOLFSSL_MSG("Bad argument");
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (len == 0) {
- mp_zero((mp_int*)bn->internal);
- }
- else {
- buff = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (buff == NULL) {
- WOLFSSL_MSG("Failed to allocate buffer.");
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS && initGlobalRNG == 0 &&
- wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Failed to use global RNG.");
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS &&
- wc_RNG_GenerateBlock(rng, buff, len) != 0) {
- WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS &&
- mp_read_unsigned_bin((mp_int*)bn->internal,buff,len)
- != MP_OKAY) {
- WOLFSSL_MSG("mp_read_unsigned_bin failed");
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- /* Truncate to requested bit length. */
- mp_rshb((mp_int*)bn->internal, 8 - (bits % 8));
- if (top == 0) {
- if (mp_set_bit((mp_int*)bn->internal, bits - 1)
- != MP_OKAY) {
- WOLFSSL_MSG("Failed to set top bit");
- ret = WOLFSSL_FAILURE;
- }
- }
- else if (top > 0) {
- if (mp_set_bit((mp_int*)bn->internal, bits - 1)
- != MP_OKAY ||
- mp_set_bit((mp_int*)bn->internal, bits - 2)
- != MP_OKAY) {
- WOLFSSL_MSG("Failed to set top 2 bits");
- ret = WOLFSSL_FAILURE;
- }
- }
- }
- if (ret == WOLFSSL_SUCCESS && bottom &&
- mp_set_bit((mp_int*)bn->internal, 0) != MP_OKAY) {
- WOLFSSL_MSG("Failed to set 0th bit");
- ret = WOLFSSL_FAILURE;
- }
- if (buff != NULL) {
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- }
- }
- WOLFSSL_LEAVE("wolfSSL_BN_rand", ret);
- return ret;
- }
- /**
- * N = length of range input var
- * Generate N-bit length numbers until generated number is less than range
- * @param r Output number
- * @param range The upper limit of generated output
- * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
- */
- int wolfSSL_BN_rand_range(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *range)
- {
- int n;
- int iter = 0;
- WOLFSSL_MSG("wolfSSL_BN_rand_range");
- if (r == NULL || range == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- n = wolfSSL_BN_num_bits(range);
- if (n <= 1) {
- wolfSSL_BN_zero(r);
- }
- else {
- do {
- if (iter >= 100) {
- WOLFSSL_MSG("wolfSSL_BN_rand_range too many iterations");
- return WOLFSSL_FAILURE;
- }
- iter++;
- if (wolfSSL_BN_pseudo_rand(r, n, -1, 0) == WOLFSSL_FAILURE) {
- WOLFSSL_MSG("wolfSSL_BN_rand error");
- return WOLFSSL_FAILURE;
- }
- } while(wolfSSL_BN_cmp(r, range) >= 0);
- }
- return WOLFSSL_SUCCESS;
- }
- /* WOLFSSL_SUCCESS on ok
- * code is same as wolfSSL_BN_rand except for how top and bottom is handled.
- * top -1 then leave most sig bit alone
- * top 0 then most sig is set to 1
- * top is 1 then first two most sig bits are 1
- *
- * bottom is hot then odd number */
- int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
- {
- int ret = 0;
- int len;
- int initTmpRng = 0;
- WC_RNG* rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRNG = NULL;
- byte* buff = NULL;
- #else
- WC_RNG tmpRNG[1];
- byte buff[1024];
- #endif
- WOLFSSL_ENTER("wolfSSL_BN_pseudo_rand");
- if (bits <= 0) {
- return WOLFSSL_FAILURE;
- }
- len = bits / 8;
- if (bits % 8)
- len++;
- /* has to be a length of at least 1 since we set buf[0] and buf[len-1] */
- if (top == 1 || top == 0 || bottom == 1) {
- if (len < 1) {
- return WOLFSSL_FAILURE;
- }
- }
- #ifdef WOLFSSL_SMALL_STACK
- buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (buff == NULL || tmpRNG == NULL) {
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- #endif
- if (bn == NULL || bn->internal == NULL)
- WOLFSSL_MSG("Bad function arguments");
- else if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else if (initGlobalRNG)
- rng = &globalRNG;
- if (rng) {
- if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
- WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
- else {
- switch (top) {
- case -1:
- break;
- case 0:
- buff[0] |= 0x80;
- break;
- case 1:
- buff[0] |= 0x80 | 0x40;
- break;
- }
- if (bottom == 1) {
- buff[len-1] |= 0x01;
- }
- if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
- WOLFSSL_MSG("mp read bin failed");
- else
- ret = WOLFSSL_SUCCESS;
- }
- }
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
- /* return code compliant with OpenSSL :
- * 1 if bit set, 0 else
- */
- int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
- {
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n);
- }
- /* return code compliant with OpenSSL :
- * 1 if success, 0 else
- */
- int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n)
- {
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) {
- WOLFSSL_MSG("mp_set_bit error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n)
- {
- int ret = WOLFSSL_FAILURE;
- #ifndef WOLFSSL_SMALL_STACK
- mp_int tmp[1];
- #else
- mp_int* tmp = NULL;
- #endif
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- goto end;
- }
- if (mp_is_bit_set((mp_int*)bn->internal, n)) {
- #ifdef WOLFSSL_SMALL_STACK
- tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (tmp == NULL) {
- goto end;
- }
- #endif
- if (mp_init(tmp) != MP_OKAY) {
- goto end;
- }
- if (mp_set_bit(tmp, n) != MP_OKAY) {
- goto cleanup;
- }
- if (mp_sub((mp_int*)bn->internal, tmp, (mp_int*)bn->internal) != MP_OKAY) {
- goto cleanup;
- }
- } else {
- goto end;
- }
- ret = WOLFSSL_SUCCESS;
- cleanup:
- mp_clear(tmp);
- end:
- #ifdef WOLFSSL_SMALL_STACK
- if (tmp)
- XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- return ret;
- }
- /* WOLFSSL_SUCCESS on ok */
- /* Note on use: this function expects str to be an even length. It is
- * converting pairs of bytes into 8-bit values. As an example, the RSA
- * public exponent is commonly 0x010001. To get it to convert, you need
- * to pass in the string "010001", it will fail if you use "10001". This
- * is an affect of how Base16_Decode() works.
- */
- int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str)
- {
- int ret = 0;
- word32 decSz = 1024;
- #ifdef WOLFSSL_SMALL_STACK
- byte* decoded;
- #else
- byte decoded[1024];
- #endif
- int weOwn = 0;
- int strLen;
- WOLFSSL_MSG("wolfSSL_BN_hex2bn");
- #ifdef WOLFSSL_SMALL_STACK
- decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER);
- if (decoded == NULL)
- return ret;
- #endif
- if (str == NULL || str[0] == '\0') {
- WOLFSSL_MSG("Bad function argument");
- ret = WOLFSSL_FAILURE;
- } else {
- strLen = (int)XSTRLEN(str);
- /* ignore trailing new lines */
- while (str[strLen-1] == '\n' && strLen > 0) strLen--;
- if (Base16_Decode((byte*)str, strLen, decoded, &decSz) < 0)
- WOLFSSL_MSG("Bad Base16_Decode error");
- else if (bn == NULL)
- ret = decSz;
- else {
- if (*bn == NULL) {
- *bn = wolfSSL_BN_new();
- if (*bn != NULL) {
- weOwn = 1;
- }
- }
- if (*bn == NULL)
- WOLFSSL_MSG("BN new failed");
- else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) {
- WOLFSSL_MSG("Bad bin2bn error");
- if (weOwn == 1) {
- wolfSSL_BN_free(*bn); /* Free new BN */
- }
- }
- else
- ret = WOLFSSL_SUCCESS;
- }
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(decoded, NULL, DYNAMIC_TYPE_DER);
- #endif
- return ret;
- }
- WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_BIGNUM* ret;
- WOLFSSL_MSG("wolfSSL_BN_dup");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return NULL;
- }
- ret = wolfSSL_BN_new();
- if (ret == NULL) {
- WOLFSSL_MSG("bn new error");
- return NULL;
- }
- if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- wolfSSL_BN_free(ret);
- return NULL;
- }
- ret->neg = bn->neg;
- return ret;
- }
- WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_MSG("wolfSSL_BN_copy");
- if (r == NULL || bn == NULL) {
- WOLFSSL_MSG("r or bn NULL error");
- return NULL;
- }
- if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- return NULL;
- }
- r->neg = bn->neg;
- return r;
- }
- /* return code compliant with OpenSSL :
- * 1 if success, 0 else
- */
- int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, unsigned long w)
- {
- WOLFSSL_MSG("wolfSSL_BN_set_word");
- if (bn == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) {
- WOLFSSL_MSG("mp_init_set_int error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- static WOLFSSL_BN_ULONG wolfSSL_BN_get_word_1(mp_int *mp) {
- #if DIGIT_BIT >= (SIZEOF_LONG * CHAR_BIT)
- return (WOLFSSL_BN_ULONG)mp->dp[0];
- #else
- WOLFSSL_BN_ULONG ret = 0UL;
- int digit_i;
- for (digit_i = 0; digit_i < mp->used; ++digit_i)
- ret |= ((WOLFSSL_BN_ULONG)mp->dp[digit_i]) << (DIGIT_BIT * digit_i);
- return ret;
- #endif
- }
- /* Returns the big number as an unsigned long if possible.
- *
- * bn big number structure to get value from
- *
- * Returns value or 0xFFFFFFFFL if bigger than unsigned long.
- */
- WOLFSSL_BN_ULONG wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn)
- {
- WOLFSSL_MSG("wolfSSL_BN_get_word");
- if (bn == NULL) {
- WOLFSSL_MSG("Invalid argument");
- return 0;
- }
- if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) {
- WOLFSSL_MSG("bignum is larger than unsigned long");
- return 0xFFFFFFFFL;
- }
- return wolfSSL_BN_get_word_1((mp_int*)bn->internal);
- }
- /* return code compliant with OpenSSL :
- * number length in decimal if success, 0 if error
- */
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
- {
- (void)bn;
- (void)str;
- WOLFSSL_MSG("wolfSSL_BN_dec2bn");
- WOLFSSL_STUB("BN_dec2bn");
- return SSL_FAILURE;
- }
- #endif
- #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
- char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn)
- {
- int len = 0;
- char *buf;
- WOLFSSL_MSG("wolfSSL_BN_bn2dec");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return NULL;
- }
- if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) {
- WOLFSSL_MSG("mp_radix_size failure");
- return NULL;
- }
- buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
- if (buf == NULL) {
- WOLFSSL_MSG("BN_bn2dec malloc buffer failure");
- return NULL;
- }
- if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) {
- XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
- return NULL;
- }
- return buf;
- }
- #else
- char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
- {
- (void)bn;
- WOLFSSL_MSG("wolfSSL_BN_bn2dec");
- return NULL;
- }
- #endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
- /* Internal function for adding/subtracting an unsigned long from a
- * WOLFSSL_BIGNUM. To add, pass "sub" as 0. To subtract, pass it as 1.
- * Returns 1 (WOLFSSL_SUCCESS) on success and 0 (WOLFSSL_FAILURE) on failure.
- */
- static int wolfSSL_BN_add_word_int(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w,
- int sub)
- {
- int ret = WOLFSSL_SUCCESS;
- int rc = 0;
- #ifdef WOLFSSL_SMALL_STACK
- mp_int *w_mp = (mp_int *)XMALLOC(sizeof(*w_mp), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (w_mp == NULL)
- return WOLFSSL_FAILURE;
- #else
- mp_int w_mp[1];
- #endif
- XMEMSET(w_mp, 0, sizeof(*w_mp));
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (w <= (WOLFSSL_BN_ULONG)MP_MASK) {
- if (sub == 1) {
- rc = mp_sub_d((mp_int*)bn->internal, (mp_digit)w,
- (mp_int*)bn->internal);
- }
- else {
- rc = mp_add_d((mp_int*)bn->internal, (mp_digit)w,
- (mp_int*)bn->internal);
- }
- if (rc != MP_OKAY) {
- WOLFSSL_MSG("mp_add/sub_d error");
- ret = WOLFSSL_FAILURE;
- }
- }
- else {
- if (mp_init(w_mp) != MP_OKAY) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (mp_set_int(w_mp, w) != MP_OKAY) {
- ret = WOLFSSL_FAILURE;
- }
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (sub == 1) {
- rc = mp_sub((mp_int *)bn->internal, w_mp,
- (mp_int *)bn->internal);
- }
- else {
- rc = mp_add((mp_int *)bn->internal, w_mp,
- (mp_int *)bn->internal);
- }
- if (rc != MP_OKAY) {
- WOLFSSL_MSG("mp_add/sub error");
- ret = WOLFSSL_FAILURE;
- }
- }
- }
- }
- mp_free(w_mp);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(w_mp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
- /* return code compliant with OpenSSL :
- * 1 if success, 0 else
- */
- int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_add_word");
- ret = wolfSSL_BN_add_word_int(bn, w, 0);
- WOLFSSL_LEAVE("wolfSSL_BN_add_word", ret);
- return ret;
- }
- /* return code compliant with OpenSSL :
- * 1 if success, 0 else
- */
- WOLFSSL_API int wolfSSL_BN_sub_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
- {
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_sub_word");
- ret = wolfSSL_BN_add_word_int(bn, w, 1);
- WOLFSSL_LEAVE("wolfSSL_BN_sub_word", ret);
- return ret;
- }
- #ifndef WOLFSSL_SP_MATH
- /* return code compliant with OpenSSL :
- * 1 if success, 0 else
- */
- int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
- {
- WOLFSSL_MSG("wolfSSL_BN_lshift");
- if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) {
- WOLFSSL_MSG("mp_mul_2d error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- /* return code compliant with OpenSSL :
- * 1 if success, 0 else
- */
- int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
- {
- WOLFSSL_MSG("wolfSSL_BN_rshift");
- if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- if (mp_div_2d((mp_int*)bn->internal, n,
- (mp_int*)r->internal, NULL) != MP_OKAY) {
- WOLFSSL_MSG("mp_mul_2d error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif
- /* return code compliant with OpenSSL :
- * 1 if success, 0 else
- */
- int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b)
- {
- WOLFSSL_MSG("wolfSSL_BN_add");
- if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL ||
- b == NULL || b->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- if (mp_add((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)r->internal) != MP_OKAY) {
- WOLFSSL_MSG("mp_add_d error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #ifndef WOLFSSL_SP_MATH
- /* r = a + b (mod m) */
- int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m,
- WOLFSSL_BN_CTX *ctx)
- {
- (void)ctx;
- WOLFSSL_MSG("wolfSSL_BN_add");
- if (r == NULL || r->internal == NULL ||
- a == NULL || a->internal == NULL ||
- b == NULL || b->internal == NULL ||
- m == NULL || m->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- if (mp_addmod((mp_int*)a->internal, (mp_int*)b->internal,
- (mp_int*)m->internal, (mp_int*)r->internal) != MP_OKAY) {
- WOLFSSL_MSG("mp_add_d error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif
- #if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA))
- int wolfSSL_BN_generate_prime_ex(WOLFSSL_BIGNUM* prime, int bits,
- int safe, const WOLFSSL_BIGNUM* add, const WOLFSSL_BIGNUM* rem,
- WOLFSSL_BN_GENCB* cb)
- {
- int ret = WOLFSSL_SUCCESS;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG* rng = NULL;
- #else
- WC_RNG rng[1];
- #endif
- (void)cb;
- WOLFSSL_ENTER("wolfSSL_BN_generate_prime_ex");
- if (safe == 1 || add != NULL || rem != NULL) {
- /* These parameters aren't supported, yet. */
- ret = WOLFSSL_FAILURE;
- }
- if (prime == NULL || prime->internal == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (ret == WOLFSSL_SUCCESS) {
- rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (rng == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- }
- #endif
- if (ret == WOLFSSL_SUCCESS) {
- XMEMSET(rng, 0, sizeof(WC_RNG));
- if (wc_InitRng(rng) != 0) {
- ret = WOLFSSL_FAILURE;
- }
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (mp_rand_prime((mp_int*)prime->internal, (bits + 7) / 8, rng, NULL)
- != MP_OKAY) {
- ret = WOLFSSL_FAILURE;
- }
- }
- wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- if (rng != NULL)
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
- WOLFSSL_LEAVE("wolfSSL_BN_generate_prime_ex", ret);
- return ret;
- }
- /* return code compliant with OpenSSL :
- * 1 if prime, 0 if not, -1 if error
- */
- int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks,
- WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb)
- {
- WC_RNG* rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRNG = NULL;
- #else
- WC_RNG tmpRNG[1];
- #endif
- int initTmpRng = 0;
- int res = MP_NO;
- (void)ctx;
- (void)cb;
- WOLFSSL_MSG("wolfSSL_BN_is_prime_ex");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FATAL_ERROR;
- }
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRNG == NULL)
- return WOLFSSL_FAILURE;
- #endif
- if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- else {
- WOLFSSL_MSG("Bad RNG Init, trying global");
- if (initGlobalRNG == 0) {
- WOLFSSL_MSG("Global RNG no Init");
- }
- else
- rng = &globalRNG;
- }
- if (rng) {
- if (mp_prime_is_prime_ex((mp_int*)bn->internal,
- nbchecks, &res, rng) != MP_OKAY) {
- WOLFSSL_MSG("mp_prime_is_prime_ex error");
- res = MP_NO;
- }
- }
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
- #endif
- if (res != MP_YES) {
- WOLFSSL_MSG("mp_prime_is_prime_ex not prime");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
- }
- /* return code compliant with OpenSSL :
- * (bn mod w) if success, -1 if error
- */
- WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn,
- WOLFSSL_BN_ULONG w)
- {
- WOLFSSL_BN_ULONG ret = 0;
- WOLFSSL_MSG("wolfSSL_BN_mod_word");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
- }
- if (w <= (WOLFSSL_BN_ULONG)MP_MASK) {
- mp_digit bn_ret;
- if (mp_mod_d((mp_int*)bn->internal, (mp_digit)w, &bn_ret) != MP_OKAY) {
- WOLFSSL_MSG("mp_add_d error");
- return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
- }
- ret = (WOLFSSL_BN_ULONG)bn_ret;
- } else {
- int mp_ret;
- mp_int w_mp, r_mp;
- if (mp_init(&w_mp) != MP_OKAY)
- return (unsigned long)WOLFSSL_FAILURE;
- if (mp_init(&r_mp) != MP_OKAY)
- return (unsigned long)WOLFSSL_FAILURE;
- if (mp_set_int(&w_mp, w) != MP_OKAY)
- return (unsigned long)WOLFSSL_FAILURE;
- mp_ret = mp_mod((mp_int *)bn->internal, &w_mp, &r_mp);
- ret = wolfSSL_BN_get_word_1(&r_mp);
- mp_free(&r_mp);
- mp_free(&w_mp);
- if (mp_ret != MP_OKAY) {
- WOLFSSL_MSG("mp_mod error");
- return (WOLFSSL_BN_ULONG)WOLFSSL_FAILURE;
- }
- }
- return ret;
- }
- #endif /* WOLFSSL_KEY_GEN && (!NO_RSA || !NO_DH || !NO_DSA) */
- char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn)
- {
- int len = 0;
- char *buf;
- WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
- if (bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return NULL;
- }
- if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) {
- WOLFSSL_MSG("mp_radix_size failure");
- return NULL;
- }
- buf = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
- if (buf == NULL) {
- WOLFSSL_MSG("BN_bn2hex malloc buffer failure");
- return NULL;
- }
- if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) {
- XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
- return NULL;
- }
- return buf;
- }
- #ifndef NO_FILESYSTEM
- /* return code compliant with OpenSSL :
- * 1 if success, 0 if error
- */
- int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn)
- {
- char *buf;
- int ret;
- WOLFSSL_ENTER("wolfSSL_BN_print_fp");
- if (fp == XBADFILE || bn == NULL || bn->internal == NULL) {
- WOLFSSL_MSG("bn NULL error");
- return WOLFSSL_FAILURE;
- }
- buf = wolfSSL_BN_bn2hex(bn);
- if (buf == NULL) {
- WOLFSSL_MSG("wolfSSL_BN_bn2hex failure");
- return WOLFSSL_FAILURE;
- }
- if (XFPRINTF(fp, "%s", buf) < 0)
- ret = WOLFSSL_FAILURE;
- else
- ret = WOLFSSL_SUCCESS;
- XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
- return ret;
- }
- #endif /* !NO_FILESYSTEM */
- WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx)
- {
- /* ctx is not used, return new Bignum */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_CTX_get");
- return wolfSSL_BN_new();
- }
- #ifndef NO_WOLFSSL_STUB
- void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx)
- {
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_CTX_start");
- WOLFSSL_STUB("BN_CTX_start");
- WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD");
- }
- #endif
- WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r,
- WOLFSSL_BIGNUM *a,
- const WOLFSSL_BIGNUM *n,
- WOLFSSL_BN_CTX *ctx)
- {
- int dynamic = 0;
- /* ctx is not used */
- (void)ctx;
- WOLFSSL_ENTER("wolfSSL_BN_mod_inverse");
- /* check parameter */
- if (r == NULL) {
- r = wolfSSL_BN_new();
- if (r == NULL){
- WOLFSSL_MSG("WolfSSL_BN_new() failed");
- return NULL;
- }
- dynamic = 1;
- }
- if (a == NULL) {
- WOLFSSL_MSG("a NULL error");
- if (dynamic == 1) {
- wolfSSL_BN_free(r);
- }
- return NULL;
- }
- if (n == NULL) {
- WOLFSSL_MSG("n NULL error");
- if (dynamic == 1) {
- wolfSSL_BN_free(r);
- }
- return NULL;
- }
- /* Compute inverse of a modulo n and return r */
- if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal,
- (mp_int*)r->internal) == MP_VAL){
- WOLFSSL_MSG("mp_invmod() error");
- if (dynamic == 1) {
- wolfSSL_BN_free(r);
- }
- return NULL;
- }
- return r;
- }
- #endif /* OPENSSL_EXTRA */
- #if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && \
- !defined(NO_ASN)
- #ifndef NO_BIO
- static int unprintable_char(char c)
- {
- const unsigned char last_unprintable = 31;
- const unsigned char LF = 10;
- const unsigned char CR = 13;
- if (c <= last_unprintable && c != LF && c != CR) {
- return 1;
- }
- return 0;
- }
- int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str)
- {
- int i;
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_print");
- if (out == NULL || str == NULL)
- return WOLFSSL_FAILURE;
- for (i=0; i < str->length; i++) {
- if (unprintable_char(str->data[i])) {
- str->data[i] = '.';
- }
- }
- if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
- return WOLFSSL_FAILURE;
- }
- return str->length;
- }
- #endif /* !NO_BIO */
- #endif /* (WOLFSSL_QT || OPENSSL_ALL || OPENSSL_EXTRA) && !NO_ASN */
- #if defined(OPENSSL_EXTRA)
- const char *wolfSSL_ASN1_tag2str(int tag)
- {
- static const char *const tag_label[31] = {
- "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL",
- "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED",
- "<ASN1 11>", "UTF8STRING", "<ASN1 13>", "<ASN1 14>", "<ASN1 15>",
- "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
- "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
- "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING",
- "<ASN1 29>", "BMPSTRING"
- };
- if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
- tag &= ~0x100;
- if (tag < 0 || tag > 30)
- return "(unknown)";
- return tag_label[tag];
- }
- #ifndef NO_BIO
- static int check_esc_char(char c, char *esc)
- {
- char *ptr;
- ptr = esc;
- while(*ptr != 0){
- if (c == *ptr)
- return 1;
- ptr++;
- }
- return 0;
- }
- int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str,
- unsigned long flags)
- {
- size_t str_len = 0, type_len = 0;
- unsigned char *typebuf = NULL;
- const char *hash="#";
- WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex");
- if (out == NULL || str == NULL)
- return WOLFSSL_FAILURE;
- /* add ASN1 type tag */
- if (flags & ASN1_STRFLGS_SHOW_TYPE){
- const char *tag = wolfSSL_ASN1_tag2str(str->type);
- /* colon len + tag len + null*/
- type_len = XSTRLEN(tag) + 2;
- typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (typebuf == NULL){
- WOLFSSL_MSG("memory alloc failed.");
- return WOLFSSL_FAILURE;
- }
- XMEMSET(typebuf, 0, type_len);
- if (XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag)
- >= (int)type_len)
- {
- WOLFSSL_MSG("Buffer overrun.");
- return WOLFSSL_FAILURE;
- }
- type_len--;
- }
- /* dump hex */
- if (flags & ASN1_STRFLGS_DUMP_ALL){
- char hex_tmp[4];
- char *str_ptr, *str_end;
- if (type_len > 0){
- if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
- XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_FAILURE;
- }
- str_len += type_len;
- }
- if (wolfSSL_BIO_write(out, hash, 1) != 1){
- goto err_exit;
- }
- str_len++;
- if (flags & ASN1_STRFLGS_DUMP_DER){
- ByteToHexStr((byte)str->type, &hex_tmp[0]);
- ByteToHexStr((byte)str->length, &hex_tmp[2]);
- if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){
- goto err_exit;
- }
- str_len += 4;
- XMEMSET(hex_tmp, 0, 4);
- }
- str_ptr = str->data;
- str_end = str->data + str->length;
- while (str_ptr < str_end){
- ByteToHexStr((byte)*str_ptr, &hex_tmp[0]);
- if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){
- goto err_exit;
- }
- str_ptr++;
- str_len += 2;
- }
- if (type_len > 0)
- XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return (int)str_len;
- }
- if (type_len > 0){
- if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
- XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_FAILURE;
- }
- str_len += type_len;
- }
- if (flags & ASN1_STRFLGS_ESC_2253){
- char esc_ch[] = "+;<>\\";
- char* esc_ptr;
- esc_ptr = str->data;
- while (*esc_ptr != 0){
- if (check_esc_char(*esc_ptr, esc_ch)){
- if (wolfSSL_BIO_write(out,"\\", 1) != 1)
- goto err_exit;
- str_len++;
- }
- if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1)
- goto err_exit;
- str_len++;
- esc_ptr++;
- }
- if (type_len > 0)
- XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return (int)str_len;
- }
- if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
- goto err_exit;
- }
- str_len += str->length;
- if (type_len > 0)
- XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return (int)str_len;
- err_exit:
- if (type_len > 0)
- XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_FAILURE;
- }
- #endif /* !NO_BIO */
- #if !defined(NO_ASN_TIME) && !defined(USER_TIME) && !defined(TIME_OVERRIDES)
- WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t,
- int offset_day, long offset_sec)
- {
- const time_t sec_per_day = 24*60*60;
- time_t t_adj = 0;
- time_t offset_day_sec = 0;
- char time_str[MAX_TIME_STRING_SZ];
- int time_get;
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj");
- if (s == NULL) {
- s = wolfSSL_ASN1_TIME_new();
- if (s == NULL) {
- return NULL;
- }
- }
- /* compute GMT time with offset */
- offset_day_sec = offset_day * sec_per_day;
- t_adj = t + offset_day_sec + offset_sec;
- /* Get time string as either UTC or GeneralizedTime */
- time_get = GetFormattedTime(&t_adj, (byte*)time_str,
- (word32)sizeof(time_str));
- if (time_get <= 0) {
- wolfSSL_ASN1_TIME_free(s);
- return NULL;
- }
- if (wolfSSL_ASN1_TIME_set_string(s, time_str) != WOLFSSL_SUCCESS) {
- wolfSSL_ASN1_TIME_free(s);
- return NULL;
- }
- return s;
- }
- #endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES */
- #ifndef NO_ASN_TIME
- WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void)
- {
- WOLFSSL_ASN1_TIME* ret = (WOLFSSL_ASN1_TIME*)
- XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, DYNAMIC_TYPE_OPENSSL);
- if (!ret)
- return NULL;
- XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME));
- return ret;
- }
- void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t)
- {
- if (t) {
- XFREE(t, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- /* not a compatibility function - length getter for opaque type */
- int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t)
- {
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_length");
- if (t == NULL)
- return WOLFSSL_FAILURE;
- return t->length;
- }
- /* not a compatibility function - data getter for opaque type */
- unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t)
- {
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_data");
- if (t == NULL)
- return NULL;
- return t->data;
- }
- WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
- WOLFSSL_ASN1_TIME **out)
- {
- int time_type = 0;
- WOLFSSL_ASN1_TIME *ret = NULL;
- WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime");
- if (t == NULL) {
- WOLFSSL_MSG("Invalid ASN_TIME value");
- } else {
- time_type = t->type;
- if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){
- WOLFSSL_MSG("Invalid ASN_TIME type.");
- } else {
- if (out == NULL || *out == NULL) {
- ret = wolfSSL_ASN1_TIME_new();
- if (ret == NULL){
- WOLFSSL_MSG("memory alloc failed.");
- }
- } else {
- ret = *out;
- }
- }
- }
- if (ret != NULL) {
- if (time_type == ASN_GENERALIZED_TIME){
- XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE);
- } else { /* ASN_UTC_TIME */
- /* convert UTC to generalized time */
- ret->type = ASN_GENERALIZED_TIME;
- ret->length = ASN_GENERALIZED_TIME_SIZE;
- if (t->data[0] >= '5') {
- ret->data[0] = '1'; ret->data[1] = '9';
- } else {
- ret->data[0] = '2'; ret->data[1] = '0';
- }
- XMEMCPY(&ret->data[2], t->data, ASN_UTC_TIME_SIZE);
- }
- }
- return ret;
- }
- #endif /* !NO_ASN_TIME */
- #ifndef NO_ASN
- int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp)
- {
- unsigned char *pptr = NULL;
- char pad = 0 ;
- unsigned char pad_val = 0;
- int ret_size = 0;
- unsigned char data1 = 0;
- unsigned char neg = 0;
- int i = 0;
- WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER");
- if (a == NULL)
- return WOLFSSL_FAILURE;
- ret_size = a->intData[1];
- if (ret_size == 0)
- ret_size = 1;
- else{
- ret_size = (int)a->intData[1];
- neg = a->negative;
- data1 = a->intData[2];
- if (ret_size == 1 && data1 == 0)
- neg = 0;
- /* 0x80 or greater positive number in first byte */
- if (!neg && (data1 > 127)){
- pad = 1;
- pad_val = 0;
- } else if (neg){
- /* negative number */
- if (data1 > 128){
- pad = 1;
- pad_val = 0xff;
- } else if (data1 == 128){
- for (i = 3; i < a->intData[1] + 2; i++){
- if (a->intData[i]){
- pad = 1;
- pad_val = 0xff;
- break;
- }
- }
- }
- }
- ret_size += (int)pad;
- }
- if (pp == NULL)
- return ret_size;
- pptr = *pp;
- if (pad)
- *(pptr++) = pad_val;
- if (a->intData[1] == 0)
- *(pptr++) = 0;
- else if (!neg){
- /* positive number */
- for (i=0; i < a->intData[1]; i++){
- *pptr = a->intData[i+2];
- pptr++;
- }
- } else {
- /* negative number */
- int str_len = 0;
- /* 0 padding from end of buffer */
- str_len = (int)a->intData[1];
- pptr += a->intData[1] - 1;
- while (!a->intData[str_len + 2] && str_len > 1){
- *(pptr--) = 0;
- str_len--;
- }
- /* 2's complement next octet */
- *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1;
- str_len--;
- /* Complement any octets left */
- while (str_len > 0){
- *(pptr--) = a->intData[str_len + 1] ^ 0xff;
- str_len--;
- }
- }
- *pp += ret_size;
- return ret_size;
- }
- #endif /* !NO_ASN */
- #endif /* OPENSSL_EXTRA */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- /* when calling SetIndividualExternal, mpi should be cleared by caller if no
- * longer used. ie mp_free(mpi). This is to free data when fastmath is
- * disabled since a copy of mpi is made by this function and placed into bn.
- */
- int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi)
- {
- byte dynamic = 0;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("Entering SetIndividualExternal");
- #endif
- if (mpi == NULL || bn == NULL) {
- WOLFSSL_MSG("mpi NULL error");
- return WOLFSSL_FATAL_ERROR;
- }
- if (*bn == NULL) {
- *bn = wolfSSL_BN_new();
- if (*bn == NULL) {
- WOLFSSL_MSG("SetIndividualExternal alloc failed");
- return WOLFSSL_FATAL_ERROR;
- }
- dynamic = 1;
- }
- if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- if (dynamic == 1) {
- wolfSSL_BN_free(*bn);
- }
- return WOLFSSL_FATAL_ERROR;
- }
- return WOLFSSL_SUCCESS;
- }
- static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn)
- {
- if (bn)
- XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM));
- }
- WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
- {
- WOLFSSL_BIGNUM* external;
- mp_int* mpi;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("wolfSSL_BN_new");
- #endif
- #if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
- mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (mpi == NULL) {
- WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure");
- return NULL;
- }
- #endif
- external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
- DYNAMIC_TYPE_BIGINT);
- if (external == NULL) {
- WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
- #if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
- XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- return NULL;
- }
- #if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
- mpi = &external->fp;
- #endif
- InitwolfSSL_BigNum(external);
- if (mp_init(mpi) != MP_OKAY) {
- wolfSSL_BN_free(external);
- return NULL;
- }
- external->internal = mpi;
- return external;
- }
- #if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
- /* This function works without BN_free only with TFM */
- void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn)
- {
- if(bn == NULL)return;
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("wolfSSL_BN_init");
- #endif
- InitwolfSSL_BigNum(bn);
- if (mp_init(&bn->fp) != MP_OKAY)
- return;
- bn->internal = (void *)&bn->fp;
- }
- #endif
- void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("wolfSSL_BN_free");
- #endif
- if (bn) {
- if (bn->internal) {
- mp_int* bni = (mp_int*)bn->internal;
- mp_free(bni);
- #if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
- XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT);
- #endif
- bn->internal = NULL;
- }
- XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
- /* bn = NULL, don't try to access or double free it */
- }
- }
- void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("wolfSSL_BN_clear_free");
- #endif
- if (bn) {
- if (bn->internal) {
- mp_int* bni = (mp_int*)bn->internal;
- mp_forcezero(bni);
- }
- wolfSSL_BN_free(bn);
- }
- }
- void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn)
- {
- #ifdef WOLFSSL_DEBUG_OPENSSL
- WOLFSSL_MSG("wolfSSL_BN_clear");
- #endif
- if (bn && bn->internal) {
- mp_forcezero((mp_int*)bn->internal);
- }
- }
- #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- #ifdef OPENSSL_ALL
- #if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8)
- int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY* pkey,
- const WOLFSSL_EVP_CIPHER* enc,
- char* passwd, int passwdSz,
- wc_pem_password_cb* cb, void* ctx)
- {
- int ret = 0;
- char password[NAME_SZ];
- byte* key = NULL;
- word32 keySz;
- byte* pem = NULL;
- int pemSz;
- int type = PKCS8_PRIVATEKEY_TYPE;
- int algId;
- const byte* curveOid;
- word32 oidSz;
- int encAlgId = 0;
- if (bio == NULL || pkey == NULL)
- return -1;
- keySz = pkey->pkey_sz + 128;
- key = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (key == NULL)
- ret = MEMORY_E;
- if (ret == 0 && enc != NULL && passwd == NULL) {
- passwdSz = cb(password, sizeof(password), 1, ctx);
- if (passwdSz < 0)
- ret = WOLFSSL_FAILURE;
- passwd = password;
- }
- if (ret == 0 && enc != NULL) {
- WC_RNG rng;
- ret = wc_InitRng(&rng);
- if (ret == 0) {
- #ifndef NO_DES3
- if (enc == EVP_DES_CBC)
- encAlgId = DESb;
- else if (enc == EVP_DES_EDE3_CBC)
- encAlgId = DES3b;
- else
- #endif
- #if !defined(NO_AES) && defined(HAVE_AES_CBC)
- #ifdef WOLFSSL_AES_256
- if (enc == EVP_AES_256_CBC)
- encAlgId = AES256CBCb;
- else
- #endif
- #endif
- ret = -1;
- if (ret == 0) {
- ret = TraditionalEnc((byte*)pkey->pkey.ptr, pkey->pkey_sz, key,
- &keySz, passwd, passwdSz, PKCS5, PBES2,
- encAlgId, NULL, 0, WC_PKCS12_ITT_DEFAULT,
- &rng, NULL);
- if (ret > 0) {
- keySz = ret;
- ret = 0;
- }
- }
- wc_FreeRng(&rng);
- }
- type = PKCS8_ENC_PRIVATEKEY_TYPE;
- }
- if (ret == 0 && enc == NULL) {
- type = PKCS8_PRIVATEKEY_TYPE;
- #ifdef HAVE_ECC
- if (pkey->type == EVP_PKEY_EC) {
- algId = ECDSAk;
- ret = wc_ecc_get_oid(pkey->ecc->group->curve_oid, &curveOid,
- &oidSz);
- }
- else
- #endif
- {
- algId = RSAk;
- curveOid = NULL;
- oidSz = 0;
- }
- #ifdef HAVE_ECC
- if (ret >= 0)
- #endif
- {
- ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr,
- pkey->pkey_sz, algId, curveOid, oidSz);
- keySz = ret;
- }
- }
- if (password == passwd)
- XMEMSET(password, 0, passwdSz);
- if (ret >= 0) {
- pemSz = 2 * keySz + 2 * 64;
- pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (pem == NULL)
- ret = MEMORY_E;
- }
- if (ret >= 0)
- ret = wc_DerToPemEx(key, keySz, pem, pemSz, NULL, type);
- if (key != NULL)
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret >= 0) {
- if (wolfSSL_BIO_write(bio, pem, ret) != ret)
- ret = -1;
- }
- if (pem != NULL)
- XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret < 0 ? 0 : ret;
- }
- #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
- int wolfSSL_PEM_write_PKCS8PrivateKey(XFILE f, WOLFSSL_EVP_PKEY* pkey,
- const WOLFSSL_EVP_CIPHER* enc, char* passwd, int passwdSz,
- wc_pem_password_cb* cb, void* ctx)
- {
- int ret = WOLFSSL_SUCCESS;
- BIO *b;
- WOLFSSL_ENTER("wolfSSL_PEM_write_PKCS8PrivateKey");
- b = wolfSSL_BIO_new_fp(f, BIO_NOCLOSE);
- if (b == NULL) {
- ret = WOLFSSL_FAILURE;
- }
- if (ret == WOLFSSL_SUCCESS) {
- ret = wolfSSL_PEM_write_bio_PKCS8PrivateKey(b, pkey, enc, passwd,
- passwdSz, cb, ctx);
- }
- wolfSSL_BIO_free(b);
- return ret;
- }
- #endif /* !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
- static int bio_get_data(WOLFSSL_BIO* bio, byte** data)
- {
- int ret = 0;
- byte* mem = NULL;
- #ifndef NO_FILESYSTEM
- long memSz;
- XFILE file;
- long curr;
- #endif
- if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
- }
- #ifndef NO_FILESYSTEM
- else if (bio->type == WOLFSSL_BIO_FILE) {
- if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS)
- ret = BAD_FUNC_ARG;
- if (ret == 0) {
- curr = XFTELL(file);
- if (curr < 0) {
- ret = WOLFSSL_BAD_FILE;
- }
- if (XFSEEK(file, 0, XSEEK_END) != 0)
- ret = WOLFSSL_BAD_FILE;
- }
- if (ret == 0) {
- memSz = XFTELL(file);
- if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz < 0) {
- ret = WOLFSSL_BAD_FILE;
- }
- }
- if (ret == 0) {
- memSz -= curr;
- ret = (int)memSz;
- if (XFSEEK(file, curr, SEEK_SET) != 0)
- ret = WOLFSSL_BAD_FILE;
- }
- }
- #endif
- if (ret > 0) {
- mem = (byte*)XMALLOC(ret, bio->heap, DYNAMIC_TYPE_OPENSSL);
- if (mem == NULL) {
- WOLFSSL_MSG("Memory error");
- ret = MEMORY_E;
- }
- if (ret >= 0) {
- if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) {
- XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
- ret = MEMORY_E;
- mem = NULL;
- }
- }
- }
- *data = mem;
- return ret;
- }
- /* DER data is PKCS#8 encrypted. */
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** pkey,
- wc_pem_password_cb* cb,
- void* ctx)
- {
- int ret;
- byte* der;
- int len;
- byte* p;
- word32 algId;
- WOLFSSL_EVP_PKEY* key;
- if ((len = bio_get_data(bio, &der)) < 0)
- return NULL;
- if (cb != NULL) {
- char password[NAME_SZ];
- int passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx);
- if (passwordSz < 0) {
- XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return NULL;
- }
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("wolfSSL_d2i_PKCS8PrivateKey_bio password", password,
- passwordSz);
- #endif
- ret = ToTraditionalEnc(der, len, password, passwordSz, &algId);
- if (ret < 0) {
- XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return NULL;
- }
- ForceZero(password, passwordSz);
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Check(password, passwordSz);
- #endif
- }
- p = der;
- key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len);
- XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return key;
- }
- #endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */
- /* Detect which type of key it is before decoding. */
- WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey,
- const unsigned char** pp,
- long length)
- {
- int ret;
- WOLFSSL_EVP_PKEY* key = NULL;
- const byte* der = *pp;
- word32 idx = 0;
- int len = 0;
- word32 end = 0;
- int cnt = 0;
- int type;
- word32 algId;
- word32 keyLen = (word32)length;
- /* Take off PKCS#8 wrapper if found. */
- if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) {
- der += idx;
- keyLen = len;
- }
- idx = 0;
- len = 0;
- /* Use the number of elements in the outer sequence to determine key type.
- */
- ret = GetSequence(der, &idx, &len, keyLen);
- if (ret >= 0) {
- end = idx + len;
- while (ret >= 0 && idx < end) {
- /* Skip type */
- idx++;
- /* Get length and skip over - keeping count */
- len = 0;
- ret = GetLength(der, &idx, &len, keyLen);
- if (ret >= 0) {
- if (idx + len > end)
- ret = ASN_PARSE_E;
- else {
- idx += len;
- cnt++;
- }
- }
- }
- }
- if (ret >= 0) {
- /* ECC includes version, private[, curve][, public key] */
- if (cnt >= 2 && cnt <= 4)
- type = EVP_PKEY_EC;
- else
- type = EVP_PKEY_RSA;
- key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen);
- *pp = der;
- }
- return key;
- }
- #endif /* OPENSSL_ALL */
- #ifdef WOLFSSL_STATIC_EPHEMERAL
- int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr)
- {
- int ret;
- word32 idx = 0;
- DerBuffer* der = NULL;
- if (ssl == NULL || ssl->ctx == NULL || keyPtr == NULL) {
- return BAD_FUNC_ARG;
- }
- #ifndef SINGLE_THREADED
- if (!ssl->ctx->staticKELockInit) {
- return BUFFER_E; /* no keys set */
- }
- ret = wc_LockMutex(&ssl->ctx->staticKELock);
- if (ret != 0) {
- return ret;
- }
- #endif
- ret = BUFFER_E; /* set default error */
- switch (keyAlgo) {
- #ifndef NO_DH
- case WC_PK_TYPE_DH:
- if (ssl != NULL)
- der = ssl->staticKE.dhKey;
- if (der == NULL)
- der = ssl->ctx->staticKE.dhKey;
- if (der != NULL) {
- DhKey* key = (DhKey*)keyPtr;
- WOLFSSL_MSG("Using static DH key");
- ret = wc_DhKeyDecode(der->buffer, &idx, key, der->length);
- }
- break;
- #endif
- #ifdef HAVE_ECC
- case WC_PK_TYPE_ECDH:
- if (ssl != NULL)
- der = ssl->staticKE.ecKey;
- if (der == NULL)
- der = ssl->ctx->staticKE.ecKey;
- if (der != NULL) {
- ecc_key* key = (ecc_key*)keyPtr;
- WOLFSSL_MSG("Using static ECDH key");
- ret = wc_EccPrivateKeyDecode(der->buffer, &idx, key, der->length);
- }
- break;
- #endif
- #ifdef HAVE_CURVE25519
- case WC_PK_TYPE_CURVE25519:
- if (ssl != NULL)
- der = ssl->staticKE.x25519Key;
- if (der == NULL)
- der = ssl->ctx->staticKE.x25519Key;
- if (der != NULL) {
- curve25519_key* key = (curve25519_key*)keyPtr;
- WOLFSSL_MSG("Using static X25519 key");
- ret = wc_Curve25519PrivateKeyDecode(der->buffer, &idx, key,
- der->length);
- }
- break;
- #endif
- #ifdef HAVE_CURVE448
- case WC_PK_TYPE_CURVE448:
- if (ssl != NULL)
- der = ssl->staticKE.x448Key;
- if (der == NULL)
- der = ssl->ctx->staticKE.x448Key;
- if (der != NULL) {
- curve448_key* key = (curve448_key*)keyPtr;
- WOLFSSL_MSG("Using static X448 key");
- ret = wc_Curve448PrivateKeyDecode(der->buffer, &idx, key,
- der->length);
- }
- break;
- #endif
- default:
- /* not supported */
- ret = NOT_COMPILED_IN;
- break;
- }
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&ssl->ctx->staticKELock);
- #endif
- return ret;
- }
- static int SetStaticEphemeralKey(WOLFSSL_CTX* ctx,
- StaticKeyExchangeInfo_t* staticKE, int keyAlgo, const char* key,
- unsigned int keySz, int format, void* heap)
- {
- int ret = 0;
- DerBuffer* der = NULL;
- byte* keyBuf = NULL;
- #ifndef NO_FILESYSTEM
- const char* keyFile = NULL;
- #endif
- /* allow empty key to free buffer */
- if (staticKE == NULL || (key == NULL && keySz > 0)) {
- return BAD_FUNC_ARG;
- }
- WOLFSSL_ENTER("SetStaticEphemeralKey");
- /* if just free'ing key then skip loading */
- if (key != NULL) {
- #ifndef NO_FILESYSTEM
- /* load file from filesystem */
- if (key != NULL && keySz == 0) {
- size_t keyBufSz = 0;
- keyFile = (const char*)key;
- ret = wc_FileLoad(keyFile, &keyBuf, &keyBufSz, heap);
- if (ret != 0) {
- return ret;
- }
- keySz = (unsigned int)keyBufSz;
- }
- else
- #endif
- {
- /* use as key buffer directly */
- keyBuf = (byte*)key;
- }
- if (format == WOLFSSL_FILETYPE_PEM) {
- #ifdef WOLFSSL_PEM_TO_DER
- int keyFormat = 0;
- ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &der,
- heap, NULL, &keyFormat);
- /* auto detect key type */
- if (ret == 0 && keyAlgo == WC_PK_TYPE_NONE) {
- if (keyFormat == ECDSAk)
- keyAlgo = WC_PK_TYPE_ECDH;
- else if (keyFormat == X25519k)
- keyAlgo = WC_PK_TYPE_CURVE25519;
- else
- keyAlgo = WC_PK_TYPE_DH;
- }
- #else
- ret = NOT_COMPILED_IN;
- #endif
- }
- else {
- /* Detect PK type (if required) */
- #ifdef HAVE_ECC
- if (keyAlgo == WC_PK_TYPE_NONE) {
- word32 idx = 0;
- ecc_key eccKey;
- ret = wc_ecc_init_ex(&eccKey, heap, INVALID_DEVID);
- if (ret == 0) {
- ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &eccKey, keySz);
- if (ret == 0)
- keyAlgo = WC_PK_TYPE_ECDH;
- wc_ecc_free(&eccKey);
- }
- }
- #endif
- #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
- if (keyAlgo == WC_PK_TYPE_NONE) {
- word32 idx = 0;
- DhKey dhKey;
- ret = wc_InitDhKey_ex(&dhKey, heap, INVALID_DEVID);
- if (ret == 0) {
- ret = wc_DhKeyDecode(keyBuf, &idx, &dhKey, keySz);
- if (ret == 0)
- keyAlgo = WC_PK_TYPE_DH;
- wc_FreeDhKey(&dhKey);
- }
- }
- #endif
- #ifdef HAVE_CURVE25519
- if (keyAlgo == WC_PK_TYPE_NONE) {
- word32 idx = 0;
- curve25519_key x25519Key;
- ret = wc_curve25519_init_ex(&x25519Key, heap, INVALID_DEVID);
- if (ret == 0) {
- ret = wc_Curve25519PrivateKeyDecode(keyBuf, &idx, &x25519Key,
- keySz);
- if (ret == 0)
- keyAlgo = WC_PK_TYPE_CURVE25519;
- wc_curve25519_free(&x25519Key);
- }
- }
- #endif
- #ifdef HAVE_CURVE448
- if (keyAlgo == WC_PK_TYPE_NONE) {
- word32 idx = 0;
- curve448_key x448Key;
- ret = wc_curve448_init(&x448Key);
- if (ret == 0) {
- ret = wc_Curve448PrivateKeyDecode(keyBuf, &idx, &x448Key,
- keySz);
- if (ret == 0)
- keyAlgo = WC_PK_TYPE_CURVE448;
- wc_curve448_free(&x448Key);
- }
- }
- #endif
- if (keyAlgo != WC_PK_TYPE_NONE) {
- ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap);
- if (ret == 0) {
- XMEMCPY(der->buffer, keyBuf, keySz);
- }
- }
- }
- }
- #ifndef NO_FILESYSTEM
- /* done with keyFile buffer */
- if (keyFile && keyBuf) {
- XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- #ifndef SINGLE_THREADED
- if (ret == 0 && !ctx->staticKELockInit) {
- ret = wc_InitMutex(&ctx->staticKELock);
- if (ret == 0) {
- ctx->staticKELockInit = 1;
- }
- }
- #endif
- if (ret == 0
- #ifndef SINGLE_THREADED
- && (ret = wc_LockMutex(&ctx->staticKELock)) == 0
- #endif
- ) {
- switch (keyAlgo) {
- #ifndef NO_DH
- case WC_PK_TYPE_DH:
- FreeDer(&staticKE->dhKey);
- staticKE->dhKey = der; der = NULL;
- break;
- #endif
- #ifdef HAVE_ECC
- case WC_PK_TYPE_ECDH:
- FreeDer(&staticKE->ecKey);
- staticKE->ecKey = der; der = NULL;
- break;
- #endif
- #ifdef HAVE_CURVE25519
- case WC_PK_TYPE_CURVE25519:
- FreeDer(&staticKE->x25519Key);
- staticKE->x25519Key = der; der = NULL;
- break;
- #endif
- #ifdef HAVE_CURVE448
- case WC_PK_TYPE_CURVE448:
- FreeDer(&staticKE->x448Key);
- staticKE->x448Key = der; der = NULL;
- break;
- #endif
- default:
- /* not supported */
- ret = NOT_COMPILED_IN;
- break;
- }
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&ctx->staticKELock);
- #endif
- }
- if (ret != 0) {
- FreeDer(&der);
- }
- (void)ctx; /* not used for single threaded */
- WOLFSSL_LEAVE("SetStaticEphemeralKey", ret);
- return ret;
- }
- int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo,
- const char* key, unsigned int keySz, int format)
- {
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- return SetStaticEphemeralKey(ctx, &ctx->staticKE, keyAlgo,
- key, keySz, format, ctx->heap);
- }
- int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
- const char* key, unsigned int keySz, int format)
- {
- if (ssl == NULL || ssl->ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- return SetStaticEphemeralKey(ssl->ctx, &ssl->staticKE, keyAlgo,
- key, keySz, format, ssl->heap);
- }
- static int GetStaticEphemeralKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- int keyAlgo, const unsigned char** key, unsigned int* keySz)
- {
- int ret = 0;
- DerBuffer* der = NULL;
- if (key) *key = NULL;
- if (keySz) *keySz = 0;
- #ifndef SINGLE_THREADED
- if (ctx->staticKELockInit &&
- (ret = wc_LockMutex(&ctx->staticKELock)) != 0) {
- return ret;
- }
- #endif
- switch (keyAlgo) {
- #ifndef NO_DH
- case WC_PK_TYPE_DH:
- if (ssl != NULL)
- der = ssl->staticKE.dhKey;
- if (der == NULL)
- der = ctx->staticKE.dhKey;
- break;
- #endif
- #ifdef HAVE_ECC
- case WC_PK_TYPE_ECDH:
- if (ssl != NULL)
- der = ssl->staticKE.ecKey;
- if (der == NULL)
- der = ctx->staticKE.ecKey;
- break;
- #endif
- #ifdef HAVE_CURVE25519
- case WC_PK_TYPE_CURVE25519:
- if (ssl != NULL)
- der = ssl->staticKE.x25519Key;
- if (der == NULL)
- der = ctx->staticKE.x25519Key;
- break;
- #endif
- #ifdef HAVE_CURVE448
- case WC_PK_TYPE_CURVE448:
- if (ssl != NULL)
- der = ssl->staticKE.x448Key;
- if (der == NULL)
- der = ctx->staticKE.x448Key;
- break;
- #endif
- default:
- /* not supported */
- ret = NOT_COMPILED_IN;
- break;
- }
- if (der) {
- if (key)
- *key = der->buffer;
- if (keySz)
- *keySz = der->length;
- }
- #ifndef SINGLE_THREADED
- wc_UnLockMutex(&ctx->staticKELock);
- #endif
- return ret;
- }
- /* returns pointer to currently loaded static ephemeral as ASN.1 */
- /* this can be converted to PEM using wc_DerToPem */
- int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo,
- const unsigned char** key, unsigned int* keySz)
- {
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- return GetStaticEphemeralKey(ctx, NULL, keyAlgo, key, keySz);
- }
- int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
- const unsigned char** key, unsigned int* keySz)
- {
- if (ssl == NULL || ssl->ctx == NULL) {
- return BAD_FUNC_ARG;
- }
- return GetStaticEphemeralKey(ssl->ctx, ssl, keyAlgo, key, keySz);
- }
- #endif /* WOLFSSL_STATIC_EPHEMERAL */
- #if defined(OPENSSL_EXTRA)
- /* wolfSSL_THREADID_current is provided as a compat API with
- * CRYPTO_THREADID_current to register current thread id into given id object.
- * However, CRYPTO_THREADID_current API has been deprecated and no longer
- * exists in the OpenSSL 1.0.0 or later.This API only works as a stub
- * like as existing wolfSSL_THREADID_set_numeric.
- */
- void wolfSSL_THREADID_current(WOLFSSL_CRYPTO_THREADID* id)
- {
- (void)id;
- return;
- }
- /* wolfSSL_THREADID_hash is provided as a compatible API with
- * CRYPTO_THREADID_hash which returns a hash value calcurated from the
- * specified thread id. However, CRYPTO_THREADID_hash API has been
- * deprecated and no longer exists in the OpenSSL 1.0.0 or later.
- * This API only works as a stub to returns 0. This behavior is
- * equivalent to the latest OpenSSL CRYPTO_THREADID_hash.
- */
- unsigned long wolfSSL_THREADID_hash(const WOLFSSL_CRYPTO_THREADID* id)
- {
- (void)id;
- return 0UL;
- }
- /* wolfSSL_CTX_set_ecdh_auto is provided as compatible API with
- * SSL_CTX_set_ecdh_auto to enable auto ecdh curve selection functionality.
- * Since this functionality is enabled by default in wolfSSL,
- * this API exists as a stub.
- */
- int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff)
- {
- (void)ctx;
- (void)onoff;
- return WOLFSSL_SUCCESS;
- }
- /**
- * set security level (wolfSSL doesn't support security level)
- * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure
- * @param level security level
- */
- void wolfSSL_CTX_set_security_level(WOLFSSL_CTX* ctx, int level)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_security_level");
- (void)ctx;
- (void)level;
- }
- /**
- * get security level (wolfSSL doesn't support security level)
- * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure
- * @return always 0(level 0)
- */
- int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_security_level");
- (void)ctx;
- return 0;
- }
- /**
- * Determine whether a WOLFSSL_SESSION object can be used for resumption
- * @param s a pointer to WOLFSSL_SESSION structure
- * @return return 1 if session is resumable, otherwise 0.
- */
- int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s)
- {
- s = ClientSessionToSession(s);
- if (s == NULL)
- return 0;
- #ifdef HAVE_SESSION_TICKET
- if (s->ticketLen > 0)
- return 1;
- #endif
- if (s->sessionIDSz > 0)
- return 1;
- return 0;
- }
- #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK)
- /*
- * This API accepts a user callback which puts key-log records into
- * a KEY LOGFILE. The callback is stored into a CTX and propagated to
- * each SSL object on its creation timing.
- */
- void wolfSSL_CTX_set_keylog_callback(WOLFSSL_CTX* ctx, wolfSSL_CTX_keylog_cb_func cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_keylog_callback");
- /* stores the callback into WOLFSSL_CTX */
- if (ctx != NULL) {
- ctx->keyLogCb = cb;
- }
- }
- wolfSSL_CTX_keylog_cb_func wolfSSL_CTX_get_keylog_callback(
- const WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_keylog_callback");
- if (ctx != NULL)
- return ctx->keyLogCb;
- else
- return NULL;
- }
- #endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */
- #endif /* OPENSSL_EXTRA */
- #ifndef NO_CERT
- #define WOLFSSL_X509_INCLUDED
- #include "src/x509.c"
- #endif
- /*******************************************************************************
- * START OF standard C library wrapping APIs
- ******************************************************************************/
- #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
- #ifndef NO_WOLFSSL_STUB
- int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
- void *(*r) (void *, size_t, const char *,
- int), void (*f) (void *))
- {
- (void) m;
- (void) r;
- (void) f;
- WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions");
- WOLFSSL_STUB("CRYPTO_set_mem_ex_functions");
- return WOLFSSL_FAILURE;
- }
- #endif
- #endif
- #if defined(OPENSSL_EXTRA)
- /**
- * free allocated memory resouce
- * @param str a pointer to resource to be freed
- * @param file dummy argument
- * @param line dummy argument
- */
- void wolfSSL_CRYPTO_free(void *str, const char *file, int line)
- {
- (void)file;
- (void)line;
- XFREE(str, 0, DYNAMIC_TYPE_TMP_BUFFER);
- }
- /**
- * allocate memory with size of num
- * @param num size of memory allocation to be malloced
- * @param file dummy argument
- * @param line dummy argument
- * @return a pointer to allocated memory on succssesful, otherwise NULL
- */
- void *wolfSSL_CRYPTO_malloc(size_t num, const char *file, int line)
- {
- (void)file;
- (void)line;
- return XMALLOC(num, 0, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- /*******************************************************************************
- * END OF standard C library wrapping APIs
- ******************************************************************************/
- /*******************************************************************************
- * START OF EX_DATA APIs
- ******************************************************************************/
- #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
- void wolfSSL_CRYPTO_cleanup_all_ex_data(void){
- WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data");
- }
- #endif
- #ifdef HAVE_EX_DATA
- void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
- #ifdef MAX_EX_DATA
- if(ex_data && idx < MAX_EX_DATA && idx >= 0) {
- return ex_data->ex_data[idx];
- }
- #else
- (void)ex_data;
- (void)idx;
- #endif
- return NULL;
- }
- int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *data)
- {
- WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data");
- #ifdef MAX_EX_DATA
- if (ex_data && idx < MAX_EX_DATA && idx >= 0) {
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- if (ex_data->ex_data_cleanup_routines[idx]) {
- if (ex_data->ex_data[idx])
- ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]);
- ex_data->ex_data_cleanup_routines[idx] = NULL;
- }
- #endif
- ex_data->ex_data[idx] = data;
- return WOLFSSL_SUCCESS;
- }
- #else
- (void)ex_data;
- (void)idx;
- (void)data;
- #endif
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- int wolfSSL_CRYPTO_set_ex_data_with_cleanup(
- WOLFSSL_CRYPTO_EX_DATA* ex_data,
- int idx,
- void *data,
- wolfSSL_ex_data_cleanup_routine_t cleanup_routine)
- {
- WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data_with_cleanup");
- if (ex_data && idx < MAX_EX_DATA && idx >= 0) {
- if (ex_data->ex_data_cleanup_routines[idx] && ex_data->ex_data[idx])
- ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]);
- ex_data->ex_data[idx] = data;
- ex_data->ex_data_cleanup_routines[idx] = cleanup_routine;
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
- /**
- * Issues unique index for the class specified by class_index.
- * Other parameter except class_index are ignored.
- * Currently, following class_index are accepted:
- * - WOLF_CRYPTO_EX_INDEX_SSL
- * - WOLF_CRYPTO_EX_INDEX_SSL_CTX
- * - WOLF_CRYPTO_EX_INDEX_X509
- * @param class_index index one of CRYPTO_EX_INDEX_xxx
- * @param argp parameters to be saved
- * @param argl parameters to be saved
- * @param new_func a pointer to WOLFSSL_CRYPTO_EX_new
- * @param dup_func a pointer to WOLFSSL_CRYPTO_EX_dup
- * @param free_func a pointer to WOLFSSL_CRYPTO_EX_free
- * @return index value grater or equal to zero on success, -1 on failure.
- */
- int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
- WOLFSSL_CRYPTO_EX_new* new_func,
- WOLFSSL_CRYPTO_EX_dup* dup_func,
- WOLFSSL_CRYPTO_EX_free* free_func)
- {
- WOLFSSL_ENTER("wolfSSL_CRYPTO_get_ex_new_index");
- WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(argl, argp, new_func, dup_func,
- free_func);
- return wolfssl_get_ex_new_index(class_index);
- }
- #endif /* HAVE_EX_DATA */
- /*******************************************************************************
- * END OF EX_DATA APIs
- ******************************************************************************/
- /*******************************************************************************
- * START OF BUF_MEM API
- ******************************************************************************/
- #if defined(OPENSSL_EXTRA)
- /* Begin functions for openssl/buffer.h */
- WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void)
- {
- WOLFSSL_BUF_MEM* buf;
- buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (buf) {
- XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM));
- }
- return buf;
- }
- /* non-compat API returns length of buffer on success */
- int wolfSSL_BUF_MEM_grow_ex(WOLFSSL_BUF_MEM* buf, size_t len,
- char zeroFill)
- {
- int len_int = (int)len;
- int mx;
- char* tmp;
- /* verify provided arguments */
- if (buf == NULL || len_int < 0) {
- return 0; /* BAD_FUNC_ARG; */
- }
- /* check to see if fits in existing length */
- if (buf->length > len) {
- buf->length = len;
- return len_int;
- }
- /* check to see if fits in max buffer */
- if (buf->max >= len) {
- if (buf->data != NULL && zeroFill) {
- XMEMSET(&buf->data[buf->length], 0, len - buf->length);
- }
- buf->length = len;
- return len_int;
- }
- /* expand size, to handle growth */
- mx = (len_int + 3) / 3 * 4;
- /* use realloc */
- tmp = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_OPENSSL);
- if (tmp == NULL) {
- return 0; /* ERR_R_MALLOC_FAILURE; */
- }
- buf->data = tmp;
- buf->max = mx;
- if (zeroFill)
- XMEMSET(&buf->data[buf->length], 0, len - buf->length);
- buf->length = len;
- return len_int;
- }
- /* returns length of buffer on success */
- int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len)
- {
- return wolfSSL_BUF_MEM_grow_ex(buf, len, 1);
- }
- /* non-compat API returns length of buffer on success */
- int wolfSSL_BUF_MEM_resize(WOLFSSL_BUF_MEM* buf, size_t len)
- {
- char* tmp;
- int mx;
- /* verify provided arguments */
- if (buf == NULL || len == 0 || (int)len <= 0) {
- return 0; /* BAD_FUNC_ARG; */
- }
- if (len == buf->length)
- return (int)len;
- if (len > buf->length)
- return wolfSSL_BUF_MEM_grow_ex(buf, len, 0);
- /* expand size, to handle growth */
- mx = ((int)len + 3) / 3 * 4;
- /* We want to shrink the internal buffer */
- tmp = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_OPENSSL);
- if (tmp == NULL)
- return 0;
- buf->data = tmp;
- buf->length = len;
- buf->max = mx;
- return (int)len;
- }
- void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf)
- {
- if (buf) {
- if (buf->data) {
- XFREE(buf->data, NULL, DYNAMIC_TYPE_OPENSSL);
- buf->data = NULL;
- }
- buf->max = 0;
- buf->length = 0;
- XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- /* End Functions for openssl/buffer.h */
- #endif /* OPENSSL_EXTRA */
- /*******************************************************************************
- * END OF BUF_MEM API
- ******************************************************************************/
- #define WOLFSSL_CONF_INCLUDED
- #include <src/conf.c>
- /*******************************************************************************
- * START OF RAND API
- ******************************************************************************/
- #if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB)
- static int wolfSSL_RAND_InitMutex(void)
- {
- if (gRandMethodsInit == 0) {
- if (wc_InitMutex(&gRandMethodMutex) != 0) {
- WOLFSSL_MSG("Bad Init Mutex rand methods");
- return BAD_MUTEX_E;
- }
- gRandMethodsInit = 1;
- }
- return 0;
- }
- #endif
- #ifdef OPENSSL_EXTRA
- /* Checks if the global RNG has been created. If not then one is created.
- *
- * Returns WOLFSSL_SUCCESS when no error is encountered.
- */
- int wolfSSL_RAND_Init(void)
- {
- int ret = WOLFSSL_FAILURE;
- #ifdef HAVE_GLOBAL_RNG
- if (wc_LockMutex(&globalRNGMutex) == 0) {
- if (initGlobalRNG == 0) {
- ret = wc_InitRng(&globalRNG);
- if (ret == 0) {
- initGlobalRNG = 1;
- ret = WOLFSSL_SUCCESS;
- }
- }
- wc_UnLockMutex(&globalRNGMutex);
- }
- #endif
- return ret;
- }
- /* WOLFSSL_SUCCESS on ok */
- int wolfSSL_RAND_seed(const void* seed, int len)
- {
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) {
- if (gRandMethods && gRandMethods->seed) {
- int ret = gRandMethods->seed(seed, len);
- wc_UnLockMutex(&gRandMethodMutex);
- return ret;
- }
- wc_UnLockMutex(&gRandMethodMutex);
- }
- #else
- (void)seed;
- (void)len;
- #endif
- /* Make sure global shared RNG (globalRNG) is initialized */
- return wolfSSL_RAND_Init();
- }
- /* Returns the path for reading seed data from.
- * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd
- *
- * Note uses stdlib by default unless XGETENV macro is overwritten
- *
- * fname buffer to hold path
- * len length of fname buffer
- *
- * Returns a pointer to fname on success and NULL on failure
- */
- const char* wolfSSL_RAND_file_name(char* fname, unsigned long len)
- {
- #ifndef NO_FILESYSTEM
- char* rt;
- char ap[] = "/.rnd";
- WOLFSSL_ENTER("wolfSSL_RAND_file_name");
- if (fname == NULL) {
- return NULL;
- }
- XMEMSET(fname, 0, len);
- /* if access to stdlib.h */
- if ((rt = XGETENV("RANDFILE")) != NULL) {
- if (len > XSTRLEN(rt)) {
- XMEMCPY(fname, rt, XSTRLEN(rt));
- }
- else {
- WOLFSSL_MSG("RANDFILE too large for buffer");
- rt = NULL;
- }
- }
- /* $RANDFILE was not set or is too large, check $HOME */
- if (rt == NULL) {
- WOLFSSL_MSG("Environment variable RANDFILE not set");
- if ((rt = XGETENV("HOME")) == NULL) {
- WOLFSSL_MSG("Environment variable HOME not set");
- return NULL;
- }
- if (len > XSTRLEN(rt) + XSTRLEN(ap)) {
- fname[0] = '\0';
- XSTRNCAT(fname, rt, len);
- XSTRNCAT(fname, ap, len - XSTRLEN(rt));
- return fname;
- }
- else {
- WOLFSSL_MSG("HOME too large for buffer");
- return NULL;
- }
- }
- return fname;
- #else
- /* no filesystem defined */
- WOLFSSL_ENTER("wolfSSL_RAND_file_name");
- WOLFSSL_MSG("No filesystem feature enabled, not compiled in");
- (void)fname;
- (void)len;
- return NULL;
- #endif
- }
- /* Writes 1024 bytes from the RNG to the given file name.
- *
- * fname name of file to write to
- *
- * Returns the number of bytes written
- */
- int wolfSSL_RAND_write_file(const char* fname)
- {
- int bytes = 0;
- WOLFSSL_ENTER("RAND_write_file");
- if (fname == NULL) {
- return SSL_FAILURE;
- }
- #ifndef NO_FILESYSTEM
- {
- #ifndef WOLFSSL_SMALL_STACK
- unsigned char buf[1024];
- #else
- unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (buf == NULL) {
- WOLFSSL_MSG("malloc failed");
- return SSL_FAILURE;
- }
- #endif
- bytes = 1024; /* default size of buf */
- if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("No RNG to use");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return 0;
- }
- if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) {
- WOLFSSL_MSG("Error generating random buffer");
- bytes = 0;
- }
- else {
- XFILE f;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("wolfSSL_RAND_write_file buf", buf, bytes);
- #endif
- f = XFOPEN(fname, "wb");
- if (f == XBADFILE) {
- WOLFSSL_MSG("Error opening the file");
- bytes = 0;
- }
- else {
- size_t bytes_written = XFWRITE(buf, 1, bytes, f);
- bytes = (int)bytes_written;
- XFCLOSE(f);
- }
- }
- ForceZero(buf, bytes);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #elif defined(WOLFSSL_CHECK_MEM_ZERO)
- wc_MemZero_Check(buf, sizeof(buf));
- #endif
- }
- #endif
- return bytes;
- }
- #ifndef FREERTOS_TCP
- /* These constant values are protocol values made by egd */
- #if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS) && \
- defined(HAVE_HASHDRBG) && !defined(NETOS) && defined(HAVE_SYS_UN_H)
- #define WOLFSSL_EGD_NBLOCK 0x01
- #include <sys/un.h>
- #endif
- /* This collects entropy from the path nm and seeds the global PRNG with it.
- *
- * nm is the file path to the egd server
- *
- * Returns the number of bytes read.
- */
- int wolfSSL_RAND_egd(const char* nm)
- {
- #ifdef WOLFSSL_EGD_NBLOCK
- struct sockaddr_un rem;
- int fd;
- int ret = WOLFSSL_SUCCESS;
- word32 bytes = 0;
- word32 idx = 0;
- #ifndef WOLFSSL_SMALL_STACK
- unsigned char buf[256];
- #else
- unsigned char* buf;
- buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf == NULL) {
- WOLFSSL_MSG("Not enough memory");
- return WOLFSSL_FATAL_ERROR;
- }
- #endif
- XMEMSET(&rem, 0, sizeof(struct sockaddr_un));
- if (nm == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return WOLFSSL_FATAL_ERROR;
- }
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) {
- WOLFSSL_MSG("Error creating socket");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return WOLFSSL_FATAL_ERROR;
- }
- rem.sun_family = AF_UNIX;
- XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1);
- rem.sun_path[sizeof(rem.sun_path)-1] = '\0';
- /* connect to egd server */
- if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un)) == -1) {
- WOLFSSL_MSG("error connecting to egd server");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- if (ret == WOLFSSL_SUCCESS) {
- wc_MemZero_Add("wolfSSL_RAND_egd buf", buf, 256);
- }
- #endif
- while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) {
- buf[idx] = WOLFSSL_EGD_NBLOCK;
- buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */
- ret = (int)write(fd, buf + idx, 2);
- if (ret != 2) {
- if (errno == EAGAIN) {
- ret = WOLFSSL_SUCCESS;
- continue;
- }
- WOLFSSL_MSG("error requesting entropy from egd server");
- ret = WOLFSSL_FATAL_ERROR;
- break;
- }
- /* attempting to read */
- buf[idx] = 0;
- ret = (int)read(fd, buf + idx, 256 - bytes);
- if (ret == 0) {
- WOLFSSL_MSG("error reading entropy from egd server");
- ret = WOLFSSL_FATAL_ERROR;
- break;
- }
- if (ret > 0 && buf[idx] > 0) {
- bytes += buf[idx]; /* egd stores amount sent in first byte */
- if (bytes + idx > 255 || buf[idx] > ret) {
- WOLFSSL_MSG("Buffer error");
- ret = WOLFSSL_FATAL_ERROR;
- break;
- }
- XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]);
- idx = bytes;
- ret = WOLFSSL_SUCCESS;
- if (bytes >= 255) {
- break;
- }
- }
- else {
- if (errno == EAGAIN || errno == EINTR) {
- WOLFSSL_MSG("EGD would read");
- ret = WOLFSSL_SUCCESS; /* try again */
- }
- else if (buf[idx] == 0) {
- /* if egd returned 0 then there is no more entropy to be had.
- Do not try more reads. */
- ret = WOLFSSL_SUCCESS;
- break;
- }
- else {
- WOLFSSL_MSG("Error with read");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- }
- if (bytes > 0 && ret == WOLFSSL_SUCCESS) {
- /* call to check global RNG is created */
- if (wolfSSL_RAND_Init() != SSL_SUCCESS) {
- WOLFSSL_MSG("Error with initializing global RNG structure");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes)
- != 0) {
- WOLFSSL_MSG("Error with reseeding DRBG structure");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #ifdef SHOW_SECRETS
- else { /* print out entropy found only when no error occured */
- word32 i;
- printf("EGD Entropy = ");
- for (i = 0; i < bytes; i++) {
- printf("%02X", buf[i]);
- }
- printf("\n");
- }
- #endif
- }
- ForceZero(buf, bytes);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #elif defined(WOLFSSL_CHECK_MEM_ZERO)
- wc_MemZero_Check(buf, 256);
- #endif
- close(fd);
- if (ret == WOLFSSL_SUCCESS) {
- return bytes;
- }
- else {
- return ret;
- }
- #else
- WOLFSSL_MSG("Type of socket needed is not available");
- WOLFSSL_MSG("\tor using mode where DRBG API is not available");
- (void)nm;
- return WOLFSSL_FATAL_ERROR;
- #endif /* WOLFSSL_EGD_NBLOCK */
- }
- #endif /* !FREERTOS_TCP */
- void wolfSSL_RAND_Cleanup(void)
- {
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) {
- if (gRandMethods && gRandMethods->cleanup)
- gRandMethods->cleanup();
- wc_UnLockMutex(&gRandMethodMutex);
- }
- if (wc_FreeMutex(&gRandMethodMutex) == 0)
- gRandMethodsInit = 0;
- #endif
- #ifdef HAVE_GLOBAL_RNG
- if (wc_LockMutex(&globalRNGMutex) == 0) {
- if (initGlobalRNG) {
- wc_FreeRng(&globalRNG);
- initGlobalRNG = 0;
- }
- wc_UnLockMutex(&globalRNGMutex);
- }
- #endif
- }
- /* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */
- int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num)
- {
- int ret;
- int hash;
- byte secret[DRBG_SEED_LEN]; /* secret length arbitraily choosen */
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) {
- if (gRandMethods && gRandMethods->pseudorand) {
- ret = gRandMethods->pseudorand(buf, num);
- wc_UnLockMutex(&gRandMethodMutex);
- return ret;
- }
- wc_UnLockMutex(&gRandMethodMutex);
- }
- #endif
- #ifdef WOLFSSL_HAVE_PRF
- #ifndef NO_SHA256
- hash = WC_SHA256;
- #elif defined(WOLFSSL_SHA384)
- hash = WC_SHA384;
- #elif !defined(NO_SHA)
- hash = WC_SHA;
- #elif !defined(NO_MD5)
- hash = WC_MD5;
- #endif
- /* get secret value from source of entropy */
- ret = wolfSSL_RAND_bytes(secret, DRBG_SEED_LEN);
- /* uses input buffer to seed for pseudo random number generation, each
- * thread will potentially have different results this way */
- if (ret == WOLFSSL_SUCCESS) {
- PRIVATE_KEY_UNLOCK();
- ret = wc_PRF(buf, num, secret, DRBG_SEED_LEN, (const byte*)buf, num,
- hash, NULL, INVALID_DEVID);
- PRIVATE_KEY_LOCK();
- ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
- }
- #else
- /* fall back to just doing wolfSSL_RAND_bytes if PRF not avialbale */
- ret = wolfSSL_RAND_bytes(buf, num);
- (void)hash;
- (void)secret;
- #endif
- return ret;
- }
- /* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */
- int wolfSSL_RAND_bytes(unsigned char* buf, int num)
- {
- int ret = 0;
- WC_RNG* rng = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRNG = NULL;
- #else
- WC_RNG tmpRNG[1];
- #endif
- int initTmpRng = 0;
- int blockCount = 0;
- #ifdef HAVE_GLOBAL_RNG
- int used_global = 0;
- #endif
- WOLFSSL_ENTER("wolfSSL_RAND_bytes");
- /* sanity check */
- if (buf == NULL || num < 0)
- /* return code compliant with OpenSSL */
- return 0;
- /* if a RAND callback has been set try and use it */
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) {
- if (gRandMethods && gRandMethods->bytes) {
- ret = gRandMethods->bytes(buf, num);
- wc_UnLockMutex(&gRandMethodMutex);
- return ret;
- }
- wc_UnLockMutex(&gRandMethodMutex);
- }
- #endif
- #ifdef HAVE_GLOBAL_RNG
- if (initGlobalRNG) {
- if (wc_LockMutex(&globalRNGMutex) != 0) {
- WOLFSSL_MSG("Bad Lock Mutex rng");
- return ret;
- }
- rng = &globalRNG;
- used_global = 1;
- }
- else
- #endif
- {
- #ifdef WOLFSSL_SMALL_STACK
- tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRNG == NULL)
- return ret;
- #endif
- if (wc_InitRng(tmpRNG) == 0) {
- rng = tmpRNG;
- initTmpRng = 1;
- }
- }
- if (rng) {
- /* handles size greater than RNG_MAX_BLOCK_LEN */
- blockCount = num / RNG_MAX_BLOCK_LEN;
- while (blockCount--) {
- ret = wc_RNG_GenerateBlock(rng, buf, RNG_MAX_BLOCK_LEN);
- if (ret != 0) {
- WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
- break;
- }
- num -= RNG_MAX_BLOCK_LEN;
- buf += RNG_MAX_BLOCK_LEN;
- }
- if (ret == 0 && num)
- ret = wc_RNG_GenerateBlock(rng, buf, num);
- if (ret != 0)
- WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
- else
- ret = WOLFSSL_SUCCESS;
- }
- #ifdef HAVE_GLOBAL_RNG
- if (used_global == 1)
- wc_UnLockMutex(&globalRNGMutex);
- #endif
- if (initTmpRng)
- wc_FreeRng(tmpRNG);
- #ifdef WOLFSSL_SMALL_STACK
- if (tmpRNG)
- XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
- #endif
- return ret;
- }
- int wolfSSL_RAND_poll(void)
- {
- byte entropy[16];
- int ret = 0;
- word32 entropy_sz = 16;
- WOLFSSL_ENTER("wolfSSL_RAND_poll");
- if (initGlobalRNG == 0){
- WOLFSSL_MSG("Global RNG no Init");
- return WOLFSSL_FAILURE;
- }
- ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz);
- if (ret != 0){
- WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
- ret = WOLFSSL_FAILURE;
- }else
- ret = WOLFSSL_SUCCESS;
- return ret;
- }
- /* If a valid struct is provided with function pointers, will override
- RAND_seed, bytes, cleanup, add, pseudo_bytes and status. If a NULL
- pointer is passed in, it will cancel any previous function overrides.
- Returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure. */
- int wolfSSL_RAND_set_rand_method(const WOLFSSL_RAND_METHOD *methods)
- {
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) {
- gRandMethods = methods;
- wc_UnLockMutex(&gRandMethodMutex);
- return WOLFSSL_SUCCESS;
- }
- #else
- (void)methods;
- #endif
- return WOLFSSL_FAILURE;
- }
- /* Returns WOLFSSL_SUCCESS if the RNG has been seeded with enough data */
- int wolfSSL_RAND_status(void)
- {
- int ret = WOLFSSL_SUCCESS;
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) {
- if (gRandMethods && gRandMethods->status)
- ret = gRandMethods->status();
- wc_UnLockMutex(&gRandMethodMutex);
- }
- else {
- ret = WOLFSSL_FAILURE;
- }
- #else
- /* wolfCrypt provides enough seed internally, so return success */
- #endif
- return ret;
- }
- void wolfSSL_RAND_add(const void* add, int len, double entropy)
- {
- #ifndef WOLFSSL_NO_OPENSSL_RAND_CB
- if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) {
- if (gRandMethods && gRandMethods->add) {
- /* callback has return code, but RAND_add does not */
- (void)gRandMethods->add(add, len, entropy);
- }
- wc_UnLockMutex(&gRandMethodMutex);
- }
- #else
- /* wolfSSL seeds/adds internally, use explicit RNG if you want
- to take control */
- (void)add;
- (void)len;
- (void)entropy;
- #endif
- }
- #endif /* OPENSSL_EXTRA */
- /*******************************************************************************
- * END OF RAND API
- ******************************************************************************/
- /*******************************************************************************
- * START OF EVP_CIPHER API
- ******************************************************************************/
- #ifdef OPENSSL_EXTRA
- /* store for external read of iv, WOLFSSL_SUCCESS on success */
- int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_StoreExternalIV");
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return WOLFSSL_FATAL_ERROR;
- }
- switch (ctx->cipherType) {
- #ifndef NO_AES
- #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT)
- case AES_128_CBC_TYPE :
- case AES_192_CBC_TYPE :
- case AES_256_CBC_TYPE :
- WOLFSSL_MSG("AES CBC");
- XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
- break;
- #endif
- #ifdef HAVE_AESGCM
- case AES_128_GCM_TYPE :
- case AES_192_GCM_TYPE :
- case AES_256_GCM_TYPE :
- WOLFSSL_MSG("AES GCM");
- XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
- break;
- #endif /* HAVE_AESGCM */
- #ifdef HAVE_AES_ECB
- case AES_128_ECB_TYPE :
- case AES_192_ECB_TYPE :
- case AES_256_ECB_TYPE :
- WOLFSSL_MSG("AES ECB");
- break;
- #endif
- #ifdef WOLFSSL_AES_COUNTER
- case AES_128_CTR_TYPE :
- case AES_192_CTR_TYPE :
- case AES_256_CTR_TYPE :
- WOLFSSL_MSG("AES CTR");
- XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
- break;
- #endif /* WOLFSSL_AES_COUNTER */
- #ifdef WOLFSSL_AES_CFB
- #if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
- case AES_128_CFB1_TYPE:
- case AES_192_CFB1_TYPE:
- case AES_256_CFB1_TYPE:
- WOLFSSL_MSG("AES CFB1");
- break;
- case AES_128_CFB8_TYPE:
- case AES_192_CFB8_TYPE:
- case AES_256_CFB8_TYPE:
- WOLFSSL_MSG("AES CFB8");
- break;
- #endif /* !HAVE_SELFTEST && !HAVE_FIPS */
- case AES_128_CFB128_TYPE:
- case AES_192_CFB128_TYPE:
- case AES_256_CFB128_TYPE:
- WOLFSSL_MSG("AES CFB128");
- break;
- #endif /* WOLFSSL_AES_CFB */
- #if defined(WOLFSSL_AES_OFB)
- case AES_128_OFB_TYPE:
- case AES_192_OFB_TYPE:
- case AES_256_OFB_TYPE:
- WOLFSSL_MSG("AES OFB");
- break;
- #endif /* WOLFSSL_AES_OFB */
- #ifdef WOLFSSL_AES_XTS
- case AES_128_XTS_TYPE:
- case AES_256_XTS_TYPE:
- WOLFSSL_MSG("AES XTS");
- break;
- #endif /* WOLFSSL_AES_XTS */
- #endif /* NO_AES */
- #ifndef NO_DES3
- case DES_CBC_TYPE :
- WOLFSSL_MSG("DES CBC");
- XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE);
- break;
- case DES_EDE3_CBC_TYPE :
- WOLFSSL_MSG("DES EDE3 CBC");
- XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
- break;
- #endif
- #ifdef WOLFSSL_DES_ECB
- case DES_ECB_TYPE :
- WOLFSSL_MSG("DES ECB");
- break;
- case DES_EDE3_ECB_TYPE :
- WOLFSSL_MSG("DES3 ECB");
- break;
- #endif
- case ARC4_TYPE :
- WOLFSSL_MSG("ARC4");
- break;
- #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
- case CHACHA20_POLY1305_TYPE:
- break;
- #endif
- case NULL_CIPHER_TYPE :
- WOLFSSL_MSG("NULL");
- break;
- default: {
- WOLFSSL_MSG("bad type");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- return WOLFSSL_SUCCESS;
- }
- /* set internal IV from external, WOLFSSL_SUCCESS on success */
- int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_SetInternalIV");
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return WOLFSSL_FATAL_ERROR;
- }
- switch (ctx->cipherType) {
- #ifndef NO_AES
- #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT)
- case AES_128_CBC_TYPE :
- case AES_192_CBC_TYPE :
- case AES_256_CBC_TYPE :
- WOLFSSL_MSG("AES CBC");
- XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
- break;
- #endif
- #ifdef HAVE_AESGCM
- case AES_128_GCM_TYPE :
- case AES_192_GCM_TYPE :
- case AES_256_GCM_TYPE :
- WOLFSSL_MSG("AES GCM");
- XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
- break;
- #endif
- #ifdef HAVE_AES_ECB
- case AES_128_ECB_TYPE :
- case AES_192_ECB_TYPE :
- case AES_256_ECB_TYPE :
- WOLFSSL_MSG("AES ECB");
- break;
- #endif
- #ifdef WOLFSSL_AES_COUNTER
- case AES_128_CTR_TYPE :
- case AES_192_CTR_TYPE :
- case AES_256_CTR_TYPE :
- WOLFSSL_MSG("AES CTR");
- XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
- break;
- #endif
- #endif /* NO_AES */
- #ifndef NO_DES3
- case DES_CBC_TYPE :
- WOLFSSL_MSG("DES CBC");
- XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE);
- break;
- case DES_EDE3_CBC_TYPE :
- WOLFSSL_MSG("DES EDE3 CBC");
- XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE);
- break;
- #endif
- #ifdef WOLFSSL_DES_ECB
- case DES_ECB_TYPE :
- WOLFSSL_MSG("DES ECB");
- break;
- case DES_EDE3_ECB_TYPE :
- WOLFSSL_MSG("DES3 ECB");
- break;
- #endif
- case ARC4_TYPE :
- WOLFSSL_MSG("ARC4");
- break;
- #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
- case CHACHA20_POLY1305_TYPE:
- break;
- #endif
- case NULL_CIPHER_TYPE :
- WOLFSSL_MSG("NULL");
- break;
- default: {
- WOLFSSL_MSG("bad type");
- return WOLFSSL_FATAL_ERROR;
- }
- }
- return WOLFSSL_SUCCESS;
- }
- #ifndef NO_DES3
- void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
- unsigned char* iv, int len)
- {
- (void)len;
- WOLFSSL_MSG("wolfSSL_3des_iv");
- if (ctx == NULL || iv == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return;
- }
- if (doset)
- wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */
- else
- XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
- }
- #endif /* NO_DES3 */
- #ifndef NO_AES
- void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
- unsigned char* iv, int len)
- {
- (void)len;
- WOLFSSL_MSG("wolfSSL_aes_ctr_iv");
- if (ctx == NULL || iv == NULL) {
- WOLFSSL_MSG("Bad function argument");
- return;
- }
- if (doset)
- (void)wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */
- else
- XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
- }
- #endif /* NO_AES */
- #endif /* OPENSSL_EXTRA */
- /*******************************************************************************
- * END OF EVP_CIPHER API
- ******************************************************************************/
- #ifndef NO_CERTS
- #define WOLFSSL_X509_STORE_INCLUDED
- #include <src/x509_str.c>
- /*******************************************************************************
- * START OF PKCS7 APIs
- ******************************************************************************/
- #ifdef HAVE_PKCS7
- #ifdef OPENSSL_ALL
- PKCS7* wolfSSL_PKCS7_new(void)
- {
- WOLFSSL_PKCS7* pkcs7;
- int ret = 0;
- pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(WOLFSSL_PKCS7), NULL,
- DYNAMIC_TYPE_PKCS7);
- if (pkcs7 != NULL) {
- XMEMSET(pkcs7, 0, sizeof(WOLFSSL_PKCS7));
- ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID);
- }
- if (ret != 0 && pkcs7 != NULL) {
- XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7);
- pkcs7 = NULL;
- }
- return (PKCS7*)pkcs7;
- }
- /******************************************************************************
- * wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data
- *
- * RETURNS:
- * returns pointer to the PKCS7 structure on success, otherwise returns NULL
- */
- PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void)
- {
- byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02};
- PKCS7* pkcs7 = NULL;
- if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL)
- return NULL;
- pkcs7->contentOID = SIGNED_DATA;
- if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) {
- if (pkcs7) {
- wolfSSL_PKCS7_free(pkcs7);
- return NULL;
- }
- }
- return pkcs7;
- }
- void wolfSSL_PKCS7_free(PKCS7* pkcs7)
- {
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- if (p7 != NULL) {
- if (p7->data != NULL)
- XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
- wc_PKCS7_Free(&p7->pkcs7);
- if (p7->certs)
- wolfSSL_sk_pop_free(p7->certs, NULL);
- XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7);
- }
- }
- void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7)
- {
- wolfSSL_PKCS7_free(p7);
- return;
- }
- /**
- * Convert DER/ASN.1 encoded signedData structure to internal PKCS7
- * structure. Note, does not support detached content.
- *
- * p7 - pointer to set to address of newly created PKCS7 structure on return
- * in - pointer to pointer of DER/ASN.1 data
- * len - length of input data, bytes
- *
- * Returns newly allocated and populated PKCS7 structure or NULL on error.
- */
- PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len)
- {
- return wolfSSL_d2i_PKCS7_ex(p7, in, len, NULL, 0);
- }
- /*****************************************************************************
- * wolfSSL_d2i_PKCS7_ex - Converts the given unsigned char buffer of size len
- * into a PKCS7 object. Optionally, accepts a byte buffer of content which
- * is stored as the PKCS7 object's content, to support detached signatures.
- * @param content The content which is signed, in case the signature is
- * detached. Ignored if NULL.
- * @param contentSz The size of the passed in content.
- *
- * RETURNS:
- * returns pointer to a PKCS7 structure on success, otherwise returns NULL
- */
- PKCS7* wolfSSL_d2i_PKCS7_ex(PKCS7** p7, const unsigned char** in, int len,
- byte* content, word32 contentSz)
- {
- WOLFSSL_PKCS7* pkcs7 = NULL;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex");
- if (in == NULL || *in == NULL || len < 0)
- return NULL;
- if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
- return NULL;
- pkcs7->len = len;
- pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
- if (pkcs7->data == NULL) {
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- XMEMCPY(pkcs7->data, *in, pkcs7->len);
- if (content != NULL) {
- pkcs7->pkcs7.content = content;
- pkcs7->pkcs7.contentSz = contentSz;
- }
- if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len)
- != 0) {
- WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed");
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- if (p7 != NULL)
- *p7 = (PKCS7*)pkcs7;
- *in += pkcs7->len;
- return (PKCS7*)pkcs7;
- }
- /**
- * This API was added as a helper function for libest. It
- * extracts a stack of certificates from the pkcs7 object.
- * @param pkcs7 PKCS7 parameter object
- * @return WOLFSSL_STACK_OF(WOLFSSL_X509)*
- */
- WOLFSSL_STACK* wolfSSL_PKCS7_to_stack(PKCS7* pkcs7)
- {
- int i;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_PKCS7_to_stack");
- if (!p7) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
- if (p7->certs)
- return p7->certs;
- for (i = 0; i < MAX_PKCS7_CERTS && p7->pkcs7.cert[i]; i++) {
- WOLFSSL_X509* x509 = wolfSSL_X509_d2i(NULL, p7->pkcs7.cert[i],
- p7->pkcs7.certSz[i]);
- if (!ret)
- ret = wolfSSL_sk_X509_new();
- if (x509) {
- if (wolfSSL_sk_X509_push(ret, x509) != WOLFSSL_SUCCESS) {
- wolfSSL_X509_free(x509);
- WOLFSSL_MSG("wolfSSL_sk_X509_push error");
- goto error;
- }
- }
- else {
- WOLFSSL_MSG("wolfSSL_X509_d2i error");
- goto error;
- }
- }
- /* Save stack to free later */
- if (p7->certs)
- wolfSSL_sk_pop_free(p7->certs, NULL);
- p7->certs = ret;
- return ret;
- error:
- if (ret) {
- wolfSSL_sk_pop_free(ret, NULL);
- }
- return NULL;
- }
- /**
- * Return stack of signers contained in PKCS7 cert.
- * Notes:
- * - Currently only PKCS#7 messages with a single signer cert is supported.
- * - Returned WOLFSSL_STACK must be freed by caller.
- *
- * pkcs7 - PKCS7 struct to retrieve signer certs from.
- * certs - currently unused
- * flags - flags to control function behavior.
- *
- * Return WOLFSSL_STACK of signers on success, NULL on error.
- */
- WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs,
- int flags)
- {
- WOLFSSL_X509* x509 = NULL;
- WOLFSSL_STACK* signers = NULL;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- if (p7 == NULL)
- return NULL;
- /* Only PKCS#7 messages with a single cert that is the verifying certificate
- * is supported.
- */
- if (flags & PKCS7_NOINTERN) {
- WOLFSSL_MSG("PKCS7_NOINTERN flag not supported");
- return NULL;
- }
- signers = wolfSSL_sk_X509_new();
- if (signers == NULL)
- return NULL;
- if (wolfSSL_d2i_X509(&x509, (const byte**)&p7->pkcs7.singleCert,
- p7->pkcs7.singleCertSz) == NULL) {
- wolfSSL_sk_X509_pop_free(signers, NULL);
- return NULL;
- }
- if (wolfSSL_sk_X509_push(signers, x509) != WOLFSSL_SUCCESS) {
- wolfSSL_sk_X509_pop_free(signers, NULL);
- return NULL;
- }
- (void)certs;
- return signers;
- }
- #ifndef NO_BIO
- PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7)
- {
- WOLFSSL_PKCS7* pkcs7;
- int ret;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_bio");
- if (bio == NULL)
- return NULL;
- if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
- return NULL;
- pkcs7->len = wolfSSL_BIO_get_len(bio);
- pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
- if (pkcs7->data == NULL) {
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- if ((ret = wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len)) <= 0) {
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- /* pkcs7->len may change if using b64 for example */
- pkcs7->len = ret;
- if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len)
- != 0) {
- WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed");
- wolfSSL_PKCS7_free((PKCS7*)pkcs7);
- return NULL;
- }
- if (p7 != NULL)
- *p7 = (PKCS7*)pkcs7;
- return (PKCS7*)pkcs7;
- }
- int wolfSSL_i2d_PKCS7(PKCS7 *p7, unsigned char **out)
- {
- byte* output = NULL;
- int localBuf = 0;
- int len;
- WC_RNG rng;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_i2d_PKCS7");
- if (!out || !p7) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if (!p7->rng) {
- if (wc_InitRng(&rng) != 0) {
- WOLFSSL_MSG("wc_InitRng error");
- return WOLFSSL_FAILURE;
- }
- p7->rng = &rng; // cppcheck-suppress autoVariables
- }
- if ((len = wc_PKCS7_EncodeSignedData(p7, NULL, 0)) < 0) {
- WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error");
- goto cleanup;
- }
- if (*out == NULL) {
- output = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (!output) {
- WOLFSSL_MSG("malloc error");
- goto cleanup;
- }
- localBuf = 1;
- }
- else {
- output = *out;
- }
- if ((len = wc_PKCS7_EncodeSignedData(p7, output, len)) < 0) {
- WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error");
- goto cleanup;
- }
- ret = len;
- cleanup:
- if (p7->rng == &rng) {
- wc_FreeRng(&rng);
- p7->rng = NULL;
- }
- if (ret == WOLFSSL_FAILURE && localBuf && output)
- XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret != WOLFSSL_FAILURE)
- *out = output;
- return ret;
- }
- int wolfSSL_i2d_PKCS7_bio(WOLFSSL_BIO *bio, PKCS7 *p7)
- {
- byte* output = NULL;
- int len;
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_i2d_PKCS7_bio");
- if (!bio || !p7) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- if ((len = wolfSSL_i2d_PKCS7(p7, &output)) == WOLFSSL_FAILURE) {
- WOLFSSL_MSG("wolfSSL_i2d_PKCS7 error");
- goto cleanup;
- }
- if (wolfSSL_BIO_write(bio, output, len) <= 0) {
- WOLFSSL_MSG("wolfSSL_BIO_write error");
- goto cleanup;
- }
- ret = WOLFSSL_SUCCESS;
- cleanup:
- if (output)
- XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- /**
- * Creates and returns a PKCS7 signedData structure.
- *
- * Inner content type is set to DATA to match OpenSSL behavior.
- *
- * signer - certificate to sign bundle with
- * pkey - private key matching signer
- * certs - optional additional set of certificates to include
- * in - input data to be signed
- * flags - optional set of flags to control sign behavior
- *
- * PKCS7_BINARY - Do not translate input data to MIME canonical
- * format (\r\n line endings), thus preventing corruption of
- * binary content.
- * PKCS7_TEXT - Prepend MIME headers for text/plain to content.
- * PKCS7_DETACHED - Set signature detached, omit content from output bundle.
- * PKCS7_STREAM - initialize PKCS7 struct for signing, do not read data.
- *
- * Flags not currently supported:
- * PKCS7_NOCERTS - Do not include the signer cert in the output bundle.
- * PKCS7_PARTIAL - Allow for PKCS7_sign() to be only partially set up,
- * then signers etc to be added separately before
- * calling PKCS7_final().
- *
- * Returns valid PKCS7 structure pointer, or NULL if an error occurred.
- */
- PKCS7* wolfSSL_PKCS7_sign(WOLFSSL_X509* signer, WOLFSSL_EVP_PKEY* pkey,
- WOLFSSL_STACK* certs, WOLFSSL_BIO* in, int flags)
- {
- int err = 0;
- WOLFSSL_PKCS7* p7 = NULL;
- WOLFSSL_STACK* cert = certs;
- WOLFSSL_ENTER("wolfSSL_PKCS7_sign");
- if (flags & PKCS7_NOCERTS) {
- WOLFSSL_MSG("PKCS7_NOCERTS flag not yet supported");
- err = 1;
- }
- if (flags & PKCS7_PARTIAL) {
- WOLFSSL_MSG("PKCS7_PARTIAL flag not yet supported");
- err = 1;
- }
- if ((err == 0) && (signer == NULL || signer->derCert == NULL ||
- signer->derCert->length == 0)) {
- WOLFSSL_MSG("Bad function arg, signer is NULL or incomplete");
- err = 1;
- }
- if ((err == 0) && (pkey == NULL || pkey->pkey.ptr == NULL ||
- pkey->pkey_sz <= 0)) {
- WOLFSSL_MSG("Bad function arg, pkey is NULL or incomplete");
- err = 1;
- }
- if ((err == 0) && (in == NULL) && !(flags & PKCS7_STREAM)) {
- WOLFSSL_MSG("input data required unless PKCS7_STREAM used");
- err = 1;
- }
- if ((err == 0) && ((p7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)) {
- WOLFSSL_MSG("Error allocating new WOLFSSL_PKCS7");
- err = 1;
- }
- /* load signer certificate */
- if (err == 0) {
- if (wc_PKCS7_InitWithCert(&p7->pkcs7, signer->derCert->buffer,
- signer->derCert->length) != 0) {
- WOLFSSL_MSG("Failed to load signer certificate");
- err = 1;
- }
- }
- /* set signer private key, data types, defaults */
- if (err == 0) {
- p7->pkcs7.privateKey = (byte*)pkey->pkey.ptr;
- p7->pkcs7.privateKeySz = pkey->pkey_sz;
- p7->pkcs7.contentOID = DATA; /* inner content default is DATA */
- p7->pkcs7.hashOID = SHA256h; /* default to SHA-256 hash type */
- p7->type = SIGNED_DATA; /* PKCS7_final switches on type */
- }
- /* add additional chain certs if provided */
- while (cert && (err == 0)) {
- if (cert->data.x509 != NULL && cert->data.x509->derCert != NULL) {
- if (wc_PKCS7_AddCertificate(&p7->pkcs7,
- cert->data.x509->derCert->buffer,
- cert->data.x509->derCert->length) != 0) {
- WOLFSSL_MSG("Error in wc_PKCS7_AddCertificate");
- err = 1;
- }
- }
- cert = cert->next;
- }
- if ((err == 0) && (flags & PKCS7_DETACHED)) {
- if (wc_PKCS7_SetDetached(&p7->pkcs7, 1) != 0) {
- WOLFSSL_MSG("Failed to set signature detached");
- err = 1;
- }
- }
- if ((err == 0) && (flags & PKCS7_STREAM)) {
- /* if streaming, return before finalizing */
- return (PKCS7*)p7;
- }
- if ((err == 0) && (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1)) {
- WOLFSSL_MSG("Error calling wolfSSL_PKCS7_final");
- err = 1;
- }
- if ((err != 0) && (p7 != NULL)) {
- wolfSSL_PKCS7_free((PKCS7*)p7);
- p7 = NULL;
- }
- return (PKCS7*)p7;
- }
- #ifdef HAVE_SMIME
- #ifndef MAX_MIME_LINE_LEN
- #define MAX_MIME_LINE_LEN 1024
- #endif
- /**
- * Copy input BIO to output BIO, but convert all line endings to CRLF (\r\n),
- * used by PKCS7_final().
- *
- * in - input WOLFSSL_BIO to be converted
- * out - output WOLFSSL_BIO to hold copy of in, with line endings adjusted
- *
- * Return 0 on success, negative on error
- */
- static int wolfSSL_BIO_to_MIME_crlf(WOLFSSL_BIO* in, WOLFSSL_BIO* out)
- {
- int ret = 0;
- int lineLen = 0;
- word32 canonLineLen = 0;
- char* canonLine = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- char* line = NULL;
- #else
- char line[MAX_MIME_LINE_LEN];
- #endif
- if (in == NULL || out == NULL) {
- return BAD_FUNC_ARG;
- }
- #ifdef WOLFSSL_SMALL_STACK
- line = (char*)XMALLOC(MAX_MIME_LINE_LEN, in->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (line == NULL) {
- return MEMORY_E;
- }
- #endif
- XMEMSET(line, 0, MAX_MIME_LINE_LEN);
- while ((lineLen = wolfSSL_BIO_gets(in, line, (int)sizeof(line))) > 0) {
- if (line[lineLen - 1] == '\r' || line[lineLen - 1] == '\n') {
- canonLineLen = (word32)lineLen;
- if ((canonLine = wc_MIME_single_canonicalize(
- line, &canonLineLen)) == NULL) {
- ret = -1;
- break;
- }
- /* remove trailing null */
- if (canonLine[canonLineLen] == '\0') {
- canonLineLen--;
- }
- if (wolfSSL_BIO_write(out, canonLine, (int)canonLineLen) < 0) {
- ret = -1;
- break;
- }
- XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
- canonLine = NULL;
- }
- else {
- /* no line ending in current line, write direct to out */
- if (wolfSSL_BIO_write(out, line, lineLen) < 0) {
- ret = -1;
- break;
- }
- }
- }
- if (canonLine != NULL) {
- XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(line, in->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
- #endif /* HAVE_SMIME */
- /* Used by both PKCS7_final() and PKCS7_verify() */
- static const char contTypeText[] = "Content-Type: text/plain\r\n\r\n";
- /**
- * Finalize PKCS7 structure, currently supports signedData only.
- *
- * Does not generate final bundle (ie: signedData), but finalizes
- * the PKCS7 structure in preparation for a output function to be called next.
- *
- * pkcs7 - initialized PKCS7 structure, populated with signer, etc
- * in - input data
- * flags - flags to control PKCS7 behavior. Other flags except those noted
- * below are ignored:
- *
- * PKCS7_BINARY - Do not translate input data to MIME canonical
- * format (\r\n line endings), thus preventing corruption of
- * binary content.
- * PKCS7_TEXT - Prepend MIME headers for text/plain to content.
- *
- * Returns 1 on success, 0 on error
- */
- int wolfSSL_PKCS7_final(PKCS7* pkcs7, WOLFSSL_BIO* in, int flags)
- {
- int ret = 1;
- int memSz = 0;
- unsigned char* mem = NULL;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- WOLFSSL_BIO* data = NULL;
- WOLFSSL_ENTER("wolfSSL_PKCS7_final");
- if (p7 == NULL || in == NULL) {
- WOLFSSL_MSG("Bad input args to PKCS7_final");
- ret = 0;
- }
- if (ret == 1) {
- if ((data = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())) == NULL) {
- WOLFSSL_MSG("Error in wolfSSL_BIO_new");
- ret = 0;
- }
- }
- /* prepend Content-Type header if PKCS7_TEXT */
- if ((ret == 1) && (flags & PKCS7_TEXT)) {
- if (wolfSSL_BIO_write(data, contTypeText,
- (int)XSTR_SIZEOF(contTypeText)) < 0) {
- WOLFSSL_MSG("Error prepending Content-Type header");
- ret = 0;
- }
- }
- /* convert line endings to CRLF if !PKCS7_BINARY */
- if (ret == 1) {
- if (flags & PKCS7_BINARY) {
- /* no CRLF conversion, direct copy content */
- if ((memSz = wolfSSL_BIO_get_len(in)) <= 0) {
- ret = 0;
- }
- if (ret == 1) {
- mem = (unsigned char*)XMALLOC(memSz, in->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_MSG("Failed to allocate memory for input data");
- ret = 0;
- }
- }
- if (ret == 1) {
- if (wolfSSL_BIO_read(in, mem, memSz) != memSz) {
- WOLFSSL_MSG("Error reading from input BIO");
- ret = 0;
- }
- else if (wolfSSL_BIO_write(data, mem, memSz) < 0) {
- ret = 0;
- }
- }
- if (mem != NULL) {
- XFREE(mem, in->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- }
- else {
- #ifdef HAVE_SMIME
- /* convert content line endings to CRLF */
- if (wolfSSL_BIO_to_MIME_crlf(in, data) != 0) {
- WOLFSSL_MSG("Error converting line endings to CRLF");
- ret = 0;
- }
- else {
- p7->pkcs7.contentCRLF = 1;
- }
- #else
- WOLFSSL_MSG("Without PKCS7_BINARY requires wolfSSL to be built "
- "with HAVE_SMIME");
- ret = 0;
- #endif
- }
- }
- if ((ret == 1) && ((memSz = wolfSSL_BIO_get_mem_data(data, &mem)) < 0)) {
- WOLFSSL_MSG("Error in wolfSSL_BIO_get_mem_data");
- ret = 0;
- }
- if (ret == 1) {
- if (p7->data != NULL) {
- XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
- }
- p7->data = (byte*)XMALLOC(memSz, NULL, DYNAMIC_TYPE_PKCS7);
- if (p7->data == NULL) {
- ret = 0;
- }
- else {
- XMEMCPY(p7->data, mem, memSz);
- p7->len = memSz;
- }
- }
- if (ret == 1) {
- p7->pkcs7.content = p7->data;
- p7->pkcs7.contentSz = p7->len;
- }
- if (data != NULL) {
- wolfSSL_BIO_free(data);
- }
- return ret;
- }
- int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs,
- WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, WOLFSSL_BIO* out, int flags)
- {
- int i, ret = 0;
- unsigned char* mem = NULL;
- int memSz = 0;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- int contTypeLen;
- WOLFSSL_X509* signer = NULL;
- WOLFSSL_STACK* signers = NULL;
- WOLFSSL_ENTER("wolfSSL_PKCS7_verify");
- if (pkcs7 == NULL)
- return WOLFSSL_FAILURE;
- if (in != NULL) {
- if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0)
- return WOLFSSL_FAILURE;
- p7->pkcs7.content = mem;
- p7->pkcs7.contentSz = memSz;
- }
- /* certs is the list of certificates to find the cert with issuer/serial. */
- (void)certs;
- /* store is the certificate store to use to verify signer certificate
- * associated with the signers.
- */
- (void)store;
- ret = wc_PKCS7_VerifySignedData(&p7->pkcs7, p7->data, p7->len);
- if (ret != 0)
- return WOLFSSL_FAILURE;
- if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) {
- /* Verify signer certificates */
- if (store == NULL || store->cm == NULL) {
- WOLFSSL_MSG("No store or store certs, but PKCS7_NOVERIFY not set");
- return WOLFSSL_FAILURE;
- }
- signers = wolfSSL_PKCS7_get0_signers(pkcs7, certs, flags);
- if (signers == NULL) {
- WOLFSSL_MSG("No signers found to verify");
- return WOLFSSL_FAILURE;
- }
- for (i = 0; i < wolfSSL_sk_X509_num(signers); i++) {
- signer = wolfSSL_sk_X509_value(signers, i);
- if (wolfSSL_CertManagerVerifyBuffer(store->cm,
- signer->derCert->buffer,
- signer->derCert->length,
- WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Failed to verify signer certificate");
- wolfSSL_sk_X509_pop_free(signers, NULL);
- return WOLFSSL_FAILURE;
- }
- }
- wolfSSL_sk_X509_pop_free(signers, NULL);
- }
- if (flags & PKCS7_TEXT) {
- /* strip MIME header for text/plain, otherwise error */
- contTypeLen = XSTR_SIZEOF(contTypeText);
- if ((p7->pkcs7.contentSz < (word32)contTypeLen) ||
- (XMEMCMP(p7->pkcs7.content, contTypeText, contTypeLen) != 0)) {
- WOLFSSL_MSG("Error PKCS7 Content-Type not found with PKCS7_TEXT");
- return WOLFSSL_FAILURE;
- }
- p7->pkcs7.content += contTypeLen;
- p7->pkcs7.contentSz -= contTypeLen;
- }
- if (out != NULL) {
- wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz);
- }
- WOLFSSL_LEAVE("wolfSSL_PKCS7_verify", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- }
- /**
- * This API was added as a helper function for libest. It
- * encodes a stack of certificates to pkcs7 format.
- * @param pkcs7 PKCS7 parameter object
- * @param certs WOLFSSL_STACK_OF(WOLFSSL_X509)*
- * @param out Output bio
- * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
- */
- int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,
- WOLFSSL_BIO* out)
- {
- int ret;
- WOLFSSL_PKCS7* p7;
- WOLFSSL_ENTER("wolfSSL_PKCS7_encode_certs");
- if (!pkcs7 || !certs || !out) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
- p7 = (WOLFSSL_PKCS7*)pkcs7;
- /* take ownership of certs */
- p7->certs = certs;
- if (pkcs7->certList) {
- WOLFSSL_MSG("wolfSSL_PKCS7_encode_certs called multiple times on same "
- "struct");
- return WOLFSSL_FAILURE;
- }
- if (certs) {
- /* Save some of the values */
- int hashOID = pkcs7->hashOID;
- byte version = pkcs7->version;
- if (!certs->data.x509 || !certs->data.x509->derCert) {
- WOLFSSL_MSG("Missing cert");
- return WOLFSSL_FAILURE;
- }
- if (wc_PKCS7_InitWithCert(pkcs7, certs->data.x509->derCert->buffer,
- certs->data.x509->derCert->length) != 0) {
- WOLFSSL_MSG("wc_PKCS7_InitWithCert error");
- return WOLFSSL_FAILURE;
- }
- certs = certs->next;
- pkcs7->hashOID = hashOID;
- pkcs7->version = version;
- }
- /* Add the certs to the PKCS7 struct */
- while (certs) {
- if (!certs->data.x509 || !certs->data.x509->derCert) {
- WOLFSSL_MSG("Missing cert");
- return WOLFSSL_FAILURE;
- }
- if (wc_PKCS7_AddCertificate(pkcs7, certs->data.x509->derCert->buffer,
- certs->data.x509->derCert->length) != 0) {
- WOLFSSL_MSG("wc_PKCS7_AddCertificate error");
- return WOLFSSL_FAILURE;
- }
- certs = certs->next;
- }
- if (wc_PKCS7_SetSignerIdentifierType(pkcs7, DEGENERATE_SID) != 0) {
- WOLFSSL_MSG("wc_PKCS7_SetSignerIdentifierType error");
- return WOLFSSL_FAILURE;
- }
- ret = wolfSSL_i2d_PKCS7_bio(out, pkcs7);
- return ret;
- }
- /******************************************************************************
- * wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO
- *
- * RETURNS:
- * returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
- */
- int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7)
- {
- #ifdef WOLFSSL_SMALL_STACK
- byte* outputHead;
- byte* outputFoot;
- #else
- byte outputHead[2048];
- byte outputFoot[2048];
- #endif
- word32 outputHeadSz = 2048;
- word32 outputFootSz = 2048;
- word32 outputSz = 0;
- byte* output = NULL;
- byte* pem = NULL;
- int pemSz = -1;
- enum wc_HashType hashType;
- byte hashBuf[WC_MAX_DIGEST_SIZE];
- word32 hashSz = -1;
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7()");
- if (bio == NULL || p7 == NULL)
- return WOLFSSL_FAILURE;
- #ifdef WOLFSSL_SMALL_STACK
- outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (outputHead == NULL)
- return MEMORY_E;
- outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (outputFoot == NULL)
- goto error;
- #endif
- XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE);
- XMEMSET(outputHead, 0, outputHeadSz);
- XMEMSET(outputFoot, 0, outputFootSz);
- hashType = wc_OidGetHash(p7->hashOID);
- hashSz = wc_HashGetDigestSize(hashType);
- if (hashSz > WC_MAX_DIGEST_SIZE)
- return WOLFSSL_FAILURE;
- /* only SIGNED_DATA is supported */
- switch (p7->contentOID) {
- case SIGNED_DATA:
- break;
- default:
- WOLFSSL_MSG("Unknown PKCS#7 Type");
- return WOLFSSL_FAILURE;
- };
- if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz,
- outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0)
- return WOLFSSL_FAILURE;
- outputSz = outputHeadSz + p7->contentSz + outputFootSz;
- output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (!output)
- return WOLFSSL_FAILURE;
- XMEMSET(output, 0, outputSz);
- outputSz = 0;
- XMEMCPY(&output[outputSz], outputHead, outputHeadSz);
- outputSz += outputHeadSz;
- XMEMCPY(&output[outputSz], p7->content, p7->contentSz);
- outputSz += p7->contentSz;
- XMEMCPY(&output[outputSz], outputFoot, outputFootSz);
- outputSz += outputFootSz;
- /* get PEM size */
- pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE);
- if (pemSz < 0)
- goto error;
- pemSz++; /* for '\0'*/
- /* create PEM buffer and convert from DER to PEM*/
- if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER))
- == NULL)
- goto error;
- XMEMSET(pem, 0, pemSz);
- if (wc_DerToPemEx(output, outputSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
- goto error;
- }
- if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) {
- XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return WOLFSSL_SUCCESS;
- }
- error:
- #ifdef WOLFSSL_SMALL_STACK
- if (outputHead) {
- XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (outputFoot) {
- XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- if (output) {
- XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (pem) {
- XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- return WOLFSSL_FAILURE;
- }
- #ifdef HAVE_SMIME
- /*****************************************************************************
- * wolfSSL_SMIME_read_PKCS7 - Reads the given S/MIME message and parses it into
- * a PKCS7 object. In case of a multipart message, stores the signed data in
- * bcont.
- *
- * RETURNS:
- * returns pointer to a PKCS7 structure on success, otherwise returns NULL
- */
- WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in,
- WOLFSSL_BIO** bcont)
- {
- MimeHdr* allHdrs = NULL;
- MimeHdr* curHdr = NULL;
- MimeParam* curParam = NULL;
- int inLen = 0;
- byte* bcontMem = NULL;
- int bcontMemSz = 0;
- int sectionLen = 0;
- int ret = -1;
- char* section = NULL;
- char* canonLine = NULL;
- char* canonSection = NULL;
- PKCS7* pkcs7 = NULL;
- word32 outLen = 0;
- word32 canonLineLen = 0;
- byte* out = NULL;
- byte* outHead = NULL;
- int canonPos = 0;
- int lineLen = 0;
- int remainLen = 0;
- byte isEnd = 0;
- size_t canonSize = 0;
- size_t boundLen = 0;
- char* boundary = NULL;
- static const char kContType[] = "Content-Type";
- static const char kCTE[] = "Content-Transfer-Encoding";
- static const char kMultSigned[] = "multipart/signed";
- static const char kAppPkcsSign[] = "application/pkcs7-signature";
- static const char kAppXPkcsSign[] = "application/x-pkcs7-signature";
- static const char kAppPkcs7Mime[] = "application/pkcs7-mime";
- static const char kAppXPkcs7Mime[] = "application/x-pkcs7-mime";
- WOLFSSL_ENTER("wolfSSL_SMIME_read_PKCS7");
- if (in == NULL || bcont == NULL) {
- goto error;
- }
- inLen = wolfSSL_BIO_get_len(in);
- if (inLen <= 0) {
- goto error;
- }
- remainLen = wolfSSL_BIO_get_len(in);
- if (remainLen <= 0) {
- goto error;
- }
- section = (char*)XMALLOC(remainLen+1, NULL, DYNAMIC_TYPE_PKCS7);
- if (section == NULL) {
- goto error;
- }
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- while (isEnd == 0 && remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- /* Line with just newline signals end of headers. */
- if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen],
- "\r\n", 2)) ||
- (lineLen==1 && (section[sectionLen] == '\r' ||
- section[sectionLen] == '\n'))) {
- isEnd = 1;
- }
- }
- section[sectionLen] = '\0';
- ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs);
- if (ret < 0) {
- WOLFSSL_MSG("Parsing MIME headers failed.");
- goto error;
- }
- isEnd = 0;
- section[0] = '\0';
- sectionLen = 0;
- curHdr = wc_MIME_find_header_name(kContType, allHdrs);
- if (curHdr && !XSTRNCMP(curHdr->body, kMultSigned,
- XSTR_SIZEOF(kMultSigned))) {
- curParam = wc_MIME_find_param_attr("protocol", curHdr->params);
- if (curParam && (!XSTRNCMP(curParam->value, kAppPkcsSign,
- XSTR_SIZEOF(kAppPkcsSign)) ||
- !XSTRNCMP(curParam->value, kAppXPkcsSign,
- XSTR_SIZEOF(kAppXPkcsSign)))) {
- curParam = wc_MIME_find_param_attr("boundary", curHdr->params);
- if (curParam == NULL) {
- goto error;
- }
- boundLen = XSTRLEN(curParam->value) + 2;
- boundary = (char*)XMALLOC(boundLen+1, NULL, DYNAMIC_TYPE_PKCS7);
- if (boundary == NULL) {
- goto error;
- }
- XMEMSET(boundary, 0, (word32)(boundLen+1));
- boundary[0] = boundary[1] = '-';
- XSTRNCPY(&boundary[2], curParam->value, boundLen-2);
- /* Parse up to first boundary, ignore everything here. */
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) &&
- remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- }
- section[0] = '\0';
- sectionLen = 0;
- canonSize = remainLen + 1;
- canonSection = (char*)XMALLOC(canonSize, NULL,
- DYNAMIC_TYPE_PKCS7);
- if (canonSection == NULL) {
- goto error;
- }
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) &&
- remainLen > 0) {
- canonLineLen = lineLen;
- canonLine = wc_MIME_single_canonicalize(§ion[sectionLen],
- &canonLineLen);
- if (canonLine == NULL) {
- goto error;
- }
- /* If line endings were added, the initial length may be
- * exceeded. */
- if ((canonPos + canonLineLen) >= canonSize) {
- canonSize = canonPos + canonLineLen;
- canonSection = (char*)XREALLOC(canonSection, canonSize,
- NULL, DYNAMIC_TYPE_PKCS7);
- if (canonSection == NULL) {
- goto error;
- }
- }
- XMEMCPY(&canonSection[canonPos], canonLine,
- (int)canonLineLen - 1);
- canonPos += canonLineLen - 1;
- XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
- canonLine = NULL;
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- }
- if (canonPos > 0) {
- canonPos--;
- }
- /* Strip the final trailing newline. Support \r, \n or \r\n. */
- if (canonSection[canonPos] == '\n') {
- if (canonPos > 0) {
- canonPos--;
- }
- }
- if (canonSection[canonPos] == '\r') {
- if (canonPos > 0) {
- canonPos--;
- }
- }
- canonSection[canonPos+1] = '\0';
- *bcont = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
- ret = wolfSSL_BIO_write(*bcont, canonSection,
- canonPos + 1);
- if (ret != (canonPos+1)) {
- goto error;
- }
- if ((bcontMemSz = wolfSSL_BIO_get_mem_data(*bcont, &bcontMem))
- < 0) {
- goto error;
- }
- XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7);
- canonSection = NULL;
- wc_MIME_free_hdrs(allHdrs);
- allHdrs = NULL;
- section[0] = '\0';
- sectionLen = 0;
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- while (isEnd == 0 && remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- /* Line with just newline signals end of headers. */
- if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen],
- "\r\n", 2)) ||
- (lineLen==1 && (section[sectionLen] == '\r' ||
- section[sectionLen] == '\n'))) {
- isEnd = 1;
- }
- }
- section[sectionLen] = '\0';
- ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs);
- if (ret < 0) {
- WOLFSSL_MSG("Parsing MIME headers failed.");
- goto error;
- }
- curHdr = wc_MIME_find_header_name(kContType, allHdrs);
- if (curHdr == NULL || (XSTRNCMP(curHdr->body, kAppPkcsSign,
- XSTR_SIZEOF(kAppPkcsSign)) &&
- XSTRNCMP(curHdr->body, kAppXPkcsSign,
- XSTR_SIZEOF(kAppXPkcsSign)))) {
- WOLFSSL_MSG("S/MIME headers not found inside "
- "multipart message.\n");
- goto error;
- }
- section[0] = '\0';
- sectionLen = 0;
- lineLen = wolfSSL_BIO_gets(in, section, remainLen);
- while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) &&
- remainLen > 0) {
- sectionLen += lineLen;
- remainLen -= lineLen;
- lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen],
- remainLen);
- if (lineLen <= 0) {
- goto error;
- }
- }
- XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7);
- boundary = NULL;
- }
- }
- else if (curHdr && (!XSTRNCMP(curHdr->body, kAppPkcs7Mime,
- XSTR_SIZEOF(kAppPkcs7Mime)) ||
- !XSTRNCMP(curHdr->body, kAppXPkcs7Mime,
- XSTR_SIZEOF(kAppXPkcs7Mime)))) {
- sectionLen = wolfSSL_BIO_get_len(in);
- if (sectionLen <= 0) {
- goto error;
- }
- ret = wolfSSL_BIO_read(in, section, sectionLen);
- if (ret < 0 || ret != sectionLen) {
- WOLFSSL_MSG("Error reading input BIO.");
- goto error;
- }
- }
- else {
- WOLFSSL_MSG("S/MIME headers not found.");
- goto error;
- }
- curHdr = wc_MIME_find_header_name(kCTE, allHdrs);
- if (curHdr == NULL) {
- WOLFSSL_MSG("Content-Transfer-Encoding header not found, "
- "assuming base64 encoding.");
- }
- else if (XSTRNCMP(curHdr->body, "base64", XSTRLEN("base64"))) {
- WOLFSSL_MSG("S/MIME encodings other than base64 are not "
- "currently supported.\n");
- goto error;
- }
- if (section == NULL || sectionLen <= 0) {
- goto error;
- }
- outLen = ((sectionLen*3+3)/4)+1;
- out = (byte*)XMALLOC(outLen*sizeof(byte), NULL, DYNAMIC_TYPE_PKCS7);
- outHead = out;
- if (outHead == NULL) {
- goto error;
- }
- /* Strip trailing newlines. */
- while ((sectionLen > 0) &&
- (section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n')) {
- sectionLen--;
- }
- section[sectionLen] = '\0';
- ret = Base64_Decode((const byte*)section, sectionLen, out, &outLen);
- if (ret < 0) {
- WOLFSSL_MSG("Error base64 decoding S/MIME message.");
- goto error;
- }
- pkcs7 = wolfSSL_d2i_PKCS7_ex(NULL, (const unsigned char**)&out, outLen,
- bcontMem, bcontMemSz);
- wc_MIME_free_hdrs(allHdrs);
- XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7);
- XFREE(section, NULL, DYNAMIC_TYPE_PKCS7);
- return pkcs7;
- error:
- wc_MIME_free_hdrs(allHdrs);
- XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7);
- XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7);
- XFREE(section, NULL, DYNAMIC_TYPE_PKCS7);
- if (canonSection != NULL)
- XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7);
- if (bcont) {
- wolfSSL_BIO_free(*bcont);
- *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */
- }
- return NULL;
- }
- /* Convert hash algo OID (from Hash_Sum in asn.h) to SMIME string equivalent.
- * Returns hash algorithm string or "unknown" if not found */
- static const char* wolfSSL_SMIME_HashOIDToString(int hashOID)
- {
- switch (hashOID) {
- case MD5h:
- return "md5";
- case SHAh:
- return "sha1";
- case SHA224h:
- return "sha-224";
- case SHA256h:
- return "sha-256";
- case SHA384h:
- return "sha-384";
- case SHA512h:
- return "sha-512";
- case SHA3_224h:
- return "sha3-224";
- case SHA3_384h:
- return "sha3-384";
- case SHA3_512h:
- return "sha3-512";
- default:
- break;
- }
- return "unknown";
- }
- /* Convert PKCS#7 type (from PKCS7_TYPES in pkcs7.h) to SMIME string.
- * RFC2633 only defines signed-data, enveloped-data, certs-only.
- * Returns string on success, NULL on unknown type. */
- static const char* wolfSSL_SMIME_PKCS7TypeToString(int type)
- {
- switch (type) {
- case SIGNED_DATA:
- return "signed-data";
- case ENVELOPED_DATA:
- return "enveloped-data";
- default:
- break;
- }
- return NULL;
- }
- /**
- * Convert PKCS7 structure to SMIME format, adding necessary headers.
- *
- * Handles generation of PKCS7 bundle (ie: signedData). PKCS7 structure
- * should be set up beforehand with PKCS7_sign/final/etc. Output is always
- * Base64 encoded.
- *
- * out - output BIO for SMIME formatted data to be placed
- * pkcs7 - input PKCS7 structure, initialized and set up
- * in - input content to be encoded into PKCS7
- * flags - flags to control behavior of PKCS7 generation
- *
- * Returns 1 on success, 0 or negative on failure
- */
- int wolfSSL_SMIME_write_PKCS7(WOLFSSL_BIO* out, PKCS7* pkcs7, WOLFSSL_BIO* in,
- int flags)
- {
- int i;
- int ret = 1;
- WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
- byte* p7out = NULL;
- int len = 0;
- char boundary[33]; /* 32 chars + \0 */
- byte* sigBase64 = NULL;
- word32 sigBase64Len = 0;
- const char* p7TypeString = NULL;
- static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (out == NULL || p7 == NULL) {
- WOLFSSL_MSG("Bad function arguments");
- return 0;
- }
- if (in != NULL && (p7->pkcs7.content == NULL || p7->pkcs7.contentSz == 0 ||
- p7->pkcs7.contentCRLF == 0)) {
- /* store and adjust content line endings for CRLF if needed */
- if (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1) {
- ret = 0;
- }
- }
- if (ret > 0) {
- /* Generate signedData bundle, DER in output (dynamic) */
- if ((len = wolfSSL_i2d_PKCS7((PKCS7*)p7, &p7out)) == WOLFSSL_FAILURE) {
- WOLFSSL_MSG("Error in wolfSSL_i2d_PKCS7");
- ret = 0;
- }
- }
- /* Base64 encode signedData bundle */
- if (ret > 0) {
- if (Base64_Encode(p7out, len, NULL, &sigBase64Len) != LENGTH_ONLY_E) {
- ret = 0;
- }
- else {
- sigBase64 = (byte*)XMALLOC(sigBase64Len, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sigBase64 == NULL) {
- ret = 0;
- }
- }
- }
- if (ret > 0) {
- XMEMSET(sigBase64, 0, sigBase64Len);
- if (Base64_Encode(p7out, len, sigBase64, &sigBase64Len) < 0) {
- WOLFSSL_MSG("Error in Base64_Encode of signature");
- ret = 0;
- }
- }
- /* build up SMIME message */
- if (ret > 0) {
- if (flags & PKCS7_DETACHED) {
- /* generate random boundary */
- if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("No RNG to use");
- ret = 0;
- }
- /* no need to generate random byte for null terminator (size-1) */
- if ((ret > 0) && (wc_RNG_GenerateBlock(&globalRNG, (byte*)boundary,
- sizeof(boundary) - 1 ) != 0)) {
- WOLFSSL_MSG("Error in wc_RNG_GenerateBlock");
- ret = 0;
- }
- if (ret > 0) {
- for (i = 0; i < (int)sizeof(boundary) - 1; i++) {
- boundary[i] =
- alphanum[boundary[i] % XSTR_SIZEOF(alphanum)];
- }
- boundary[sizeof(boundary)-1] = 0;
- }
- if (ret > 0) {
- /* S/MIME header beginning */
- ret = wolfSSL_BIO_printf(out,
- "MIME-Version: 1.0\n"
- "Content-Type: multipart/signed; "
- "protocol=\"application/x-pkcs7-signature\"; "
- "micalg=\"%s\"; "
- "boundary=\"----%s\"\n\n"
- "This is an S/MIME signed message\n\n"
- "------%s\n",
- wolfSSL_SMIME_HashOIDToString(p7->pkcs7.hashOID),
- boundary, boundary);
- }
- if (ret > 0) {
- /* S/MIME content */
- ret = wolfSSL_BIO_write(out,
- p7->pkcs7.content, p7->pkcs7.contentSz);
- }
- if (ret > 0) {
- /* S/SMIME header end boundary */
- ret = wolfSSL_BIO_printf(out,
- "\n------%s\n", boundary);
- }
- if (ret > 0) {
- /* Signature and header */
- ret = wolfSSL_BIO_printf(out,
- "Content-Type: application/x-pkcs7-signature; "
- "name=\"smime.p7s\"\n"
- "Content-Transfer-Encoding: base64\n"
- "Content-Disposition: attachment; "
- "filename=\"smime.p7s\"\n\n"
- "%.*s\n" /* Base64 encoded signature */
- "------%s--\n\n",
- sigBase64Len, sigBase64,
- boundary);
- }
- }
- else {
- p7TypeString = wolfSSL_SMIME_PKCS7TypeToString(p7->type);
- if (p7TypeString == NULL) {
- WOLFSSL_MSG("Unsupported PKCS7 SMIME type");
- ret = 0;
- }
- if (ret > 0) {
- /* not detached */
- ret = wolfSSL_BIO_printf(out,
- "MIME-Version: 1.0\n"
- "Content-Disposition: attachment; "
- "filename=\"smime.p7m\"\n"
- "Content-Type: application/x-pkcs7-mime; "
- "smime-type=%s; name=\"smime.p7m\"\n"
- "Content-Transfer-Encoding: base64\n\n"
- "%.*s\n" /* signature */,
- p7TypeString, sigBase64Len, sigBase64);
- }
- }
- }
- if (p7out != NULL) {
- XFREE(p7out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (sigBase64 != NULL) {
- XFREE(sigBase64, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- if (ret > 0) {
- return WOLFSSL_SUCCESS;
- }
- return WOLFSSL_FAILURE;
- }
- #endif /* HAVE_SMIME */
- #endif /* !NO_BIO */
- #endif /* OPENSSL_ALL */
- #endif /* HAVE_PKCS7 */
- /*******************************************************************************
- * END OF PKCS7 APIs
- ******************************************************************************/
- /*******************************************************************************
- * START OF PKCS12 APIs
- ******************************************************************************/
- #ifdef OPENSSL_EXTRA
- /* no-op function. Was initially used for adding encryption algorithms available
- * for PKCS12 */
- void wolfSSL_PKCS12_PBE_add(void)
- {
- WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
- }
- #if !defined(NO_FILESYSTEM)
- WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp,
- WOLFSSL_X509_PKCS12 **pkcs12)
- {
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp");
- return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12,
- PKCS12_TYPE);
- }
- #endif /* !NO_FILESYSTEM */
- #endif /* OPENSSL_EXTRA */
- #if defined(HAVE_PKCS12)
- #ifdef OPENSSL_EXTRA
- #if !defined(NO_ASN) && !defined(NO_PWDBASED)
- #ifndef NO_BIO
- WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
- {
- WC_PKCS12* localPkcs12 = NULL;
- unsigned char* mem = NULL;
- long memSz;
- int ret = -1;
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
- if (bio == NULL) {
- WOLFSSL_MSG("Bad Function Argument bio is NULL");
- return NULL;
- }
- memSz = wolfSSL_BIO_get_len(bio);
- if (memSz <= 0) {
- return NULL;
- }
- mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- return NULL;
- }
- if (mem != NULL) {
- localPkcs12 = wc_PKCS12_new();
- if (localPkcs12 == NULL) {
- WOLFSSL_MSG("Memory error");
- }
- }
- if (mem != NULL && localPkcs12 != NULL) {
- if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
- ret = wc_d2i_PKCS12(mem, (word32)memSz, localPkcs12);
- if (ret < 0) {
- WOLFSSL_MSG("Failed to get PKCS12 sequence");
- }
- }
- else {
- WOLFSSL_MSG("Failed to get data from bio struct");
- }
- }
- /* cleanup */
- if (mem != NULL)
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ret < 0 && localPkcs12 != NULL) {
- wc_PKCS12_free(localPkcs12);
- localPkcs12 = NULL;
- }
- if (pkcs12 != NULL)
- *pkcs12 = localPkcs12;
- return localPkcs12;
- }
- /* Converts the PKCS12 to DER format and outputs it into bio.
- *
- * bio is the structure to hold output DER
- * pkcs12 structure to create DER from
- *
- * return 1 for success or 0 if an error occurs
- */
- int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12)
- {
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio");
- if ((bio != NULL) && (pkcs12 != NULL)) {
- word32 certSz = 0;
- byte *certDer = NULL;
- certSz = wc_i2d_PKCS12(pkcs12, &certDer, NULL);
- if ((certSz > 0) && (certDer != NULL)) {
- if (wolfSSL_BIO_write(bio, certDer, certSz) == (int)certSz) {
- ret = WOLFSSL_SUCCESS;
- }
- }
- if (certDer != NULL) {
- XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS);
- }
- }
- return ret;
- }
- #endif /* !NO_BIO */
- /* Creates a new WC_PKCS12 structure
- *
- * pass password to use
- * name friendlyName to use
- * pkey private key to go into PKCS12 bundle
- * cert certificate to go into PKCS12 bundle
- * ca extra certificates that can be added to bundle. Can be NULL
- * keyNID type of encryption to use on the key (-1 means no encryption)
- * certNID type of encryption to use on the certificate
- * itt number of iterations with encryption
- * macItt number of iterations with mac creation
- * keyType flag for signature and/or encryption key
- *
- * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail
- */
- WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, WOLFSSL_EVP_PKEY* pkey,
- WOLFSSL_X509* cert, WOLF_STACK_OF(WOLFSSL_X509)* ca, int keyNID,
- int certNID, int itt, int macItt, int keyType)
- {
- WC_PKCS12* pkcs12;
- WC_DerCertList* list = NULL;
- word32 passSz;
- byte* keyDer = NULL;
- word32 keyDerSz;
- byte* certDer;
- int certDerSz;
- WOLFSSL_ENTER("wolfSSL_PKCS12_create()");
- if (pass == NULL || pkey == NULL || cert == NULL) {
- WOLFSSL_LEAVE("wolfSSL_PKCS12_create()", BAD_FUNC_ARG);
- return NULL;
- }
- passSz = (word32)XSTRLEN(pass);
- keyDer = (byte*)pkey->pkey.ptr;
- keyDerSz = pkey->pkey_sz;
- certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz);
- if (certDer == NULL) {
- return NULL;
- }
- if (ca != NULL) {
- WC_DerCertList* cur;
- unsigned long numCerts = ca->num;
- byte* curDer;
- int curDerSz = 0;
- WOLFSSL_STACK* sk = ca;
- while (numCerts > 0 && sk != NULL) {
- cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL,
- DYNAMIC_TYPE_PKCS);
- if (cur == NULL) {
- wc_FreeCertList(list, NULL);
- return NULL;
- }
- curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz);
- if (curDer == NULL || curDerSz < 0) {
- XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
- wc_FreeCertList(list, NULL);
- return NULL;
- }
- cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS);
- if (cur->buffer == NULL) {
- XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
- wc_FreeCertList(list, NULL);
- return NULL;
- }
- XMEMCPY(cur->buffer, curDer, curDerSz);
- cur->bufferSz = curDerSz;
- cur->next = list;
- list = cur;
- sk = sk->next;
- numCerts--;
- }
- }
- pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz,
- certDer, certDerSz, list, keyNID, certNID, itt, macItt,
- keyType, NULL);
- if (ca != NULL) {
- wc_FreeCertList(list, NULL);
- }
- return pkcs12;
- }
- /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */
- int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
- WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert,
- WOLF_STACK_OF(WOLFSSL_X509)** ca)
- {
- void* heap = NULL;
- int ret;
- byte* certData = NULL;
- word32 certDataSz;
- byte* pk = NULL;
- word32 pkSz;
- WC_DerCertList* certList = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert *DeCert;
- #else
- DecodedCert DeCert[1];
- #endif
- WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
- /* make sure we init return args */
- if (pkey) *pkey = NULL;
- if (cert) *cert = NULL;
- if (ca) *ca = NULL;
- if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
- WOLFSSL_MSG("Bad argument value");
- return WOLFSSL_FAILURE;
- }
- heap = wc_PKCS12_GetHeap(pkcs12);
- if (ca == NULL) {
- ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
- NULL);
- }
- else {
- ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
- &certList);
- }
- if (ret < 0) {
- WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
- return WOLFSSL_FAILURE;
- }
- #ifdef WOLFSSL_SMALL_STACK
- DeCert = (DecodedCert *)XMALLOC(sizeof(*DeCert), heap,
- DYNAMIC_TYPE_DCERT);
- if (DeCert == NULL) {
- WOLFSSL_MSG("out of memory");
- return WOLFSSL_FAILURE;
- }
- #endif
- /* Decode cert and place in X509 stack struct */
- if (certList != NULL) {
- WC_DerCertList* current = certList;
- *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(
- sizeof(WOLF_STACK_OF(WOLFSSL_X509)), heap, DYNAMIC_TYPE_X509);
- if (*ca == NULL) {
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (certData != NULL) {
- XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL;
- }
- /* Free up WC_DerCertList and move on */
- while (current != NULL) {
- WC_DerCertList* next = current->next;
- XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- current = next;
- }
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509)));
- /* add list of DER certs as X509's to stack */
- while (current != NULL) {
- WC_DerCertList* toFree = current;
- WOLFSSL_X509* x509;
- x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
- DYNAMIC_TYPE_X509);
- InitX509(x509, 1, heap);
- InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap);
- if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
- WOLFSSL_MSG("Issue with parsing certificate");
- FreeDecodedCert(DeCert);
- wolfSSL_X509_free(x509);
- }
- else {
- if (CopyDecodedToX509(x509, DeCert) != 0) {
- WOLFSSL_MSG("Failed to copy decoded cert");
- FreeDecodedCert(DeCert);
- wolfSSL_X509_free(x509);
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (certData != NULL) {
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- }
- /* Free up WC_DerCertList */
- while (current != NULL) {
- WC_DerCertList* next = current->next;
- XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- current = next;
- }
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- FreeDecodedCert(DeCert);
- if (wolfSSL_sk_X509_push(*ca, x509) != 1) {
- WOLFSSL_MSG("Failed to push x509 onto stack");
- wolfSSL_X509_free(x509);
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (certData != NULL) {
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- }
- /* Free up WC_DerCertList */
- while (current != NULL) {
- WC_DerCertList* next = current->next;
- XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(current, heap, DYNAMIC_TYPE_PKCS);
- current = next;
- }
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- }
- current = current->next;
- XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS);
- XFREE(toFree, heap, DYNAMIC_TYPE_PKCS);
- }
- }
- /* Decode cert and place in X509 struct */
- if (certData != NULL) {
- *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
- DYNAMIC_TYPE_X509);
- if (*cert == NULL) {
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- InitX509(*cert, 1, heap);
- InitDecodedCert(DeCert, certData, certDataSz, heap);
- if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
- WOLFSSL_MSG("Issue with parsing certificate");
- }
- if (CopyDecodedToX509(*cert, DeCert) != 0) {
- WOLFSSL_MSG("Failed to copy decoded cert");
- FreeDecodedCert(DeCert);
- if (pk != NULL) {
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- wolfSSL_X509_free(*cert); *cert = NULL;
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- FreeDecodedCert(DeCert);
- XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
- }
- /* get key type */
- ret = BAD_STATE_E;
- if (pk != NULL) { /* decode key if present */
- *pkey = wolfSSL_EVP_PKEY_new_ex(heap);
- if (*pkey == NULL) {
- wolfSSL_X509_free(*cert); *cert = NULL;
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- #ifndef NO_RSA
- {
- const unsigned char* pt = pk;
- if (wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, pkey, &pt, pkSz) !=
- NULL) {
- ret = 0;
- }
- }
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- if (ret != 0) { /* if is in fail state check if ECC key */
- const unsigned char* pt = pk;
- if (wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, pkey, &pt, pkSz) !=
- NULL) {
- ret = 0;
- }
- }
- #endif /* HAVE_ECC */
- if (pk != NULL)
- XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
- if (ret != 0) { /* if is in fail state and no PKEY then fail */
- wolfSSL_X509_free(*cert); *cert = NULL;
- if (ca != NULL) {
- wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
- }
- wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
- WOLFSSL_MSG("Bad PKCS12 key format");
- ret = WOLFSSL_FAILURE;
- goto out;
- }
- if (pkey != NULL && *pkey != NULL) {
- (*pkey)->save_type = 0;
- }
- }
- (void)ret;
- (void)ca;
- ret = WOLFSSL_SUCCESS;
- out:
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(DeCert, heap, DYNAMIC_TYPE_DCERT);
- #endif
- return ret;
- }
- int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw,
- int pswLen)
- {
- WOLFSSL_ENTER("wolfSSL_PKCS12_verify_mac");
- if (!pkcs12) {
- return WOLFSSL_FAILURE;
- }
- return wc_PKCS12_verify_ex(pkcs12, (const byte*)psw, pswLen) == 0 ?
- WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
- }
- #endif /* !NO_ASN && !NO_PWDBASED */
- #endif /* OPENSSL_EXTRA */
- #endif /* HAVE_PKCS12 */
- /*******************************************************************************
- * END OF PKCS12 APIs
- ******************************************************************************/
- #endif /* !NO_CERTS */
- /*******************************************************************************
- * BEGIN OPENSSL FIPS DRBG APIs
- ******************************************************************************/
- #if defined(OPENSSL_EXTRA) && !defined(WC_NO_RNG) && defined(HAVE_HASHDRBG)
- int wolfSSL_FIPS_drbg_init(WOLFSSL_DRBG_CTX *ctx, int type, unsigned int flags)
- {
- int ret = WOLFSSL_FAILURE;
- if (ctx != NULL) {
- XMEMSET(ctx, 0, sizeof(WOLFSSL_DRBG_CTX));
- ctx->type = type;
- ctx->xflags = flags;
- ctx->status = DRBG_STATUS_UNINITIALISED;
- ret = WOLFSSL_SUCCESS;
- }
- return ret;
- }
- WOLFSSL_DRBG_CTX* wolfSSL_FIPS_drbg_new(int type, unsigned int flags)
- {
- int ret = WOLFSSL_FAILURE;
- WOLFSSL_DRBG_CTX* ctx = (WOLFSSL_DRBG_CTX*)XMALLOC(sizeof(WOLFSSL_DRBG_CTX),
- NULL, DYNAMIC_TYPE_OPENSSL);
- ret = wolfSSL_FIPS_drbg_init(ctx, type, flags);
- if (ret == WOLFSSL_SUCCESS && type != 0) {
- ret = wolfSSL_FIPS_drbg_instantiate(ctx, NULL, 0);
- }
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_ERROR(ret);
- wolfSSL_FIPS_drbg_free(ctx);
- ctx = NULL;
- }
- return ctx;
- }
- int wolfSSL_FIPS_drbg_instantiate(WOLFSSL_DRBG_CTX* ctx,
- const unsigned char* pers, size_t perslen)
- {
- int ret = WOLFSSL_FAILURE;
- if (ctx != NULL && ctx->rng == NULL) {
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS) && FIPS_VERSION_GE(5,0)))
- ctx->rng = wc_rng_new((byte*)pers, (word32)perslen, NULL);
- #else
- ctx->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (ctx->rng != NULL) {
- #if defined(HAVE_FIPS) && FIPS_VERSION_GE(2,0)
- ret = wc_InitRngNonce(ctx->rng, (byte*)pers, (word32)perslen);
- #else
- ret = wc_InitRng(ctx->rng);
- (void)pers;
- (void)perslen;
- #endif
- if (ret != 0) {
- WOLFSSL_ERROR(ret);
- XFREE(ctx->rng, NULL, DYNAMIC_TYPE_RNG);
- ctx->rng = NULL;
- }
- }
- #endif
- }
- if (ctx != NULL && ctx->rng != NULL) {
- ctx->status = DRBG_STATUS_READY;
- ret = WOLFSSL_SUCCESS;
- }
- return ret;
- }
- int wolfSSL_FIPS_drbg_set_callbacks(WOLFSSL_DRBG_CTX* ctx,
- drbg_entropy_get entropy_get, drbg_entropy_clean entropy_clean,
- size_t entropy_blocklen,
- drbg_nonce_get none_get, drbg_nonce_clean nonce_clean)
- {
- int ret = WOLFSSL_FAILURE;
- if (ctx != NULL) {
- ctx->entropy_get = entropy_get;
- ctx->entropy_clean = entropy_clean;
- ctx->entropy_blocklen = entropy_blocklen;
- ctx->none_get = none_get;
- ctx->nonce_clean = nonce_clean;
- ret = WOLFSSL_SUCCESS;
- }
- return ret;
- }
- void wolfSSL_FIPS_rand_add(const void* buf, int num, double entropy)
- {
- /* not implemented */
- (void)buf;
- (void)num;
- (void)entropy;
- }
- int wolfSSL_FIPS_drbg_reseed(WOLFSSL_DRBG_CTX* ctx, const unsigned char* adin,
- size_t adinlen)
- {
- int ret = WOLFSSL_FAILURE;
- if (ctx != NULL && ctx->rng != NULL) {
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS) && FIPS_VERSION_GE(2,0)))
- if (wc_RNG_DRBG_Reseed(ctx->rng, adin, (word32)adinlen) == 0) {
- ret = WOLFSSL_SUCCESS;
- }
- #else
- ret = WOLFSSL_SUCCESS;
- (void)adin;
- (void)adinlen;
- #endif
- }
- return ret;
- }
- int wolfSSL_FIPS_drbg_generate(WOLFSSL_DRBG_CTX* ctx, unsigned char* out,
- size_t outlen, int prediction_resistance, const unsigned char* adin,
- size_t adinlen)
- {
- int ret = WOLFSSL_FAILURE;
- if (ctx != NULL && ctx->rng != NULL) {
- ret = wc_RNG_GenerateBlock(ctx->rng, out, (word32)outlen);
- if (ret == 0) {
- ret = WOLFSSL_SUCCESS;
- }
- }
- (void)prediction_resistance;
- (void)adin;
- (void)adinlen;
- return ret;
- }
- int wolfSSL_FIPS_drbg_uninstantiate(WOLFSSL_DRBG_CTX *ctx)
- {
- if (ctx != NULL && ctx->rng != NULL) {
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
- (defined(HAVE_FIPS) && FIPS_VERSION_GE(5,0)))
- wc_rng_free(ctx->rng);
- #else
- wc_FreeRng(ctx->rng);
- XFREE(ctx->rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
- ctx->rng = NULL;
- ctx->status = DRBG_STATUS_UNINITIALISED;
- }
- return WOLFSSL_SUCCESS;
- }
- void wolfSSL_FIPS_drbg_free(WOLFSSL_DRBG_CTX *ctx)
- {
- if (ctx != NULL) {
- /* As saftey check if free'ing the default drbg, then mark global NULL.
- * Technically the user should not call free on the default drbg. */
- if (ctx == gDrbgDefCtx) {
- gDrbgDefCtx = NULL;
- }
- wolfSSL_FIPS_drbg_uninstantiate(ctx);
- XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
- WOLFSSL_DRBG_CTX* wolfSSL_FIPS_get_default_drbg(void)
- {
- if (gDrbgDefCtx == NULL) {
- gDrbgDefCtx = wolfSSL_FIPS_drbg_new(0, 0);
- }
- return gDrbgDefCtx;
- }
- void wolfSSL_FIPS_get_timevec(unsigned char* buf, unsigned long* pctr)
- {
- /* not implemented */
- (void)buf;
- (void)pctr;
- }
- void* wolfSSL_FIPS_drbg_get_app_data(WOLFSSL_DRBG_CTX *ctx)
- {
- if (ctx != NULL) {
- return ctx->app_data;
- }
- return NULL;
- }
- void wolfSSL_FIPS_drbg_set_app_data(WOLFSSL_DRBG_CTX *ctx, void *app_data)
- {
- if (ctx != NULL) {
- ctx->app_data = app_data;
- }
- }
- #endif
- /*******************************************************************************
- * END OF OPENSSL FIPS DRBG APIs
- ******************************************************************************/
- #endif /* !WOLFCRYPT_ONLY */
- /*******************************************************************************
- * START OF CRYPTO-ONLY APIs
- ******************************************************************************/
- #if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
- defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
- defined(WOLFSSL_HAPROXY)
- #ifndef NO_SHA
- /* One shot SHA1 hash of message.
- *
- * d message to hash
- * n size of d buffer
- * md buffer to hold digest. Should be SHA_DIGEST_SIZE.
- *
- * Note: if md is null then a static buffer of SHA_DIGEST_SIZE is used.
- * When the static buffer is used this function is not thread safe.
- *
- * Returns a pointer to the message digest on success and NULL on failure.
- */
- unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n,
- unsigned char *md)
- {
- static byte dig[WC_SHA_DIGEST_SIZE];
- byte* ret = md;
- wc_Sha sha;
- WOLFSSL_ENTER("wolfSSL_SHA1");
- if (wc_InitSha_ex(&sha, NULL, INVALID_DEVID) != 0) {
- WOLFSSL_MSG("SHA1 Init failed");
- return NULL;
- }
- if (wc_ShaUpdate(&sha, (const byte*)d, (word32)n) != 0) {
- WOLFSSL_MSG("SHA1 Update failed");
- return NULL;
- }
- if (md == NULL) {
- WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA1 IS NOT "
- "THREAD SAFE WHEN md == NULL");
- ret = dig;
- }
- if (wc_ShaFinal(&sha, ret) != 0) {
- WOLFSSL_MSG("SHA1 Final failed");
- wc_ShaFree(&sha);
- return NULL;
- }
- wc_ShaFree(&sha);
- return ret;
- }
- #endif /* ! NO_SHA */
- #ifdef WOLFSSL_SHA224
- /* One shot SHA224 hash of message.
- *
- * d message to hash
- * n size of d buffer
- * md buffer to hold digest. Should be WC_SHA224_DIGEST_SIZE.
- *
- * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
- * When the static buffer is used this function is not thread safe.
- *
- * Returns a pointer to the message digest on success and NULL on failure.
- */
- unsigned char *wolfSSL_SHA224(const unsigned char *d, size_t n,
- unsigned char *md)
- {
- static byte dig[WC_SHA224_DIGEST_SIZE];
- byte* ret = md;
- wc_Sha256 sha;
- WOLFSSL_ENTER("wolfSSL_SHA224");
- if (wc_InitSha224_ex(&sha, NULL, INVALID_DEVID) != 0) {
- WOLFSSL_MSG("SHA224 Init failed");
- return NULL;
- }
- if (wc_Sha224Update(&sha, (const byte*)d, (word32)n) != 0) {
- WOLFSSL_MSG("SHA224 Update failed");
- return NULL;
- }
- if (md == NULL) {
- WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA224 IS NOT "
- "THREAD SAFE WHEN md == NULL");
- ret = dig;
- }
- if (wc_Sha224Final(&sha, ret) != 0) {
- WOLFSSL_MSG("SHA224 Final failed");
- wc_Sha224Free(&sha);
- return NULL;
- }
- wc_Sha224Free(&sha);
- return ret;
- }
- #endif
- #ifndef NO_SHA256
- /* One shot SHA256 hash of message.
- *
- * d message to hash
- * n size of d buffer
- * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
- *
- * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
- * When the static buffer is used this function is not thread safe.
- *
- * Returns a pointer to the message digest on success and NULL on failure.
- */
- unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n,
- unsigned char *md)
- {
- static byte dig[WC_SHA256_DIGEST_SIZE];
- byte* ret = md;
- wc_Sha256 sha;
- WOLFSSL_ENTER("wolfSSL_SHA256");
- if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) {
- WOLFSSL_MSG("SHA256 Init failed");
- return NULL;
- }
- if (wc_Sha256Update(&sha, (const byte*)d, (word32)n) != 0) {
- WOLFSSL_MSG("SHA256 Update failed");
- return NULL;
- }
- if (md == NULL) {
- WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA256 IS NOT "
- "THREAD SAFE WHEN md == NULL");
- ret = dig;
- }
- if (wc_Sha256Final(&sha, ret) != 0) {
- WOLFSSL_MSG("SHA256 Final failed");
- wc_Sha256Free(&sha);
- return NULL;
- }
- wc_Sha256Free(&sha);
- return ret;
- }
- #endif /* ! NO_SHA256 */
- #ifdef WOLFSSL_SHA384
- /* One shot SHA384 hash of message.
- *
- * d message to hash
- * n size of d buffer
- * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
- *
- * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
- * When the static buffer is used this function is not thread safe.
- *
- * Returns a pointer to the message digest on success and NULL on failure.
- */
- unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n,
- unsigned char *md)
- {
- static byte dig[WC_SHA384_DIGEST_SIZE];
- byte* ret = md;
- wc_Sha384 sha;
- WOLFSSL_ENTER("wolfSSL_SHA384");
- if (wc_InitSha384_ex(&sha, NULL, INVALID_DEVID) != 0) {
- WOLFSSL_MSG("SHA384 Init failed");
- return NULL;
- }
- if (wc_Sha384Update(&sha, (const byte*)d, (word32)n) != 0) {
- WOLFSSL_MSG("SHA384 Update failed");
- return NULL;
- }
- if (md == NULL) {
- WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA384 IS NOT "
- "THREAD SAFE WHEN md == NULL");
- ret = dig;
- }
- if (wc_Sha384Final(&sha, ret) != 0) {
- WOLFSSL_MSG("SHA384 Final failed");
- wc_Sha384Free(&sha);
- return NULL;
- }
- wc_Sha384Free(&sha);
- return ret;
- }
- #endif /* WOLFSSL_SHA384 */
- #if defined(WOLFSSL_SHA512)
- /* One shot SHA512 hash of message.
- *
- * d message to hash
- * n size of d buffer
- * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
- *
- * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
- * When the static buffer is used this function is not thread safe.
- *
- * Returns a pointer to the message digest on success and NULL on failure.
- */
- unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n,
- unsigned char *md)
- {
- static byte dig[WC_SHA512_DIGEST_SIZE];
- byte* ret = md;
- wc_Sha512 sha;
- WOLFSSL_ENTER("wolfSSL_SHA512");
- if (wc_InitSha512_ex(&sha, NULL, INVALID_DEVID) != 0) {
- WOLFSSL_MSG("SHA512 Init failed");
- return NULL;
- }
- if (wc_Sha512Update(&sha, (const byte*)d, (word32)n) != 0) {
- WOLFSSL_MSG("SHA512 Update failed");
- return NULL;
- }
- if (md == NULL) {
- WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA512 IS NOT "
- "THREAD SAFE WHEN md == NULL");
- ret = dig;
- }
- if (wc_Sha512Final(&sha, ret) != 0) {
- WOLFSSL_MSG("SHA512 Final failed");
- wc_Sha512Free(&sha);
- return NULL;
- }
- wc_Sha512Free(&sha);
- return ret;
- }
- #endif /* WOLFSSL_SHA512 */
- #endif /* OPENSSL_EXTRA || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE ||
- * HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
- /*******************************************************************************
- * END OF CRYPTO-ONLY APIs
- ******************************************************************************/
|