1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981 |
- /* tls.c
- *
- * Copyright (C) 2006-2020 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>
- #ifndef WOLFCRYPT_ONLY
- #include <wolfssl/ssl.h>
- #include <wolfssl/internal.h>
- #include <wolfssl/error-ssl.h>
- #include <wolfssl/wolfcrypt/hmac.h>
- #ifdef NO_INLINE
- #include <wolfssl/wolfcrypt/misc.h>
- #else
- #define WOLFSSL_MISC_INCLUDED
- #include <wolfcrypt/src/misc.c>
- #endif
- #ifdef HAVE_CURVE25519
- #include <wolfssl/wolfcrypt/curve25519.h>
- #endif
- #ifdef HAVE_CURVE448
- #include <wolfssl/wolfcrypt/curve448.h>
- #endif
- #ifdef HAVE_NTRU
- #include "libntruencrypt/ntru_crypto.h"
- #include <wolfssl/wolfcrypt/random.h>
- #endif
- #ifdef HAVE_QSH
- static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key);
- static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name);
- #if defined(HAVE_NTRU)
- static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type);
- #endif
- #endif /* HAVE_QSH */
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
- static int TLSX_KeyShare_IsSupported(int namedGroup);
- #endif
- #ifdef HAVE_SUPPORTED_CURVES
- static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions);
- #endif
- #ifndef NO_TLS
- /* Digest enable checks */
- #ifdef NO_OLD_TLS /* TLS 1.2 only */
- #if defined(NO_SHA256) && !defined(WOLFSSL_SHA384) && \
- !defined(WOLFSSL_SHA512)
- #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2
- #endif
- #else /* TLS 1.1 or older */
- #if defined(NO_MD5) && defined(NO_SHA)
- #error Must have SHA1 and MD5 enabled for old TLS
- #endif
- #endif
- #ifdef WOLFSSL_TLS13
- #if !defined(NO_DH) && \
- !defined(HAVE_FFDHE_2048) && !defined(HAVE_FFDHE_3072) && \
- !defined(HAVE_FFDHE_4096) && !defined(HAVE_FFDHE_6144) && \
- !defined(HAVE_FFDHE_8192)
- #error Please configure your TLS 1.3 DH key size using either: HAVE_FFDHE_2048, HAVE_FFDHE_3072, HAVE_FFDHE_4096, HAVE_FFDHE_6144 or HAVE_FFDHE_8192
- #endif
- #if !defined(NO_RSA) && !defined(WC_RSA_PSS)
- #error The build option WC_RSA_PSS is required for TLS 1.3 with RSA
- #endif
- #ifndef HAVE_TLS_EXTENSIONS
- #ifndef _MSC_VER
- #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3"
- #else
- #pragma message("Error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3")
- #endif
- #endif
- #endif
- /* Warn if secrets logging is enabled */
- #if defined(SHOW_SECRETS) || defined(WOLFSSL_SSLKEYLOGFILE)
- #ifndef _MSC_VER
- #warning The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment
- #else
- #pragma message("Warning: The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment")
- #endif
- #endif
- /* Optional Pre-Master-Secret logging for Wireshark */
- #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE)
- #ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT
- #define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log"
- #endif
- #endif
- #ifndef WOLFSSL_NO_TLS12
- #ifdef WOLFSSL_SHA384
- #define HSHASH_SZ WC_SHA384_DIGEST_SIZE
- #else
- #define HSHASH_SZ FINISHED_SZ
- #endif
- #ifdef WOLFSSL_RENESAS_TSIP_TLS
-
- #if (WOLFSSL_RENESAS_TSIP_VER >=109)
- int tsip_generateMasterSecretEx(
- byte cipherSuiteFirst,
- byte cipherSuite,
- const byte* pr, /* pre-master */
- const byte* cr, /* client random */
- const byte* sr, /* server random */
- byte* ms);
- #elif (WOLFSSL_RENESAS_TSIP_VER >=106)
-
- int tsip_generateMasterSecret(
- const byte* pre,
- const byte* cr,
- const byte* sr,
- byte* ms);
-
- #endif
- int tsip_useable(const WOLFSSL *ssl);
- int tsip_generateSeesionKey(WOLFSSL *ssl);
- int tsip_generateVerifyData(
- const byte* ms,
- const byte* side,
- const byte* handshake_hash,
- byte* hashes);
- #endif /*WOLFSSL_RENESAS_TSIP_TLS*/
- int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen)
- {
- int ret = 0;
- word32 hashSz = FINISHED_SZ;
- if (ssl == NULL || hash == NULL || hashLen == NULL || *hashLen < HSHASH_SZ)
- return BAD_FUNC_ARG;
- /* for constant timing perform these even if error */
- #ifndef NO_OLD_TLS
- ret |= wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash);
- ret |= wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]);
- #endif
- if (IsAtLeastTLSv1_2(ssl)) {
- #ifndef NO_SHA256
- if (ssl->specs.mac_algorithm <= sha256_mac ||
- ssl->specs.mac_algorithm == blake2b_mac) {
- ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
- hashSz = WC_SHA256_DIGEST_SIZE;
- }
- #endif
- #ifdef WOLFSSL_SHA384
- if (ssl->specs.mac_algorithm == sha384_mac) {
- ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
- hashSz = WC_SHA384_DIGEST_SIZE;
- }
- #endif
- }
- *hashLen = hashSz;
- if (ret != 0)
- ret = BUILD_MSG_ERROR;
- return ret;
- }
- int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
- {
- int ret;
- const byte* side;
- word32 hashSz = HSHASH_SZ;
- #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
- DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap);
- if (handshake_hash == NULL)
- return MEMORY_E;
- #else
- byte handshake_hash[HSHASH_SZ];
- #endif
- ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
- if (ret == 0) {
- if (XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
- side = tls_client;
- else
- side = tls_server;
- #ifdef WOLFSSL_HAVE_PRF
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
- !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
- if (tsip_useable(ssl)) {
- ret = tsip_generateVerifyData(ssl->arrays->tsip_masterSecret,
- side, handshake_hash, (byte*)hashes /* out */);
- } else
- #endif
- ret = wc_PRF_TLS((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret,
- SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz,
- IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
- ssl->heap, ssl->devId);
- #else
- /* Pseudo random function must be enabled in the configuration. */
- ret = PRF_MISSING;
- WOLFSSL_MSG("Pseudo-random function is not enabled");
- (void)side;
- (void)hashes;
- #endif
- }
- #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
- FREE_VAR(handshake_hash, ssl->heap);
- #endif
- return ret;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_TLSV10
- ProtocolVersion MakeTLSv1(void)
- {
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_MINOR;
- return pv;
- }
- #endif /* WOLFSSL_ALLOW_TLSV10 */
- ProtocolVersion MakeTLSv1_1(void)
- {
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_1_MINOR;
- return pv;
- }
- #endif /* !NO_OLD_TLS */
- #ifndef WOLFSSL_NO_TLS12
- ProtocolVersion MakeTLSv1_2(void)
- {
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_2_MINOR;
- return pv;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- #ifdef WOLFSSL_TLS13
- /* The TLS v1.3 protocol version.
- *
- * returns the protocol version data for TLS v1.3.
- */
- ProtocolVersion MakeTLSv1_3(void)
- {
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_3_MINOR;
- return pv;
- }
- #endif
- #ifndef WOLFSSL_NO_TLS12
- #ifdef HAVE_EXTENDED_MASTER
- static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] =
- "extended master secret";
- #endif
- static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
- static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion";
- static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
- const byte* ms, word32 msLen,
- const byte* sr, const byte* cr,
- int tls1_2, int hash_type,
- void* heap, int devId)
- {
- int ret;
- #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
- DECLARE_VAR(seed, byte, SEED_LEN, heap);
- if (seed == NULL)
- return MEMORY_E;
- #else
- byte seed[SEED_LEN];
- #endif
- XMEMCPY(seed, sr, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, cr, RAN_LEN);
- #ifdef WOLFSSL_HAVE_PRF
- ret = wc_PRF_TLS(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ,
- seed, SEED_LEN, tls1_2, hash_type, heap, devId);
- #else
- /* Pseudo random function must be enabled in the configuration. */
- ret = PRF_MISSING;
- WOLFSSL_MSG("Pseudo-random function is not enabled");
- (void)key_dig;
- (void)key_dig_len;
- (void)ms;
- (void)msLen;
- (void)tls1_2;
- (void)hash_type;
- (void)heap;
- (void)devId;
- (void)key_label;
- (void)master_label;
- #ifdef HAVE_EXTENDED_MASTER
- (void)ext_master_label;
- #endif
- #endif
- #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
- FREE_VAR(seed, heap);
- #endif
- return ret;
- }
- /* External facing wrapper so user can call as well, 0 on success */
- int wolfSSL_DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
- const byte* ms, word32 msLen,
- const byte* sr, const byte* cr,
- int tls1_2, int hash_type)
- {
- return _DeriveTlsKeys(key_dig, key_dig_len, ms, msLen, sr, cr, tls1_2,
- hash_type, NULL, INVALID_DEVID);
- }
- int DeriveTlsKeys(WOLFSSL* ssl)
- {
- int ret;
- int key_dig_len = 2 * ssl->specs.hash_size +
- 2 * ssl->specs.key_size +
- 2 * ssl->specs.iv_size;
- #ifdef WOLFSSL_SMALL_STACK
- byte* key_dig;
- #else
- byte key_dig[MAX_PRF_DIG];
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST);
- if (key_dig == NULL) {
- return MEMORY_E;
- }
- #endif
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
- !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
- if (tsip_useable(ssl))
- ret = tsip_generateSeesionKey(ssl);
- else {
- #endif
- ret = _DeriveTlsKeys(key_dig, key_dig_len,
- ssl->arrays->masterSecret, SECRET_LEN,
- ssl->arrays->serverRandom, ssl->arrays->clientRandom,
- IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
- ssl->heap, ssl->devId);
- if (ret == 0)
- ret = StoreKeys(ssl, key_dig, PROVISION_CLIENT_SERVER);
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
- !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
- }
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
- #endif
- return ret;
- }
- static int _MakeTlsMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* cr, const byte* sr,
- int tls1_2, int hash_type,
- void* heap, int devId)
- {
- int ret;
- #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
- DECLARE_VAR(seed, byte, SEED_LEN, heap);
- if (seed == NULL)
- return MEMORY_E;
- #else
- byte seed[SEED_LEN];
- #endif
- XMEMCPY(seed, cr, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, sr, RAN_LEN);
- #ifdef WOLFSSL_HAVE_PRF
- ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ,
- seed, SEED_LEN, tls1_2, hash_type, heap, devId);
- #else
- /* Pseudo random function must be enabled in the configuration. */
- ret = PRF_MISSING;
- WOLFSSL_MSG("Pseudo-random function is not enabled");
- (void)ms;
- (void)msLen;
- (void)pms;
- (void)pmsLen;
- (void)tls1_2;
- (void)hash_type;
- (void)heap;
- (void)devId;
- #endif
- #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
- FREE_VAR(seed, heap);
- #endif
- return ret;
- }
- /* External facing wrapper so user can call as well, 0 on success */
- int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* cr, const byte* sr,
- int tls1_2, int hash_type)
- {
- return _MakeTlsMasterSecret(ms, msLen, pms, pmsLen, cr, sr, tls1_2,
- hash_type, NULL, INVALID_DEVID);
- }
- #ifdef HAVE_EXTENDED_MASTER
- static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* sHash, word32 sHashLen,
- int tls1_2, int hash_type,
- void* heap, int devId)
- {
- int ret;
- #ifdef WOLFSSL_HAVE_PRF
- ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ,
- sHash, sHashLen, tls1_2, hash_type, heap, devId);
- #else
- /* Pseudo random function must be enabled in the configuration. */
- ret = PRF_MISSING;
- WOLFSSL_MSG("Pseudo-random function is not enabled");
- (void)ms;
- (void)msLen;
- (void)pms;
- (void)pmsLen;
- (void)sHash;
- (void)sHashLen;
- (void)tls1_2;
- (void)hash_type;
- (void)heap;
- (void)devId;
- #endif
- return ret;
- }
- /* External facing wrapper so user can call as well, 0 on success */
- int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* sHash, word32 sHashLen,
- int tls1_2, int hash_type)
- {
- return _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen,
- tls1_2, hash_type, NULL, INVALID_DEVID);
- }
- #endif /* HAVE_EXTENDED_MASTER */
- int MakeTlsMasterSecret(WOLFSSL* ssl)
- {
- int ret;
- #ifdef HAVE_EXTENDED_MASTER
- if (ssl->options.haveEMS) {
- word32 hashSz = HSHASH_SZ;
- #ifdef WOLFSSL_SMALL_STACK
- byte* handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap,
- DYNAMIC_TYPE_DIGEST);
- if (handshake_hash == NULL)
- return MEMORY_E;
- #else
- byte handshake_hash[HSHASH_SZ];
- #endif
- ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
- if (ret == 0) {
- ret = _MakeTlsExtendedMasterSecret(
- ssl->arrays->masterSecret, SECRET_LEN,
- ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
- handshake_hash, hashSz,
- IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
- ssl->heap, ssl->devId);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST);
- #endif
- }
- else
- #endif /* HAVE_EXTENDED_MASTER */
- {
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
- !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
- if (tsip_useable(ssl)) {
-
- #if (WOLFSSL_RENESAS_TSIP_VER>=109)
- ret = tsip_generateMasterSecretEx(
- ssl->options.cipherSuite0,
- ssl->options.cipherSuite,
- &ssl->arrays->preMasterSecret[VERSION_SZ],
- ssl->arrays->clientRandom,
- ssl->arrays->serverRandom,
- ssl->arrays->tsip_masterSecret);
-
- #elif (WOLFSSL_RENESAS_TSIP_VER>=106)
- ret = tsip_generateMasterSecret(
- &ssl->arrays->preMasterSecret[VERSION_SZ],
- ssl->arrays->clientRandom,
- ssl->arrays->serverRandom,
- ssl->arrays->tsip_masterSecret);
- #else
- ret = NOT_COMPILED_IN;
- #endif
- } else
- #endif
- ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN,
- ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
- ssl->arrays->clientRandom, ssl->arrays->serverRandom,
- IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
- ssl->heap, ssl->devId);
- }
- if (ret == 0) {
- #ifdef SHOW_SECRETS
- /* Wireshark Pre-Master-Secret Format:
- * CLIENT_RANDOM <clientrandom> <mastersecret>
- */
- const char* CLIENT_RANDOM_LABEL = "CLIENT_RANDOM";
- int i, pmsPos = 0;
- char pmsBuf[13 + 1 + 64 + 1 + 96 + 1 + 1];
- XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ",
- CLIENT_RANDOM_LABEL);
- pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1;
- for (i = 0; i < RAN_LEN; i++) {
- XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x",
- ssl->arrays->clientRandom[i]);
- pmsPos += 2;
- }
- XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, " ");
- pmsPos += 1;
- for (i = 0; i < SECRET_LEN; i++) {
- XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x",
- ssl->arrays->masterSecret[i]);
- pmsPos += 2;
- }
- XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "\n");
- pmsPos += 1;
- /* print master secret */
- puts(pmsBuf);
- #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE)
- {
- FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a");
- if (f != XBADFILE) {
- XFWRITE(pmsBuf, 1, pmsPos, f);
- XFCLOSE(f);
- }
- }
- #endif
- #endif /* SHOW_SECRETS */
- ret = DeriveTlsKeys(ssl);
- }
- return ret;
- }
- /* Used by EAP-TLS and EAP-TTLS to derive keying material from
- * the master_secret. */
- int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len,
- const char* label)
- {
- int ret;
- #ifdef WOLFSSL_SMALL_STACK
- byte* seed;
- #else
- byte seed[SEED_LEN];
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- seed = (byte*)XMALLOC(SEED_LEN, ssl->heap, DYNAMIC_TYPE_SEED);
- if (seed == NULL)
- return MEMORY_E;
- #endif
- /*
- * As per RFC-5281, the order of the client and server randoms is reversed
- * from that used by the TLS protocol to derive keys.
- */
- XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
- #ifdef WOLFSSL_HAVE_PRF
- ret = wc_PRF_TLS((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN,
- (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN,
- IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
- ssl->heap, ssl->devId);
- #else
- /* Pseudo random function must be enabled in the configuration. */
- ret = PRF_MISSING;
- WOLFSSL_MSG("Pseudo-random function is not enabled");
- (void)msk;
- (void)len;
- (void)label;
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED);
- #endif
- return ret;
- }
- /* return HMAC digest type in wolfSSL format */
- int wolfSSL_GetHmacType(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- switch (ssl->specs.mac_algorithm) {
- #ifndef NO_MD5
- case md5_mac:
- {
- return WC_MD5;
- }
- #endif
- #ifndef NO_SHA256
- case sha256_mac:
- {
- return WC_SHA256;
- }
- #endif
- #ifdef WOLFSSL_SHA384
- case sha384_mac:
- {
- return WC_SHA384;
- }
- #endif
- #ifndef NO_SHA
- case sha_mac:
- {
- return WC_SHA;
- }
- #endif
- #ifdef HAVE_BLAKE2
- case blake2b_mac:
- {
- return BLAKE2B_ID;
- }
- #endif
- default:
- {
- return WOLFSSL_FATAL_ERROR;
- }
- }
- }
- int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content,
- int verify)
- {
- if (ssl == NULL || inner == NULL)
- return BAD_FUNC_ARG;
- XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ);
- WriteSEQ(ssl, verify, inner);
- inner[SEQ_SZ] = (byte)content;
- inner[SEQ_SZ + ENUM_LEN] = ssl->version.major;
- inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor;
- c16toa((word16)sz, inner + SEQ_SZ + ENUM_LEN + VERSION_SZ);
- return 0;
- }
- #ifndef WOLFSSL_AEAD_ONLY
- #if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
- !defined(HAVE_SELFTEST)
- /* Update the hash in the HMAC.
- *
- * hmac HMAC object.
- * data Data to be hashed.
- * sz Size of data to hash.
- * returns 0 on success, otherwise failure.
- */
- static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz)
- {
- int ret = BAD_FUNC_ARG;
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- ret = wc_ShaUpdate(&hmac->hash.sha, data, sz);
- break;
- #endif /* !NO_SHA */
- #ifndef NO_SHA256
- case WC_SHA256:
- ret = wc_Sha256Update(&hmac->hash.sha256, data, sz);
- break;
- #endif /* !NO_SHA256 */
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- ret = wc_Sha384Update(&hmac->hash.sha384, data, sz);
- break;
- #endif /* WOLFSSL_SHA384 */
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- ret = wc_Sha512Update(&hmac->hash.sha512, data, sz);
- break;
- #endif /* WOLFSSL_SHA512 */
- }
- return ret;
- }
- /* Finalize the hash but don't put the EOC, padding or length in.
- *
- * hmac HMAC object.
- * hash Hash result.
- * returns 0 on success, otherwise failure.
- */
- static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash)
- {
- int ret = BAD_FUNC_ARG;
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- ret = wc_ShaFinalRaw(&hmac->hash.sha, hash);
- break;
- #endif /* !NO_SHA */
- #ifndef NO_SHA256
- case WC_SHA256:
- ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hash);
- break;
- #endif /* !NO_SHA256 */
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- ret = wc_Sha384FinalRaw(&hmac->hash.sha384, hash);
- break;
- #endif /* WOLFSSL_SHA384 */
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash);
- break;
- #endif /* WOLFSSL_SHA512 */
- }
- return ret;
- }
- /* Finalize the HMAC by performing outer hash.
- *
- * hmac HMAC object.
- * mac MAC result.
- * returns 0 on success, otherwise failure.
- */
- static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac)
- {
- int ret = BAD_FUNC_ARG;
- wc_HashAlg hash;
- enum wc_HashType hashType = (enum wc_HashType)hmac->macType;
- int digestSz = wc_HashGetDigestSize(hashType);
- int blockSz = wc_HashGetBlockSize(hashType);
- if ((digestSz >= 0) && (blockSz >= 0)) {
- ret = wc_HashInit(&hash, hashType);
- }
- if (ret == 0) {
- ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->opad,
- blockSz);
- if (ret == 0)
- ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->innerHash,
- digestSz);
- if (ret == 0)
- ret = wc_HashFinal(&hash, hashType, mac);
- wc_HashFree(&hash, hashType);
- }
- return ret;
- }
- /* Calculate the HMAC of the header + message data.
- * Constant time implementation using wc_Sha*FinalRaw().
- *
- * hmac HMAC object.
- * digest MAC result.
- * in Message data.
- * sz Size of the message data.
- * header Constructed record header with length of handshake data.
- * returns 0 on success, otherwise failure.
- */
- static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in,
- word32 sz, byte* header)
- {
- byte lenBytes[8];
- int i, j, k;
- int blockBits, blockMask;
- int lastBlockLen, macLen, extraLen, eocIndex;
- int blocks, safeBlocks, lenBlock, eocBlock;
- int maxLen;
- int blockSz, padSz;
- int ret;
- word32 realLen;
- byte extraBlock;
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- blockSz = WC_SHA_BLOCK_SIZE;
- blockBits = 6;
- macLen = WC_SHA_DIGEST_SIZE;
- padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA */
- #ifndef NO_SHA256
- case WC_SHA256:
- blockSz = WC_SHA256_BLOCK_SIZE;
- blockBits = 6;
- macLen = WC_SHA256_DIGEST_SIZE;
- padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA256 */
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- blockSz = WC_SHA384_BLOCK_SIZE;
- blockBits = 7;
- macLen = WC_SHA384_DIGEST_SIZE;
- padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA384 */
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- blockSz = WC_SHA512_BLOCK_SIZE;
- blockBits = 7;
- macLen = WC_SHA512_DIGEST_SIZE;
- padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA512 */
- default:
- return BAD_FUNC_ARG;
- }
- blockMask = blockSz - 1;
- /* Size of data to HMAC if padding length byte is zero. */
- maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - macLen;
- /* Complete data (including padding) has block for EOC and/or length. */
- extraBlock = ctSetLTE((maxLen + padSz) & blockMask, padSz);
- /* Total number of blocks for data including padding. */
- blocks = ((maxLen + blockSz - 1) >> blockBits) + extraBlock;
- /* Up to last 6 blocks can be hashed safely. */
- safeBlocks = blocks - 6;
- /* Length of message data. */
- realLen = maxLen - in[sz - 1];
- /* Number of message bytes in last block. */
- lastBlockLen = realLen & blockMask;
- /* Number of padding bytes in last block. */
- extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1;
- /* Number of blocks to create for hash. */
- lenBlock = (realLen + extraLen) >> blockBits;
- /* Block containing EOC byte. */
- eocBlock = realLen >> blockBits;
- /* Index of EOC byte in block. */
- eocIndex = realLen & blockMask;
- /* Add length of hmac's ipad to total length. */
- realLen += blockSz;
- /* Length as bits - 8 bytes bigendian. */
- c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes);
- c32toa(realLen << 3, lenBytes + sizeof(word32));
- ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, blockSz);
- if (ret != 0)
- return ret;
- XMEMSET(hmac->innerHash, 0, macLen);
- if (safeBlocks > 0) {
- ret = Hmac_HashUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
- if (ret != 0)
- return ret;
- ret = Hmac_HashUpdate(hmac, in, safeBlocks * blockSz -
- WOLFSSL_TLS_HMAC_INNER_SZ);
- if (ret != 0)
- return ret;
- }
- else
- safeBlocks = 0;
- XMEMSET(digest, 0, macLen);
- k = safeBlocks * blockSz;
- for (i = safeBlocks; i < blocks; i++) {
- unsigned char hashBlock[WC_MAX_BLOCK_SIZE];
- unsigned char isEocBlock = ctMaskEq(i, eocBlock);
- unsigned char isOutBlock = ctMaskEq(i, lenBlock);
- for (j = 0; j < blockSz; j++, k++) {
- unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock;
- unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock;
- unsigned char b = 0;
- if (k < WOLFSSL_TLS_HMAC_INNER_SZ)
- b = header[k];
- else if (k < maxLen)
- b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ];
- b = ctMaskSel(atEoc, 0x80, b);
- b &= (unsigned char)~(word32)pastEoc;
- b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock;
- if (j >= blockSz - 8) {
- b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b);
- }
- hashBlock[j] = b;
- }
- ret = Hmac_HashUpdate(hmac, hashBlock, blockSz);
- if (ret != 0)
- return ret;
- ret = Hmac_HashFinalRaw(hmac, hashBlock);
- if (ret != 0)
- return ret;
- for (j = 0; j < macLen; j++)
- ((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock;
- }
- ret = Hmac_OuterHash(hmac, digest);
- return ret;
- }
- #endif
- #if defined(WOLFSSL_NO_HASH_RAW) || defined(HAVE_FIPS) || \
- defined(HAVE_SELFTEST) || defined(HAVE_BLAKE2)
- /* Calculate the HMAC of the header + message data.
- * Constant time implementation using normal hashing operations.
- * Update-Final need to be constant time.
- *
- * hmac HMAC object.
- * digest MAC result.
- * in Message data.
- * sz Size of the message data.
- * header Constructed record header with length of handshake data.
- * returns 0 on success, otherwise failure.
- */
- static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in,
- word32 sz, byte* header)
- {
- byte dummy[WC_MAX_BLOCK_SIZE] = {0};
- int ret;
- word32 msgSz, blockSz, macSz, padSz, maxSz, realSz;
- word32 currSz, offset = 0;
- int msgBlocks, blocks, blockBits;
- int i;
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- blockSz = WC_SHA_BLOCK_SIZE;
- blockBits = 6;
- macSz = WC_SHA_DIGEST_SIZE;
- padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA */
- #ifndef NO_SHA256
- case WC_SHA256:
- blockSz = WC_SHA256_BLOCK_SIZE;
- blockBits = 6;
- macSz = WC_SHA256_DIGEST_SIZE;
- padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA256 */
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- blockSz = WC_SHA384_BLOCK_SIZE;
- blockBits = 7;
- macSz = WC_SHA384_DIGEST_SIZE;
- padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA384 */
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- blockSz = WC_SHA512_BLOCK_SIZE;
- blockBits = 7;
- macSz = WC_SHA512_DIGEST_SIZE;
- padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA512 */
- #ifdef HAVE_BLAKE2
- case WC_HASH_TYPE_BLAKE2B:
- blockSz = BLAKE2B_BLOCKBYTES;
- blockBits = 7;
- macSz = BLAKE2B_256;
- padSz = 0;
- break;
- #endif /* HAVE_BLAK2 */
- default:
- return BAD_FUNC_ARG;
- }
- msgSz = sz - (1 + in[sz - 1] + macSz);
- /* Make negative result 0 */
- msgSz &= ~(0 - (msgSz >> 31));
- realSz = WOLFSSL_TLS_HMAC_INNER_SZ + msgSz;
- maxSz = WOLFSSL_TLS_HMAC_INNER_SZ + (sz - 1) - macSz;
- /* Calculate #blocks processed in HMAC for max and real data. */
- blocks = maxSz >> blockBits;
- blocks += ((maxSz + padSz) % blockSz) < padSz;
- msgBlocks = realSz >> blockBits;
- /* #Extra blocks to process. */
- blocks -= msgBlocks + (((realSz + padSz) % blockSz) < padSz);
- /* Calculate whole blocks. */
- msgBlocks--;
- ret = wc_HmacUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
- if (ret == 0) {
- /* Fill the rest of the block with any available data. */
- currSz = ctMaskLT(msgSz, blockSz) & msgSz;
- currSz |= ctMaskGTE(msgSz, blockSz) & blockSz;
- currSz -= WOLFSSL_TLS_HMAC_INNER_SZ;
- currSz &= ~(0 - (currSz >> 31));
- ret = wc_HmacUpdate(hmac, in, currSz);
- offset = currSz;
- }
- if (ret == 0) {
- /* Do the hash operations on a block basis. */
- for (i = 0; i < msgBlocks; i++, offset += blockSz) {
- ret = wc_HmacUpdate(hmac, in + offset, blockSz);
- if (ret != 0)
- break;
- }
- }
- if (ret == 0)
- ret = wc_HmacUpdate(hmac, in + offset, msgSz - offset);
- if (ret == 0)
- ret = wc_HmacFinal(hmac, digest);
- if (ret == 0) {
- /* Do the dummy hash operations. Do at least one. */
- for (i = 0; i < blocks + 1; i++) {
- ret = wc_HmacUpdate(hmac, dummy, blockSz);
- if (ret != 0)
- break;
- }
- }
- return ret;
- }
- #endif
- int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
- int content, int verify, int epochOrder)
- {
- Hmac hmac;
- byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
- int ret = 0;
- const byte* macSecret = NULL;
- word32 hashSz = 0;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- #ifdef HAVE_TRUNCATED_HMAC
- hashSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
- : ssl->specs.hash_size;
- #else
- hashSz = ssl->specs.hash_size;
- #endif
- #ifdef HAVE_FUZZER
- /* Fuzz "in" buffer with sz to be used in HMAC algorithm */
- if (ssl->fuzzerCb) {
- if (verify && padSz >= 0) {
- ssl->fuzzerCb(ssl, in, sz + hashSz + padSz + 1, FUZZ_HMAC,
- ssl->fuzzerCtx);
- }
- else {
- ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
- }
- }
- #endif
- if (!ssl->options.dtls)
- wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify);
- else
- wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, epochOrder);
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
- !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
- if (tsip_useable(ssl)) {
- if (ssl->specs.hash_size == WC_SHA_DIGEST_SIZE)
- ret = tsip_Sha1Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ,
- in, sz, digest, verify);
- else if (ssl->specs.hash_size == WC_SHA256_DIGEST_SIZE)
- ret = tsip_Sha256Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ,
- in, sz, digest, verify);
- else
- ret = TSIP_MAC_DIGSZ_E;
- return ret;
- }
- #endif
- ret = wc_HmacInit(&hmac, ssl->heap, ssl->devId);
- if (ret != 0)
- return ret;
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- macSecret = wolfSSL_GetDtlsMacSecret(ssl, verify, epochOrder);
- else
- macSecret = wolfSSL_GetMacSecret(ssl, verify);
- #else
- macSecret = wolfSSL_GetMacSecret(ssl, verify);
- #endif
- ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
- macSecret,
- ssl->specs.hash_size);
- if (ret == 0) {
- /* Constant time verification required. */
- if (verify && padSz >= 0) {
- #if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
- !defined(HAVE_SELFTEST)
- #ifdef HAVE_BLAKE2
- if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) {
- ret = Hmac_UpdateFinal(&hmac, digest, in,
- sz + hashSz + padSz + 1, myInner);
- }
- else
- #endif
- {
- ret = Hmac_UpdateFinal_CT(&hmac, digest, in,
- sz + hashSz + padSz + 1, myInner);
- }
- #else
- ret = Hmac_UpdateFinal(&hmac, digest, in, sz + hashSz + padSz + 1,
- myInner);
- #endif
- }
- else {
- ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
- if (ret == 0)
- ret = wc_HmacUpdate(&hmac, in, sz); /* content */
- if (ret == 0)
- ret = wc_HmacFinal(&hmac, digest);
- }
- }
- wc_HmacFree(&hmac);
- return ret;
- }
- #endif /* WOLFSSL_AEAD_ONLY */
- #endif /* !WOLFSSL_NO_TLS12 */
- #ifdef HAVE_TLS_EXTENSIONS
- /**
- * The TLSX semaphore is used to calculate the size of the extensions to be sent
- * from one peer to another.
- */
- /** Supports up to 64 flags. Increase as needed. */
- #define SEMAPHORE_SIZE 8
- /**
- * Converts the extension type (id) to an index in the semaphore.
- *
- * Official reference for TLS extension types:
- * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
- *
- * Motivation:
- * Previously, we used the extension type itself as the index of that
- * extension in the semaphore as the extension types were declared
- * sequentially, but maintain a semaphore as big as the number of available
- * extensions is no longer an option since the release of renegotiation_info.
- *
- * How to update:
- * Assign extension types that extrapolate the number of available semaphores
- * to the first available index going backwards in the semaphore array.
- * When adding a new extension type that don't extrapolate the number of
- * available semaphores, check for a possible collision with with a
- * 'remapped' extension type.
- */
- static WC_INLINE word16 TLSX_ToSemaphore(word16 type)
- {
- switch (type) {
- case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */
- return 63;
- default:
- if (type > 62) {
- /* This message SHOULD only happens during the adding of
- new TLS extensions in which its IANA number overflows
- the current semaphore's range, or if its number already
- is assigned to be used by another extension.
- Use this check value for the new extension and decrement
- the check value by one. */
- WOLFSSL_MSG("### TLSX semaphore collision or overflow detected!");
- }
- }
- return type;
- }
- /** Checks if a specific light (tls extension) is not set in the semaphore. */
- #define IS_OFF(semaphore, light) \
- (!(((semaphore)[(light) / 8] & (byte) (0x01 << ((light) % 8)))))
- /** Turn on a specific light (tls extension) in the semaphore. */
- /* the semaphore marks the extensions already written to the message */
- #define TURN_ON(semaphore, light) \
- ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8)))
- /** Turn off a specific light (tls extension) in the semaphore. */
- #define TURN_OFF(semaphore, light) \
- ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8)))
- /** Creates a new extension. */
- static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap)
- {
- TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX);
- (void)heap;
- if (extension) {
- extension->type = type;
- extension->data = data;
- extension->resp = 0;
- extension->next = NULL;
- }
- return extension;
- }
- /**
- * Creates a new extension and pushes it to the provided list.
- * Checks for duplicate extensions, keeps the newest.
- */
- static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap)
- {
- TLSX* extension = TLSX_New(type, data, heap);
- if (extension == NULL)
- return MEMORY_E;
- /* pushes the new extension on the list. */
- extension->next = *list;
- *list = extension;
- /* remove duplicate extensions, there should be only one of each type. */
- do {
- if (extension->next && extension->next->type == type) {
- TLSX *next = extension->next;
- extension->next = next->next;
- next->next = NULL;
- TLSX_FreeAll(next, heap);
- /* there is no way to occur more than
- * two extensions of the same type.
- */
- break;
- }
- } while ((extension = extension->next));
- return 0;
- }
- #ifdef WOLFSSL_TLS13
- /**
- * Creates a new extension and prepend it to the provided list.
- * Checks for duplicate extensions, keeps the newest.
- */
- static int TLSX_Prepend(TLSX** list, TLSX_Type type, void* data, void* heap)
- {
- TLSX* extension = TLSX_New(type, data, heap);
- TLSX* curr = *list;
- if (extension == NULL)
- return MEMORY_E;
- /* remove duplicate extensions, there should be only one of each type. */
- while (curr && curr->next) {
- if (curr->next->type == type) {
- TLSX *next = curr->next;
- curr->next = next->next;
- next->next = NULL;
- TLSX_FreeAll(next, heap);
- }
- curr = curr->next;
- }
- if (curr)
- curr->next = extension;
- else
- *list = extension;
- return 0;
- }
- #endif /* WOLFSSL_TLS13 */
- #ifndef NO_WOLFSSL_CLIENT
- int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type);
- int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type)
- {
- TLSX *extension = TLSX_Find(ssl->extensions, type);
- if (!extension)
- extension = TLSX_Find(ssl->ctx->extensions, type);
- return extension == NULL;
- }
- int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl);
- int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl)
- {
- SendAlert(ssl, alert_fatal, unsupported_extension);
- return UNSUPPORTED_EXTENSION;
- }
- #else
- #define TLSX_CheckUnsupportedExtension(ssl, type) 0
- #define TLSX_HandleUnsupportedExtension(ssl) 0
- #endif
- /** Mark an extension to be sent back to the client. */
- void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type);
- void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type)
- {
- TLSX *extension = TLSX_Find(ssl->extensions, type);
- if (extension)
- extension->resp = 1;
- }
- /******************************************************************************/
- /* Application-Layer Protocol Negotiation */
- /******************************************************************************/
- #ifdef HAVE_ALPN
- /** Creates a new ALPN object, providing protocol name to use. */
- static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz,
- void* heap)
- {
- ALPN *alpn;
- WOLFSSL_ENTER("TLSX_ALPN_New");
- if (protocol_name == NULL ||
- protocol_nameSz > WOLFSSL_MAX_ALPN_PROTO_NAME_LEN) {
- WOLFSSL_MSG("Invalid arguments");
- return NULL;
- }
- alpn = (ALPN*)XMALLOC(sizeof(ALPN), heap, DYNAMIC_TYPE_TLSX);
- if (alpn == NULL) {
- WOLFSSL_MSG("Memory failure");
- return NULL;
- }
- alpn->next = NULL;
- alpn->negotiated = 0;
- alpn->options = 0;
- alpn->protocol_name = (char*)XMALLOC(protocol_nameSz + 1,
- heap, DYNAMIC_TYPE_TLSX);
- if (alpn->protocol_name == NULL) {
- WOLFSSL_MSG("Memory failure");
- XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
- return NULL;
- }
- XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz);
- alpn->protocol_name[protocol_nameSz] = 0;
- (void)heap;
- return alpn;
- }
- /** Releases an ALPN object. */
- static void TLSX_ALPN_Free(ALPN *alpn, void* heap)
- {
- (void)heap;
- if (alpn == NULL)
- return;
- XFREE(alpn->protocol_name, heap, DYNAMIC_TYPE_TLSX);
- XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
- }
- /** Releases all ALPN objects in the provided list. */
- static void TLSX_ALPN_FreeAll(ALPN *list, void* heap)
- {
- ALPN* alpn;
- while ((alpn = list)) {
- list = alpn->next;
- TLSX_ALPN_Free(alpn, heap);
- }
- }
- /** Tells the buffered size of the ALPN objects in a list. */
- static word16 TLSX_ALPN_GetSize(ALPN *list)
- {
- ALPN* alpn;
- word16 length = OPAQUE16_LEN; /* list length */
- while ((alpn = list)) {
- list = alpn->next;
- length++; /* protocol name length is on one byte */
- length += (word16)XSTRLEN(alpn->protocol_name);
- }
- return length;
- }
- /** Writes the ALPN objects of a list in a buffer. */
- static word16 TLSX_ALPN_Write(ALPN *list, byte *output)
- {
- ALPN* alpn;
- word16 length = 0;
- word16 offset = OPAQUE16_LEN; /* list length offset */
- while ((alpn = list)) {
- list = alpn->next;
- length = (word16)XSTRLEN(alpn->protocol_name);
- /* protocol name length */
- output[offset++] = (byte)length;
- /* protocol name value */
- XMEMCPY(output + offset, alpn->protocol_name, length);
- offset += length;
- }
- /* writing list length */
- c16toa(offset - OPAQUE16_LEN, output);
- return offset;
- }
- /** Finds a protocol name in the provided ALPN list */
- static ALPN* TLSX_ALPN_Find(ALPN *list, char *protocol_name, word16 size)
- {
- ALPN *alpn;
- if (list == NULL || protocol_name == NULL)
- return NULL;
- alpn = list;
- while (alpn != NULL && (
- (word16)XSTRLEN(alpn->protocol_name) != size ||
- XSTRNCMP(alpn->protocol_name, protocol_name, size)))
- alpn = alpn->next;
- return alpn;
- }
- /** Set the ALPN matching client and server requirements */
- static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size,
- void* heap)
- {
- ALPN *alpn;
- int ret;
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
- alpn = TLSX_ALPN_New((char *)data, size, heap);
- if (alpn == NULL) {
- WOLFSSL_MSG("Memory failure");
- return MEMORY_E;
- }
- alpn->negotiated = 1;
- ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn,
- heap);
- if (ret != 0) {
- TLSX_ALPN_Free(alpn, heap);
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- /** Parses a buffer of ALPN extensions and set the first one matching
- * client and server requirements */
- static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
- byte isRequest)
- {
- word16 size = 0, offset = 0, idx = 0;
- int r = BUFFER_ERROR;
- byte match = 0;
- TLSX *extension;
- ALPN *alpn = NULL, *list;
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
- ato16(input, &size);
- offset += OPAQUE16_LEN;
- if (size == 0)
- return BUFFER_ERROR;
- extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
- if (extension == NULL)
- extension = TLSX_Find(ssl->ctx->extensions,
- TLSX_APPLICATION_LAYER_PROTOCOL);
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- if (ssl->alpnSelect != NULL) {
- const byte* out;
- unsigned char outLen;
- if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size,
- ssl->alpnSelectArg) == 0) {
- WOLFSSL_MSG("ALPN protocol match");
- if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap)
- == WOLFSSL_SUCCESS) {
- if (extension == NULL) {
- extension = TLSX_Find(ssl->extensions,
- TLSX_APPLICATION_LAYER_PROTOCOL);
- }
- }
- }
- }
- #endif
- if (extension == NULL || extension->data == NULL) {
- return isRequest ? 0
- : TLSX_HandleUnsupportedExtension(ssl);
- }
- /* validating alpn list length */
- if (length != OPAQUE16_LEN + size)
- return BUFFER_ERROR;
- list = (ALPN*)extension->data;
- /* keep the list sent by client */
- if (isRequest) {
- if (ssl->alpn_client_list != NULL)
- XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
- ssl->alpn_client_list = (char *)XMALLOC(size, ssl->heap,
- DYNAMIC_TYPE_ALPN);
- if (ssl->alpn_client_list == NULL)
- return MEMORY_ERROR;
- }
- for (size = 0; offset < length; offset += size) {
- size = input[offset++];
- if (offset + size > length || size == 0)
- return BUFFER_ERROR;
- if (isRequest) {
- XMEMCPY(ssl->alpn_client_list+idx, (char*)input + offset, size);
- idx += size;
- ssl->alpn_client_list[idx++] = ',';
- }
- if (!match) {
- alpn = TLSX_ALPN_Find(list, (char*)input + offset, size);
- if (alpn != NULL) {
- WOLFSSL_MSG("ALPN protocol match");
- match = 1;
- /* skip reading other values if not required */
- if (!isRequest)
- break;
- }
- }
- }
- if (isRequest)
- ssl->alpn_client_list[idx-1] = 0;
- if (!match) {
- WOLFSSL_MSG("No ALPN protocol match");
- /* do nothing if no protocol match between client and server and option
- is set to continue (like OpenSSL) */
- if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) {
- WOLFSSL_MSG("Continue on mismatch");
- return 0;
- }
- SendAlert(ssl, alert_fatal, no_application_protocol);
- return UNKNOWN_ALPN_PROTOCOL_NAME_E;
- }
- /* set the matching negotiated protocol */
- r = TLSX_SetALPN(&ssl->extensions,
- alpn->protocol_name,
- (word16)XSTRLEN(alpn->protocol_name),
- ssl->heap);
- if (r != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("TLSX_UseALPN failed");
- return BUFFER_ERROR;
- }
- /* reply to ALPN extension sent from client */
- if (isRequest) {
- #ifndef NO_WOLFSSL_SERVER
- TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL);
- #endif
- }
- return 0;
- }
- /** Add a protocol name to the list of accepted usable ones */
- int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options,
- void* heap)
- {
- ALPN *alpn;
- TLSX *extension;
- int ret;
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
- alpn = TLSX_ALPN_New((char *)data, size, heap);
- if (alpn == NULL) {
- WOLFSSL_MSG("Memory failure");
- return MEMORY_E;
- }
- /* Set Options of ALPN */
- alpn->options = options;
- extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
- if (extension == NULL) {
- ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL,
- (void*)alpn, heap);
- if (ret != 0) {
- TLSX_ALPN_Free(alpn, heap);
- return ret;
- }
- }
- else {
- /* push new ALPN object to extension data. */
- alpn->next = (ALPN*)extension->data;
- extension->data = (void*)alpn;
- }
- return WOLFSSL_SUCCESS;
- }
- /** Get the protocol name set by the server */
- int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz)
- {
- TLSX *extension;
- ALPN *alpn;
- if (extensions == NULL || data == NULL || dataSz == NULL)
- return BAD_FUNC_ARG;
- extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
- if (extension == NULL) {
- WOLFSSL_MSG("TLS extension not found");
- return WOLFSSL_ALPN_NOT_FOUND;
- }
- alpn = (ALPN *)extension->data;
- if (alpn == NULL) {
- WOLFSSL_MSG("ALPN extension not found");
- *data = NULL;
- *dataSz = 0;
- return WOLFSSL_FATAL_ERROR;
- }
- if (alpn->negotiated != 1) {
- /* consider as an error */
- if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) {
- WOLFSSL_MSG("No protocol match with peer -> Failed");
- return WOLFSSL_FATAL_ERROR;
- }
- /* continue without negotiated protocol */
- WOLFSSL_MSG("No protocol match with peer -> Continue");
- return WOLFSSL_ALPN_NOT_FOUND;
- }
- if (alpn->next != NULL) {
- WOLFSSL_MSG("Only one protocol name must be accepted");
- return WOLFSSL_FATAL_ERROR;
- }
- *data = alpn->protocol_name;
- *dataSz = (word16)XSTRLEN((char*)*data);
- return WOLFSSL_SUCCESS;
- }
- #define ALPN_FREE_ALL TLSX_ALPN_FreeAll
- #define ALPN_GET_SIZE TLSX_ALPN_GetSize
- #define ALPN_WRITE TLSX_ALPN_Write
- #define ALPN_PARSE TLSX_ALPN_ParseAndSet
- #else /* HAVE_ALPN */
- #define ALPN_FREE_ALL(list, heap)
- #define ALPN_GET_SIZE(list) 0
- #define ALPN_WRITE(a, b) 0
- #define ALPN_PARSE(a, b, c, d) 0
- #endif /* HAVE_ALPN */
- /******************************************************************************/
- /* Server Name Indication */
- /******************************************************************************/
- #ifdef HAVE_SNI
- /** Creates a new SNI object. */
- static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap)
- {
- SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX);
- (void)heap;
- if (sni) {
- sni->type = type;
- sni->next = NULL;
- #ifndef NO_WOLFSSL_SERVER
- sni->options = 0;
- sni->status = WOLFSSL_SNI_NO_MATCH;
- #endif
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- sni->data.host_name = (char*)XMALLOC(size + 1, heap,
- DYNAMIC_TYPE_TLSX);
- if (sni->data.host_name) {
- XSTRNCPY(sni->data.host_name, (const char*)data, size);
- sni->data.host_name[size] = '\0';
- } else {
- XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
- sni = NULL;
- }
- break;
- default: /* invalid type */
- XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
- sni = NULL;
- }
- }
- return sni;
- }
- /** Releases a SNI object. */
- static void TLSX_SNI_Free(SNI* sni, void* heap)
- {
- if (sni) {
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX);
- break;
- }
- XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- /** Releases all SNI objects in the provided list. */
- static void TLSX_SNI_FreeAll(SNI* list, void* heap)
- {
- SNI* sni;
- while ((sni = list)) {
- list = sni->next;
- TLSX_SNI_Free(sni, heap);
- }
- }
- /** Tells the buffered size of the SNI objects in a list. */
- static word16 TLSX_SNI_GetSize(SNI* list)
- {
- SNI* sni;
- word16 length = OPAQUE16_LEN; /* list length */
- while ((sni = list)) {
- list = sni->next;
- length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- length += (word16)XSTRLEN((char*)sni->data.host_name);
- break;
- }
- }
- return length;
- }
- /** Writes the SNI objects of a list in a buffer. */
- static word16 TLSX_SNI_Write(SNI* list, byte* output)
- {
- SNI* sni;
- word16 length = 0;
- word16 offset = OPAQUE16_LEN; /* list length offset */
- while ((sni = list)) {
- list = sni->next;
- output[offset++] = sni->type; /* sni type */
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- length = (word16)XSTRLEN((char*)sni->data.host_name);
- c16toa(length, output + offset); /* sni length */
- offset += OPAQUE16_LEN;
- XMEMCPY(output + offset, sni->data.host_name, length);
- offset += length;
- break;
- }
- }
- c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
- return offset;
- }
- /** Finds a SNI object in the provided list. */
- static SNI* TLSX_SNI_Find(SNI *list, byte type)
- {
- SNI* sni = list;
- while (sni && sni->type != type)
- sni = sni->next;
- return sni;
- }
- /** Sets the status of a SNI object. */
- static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
- if (sni)
- sni->status = status;
- }
- /** Gets the status of a SNI object. */
- byte TLSX_SNI_Status(TLSX* extensions, byte type)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
- if (sni)
- return sni->status;
- return 0;
- }
- /** Parses a buffer of SNI extensions. */
- static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- #ifndef NO_WOLFSSL_SERVER
- word16 size = 0;
- word16 offset = 0;
- int cacheOnly = 0;
- SNI *sni = NULL;
- byte type;
- int matchStat;
- byte matched;
- #endif
- TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
- if (!extension)
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
- if (!isRequest) {
- #ifndef NO_WOLFSSL_CLIENT
- if (!extension || !extension->data)
- return TLSX_HandleUnsupportedExtension(ssl);
- if (length > 0)
- return BUFFER_ERROR; /* SNI response MUST be empty. */
- /* This call enables wolfSSL_SNI_GetRequest() to be called in the
- * client side to fetch the used SNI. It will only work if the SNI
- * was set at the SSL object level. Right now we only support one
- * name type, WOLFSSL_SNI_HOST_NAME, but in the future, the
- * inclusion of other name types will turn this method inaccurate,
- * as the extension response doesn't contains information of which
- * name was accepted.
- */
- TLSX_SNI_SetStatus(ssl->extensions, WOLFSSL_SNI_HOST_NAME,
- WOLFSSL_SNI_REAL_MATCH);
- return 0;
- #endif
- }
- #ifndef NO_WOLFSSL_SERVER
- if (!extension || !extension->data) {
- #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER)
- /* This will keep SNI even though TLSX_UseSNI has not been called.
- * Enable it so that the received sni is available to functions
- * that use a custom callback when SNI is received.
- */
- cacheOnly = 1;
- WOLFSSL_MSG("Forcing SSL object to store SNI parameter");
- #else
- /* Skipping, SNI not enabled at server side. */
- return 0;
- #endif
- }
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
- ato16(input, &size);
- offset += OPAQUE16_LEN;
- /* validating sni list length */
- if (length != OPAQUE16_LEN + size || size == 0)
- return BUFFER_ERROR;
- /* SNI was badly specified and only one type is now recognized and allowed.
- * Only one SNI value per type (RFC6066), so, no loop. */
- type = input[offset++];
- if (type != WOLFSSL_SNI_HOST_NAME)
- return BUFFER_ERROR;
- if (offset + OPAQUE16_LEN > length)
- return BUFFER_ERROR;
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN;
- if (offset + size != length || size == 0)
- return BUFFER_ERROR;
- if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type)))
- return 0; /* not using this type of SNI. */
- #ifdef WOLFSSL_TLS13
- /* Don't process the second ClientHello SNI extension if there
- * was problems with the first.
- */
- if (!cacheOnly && sni->status != 0)
- return 0;
- #endif
- matched = cacheOnly || (XSTRLEN(sni->data.host_name) == size &&
- XSTRNCMP(sni->data.host_name, (const char*)input + offset, size) == 0);
- if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) {
- int r = TLSX_UseSNI(&ssl->extensions, type, input + offset, size,
- ssl->heap);
- if (r != WOLFSSL_SUCCESS)
- return r; /* throws error. */
- if (cacheOnly) {
- WOLFSSL_MSG("Forcing storage of SNI, Fake match");
- matchStat = WOLFSSL_SNI_FORCE_KEEP;
- }
- else if (matched) {
- WOLFSSL_MSG("SNI did match!");
- matchStat = WOLFSSL_SNI_REAL_MATCH;
- }
- else {
- WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH");
- matchStat = WOLFSSL_SNI_FAKE_MATCH;
- }
- TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat);
- if(!cacheOnly)
- TLSX_SetResponse(ssl, TLSX_SERVER_NAME);
- }
- else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) {
- SendAlert(ssl, alert_fatal, unrecognized_name);
- return UNKNOWN_SNI_HOST_NAME_E;
- }
- #else
- (void)input;
- #endif
- return 0;
- }
- static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest)
- {
- (void)ssl;
- if (isRequest) {
- #ifndef NO_WOLFSSL_SERVER
- TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
- TLSX* ssl_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
- SNI* ctx_sni = ctx_ext ? (SNI*)ctx_ext->data : NULL;
- SNI* ssl_sni = ssl_ext ? (SNI*)ssl_ext->data : NULL;
- SNI* sni = NULL;
- for (; ctx_sni; ctx_sni = ctx_sni->next) {
- if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
- sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type);
- if (sni) {
- if (sni->status != WOLFSSL_SNI_NO_MATCH)
- continue;
- /* if ssl level overrides ctx level, it is ok. */
- if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0)
- continue;
- }
- SendAlert(ssl, alert_fatal, handshake_failure);
- return SNI_ABSENT_ERROR;
- }
- }
- for (; ssl_sni; ssl_sni = ssl_sni->next) {
- if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
- if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH)
- continue;
- SendAlert(ssl, alert_fatal, handshake_failure);
- return SNI_ABSENT_ERROR;
- }
- }
- #endif /* NO_WOLFSSL_SERVER */
- }
- return 0;
- }
- int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size,
- void* heap)
- {
- TLSX* extension;
- SNI* sni = NULL;
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
- if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL)
- return MEMORY_E;
- extension = TLSX_Find(*extensions, TLSX_SERVER_NAME);
- if (!extension) {
- int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap);
- if (ret != 0) {
- TLSX_SNI_Free(sni, heap);
- return ret;
- }
- }
- else {
- /* push new SNI object to extension data. */
- sni->next = (SNI*)extension->data;
- extension->data = (void*)sni;
- /* remove duplicate SNI, there should be only one of each type. */
- do {
- if (sni->next && sni->next->type == type) {
- SNI* next = sni->next;
- sni->next = next->next;
- TLSX_SNI_Free(next, heap);
- /* there is no way to occur more than
- * two SNIs of the same type.
- */
- break;
- }
- } while ((sni = sni->next));
- }
- return WOLFSSL_SUCCESS;
- }
- #ifndef NO_WOLFSSL_SERVER
- /** Tells the SNI requested by the client. */
- word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
- if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) {
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- if (data) {
- *data = sni->data.host_name;
- return (word16)XSTRLEN((char*)*data);
- }
- }
- }
- return 0;
- }
- /** Sets the options for a SNI object. */
- void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
- if (sni)
- sni->options = options;
- }
- /** Retrieves a SNI request from a client hello buffer. */
- int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
- byte type, byte* sni, word32* inOutSz)
- {
- word32 offset = 0;
- word32 len32 = 0;
- word16 len16 = 0;
- if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST)
- return INCOMPLETE_DATA;
- /* TLS record header */
- if ((enum ContentType) clientHello[offset++] != handshake) {
- /* checking for SSLv2.0 client hello according to: */
- /* http://tools.ietf.org/html/rfc4346#appendix-E.1 */
- if ((enum HandShakeType) clientHello[++offset] == client_hello) {
- offset += ENUM_LEN + VERSION_SZ; /* skip version */
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
- if (len16 % 3) /* cipher_spec_length must be multiple of 3 */
- return BUFFER_ERROR;
- ato16(clientHello + offset, &len16);
- /* Returning SNI_UNSUPPORTED do not increment offset here */
- if (len16 != 0) /* session_id_length must be 0 */
- return BUFFER_ERROR;
- return SNI_UNSUPPORTED;
- }
- return BUFFER_ERROR;
- }
- if (clientHello[offset++] != SSLv3_MAJOR)
- return BUFFER_ERROR;
- if (clientHello[offset++] < TLSv1_MINOR)
- return SNI_UNSUPPORTED;
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
- if (offset + len16 > helloSz)
- return INCOMPLETE_DATA;
- /* Handshake header */
- if ((enum HandShakeType) clientHello[offset] != client_hello)
- return BUFFER_ERROR;
- c24to32(clientHello + offset + 1, &len32);
- offset += HANDSHAKE_HEADER_SZ;
- if (offset + len32 > helloSz)
- return BUFFER_ERROR;
- /* client hello */
- offset += VERSION_SZ + RAN_LEN; /* version, random */
- if (helloSz < offset + clientHello[offset])
- return BUFFER_ERROR;
- offset += ENUM_LEN + clientHello[offset]; /* skip session id */
- /* cypher suites */
- if (helloSz < offset + OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
- if (helloSz < offset + len16)
- return BUFFER_ERROR;
- offset += len16; /* skip cypher suites */
- /* compression methods */
- if (helloSz < offset + 1)
- return BUFFER_ERROR;
- if (helloSz < offset + clientHello[offset])
- return BUFFER_ERROR;
- offset += ENUM_LEN + clientHello[offset]; /* skip compression methods */
- /* extensions */
- if (helloSz < offset + OPAQUE16_LEN)
- return 0; /* no extensions in client hello. */
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
- if (helloSz < offset + len16)
- return BUFFER_ERROR;
- while (len16 >= OPAQUE16_LEN + OPAQUE16_LEN) {
- word16 extType;
- word16 extLen;
- ato16(clientHello + offset, &extType);
- offset += OPAQUE16_LEN;
- ato16(clientHello + offset, &extLen);
- offset += OPAQUE16_LEN;
- if (helloSz < offset + extLen)
- return BUFFER_ERROR;
- if (extType != TLSX_SERVER_NAME) {
- offset += extLen; /* skip extension */
- } else {
- word16 listLen;
- ato16(clientHello + offset, &listLen);
- offset += OPAQUE16_LEN;
- if (helloSz < offset + listLen)
- return BUFFER_ERROR;
- while (listLen > ENUM_LEN + OPAQUE16_LEN) {
- byte sniType = clientHello[offset++];
- word16 sniLen;
- ato16(clientHello + offset, &sniLen);
- offset += OPAQUE16_LEN;
- if (helloSz < offset + sniLen)
- return BUFFER_ERROR;
- if (sniType != type) {
- offset += sniLen;
- listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
- continue;
- }
- *inOutSz = min(sniLen, *inOutSz);
- XMEMCPY(sni, clientHello + offset, *inOutSz);
- return WOLFSSL_SUCCESS;
- }
- }
- len16 -= min(2 * OPAQUE16_LEN + extLen, len16);
- }
- return len16 ? BUFFER_ERROR : 0;
- }
- #endif
- #define SNI_FREE_ALL TLSX_SNI_FreeAll
- #define SNI_GET_SIZE TLSX_SNI_GetSize
- #define SNI_WRITE TLSX_SNI_Write
- #define SNI_PARSE TLSX_SNI_Parse
- #define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse
- #else
- #define SNI_FREE_ALL(list, heap)
- #define SNI_GET_SIZE(list) 0
- #define SNI_WRITE(a, b) 0
- #define SNI_PARSE(a, b, c, d) 0
- #define SNI_VERIFY_PARSE(a, b) 0
- #endif /* HAVE_SNI */
- /******************************************************************************/
- /* Trusted CA Key Indication */
- /******************************************************************************/
- #ifdef HAVE_TRUSTED_CA
- /** Creates a new TCA object. */
- static TCA* TLSX_TCA_New(byte type, const byte* id, word16 idSz, void* heap)
- {
- TCA* tca = (TCA*)XMALLOC(sizeof(TCA), heap, DYNAMIC_TYPE_TLSX);
- if (tca) {
- XMEMSET(tca, 0, sizeof(TCA));
- tca->type = type;
- switch (type) {
- case WOLFSSL_TRUSTED_CA_PRE_AGREED:
- break;
- #ifndef NO_SHA
- case WOLFSSL_TRUSTED_CA_KEY_SHA1:
- case WOLFSSL_TRUSTED_CA_CERT_SHA1:
- if (idSz == WC_SHA_DIGEST_SIZE &&
- (tca->id =
- (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) {
- XMEMCPY(tca->id, id, idSz);
- tca->idSz = idSz;
- }
- else {
- XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
- tca = NULL;
- }
- break;
- #endif
- case WOLFSSL_TRUSTED_CA_X509_NAME:
- if (idSz > 0 &&
- (tca->id =
- (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) {
- XMEMCPY(tca->id, id, idSz);
- tca->idSz = idSz;
- }
- else {
- XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
- tca = NULL;
- }
- break;
- default: /* invalid type */
- XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
- tca = NULL;
- }
- }
- (void)heap;
- return tca;
- }
- /** Releases a TCA object. */
- static void TLSX_TCA_Free(TCA* tca, void* heap)
- {
- (void)heap;
- if (tca) {
- if (tca->id)
- XFREE(tca->id, heap, DYNAMIC_TYPE_TLSX);
- XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
- }
- }
- /** Releases all TCA objects in the provided list. */
- static void TLSX_TCA_FreeAll(TCA* list, void* heap)
- {
- TCA* tca;
- while ((tca = list)) {
- list = tca->next;
- TLSX_TCA_Free(tca, heap);
- }
- }
- /** Tells the buffered size of the TCA objects in a list. */
- static word16 TLSX_TCA_GetSize(TCA* list)
- {
- TCA* tca;
- word16 length = OPAQUE16_LEN; /* list length */
- while ((tca = list)) {
- list = tca->next;
- length += ENUM_LEN; /* tca type */
- switch (tca->type) {
- case WOLFSSL_TRUSTED_CA_PRE_AGREED:
- break;
- case WOLFSSL_TRUSTED_CA_KEY_SHA1:
- case WOLFSSL_TRUSTED_CA_CERT_SHA1:
- length += tca->idSz;
- break;
- case WOLFSSL_TRUSTED_CA_X509_NAME:
- length += OPAQUE16_LEN + tca->idSz;
- break;
- }
- }
- return length;
- }
- /** Writes the TCA objects of a list in a buffer. */
- static word16 TLSX_TCA_Write(TCA* list, byte* output)
- {
- TCA* tca;
- word16 offset = OPAQUE16_LEN; /* list length offset */
- while ((tca = list)) {
- list = tca->next;
- output[offset++] = tca->type; /* tca type */
- switch (tca->type) {
- case WOLFSSL_TRUSTED_CA_PRE_AGREED:
- break;
- #ifndef NO_SHA
- case WOLFSSL_TRUSTED_CA_KEY_SHA1:
- case WOLFSSL_TRUSTED_CA_CERT_SHA1:
- if (tca->id != NULL) {
- XMEMCPY(output + offset, tca->id, tca->idSz);
- offset += tca->idSz;
- }
- else {
- /* ID missing. Set to an empty string. */
- c16toa(0, output + offset);
- offset += OPAQUE16_LEN;
- }
- break;
- #endif
- case WOLFSSL_TRUSTED_CA_X509_NAME:
- if (tca->id != NULL) {
- c16toa(tca->idSz, output + offset); /* tca length */
- offset += OPAQUE16_LEN;
- XMEMCPY(output + offset, tca->id, tca->idSz);
- offset += tca->idSz;
- }
- else {
- /* ID missing. Set to an empty string. */
- c16toa(0, output + offset);
- offset += OPAQUE16_LEN;
- }
- break;
- default:
- /* ID unknown. Set to an empty string. */
- c16toa(0, output + offset);
- offset += OPAQUE16_LEN;
- }
- }
- c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
- return offset;
- }
- #ifndef NO_WOLFSSL_SERVER
- static TCA* TLSX_TCA_Find(TCA *list, byte type, const byte* id, word16 idSz)
- {
- TCA* tca = list;
- while (tca && tca->type != type && type != WOLFSSL_TRUSTED_CA_PRE_AGREED &&
- idSz != tca->idSz && !XMEMCMP(id, tca->id, idSz))
- tca = tca->next;
- return tca;
- }
- #endif /* NO_WOLFSSL_SERVER */
- /** Parses a buffer of TCA extensions. */
- static int TLSX_TCA_Parse(WOLFSSL* ssl, const byte* input, word16 length,
- byte isRequest)
- {
- #ifndef NO_WOLFSSL_SERVER
- word16 size = 0;
- word16 offset = 0;
- #endif
- TLSX *extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS);
- if (!extension)
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_TRUSTED_CA_KEYS);
- if (!isRequest) {
- #ifndef NO_WOLFSSL_CLIENT
- if (!extension || !extension->data)
- return TLSX_HandleUnsupportedExtension(ssl);
- if (length > 0)
- return BUFFER_ERROR; /* TCA response MUST be empty. */
- /* Set the flag that we're good for keys */
- TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS);
- return 0;
- #endif
- }
- #ifndef NO_WOLFSSL_SERVER
- if (!extension || !extension->data) {
- /* Skipping, TCA not enabled at server side. */
- return 0;
- }
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
- ato16(input, &size);
- offset += OPAQUE16_LEN;
- /* validating tca list length */
- if (length != OPAQUE16_LEN + size)
- return BUFFER_ERROR;
- for (size = 0; offset < length; offset += size) {
- TCA *tca = NULL;
- byte type;
- const byte* id = NULL;
- word16 idSz = 0;
- if (offset + ENUM_LEN > length)
- return BUFFER_ERROR;
- type = input[offset++];
- switch (type) {
- case WOLFSSL_TRUSTED_CA_PRE_AGREED:
- break;
- #ifndef NO_SHA
- case WOLFSSL_TRUSTED_CA_KEY_SHA1:
- case WOLFSSL_TRUSTED_CA_CERT_SHA1:
- if (offset + WC_SHA_DIGEST_SIZE > length)
- return BUFFER_ERROR;
- idSz = WC_SHA_DIGEST_SIZE;
- id = input + offset;
- offset += idSz;
- break;
- #endif
- case WOLFSSL_TRUSTED_CA_X509_NAME:
- if (offset + OPAQUE16_LEN > length)
- return BUFFER_ERROR;
- ato16(input + offset, &idSz);
- offset += OPAQUE16_LEN;
- if ((offset > length) || (idSz > length - offset))
- return BUFFER_ERROR;
- id = input + offset;
- offset += idSz;
- break;
- default:
- return TCA_INVALID_ID_TYPE;
- }
- /* Find the type/ID in the TCA list. */
- tca = TLSX_TCA_Find((TCA*)extension->data, type, id, idSz);
- if (tca != NULL) {
- /* Found it. Set the response flag and break out of the loop. */
- TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS);
- break;
- }
- }
- #else
- (void)input;
- #endif
- return 0;
- }
- /* Checks to see if the server sent a response for the TCA. */
- static int TLSX_TCA_VerifyParse(WOLFSSL* ssl, byte isRequest)
- {
- (void)ssl;
- if (!isRequest) {
- #ifndef NO_WOLFSSL_CLIENT
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS);
- if (extension && !extension->resp) {
- SendAlert(ssl, alert_fatal, handshake_failure);
- return TCA_ABSENT_ERROR;
- }
- #endif /* NO_WOLFSSL_CLIENT */
- }
- return 0;
- }
- int TLSX_UseTrustedCA(TLSX** extensions, byte type,
- const byte* id, word16 idSz, void* heap)
- {
- TLSX* extension;
- TCA* tca = NULL;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- if ((tca = TLSX_TCA_New(type, id, idSz, heap)) == NULL)
- return MEMORY_E;
- extension = TLSX_Find(*extensions, TLSX_TRUSTED_CA_KEYS);
- if (!extension) {
- int ret = TLSX_Push(extensions, TLSX_TRUSTED_CA_KEYS, (void*)tca, heap);
- if (ret != 0) {
- TLSX_TCA_Free(tca, heap);
- return ret;
- }
- }
- else {
- /* push new TCA object to extension data. */
- tca->next = (TCA*)extension->data;
- extension->data = (void*)tca;
- }
- return WOLFSSL_SUCCESS;
- }
- #define TCA_FREE_ALL TLSX_TCA_FreeAll
- #define TCA_GET_SIZE TLSX_TCA_GetSize
- #define TCA_WRITE TLSX_TCA_Write
- #define TCA_PARSE TLSX_TCA_Parse
- #define TCA_VERIFY_PARSE TLSX_TCA_VerifyParse
- #else /* HAVE_TRUSTED_CA */
- #define TCA_FREE_ALL(list, heap)
- #define TCA_GET_SIZE(list) 0
- #define TCA_WRITE(a, b) 0
- #define TCA_PARSE(a, b, c, d) 0
- #define TCA_VERIFY_PARSE(a, b) 0
- #endif /* HAVE_TRUSTED_CA */
- /******************************************************************************/
- /* Max Fragment Length Negotiation */
- /******************************************************************************/
- #ifdef HAVE_MAX_FRAGMENT
- static word16 TLSX_MFL_Write(byte* data, byte* output)
- {
- output[0] = data[0];
- return ENUM_LEN;
- }
- static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- if (length != ENUM_LEN)
- return BUFFER_ERROR;
- #ifdef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
- (void) isRequest;
- #else
- if (!isRequest)
- if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH))
- return TLSX_HandleUnsupportedExtension(ssl);
- #endif
- switch (*input) {
- 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:
- SendAlert(ssl, alert_fatal, illegal_parameter);
- return UNKNOWN_MAX_FRAG_LEN_E;
- }
- #ifndef NO_WOLFSSL_SERVER
- if (isRequest) {
- int ret = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
- TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH);
- }
- #endif
- return 0;
- }
- int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap)
- {
- byte* data = NULL;
- int ret = 0;
- if (extensions == NULL || mfl < WOLFSSL_MFL_MIN || mfl > WOLFSSL_MFL_MAX)
- return BAD_FUNC_ARG;
- data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX);
- if (data == NULL)
- return MEMORY_E;
- data[0] = mfl;
- ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap);
- if (ret != 0) {
- XFREE(data, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- #define MFL_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
- #define MFL_GET_SIZE(data) ENUM_LEN
- #define MFL_WRITE TLSX_MFL_Write
- #define MFL_PARSE TLSX_MFL_Parse
- #else
- #define MFL_FREE_ALL(a, b)
- #define MFL_GET_SIZE(a) 0
- #define MFL_WRITE(a, b) 0
- #define MFL_PARSE(a, b, c, d) 0
- #endif /* HAVE_MAX_FRAGMENT */
- /******************************************************************************/
- /* Truncated HMAC */
- /******************************************************************************/
- #ifdef HAVE_TRUNCATED_HMAC
- static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- if (length != 0 || input == NULL)
- return BUFFER_ERROR;
- if (!isRequest) {
- #ifndef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
- if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC))
- return TLSX_HandleUnsupportedExtension(ssl);
- #endif
- }
- else {
- #ifndef NO_WOLFSSL_SERVER
- int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
- TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC);
- #endif
- }
- ssl->truncated_hmac = 1;
- return 0;
- }
- int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap)
- {
- int ret = 0;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap);
- if (ret != 0)
- return ret;
- return WOLFSSL_SUCCESS;
- }
- #define THM_PARSE TLSX_THM_Parse
- #else
- #define THM_PARSE(a, b, c, d) 0
- #endif /* HAVE_TRUNCATED_HMAC */
- /******************************************************************************/
- /* Certificate Status Request */
- /******************************************************************************/
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
- {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- FreeOcspRequest(&csr->request.ocsp);
- break;
- }
- XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
- (void)heap;
- }
- static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
- {
- word16 size = 0;
- /* shut up compiler warnings */
- (void) csr; (void) isRequest;
- #ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- size += ENUM_LEN + 2 * OPAQUE16_LEN;
- if (csr->request.ocsp.nonceSz)
- size += OCSP_NONCE_EXT_SZ;
- break;
- }
- }
- #endif
- #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
- if (!isRequest && csr->ssl->options.tls1_3)
- return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length;
- #endif
- return size;
- }
- static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
- byte isRequest)
- {
- /* shut up compiler warnings */
- (void) csr; (void) output; (void) isRequest;
- #ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- word16 offset = 0;
- word16 length = 0;
- /* type */
- output[offset++] = csr->status_type;
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- /* responder id list */
- c16toa(0, output + offset);
- offset += OPAQUE16_LEN;
- /* request extensions */
- if (csr->request.ocsp.nonceSz)
- length = (word16)EncodeOcspRequestExtensions(
- &csr->request.ocsp,
- output + offset + OPAQUE16_LEN,
- OCSP_NONCE_EXT_SZ);
- c16toa(length, output + offset);
- offset += OPAQUE16_LEN + length;
- break;
- }
- return offset;
- }
- #endif
- #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
- if (!isRequest && csr->ssl->options.tls1_3) {
- word16 offset = 0;
- output[offset++] = csr->status_type;
- c32to24(csr->response.length, output + offset);
- offset += OPAQUE24_LEN;
- XMEMCPY(output + offset, csr->response.buffer, csr->response.length);
- offset += csr->response.length;
- return offset;
- }
- #endif
- return 0;
- }
- static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- int ret;
- #if !defined(NO_WOLFSSL_SERVER)
- byte status_type;
- word16 size = 0;
- #if defined(WOLFSSL_TLS13)
- DecodedCert* cert;
- #endif
- #endif
- #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) \
- && defined(WOLFSSL_TLS13)
- OcspRequest* request;
- TLSX* extension;
- CertificateStatusRequest* csr;
- #endif
- #if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_TLS13) \
- || !defined(NO_WOLFSSL_SERVER)
- word32 offset = 0;
- #endif
- #if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_TLS13)
- word32 resp_length;
- #endif
- /* shut up compiler warnings */
- (void) ssl; (void) input;
- if (!isRequest) {
- #ifndef NO_WOLFSSL_CLIENT
- extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
- csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
- if (!csr) {
- /* look at context level */
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST);
- csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
- if (!csr) /* unexpected extension */
- return TLSX_HandleUnsupportedExtension(ssl);
- /* enable extension at ssl level */
- ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
- csr->status_type, csr->options, ssl,
- ssl->heap, ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- /* propagate nonce */
- if (csr->request.ocsp.nonceSz) {
- request =
- (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
- if (request) {
- XMEMCPY(request->nonce, csr->request.ocsp.nonce,
- csr->request.ocsp.nonceSz);
- request->nonceSz = csr->request.ocsp.nonceSz;
- }
- }
- break;
- }
- }
- ssl->status_request = 1;
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3) {
- /* Get the new extension potentially created above. */
- extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
- csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
- if (csr == NULL)
- return MEMORY_ERROR;
- ret = 0;
- if (OPAQUE8_LEN + OPAQUE24_LEN > length)
- ret = BUFFER_ERROR;
- if (ret == 0 && input[offset++] != WOLFSSL_CSR_OCSP)
- ret = BAD_CERTIFICATE_STATUS_ERROR;
- if (ret == 0) {
- c24to32(input + offset, &resp_length);
- offset += OPAQUE24_LEN;
- if (offset + resp_length != length)
- ret = BUFFER_ERROR;
- }
- if (ret == 0) {
- csr->response.buffer = input + offset;
- csr->response.length = resp_length;
- }
- return ret;
- }
- else
- #endif
- {
- /* extension_data MUST be empty. */
- return length ? BUFFER_ERROR : 0;
- }
- #endif
- }
- else {
- #ifndef NO_WOLFSSL_SERVER
- if (length == 0)
- return 0;
- status_type = input[offset++];
- switch (status_type) {
- case WOLFSSL_CSR_OCSP: {
- /* skip responder_id_list */
- if ((int)(length - offset) < OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN + size;
- /* skip request_extensions */
- if ((int)(length - offset) < OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN + size;
- if (offset > length)
- return BUFFER_ERROR;
- /* is able to send OCSP response? */
- if (ssl->ctx->cm == NULL || !ssl->ctx->cm->ocspStaplingEnabled)
- return 0;
- }
- break;
- /* unknown status type */
- default:
- return 0;
- }
- /* if using status_request and already sending it, skip this one */
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
- if (ssl->status_request_v2)
- return 0;
- #endif
- /* accept the first good status_type and return */
- ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
- 0, ssl, ssl->heap, ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
- #if defined(WOLFSSL_TLS13)
- if (ssl->options.tls1_3) {
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL) {
- return MEMORY_E;
- }
- InitDecodedCert(cert, ssl->buffers.certificate->buffer,
- ssl->buffers.certificate->length, ssl->heap);
- ret = ParseCert(cert, CERT_TYPE, 1, ssl->ctx->cm);
- if (ret != 0 ) {
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- return ret;
- }
- ret = TLSX_CSR_InitRequest(ssl->extensions, cert, ssl->heap);
- if (ret != 0 ) {
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- return ret;
- }
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
- csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
- if (csr == NULL)
- return MEMORY_ERROR;
- request = &csr->request.ocsp;
- ret = CreateOcspResponse(ssl, &request, &csr->response);
- if (ret != 0)
- return ret;
- if (csr->response.buffer)
- TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
- }
- else
- #endif
- TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
- ssl->status_request = status_type;
- #endif
- }
- return 0;
- }
- int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
- CertificateStatusRequest* csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
- int ret = 0;
- if (csr) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP: {
- byte nonce[MAX_OCSP_NONCE_SZ];
- int nonceSz = csr->request.ocsp.nonceSz;
- /* preserve nonce */
- XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz);
- if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0, heap))
- != 0)
- return ret;
- /* restore nonce */
- XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz);
- csr->request.ocsp.nonceSz = nonceSz;
- }
- break;
- }
- }
- return ret;
- }
- void* TLSX_CSR_GetRequest(TLSX* extensions)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
- CertificateStatusRequest* csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
- if (csr) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- return &csr->request.ocsp;
- break;
- }
- }
- return NULL;
- }
- int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
- {
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
- CertificateStatusRequest* csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
- if (csr) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- if (ssl->ctx->cm->ocspEnabled) {
- csr->request.ocsp.ssl = ssl;
- return CheckOcspRequest(ssl->ctx->cm->ocsp,
- &csr->request.ocsp, NULL);
- }
- else
- return OCSP_LOOKUP_FAIL;
- }
- }
- return 0;
- }
- int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
- byte options, WOLFSSL* ssl, void* heap,
- int devId)
- {
- CertificateStatusRequest* csr = NULL;
- int ret = 0;
- if (!extensions || status_type != WOLFSSL_CSR_OCSP)
- return BAD_FUNC_ARG;
- csr = (CertificateStatusRequest*)
- XMALLOC(sizeof(CertificateStatusRequest), heap, DYNAMIC_TYPE_TLSX);
- if (!csr)
- return MEMORY_E;
- ForceZero(csr, sizeof(CertificateStatusRequest));
- csr->status_type = status_type;
- csr->options = options;
- csr->ssl = ssl;
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- if (options & WOLFSSL_CSR_OCSP_USE_NONCE) {
- WC_RNG rng;
- #ifndef HAVE_FIPS
- ret = wc_InitRng_ex(&rng, heap, devId);
- #else
- ret = wc_InitRng(&rng);
- (void)devId;
- #endif
- if (ret == 0) {
- if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce,
- MAX_OCSP_NONCE_SZ) == 0)
- csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ;
- wc_FreeRng(&rng);
- }
- }
- break;
- }
- if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr, heap)) != 0) {
- XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- #define CSR_FREE_ALL TLSX_CSR_Free
- #define CSR_GET_SIZE TLSX_CSR_GetSize
- #define CSR_WRITE TLSX_CSR_Write
- #define CSR_PARSE TLSX_CSR_Parse
- #else
- #define CSR_FREE_ALL(data, heap)
- #define CSR_GET_SIZE(a, b) 0
- #define CSR_WRITE(a, b, c) 0
- #define CSR_PARSE(a, b, c, d) 0
- #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
- /******************************************************************************/
- /* Certificate Status Request v2 */
- /******************************************************************************/
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
- static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap)
- {
- CertificateStatusRequestItemV2* next;
- for (; csr2; csr2 = next) {
- next = csr2->next;
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- while(csr2->requests--)
- FreeOcspRequest(&csr2->request.ocsp[csr2->requests]);
- break;
- }
- XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2,
- byte isRequest)
- {
- word16 size = 0;
- /* shut up compiler warnings */
- (void) csr2; (void) isRequest;
- #ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- CertificateStatusRequestItemV2* next;
- for (size = OPAQUE16_LEN; csr2; csr2 = next) {
- next = csr2->next;
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- size += ENUM_LEN + 3 * OPAQUE16_LEN;
- if (csr2->request.ocsp[0].nonceSz)
- size += OCSP_NONCE_EXT_SZ;
- break;
- }
- }
- }
- #endif
- return size;
- }
- static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2,
- byte* output, byte isRequest)
- {
- /* shut up compiler warnings */
- (void) csr2; (void) output; (void) isRequest;
- #ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- word16 offset;
- word16 length;
- for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) {
- /* status_type */
- output[offset++] = csr2->status_type;
- /* request */
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* request_length */
- length = 2 * OPAQUE16_LEN;
- if (csr2->request.ocsp[0].nonceSz)
- length += OCSP_NONCE_EXT_SZ;
- c16toa(length, output + offset);
- offset += OPAQUE16_LEN;
- /* responder id list */
- c16toa(0, output + offset);
- offset += OPAQUE16_LEN;
- /* request extensions */
- length = 0;
- if (csr2->request.ocsp[0].nonceSz)
- length = (word16)EncodeOcspRequestExtensions(
- &csr2->request.ocsp[0],
- output + offset + OPAQUE16_LEN,
- OCSP_NONCE_EXT_SZ);
- c16toa(length, output + offset);
- offset += OPAQUE16_LEN + length;
- break;
- }
- }
- /* list size */
- c16toa(offset - OPAQUE16_LEN, output);
- return offset;
- }
- #endif
- return 0;
- }
- static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- int ret;
- /* shut up compiler warnings */
- (void) ssl; (void) input;
- if (!isRequest) {
- #ifndef NO_WOLFSSL_CLIENT
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
- if (!csr2) {
- /* look at context level */
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2);
- csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
- if (!csr2) /* unexpected extension */
- return TLSX_HandleUnsupportedExtension(ssl);
- /* enable extension at ssl level */
- for (; csr2; csr2 = csr2->next) {
- ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
- csr2->status_type, csr2->options, ssl->heap,
- ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- /* followed by */
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* propagate nonce */
- if (csr2->request.ocsp[0].nonceSz) {
- OcspRequest* request =
- (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
- csr2->status_type, 0);
- if (request) {
- XMEMCPY(request->nonce,
- csr2->request.ocsp[0].nonce,
- csr2->request.ocsp[0].nonceSz);
- request->nonceSz =
- csr2->request.ocsp[0].nonceSz;
- }
- }
- break;
- }
- }
- }
- ssl->status_request_v2 = 1;
- return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */
- #endif
- }
- else {
- #ifndef NO_WOLFSSL_SERVER
- byte status_type;
- word16 request_length;
- word16 offset = 0;
- word16 size = 0;
- /* list size */
- if (offset + OPAQUE16_LEN >= length) {
- return BUFFER_E;
- }
- ato16(input + offset, &request_length);
- offset += OPAQUE16_LEN;
- if (length - OPAQUE16_LEN != request_length)
- return BUFFER_ERROR;
- while (length > offset) {
- if ((int)(length - offset) < ENUM_LEN + OPAQUE16_LEN)
- return BUFFER_ERROR;
- status_type = input[offset++];
- ato16(input + offset, &request_length);
- offset += OPAQUE16_LEN;
- if (length - offset < request_length)
- return BUFFER_ERROR;
- switch (status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* skip responder_id_list */
- if ((int)(length - offset) < OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input + offset, &size);
- if (length - offset < size)
- return BUFFER_ERROR;
- offset += OPAQUE16_LEN + size;
- /* skip request_extensions */
- if ((int)(length - offset) < OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input + offset, &size);
- if (length - offset < size)
- return BUFFER_ERROR;
- offset += OPAQUE16_LEN + size;
- if (offset > length)
- return BUFFER_ERROR;
- /* is able to send OCSP response? */
- if (ssl->ctx->cm == NULL
- || !ssl->ctx->cm->ocspStaplingEnabled)
- continue;
- break;
- default:
- /* unknown status type, skipping! */
- offset += request_length;
- continue;
- }
- /* if using status_request and already sending it, skip this one */
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- if (ssl->status_request)
- return 0;
- #endif
- /* TLS 1.3 servers MUST NOT act upon presence or information in
- * this extension (RFC 8448 Section 4.4.2.1).
- */
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- /* accept the first good status_type and return */
- ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
- status_type, 0, ssl->heap, ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
- TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2);
- ssl->status_request_v2 = status_type;
- }
- return 0;
- }
- #endif
- }
- return 0;
- }
- int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer,
- void* heap)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
- int ret = 0;
- for (; csr2; csr2 = csr2->next) {
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- if (!isPeer || csr2->requests != 0)
- break;
- FALL_THROUGH; /* followed by */
- case WOLFSSL_CSR2_OCSP_MULTI: {
- if (csr2->requests < 1 + MAX_CHAIN_DEPTH) {
- byte nonce[MAX_OCSP_NONCE_SZ];
- int nonceSz = csr2->request.ocsp[0].nonceSz;
- /* preserve nonce, replicating nonce of ocsp[0] */
- XMEMCPY(nonce, csr2->request.ocsp[0].nonce, nonceSz);
- if ((ret = InitOcspRequest(
- &csr2->request.ocsp[csr2->requests], cert,
- 0, heap)) != 0)
- return ret;
- /* restore nonce */
- XMEMCPY(csr2->request.ocsp[csr2->requests].nonce,
- nonce, nonceSz);
- csr2->request.ocsp[csr2->requests].nonceSz = nonceSz;
- csr2->requests++;
- }
- }
- break;
- }
- }
- (void)cert;
- return ret;
- }
- void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx)
- {
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
- for (; csr2; csr2 = csr2->next) {
- if (csr2->status_type == status_type) {
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- /* followed by */
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* requests are initialized in the reverse order */
- return idx < csr2->requests
- ? &csr2->request.ocsp[csr2->requests - idx - 1]
- : NULL;
- break;
- }
- }
- }
- return NULL;
- }
- int TLSX_CSR2_ForceRequest(WOLFSSL* ssl)
- {
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
- /* forces only the first one */
- if (csr2) {
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- /* followed by */
- case WOLFSSL_CSR2_OCSP_MULTI:
- if (ssl->ctx->cm->ocspEnabled) {
- csr2->request.ocsp[0].ssl = ssl;
- return CheckOcspRequest(ssl->ctx->cm->ocsp,
- &csr2->request.ocsp[0], NULL);
- }
- else
- return OCSP_LOOKUP_FAIL;
- }
- }
- return 0;
- }
- int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type,
- byte options, void* heap, int devId)
- {
- TLSX* extension = NULL;
- CertificateStatusRequestItemV2* csr2 = NULL;
- int ret = 0;
- if (!extensions)
- return BAD_FUNC_ARG;
- if (status_type != WOLFSSL_CSR2_OCSP
- && status_type != WOLFSSL_CSR2_OCSP_MULTI)
- return BAD_FUNC_ARG;
- csr2 = (CertificateStatusRequestItemV2*)
- XMALLOC(sizeof(CertificateStatusRequestItemV2), heap, DYNAMIC_TYPE_TLSX);
- if (!csr2)
- return MEMORY_E;
- ForceZero(csr2, sizeof(CertificateStatusRequestItemV2));
- csr2->status_type = status_type;
- csr2->options = options;
- csr2->next = NULL;
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) {
- WC_RNG rng;
- #ifndef HAVE_FIPS
- ret = wc_InitRng_ex(&rng, heap, devId);
- #else
- ret = wc_InitRng(&rng);
- (void)devId;
- #endif
- if (ret == 0) {
- if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce,
- MAX_OCSP_NONCE_SZ) == 0)
- csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ;
- wc_FreeRng(&rng);
- }
- }
- break;
- }
- /* append new item */
- if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) {
- CertificateStatusRequestItemV2* last =
- (CertificateStatusRequestItemV2*)extension->data;
- for (; last->next; last = last->next);
- last->next = csr2;
- }
- else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2,heap))) {
- XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- #define CSR2_FREE_ALL TLSX_CSR2_FreeAll
- #define CSR2_GET_SIZE TLSX_CSR2_GetSize
- #define CSR2_WRITE TLSX_CSR2_Write
- #define CSR2_PARSE TLSX_CSR2_Parse
- #else
- #define CSR2_FREE_ALL(data, heap)
- #define CSR2_GET_SIZE(a, b) 0
- #define CSR2_WRITE(a, b, c) 0
- #define CSR2_PARSE(a, b, c, d) 0
- #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
- /******************************************************************************/
- /* Supported Elliptic Curves */
- /******************************************************************************/
- #ifdef HAVE_SUPPORTED_CURVES
- #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \
- && !defined(HAVE_FFDHE)
- #error Elliptic Curves Extension requires Elliptic Curve Cryptography. \
- Use --enable-ecc in the configure script or define HAVE_ECC. \
- Alternatively use FFDHE for DH ciphersuites.
- #endif
- static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name,
- void* heap)
- {
- if (curve == NULL)
- return BAD_FUNC_ARG;
- (void)heap;
- *curve = (SupportedCurve*)XMALLOC(sizeof(SupportedCurve), heap,
- DYNAMIC_TYPE_TLSX);
- if (*curve == NULL)
- return MEMORY_E;
- (*curve)->name = name;
- (*curve)->next = NULL;
- return 0;
- }
- static int TLSX_PointFormat_New(PointFormat** point, byte format, void* heap)
- {
- if (point == NULL)
- return BAD_FUNC_ARG;
- (void)heap;
- *point = (PointFormat*)XMALLOC(sizeof(PointFormat), heap,
- DYNAMIC_TYPE_TLSX);
- if (*point == NULL)
- return MEMORY_E;
- (*point)->format = format;
- (*point)->next = NULL;
- return 0;
- }
- static void TLSX_SupportedCurve_FreeAll(SupportedCurve* list, void* heap)
- {
- SupportedCurve* curve;
- while ((curve = list)) {
- list = curve->next;
- XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- static void TLSX_PointFormat_FreeAll(PointFormat* list, void* heap)
- {
- PointFormat* point;
- while ((point = list)) {
- list = point->next;
- XFREE(point, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name,
- void* heap)
- {
- int ret = BAD_FUNC_ARG;
- while (list) {
- if (list->name == name) {
- ret = 0; /* curve already in use */
- break;
- }
- if (list->next == NULL) {
- ret = TLSX_SupportedCurve_New(&list->next, name, heap);
- break;
- }
- list = list->next;
- }
- return ret;
- }
- static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap)
- {
- int ret = BAD_FUNC_ARG;
- while (list) {
- if (list->format == format) {
- ret = 0; /* format already in use */
- break;
- }
- if (list->next == NULL) {
- ret = TLSX_PointFormat_New(&list->next, format, heap);
- break;
- }
- list = list->next;
- }
- return ret;
- }
- #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
- static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
- {
- word16 i;
- for (i = 0; i < ssl->suites->suiteSz; i+= 2) {
- if (ssl->suites->suites[i] == TLS13_BYTE)
- return;
- if (ssl->suites->suites[i] == ECC_BYTE ||
- ssl->suites->suites[i] == CHACHA_BYTE) {
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
- defined(HAVE_CURVE448)
- return;
- #endif
- }
- else {
- #ifdef HAVE_FFDHE
- return;
- #endif
- }
- }
- /* turns semaphore on to avoid sending this extension. */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS));
- }
- static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
- {
- word16 i;
- for (i = 0; i < ssl->suites->suiteSz; i+= 2) {
- if (ssl->suites->suites[i] == TLS13_BYTE)
- return;
- if (ssl->suites->suites[i] == ECC_BYTE ||
- ssl->suites->suites[i] == CHACHA_BYTE) {
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
- defined(HAVE_CURVE448)
- return;
- #endif
- }
- }
- #ifdef HAVE_FFDHE
- return;
- #endif
- /* turns semaphore on to avoid sending this extension. */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- }
- #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
- #ifndef NO_WOLFSSL_SERVER
- static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore)
- {
- #if defined(HAVE_FFDHE) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
- defined(HAVE_CURVE448)
- (void)semaphore;
- #endif
- if (ssl->options.cipherSuite0 == TLS13_BYTE)
- return;
- if (ssl->options.cipherSuite0 == ECC_BYTE ||
- ssl->options.cipherSuite0 == CHACHA_BYTE) {
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
- return;
- #endif
- }
- else {
- #ifdef HAVE_FFDHE
- return;
- #endif
- }
- #if !defined(HAVE_FFDHE) || (!defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \
- && !defined(HAVE_CURVE448))
- /* turns semaphore on to avoid sending this extension. */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- #endif
- }
- #endif /* !NO_WOLFSSL_SERVER */
- #ifndef NO_WOLFSSL_CLIENT
- static word16 TLSX_SupportedCurve_GetSize(SupportedCurve* list)
- {
- SupportedCurve* curve;
- word16 length = OPAQUE16_LEN; /* list length */
- while ((curve = list)) {
- list = curve->next;
- length += OPAQUE16_LEN; /* curve length */
- }
- return length;
- }
- #endif
- static word16 TLSX_PointFormat_GetSize(PointFormat* list)
- {
- PointFormat* point;
- word16 length = ENUM_LEN; /* list length */
- while ((point = list)) {
- list = point->next;
- length += ENUM_LEN; /* format length */
- }
- return length;
- }
- #ifndef NO_WOLFSSL_CLIENT
- static word16 TLSX_SupportedCurve_Write(SupportedCurve* list, byte* output)
- {
- word16 offset = OPAQUE16_LEN;
- while (list) {
- c16toa(list->name, output + offset);
- offset += OPAQUE16_LEN;
- list = list->next;
- }
- c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
- return offset;
- }
- #endif
- static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output)
- {
- word16 offset = ENUM_LEN;
- while (list) {
- output[offset++] = list->format;
- list = list->next;
- }
- output[0] = (byte)(offset - ENUM_LEN);
- return offset;
- }
- #if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
- !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
- static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- word16 offset;
- word16 name;
- int ret;
- if(!isRequest && !IsAtLeastTLSv1_3(ssl->version)) {
- #ifdef WOLFSSL_ALLOW_SERVER_SC_EXT
- return 0;
- #else
- return BUFFER_ERROR; /* servers doesn't send this extension. */
- #endif
- }
- if (OPAQUE16_LEN > length || length % OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input, &offset);
- /* validating curve list length */
- if (length != OPAQUE16_LEN + offset)
- return BUFFER_ERROR;
- offset = OPAQUE16_LEN;
- if (offset == length)
- return 0;
- #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
- if (!isRequest) {
- TLSX* extension;
- SupportedCurve* curve;
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (extension != NULL) {
- /* Replace client list with server list of supported groups. */
- curve = (SupportedCurve*)extension->data;
- extension->data = NULL;
- TLSX_SupportedCurve_FreeAll(curve, ssl->heap);
- ato16(input + offset, &name);
- offset += OPAQUE16_LEN;
- ret = TLSX_SupportedCurve_New(&curve, name, ssl->heap);
- if (ret != 0)
- return ret; /* throw error */
- extension->data = (void*)curve;
- }
- }
- #endif
- for (; offset < length; offset += OPAQUE16_LEN) {
- ato16(input + offset, &name);
- ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
- }
- return 0;
- }
- #endif
- #if !defined(NO_WOLFSSL_SERVER)
- #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
- /* Checks the priority of the groups on the server and set the supported groups
- * response if there is a group not advertised by the client that is preferred.
- *
- * ssl SSL/TLS object.
- * returns 0 on success, otherwise an error.
- */
- int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl)
- {
- int ret;
- TLSX* extension;
- TLSX* priority = NULL;
- TLSX* ext = NULL;
- word16 name;
- SupportedCurve* curve;
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- /* May be doing PSK with no key exchange. */
- if (extension == NULL)
- return 0;
- if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS)
- return ret;
- ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
- if (ext == NULL) {
- WOLFSSL_MSG("Could not find supported groups extension");
- return 0;
- }
- curve = (SupportedCurve*)ext->data;
- name = curve->name;
- curve = (SupportedCurve*)extension->data;
- while (curve != NULL) {
- if (curve->name == name)
- break;
- curve = curve->next;
- }
- if (curve == NULL) {
- /* Couldn't find the preferred group in client list. */
- extension->resp = 1;
- /* Send server list back and free client list. */
- curve = (SupportedCurve*)extension->data;
- extension->data = ext->data;
- ext->data = curve;
- }
- TLSX_FreeAll(priority, ssl->heap);
- return 0;
- }
- #endif /* WOLFSSL_TLS13 && !WOLFSSL_NO_SERVER_GROUPS_EXT */
- #if defined(HAVE_FFDHE) && !defined(WOLFSSL_NO_TLS12)
- /* Set the highest priority common FFDHE group on the server as compared to
- * client extensions.
- *
- * ssl SSL/TLS object.
- * returns 0 on success, otherwise an error.
- */
- int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl)
- {
- int ret = 0;
- TLSX* extension;
- TLSX* priority = NULL;
- TLSX* ext = NULL;
- SupportedCurve* serverGroup;
- SupportedCurve* clientGroup;
- SupportedCurve* group;
- const DhParams* params = NULL;
- int found = 0;
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- /* May be doing PSK with no key exchange. */
- if (extension == NULL)
- return 0;
- clientGroup = (SupportedCurve*)extension->data;
- for (group = clientGroup; group != NULL; group = group->next) {
- if (group->name >= MIN_FFHDE_GROUP && group->name <= MAX_FFHDE_GROUP) {
- found = 1;
- break;
- }
- }
- if (!found)
- return 0;
- if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- }
- if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- }
- ssl->buffers.serverDH_P.buffer = NULL;
- ssl->buffers.serverDH_G.buffer = NULL;
- ssl->buffers.weOwnDH = 0;
- ssl->options.haveDH = 0;
- if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) {
- TLSX_FreeAll(priority, ssl->heap);
- return ret;
- }
- ret = 0;
- ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
- serverGroup = (SupportedCurve*)ext->data;
- for (; serverGroup != NULL; serverGroup = serverGroup->next) {
- if ((serverGroup->name & NAMED_DH_MASK) != NAMED_DH_MASK)
- continue;
- for (group = clientGroup; group != NULL; group = group->next) {
- if (serverGroup->name != group->name)
- continue;
- switch (serverGroup->name) {
- #ifdef HAVE_FFDHE_2048
- case WOLFSSL_FFDHE_2048:
- params = wc_Dh_ffdhe2048_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_3072
- case WOLFSSL_FFDHE_3072:
- params = wc_Dh_ffdhe3072_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_4096
- case WOLFSSL_FFDHE_4096:
- params = wc_Dh_ffdhe4096_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_6144
- case WOLFSSL_FFDHE_6144:
- params = wc_Dh_ffdhe6144_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_8192
- case WOLFSSL_FFDHE_8192:
- params = wc_Dh_ffdhe8192_Get();
- break;
- #endif
- }
- if (params == NULL)
- return BAD_FUNC_ARG;
- if (params->p_len >= ssl->options.minDhKeySz &&
- params->p_len <= ssl->options.maxDhKeySz) {
- break;
- }
- }
- if (group != NULL && serverGroup->name == group->name)
- break;
- }
- if (serverGroup) {
- ssl->buffers.serverDH_P.buffer = (unsigned char *)params->p;
- ssl->buffers.serverDH_P.length = params->p_len;
- ssl->buffers.serverDH_G.buffer = (unsigned char *)params->g;
- ssl->buffers.serverDH_G.length = params->g_len;
- ssl->namedGroup = serverGroup->name;
- #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
- !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
- ssl->options.dhDoKeyTest = 0;
- #endif
- ssl->options.haveDH = 1;
- }
- TLSX_FreeAll(priority, ssl->heap);
- return ret;
- }
- #endif /* HAVE_FFDHE && !WOLFSSL_NO_TLS12 */
- #endif /* !NO_WOLFSSL_SERVER */
- #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
- /* Return the preferred group.
- *
- * ssl SSL/TLS object.
- * checkSupported Whether to check for the first supported group.
- * returns BAD_FUNC_ARG if no group found, otherwise the group.
- */
- int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported)
- {
- TLSX* extension;
- SupportedCurve* curve;
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (extension == NULL)
- return BAD_FUNC_ARG;
- curve = (SupportedCurve*)extension->data;
- while (curve != NULL) {
- if (!checkSupported || TLSX_KeyShare_IsSupported(curve->name))
- return curve->name;
- curve = curve->next;
- }
- return BAD_FUNC_ARG;
- }
- #endif /* HAVE_SUPPORTED_CURVES */
- #ifndef NO_WOLFSSL_SERVER
- static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- int ret;
- /* validating formats list length */
- if (ENUM_LEN > length || length != (word16)ENUM_LEN + input[0])
- return BUFFER_ERROR;
- if (isRequest) {
- /* adding uncompressed point format to response */
- ret = TLSX_UsePointFormat(&ssl->extensions, WOLFSSL_EC_PF_UNCOMPRESSED,
- ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
- TLSX_SetResponse(ssl, TLSX_EC_POINT_FORMATS);
- }
- return 0;
- }
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
- int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) {
- TLSX* extension = NULL;
- SupportedCurve* curve = NULL;
- word32 oid = 0;
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_ED25519) || \
- defined(HAVE_CURVE448) || defined(HAVE_ED448) || \
- (!defined(NO_RSA) && defined(WOLFSSL_STATIC_DH))
- word32 pkOid = 0;
- #endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 || (!NO_RSA && STATIC_DH) */
- word32 defOid = 0;
- word32 defSz = 80; /* Maximum known curve size is 66. */
- word32 nextOid = 0;
- word32 nextSz = 80; /* Maximum known curve size is 66. */
- word32 currOid = ssl->ecdhCurveOID;
- int ephmSuite = 0;
- word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */
- int sig = 0; /* validate signature */
- int key = 0; /* validate key */
- (void)oid;
- (void)pkOid;
- if (first == CHACHA_BYTE) {
- switch (second) {
- case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
- case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
- case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
- return 1; /* no suite restriction */
- case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
- case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
- break;
- }
- }
- if (first == ECC_BYTE || first == CHACHA_BYTE)
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (!extension)
- return 1; /* no suite restriction */
- for (curve = (SupportedCurve*)extension->data;
- curve && !(sig && key);
- curve = curve->next) {
- #ifdef OPENSSL_EXTRA
- /* skip if name is not in supported ECC range */
- if (curve->name > WOLFSSL_ECC_X448)
- continue;
- /* skip if curve is disabled by user */
- if (ssl->ctx->disabledCurves & (1 << curve->name))
- continue;
- #endif
- /* find supported curve */
- switch (curve->name) {
- #ifdef HAVE_ECC
- #if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP160R1:
- pkOid = oid = ECC_SECP160R1_OID;
- octets = 20;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_SECPR2
- case WOLFSSL_ECC_SECP160R2:
- pkOid = oid = ECC_SECP160R2_OID;
- octets = 20;
- break;
- #endif /* HAVE_ECC_SECPR2 */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP160K1:
- pkOid = oid = ECC_SECP160K1_OID;
- octets = 20;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #endif
- #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP192R1:
- pkOid = oid = ECC_SECP192R1_OID;
- octets = 24;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP192K1:
- pkOid = oid = ECC_SECP192K1_OID;
- octets = 24;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #endif
- #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP224R1:
- pkOid = oid = ECC_SECP224R1_OID;
- octets = 28;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP224K1:
- pkOid = oid = ECC_SECP224K1_OID;
- octets = 28;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #endif
- #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- pkOid = oid = ECC_SECP256R1_OID;
- octets = 32;
- break;
- #endif /* !NO_ECC_SECP */
- #endif /* !NO_ECC256 || HAVE_ALL_CURVES */
- #endif
- #if (defined(HAVE_CURVE25519) || defined(HAVE_ED25519)) && ECC_MIN_KEY_SZ <= 256
- case WOLFSSL_ECC_X25519:
- oid = ECC_X25519_OID;
- #ifdef HAVE_ED25519
- pkOid = ECC_ED25519_OID;
- #else
- pkOid = ECC_X25519_OID;
- #endif
- octets = 32;
- break;
- #endif /* HAVE_CURVE25519 */
- #ifdef HAVE_ECC
- #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP256K1:
- pkOid = oid = ECC_SECP256K1_OID;
- octets = 32;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP256R1:
- pkOid = oid = ECC_BRAINPOOLP256R1_OID;
- octets = 32;
- break;
- #endif /* HAVE_ECC_BRAINPOOL */
- #endif
- #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP384R1:
- pkOid = oid = ECC_SECP384R1_OID;
- octets = 48;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP384R1:
- pkOid = oid = ECC_BRAINPOOLP384R1_OID;
- octets = 48;
- break;
- #endif /* HAVE_ECC_BRAINPOOL */
- #endif
- #endif
- #if (defined(HAVE_CURVE448) || defined(HAVE_ED448)) && ECC_MIN_KEY_SZ <= 448
- case WOLFSSL_ECC_X448:
- oid = ECC_X448_OID;
- #ifdef HAVE_ED448
- pkOid = ECC_ED448_OID;
- #else
- pkOid = ECC_X448_OID;
- #endif
- octets = 57;
- break;
- #endif /* HAVE_CURVE448 */
- #ifdef HAVE_ECC
- #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP512R1:
- pkOid = oid = ECC_BRAINPOOLP512R1_OID;
- octets = 64;
- break;
- #endif /* HAVE_ECC_BRAINPOOL */
- #endif
- #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- pkOid = oid = ECC_SECP521R1_OID;
- octets = 66;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #endif
- default: continue; /* unsupported curve */
- }
- #ifdef HAVE_ECC
- /* Set default Oid */
- if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) {
- defOid = oid;
- defSz = octets;
- }
- /* The eccTempKeySz is the preferred ephemeral key size */
- if (currOid == 0 && ssl->eccTempKeySz == octets)
- currOid = oid;
- if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) {
- nextOid = oid;
- nextSz = octets;
- }
- #else
- if (defOid == 0 && defSz > octets) {
- defOid = oid;
- defSz = octets;
- }
- if (currOid == 0)
- currOid = oid;
- if (nextOid == 0 || nextSz > octets) {
- nextOid = oid;
- nextSz = octets;
- }
- #endif
- if (first == ECC_BYTE) {
- switch (second) {
- #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
- /* ECDHE_ECDSA */
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
- case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
- sig |= ssl->pkCurveOID == pkOid;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
- #ifdef WOLFSSL_STATIC_DH
- /* ECDH_ECDSA */
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- if (oid == ECC_X25519_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- if (oid == ECC_X448_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- sig |= ssl->pkCurveOID == pkOid;
- key |= ssl->pkCurveOID == oid;
- break;
- #endif /* WOLFSSL_STATIC_DH */
- #endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
- #ifndef NO_RSA
- /* ECDHE_RSA */
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- sig = 1;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
- #ifdef WOLFSSL_STATIC_DH
- /* ECDH_RSA */
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDH_RSA_WITH_RC4_128_SHA:
- case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- if (oid == ECC_X25519_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- if (oid == ECC_X448_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- sig = 1;
- key |= ssl->pkCurveOID == pkOid;
- break;
- #endif /* WOLFSSL_STATIC_DH */
- #endif
- default:
- if (oid == ECC_X25519_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- if (oid == ECC_X448_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- if (oid != ECC_X25519_OID && oid != ECC_X448_OID) {
- sig = 1;
- }
- key = 1;
- break;
- }
- }
- /* ChaCha20-Poly1305 ECC cipher suites */
- if (first == CHACHA_BYTE) {
- switch (second) {
- #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
- /* ECDHE_ECDSA */
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
- sig |= ssl->pkCurveOID == pkOid;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
- #endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
- #ifndef NO_RSA
- /* ECDHE_RSA */
- case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
- case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
- sig = 1;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
- #endif
- default:
- sig = 1;
- key = 1;
- break;
- }
- }
- }
- /* Choose the default if it is at the required strength. */
- #ifdef HAVE_ECC
- if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz)
- #else
- if (ssl->ecdhCurveOID == 0)
- #endif
- {
- key = 1;
- ssl->ecdhCurveOID = defOid;
- }
- /* Choose any curve at the required strength. */
- if (ssl->ecdhCurveOID == 0) {
- key = 1;
- ssl->ecdhCurveOID = currOid;
- }
- /* Choose the default if it is at the next highest strength. */
- if (ssl->ecdhCurveOID == 0 && defSz == nextSz)
- ssl->ecdhCurveOID = defOid;
- /* Choose any curve at the next highest strength. */
- if (ssl->ecdhCurveOID == 0)
- ssl->ecdhCurveOID = nextOid;
- /* No curve and ephemeral ECC suite requires a matching curve. */
- if (ssl->ecdhCurveOID == 0 && ephmSuite)
- key = 0;
- return sig && key;
- }
- #endif
- #endif /* NO_WOLFSSL_SERVER */
- int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap)
- {
- TLSX* extension = NULL;
- SupportedCurve* curve = NULL;
- int ret;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS);
- if (!extension) {
- ret = TLSX_SupportedCurve_New(&curve, name, heap);
- if (ret != 0)
- return ret;
- ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap);
- if (ret != 0) {
- XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- }
- else {
- ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data, name,
- heap);
- if (ret != 0)
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap)
- {
- TLSX* extension = NULL;
- PointFormat* point = NULL;
- int ret = 0;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- extension = TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS);
- if (!extension) {
- ret = TLSX_PointFormat_New(&point, format, heap);
- if (ret != 0)
- return ret;
- ret = TLSX_Push(extensions, TLSX_EC_POINT_FORMATS, point, heap);
- if (ret != 0) {
- XFREE(point, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- }
- else {
- ret = TLSX_PointFormat_Append((PointFormat*)extension->data, format,
- heap);
- if (ret != 0)
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- #define EC_FREE_ALL TLSX_SupportedCurve_FreeAll
- #define EC_VALIDATE_REQUEST TLSX_SupportedCurve_ValidateRequest
- #ifndef NO_WOLFSSL_CLIENT
- #define EC_GET_SIZE TLSX_SupportedCurve_GetSize
- #define EC_WRITE TLSX_SupportedCurve_Write
- #else
- #define EC_GET_SIZE(list) 0
- #define EC_WRITE(a, b) 0
- #endif
- #if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
- !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
- #define EC_PARSE TLSX_SupportedCurve_Parse
- #else
- #define EC_PARSE(a, b, c, d) 0
- #endif
- #define PF_FREE_ALL TLSX_PointFormat_FreeAll
- #define PF_VALIDATE_REQUEST TLSX_PointFormat_ValidateRequest
- #define PF_VALIDATE_RESPONSE TLSX_PointFormat_ValidateResponse
- #define PF_GET_SIZE TLSX_PointFormat_GetSize
- #define PF_WRITE TLSX_PointFormat_Write
- #ifndef NO_WOLFSSL_SERVER
- #define PF_PARSE TLSX_PointFormat_Parse
- #else
- #define PF_PARSE(a, b, c, d) 0
- #endif
- #else
- #define EC_FREE_ALL(list, heap)
- #define EC_GET_SIZE(list) 0
- #define EC_WRITE(a, b) 0
- #define EC_PARSE(a, b, c, d) 0
- #define EC_VALIDATE_REQUEST(a, b)
- #define PF_FREE_ALL(list, heap)
- #define PF_GET_SIZE(list) 0
- #define PF_WRITE(a, b) 0
- #define PF_PARSE(a, b, c, d) 0
- #define PF_VALIDATE_REQUEST(a, b)
- #define PF_VALIDATE_RESPONSE(a, b)
- #endif /* HAVE_SUPPORTED_CURVES */
- /******************************************************************************/
- /* Renegotiation Indication */
- /******************************************************************************/
- #if defined(HAVE_SECURE_RENEGOTIATION) \
- || defined(HAVE_SERVER_RENEGOTIATION_INFO)
- static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data,
- int isRequest)
- {
- byte length = OPAQUE8_LEN; /* empty info length */
- /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */
- if (data && data->enabled && data->verifySet) {
- /* client sends client_verify_data only */
- length += TLS_FINISHED_SZ;
- /* server also sends server_verify_data */
- if (!isRequest)
- length += TLS_FINISHED_SZ;
- }
- return length;
- }
- static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data,
- byte* output, int isRequest)
- {
- word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */
- if (data && data->enabled && data->verifySet) {
- /* client sends client_verify_data only */
- XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ);
- offset += TLS_FINISHED_SZ;
- /* server also sends server_verify_data */
- if (!isRequest) {
- XMEMCPY(output + offset, data->server_verify_data, TLS_FINISHED_SZ);
- offset += TLS_FINISHED_SZ;
- }
- }
- output[0] = (byte)(offset - 1); /* info length - self */
- return offset;
- }
- static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input,
- word16 length, byte isRequest)
- {
- int ret = SECURE_RENEGOTIATION_E;
- if (length >= OPAQUE8_LEN) {
- if (isRequest) {
- #ifndef NO_WOLFSSL_SERVER
- if (ssl->secure_renegotiation == NULL) {
- ret = wolfSSL_UseSecureRenegotiation(ssl);
- if (ret == WOLFSSL_SUCCESS)
- ret = 0;
- }
- if (ret != 0 && ret != SECURE_RENEGOTIATION_E) {
- }
- else if (!ssl->secure_renegotiation->enabled) {
- if (*input == 0) {
- input++; /* get past size */
- ssl->secure_renegotiation->enabled = 1;
- TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO);
- ret = 0;
- }
- else {
- /* already in error state */
- WOLFSSL_MSG("SCR client verify data present");
- }
- }
- else if (*input == TLS_FINISHED_SZ) {
- if (length < TLS_FINISHED_SZ + 1) {
- WOLFSSL_MSG("SCR malformed buffer");
- ret = BUFFER_E;
- }
- else {
- input++; /* get past size */
- /* validate client verify data */
- if (XMEMCMP(input,
- ssl->secure_renegotiation->client_verify_data,
- TLS_FINISHED_SZ) == 0) {
- WOLFSSL_MSG("SCR client verify data match");
- TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO);
- ret = 0; /* verified */
- } else {
- /* already in error state */
- WOLFSSL_MSG("SCR client verify data Failure");
- }
- }
- }
- #endif
- }
- else if (ssl->secure_renegotiation != NULL) {
- #ifndef NO_WOLFSSL_CLIENT
- if (!ssl->secure_renegotiation->enabled) {
- if (*input == 0) {
- ssl->secure_renegotiation->enabled = 1;
- ret = 0;
- }
- }
- else if (*input == 2 * TLS_FINISHED_SZ &&
- length == 2 * TLS_FINISHED_SZ + OPAQUE8_LEN) {
- input++; /* get past size */
- /* validate client and server verify data */
- if (XMEMCMP(input,
- ssl->secure_renegotiation->client_verify_data,
- TLS_FINISHED_SZ) == 0 &&
- XMEMCMP(input + TLS_FINISHED_SZ,
- ssl->secure_renegotiation->server_verify_data,
- TLS_FINISHED_SZ) == 0) {
- WOLFSSL_MSG("SCR client and server verify data match");
- ret = 0; /* verified */
- } else {
- /* already in error state */
- WOLFSSL_MSG("SCR client and server verify data Failure");
- }
- }
- #endif
- }
- }
- if (ret != 0) {
- SendAlert(ssl, alert_fatal, handshake_failure);
- }
- return ret;
- }
- int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap)
- {
- int ret = 0;
- SecureRenegotiation* data;
- data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), heap,
- DYNAMIC_TYPE_TLSX);
- if (data == NULL)
- return MEMORY_E;
- XMEMSET(data, 0, sizeof(SecureRenegotiation));
- ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data, heap);
- if (ret != 0) {
- XFREE(data, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- #ifdef HAVE_SERVER_RENEGOTIATION_INFO
- int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap)
- {
- int ret;
- /* send empty renegotiation_info extension */
- TLSX* ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO);
- if (ext == NULL) {
- ret = TLSX_UseSecureRenegotiation(extensions, heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO);
- }
- if (ext)
- ext->resp = 1;
- return WOLFSSL_SUCCESS;
- }
- #endif /* HAVE_SERVER_RENEGOTIATION_INFO */
- #define SCR_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
- #define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize
- #define SCR_WRITE TLSX_SecureRenegotiation_Write
- #define SCR_PARSE TLSX_SecureRenegotiation_Parse
- #else
- #define SCR_FREE_ALL(a, heap)
- #define SCR_GET_SIZE(a, b) 0
- #define SCR_WRITE(a, b, c) 0
- #define SCR_PARSE(a, b, c, d) 0
- #endif /* HAVE_SECURE_RENEGOTIATION */
- /******************************************************************************/
- /* Session Tickets */
- /******************************************************************************/
- #ifdef HAVE_SESSION_TICKET
- #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
- static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl)
- {
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET);
- SessionTicket* ticket = extension ?
- (SessionTicket*)extension->data : NULL;
- if (ticket) {
- /* TODO validate ticket timeout here! */
- if (ticket->lifetime == 0xfffffff) {
- /* send empty ticket on timeout */
- TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
- }
- }
- }
- #endif /* WLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
- static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
- {
- (void)isRequest;
- return ticket ? ticket->size : 0;
- }
- static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
- int isRequest)
- {
- word16 offset = 0; /* empty ticket */
- if (isRequest && ticket) {
- XMEMCPY(output + offset, ticket->data, ticket->size);
- offset += ticket->size;
- }
- return offset;
- }
- static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- int ret = 0;
- (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */
- if (!isRequest) {
- if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET))
- return TLSX_HandleUnsupportedExtension(ssl);
- if (length != 0)
- return BUFFER_ERROR;
- #ifndef NO_WOLFSSL_CLIENT
- ssl->expect_session_ticket = 1;
- #endif
- }
- #ifndef NO_WOLFSSL_SERVER
- else {
- /* server side */
- if (ssl->ctx->ticketEncCb == NULL) {
- WOLFSSL_MSG("Client sent session ticket, server has no callback");
- return 0;
- }
- if (length > SESSION_TICKET_LEN) {
- ret = BAD_TICKET_MSG_SZ;
- } else if (IsAtLeastTLSv1_3(ssl->version)) {
- WOLFSSL_MSG("Process client ticket rejected, TLS 1.3 no support");
- ssl->options.rejectTicket = 1;
- ret = 0; /* not fatal */
- } else if (ssl->options.noTicketTls12) {
- /* ignore ticket request */
- } else if (length == 0) {
- /* blank ticket */
- ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
- if (ret == WOLFSSL_SUCCESS) {
- ret = 0;
- /* send blank ticket */
- TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);
- ssl->options.createTicket = 1; /* will send ticket msg */
- ssl->options.useTicket = 1;
- ssl->options.resuming = 0; /* no standard resumption */
- ssl->arrays->sessionIDSz = 0; /* no echo on blank ticket */
- }
- } else {
- /* got actual ticket from client */
- ret = DoClientTicket(ssl, input, length);
- if (ret == WOLFSSL_TICKET_RET_OK) { /* use ticket to resume */
- WOLFSSL_MSG("Using existing client ticket");
- ssl->options.useTicket = 1;
- ssl->options.resuming = 1;
- } else if (ret == WOLFSSL_TICKET_RET_CREATE) {
- WOLFSSL_MSG("Using existing client ticket, creating new one");
- ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
- if (ret == WOLFSSL_SUCCESS) {
- ret = 0;
- TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);
- /* send blank ticket */
- ssl->options.createTicket = 1; /* will send ticket msg */
- ssl->options.useTicket = 1;
- ssl->options.resuming = 1;
- }
- } else if (ret == WOLFSSL_TICKET_RET_REJECT) {
- WOLFSSL_MSG("Process client ticket rejected, not using");
- ssl->options.rejectTicket = 1;
- ret = 0; /* not fatal */
- } else if (ret == VERSION_ERROR) {
- WOLFSSL_MSG("Process client ticket rejected, bad TLS version");
- ssl->options.rejectTicket = 1;
- ret = 0; /* not fatal */
- } else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) {
- WOLFSSL_MSG("Process client ticket fatal error, not using");
- }
- }
- }
- #endif /* NO_WOLFSSL_SERVER */
- return ret;
- }
- WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
- byte* data, word16 size, void* heap)
- {
- SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket),
- heap, DYNAMIC_TYPE_TLSX);
- if (ticket) {
- ticket->data = (byte*)XMALLOC(size, heap, DYNAMIC_TYPE_TLSX);
- if (ticket->data == NULL) {
- XFREE(ticket, heap, DYNAMIC_TYPE_TLSX);
- return NULL;
- }
- XMEMCPY(ticket->data, data, size);
- ticket->size = size;
- ticket->lifetime = lifetime;
- }
- (void)heap;
- return ticket;
- }
- WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap)
- {
- if (ticket) {
- XFREE(ticket->data, heap, DYNAMIC_TYPE_TLSX);
- XFREE(ticket, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap)
- {
- int ret = 0;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- /* If the ticket is NULL, the client will request a new ticket from the
- server. Otherwise, the client will use it in the next client hello. */
- if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket, heap))
- != 0)
- return ret;
- return WOLFSSL_SUCCESS;
- }
- #define WOLF_STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest
- #define WOLF_STK_GET_SIZE TLSX_SessionTicket_GetSize
- #define WOLF_STK_WRITE TLSX_SessionTicket_Write
- #define WOLF_STK_PARSE TLSX_SessionTicket_Parse
- #define WOLF_STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap))
- #else
- #define WOLF_STK_FREE(a, b)
- #define WOLF_STK_VALIDATE_REQUEST(a)
- #define WOLF_STK_GET_SIZE(a, b) 0
- #define WOLF_STK_WRITE(a, b, c) 0
- #define WOLF_STK_PARSE(a, b, c, d) 0
- #endif /* HAVE_SESSION_TICKET */
- /******************************************************************************/
- /* Quantum-Safe-Hybrid */
- /******************************************************************************/
- #ifdef HAVE_QSH
- #if defined(HAVE_NTRU)
- static WC_RNG* gRng;
- static wolfSSL_Mutex* gRngMutex;
- #endif
- static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap)
- {
- QSHScheme* current;
- while ((current = list)) {
- list = current->next;
- XFREE(current, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- static int TLSX_QSH_Append(QSHScheme** list, word16 name, byte* pub,
- word16 pubLen)
- {
- QSHScheme* temp;
- if (list == NULL)
- return BAD_FUNC_ARG;
- if ((temp = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return MEMORY_E;
- temp->name = name;
- temp->PK = pub;
- temp->PKLen = pubLen;
- temp->next = *list;
- *list = temp;
- return 0;
- }
- /* request for server's public key : 02 indicates 0-2 requested */
- static byte TLSX_QSH_SerPKReq(byte* output, byte isRequest)
- {
- if (isRequest) {
- /* only request one public key from the server */
- output[0] = 0x01;
- return OPAQUE8_LEN;
- }
- else {
- return 0;
- }
- }
- #ifndef NO_WOLFSSL_CLIENT
- /* check for TLS_QSH suite */
- static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
- {
- int i;
- for (i = 0; i < ssl->suites->suiteSz; i+= 2)
- if (ssl->suites->suites[i] == QSH_BYTE)
- return;
- /* No QSH suite found */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_QUANTUM_SAFE_HYBRID));
- }
- /* return the size of the QSH hello extension
- list the list of QSHScheme structs containing id and key
- isRequest if 1 then is being sent to the server
- */
- word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest)
- {
- QSHScheme* temp = list;
- word16 length = 0;
- /* account for size of scheme list and public key list */
- if (isRequest)
- length = OPAQUE16_LEN;
- length += OPAQUE24_LEN;
- /* for each non null element in list add size */
- while ((temp)) {
- /* add public key info Scheme | Key Length | Key */
- length += OPAQUE16_LEN;
- length += OPAQUE16_LEN;
- length += temp->PKLen;
- /* if client add name size for scheme list
- advance to next QSHScheme struct in list */
- if (isRequest)
- length += OPAQUE16_LEN;
- temp = temp->next;
- }
- /* add length for request server public keys */
- if (isRequest)
- length += OPAQUE8_LEN;
- return length;
- }
- /* write out a list of QSHScheme IDs */
- static word16 TLSX_QSH_Write(QSHScheme* list, byte* output)
- {
- QSHScheme* current = list;
- word16 length = 0;
- length += OPAQUE16_LEN;
- while (current) {
- c16toa(current->name, output + length);
- length += OPAQUE16_LEN;
- current = (QSHScheme*)current->next;
- }
- c16toa(length - OPAQUE16_LEN, output); /* writing list length */
- return length;
- }
- /* write public key list in extension */
- static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output)
- {
- word32 offset = 0;
- word16 public_len = 0;
- if (!format)
- return offset;
- /* write scheme ID */
- c16toa(format->name, output + offset);
- offset += OPAQUE16_LEN;
- /* write public key matching scheme */
- public_len = format->PKLen;
- c16toa(public_len, output + offset);
- offset += OPAQUE16_LEN;
- if (format->PK) {
- XMEMCPY(output+offset, format->PK, public_len);
- }
- return public_len + offset;
- }
- word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output)
- {
- QSHScheme* current = list;
- word32 length = 0;
- word24 toWire;
- length += OPAQUE24_LEN;
- while (current) {
- length += TLSX_QSHPK_WriteR(current, output + length);
- current = (QSHScheme*)current->next;
- }
- /* length of public keys sent */
- c32to24(length - OPAQUE24_LEN, toWire);
- output[0] = toWire[0];
- output[1] = toWire[1];
- output[2] = toWire[2];
- return length;
- }
- #endif /* NO_WOLFSSL_CLIENT */
- #ifndef NO_WOLFSSL_SERVER
- static void TLSX_QSHAgreement(TLSX** extensions, void* heap)
- {
- TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
- QSHScheme* format = NULL;
- QSHScheme* del = NULL;
- QSHScheme* prev = NULL;
- if (extension == NULL)
- return;
- format = (QSHScheme*)extension->data;
- while (format) {
- if (format->PKLen == 0) {
- /* case of head */
- if (format == extension->data) {
- extension->data = format->next;
- }
- if (prev)
- prev->next = format->next;
- del = format;
- format = format->next;
- XFREE(del, heap, DYNAMIC_TYPE_TMP_BUFFER);
- del = NULL;
- } else {
- prev = format;
- format = format->next;
- }
- }
- (void)heap;
- }
- /* Parse in hello extension
- input the byte stream to process
- length length of total extension found
- isRequest set to 1 if being sent to the server
- */
- static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
- {
- byte numKeys = 0;
- word16 offset = 0;
- word16 schemSz = 0;
- word16 offset_len = 0;
- word32 offset_pk = 0;
- word16 name = 0;
- word16 PKLen = 0;
- byte* PK = NULL;
- int r;
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
- if (isRequest) {
- ato16(input, &schemSz);
- /* list of public keys available for QSH schemes */
- offset_len = schemSz + OPAQUE16_LEN;
- }
- offset_pk = ((input[offset_len] << 16) & 0xFF00000) |
- (((input[offset_len + 1]) << 8) & 0xFF00) |
- (input[offset_len + 2] & 0xFF);
- offset_len += OPAQUE24_LEN;
- /* check buffer size */
- if (offset_pk > length)
- return BUFFER_ERROR;
- /* set maximum number of keys the client will accept */
- if (!isRequest)
- numKeys = (ssl->maxRequest < 1)? 1 : ssl->maxRequest;
- /* hello extension read list of scheme ids */
- if (isRequest) {
- /* read in request for public keys */
- ssl->minRequest = (input[length -1] >> 4) & 0xFF;
- ssl->maxRequest = input[length -1] & 0x0F;
- /* choose the min between min requested by client and 1 */
- numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1;
- if (ssl->minRequest > ssl->maxRequest)
- return BAD_FUNC_ARG;
- offset += OPAQUE16_LEN;
- schemSz += offset;
- /* check buffer size */
- if (schemSz > length)
- return BUFFER_ERROR;
- while ((offset < schemSz) && numKeys) {
- /* Scheme ID list */
- ato16(input + offset, &name);
- offset += OPAQUE16_LEN;
- /* validate we have scheme id */
- if (ssl->user_set_QSHSchemes &&
- !TLSX_ValidateQSHScheme(&ssl->extensions, name)) {
- continue;
- }
- /* server create keys on demand */
- if ((r = TLSX_CreateNtruKey(ssl, name)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return r;
- }
- /* peer sent an agreed upon scheme */
- r = TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap);
- if (r != WOLFSSL_SUCCESS) return r; /* throw error */
- numKeys--;
- }
- /* choose the min between min requested by client and 1 */
- numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1;
- }
- /* QSHPK struct */
- offset_pk += offset_len;
- while ((offset_len < offset_pk) && numKeys) {
- QSHKey * temp;
- if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return MEMORY_E;
- /* initialize */
- temp->next = NULL;
- temp->pub.buffer = NULL;
- temp->pub.length = 0;
- temp->pri.buffer = NULL;
- temp->pri.length = 0;
- /* scheme id */
- ato16(input + offset_len, &(temp->name));
- offset_len += OPAQUE16_LEN;
- /* public key length */
- ato16(input + offset_len, &PKLen);
- temp->pub.length = PKLen;
- offset_len += OPAQUE16_LEN;
- if (isRequest) {
- /* validate we have scheme id */
- if (ssl->user_set_QSHSchemes &&
- (!TLSX_ValidateQSHScheme(&ssl->extensions, temp->name))) {
- offset_len += PKLen;
- XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX);
- continue;
- }
- }
- /* read in public key */
- if (PKLen > 0) {
- temp->pub.buffer = (byte*)XMALLOC(temp->pub.length,
- ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- XMEMCPY(temp->pub.buffer, input + offset_len, temp->pub.length);
- offset_len += PKLen;
- }
- else {
- PK = NULL;
- }
- /* use own key when adding to extensions list for sending reply */
- PKLen = 0;
- PK = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, &PKLen, temp->name);
- r = TLSX_UseQSHScheme(&ssl->extensions, temp->name, PK, PKLen,
- ssl->heap);
- /* store peers key */
- ssl->peerQSHKeyPresent = 1;
- if (TLSX_AddQSHKey(&ssl->peerQSHKey, temp) != 0)
- return MEMORY_E;
- if (temp->pub.length == 0) {
- XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX);
- }
- if (r != WOLFSSL_SUCCESS) {return r;} /* throw error */
- numKeys--;
- }
- /* reply to a QSH extension sent from client */
- if (isRequest) {
- TLSX_SetResponse(ssl, TLSX_QUANTUM_SAFE_HYBRID);
- /* only use schemes we have key generated for -- free the rest */
- TLSX_QSHAgreement(&ssl->extensions, ssl->heap);
- }
- return 0;
- }
- /* Used for parsing in QSHCipher structs on Key Exchange */
- int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length,
- byte isServer)
- {
- QSHKey* key;
- word16 Max_Secret_Len = 48;
- word16 offset = 0;
- word16 offset_len = 0;
- word32 offset_pk = 0;
- word16 name = 0;
- word16 secretLen = 0;
- byte* secret = NULL;
- word16 buffLen = 0;
- byte buff[145]; /* size enough for 3 secrets */
- buffer* buf;
- /* pointer to location where secret should be stored */
- if (isServer) {
- buf = ssl->QSH_secret->CliSi;
- }
- else {
- buf = ssl->QSH_secret->SerSi;
- }
- offset_pk = ((input[offset_len] << 16) & 0xFF0000) |
- (((input[offset_len + 1]) << 8) & 0xFF00) |
- (input[offset_len + 2] & 0xFF);
- offset_len += OPAQUE24_LEN;
- /* validating extension list length -- check if trying to read over edge
- of buffer */
- if (length < (offset_pk + OPAQUE24_LEN)) {
- return BUFFER_ERROR;
- }
- /* QSHCipherList struct */
- offset_pk += offset_len;
- while (offset_len < offset_pk) {
- /* scheme id */
- ato16(input + offset_len, &name);
- offset_len += OPAQUE16_LEN;
- /* public key length */
- ato16(input + offset_len, &secretLen);
- offset_len += OPAQUE16_LEN;
- /* read in public key */
- if (secretLen > 0) {
- secret = (byte*)(input + offset_len);
- offset_len += secretLen;
- }
- else {
- secret = NULL;
- }
- /* no secret sent */
- if (secret == NULL)
- continue;
- /* find corresponding key */
- key = ssl->QSH_Key;
- while (key) {
- if (key->name == name)
- break;
- else
- key = (QSHKey*)key->next;
- }
- /* if we do not have the key than there was a big issue negotiation */
- if (key == NULL) {
- WOLFSSL_MSG("key was null for decryption!!!\n");
- return MEMORY_E;
- }
- /* Decrypt sent secret */
- buffLen = Max_Secret_Len;
- QSH_Decrypt(key, secret, secretLen, buff + offset, &buffLen);
- offset += buffLen;
- }
- /* allocate memory for buffer */
- buf->length = offset;
- buf->buffer = (byte*)XMALLOC(offset, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf->buffer == NULL)
- return MEMORY_E;
- /* store secrets */
- XMEMCPY(buf->buffer, buff, offset);
- ForceZero(buff, offset);
- return offset_len;
- }
- /* return 1 on success */
- int TLSX_ValidateQSHScheme(TLSX** extensions, word16 theirs) {
- TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
- QSHScheme* format = NULL;
- /* if no extension is sent then do not use QSH */
- if (!extension) {
- WOLFSSL_MSG("No QSH Extension");
- return 0;
- }
- for (format = (QSHScheme*)extension->data; format; format = format->next) {
- if (format->name == theirs) {
- WOLFSSL_MSG("Found Matching QSH Scheme");
- return 1; /* have QSH */
- }
- }
- return 0;
- }
- #endif /* NO_WOLFSSL_SERVER */
- /* test if the QSH Scheme is implemented
- return 1 if yes 0 if no */
- static int TLSX_HaveQSHScheme(word16 name)
- {
- switch(name) {
- #ifdef HAVE_NTRU
- case WOLFSSL_NTRU_EESS439:
- case WOLFSSL_NTRU_EESS593:
- case WOLFSSL_NTRU_EESS743:
- return 1;
- #endif
- case WOLFSSL_LWE_XXX:
- case WOLFSSL_HFE_XXX:
- return 0; /* not supported yet */
- default:
- return 0;
- }
- }
- /* Add a QSHScheme struct to list of usable ones */
- int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz,
- void* heap)
- {
- TLSX* extension = NULL;
- QSHScheme* format = NULL;
- int ret = 0;
- /* sanity check */
- if (extensions == NULL || (pKey == NULL && pkeySz != 0))
- return BAD_FUNC_ARG;
- extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
- /* if scheme is implemented than add */
- if (TLSX_HaveQSHScheme(name)) {
- if ((ret = TLSX_QSH_Append(&format, name, pKey, pkeySz)) != 0)
- return ret;
- extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
- if (!extension) {
- if ((ret = TLSX_Push(extensions, TLSX_QUANTUM_SAFE_HYBRID, format,
- heap)) != 0) {
- XFREE(format, 0, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- }
- else {
- /* push new QSH object to extension data. */
- format->next = (QSHScheme*)extension->data;
- extension->data = (void*)format;
- /* look for another format of the same name to remove (replacement) */
- do {
- if (format->next && (format->next->name == name)) {
- QSHScheme* next = format->next;
- format->next = next->next;
- XFREE(next, 0, DYNAMIC_TYPE_TLSX);
- break;
- }
- } while ((format = format->next));
- }
- }
- return WOLFSSL_SUCCESS;
- }
- #define QSH_FREE_ALL TLSX_QSH_FreeAll
- #define QSH_VALIDATE_REQUEST TLSX_QSH_ValidateRequest
- #ifndef NO_WOLFSSL_CLIENT
- #define QSH_GET_SIZE TLSX_QSH_GetSize
- #define QSH_WRITE TLSX_QSH_Write
- #else
- #define QSH_GET_SIZE(list, a) 0
- #define QSH_WRITE(a, b) 0
- #endif
- #ifndef NO_WOLFSSL_SERVER
- #define QSH_PARSE TLSX_QSH_Parse
- #else
- #define QSH_PARSE(a, b, c, d) 0
- #endif
- #define QSHPK_WRITE TLSX_QSHPK_Write
- #define QSH_SERREQ TLSX_QSH_SerPKReq
- #else
- #define QSH_FREE_ALL(list, heap)
- #define QSH_GET_SIZE(list, a) 0
- #define QSH_WRITE(a, b) 0
- #define QSH_PARSE(a, b, c, d) 0
- #define QSHPK_WRITE(a, b) 0
- #define QSH_SERREQ(a, b) 0
- #define QSH_VALIDATE_REQUEST(a, b)
- #endif /* HAVE_QSH */
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- /******************************************************************************/
- /* Encrypt-then-MAC */
- /******************************************************************************/
- #ifndef WOLFSSL_NO_TLS12
- static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl);
- /**
- * Get the size of the Encrypt-Then-MAC extension.
- *
- * msgType Type of message to put extension into.
- * pSz Size of extension data.
- * return SANITY_MSG_E when the message is not allowed to have extension and
- * 0 otherwise.
- */
- static int TLSX_EncryptThenMac_GetSize(byte msgType, word16* pSz)
- {
- (void)pSz;
- if (msgType != client_hello && msgType != server_hello) {
- return SANITY_MSG_E;
- }
- /* Empty extension */
- return 0;
- }
- /**
- * Write the Encrypt-Then-MAC extension.
- *
- * data Unused
- * output Extension data buffer. Unused.
- * msgType Type of message to put extension into.
- * pSz Size of extension data.
- * return SANITY_MSG_E when the message is not allowed to have extension and
- * 0 otherwise.
- */
- static int TLSX_EncryptThenMac_Write(void* data, byte* output, byte msgType,
- word16* pSz)
- {
- (void)data;
- (void)output;
- (void)pSz;
- if (msgType != client_hello && msgType != server_hello) {
- return SANITY_MSG_E;
- }
- /* Empty extension */
- return 0;
- }
- /**
- * Parse the Encrypt-Then-MAC extension.
- *
- * ssl SSL object
- * input Extension data buffer.
- * length Length of this extension's data.
- * msgType Type of message to extension appeared in.
- * return SANITY_MSG_E when the message is not allowed to have extension,
- * BUFFER_ERROR when the extension's data is invalid,
- * MEMORY_E when unable to allocate memory and
- * 0 otherwise.
- */
- static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
- {
- int ret;
- (void)input;
- if (msgType != client_hello && msgType != server_hello) {
- return SANITY_MSG_E;
- }
- /* Empty extension */
- if (length != 0)
- return BUFFER_ERROR;
- if (msgType == client_hello) {
- /* Check the user hasn't disallowed use of Encrypt-Then-Mac. */
- if (!ssl->options.disallowEncThenMac) {
- ssl->options.encThenMac = 1;
- /* Set the extension reply. */
- ret = TLSX_EncryptThenMac_Use(ssl);
- if (ret != 0)
- return ret;
- TLSX_SetResponse(ssl, TLSX_ENCRYPT_THEN_MAC);
- }
- return 0;
- }
- /* Server Hello */
- if (ssl->options.disallowEncThenMac)
- return SANITY_MSG_E;
- ssl->options.encThenMac = 1;
- return 0;
- }
- /**
- * Add the Encrypt-Then-MAC extension to list.
- *
- * ssl SSL object
- * return MEMORY_E when unable to allocate memory and 0 otherwise.
- */
- static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl)
- {
- int ret = 0;
- TLSX* extension;
- /* Find the Encrypt-Then-Mac extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC);
- if (extension == NULL) {
- /* Push new Encrypt-Then-Mac extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_ENCRYPT_THEN_MAC, NULL,
- ssl->heap);
- if (ret != 0)
- return ret;
- }
- return 0;
- }
- #define ETM_GET_SIZE TLSX_EncryptThenMac_GetSize
- #define ETM_WRITE TLSX_EncryptThenMac_Write
- #define ETM_PARSE TLSX_EncryptThenMac_Parse
- #else
- #define ETM_GET_SIZE(a, b) 0
- #define ETM_WRITE(a, b, c, d) 0
- #define ETM_PARSE(a, b, c, d) 0
- #endif /* !WOLFSSL_NO_TLS12 */
- #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
- /******************************************************************************/
- /* Supported Versions */
- /******************************************************************************/
- #ifdef WOLFSSL_TLS13
- /* Return the size of the SupportedVersions extension's data.
- *
- * data The SSL/TLS object.
- * msgType The type of the message this extension is being written into.
- * returns the length of data that will be in the extension.
- */
- static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- if (msgType == client_hello) {
- /* TLS v1.2 and TLS v1.3 */
- int cnt = 0;
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0)
- #endif
- cnt++;
- if (ssl->options.downgrade) {
- #ifndef WOLFSSL_NO_TLS12
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0)
- #endif
- cnt++;
- #endif
- #ifndef NO_OLD_TLS
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0)
- #endif
- cnt++;
- #ifdef WOLFSSL_ALLOW_TLSV10
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0)
- #endif
- cnt++;
- #endif
- #endif
- }
- *pSz += (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN);
- }
- else if (msgType == server_hello || msgType == hello_retry_request)
- *pSz += OPAQUE16_LEN;
- else
- return SANITY_MSG_E;
- return 0;
- }
- /* Writes the SupportedVersions extension into the buffer.
- *
- * data The SSL/TLS object.
- * output The buffer to write the extension into.
- * msgType The type of the message this extension is being written into.
- * returns the length of data that was written.
- */
- static int TLSX_SupportedVersions_Write(void* data, byte* output,
- byte msgType, word16* pSz)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- byte major;
- byte* cnt;
- if (msgType == client_hello) {
- major = ssl->ctx->method->version.major;
- cnt = output++;
- *cnt = 0;
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0)
- #endif
- {
- *cnt += OPAQUE16_LEN;
- #ifdef WOLFSSL_TLS13_DRAFT
- /* The TLS draft major number. */
- *(output++) = TLS_DRAFT_MAJOR;
- /* Version of draft supported. */
- *(output++) = TLS_DRAFT_MINOR;
- #else
- *(output++) = major;
- *(output++) = (byte)TLSv1_3_MINOR;
- #endif
- }
- if (ssl->options.downgrade) {
- #ifndef WOLFSSL_NO_TLS12
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0)
- #endif
- {
- *cnt += OPAQUE16_LEN;
- *(output++) = major;
- *(output++) = (byte)TLSv1_2_MINOR;
- }
- #endif
- #ifndef NO_OLD_TLS
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0)
- #endif
- {
- *cnt += OPAQUE16_LEN;
- *(output++) = major;
- *(output++) = (byte)TLSv1_1_MINOR;
- }
- #ifdef WOLFSSL_ALLOW_TLSV10
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0)
- #endif
- {
- *cnt += OPAQUE16_LEN;
- *(output++) = major;
- *(output++) = (byte)TLSv1_MINOR;
- }
- #endif
- #endif
- }
- *pSz += (word16)(OPAQUE8_LEN + *cnt);
- }
- else if (msgType == server_hello || msgType == hello_retry_request) {
- output[0] = ssl->version.major;
- output[1] = ssl->version.minor;
- *pSz += OPAQUE16_LEN;
- }
- else
- return SANITY_MSG_E;
- return 0;
- }
- /* Parse the SupportedVersions extension.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, byte* input,
- word16 length, byte msgType)
- {
- ProtocolVersion pv = ssl->ctx->method->version;
- int i;
- int len;
- byte major, minor;
- int newMinor = 0;
- int set = 0;
- int ret;
- if (msgType == client_hello) {
- /* Must contain a length and at least one version. */
- if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1)
- return BUFFER_ERROR;
- len = *input;
- /* Protocol version array must fill rest of data. */
- if (length != (word16)OPAQUE8_LEN + len)
- return BUFFER_ERROR;
- input++;
- /* Find first match. */
- for (i = 0; i < len; i += OPAQUE16_LEN) {
- major = input[i];
- minor = input[i + OPAQUE8_LEN];
- #ifdef WOLFSSL_TLS13_DRAFT
- if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) {
- major = SSLv3_MAJOR;
- minor = TLSv1_3_MINOR;
- }
- #else
- if (major == TLS_DRAFT_MAJOR)
- continue;
- #endif
- if (major != pv.major)
- continue;
- /* No upgrade allowed. */
- if (minor > ssl->version.minor)
- continue;
- /* Check downgrade. */
- if (minor < ssl->version.minor) {
- if (!ssl->options.downgrade)
- continue;
- if (minor < ssl->options.minDowngrade)
- continue;
- if (newMinor == 0 && minor > ssl->options.oldMinor) {
- /* Downgrade the version. */
- ssl->version.minor = minor;
- }
- }
- if (minor >= TLSv1_3_MINOR) {
- if (!ssl->options.tls1_3) {
- ssl->options.tls1_3 = 1;
- ret = TLSX_Prepend(&ssl->extensions,
- TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap);
- if (ret != 0) {
- return ret;
- }
- TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS);
- }
- if (minor > newMinor) {
- ssl->version.minor = minor;
- newMinor = minor;
- }
- }
- else if (minor > ssl->options.oldMinor)
- ssl->options.oldMinor = minor;
- set = 1;
- }
- if (!set) {
- #ifdef WOLFSSL_MYSQL_COMPATIBLE
- SendAlert(ssl, alert_fatal, wc_protocol_version);
- #else
- SendAlert(ssl, alert_fatal, protocol_version);
- #endif
- return VERSION_ERROR;
- }
- }
- else if (msgType == server_hello || msgType == hello_retry_request) {
- /* Must contain one version. */
- if (length != OPAQUE16_LEN)
- return BUFFER_ERROR;
- major = input[0];
- minor = input[OPAQUE8_LEN];
- if (major != pv.major)
- return VERSION_ERROR;
- /* Can't downgrade with this extension below TLS v1.3. */
- if (minor < TLSv1_3_MINOR)
- return VERSION_ERROR;
- /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */
- if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) {
- /* Set minor version back to TLS v1.3+ */
- ssl->version.minor = ssl->ctx->method->version.minor;
- }
- /* No upgrade allowed. */
- if (ssl->version.minor < minor)
- return VERSION_ERROR;
- /* Check downgrade. */
- if (ssl->version.minor > minor) {
- if (!ssl->options.downgrade)
- return VERSION_ERROR;
- if (minor < ssl->options.minDowngrade)
- return VERSION_ERROR;
- /* Downgrade the version. */
- ssl->version.minor = minor;
- }
- }
- else
- return SANITY_MSG_E;
- return 0;
- }
- /* Sets a new SupportedVersions extension into the extension list.
- *
- * extensions The list of extensions.
- * data The extensions specific data.
- * heap The heap used for allocation.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data,
- void* heap)
- {
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
- return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap);
- }
- #define SV_GET_SIZE TLSX_SupportedVersions_GetSize
- #define SV_WRITE TLSX_SupportedVersions_Write
- #define SV_PARSE TLSX_SupportedVersions_Parse
- #else
- #define SV_GET_SIZE(a, b, c) 0
- #define SV_WRITE(a, b, c, d) 0
- #define SV_PARSE(a, b, c, d) 0
- #endif /* WOLFSSL_TLS13 */
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
- /******************************************************************************/
- /* Cookie */
- /******************************************************************************/
- /* Free the cookie data.
- *
- * cookie Cookie data.
- * heap The heap used for allocation.
- */
- static void TLSX_Cookie_FreeAll(Cookie* cookie, void* heap)
- {
- (void)heap;
- if (cookie != NULL)
- XFREE(cookie, heap, DYNAMIC_TYPE_TLSX);
- }
- /* Get the size of the encoded Cookie extension.
- * In messages: ClientHello and HelloRetryRequest.
- *
- * cookie The cookie to write.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded Cookie extension.
- */
- static int TLSX_Cookie_GetSize(Cookie* cookie, byte msgType, word16* pSz)
- {
- if (msgType == client_hello || msgType == hello_retry_request)
- *pSz += OPAQUE16_LEN + cookie->len;
- else
- return SANITY_MSG_E;
- return 0;
- }
- /* Writes the Cookie extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- * In messages: ClientHello and HelloRetryRequest.
- *
- * cookie The cookie to write.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
- static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType,
- word16* pSz)
- {
- if (msgType == client_hello || msgType == hello_retry_request) {
- c16toa(cookie->len, output);
- output += OPAQUE16_LEN;
- XMEMCPY(output, &cookie->data, cookie->len);
- *pSz += OPAQUE16_LEN + cookie->len;
- }
- else
- return SANITY_MSG_E;
- return 0;
- }
- /* Parse the Cookie extension.
- * In messages: ClientHello and HelloRetryRequest.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
- {
- word16 len;
- word16 idx = 0;
- TLSX* extension;
- Cookie* cookie;
- if (msgType != client_hello && msgType != hello_retry_request)
- return SANITY_MSG_E;
- /* Message contains length and Cookie which must be at least one byte
- * in length.
- */
- if (length < OPAQUE16_LEN + 1)
- return BUFFER_E;
- ato16(input + idx, &len);
- idx += OPAQUE16_LEN;
- if (length - idx != len)
- return BUFFER_E;
- if (msgType == hello_retry_request)
- return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0);
- /* client_hello */
- extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
- if (extension == NULL)
- return HRR_COOKIE_ERROR;
- cookie = (Cookie*)extension->data;
- if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0)
- return HRR_COOKIE_ERROR;
- /* Request seen. */
- extension->resp = 0;
- return 0;
- }
- /* Use the data to create a new Cookie object in the extensions.
- *
- * ssl SSL/TLS object.
- * data Cookie data.
- * len Length of cookie data in bytes.
- * mac MAC data.
- * macSz Length of MAC data in bytes.
- * resp Indicates the extension will go into a response (HelloRetryRequest).
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac,
- byte macSz, int resp)
- {
- int ret = 0;
- TLSX* extension;
- Cookie* cookie;
- /* Find the cookie extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
- if (extension == NULL) {
- /* Push new cookie extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_COOKIE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
- if (extension == NULL)
- return MEMORY_E;
- }
- /* The Cookie structure has one byte for cookie data already. */
- cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz - 1, ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (cookie == NULL)
- return MEMORY_E;
- cookie->len = len + macSz;
- XMEMCPY(&cookie->data, data, len);
- if (mac != NULL)
- XMEMCPY(&cookie->data + len, mac, macSz);
- if (extension->data != NULL)
- XFREE(extension->data, ssl->heap, DYNAMIC_TYPE_TLSX);
- extension->data = (void*)cookie;
- extension->resp = (byte)resp;
- return 0;
- }
- #define CKE_FREE_ALL TLSX_Cookie_FreeAll
- #define CKE_GET_SIZE TLSX_Cookie_GetSize
- #define CKE_WRITE TLSX_Cookie_Write
- #define CKE_PARSE TLSX_Cookie_Parse
- #else
- #define CKE_FREE_ALL(a, b) 0
- #define CKE_GET_SIZE(a, b, c) 0
- #define CKE_WRITE(a, b, c, d) 0
- #define CKE_PARSE(a, b, c, d) 0
- #endif
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- /******************************************************************************/
- /* Signature Algorithms */
- /******************************************************************************/
- /* Return the size of the SignatureAlgorithms extension's data.
- *
- * data Unused
- * returns the length of data that will be in the extension.
- */
- static word16 TLSX_SignatureAlgorithms_GetSize(void* data)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz;
- }
- /* Creates a bit string of supported hash algorithms with RSA PSS.
- * The bit string is used when determining which signature algorithm to use
- * when creating the CertificateVerify message.
- * Note: Valid data has an even length as each signature algorithm is two bytes.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the list of supported signature algorithms.
- * length The length of the list in bytes.
- * returns 0 on success, BUFFER_ERROR when the length is not even.
- */
- static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, byte* input,
- word16 length)
- {
- word16 i;
- if ((length & 1) == 1)
- return BUFFER_ERROR;
- ssl->pssAlgo = 0;
- for (i = 0; i < length; i += 2) {
- if (input[i] == rsa_pss_sa_algo && input[i + 1] <= sha512_mac)
- ssl->pssAlgo |= 1 << input[i + 1];
- #ifdef WOLFSSL_TLS13
- if (input[i] == rsa_pss_sa_algo && input[i + 1] >= pss_sha256 &&
- input[i + 1] <= pss_sha512) {
- ssl->pssAlgo |= 1 << input[i + 1];
- }
- #endif
- }
- return 0;
- }
- /* Writes the SignatureAlgorithms extension into the buffer.
- *
- * data Unused
- * output The buffer to write the extension into.
- * returns the length of data that was written.
- */
- static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- c16toa(ssl->suites->hashSigAlgoSz, output);
- XMEMCPY(output + OPAQUE16_LEN, ssl->suites->hashSigAlgo,
- ssl->suites->hashSigAlgoSz);
- TLSX_SignatureAlgorithms_MapPss(ssl, output + OPAQUE16_LEN,
- ssl->suites->hashSigAlgoSz);
- return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz;
- }
- /* Parse the SignatureAlgorithms extension.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the extension data.
- * length The length of the extension data.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input,
- word16 length, byte isRequest, Suites* suites)
- {
- word16 len;
- if (!isRequest)
- return BUFFER_ERROR;
- /* Must contain a length and at least algorithm. */
- if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
- return BUFFER_ERROR;
- ato16(input, &len);
- input += OPAQUE16_LEN;
- /* Algorithm array must fill rest of data. */
- if (length != OPAQUE16_LEN + len)
- return BUFFER_ERROR;
- /* Sig Algo list size must be even. */
- if (suites->hashSigAlgoSz % 2 != 0)
- return BUFFER_ERROR;
- /* truncate hashSigAlgo list if too long */
- suites->hashSigAlgoSz = len;
- if (suites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
- WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
- suites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
- }
- XMEMCPY(suites->hashSigAlgo, input, suites->hashSigAlgoSz);
- return TLSX_SignatureAlgorithms_MapPss(ssl, input, len);
- }
- /* Sets a new SignatureAlgorithms extension into the extension list.
- *
- * extensions The list of extensions.
- * data The extensions specific data.
- * heap The heap used for allocation.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data,
- void* heap)
- {
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap);
- }
- #define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize
- #define SA_WRITE TLSX_SignatureAlgorithms_Write
- #define SA_PARSE TLSX_SignatureAlgorithms_Parse
- #endif
- /******************************************************************************/
- /* Signature Algorithms Certificate */
- /******************************************************************************/
- #if defined(WOLFSSL_TLS13) && !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- /* Return the size of the SignatureAlgorithms extension's data.
- *
- * data Unused
- * returns the length of data that will be in the extension.
- */
- static word16 TLSX_SignatureAlgorithmsCert_GetSize(void* data)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
- }
- /* Writes the SignatureAlgorithmsCert extension into the buffer.
- *
- * data Unused
- * output The buffer to write the extension into.
- * returns the length of data that was written.
- */
- static word16 TLSX_SignatureAlgorithmsCert_Write(void* data, byte* output)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- c16toa(ssl->certHashSigAlgoSz, output);
- XMEMCPY(output + OPAQUE16_LEN, ssl->certHashSigAlgo,
- ssl->certHashSigAlgoSz);
- return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
- }
- /* Parse the SignatureAlgorithmsCert extension.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the extension data.
- * length The length of the extension data.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input,
- word16 length, byte isRequest)
- {
- word16 len;
- if (!isRequest)
- return BUFFER_ERROR;
- /* Must contain a length and at least algorithm. */
- if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
- return BUFFER_ERROR;
- ato16(input, &len);
- input += OPAQUE16_LEN;
- /* Algorithm array must fill rest of data. */
- if (length != OPAQUE16_LEN + len)
- return BUFFER_ERROR;
- /* truncate hashSigAlgo list if too long */
- ssl->certHashSigAlgoSz = len;
- if (ssl->certHashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
- WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
- ssl->certHashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
- }
- XMEMCPY(ssl->certHashSigAlgo, input, ssl->certHashSigAlgoSz);
- return 0;
- }
- /* Sets a new SignatureAlgorithmsCert extension into the extension list.
- *
- * extensions The list of extensions.
- * data The extensions specific data.
- * heap The heap used for allocation.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data,
- void* heap)
- {
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, (void *)data,
- heap);
- }
- #define SAC_GET_SIZE TLSX_SignatureAlgorithmsCert_GetSize
- #define SAC_WRITE TLSX_SignatureAlgorithmsCert_Write
- #define SAC_PARSE TLSX_SignatureAlgorithmsCert_Parse
- #endif /* WOLFSSL_TLS13 */
- /******************************************************************************/
- /* Key Share */
- /******************************************************************************/
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
- /* Create a key share entry using named Diffie-Hellman parameters group.
- * Generates a key pair.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry object.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
- {
- int ret;
- #ifndef NO_DH
- byte* keyData;
- void* key = NULL;
- word32 keySz;
- word32 dataSz;
- const DhParams* params;
- #ifdef WOLFSSL_SMALL_STACK
- DhKey* dhKey = NULL;
- #else
- DhKey dhKey[1];
- #endif
- /* TODO: [TLS13] The key size should come from wolfcrypt. */
- /* Pick the parameters from the named group. */
- switch (kse->group) {
- #ifdef HAVE_FFDHE_2048
- case WOLFSSL_FFDHE_2048:
- params = wc_Dh_ffdhe2048_Get();
- keySz = 29;
- break;
- #endif
- #ifdef HAVE_FFDHE_3072
- case WOLFSSL_FFDHE_3072:
- params = wc_Dh_ffdhe3072_Get();
- keySz = 34;
- break;
- #endif
- #ifdef HAVE_FFDHE_4096
- case WOLFSSL_FFDHE_4096:
- params = wc_Dh_ffdhe4096_Get();
- keySz = 39;
- break;
- #endif
- #ifdef HAVE_FFDHE_6144
- case WOLFSSL_FFDHE_6144:
- params = wc_Dh_ffdhe6144_Get();
- keySz = 46;
- break;
- #endif
- #ifdef HAVE_FFDHE_8192
- case WOLFSSL_FFDHE_8192:
- params = wc_Dh_ffdhe8192_Get();
- keySz = 52;
- break;
- #endif
- default:
- return BAD_FUNC_ARG;
- }
- #ifdef WOLFSSL_SMALL_STACK
- dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH);
- if (dhKey == NULL)
- return MEMORY_E;
- #endif
- ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId);
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return ret;
- }
- /* Allocate space for the public key */
- dataSz = params->p_len;
- keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (keyData == NULL) {
- ret = MEMORY_E;
- goto end;
- }
- /* Allocate space for the private key */
- key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- if (key == NULL) {
- ret = MEMORY_E;
- goto end;
- }
- /* Set key */
- ret = wc_DhSetKey(dhKey,
- (byte*)params->p, params->p_len,
- (byte*)params->g, params->g_len);
- if (ret != 0)
- goto end;
- #if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA)
- if (ssl->staticKE.dhKey) {
- DerBuffer* keyDer = ssl->staticKE.dhKey;
- word32 idx = 0;
- WOLFSSL_MSG("Using static DH key");
- ret = wc_DhKeyDecode(keyDer->buffer, &idx, dhKey, keyDer->length);
- if (ret == 0) {
- ret = wc_DhExportKeyPair(dhKey, (byte*)key, &keySz, keyData, &dataSz);
- }
- }
- else
- #endif
- {
- /* Generate a new key pair */
- ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData,
- &dataSz);
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* TODO: Make this function non-blocking */
- if (ret == WC_PENDING_E) {
- ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
- }
- #endif
- }
- if (ret != 0)
- goto end;
- if (params->p_len != dataSz) {
- /* Zero pad the front of the public key to match prime "p" size */
- XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz);
- XMEMSET(keyData, 0, params->p_len - dataSz);
- }
- kse->pubKey = keyData;
- kse->pubKeyLen = params->p_len;
- kse->key = key;
- kse->keyLen = keySz;
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public DH Key");
- WOLFSSL_BUFFER(keyData, params->p_len);
- #endif
- end:
- wc_FreeDhKey(dhKey);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (keyData != NULL)
- XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (key != NULL)
- XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- /* Create a key share entry using X25519 parameters group.
- * Generates a key pair.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry object.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
- {
- int ret;
- #ifdef HAVE_CURVE25519
- byte* keyData = NULL;
- word32 dataSize = CURVE25519_KEYSIZE;
- curve25519_key* key;
- /* Allocate an ECC key to hold private key. */
- key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap,
- DYNAMIC_TYPE_PRIVATE_KEY);
- if (key == NULL) {
- WOLFSSL_MSG("EccTempKey Memory error");
- return MEMORY_E;
- }
- /* Make an ECC key. */
- ret = wc_curve25519_init(key);
- if (ret != 0)
- goto end;
- ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
- if (ret != 0)
- goto end;
- /* Allocate space for the public key. */
- keyData = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (keyData == NULL) {
- WOLFSSL_MSG("Key data Memory error");
- ret = MEMORY_E;
- goto end;
- }
- /* Export public key. */
- if (wc_curve25519_export_public_ex(key, keyData, &dataSize,
- EC25519_LITTLE_ENDIAN) != 0) {
- ret = ECC_EXPORT_ERROR;
- goto end;
- }
- kse->pubKey = keyData;
- kse->pubKeyLen = CURVE25519_KEYSIZE;
- kse->key = key;
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public Curve25519 Key");
- WOLFSSL_BUFFER(keyData, dataSize);
- #endif
- end:
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (keyData != NULL)
- XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- wc_curve25519_free(key);
- XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- #endif /* HAVE_CURVE25519 */
- return ret;
- }
- /* Create a key share entry using X448 parameters group.
- * Generates a key pair.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry object.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_KeyShare_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse)
- {
- int ret;
- #ifdef HAVE_CURVE448
- byte* keyData = NULL;
- word32 dataSize = CURVE448_KEY_SIZE;
- curve448_key* key;
- /* Allocate an ECC key to hold private key. */
- key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap,
- DYNAMIC_TYPE_PRIVATE_KEY);
- if (key == NULL) {
- WOLFSSL_MSG("EccTempKey Memory error");
- return MEMORY_E;
- }
- /* Make an ECC key. */
- ret = wc_curve448_init(key);
- if (ret != 0)
- goto end;
- ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key);
- if (ret != 0)
- goto end;
- /* Allocate space for the public key. */
- keyData = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (keyData == NULL) {
- WOLFSSL_MSG("Key data Memory error");
- ret = MEMORY_E;
- goto end;
- }
- /* Export public key. */
- if (wc_curve448_export_public_ex(key, keyData, &dataSize,
- EC448_LITTLE_ENDIAN) != 0) {
- ret = ECC_EXPORT_ERROR;
- goto end;
- }
- kse->pubKey = keyData;
- kse->pubKeyLen = CURVE448_KEY_SIZE;
- kse->key = key;
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public Curve448 Key");
- WOLFSSL_BUFFER(keyData, dataSize);
- #endif
- end:
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (keyData != NULL)
- XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- wc_curve448_free(key);
- XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- #endif /* HAVE_CURVE448 */
- return ret;
- }
- /* Create a key share entry using named elliptic curve parameters group.
- * Generates a key pair.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry object.
- * returns 0 on success, otherwise failure.
- */
- static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
- {
- int ret;
- #ifdef HAVE_ECC
- byte* keyData = NULL;
- word32 dataSize;
- byte* keyPtr = NULL;
- word32 keySize;
- ecc_key* eccKey;
- word16 curveId;
- /* TODO: [TLS13] The key sizes should come from wolfcrypt. */
- /* Translate named group to a curve id. */
- switch (kse->group) {
- #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- curveId = ECC_SECP256R1;
- keySize = 32;
- dataSize = keySize * 2 + 1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP384R1:
- curveId = ECC_SECP384R1;
- keySize = 48;
- dataSize = keySize * 2 + 1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- curveId = ECC_SECP521R1;
- keySize = 66;
- dataSize = keySize * 2 + 1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_X448) && ECC_MIN_KEY_SZ <= 448
- case WOLFSSL_ECC_X448:
- curveId = ECC_X448;
- dataSize = keySize = 56;
- break;
- #endif
- default:
- return BAD_FUNC_ARG;
- }
- /* Allocate an ECC key to hold private key. */
- keyPtr = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap,
- DYNAMIC_TYPE_PRIVATE_KEY);
- if (keyPtr == NULL) {
- WOLFSSL_MSG("EccTempKey Memory error");
- return MEMORY_E;
- }
- eccKey = (ecc_key*)keyPtr;
- /* Make an ECC key. */
- ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId);
- if (ret != 0)
- goto end;
- #ifdef WOLFSSL_STATIC_EPHEMERAL
- if (ssl->staticKE.ecKey) {
- DerBuffer* keyDer = ssl->staticKE.ecKey;
- word32 idx = 0;
- WOLFSSL_MSG("Using static ECDH key");
- ret = wc_EccPrivateKeyDecode(keyDer->buffer, &idx, eccKey, keyDer->length);
- }
- else
- #endif
- {
- /* Generate ephemeral ECC key */
- ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId);
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* TODO: Make this function non-blocking */
- if (ret == WC_PENDING_E) {
- ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE);
- }
- #endif
- }
- if (ret != 0)
- goto end;
- /* Allocate space for the public key. */
- keyData = (byte*)XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (keyData == NULL) {
- WOLFSSL_MSG("Key data Memory error");
- ret = MEMORY_E;
- goto end;
- }
- /* Export public key. */
- if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) {
- ret = ECC_EXPORT_ERROR;
- goto end;
- }
- kse->pubKey = keyData;
- kse->pubKeyLen = dataSize;
- kse->key = keyPtr;
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public ECC Key");
- WOLFSSL_BUFFER(keyData, dataSize);
- #endif
- end:
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (keyPtr != NULL)
- XFREE(keyPtr, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- if (keyData != NULL)
- XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- #endif /* HAVE_ECC */
- return ret;
- }
- /* Generate a secret/key using the key share entry.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry holding peer data.
- */
- static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
- {
- /* Named FFHE groups have a bit set to identify them. */
- if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK)
- return TLSX_KeyShare_GenDhKey(ssl, kse);
- if (kse->group == WOLFSSL_ECC_X25519)
- return TLSX_KeyShare_GenX25519Key(ssl, kse);
- if (kse->group == WOLFSSL_ECC_X448)
- return TLSX_KeyShare_GenX448Key(ssl, kse);
- return TLSX_KeyShare_GenEccKey(ssl, kse);
- }
- /* Free the key share dynamic data.
- *
- * list The linked list of key share entry objects.
- * heap The heap used for allocation.
- */
- static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
- {
- KeyShareEntry* current;
- while ((current = list) != NULL) {
- list = current->next;
- if ((current->group & NAMED_DH_MASK) == 0) {
- if (current->group == WOLFSSL_ECC_X25519) {
- #ifdef HAVE_CURVE25519
- wc_curve25519_free((curve25519_key*)current->key);
- #endif
- }
- else if (current->group == WOLFSSL_ECC_X448) {
- #ifdef HAVE_CURVE448
- wc_curve448_free((curve448_key*)current->key);
- #endif
- }
- else {
- #ifdef HAVE_ECC
- wc_ecc_free((ecc_key*)(current->key));
- #endif
- }
- }
- if (current->key != NULL)
- XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY);
- XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(current, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- /* Get the size of the encoded key share extension.
- *
- * list The linked list of key share extensions.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded key share extension.
- */
- static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType)
- {
- word16 len = 0;
- byte isRequest = (msgType == client_hello);
- KeyShareEntry* current;
- /* The named group the server wants to use. */
- if (msgType == hello_retry_request)
- return OPAQUE16_LEN;
- /* List of key exchange groups. */
- if (isRequest)
- len += OPAQUE16_LEN;
- while ((current = list) != NULL) {
- list = current->next;
- if (!isRequest && current->key == NULL)
- continue;
- len += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen;
- }
- return len;
- }
- /* Writes the key share extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- *
- * list The linked list of key share entries.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
- static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output,
- byte msgType)
- {
- word16 i = 0;
- byte isRequest = (msgType == client_hello);
- KeyShareEntry* current;
- if (msgType == hello_retry_request) {
- c16toa(list->group, output);
- return OPAQUE16_LEN;
- }
- /* ClientHello has a list but ServerHello is only the chosen. */
- if (isRequest)
- i += OPAQUE16_LEN;
- /* Write out all in the list. */
- while ((current = list) != NULL) {
- list = current->next;
- if (!isRequest && current->key == NULL)
- continue;
- c16toa(current->group, &output[i]);
- i += KE_GROUP_LEN;
- c16toa((word16)(current->pubKeyLen), &output[i]);
- i += OPAQUE16_LEN;
- XMEMCPY(&output[i], current->pubKey, current->pubKeyLen);
- i += (word16)current->pubKeyLen;
- }
- /* Write the length of the list if required. */
- if (isRequest)
- c16toa(i - OPAQUE16_LEN, output);
- return i;
- }
- /* Process the DH key share extension on the client side.
- *
- * ssl The SSL/TLS object.
- * keyShareEntry The key share entry object to use to calculate shared secret.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
- {
- #ifndef NO_DH
- int ret;
- const DhParams* params;
- #ifdef WOLFSSL_SMALL_STACK
- DhKey* dhKey = NULL;
- #else
- DhKey dhKey[1];
- #endif
- switch (keyShareEntry->group) {
- #ifdef HAVE_FFDHE_2048
- case WOLFSSL_FFDHE_2048:
- params = wc_Dh_ffdhe2048_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_3072
- case WOLFSSL_FFDHE_3072:
- params = wc_Dh_ffdhe3072_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_4096
- case WOLFSSL_FFDHE_4096:
- params = wc_Dh_ffdhe4096_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_6144
- case WOLFSSL_FFDHE_6144:
- params = wc_Dh_ffdhe6144_Get();
- break;
- #endif
- #ifdef HAVE_FFDHE_8192
- case WOLFSSL_FFDHE_8192:
- params = wc_Dh_ffdhe8192_Get();
- break;
- #endif
- default:
- return PEER_KEY_ERROR;
- }
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer DH Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
- #endif
- #ifdef WOLFSSL_SMALL_STACK
- dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH);
- if (dhKey == NULL)
- return MEMORY_E;
- #endif
- ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId);
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return ret;
- }
- /* Set key */
- ret = wc_DhSetKey(dhKey, (byte*)params->p, params->p_len, (byte*)params->g,
- params->g_len);
- if (ret != 0) {
- wc_FreeDhKey(dhKey);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return ret;
- }
- ret = wc_DhCheckPubKey(dhKey, keyShareEntry->ke, keyShareEntry->keLen);
- if (ret != 0) {
- wc_FreeDhKey(dhKey);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return PEER_KEY_ERROR;
- }
- /* Derive secret from private key and peer's public key. */
- ret = wc_DhAgree(dhKey,
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
- (const byte*)keyShareEntry->key, keyShareEntry->keyLen,
- keyShareEntry->ke, keyShareEntry->keLen);
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* TODO: Make this function non-blocking */
- if (ret == WC_PENDING_E) {
- ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
- }
- #endif
- /* RFC 8446 Section 7.4.1:
- * ... left-padded with zeros up to the size of the prime. ...
- */
- if (params->p_len > ssl->arrays->preMasterSz) {
- word32 diff = params->p_len - ssl->arrays->preMasterSz;
- XMEMMOVE(ssl->arrays->preMasterSecret + diff,
- ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
- XMEMSET(ssl->arrays->preMasterSecret, 0, diff);
- ssl->arrays->preMasterSz = params->p_len;
- }
- ssl->options.dhKeySz = params->p_len;
- wc_FreeDhKey(dhKey);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- if (keyShareEntry->key != NULL) {
- XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- keyShareEntry->key = NULL;
- }
- XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- keyShareEntry->pubKey = NULL;
- XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- keyShareEntry->ke = NULL;
- return ret;
- #else
- (void)ssl;
- (void)keyShareEntry;
- return PEER_KEY_ERROR;
- #endif
- }
- /* Process the X25519 key share extension on the client side.
- *
- * ssl The SSL/TLS object.
- * keyShareEntry The key share entry object to use to calculate shared secret.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_KeyShare_ProcessX25519(WOLFSSL* ssl,
- KeyShareEntry* keyShareEntry)
- {
- int ret;
- #ifdef HAVE_CURVE25519
- curve25519_key* key = (curve25519_key*)keyShareEntry->key;
- curve25519_key* peerX25519Key;
- #ifdef HAVE_ECC
- if (ssl->peerEccKey != NULL) {
- wc_ecc_free(ssl->peerEccKey);
- ssl->peerEccKey = NULL;
- }
- #endif
- peerX25519Key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (peerX25519Key == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- return MEMORY_ERROR;
- }
- ret = wc_curve25519_init(peerX25519Key);
- if (ret != 0) {
- XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer Curve25519 Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
- #endif
- if (wc_curve25519_check_public(keyShareEntry->ke, keyShareEntry->keLen,
- EC25519_LITTLE_ENDIAN) != 0) {
- ret = ECC_PEERKEY_ERROR;
- }
- if (ret == 0) {
- if (wc_curve25519_import_public_ex(keyShareEntry->ke,
- keyShareEntry->keLen, peerX25519Key,
- EC25519_LITTLE_ENDIAN) != 0) {
- ret = ECC_PEERKEY_ERROR;
- }
- }
- if (ret == 0) {
- ssl->ecdhCurveOID = ECC_X25519_OID;
- ret = wc_curve25519_shared_secret_ex(key, peerX25519Key,
- ssl->arrays->preMasterSecret,
- &ssl->arrays->preMasterSz,
- EC25519_LITTLE_ENDIAN);
- }
- wc_curve25519_free(peerX25519Key);
- XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
- wc_curve25519_free((curve25519_key*)keyShareEntry->key);
- if (keyShareEntry->key != NULL) {
- XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- keyShareEntry->key = NULL;
- }
- #else
- (void)ssl;
- (void)keyShareEntry;
- ret = PEER_KEY_ERROR;
- #endif /* HAVE_CURVE25519 */
- return ret;
- }
- /* Process the X448 key share extension on the client side.
- *
- * ssl The SSL/TLS object.
- * keyShareEntry The key share entry object to use to calculate shared secret.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
- {
- int ret;
- #ifdef HAVE_CURVE448
- curve448_key* key = (curve448_key*)keyShareEntry->key;
- curve448_key* peerX448Key;
- #ifdef HAVE_ECC
- if (ssl->peerEccKey != NULL) {
- wc_ecc_free(ssl->peerEccKey);
- ssl->peerEccKey = NULL;
- }
- #endif
- peerX448Key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (peerX448Key == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- return MEMORY_ERROR;
- }
- ret = wc_curve448_init(peerX448Key);
- if (ret != 0) {
- XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer Curve448 Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
- #endif
- if (wc_curve448_check_public(keyShareEntry->ke, keyShareEntry->keLen,
- EC448_LITTLE_ENDIAN) != 0) {
- ret = ECC_PEERKEY_ERROR;
- }
- if (ret == 0) {
- if (wc_curve448_import_public_ex(keyShareEntry->ke,
- keyShareEntry->keLen, peerX448Key,
- EC448_LITTLE_ENDIAN) != 0) {
- ret = ECC_PEERKEY_ERROR;
- }
- }
- if (ret == 0) {
- ssl->ecdhCurveOID = ECC_X448_OID;
- ret = wc_curve448_shared_secret_ex(key, peerX448Key,
- ssl->arrays->preMasterSecret,
- &ssl->arrays->preMasterSz,
- EC448_LITTLE_ENDIAN);
- }
- wc_curve448_free(peerX448Key);
- XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
- wc_curve448_free((curve448_key*)keyShareEntry->key);
- if (keyShareEntry->key != NULL) {
- XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- keyShareEntry->key = NULL;
- }
- #else
- (void)ssl;
- (void)keyShareEntry;
- ret = PEER_KEY_ERROR;
- #endif /* HAVE_CURVE448 */
- return ret;
- }
- /* Process the ECC key share extension on the client side.
- *
- * ssl The SSL/TLS object.
- * keyShareEntry The key share entry object to use to calculate shared secret.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
- {
- int ret;
- #ifdef HAVE_ECC
- int curveId;
- ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key;
- if (ssl->peerEccKey != NULL)
- wc_ecc_free(ssl->peerEccKey);
- ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
- DYNAMIC_TYPE_ECC);
- if (ssl->peerEccKey == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- return MEMORY_ERROR;
- }
- ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId);
- if (ret != 0)
- return ret;
- /* find supported curve */
- switch (keyShareEntry->group) {
- #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- curveId = ECC_SECP256R1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP384R1:
- curveId = ECC_SECP384R1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- curveId = ECC_SECP521R1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_X448) && ECC_MIN_KEY_SZ <= 448
- case WOLFSSL_ECC_X448:
- curveId = ECC_X448;
- break;
- #endif
- default:
- /* unsupported curve */
- return ECC_PEERKEY_ERROR;
- }
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer ECC Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
- #endif
- /* Point is validated by import function. */
- if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen,
- ssl->peerEccKey, curveId) != 0) {
- return ECC_PEERKEY_ERROR;
- }
- ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum;
- #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
- (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
- !defined(HAVE_SELFTEST)
- ret = wc_ecc_set_rng(keyShareKey, ssl->rng);
- if (ret != 0) {
- return ret;
- }
- #endif
- do {
- #if defined(WOLFSSL_ASYNC_CRYPT)
- ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
- #endif
- if (ret >= 0)
- ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey,
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz);
- } while (ret == WC_PENDING_E);
- #if 0
- /* TODO: Switch to support async here and use: */
- ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey,
- keyShareEntry->ke, &keyShareEntry->keLen,
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
- ssl->options.side
- );
- #endif
- wc_ecc_free(ssl->peerEccKey);
- XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
- ssl->peerEccKey = NULL;
- wc_ecc_free((ecc_key*)(keyShareEntry->key));
- if (keyShareEntry->key != NULL) {
- XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- keyShareEntry->key = NULL;
- }
- #else
- (void)ssl;
- (void)keyShareEntry;
- ret = PEER_KEY_ERROR;
- #endif /* HAVE_ECC */
- return ret;
- }
- /* Process the key share extension on the client side.
- *
- * ssl The SSL/TLS object.
- * keyShareEntry The key share entry object to use to calculate shared secret.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
- {
- int ret;
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- ssl->session.namedGroup = (byte)keyShareEntry->group;
- #endif
- /* Use Key Share Data from server. */
- if (keyShareEntry->group & NAMED_DH_MASK)
- ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry);
- else if (keyShareEntry->group == WOLFSSL_ECC_X25519)
- ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry);
- else if (keyShareEntry->group == WOLFSSL_ECC_X448)
- ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry);
- else
- ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry);
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("KE Secret");
- WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
- #endif
- return ret;
- }
- /* Parse an entry of the KeyShare extension.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * kse The new key share entry object.
- * returns a positive number to indicate amount of data parsed and a negative
- * number on error.
- */
- static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length,
- KeyShareEntry **kse)
- {
- int ret;
- word16 group;
- word16 keLen;
- int offset = 0;
- byte* ke;
- if (length < OPAQUE16_LEN + OPAQUE16_LEN)
- return BUFFER_ERROR;
- /* Named group */
- ato16(&input[offset], &group);
- offset += OPAQUE16_LEN;
- /* Key exchange data - public key. */
- ato16(&input[offset], &keLen);
- offset += OPAQUE16_LEN;
- if (keLen == 0)
- return INVALID_PARAMETER;
- if (keLen > length - offset)
- return BUFFER_ERROR;
- /* Store a copy in the key share object. */
- ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (ke == NULL)
- return MEMORY_E;
- XMEMCPY(ke, &input[offset], keLen);
- /* Populate a key share object in the extension. */
- ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse);
- if (ret != 0) {
- XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- return ret;
- }
- /* Total length of the parsed data. */
- return offset + keLen;
- }
- /* Searches the groups sent for the specified named group.
- *
- * ssl SSL/TLS object.
- * name Group name to match.
- * returns 1 when the extension has the group name and 0 otherwise.
- */
- static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group)
- {
- TLSX* extension;
- KeyShareEntry* list;
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_KEY_SHARE);
- if (extension == NULL)
- return 0;
- }
- list = (KeyShareEntry*)extension->data;
- while (list != NULL) {
- if (list->group == group)
- return 1;
- list = list->next;
- }
- return 0;
- }
- /* Searches the supported groups extension for the specified named group.
- *
- * ssl The SSL/TLS object.
- * name The group name to match.
- * returns 1 when the extension has the group name and 0 otherwise.
- */
- static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name)
- {
- #ifdef HAVE_SUPPORTED_CURVES
- TLSX* extension;
- SupportedCurve* curve = NULL;
- if ((extension = TLSX_Find(ssl->extensions,
- TLSX_SUPPORTED_GROUPS)) == NULL) {
- if ((extension = TLSX_Find(ssl->ctx->extensions,
- TLSX_SUPPORTED_GROUPS)) == NULL) {
- return 0;
- }
- }
- for (curve = (SupportedCurve*)extension->data; curve; curve = curve->next) {
- if (curve->name == name)
- return 1;
- }
- #endif
- (void)ssl;
- (void)name;
- return 0;
- }
- /* Parse the KeyShare extension.
- * Different formats in different messages.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
- {
- int ret;
- KeyShareEntry *keyShareEntry = NULL;
- word16 group;
- if (msgType == client_hello) {
- int offset = 0;
- word16 len;
- TLSX* extension;
- /* Add a KeyShare extension if it doesn't exist. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- }
- if (length < OPAQUE16_LEN)
- return BUFFER_ERROR;
- /* ClientHello contains zero or more key share entries. */
- ato16(input, &len);
- if (len != length - OPAQUE16_LEN)
- return BUFFER_ERROR;
- offset += OPAQUE16_LEN;
- while (offset < (int)length) {
- ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length - offset,
- &keyShareEntry);
- if (ret < 0)
- return ret;
- offset += ret;
- }
- ret = 0;
- }
- else if (msgType == server_hello) {
- int len;
- if (length < OPAQUE16_LEN)
- return BUFFER_ERROR;
- /* The data is the named group the server wants to use. */
- ato16(input, &group);
- /* Check the selected group was supported by ClientHello extensions. */
- if (!TLSX_SupportedGroups_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
- /* Check if the group was sent. */
- if (!TLSX_KeyShare_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
- /* ServerHello contains one key share entry. */
- len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry);
- if (len != (int)length)
- return BUFFER_ERROR;
- /* Not in list sent if there isn't a private key. */
- if (keyShareEntry == NULL || keyShareEntry->key == NULL)
- return BAD_KEY_SHARE_DATA;
- /* Process the entry to calculate the secret. */
- ret = TLSX_KeyShare_Process(ssl, keyShareEntry);
- if (ret == 0)
- ssl->session.namedGroup = ssl->namedGroup = group;
- }
- else if (msgType == hello_retry_request) {
- if (length != OPAQUE16_LEN)
- return BUFFER_ERROR;
- /* The data is the named group the server wants to use. */
- ato16(input, &group);
- /* Check the selected group was supported by ClientHello extensions. */
- if (!TLSX_SupportedGroups_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
- /* Check if the group was sent. */
- if (TLSX_KeyShare_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
- /* Clear out unusable key shares. */
- ret = TLSX_KeyShare_Empty(ssl);
- if (ret != 0)
- return ret;
- /* Try to use the server's group. */
- ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL);
- }
- else {
- /* Not a message type that is allowed to have this extension. */
- return SANITY_MSG_E;
- }
- return ret;
- }
- /* Create a new key share entry and put it into the list.
- *
- * list The linked list of key share entries.
- * group The named group.
- * heap The memory to allocate with.
- * keyShareEntry The new key share entry object.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap,
- KeyShareEntry** keyShareEntry)
- {
- KeyShareEntry* kse;
- KeyShareEntry** next;
- kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap,
- DYNAMIC_TYPE_TLSX);
- if (kse == NULL)
- return MEMORY_E;
- XMEMSET(kse, 0, sizeof(*kse));
- kse->group = (word16)group;
- /* Add it to the back and maintain the links. */
- while (*list != NULL) {
- /* Assign to temporary to work around compiler bug found by customer. */
- next = &((*list)->next);
- list = next;
- }
- *list = kse;
- *keyShareEntry = kse;
- (void)heap;
- return 0;
- }
- /* Use the data to create a new key share object in the extensions.
- *
- * ssl The SSL/TLS object.
- * group The named group.
- * len The length of the public key data.
- * data The public key data.
- * kse The new key share entry object.
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data,
- KeyShareEntry **kse)
- {
- int ret = 0;
- TLSX* extension;
- KeyShareEntry* keyShareEntry = NULL;
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL)
- return MEMORY_E;
- }
- extension->resp = 0;
- /* Try to find the key share entry with this group. */
- keyShareEntry = (KeyShareEntry*)extension->data;
- while (keyShareEntry != NULL) {
- if (keyShareEntry->group == group)
- break;
- keyShareEntry = keyShareEntry->next;
- }
- /* Create a new key share entry if not found. */
- if (keyShareEntry == NULL) {
- ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group,
- ssl->heap, &keyShareEntry);
- if (ret != 0)
- return ret;
- }
- if (data != NULL) {
- if (keyShareEntry->ke != NULL) {
- XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- keyShareEntry->ke = data;
- keyShareEntry->keLen = len;
- }
- else {
- /* Generate a key pair. */
- ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry);
- if (ret != 0)
- return ret;
- }
- if (kse != NULL)
- *kse = keyShareEntry;
- return 0;
- }
- /* Set an empty Key Share extension.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_KeyShare_Empty(WOLFSSL* ssl)
- {
- int ret = 0;
- TLSX* extension;
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- }
- else if (extension->data != NULL) {
- TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
- extension->data = NULL;
- }
- return ret;
- }
- /* Returns whether this group is supported.
- *
- * namedGroup The named group to check.
- * returns 1 when supported or 0 otherwise.
- */
- static int TLSX_KeyShare_IsSupported(int namedGroup)
- {
- switch (namedGroup) {
- #ifdef HAVE_FFDHE_2048
- case WOLFSSL_FFDHE_2048:
- break;
- #endif
- #ifdef HAVE_FFDHE_3072
- case WOLFSSL_FFDHE_3072:
- break;
- #endif
- #ifdef HAVE_FFDHE_4096
- case WOLFSSL_FFDHE_4096:
- break;
- #endif
- #ifdef HAVE_FFDHE_6144
- case WOLFSSL_FFDHE_6144:
- break;
- #endif
- #ifdef HAVE_FFDHE_8192
- case WOLFSSL_FFDHE_8192:
- break;
- #endif
- #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
- case WOLFSSL_ECC_X25519:
- break;
- #endif
- #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
- case WOLFSSL_ECC_X448:
- break;
- #endif
- #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP384R1:
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- default:
- return 0;
- }
- return 1;
- }
- /* Examines the application specified group ranking and returns the rank of the
- * group.
- * If no group ranking set then all groups are rank 0 (highest).
- *
- * ssl The SSL/TLS object.
- * group The group to check ranking for.
- * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list.
- */
- static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group)
- {
- byte i;
- if (ssl->numGroups == 0) {
- #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
- #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
- #ifndef NO_ECC_SECP
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP256R1;
- #endif
- #endif
- #endif
- #ifndef HAVE_FIPS
- #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X25519;
- #endif
- #endif
- #ifndef HAVE_FIPS
- #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X448;
- #endif
- #endif
- #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
- #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
- #ifndef NO_ECC_SECP
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP384R1;
- #endif
- #endif
- #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
- #ifndef NO_ECC_SECP
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP521R1;
- #endif
- #endif
- #endif
- /* Add FFDHE supported groups. */
- #ifdef HAVE_FFDHE_2048
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_2048;
- #endif
- #ifdef HAVE_FFDHE_3072
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_3072;
- #endif
- #ifdef HAVE_FFDHE_4096
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_4096;
- #endif
- #ifdef HAVE_FFDHE_6144
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_6144;
- #endif
- #ifdef HAVE_FFDHE_8192
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192;
- #endif
- }
- for (i = 0; i < ssl->numGroups; i++)
- if (ssl->group[i] == (word16)group)
- return i;
- return -1;
- }
- /* Set a key share that is supported by the client into extensions.
- *
- * ssl The SSL/TLS object.
- * returns BAD_KEY_SHARE_DATA if no supported group has a key share,
- * 0 if a supported group has a key share and other values indicate an error.
- */
- static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl)
- {
- int ret;
- #ifdef HAVE_SUPPORTED_CURVES
- TLSX* extension;
- SupportedCurve* curve = NULL;
- SupportedCurve* preferredCurve = NULL;
- int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
- int rank;
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (extension != NULL)
- curve = (SupportedCurve*)extension->data;
- /* Use server's preference order. */
- for (; curve != NULL; curve = curve->next) {
- if (!TLSX_KeyShare_IsSupported(curve->name))
- continue;
- rank = TLSX_KeyShare_GroupRank(ssl, curve->name);
- if (rank == -1)
- continue;
- if (rank < preferredRank) {
- preferredCurve = curve;
- preferredRank = rank;
- }
- }
- curve = preferredCurve;
- if (curve == NULL)
- return BAD_KEY_SHARE_DATA;
- /* Delete the old key share data list. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension != NULL) {
- TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
- extension->data = NULL;
- }
- /* Add in the chosen group. */
- ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL);
- if (ret != 0)
- return ret;
- /* Set extension to be in response. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- extension->resp = 1;
- #else
- (void)ssl;
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- /* Ensure there is a key pair that can be used for key exchange.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_KeyShare_Establish(WOLFSSL *ssl)
- {
- int ret;
- TLSX* extension;
- KeyShareEntry* clientKSE = NULL;
- KeyShareEntry* serverKSE;
- KeyShareEntry* list = NULL;
- KeyShareEntry* preferredKSE = NULL;
- int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
- int rank;
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension != NULL)
- list = (KeyShareEntry*)extension->data;
- if (extension && extension->resp == 1)
- return 0;
- /* Use server's preference order. */
- for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) {
- if (clientKSE->ke == NULL)
- continue;
- /* Check consistency now - extensions in any order. */
- if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group))
- return BAD_KEY_SHARE_DATA;
- if ((clientKSE->group & NAMED_DH_MASK) == 0) {
- /* Check max value supported. */
- if (clientKSE->group > WOLFSSL_ECC_MAX) {
- continue;
- }
- #ifdef OPENSSL_EXTRA
- /* Check if server supports group. */
- if (ssl->ctx->disabledCurves & ((word32)1 << clientKSE->group))
- continue;
- #endif
- }
- if (!TLSX_KeyShare_IsSupported(clientKSE->group))
- continue;
- rank = TLSX_KeyShare_GroupRank(ssl, clientKSE->group);
- if (rank == -1)
- continue;
- if (rank < preferredRank) {
- preferredKSE = clientKSE;
- preferredRank = rank;
- }
- }
- clientKSE = preferredKSE;
- /* No supported group found - send HelloRetryRequest. */
- if (clientKSE == NULL) {
- ret = TLSX_KeyShare_SetSupported(ssl);
- /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */
- if (ret == 0)
- return KEY_SHARE_ERROR;
- return ret;
- }
- list = NULL;
- /* Generate a new key pair. */
- ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE);
- if (ret != 0)
- return ret;
- if (clientKSE->key == NULL) {
- ret = TLSX_KeyShare_GenKey(ssl, serverKSE);
- if (ret != 0)
- return ret;
- }
- else {
- serverKSE->key = clientKSE->key;
- serverKSE->keyLen = clientKSE->keyLen;
- serverKSE->pubKey = clientKSE->pubKey;
- serverKSE->pubKeyLen = clientKSE->pubKeyLen;
- clientKSE->key = NULL;
- clientKSE->pubKey = NULL;
- }
- serverKSE->ke = clientKSE->ke;
- serverKSE->keLen = clientKSE->keLen;
- clientKSE->ke = NULL;
- clientKSE->keLen = 0;
- TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
- extension->data = (void *)serverKSE;
- extension->resp = 1;
- return 0;
- }
- /* Derive the shared secret of the key exchange.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl)
- {
- int ret;
- TLSX* extension;
- KeyShareEntry* list = NULL;
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension != NULL)
- list = (KeyShareEntry*)extension->data;
- if (list == NULL)
- return KEY_SHARE_ERROR;
- /* Calculate secret. */
- ret = TLSX_KeyShare_Process(ssl, list);
- if (ret != 0)
- return ret;
- return ret;
- }
- #define KS_FREE_ALL TLSX_KeyShare_FreeAll
- #define KS_GET_SIZE TLSX_KeyShare_GetSize
- #define KS_WRITE TLSX_KeyShare_Write
- #define KS_PARSE TLSX_KeyShare_Parse
- #else
- #define KS_FREE_ALL(a, b)
- #define KS_GET_SIZE(a, b) 0
- #define KS_WRITE(a, b, c) 0
- #define KS_PARSE(a, b, c, d) 0
- #endif /* WOLFSSL_TLS13 */
- /******************************************************************************/
- /* Pre-Shared Key */
- /******************************************************************************/
- #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- /* Free the pre-shared key dynamic data.
- *
- * list The linked list of key share entry objects.
- * heap The heap used for allocation.
- */
- static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap)
- {
- PreSharedKey* current;
- while ((current = list) != NULL) {
- list = current->next;
- XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX);
- XFREE(current, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- /* Get the size of the encoded pre shared key extension.
- *
- * list The linked list of pre-shared key extensions.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded pre-shared key extension or
- * SANITY_MSG_E to indicate invalid message type.
- */
- static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType,
- word16* pSz)
- {
- if (msgType == client_hello) {
- /* Length of identities + Length of binders. */
- word16 len = OPAQUE16_LEN + OPAQUE16_LEN;
- while (list != NULL) {
- /* Each entry has: identity, ticket age and binder. */
- len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN +
- OPAQUE8_LEN + list->binderLen;
- list = list->next;
- }
- *pSz += len;
- return 0;
- }
- if (msgType == server_hello) {
- *pSz += OPAQUE16_LEN;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* The number of bytes to be written for the binders.
- *
- * list The linked list of pre-shared key extensions.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded pre-shared key extension or
- * SANITY_MSG_E to indicate invalid message type.
- */
- int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType,
- word16* pSz)
- {
- word16 len;
- if (msgType != client_hello)
- return SANITY_MSG_E;
- /* Length of all binders. */
- len = OPAQUE16_LEN;
- while (list != NULL) {
- len += OPAQUE8_LEN + list->binderLen;
- list = list->next;
- }
- *pSz = len;
- return 0;
- }
- /* Writes the pre-shared key extension into the output buffer - binders only.
- * Assumes that the the output buffer is big enough to hold data.
- *
- * list The linked list of key share entries.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
- int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output,
- byte msgType, word16* pSz)
- {
- PreSharedKey* current = list;
- word16 idx = 0;
- word16 lenIdx;
- word16 len;
- if (msgType != client_hello)
- return SANITY_MSG_E;
- /* Skip length of all binders. */
- lenIdx = idx;
- idx += OPAQUE16_LEN;
- while (current != NULL) {
- /* Binder data length. */
- output[idx++] = current->binderLen;
- /* Binder data. */
- XMEMCPY(output + idx, current->binder, current->binderLen);
- idx += current->binderLen;
- current = current->next;
- }
- /* Length of the binders. */
- len = idx - lenIdx - OPAQUE16_LEN;
- c16toa(len, output + lenIdx);
- *pSz = idx;
- return 0;
- }
- /* Writes the pre-shared key extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- *
- * list The linked list of key share entries.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
- static int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output,
- byte msgType, word16* pSz)
- {
- if (msgType == client_hello) {
- PreSharedKey* current = list;
- word16 idx = 0;
- word16 lenIdx;
- word16 len;
- int ret;
- /* Write identites only. Binders after HMACing over this. */
- lenIdx = idx;
- idx += OPAQUE16_LEN;
- while (current != NULL) {
- /* Identity length */
- c16toa(current->identityLen, output + idx);
- idx += OPAQUE16_LEN;
- /* Identity data */
- XMEMCPY(output + idx, current->identity, current->identityLen);
- idx += current->identityLen;
- /* Obfuscated ticket age. */
- c32toa(current->ticketAge, output + idx);
- idx += OPAQUE32_LEN;
- current = current->next;
- }
- /* Length of the identites. */
- len = idx - lenIdx - OPAQUE16_LEN;
- c16toa(len, output + lenIdx);
- /* Don't include binders here.
- * The binders are based on the hash of all the ClientHello data up to
- * and include the identities written above.
- */
- ret = TLSX_PreSharedKey_GetSizeBinders(list, msgType, &len);
- if (ret < 0)
- return ret;
- *pSz += idx + len;
- }
- else if (msgType == server_hello) {
- word16 i;
- /* Find the index of the chosen identity. */
- for (i=0; list != NULL && !list->chosen; i++)
- list = list->next;
- if (list == NULL)
- return BUILD_MSG_ERROR;
- /* The index of the identity chosen by the server from the list supplied
- * by the client.
- */
- c16toa(i, output);
- *pSz += OPAQUE16_LEN;
- }
- else
- return SANITY_MSG_E;
- return 0;
- }
- /* Parse the pre-shared key extension.
- * Different formats in different messages.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
- {
- TLSX* extension;
- PreSharedKey* list;
- if (msgType == client_hello) {
- int ret;
- word16 len;
- word16 idx = 0;
- TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
- /* Length of identities and of binders. */
- if ((int)(length - idx) < OPAQUE16_LEN + OPAQUE16_LEN)
- return BUFFER_E;
- /* Length of identities. */
- ato16(input + idx, &len);
- idx += OPAQUE16_LEN;
- if (len < MIN_PSK_ID_LEN || length - idx < len)
- return BUFFER_E;
- /* Create a pre-shared key object for each identity. */
- while (len > 0) {
- byte* identity;
- word16 identityLen;
- word32 age;
- if (len < OPAQUE16_LEN)
- return BUFFER_E;
- /* Length of identity. */
- ato16(input + idx, &identityLen);
- idx += OPAQUE16_LEN;
- if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN ||
- identityLen > MAX_PSK_ID_LEN)
- return BUFFER_E;
- /* Cache identity pointer. */
- identity = input + idx;
- idx += identityLen;
- /* Ticket age. */
- ato32(input + idx, &age);
- idx += OPAQUE32_LEN;
- ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, no_mac,
- 0, 0, 1, NULL);
- if (ret != 0)
- return ret;
- /* Done with this identity. */
- len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN;
- }
- /* Find the list of identities sent to server. */
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL)
- return PSK_KEY_ERROR;
- list = (PreSharedKey*)extension->data;
- /* Length of binders. */
- if (idx + OPAQUE16_LEN > length)
- return BUFFER_E;
- ato16(input + idx, &len);
- idx += OPAQUE16_LEN;
- if (len < MIN_PSK_BINDERS_LEN || length - idx < len)
- return BUFFER_E;
- /* Set binder for each identity. */
- while (list != NULL && len > 0) {
- /* Length of binder */
- list->binderLen = input[idx++];
- if (list->binderLen < WC_SHA256_DIGEST_SIZE ||
- list->binderLen > WC_MAX_DIGEST_SIZE)
- return BUFFER_E;
- if (len < OPAQUE8_LEN + list->binderLen)
- return BUFFER_E;
- /* Copy binder into static buffer. */
- XMEMCPY(list->binder, input + idx, list->binderLen);
- idx += list->binderLen;
- /* Done with binder entry. */
- len -= OPAQUE8_LEN + list->binderLen;
- /* Next identity. */
- list = list->next;
- }
- if (list != NULL || len != 0)
- return BUFFER_E;
- return 0;
- }
- if (msgType == server_hello) {
- word16 idx;
- /* Index of identity chosen by server. */
- if (length != OPAQUE16_LEN)
- return BUFFER_E;
- ato16(input, &idx);
- #ifdef WOLFSSL_EARLY_DATA
- ssl->options.pskIdIndex = idx + 1;
- #endif
- /* Find the list of identities sent to server. */
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL)
- return PSK_KEY_ERROR;
- list = (PreSharedKey*)extension->data;
- /* Mark the identity as chosen. */
- for (; list != NULL && idx > 0; idx--)
- list = list->next;
- if (list == NULL)
- return PSK_KEY_ERROR;
- list->chosen = 1;
- #ifdef HAVE_SESSION_TICKET
- if (list->resumption) {
- /* Check that the session's details are the same as the server's. */
- if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 ||
- ssl->options.cipherSuite != ssl->session.cipherSuite ||
- ssl->session.version.major != ssl->ctx->method->version.major ||
- ssl->session.version.minor != ssl->ctx->method->version.minor) {
- return PSK_KEY_ERROR;
- }
- }
- #endif
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Create a new pre-shared key and put it into the list.
- *
- * list The linked list of pre-shared key.
- * identity The identity.
- * len The length of the identity data.
- * heap The memory to allocate with.
- * preSharedKey The new pre-shared key object.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity,
- word16 len, void *heap,
- PreSharedKey** preSharedKey)
- {
- PreSharedKey* psk;
- PreSharedKey** next;
- psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX);
- if (psk == NULL)
- return MEMORY_E;
- XMEMSET(psk, 0, sizeof(*psk));
- /* Make a copy of the identity data. */
- psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX);
- if (psk->identity == NULL) {
- XFREE(psk, heap, DYNAMIC_TYPE_TLSX);
- return MEMORY_E;
- }
- XMEMCPY(psk->identity, identity, len);
- psk->identityLen = len;
- /* Add it to the end and maintain the links. */
- while (*list != NULL) {
- /* Assign to temporary to work around compiler bug found by customer. */
- next = &((*list)->next);
- list = next;
- }
- *list = psk;
- *preSharedKey = psk;
- (void)heap;
- return 0;
- }
- static WC_INLINE byte GetHmacLength(int hmac)
- {
- switch (hmac) {
- #ifndef NO_SHA256
- case sha256_mac:
- return WC_SHA256_DIGEST_SIZE;
- #endif
- #ifdef WOLFSSL_SHA384
- case sha384_mac:
- return WC_SHA384_DIGEST_SIZE;
- #endif
- #ifdef WOLFSSL_SHA512
- case sha512_mac:
- return WC_SHA512_DIGEST_SIZE;
- #endif
- }
- return 0;
- }
- /* Use the data to create a new pre-shared key object in the extensions.
- *
- * ssl The SSL/TLS object.
- * identity The identity.
- * len The length of the identity data.
- * age The age of the identity.
- * hmac The HMAC algorithm.
- * ciphersuite0 The first byte of the ciphersuite to use.
- * ciphersuite The second byte of the ciphersuite to use.
- * resumption The PSK is for resumption of a session.
- * preSharedKey The new pre-shared key object.
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age,
- byte hmac, byte cipherSuite0,
- byte cipherSuite, byte resumption,
- PreSharedKey **preSharedKey)
- {
- int ret = 0;
- TLSX* extension;
- PreSharedKey* psk = NULL;
- /* Find the pre-shared key extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL) {
- /* Push new pre-shared key extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL)
- return MEMORY_E;
- }
- /* Try to find the pre-shared key with this identity. */
- psk = (PreSharedKey*)extension->data;
- while (psk != NULL) {
- if ((psk->identityLen == len) &&
- (XMEMCMP(psk->identity, identity, len) == 0)) {
- break;
- }
- psk = psk->next;
- }
- /* Create a new pre-shared key object if not found. */
- if (psk == NULL) {
- ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity,
- len, ssl->heap, &psk);
- if (ret != 0)
- return ret;
- }
- /* Update/set age and HMAC algorithm. */
- psk->ticketAge = age;
- psk->hmac = hmac;
- psk->cipherSuite0 = cipherSuite0;
- psk->cipherSuite = cipherSuite;
- psk->resumption = resumption;
- psk->binderLen = GetHmacLength(psk->hmac);
- if (preSharedKey != NULL)
- *preSharedKey = psk;
- return 0;
- }
- #define PSK_FREE_ALL TLSX_PreSharedKey_FreeAll
- #define PSK_GET_SIZE TLSX_PreSharedKey_GetSize
- #define PSK_WRITE TLSX_PreSharedKey_Write
- #define PSK_PARSE TLSX_PreSharedKey_Parse
- #else
- #define PSK_FREE_ALL(a, b)
- #define PSK_GET_SIZE(a, b, c) 0
- #define PSK_WRITE(a, b, c, d) 0
- #define PSK_PARSE(a, b, c, d) 0
- #endif
- /******************************************************************************/
- /* PSK Key Exchange Modes */
- /******************************************************************************/
- #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- /* Get the size of the encoded PSK KE modes extension.
- * Only in ClientHello.
- *
- * modes The PSK KE mode bit string.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded PSK KE mode extension.
- */
- static int TLSX_PskKeModes_GetSize(byte modes, byte msgType, word16* pSz)
- {
- if (msgType == client_hello) {
- /* Format: Len | Modes* */
- word16 len = OPAQUE8_LEN;
- /* Check whether each possible mode is to be written. */
- if (modes & (1 << PSK_KE))
- len += OPAQUE8_LEN;
- if (modes & (1 << PSK_DHE_KE))
- len += OPAQUE8_LEN;
- *pSz += len;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Writes the PSK KE modes extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- * Only in ClientHello.
- *
- * modes The PSK KE mode bit string.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
- static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType,
- word16* pSz)
- {
- if (msgType == client_hello) {
- /* Format: Len | Modes* */
- int idx = OPAQUE8_LEN;
- /* Write out each possible mode. */
- if (modes & (1 << PSK_KE))
- output[idx++] = PSK_KE;
- if (modes & (1 << PSK_DHE_KE))
- output[idx++] = PSK_DHE_KE;
- /* Write out length of mode list. */
- output[0] = idx - OPAQUE8_LEN;
- *pSz += idx;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Parse the PSK KE modes extension.
- * Only in ClientHello.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
- {
- int ret;
- if (msgType == client_hello) {
- /* Format: Len | Modes* */
- int idx = 0;
- word16 len;
- byte modes = 0;
- /* Ensure length byte exists. */
- if (length < OPAQUE8_LEN)
- return BUFFER_E;
- /* Get length of mode list and ensure that is the only data. */
- len = input[0];
- if (length - OPAQUE8_LEN != len)
- return BUFFER_E;
- idx = OPAQUE8_LEN;
- /* Set a bit for each recognized modes. */
- while (len > 0) {
- /* Ignore unrecognized modes. */
- if (input[idx] <= PSK_DHE_KE)
- modes |= 1 << input[idx];
- idx++;
- len--;
- }
- ret = TLSX_PskKeModes_Use(ssl, modes);
- if (ret != 0)
- return ret;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Use the data to create a new PSK Key Exchange Modes object in the extensions.
- *
- * ssl The SSL/TLS object.
- * modes The PSK key exchange modes.
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes)
- {
- int ret = 0;
- TLSX* extension;
- /* Find the PSK key exchange modes extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
- if (extension == NULL) {
- /* Push new PSK key exchange modes extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL,
- ssl->heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
- if (extension == NULL)
- return MEMORY_E;
- }
- extension->val = modes;
- return 0;
- }
- #define PKM_GET_SIZE TLSX_PskKeModes_GetSize
- #define PKM_WRITE TLSX_PskKeModes_Write
- #define PKM_PARSE TLSX_PskKeModes_Parse
- #else
- #define PKM_GET_SIZE(a, b, c) 0
- #define PKM_WRITE(a, b, c, d) 0
- #define PKM_PARSE(a, b, c, d) 0
- #endif
- /******************************************************************************/
- /* Post-Handshake Authentication */
- /******************************************************************************/
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- /* Get the size of the encoded Post-Handshake Authentication extension.
- * Only in ClientHello.
- *
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded Post-Handshake Authentication
- * extension.
- */
- static int TLSX_PostHandAuth_GetSize(byte msgType, word16* pSz)
- {
- if (msgType == client_hello) {
- *pSz += 0;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Writes the Post-Handshake Authentication extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- * Only in ClientHello.
- *
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
- static int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz)
- {
- (void)output;
- if (msgType == client_hello) {
- *pSz += 0;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Parse the Post-Handshake Authentication extension.
- * Only in ClientHello.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
- {
- (void)input;
- if (msgType == client_hello) {
- /* Ensure extension is empty. */
- if (length != 0)
- return BUFFER_E;
- ssl->options.postHandshakeAuth = 1;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Create a new Post-handshake authentication object in the extensions.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_PostHandAuth_Use(WOLFSSL* ssl)
- {
- int ret = 0;
- TLSX* extension;
- /* Find the PSK key exchange modes extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_POST_HANDSHAKE_AUTH);
- if (extension == NULL) {
- /* Push new Post-handshake Authentication extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_POST_HANDSHAKE_AUTH, NULL,
- ssl->heap);
- if (ret != 0)
- return ret;
- }
- return 0;
- }
- #define PHA_GET_SIZE TLSX_PostHandAuth_GetSize
- #define PHA_WRITE TLSX_PostHandAuth_Write
- #define PHA_PARSE TLSX_PostHandAuth_Parse
- #else
- #define PHA_GET_SIZE(a, b) 0
- #define PHA_WRITE(a, b, c) 0
- #define PHA_PARSE(a, b, c, d) 0
- #endif
- /******************************************************************************/
- /* Early Data Indication */
- /******************************************************************************/
- #ifdef WOLFSSL_EARLY_DATA
- /* Get the size of the encoded Early Data Indication extension.
- * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
- *
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded Early Data Indication extension.
- */
- static int TLSX_EarlyData_GetSize(byte msgType, word16* pSz)
- {
- int ret = 0;
- if (msgType == client_hello || msgType == encrypted_extensions)
- *pSz += 0;
- else if (msgType == session_ticket)
- *pSz += OPAQUE32_LEN;
- else
- ret = SANITY_MSG_E;
- return ret;
- }
- /* Writes the Early Data Indicator extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
- *
- * maxSz The maximum early data size.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
- static int TLSX_EarlyData_Write(word32 maxSz, byte* output, byte msgType,
- word16* pSz)
- {
- if (msgType == client_hello || msgType == encrypted_extensions)
- return 0;
- else if (msgType == session_ticket) {
- c32toa(maxSz, output);
- *pSz += OPAQUE32_LEN;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Parse the Early Data Indicator extension.
- * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
- {
- if (msgType == client_hello) {
- if (length != 0)
- return BUFFER_E;
- if (ssl->earlyData == expecting_early_data)
- return TLSX_EarlyData_Use(ssl, 0);
- ssl->earlyData = early_data_ext;
- return 0;
- }
- if (msgType == encrypted_extensions) {
- if (length != 0)
- return BUFFER_E;
- /* Ensure the index of PSK identity chosen by server is 0.
- * Index is plus one to handle 'not set' value of 0.
- */
- if (ssl->options.pskIdIndex != 1)
- return PSK_KEY_ERROR;
- return TLSX_EarlyData_Use(ssl, 1);
- }
- if (msgType == session_ticket) {
- word32 maxSz;
- if (length != OPAQUE32_LEN)
- return BUFFER_E;
- ato32(input, &maxSz);
- ssl->session.maxEarlyDataSz = maxSz;
- return 0;
- }
- return SANITY_MSG_E;
- }
- /* Use the data to create a new Early Data object in the extensions.
- *
- * ssl The SSL/TLS object.
- * maxSz The maximum early data size.
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 maxSz)
- {
- int ret = 0;
- TLSX* extension;
- /* Find the early data extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
- if (extension == NULL) {
- /* Push new early data extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_EARLY_DATA, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
- if (extension == NULL)
- return MEMORY_E;
- }
- extension->resp = 1;
- extension->val = maxSz;
- return 0;
- }
- #define EDI_GET_SIZE TLSX_EarlyData_GetSize
- #define EDI_WRITE TLSX_EarlyData_Write
- #define EDI_PARSE TLSX_EarlyData_Parse
- #else
- #define EDI_GET_SIZE(a, b) 0
- #define EDI_WRITE(a, b, c, d) 0
- #define EDI_PARSE(a, b, c, d) 0
- #endif
- /******************************************************************************/
- /* TLS Extensions Framework */
- /******************************************************************************/
- /** Finds an extension in the provided list. */
- TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
- {
- TLSX* extension = list;
- while (extension && extension->type != type)
- extension = extension->next;
- return extension;
- }
- /** Remove an extension. */
- void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap)
- {
- TLSX* extension = *list;
- TLSX** next = list;
- while (extension && extension->type != type) {
- next = &extension->next;
- extension = extension->next;
- }
- if (extension) {
- *next = extension->next;
- extension->next = NULL;
- TLSX_FreeAll(extension, heap);
- }
- }
- /** Releases all extensions in the provided list. */
- void TLSX_FreeAll(TLSX* list, void* heap)
- {
- TLSX* extension;
- while ((extension = list)) {
- list = extension->next;
- switch (extension->type) {
- #ifdef HAVE_SNI
- case TLSX_SERVER_NAME:
- SNI_FREE_ALL((SNI*)extension->data, heap);
- break;
- #endif
- case TLSX_TRUSTED_CA_KEYS:
- TCA_FREE_ALL((TCA*)extension->data, heap);
- break;
- case TLSX_MAX_FRAGMENT_LENGTH:
- MFL_FREE_ALL(extension->data, heap);
- break;
- case TLSX_EXTENDED_MASTER_SECRET:
- case TLSX_TRUNCATED_HMAC:
- /* Nothing to do. */
- break;
- case TLSX_SUPPORTED_GROUPS:
- EC_FREE_ALL((SupportedCurve*)extension->data, heap);
- break;
- case TLSX_EC_POINT_FORMATS:
- PF_FREE_ALL((PointFormat*)extension->data, heap);
- break;
- case TLSX_STATUS_REQUEST:
- CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap);
- break;
- case TLSX_STATUS_REQUEST_V2:
- CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data,
- heap);
- break;
- case TLSX_RENEGOTIATION_INFO:
- SCR_FREE_ALL(extension->data, heap);
- break;
- case TLSX_SESSION_TICKET:
- WOLF_STK_FREE(extension->data, heap);
- break;
- case TLSX_QUANTUM_SAFE_HYBRID:
- QSH_FREE_ALL((QSHScheme*)extension->data, heap);
- break;
- case TLSX_APPLICATION_LAYER_PROTOCOL:
- ALPN_FREE_ALL((ALPN*)extension->data, heap);
- break;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS:
- break;
- #endif
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- case TLSX_ENCRYPT_THEN_MAC:
- break;
- #endif
- #ifdef WOLFSSL_TLS13
- case TLSX_SUPPORTED_VERSIONS:
- break;
- #ifdef WOLFSSL_SEND_HRR_COOKIE
- case TLSX_COOKIE:
- CKE_FREE_ALL((Cookie*)extension->data, heap);
- break;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- case TLSX_PRE_SHARED_KEY:
- PSK_FREE_ALL((PreSharedKey*)extension->data, heap);
- break;
- case TLSX_PSK_KEY_EXCHANGE_MODES:
- break;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- case TLSX_EARLY_DATA:
- break;
- #endif
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- case TLSX_POST_HANDSHAKE_AUTH:
- break;
- #endif
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS_CERT:
- break;
- #endif
- case TLSX_KEY_SHARE:
- KS_FREE_ALL((KeyShareEntry*)extension->data, heap);
- break;
- #endif
- }
- XFREE(extension, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- /** Checks if the tls extensions are supported based on the protocol version. */
- int TLSX_SupportExtensions(WOLFSSL* ssl) {
- return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR);
- }
- /** Tells the buffered size of the extensions in a list. */
- static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
- word16* pLength)
- {
- int ret = 0;
- TLSX* extension;
- word16 length = 0;
- byte isRequest = (msgType == client_hello ||
- msgType == certificate_request);
- while ((extension = list)) {
- list = extension->next;
- /* only extensions marked as response are sent back to the client. */
- if (!isRequest && !extension->resp)
- continue; /* skip! */
- /* ssl level extensions are expected to override ctx level ones. */
- if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
- continue; /* skip! */
- /* extension type + extension data length. */
- length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
- switch (extension->type) {
- #ifdef HAVE_SNI
- case TLSX_SERVER_NAME:
- /* SNI only sends the name on the request. */
- if (isRequest)
- length += SNI_GET_SIZE((SNI*)extension->data);
- break;
- #endif
- case TLSX_TRUSTED_CA_KEYS:
- /* TCA only sends the list on the request. */
- if (isRequest)
- length += TCA_GET_SIZE((TCA*)extension->data);
- break;
- case TLSX_MAX_FRAGMENT_LENGTH:
- length += MFL_GET_SIZE(extension->data);
- break;
- case TLSX_EXTENDED_MASTER_SECRET:
- case TLSX_TRUNCATED_HMAC:
- /* always empty. */
- break;
- case TLSX_SUPPORTED_GROUPS:
- length += EC_GET_SIZE((SupportedCurve*)extension->data);
- break;
- case TLSX_EC_POINT_FORMATS:
- length += PF_GET_SIZE((PointFormat*)extension->data);
- break;
- case TLSX_STATUS_REQUEST:
- length += CSR_GET_SIZE(
- (CertificateStatusRequest*)extension->data, isRequest);
- break;
- case TLSX_STATUS_REQUEST_V2:
- length += CSR2_GET_SIZE(
- (CertificateStatusRequestItemV2*)extension->data,
- isRequest);
- break;
- case TLSX_RENEGOTIATION_INFO:
- length += SCR_GET_SIZE((SecureRenegotiation*)extension->data,
- isRequest);
- break;
- case TLSX_SESSION_TICKET:
- length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data,
- isRequest);
- break;
- case TLSX_QUANTUM_SAFE_HYBRID:
- length += QSH_GET_SIZE((QSHScheme*)extension->data, isRequest);
- break;
- case TLSX_APPLICATION_LAYER_PROTOCOL:
- length += ALPN_GET_SIZE((ALPN*)extension->data);
- break;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS:
- length += SA_GET_SIZE(extension->data);
- break;
- #endif
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- case TLSX_ENCRYPT_THEN_MAC:
- ret = ETM_GET_SIZE(msgType, &length);
- break;
- #endif /* HAVE_ENCRYPT_THEN_MAC */
- #ifdef WOLFSSL_TLS13
- case TLSX_SUPPORTED_VERSIONS:
- ret = SV_GET_SIZE(extension->data, msgType, &length);
- break;
- #ifdef WOLFSSL_SEND_HRR_COOKIE
- case TLSX_COOKIE:
- ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &length);
- break;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- case TLSX_PRE_SHARED_KEY:
- ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType,
- &length);
- break;
- case TLSX_PSK_KEY_EXCHANGE_MODES:
- ret = PKM_GET_SIZE(extension->val, msgType, &length);
- break;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- case TLSX_EARLY_DATA:
- ret = EDI_GET_SIZE(msgType, &length);
- break;
- #endif
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- case TLSX_POST_HANDSHAKE_AUTH:
- ret = PHA_GET_SIZE(msgType, &length);
- break;
- #endif
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS_CERT:
- length += SAC_GET_SIZE(extension->data);
- break;
- #endif
- case TLSX_KEY_SHARE:
- length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType);
- break;
- #endif
- }
- /* marks the extension as processed so ctx level */
- /* extensions don't overlap with ssl level ones. */
- TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
- }
- *pLength += length;
- return ret;
- }
- /** Writes the extensions of a list in a buffer. */
- static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
- byte msgType, word16* pOffset)
- {
- int ret = 0;
- TLSX* extension;
- word16 offset = 0;
- word16 length_offset = 0;
- byte isRequest = (msgType == client_hello ||
- msgType == certificate_request);
- while ((extension = list)) {
- list = extension->next;
- /* only extensions marked as response are written in a response. */
- if (!isRequest && !extension->resp)
- continue; /* skip! */
- /* ssl level extensions are expected to override ctx level ones. */
- if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
- continue; /* skip! */
- /* writes extension type. */
- c16toa(extension->type, output + offset);
- offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
- length_offset = offset;
- /* extension data should be written internally. */
- switch (extension->type) {
- #ifdef HAVE_SNI
- case TLSX_SERVER_NAME:
- if (isRequest) {
- WOLFSSL_MSG("SNI extension to write");
- offset += SNI_WRITE((SNI*)extension->data, output + offset);
- }
- break;
- #endif
- case TLSX_TRUSTED_CA_KEYS:
- WOLFSSL_MSG("Trusted CA Indication extension to write");
- if (isRequest) {
- offset += TCA_WRITE((TCA*)extension->data, output + offset);
- }
- break;
- case TLSX_MAX_FRAGMENT_LENGTH:
- WOLFSSL_MSG("Max Fragment Length extension to write");
- offset += MFL_WRITE((byte*)extension->data, output + offset);
- break;
- case TLSX_EXTENDED_MASTER_SECRET:
- WOLFSSL_MSG("Extended Master Secret");
- /* always empty. */
- break;
- case TLSX_TRUNCATED_HMAC:
- WOLFSSL_MSG("Truncated HMAC extension to write");
- /* always empty. */
- break;
- case TLSX_SUPPORTED_GROUPS:
- WOLFSSL_MSG("Supported Groups extension to write");
- offset += EC_WRITE((SupportedCurve*)extension->data,
- output + offset);
- break;
- case TLSX_EC_POINT_FORMATS:
- WOLFSSL_MSG("Point Formats extension to write");
- offset += PF_WRITE((PointFormat*)extension->data,
- output + offset);
- break;
- case TLSX_STATUS_REQUEST:
- WOLFSSL_MSG("Certificate Status Request extension to write");
- offset += CSR_WRITE((CertificateStatusRequest*)extension->data,
- output + offset, isRequest);
- break;
- case TLSX_STATUS_REQUEST_V2:
- WOLFSSL_MSG("Certificate Status Request v2 extension to write");
- offset += CSR2_WRITE(
- (CertificateStatusRequestItemV2*)extension->data,
- output + offset, isRequest);
- break;
- case TLSX_RENEGOTIATION_INFO:
- WOLFSSL_MSG("Secure Renegotiation extension to write");
- offset += SCR_WRITE((SecureRenegotiation*)extension->data,
- output + offset, isRequest);
- break;
- case TLSX_SESSION_TICKET:
- WOLFSSL_MSG("Session Ticket extension to write");
- offset += WOLF_STK_WRITE((SessionTicket*)extension->data,
- output + offset, isRequest);
- break;
- case TLSX_QUANTUM_SAFE_HYBRID:
- WOLFSSL_MSG("Quantum-Safe-Hybrid extension to write");
- if (isRequest) {
- offset += QSH_WRITE((QSHScheme*)extension->data, output + offset);
- }
- offset += QSHPK_WRITE((QSHScheme*)extension->data, output + offset);
- offset += QSH_SERREQ(output + offset, isRequest);
- break;
- case TLSX_APPLICATION_LAYER_PROTOCOL:
- WOLFSSL_MSG("ALPN extension to write");
- offset += ALPN_WRITE((ALPN*)extension->data, output + offset);
- break;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS:
- WOLFSSL_MSG("Signature Algorithms extension to write");
- offset += SA_WRITE(extension->data, output + offset);
- break;
- #endif
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- case TLSX_ENCRYPT_THEN_MAC:
- WOLFSSL_MSG("Encrypt-Then-Mac extension to write");
- ret = ETM_WRITE(extension->data, output, msgType, &offset);
- break;
- #endif /* HAVE_ENCRYPT_THEN_MAC */
- #ifdef WOLFSSL_TLS13
- case TLSX_SUPPORTED_VERSIONS:
- WOLFSSL_MSG("Supported Versions extension to write");
- ret = SV_WRITE(extension->data, output + offset, msgType, &offset);
- break;
- #ifdef WOLFSSL_SEND_HRR_COOKIE
- case TLSX_COOKIE:
- WOLFSSL_MSG("Cookie extension to write");
- ret = CKE_WRITE((Cookie*)extension->data, output + offset,
- msgType, &offset);
- break;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- case TLSX_PRE_SHARED_KEY:
- WOLFSSL_MSG("Pre-Shared Key extension to write");
- ret = PSK_WRITE((PreSharedKey*)extension->data, output + offset,
- msgType, &offset);
- break;
- case TLSX_PSK_KEY_EXCHANGE_MODES:
- WOLFSSL_MSG("PSK Key Exchange Modes extension to write");
- ret = PKM_WRITE(extension->val, output + offset, msgType,
- &offset);
- break;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- case TLSX_EARLY_DATA:
- WOLFSSL_MSG("Early Data extension to write");
- ret = EDI_WRITE(extension->val, output + offset, msgType,
- &offset);
- break;
- #endif
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- case TLSX_POST_HANDSHAKE_AUTH:
- WOLFSSL_MSG("Post-Handshake Authentication extension to write");
- ret = PHA_WRITE(output + offset, msgType, &offset);
- break;
- #endif
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS_CERT:
- WOLFSSL_MSG("Signature Algorithms extension to write");
- offset += SAC_WRITE(extension->data, output + offset);
- break;
- #endif
- case TLSX_KEY_SHARE:
- WOLFSSL_MSG("Key Share extension to write");
- offset += KS_WRITE((KeyShareEntry*)extension->data,
- output + offset, msgType);
- break;
- #endif
- }
- /* writes extension data length. */
- c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN);
- /* marks the extension as processed so ctx level */
- /* extensions don't overlap with ssl level ones. */
- TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
- }
- *pOffset += offset;
- return ret;
- }
- #if defined(HAVE_NTRU) && defined(HAVE_QSH)
- static word32 GetEntropy(unsigned char* out, word32 num_bytes)
- {
- int ret = 0;
- if (gRng == NULL) {
- if ((gRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return DRBG_OUT_OF_MEMORY;
- wc_InitRng(gRng);
- }
- if (gRngMutex == NULL) {
- if ((gRngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return DRBG_OUT_OF_MEMORY;
- wc_InitMutex(gRngMutex);
- }
- ret |= wc_LockMutex(gRngMutex);
- ret |= wc_RNG_GenerateBlock(gRng, out, num_bytes);
- ret |= wc_UnLockMutex(gRngMutex);
- if (ret != 0)
- return DRBG_ENTROPY_FAIL;
- return DRBG_OK;
- }
- #endif
- #ifdef HAVE_QSH
- static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type)
- {
- int ret = -1;
- (void)ssl;
- switch (type) {
- #ifdef HAVE_NTRU
- case WOLFSSL_NTRU_EESS439:
- case WOLFSSL_NTRU_EESS593:
- case WOLFSSL_NTRU_EESS743:
- ret = TLSX_CreateNtruKey(ssl, type);
- break;
- #endif
- default:
- WOLFSSL_MSG("Unknown type for creating NTRU key");
- break;
- }
- return ret;
- }
- static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key)
- {
- QSHKey* current;
- if (key == NULL)
- return BAD_FUNC_ARG;
- /* if no public key stored in key then do not add */
- if (key->pub.length == 0 || key->pub.buffer == NULL)
- return 0;
- /* first element to be added to the list */
- current = *list;
- if (current == NULL) {
- *list = key;
- return 0;
- }
- while (current->next) {
- /* can only have one of the key in the list */
- if (current->name == key->name)
- return -1;
- current = (QSHKey*)current->next;
- }
- current->next = (struct QSHKey*)key;
- return 0;
- }
- #if defined(HAVE_NTRU)
- int TLSX_CreateNtruKey(WOLFSSL* ssl, int type)
- {
- int ret = -1;
- int ntruType;
- /* variable declarations for NTRU*/
- QSHKey* temp = NULL;
- byte public_key[1027];
- word16 public_key_len = sizeof(public_key);
- byte private_key[1120];
- word16 private_key_len = sizeof(private_key);
- DRBG_HANDLE drbg;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- switch (type) {
- case WOLFSSL_NTRU_EESS439:
- ntruType = NTRU_EES439EP1;
- break;
- case WOLFSSL_NTRU_EESS593:
- ntruType = NTRU_EES593EP1;
- break;
- case WOLFSSL_NTRU_EESS743:
- ntruType = NTRU_EES743EP1;
- break;
- default:
- WOLFSSL_MSG("Unknown type for creating NTRU key");
- return -1;
- }
- ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
- if (ret != DRBG_OK) {
- WOLFSSL_MSG("NTRU drbg instantiate failed\n");
- return ret;
- }
- if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType,
- &public_key_len, NULL, &private_key_len, NULL)) != NTRU_OK)
- return ret;
- if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType,
- &public_key_len, public_key, &private_key_len, private_key)) != NTRU_OK)
- return ret;
- ret = ntru_crypto_drbg_uninstantiate(drbg);
- if (ret != NTRU_OK) {
- WOLFSSL_MSG("NTRU drbg uninstantiate failed\n");
- return ret;
- }
- if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return MEMORY_E;
- temp->name = type;
- temp->pub.length = public_key_len;
- temp->pub.buffer = (byte*)XMALLOC(public_key_len, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- XMEMCPY(temp->pub.buffer, public_key, public_key_len);
- temp->pri.length = private_key_len;
- temp->pri.buffer = (byte*)XMALLOC(private_key_len, ssl->heap,
- DYNAMIC_TYPE_ARRAYS);
- XMEMCPY(temp->pri.buffer, private_key, private_key_len);
- temp->next = NULL;
- TLSX_AddQSHKey(&ssl->QSH_Key, temp);
- (void)ssl;
- (void)type;
- return ret;
- }
- #endif
- /*
- Used to find a public key from the list of keys
- pubLen length of array
- name input the name of the scheme looking for ie WOLFSSL_NTRU_ESSXXX
- returns a pointer to public key byte* or NULL if not found
- */
- static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name)
- {
- QSHKey* current = qsh;
- if (qsh == NULL || pubLen == NULL)
- return NULL;
- *pubLen = 0;
- while(current) {
- if (current->name == name) {
- *pubLen = current->pub.length;
- return current->pub.buffer;
- }
- current = (QSHKey*)current->next;
- }
- return NULL;
- }
- #endif /* HAVE_QSH */
- #ifdef HAVE_SUPPORTED_CURVES
- /* Populates the default supported groups / curves */
- static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
- {
- int ret = WOLFSSL_SUCCESS;
- #ifdef WOLFSSL_TLS13
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (ssl->options.resuming && ssl->session.namedGroup != 0) {
- return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup,
- ssl->heap);
- }
- #endif
- if (ssl->numGroups != 0) {
- int i;
- for (i = 0; i < ssl->numGroups; i++) {
- ret = TLSX_UseSupportedCurve(extensions, ssl->group[i], ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
- #endif /* WOLFSSL_TLS13 */
- #if defined(HAVE_ECC)
- /* list in order by strength, since not all servers choose by strength */
- #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
- #ifndef NO_ECC_SECP
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP521R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
- #ifdef HAVE_ECC_BRAINPOOL
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
- #ifndef NO_ECC_SECP
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP384R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_BRAINPOOL
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #endif /* HAVE_ECC */
- #ifndef HAVE_FIPS
- #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_X448, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif /* HAVE_FIPS */
- #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
- #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
- #ifndef NO_ECC_SECP
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP256R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_KOBLITZ
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP256K1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_BRAINPOOL
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #endif /* HAVE_ECC */
- #ifndef HAVE_FIPS
- #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_X25519, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif /* HAVE_FIPS */
- #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
- #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224
- #ifndef NO_ECC_SECP
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP224R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_KOBLITZ
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP224K1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #ifndef HAVE_FIPS
- #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192
- #ifndef NO_ECC_SECP
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP192R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_KOBLITZ
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP192K1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160
- #ifndef NO_ECC_SECP
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP160R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_SECPR2
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP160R2, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_KOBLITZ
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP160K1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #endif /* HAVE_FIPS */
- #endif /* HAVE_ECC */
- #ifndef NO_DH
- /* Add FFDHE supported groups. */
- #ifdef HAVE_FFDHE_8192
- if (8192/8 >= ssl->options.minDhKeySz &&
- 8192/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_8192, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #ifdef HAVE_FFDHE_6144
- if (6144/8 >= ssl->options.minDhKeySz &&
- 6144/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_6144, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #ifdef HAVE_FFDHE_4096
- if (4096/8 >= ssl->options.minDhKeySz &&
- 4096/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_4096, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #ifdef HAVE_FFDHE_3072
- if (3072/8 >= ssl->options.minDhKeySz &&
- 3072/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_3072, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #ifdef HAVE_FFDHE_2048
- if (2048/8 >= ssl->options.minDhKeySz &&
- 2048/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_2048, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #endif
- (void)ssl;
- (void)extensions;
- return ret;
- }
- #endif /* HAVE_SUPPORTED_CURVES */
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
- static const word16 preferredGroup[] = {
- #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \
- defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 256
- WOLFSSL_ECC_SECP256R1,
- #endif
- #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
- WOLFSSL_ECC_X25519,
- #endif
- #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
- WOLFSSL_ECC_X448,
- #endif
- #if defined(HAVE_ECC) && (!defined(NO_ECC384) || \
- defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 384
- WOLFSSL_ECC_SECP384R1,
- #endif
- #if defined(HAVE_ECC) && (!defined(NO_ECC521) || \
- defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 521
- WOLFSSL_ECC_SECP521R1,
- #endif
- #if defined(HAVE_FFDHE_2048)
- WOLFSSL_FFDHE_2048,
- #endif
- #if defined(HAVE_FFDHE_3072)
- WOLFSSL_FFDHE_3072,
- #endif
- #if defined(HAVE_FFDHE_4096)
- WOLFSSL_FFDHE_4096,
- #endif
- #if defined(HAVE_FFDHE_6144)
- WOLFSSL_FFDHE_6144,
- #endif
- #if defined(HAVE_FFDHE_8192)
- WOLFSSL_FFDHE_8192,
- #endif
- };
- #define PREFERRED_GROUP_SZ (sizeof(preferredGroup) / sizeof(*preferredGroup))
- #endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */
- int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
- {
- int ret = 0;
- byte* public_key = NULL;
- word16 public_key_len = 0;
- #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- int usingPSK = 0;
- #endif
- #ifdef HAVE_QSH
- TLSX* extension;
- QSHScheme* qsh;
- QSHScheme* next;
- /* add supported QSHSchemes */
- WOLFSSL_MSG("Adding supported QSH Schemes");
- #endif
- /* server will add extension depending on what is parsed from client */
- if (!isServer) {
- #ifdef HAVE_QSH
- /* test if user has set a specific scheme already */
- if (!ssl->user_set_QSHSchemes) {
- if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) {
- if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return ret;
- }
- if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return ret;
- }
- if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return ret;
- }
- /* add NTRU 256 */
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, WOLFSSL_NTRU_EESS743);
- }
- if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743,
- public_key, public_key_len, ssl->heap)
- != WOLFSSL_SUCCESS)
- ret = -1;
- /* add NTRU 196 */
- if (ssl->sendQSHKeys) {
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, WOLFSSL_NTRU_EESS593);
- }
- if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593,
- public_key, public_key_len, ssl->heap)
- != WOLFSSL_SUCCESS)
- ret = -1;
- /* add NTRU 128 */
- if (ssl->sendQSHKeys) {
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, WOLFSSL_NTRU_EESS439);
- }
- if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439,
- public_key, public_key_len, ssl->heap)
- != WOLFSSL_SUCCESS)
- ret = -1;
- }
- else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) {
- /* for each scheme make a client key */
- extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID);
- if (extension) {
- qsh = (QSHScheme*)extension->data;
- while (qsh) {
- if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0)
- return ret;
- /* get next now because qsh could be freed */
- next = qsh->next;
- /* find the public key created and add to extension*/
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, qsh->name);
- if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name,
- public_key, public_key_len,
- ssl->heap) != WOLFSSL_SUCCESS)
- ret = -1;
- qsh = next;
- }
- }
- }
- #endif
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (!ssl->options.disallowEncThenMac) {
- ret = TLSX_EncryptThenMac_Use(ssl);
- if (ret != 0)
- return ret;
- }
- #endif
- #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
- defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES)
- if (!ssl->options.userCurves && !ssl->ctx->userCurves) {
- if (TLSX_Find(ssl->ctx->extensions,
- TLSX_SUPPORTED_GROUPS) == NULL) {
- ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- }
- if ((!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade) &&
- TLSX_Find(ssl->ctx->extensions, TLSX_EC_POINT_FORMATS) == NULL &&
- TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS) == NULL) {
- ret = TLSX_UsePointFormat(&ssl->extensions,
- WOLFSSL_EC_PF_UNCOMPRESSED, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
- } /* is not server */
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- WOLFSSL_MSG("Adding signature algorithms extension");
- if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap))
- != 0) {
- return ret;
- }
- #else
- ret = 0;
- #endif
- #ifdef WOLFSSL_TLS13
- if (!isServer && IsAtLeastTLSv1_3(ssl->version)) {
- /* Add mandatory TLS v1.3 extension: supported version */
- WOLFSSL_MSG("Adding supported versions extension");
- if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl,
- ssl->heap)) != 0) {
- return ret;
- }
- #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \
- !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)
- if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) {
- /* Put in DH groups for TLS 1.3 only. */
- ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- ret = 0;
- }
- #endif /* !(HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
-
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- if (ssl->certHashSigAlgoSz > 0) {
- WOLFSSL_MSG("Adding signature algorithms cert extension");
- if ((ret = TLSX_SetSignatureAlgorithmsCert(&ssl->extensions,
- ssl, ssl->heap)) != 0) {
- return ret;
- }
- }
- #endif
- #if defined(HAVE_SUPPORTED_CURVES)
- if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) {
- word16 namedGroup;
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (ssl->options.resuming && ssl->session.namedGroup != 0)
- namedGroup = ssl->session.namedGroup;
- else
- #endif
- if (PREFERRED_GROUP_SZ == 0) {
- WOLFSSL_MSG("No groups in preference list");
- return KEY_SHARE_ERROR;
- }
- else if (ssl->numGroups > 0) {
- int set = 0;
- int i, j;
- /* Default to first group in supported list. */
- namedGroup = ssl->group[0];
- /* Try to find preferred in supported list. */
- for (i = 0; i < (int)PREFERRED_GROUP_SZ && !set; i++) {
- for (j = 0; j < ssl->numGroups; j++) {
- if (preferredGroup[i] == ssl->group[j]) {
- /* Most preferred that is supported. */
- namedGroup = ssl->group[j];
- set = 1;
- break;
- }
- }
- }
- }
- else {
- /* Choose the most preferred group. */
- namedGroup = preferredGroup[0];
- }
- ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL);
- if (ret != 0)
- return ret;
- }
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
- #endif
- #if defined(HAVE_SESSION_TICKET)
- if (ssl->options.resuming && ssl->session.ticketLen > 0) {
- WOLFSSL_SESSION* sess = &ssl->session;
- word32 milli;
- if (sess->ticketLen > MAX_PSK_ID_LEN) {
- WOLFSSL_MSG("Session ticket length for PSK ext is too large");
- return BUFFER_ERROR;
- }
- /* Determine the MAC algorithm for the cipher suite used. */
- ssl->options.cipherSuite0 = sess->cipherSuite0;
- ssl->options.cipherSuite = sess->cipherSuite;
- ret = SetCipherSpecs(ssl);
- if (ret != 0)
- return ret;
- milli = TimeNowInMilliseconds() - sess->ticketSeen +
- sess->ticketAdd;
- /* Pre-shared key is mandatory extension for resumption. */
- ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen,
- milli, ssl->specs.mac_algorithm,
- ssl->options.cipherSuite0,
- ssl->options.cipherSuite, 1,
- NULL);
- if (ret != 0)
- return ret;
- usingPSK = 1;
- }
- #endif
- #ifndef NO_PSK
- if (ssl->options.client_psk_cb != NULL ||
- ssl->options.client_psk_tls13_cb != NULL) {
- /* Default ciphersuite. */
- byte cipherSuite0 = TLS13_BYTE;
- byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER;
- int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE;
- const char* cipherName = NULL;
- if (ssl->options.client_psk_tls13_cb != NULL) {
- ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(
- ssl, ssl->arrays->server_hint,
- ssl->arrays->client_identity, MAX_PSK_ID_LEN,
- ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName);
- if (GetCipherSuiteFromName(cipherName, &cipherSuite0,
- &cipherSuite, &cipherSuiteFlags) != 0) {
- return PSK_KEY_ERROR;
- }
- }
- else {
- ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
- ssl->arrays->server_hint, ssl->arrays->client_identity,
- MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
- }
- if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
- return PSK_KEY_ERROR;
- }
- ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0';
- ssl->options.cipherSuite0 = cipherSuite0;
- ssl->options.cipherSuite = cipherSuite;
- (void)cipherSuiteFlags;
- ret = SetCipherSpecs(ssl);
- if (ret != 0)
- return ret;
- ret = TLSX_PreSharedKey_Use(ssl,
- (byte*)ssl->arrays->client_identity,
- (word16)XSTRLEN(ssl->arrays->client_identity),
- 0, ssl->specs.mac_algorithm,
- cipherSuite0, cipherSuite, 0,
- NULL);
- if (ret != 0)
- return ret;
- usingPSK = 1;
- }
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (usingPSK) {
- byte modes;
- /* Pre-shared key modes: mandatory extension for resumption. */
- modes = 1 << PSK_KE;
- #if !defined(NO_DH) || defined(HAVE_ECC) || \
- defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
- if (!ssl->options.noPskDheKe)
- modes |= 1 << PSK_DHE_KE;
- #endif
- ret = TLSX_PskKeModes_Use(ssl, modes);
- if (ret != 0)
- return ret;
- }
- #endif
- #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- if (!isServer && ssl->options.postHandshakeAuth) {
- ret = TLSX_PostHandAuth_Use(ssl);
- if (ret != 0)
- return ret;
- }
- #endif
- }
- #endif
- (void)isServer;
- (void)public_key;
- (void)public_key_len;
- (void)ssl;
- return ret;
- }
- #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
- /** Tells the buffered size of extensions to be sent into the client hello. */
- int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength)
- {
- int ret = 0;
- word16 length = 0;
- byte semaphore[SEMAPHORE_SIZE] = {0};
- if (!TLSX_SupportExtensions(ssl))
- return 0;
- if (msgType == client_hello) {
- EC_VALIDATE_REQUEST(ssl, semaphore);
- PF_VALIDATE_REQUEST(ssl, semaphore);
- QSH_VALIDATE_REQUEST(ssl, semaphore);
- WOLF_STK_VALIDATE_REQUEST(ssl);
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- if (ssl->suites->hashSigAlgoSz == 0)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
- #endif
- #if defined(WOLFSSL_TLS13)
- if (!IsAtLeastTLSv1_2(ssl))
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- #endif
- #ifdef WOLFSSL_SEND_HRR_COOKIE
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
- #endif
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
- #endif
- }
- #endif
- #endif
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- if (!ssl->ctx->cm->ocspStaplingEnabled) {
- /* mark already sent, so it won't send it */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
- }
- #endif
- }
- #ifdef WOLFSSL_TLS13
- #ifndef NO_CERTS
- else if (msgType == certificate_request) {
- /* Don't send out any extension except those that are turned off. */
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
- #endif
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
- * TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS
- * TLSX_STATUS_REQUEST
- */
- }
- #endif
- #endif
- if (ssl->extensions) {
- ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length);
- if (ret != 0)
- return ret;
- }
- if (ssl->ctx && ssl->ctx->extensions) {
- ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, &length);
- if (ret != 0)
- return ret;
- }
- #ifdef HAVE_EXTENDED_MASTER
- if (msgType == client_hello && ssl->options.haveEMS &&
- (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) {
- length += HELLO_EXT_SZ;
- }
- #endif
- if (length)
- length += OPAQUE16_LEN; /* for total length storage. */
- *pLength += length;
- return ret;
- }
- /** Writes the extensions to be sent into the client hello. */
- int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset)
- {
- int ret = 0;
- word16 offset = 0;
- byte semaphore[SEMAPHORE_SIZE] = {0};
- if (!TLSX_SupportExtensions(ssl) || output == NULL)
- return 0;
- offset += OPAQUE16_LEN; /* extensions length */
- if (msgType == client_hello) {
- EC_VALIDATE_REQUEST(ssl, semaphore);
- PF_VALIDATE_REQUEST(ssl, semaphore);
- WOLF_STK_VALIDATE_REQUEST(ssl);
- QSH_VALIDATE_REQUEST(ssl, semaphore);
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- if (ssl->suites->hashSigAlgoSz == 0)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
- #endif
- #ifdef WOLFSSL_TLS13
- if (!IsAtLeastTLSv1_2(ssl))
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- #endif
- #ifdef WOLFSSL_SEND_HRR_COOKIE
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
- #endif
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
- #endif
- }
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- /* Must write Pre-shared Key extension at the end in TLS v1.3.
- * Must not write out Pre-shared Key extension in earlier versions of
- * protocol.
- */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- #endif
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- /* mark already sent, so it won't send it */
- if (!ssl->ctx->cm->ocspStaplingEnabled) {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
- }
- #endif
- }
- #ifdef WOLFSSL_TLS13
- #ifndef NO_CERTS
- else if (msgType == certificate_request) {
- /* Don't send out any extension except those that are turned off. */
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
- #endif
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
- * TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS
- * TLSX_STATUS_REQUEST
- */
- }
- #endif
- #endif
- if (ssl->extensions) {
- ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
- msgType, &offset);
- if (ret != 0)
- return ret;
- }
- if (ssl->ctx && ssl->ctx->extensions) {
- ret = TLSX_Write(ssl->ctx->extensions, output + offset, semaphore,
- msgType, &offset);
- if (ret != 0)
- return ret;
- }
- #ifdef HAVE_EXTENDED_MASTER
- if (msgType == client_hello && ssl->options.haveEMS &&
- (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) {
- WOLFSSL_MSG("EMS extension to write");
- c16toa(HELLO_EXT_EXTMS, output + offset);
- offset += HELLO_EXT_TYPE_SZ;
- c16toa(0, output + offset);
- offset += HELLO_EXT_SZ_SZ;
- }
- #endif
- #ifdef WOLFSSL_TLS13
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (msgType == client_hello && IsAtLeastTLSv1_3(ssl->version)) {
- /* Write out what we can of Pre-shared key extension. */
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
- client_hello, &offset);
- if (ret != 0)
- return ret;
- }
- #endif
- #endif
- if (offset > OPAQUE16_LEN || msgType != client_hello)
- c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
- *pOffset += offset;
- return ret;
- }
- #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
- #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
- /** Tells the buffered size of extensions to be sent into the server hello. */
- int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength)
- {
- int ret = 0;
- word16 length = 0;
- byte semaphore[SEMAPHORE_SIZE] = {0};
- switch (msgType) {
- #ifndef NO_WOLFSSL_SERVER
- case server_hello:
- PF_VALIDATE_RESPONSE(ssl, semaphore);
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore,
- TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #ifdef HAVE_SUPPORTED_CURVES
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
- else {
- #ifdef HAVE_SUPPORTED_CURVES
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- #endif
- #endif
- break;
- #ifdef WOLFSSL_TLS13
- case hello_retry_request:
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #ifdef HAVE_SUPPORTED_CURVES
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- #ifdef WOLFSSL_SEND_HRR_COOKIE
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
- #endif
- break;
- #endif
- #ifdef WOLFSSL_TLS13
- case encrypted_extensions:
- /* Send out all extension except those that are turned on. */
- #ifdef HAVE_ECC
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- #endif
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #ifdef HAVE_SESSION_TICKET
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
- #endif
- #ifdef HAVE_SUPPORTED_CURVES
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- #endif
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
- #endif
- #if defined(HAVE_SECURE_RENEGOTIATION)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
- #endif
- break;
- #ifdef WOLFSSL_EARLY_DATA
- case session_ticket:
- if (ssl->options.tls1_3) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- }
- break;
- #endif
- #endif
- #endif
- #ifdef WOLFSSL_TLS13
- #ifndef NO_CERTS
- case certificate:
- /* Don't send out any extension except those that are turned off. */
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
- * TLSX_SERVER_CERTIFICATE_TYPE
- */
- break;
- #endif
- #endif
- }
- #ifdef HAVE_QSH
- /* change response if not using TLS_QSH */
- if (!ssl->options.haveQSH) {
- TLSX* ext = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID);
- if (ext)
- ext->resp = 0;
- }
- #endif
- #ifdef HAVE_EXTENDED_MASTER
- if (ssl->options.haveEMS && msgType == server_hello &&
- !IsAtLeastTLSv1_3(ssl->version)) {
- length += HELLO_EXT_SZ;
- }
- #endif
- if (TLSX_SupportExtensions(ssl)) {
- ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length);
- if (ret != 0)
- return ret;
- }
- /* All the response data is set at the ssl object only, so no ctx here. */
- if (length || msgType != server_hello)
- length += OPAQUE16_LEN; /* for total length storage. */
- *pLength += length;
- return ret;
- }
- /** Writes the server hello extensions into a buffer. */
- int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset)
- {
- int ret = 0;
- word16 offset = 0;
- if (TLSX_SupportExtensions(ssl) && output) {
- byte semaphore[SEMAPHORE_SIZE] = {0};
- switch (msgType) {
- #ifndef NO_WOLFSSL_SERVER
- case server_hello:
- PF_VALIDATE_RESPONSE(ssl, semaphore);
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore,
- TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #ifdef HAVE_SUPPORTED_CURVES
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
- else {
- #ifdef HAVE_SUPPORTED_CURVES
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- #endif
- #endif
- break;
- #ifdef WOLFSSL_TLS13
- case hello_retry_request:
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #ifdef HAVE_SUPPORTED_CURVES
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- /* Cookie is written below as last extension. */
- break;
- #endif
- #ifdef WOLFSSL_TLS13
- case encrypted_extensions:
- /* Send out all extension except those that are turned on. */
- #ifdef HAVE_ECC
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- #endif
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #ifdef HAVE_SESSION_TICKET
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
- #endif
- #ifdef HAVE_SUPPORTED_CURVES
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- #endif
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
- #endif
- #if defined(HAVE_SECURE_RENEGOTIATION)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
- #endif
- break;
- #ifdef WOLFSSL_EARLY_DATA
- case session_ticket:
- if (ssl->options.tls1_3) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- }
- break;
- #endif
- #endif
- #endif
- #ifdef WOLFSSL_TLS13
- #ifndef NO_CERTS
- case certificate:
- /* Don't send out any extension except those that are turned
- * off. */
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
- * TLSX_SERVER_CERTIFICATE_TYPE
- */
- break;
- #endif
- #endif
- }
- offset += OPAQUE16_LEN; /* extensions length */
- ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
- msgType, &offset);
- if (ret != 0)
- return ret;
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
- if (msgType == hello_retry_request) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
- ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
- msgType, &offset);
- if (ret != 0)
- return ret;
- }
- #endif
- #ifdef HAVE_EXTENDED_MASTER
- if (ssl->options.haveEMS && msgType == server_hello &&
- !IsAtLeastTLSv1_3(ssl->version)) {
- WOLFSSL_MSG("EMS extension to write");
- c16toa(HELLO_EXT_EXTMS, output + offset);
- offset += HELLO_EXT_TYPE_SZ;
- c16toa(0, output + offset);
- offset += HELLO_EXT_SZ_SZ;
- }
- #endif
- if (offset > OPAQUE16_LEN || msgType != server_hello)
- c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
- }
- if (pOffset)
- *pOffset += offset;
- return ret;
- }
- #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */
- #ifdef WOLFSSL_TLS13
- int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
- int* found)
- {
- int ret = 0;
- int offset = 0;
- *found = 0;
- while (offset < (int)length) {
- word16 type;
- word16 size;
- if (offset + (2 * OPAQUE16_LEN) > length) {
- ret = BUFFER_ERROR;
- break;
- }
- ato16(input + offset, &type);
- offset += HELLO_EXT_TYPE_SZ;
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN;
- if (offset + size > length) {
- ret = BUFFER_ERROR;
- break;
- }
- if (type == TLSX_SUPPORTED_VERSIONS) {
- *found = 1;
- WOLFSSL_MSG("Supported Versions extension received");
- ret = SV_PARSE(ssl, input + offset, size, msgType);
- break;
- }
- offset += size;
- }
- return ret;
- }
- #endif
- /** Parses a buffer of TLS extensions. */
- int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
- Suites *suites)
- {
- int ret = 0;
- word16 offset = 0;
- byte isRequest = (msgType == client_hello ||
- msgType == certificate_request);
- #ifdef HAVE_EXTENDED_MASTER
- byte pendingEMS = 0;
- #endif
- #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- int pskDone = 0;
- #endif
- if (!ssl || !input || (isRequest && !suites))
- return BAD_FUNC_ARG;
- while (ret == 0 && offset < length) {
- word16 type;
- word16 size;
- #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- if (msgType == client_hello && pskDone)
- return PSK_KEY_ERROR;
- #endif
- if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input + offset, &type);
- offset += HELLO_EXT_TYPE_SZ;
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN;
- if (offset + size > length)
- return BUFFER_ERROR;
- switch (type) {
- #ifdef HAVE_SNI
- case TLSX_SERVER_NAME:
- WOLFSSL_MSG("SNI extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SNI)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != server_hello &&
- msgType != encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- else if (!IsAtLeastTLSv1_3(ssl->version) &&
- msgType == encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = SNI_PARSE(ssl, input + offset, size, isRequest);
- break;
- #endif
- case TLSX_TRUSTED_CA_KEYS:
- WOLFSSL_MSG("Trusted CA extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_TRUSTED_CA)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = TCA_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_MAX_FRAGMENT_LENGTH:
- WOLFSSL_MSG("Max Fragment Length extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_MAX_FRAGMENT)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- else if (!IsAtLeastTLSv1_3(ssl->version) &&
- msgType == encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = MFL_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_TRUNCATED_HMAC:
- WOLFSSL_MSG("Truncated HMAC extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_TRUNCATED_HMAC)
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- ret = THM_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_SUPPORTED_GROUPS:
- WOLFSSL_MSG("Supported Groups extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != server_hello &&
- msgType != encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- else if (!IsAtLeastTLSv1_3(ssl->version) &&
- msgType == encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = EC_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_EC_POINT_FORMATS:
- WOLFSSL_MSG("Point Formats extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- ret = PF_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_STATUS_REQUEST:
- WOLFSSL_MSG("Certificate Status Request extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != certificate_request &&
- msgType != certificate) {
- break;
- }
- #endif
- ret = CSR_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_STATUS_REQUEST_V2:
- WOLFSSL_MSG("Certificate Status Request v2 extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != certificate_request &&
- msgType != certificate) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = CSR2_PARSE(ssl, input + offset, size, isRequest);
- break;
- #ifdef HAVE_EXTENDED_MASTER
- case HELLO_EXT_EXTMS:
- WOLFSSL_MSG("Extended Master Secret extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13)
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- if (size != 0)
- return BUFFER_ERROR;
- #ifndef NO_WOLFSSL_SERVER
- if (isRequest)
- ssl->options.haveEMS = 1;
- #endif
- pendingEMS = 1;
- break;
- #endif
- case TLSX_RENEGOTIATION_INFO:
- WOLFSSL_MSG("Secure Renegotiation extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SECURE_RENEGOTIATION)
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- ret = SCR_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_SESSION_TICKET:
- WOLFSSL_MSG("Session Ticket extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_QUANTUM_SAFE_HYBRID:
- WOLFSSL_MSG("Quantum-Safe-Hybrid extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_QSH)
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- ret = QSH_PARSE(ssl, input + offset, size, isRequest);
- break;
- case TLSX_APPLICATION_LAYER_PROTOCOL:
- WOLFSSL_MSG("ALPN extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ALPN)
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != server_hello &&
- msgType != encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- else if (!IsAtLeastTLSv1_3(ssl->version) &&
- msgType == encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = ALPN_PARSE(ssl, input + offset, size, isRequest);
- break;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS:
- WOLFSSL_MSG("Signature Algorithms extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- if (!IsAtLeastTLSv1_2(ssl))
- break;
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version) &&
- msgType != client_hello &&
- msgType != certificate_request) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = SA_PARSE(ssl, input + offset, size, isRequest, suites);
- break;
- #endif
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- case TLSX_ENCRYPT_THEN_MAC:
- WOLFSSL_MSG("Encrypt-Then-Mac extension received");
- /* Ignore for TLS 1.3+ */
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- ret = ETM_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif /* HAVE_ENCRYPT_THEN_MAC */
- #ifdef WOLFSSL_TLS13
- case TLSX_SUPPORTED_VERSIONS:
- WOLFSSL_MSG("Skipping Supported Versions - already processed");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- break;
- #ifdef WOLFSSL_SEND_HRR_COOKIE
- case TLSX_COOKIE:
- WOLFSSL_MSG("Cookie extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello &&
- msgType != hello_retry_request) {
- return EXT_NOT_ALLOWED;
- }
- ret = CKE_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- case TLSX_PRE_SHARED_KEY:
- WOLFSSL_MSG("Pre-Shared Key extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello && msgType != server_hello)
- return EXT_NOT_ALLOWED;
- ret = PSK_PARSE(ssl, input + offset, size, msgType);
- pskDone = 1;
- break;
- case TLSX_PSK_KEY_EXCHANGE_MODES:
- WOLFSSL_MSG("PSK Key Exchange Modes extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello)
- return EXT_NOT_ALLOWED;
- ret = PKM_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- case TLSX_EARLY_DATA:
- WOLFSSL_MSG("Early Data extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello && msgType != session_ticket &&
- msgType != encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
- if (!IsAtLeastTLSv1_3(ssl->version) &&
- (msgType == session_ticket ||
- msgType == encrypted_extensions)) {
- return EXT_NOT_ALLOWED;
- }
- ret = EDI_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- case TLSX_POST_HANDSHAKE_AUTH:
- WOLFSSL_MSG("Post Handshake Authentication extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello)
- return EXT_NOT_ALLOWED;
- ret = PHA_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS_CERT:
- WOLFSSL_MSG("Signature Algorithms extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello &&
- msgType != certificate_request) {
- return EXT_NOT_ALLOWED;
- }
- if (!IsAtLeastTLSv1_3(ssl->version) &&
- msgType == certificate_request) {
- return EXT_NOT_ALLOWED;
- }
- ret = SAC_PARSE(ssl, input + offset, size, isRequest);
- break;
- #endif
- case TLSX_KEY_SHARE:
- WOLFSSL_MSG("Key Share extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #ifdef HAVE_SUPPORTED_CURVES
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello && msgType != server_hello &&
- msgType != hello_retry_request) {
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = KS_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
- default:
- WOLFSSL_MSG("Unknown TLS extension type");
- }
- /* offset should be updated here! */
- offset += size;
- }
- #ifdef HAVE_EXTENDED_MASTER
- if (!isRequest && ssl->options.haveEMS && !pendingEMS)
- ssl->options.haveEMS = 0;
- #endif
- if (ret == 0)
- ret = SNI_VERIFY_PARSE(ssl, isRequest);
- if (ret == 0)
- ret = TCA_VERIFY_PARSE(ssl, isRequest);
- return ret;
- }
- /* undefining semaphore macros */
- #undef IS_OFF
- #undef TURN_ON
- #undef SEMAPHORE_SIZE
- #endif /* HAVE_TLS_EXTENSIONS */
- #ifndef NO_WOLFSSL_CLIENT
- WOLFSSL_METHOD* wolfTLS_client_method(void)
- {
- return wolfTLS_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLS_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLS_client_method_ex");
- if (method) {
- #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());
- #elif defined(WOLFSSL_ALLOW_TLSV10)
- InitSSL_Method(method, MakeTLSv1());
- #else
- #error No TLS version enabled!
- #endif
- method->downgrade = 1;
- method->side = WOLFSSL_CLIENT_END;
- }
- return method;
- }
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_TLSV10
- WOLFSSL_METHOD* wolfTLSv1_client_method(void)
- {
- return wolfTLSv1_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_client_method_ex");
- if (method)
- InitSSL_Method(method, MakeTLSv1());
- return method;
- }
- #endif /* WOLFSSL_ALLOW_TLSV10 */
- WOLFSSL_METHOD* wolfTLSv1_1_client_method(void)
- {
- return wolfTLSv1_1_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_1_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_1_client_method_ex");
- if (method)
- InitSSL_Method(method, MakeTLSv1_1());
- return method;
- }
- #endif /* !NO_OLD_TLS */
- #ifndef WOLFSSL_NO_TLS12
- WOLFSSL_ABI
- WOLFSSL_METHOD* wolfTLSv1_2_client_method(void)
- {
- return wolfTLSv1_2_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_2_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_2_client_method_ex");
- if (method)
- InitSSL_Method(method, MakeTLSv1_2());
- return method;
- }
- #endif /* WOLFSSL_NO_TLS12 */
- #ifdef WOLFSSL_TLS13
- /* The TLS v1.3 client method data.
- *
- * returns the method data for a TLS v1.3 client.
- */
- WOLFSSL_ABI
- WOLFSSL_METHOD* wolfTLSv1_3_client_method(void)
- {
- return wolfTLSv1_3_client_method_ex(NULL);
- }
- /* The TLS v1.3 client method data.
- *
- * heap The heap used for allocation.
- * returns the method data for a TLS v1.3 client.
- */
- WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method = (WOLFSSL_METHOD*)
- XMALLOC(sizeof(WOLFSSL_METHOD), heap,
- DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_3_client_method_ex");
- if (method)
- InitSSL_Method(method, MakeTLSv1_3());
- return method;
- }
- #endif /* WOLFSSL_TLS13 */
- #ifdef WOLFSSL_DTLS
- WOLFSSL_METHOD* wolfDTLS_client_method(void)
- {
- return wolfDTLS_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLS_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("DTLS_client_method_ex");
- if (method) {
- #if !defined(WOLFSSL_NO_TLS12)
- InitSSL_Method(method, MakeDTLSv1_2());
- #elif !defined(NO_OLD_TLS)
- InitSSL_Method(method, MakeDTLSv1());
- #else
- #error No DTLS version enabled!
- #endif
- method->downgrade = 1;
- method->side = WOLFSSL_CLIENT_END;
- }
- return method;
- }
- #ifndef NO_OLD_TLS
- WOLFSSL_METHOD* wolfDTLSv1_client_method(void)
- {
- return wolfDTLSv1_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("DTLSv1_client_method_ex");
- if (method)
- InitSSL_Method(method, MakeDTLSv1());
- return method;
- }
- #endif /* NO_OLD_TLS */
- #ifndef WOLFSSL_NO_TLS12
- WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void)
- {
- return wolfDTLSv1_2_client_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("DTLSv1_2_client_method_ex");
- if (method)
- InitSSL_Method(method, MakeDTLSv1_2());
- (void)heap;
- return method;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- #endif /* WOLFSSL_DTLS */
- #endif /* NO_WOLFSSL_CLIENT */
- /* EITHER SIDE METHODS */
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_TLSV10
- /* Gets a WOLFSL_METHOD type that is not set as client or server
- *
- * Returns a pointer to a WOLFSSL_METHOD struct
- */
- WOLFSSL_METHOD* wolfTLSv1_method(void)
- {
- return wolfTLSv1_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m;
- WOLFSSL_ENTER("TLSv1_method");
- #ifndef NO_WOLFSSL_CLIENT
- m = wolfTLSv1_client_method_ex(heap);
- #else
- m = wolfTLSv1_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #endif /* WOLFSSL_ALLOW_TLSV10 */
- /* Gets a WOLFSL_METHOD type that is not set as client or server
- *
- * Returns a pointer to a WOLFSSL_METHOD struct
- */
- WOLFSSL_METHOD* wolfTLSv1_1_method(void)
- {
- return wolfTLSv1_1_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_1_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m;
- WOLFSSL_ENTER("TLSv1_1_method");
- #ifndef NO_WOLFSSL_CLIENT
- m = wolfTLSv1_1_client_method_ex(heap);
- #else
- m = wolfTLSv1_1_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #endif /* !NO_OLD_TLS */
- #ifndef WOLFSSL_NO_TLS12
- /* Gets a WOLFSL_METHOD type that is not set as client or server
- *
- * Returns a pointer to a WOLFSSL_METHOD struct
- */
- WOLFSSL_METHOD* wolfTLSv1_2_method(void)
- {
- return wolfTLSv1_2_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_2_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m;
- WOLFSSL_ENTER("TLSv1_2_method");
- #ifndef NO_WOLFSSL_CLIENT
- m = wolfTLSv1_2_client_method_ex(heap);
- #else
- m = wolfTLSv1_2_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- #ifdef WOLFSSL_TLS13
- /* Gets a WOLFSL_METHOD type that is not set as client or server
- *
- * Returns a pointer to a WOLFSSL_METHOD struct
- */
- WOLFSSL_METHOD* wolfTLSv1_3_method(void)
- {
- return wolfTLSv1_3_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_3_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m;
- WOLFSSL_ENTER("TLSv1_3_method");
- #ifndef NO_WOLFSSL_CLIENT
- m = wolfTLSv1_3_client_method_ex(heap);
- #else
- m = wolfTLSv1_3_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #endif /* WOLFSSL_TLS13 */
- #ifdef WOLFSSL_DTLS
- WOLFSSL_METHOD* wolfDTLS_method(void)
- {
- return wolfDTLS_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLS_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m;
- WOLFSSL_ENTER("DTLS_method_ex");
- #ifndef NO_WOLFSSL_CLIENT
- m = wolfDTLS_client_method_ex(heap);
- #else
- m = wolfDTLS_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #ifndef NO_OLD_TLS
- WOLFSSL_METHOD* wolfDTLSv1_method(void)
- {
- return wolfDTLSv1_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLSv1_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m;
- WOLFSSL_ENTER("DTLSv1_method_ex");
- #ifndef NO_WOLFSSL_CLIENT
- m = wolfDTLSv1_client_method_ex(heap);
- #else
- m = wolfDTLSv1_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #endif /* !NO_OLD_TLS */
- #ifndef WOLFSSL_NO_TLS12
- WOLFSSL_METHOD* wolfDTLSv1_2_method(void)
- {
- return wolfDTLSv1_2_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLSv1_2_method_ex(void* heap)
- {
- WOLFSSL_METHOD* m;
- WOLFSSL_ENTER("DTLSv1_2_method");
- #ifndef NO_WOLFSSL_CLIENT
- m = wolfDTLSv1_2_client_method_ex(heap);
- #else
- m = wolfDTLSv1_2_server_method_ex(heap);
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
- return m;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- #endif /* WOLFSSL_DTLS */
- #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
- #ifndef NO_WOLFSSL_SERVER
- WOLFSSL_METHOD* wolfTLS_server_method(void)
- {
- return wolfTLS_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLS_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLS_server_method_ex");
- if (method) {
- #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());
- #elif defined(WOLFSSL_ALLOW_TLSV10)
- InitSSL_Method(method, MakeTLSv1());
- #else
- #error No TLS version enabled!
- #endif
- method->downgrade = 1;
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_TLSV10
- WOLFSSL_METHOD* wolfTLSv1_server_method(void)
- {
- return wolfTLSv1_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_server_method_ex");
- if (method) {
- InitSSL_Method(method, MakeTLSv1());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #endif /* WOLFSSL_ALLOW_TLSV10 */
- WOLFSSL_METHOD* wolfTLSv1_1_server_method(void)
- {
- return wolfTLSv1_1_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_1_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_1_server_method_ex");
- if (method) {
- InitSSL_Method(method, MakeTLSv1_1());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #endif /* !NO_OLD_TLS */
- #ifndef WOLFSSL_NO_TLS12
- WOLFSSL_ABI
- WOLFSSL_METHOD* wolfTLSv1_2_server_method(void)
- {
- return wolfTLSv1_2_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfTLSv1_2_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_2_server_method_ex");
- if (method) {
- InitSSL_Method(method, MakeTLSv1_2());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- #ifdef WOLFSSL_TLS13
- /* The TLS v1.3 server method data.
- *
- * returns the method data for a TLS v1.3 server.
- */
- WOLFSSL_ABI
- WOLFSSL_METHOD* wolfTLSv1_3_server_method(void)
- {
- return wolfTLSv1_3_server_method_ex(NULL);
- }
- /* The TLS v1.3 server method data.
- *
- * heap The heap used for allocation.
- * returns the method data for a TLS v1.3 server.
- */
- WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("TLSv1_3_server_method_ex");
- if (method) {
- InitSSL_Method(method, MakeTLSv1_3());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #endif /* WOLFSSL_TLS13 */
- #ifdef WOLFSSL_DTLS
- WOLFSSL_METHOD* wolfDTLS_server_method(void)
- {
- return wolfDTLS_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLS_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("DTLS_server_method_ex");
- if (method) {
- #if !defined(WOLFSSL_NO_TLS12)
- InitSSL_Method(method, MakeDTLSv1_2());
- #elif !defined(NO_OLD_TLS)
- InitSSL_Method(method, MakeDTLSv1());
- #else
- #error No DTLS version enabled!
- #endif
- method->downgrade = 1;
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #ifndef NO_OLD_TLS
- WOLFSSL_METHOD* wolfDTLSv1_server_method(void)
- {
- return wolfDTLSv1_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- (void)heap;
- WOLFSSL_ENTER("DTLSv1_server_method_ex");
- if (method) {
- InitSSL_Method(method, MakeDTLSv1());
- method->side = WOLFSSL_SERVER_END;
- }
- return method;
- }
- #endif /* !NO_OLD_TLS */
- #ifndef WOLFSSL_NO_TLS12
- WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void)
- {
- return wolfDTLSv1_2_server_method_ex(NULL);
- }
- WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
- heap, DYNAMIC_TYPE_METHOD);
- WOLFSSL_ENTER("DTLSv1_2_server_method_ex");
- (void)heap;
- if (method) {
- InitSSL_Method(method, MakeDTLSv1_2());
- method->side = WOLFSSL_SERVER_END;
- }
- (void)heap;
- return method;
- }
- #endif /* !WOLFSSL_NO_TLS12 */
- #endif /* WOLFSSL_DTLS */
- #endif /* NO_WOLFSSL_SERVER */
- #endif /* NO_TLS */
- #endif /* WOLFCRYPT_ONLY */
|