1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248 |
- /* tls.c
- *
- * Copyright (C) 2006-2023 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/hash.h>
- #include <wolfssl/wolfcrypt/hmac.h>
- #include <wolfssl/wolfcrypt/kdf.h>
- #ifdef NO_INLINE
- #include <wolfssl/wolfcrypt/misc.h>
- #else
- #define WOLFSSL_MISC_INCLUDED
- #include <wolfcrypt/src/misc.c>
- #endif
- #ifdef HAVE_CURVE25519
- #include <wolfssl/wolfcrypt/curve25519.h>
- #endif
- #ifdef HAVE_CURVE448
- #include <wolfssl/wolfcrypt/curve448.h>
- #endif
- #ifdef HAVE_PQC
- #include <wolfssl/wolfcrypt/kyber.h>
- #ifdef WOLFSSL_WC_KYBER
- #include <wolfssl/wolfcrypt/wc_kyber.h>
- #elif defined(HAVE_LIBOQS) || defined(HAVE_PQM4)
- #include <wolfssl/wolfcrypt/ext_kyber.h>
- #endif
- #endif
- #if defined(WOLFSSL_RENESAS_TSIP_TLS)
- #include <wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h>
- #endif
- #include <wolfssl/wolfcrypt/hpke.h>
- #ifndef NO_TLS
- #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
- static int TLSX_KeyShare_IsSupported(int namedGroup);
- static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap);
- #endif
- #ifdef HAVE_SUPPORTED_CURVES
- static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions);
- #endif
- /* 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
- #ifndef WOLFSSL_NO_TLS12
- #ifdef WOLFSSL_SHA384
- #define HSHASH_SZ WC_SHA384_DIGEST_SIZE
- #else
- #define HSHASH_SZ FINISHED_SZ
- #endif
- 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
- #ifdef WOLFSSL_SM3
- if (ssl->specs.mac_algorithm == sm3_mac) {
- ret |= wc_Sm3GetHash(&ssl->hsHashes->hashSm3, hash);
- hashSz = WC_SM3_DIGEST_SIZE;
- }
- #endif
- }
- *hashLen = hashSz;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("TLS handshake hash", hash, hashSz);
- #endif
- if (ret != 0) {
- ret = BUILD_MSG_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- return ret;
- }
- int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
- {
- int ret;
- const byte* side = NULL;
- word32 hashSz = HSHASH_SZ;
- #if !defined(WOLFSSL_ASYNC_CRYPT) || defined(WC_ASYNC_NO_HASH)
- byte handshake_hash[HSHASH_SZ];
- #else
- WC_DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap);
- if (handshake_hash == NULL)
- return MEMORY_E;
- #endif
- ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
- if (ret == 0) {
- if (XSTRNCMP((const char*)sender, (const char*)kTlsClientStr,
- SIZEOF_SENDER) == 0) {
- side = kTlsClientFinStr;
- }
- else if (XSTRNCMP((const char*)sender, (const char*)kTlsServerStr,
- SIZEOF_SENDER) == 0) {
- side = kTlsServerFinStr;
- }
- else {
- ret = BAD_FUNC_ARG;
- WOLFSSL_MSG("Unexpected sender value");
- }
- }
- if (ret == 0) {
- #ifdef WOLFSSL_HAVE_PRF
- #if !defined(NO_CERTS) && defined(HAVE_PK_CALLBACKS)
- if (ssl->ctx->TlsFinishedCb) {
- void* ctx = wolfSSL_GetTlsFinishedCtx(ssl);
- ret = ssl->ctx->TlsFinishedCb(ssl, side, handshake_hash, hashSz,
- (byte*)hashes, ctx);
- }
- if (!ssl->ctx->TlsFinishedCb || ret == PROTOCOLCB_UNAVAILABLE)
- #endif
- {
- PRIVATE_KEY_UNLOCK();
- 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);
- PRIVATE_KEY_LOCK();
- }
- ForceZero(handshake_hash, hashSz);
- #else
- /* Pseudo random function must be enabled in the configuration. */
- ret = PRF_MISSING;
- WOLFSSL_ERROR_VERBOSE(ret);
- WOLFSSL_MSG("Pseudo-random function is not enabled");
- (void)side;
- (void)hashes;
- #endif
- }
- #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
- WC_FREE_VAR(handshake_hash, ssl->heap);
- #elif defined(WOLFSSL_CHECK_MEM_ZERO)
- wc_MemZero_Check(handshake_hash, HSHASH_SZ);
- #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)
- WC_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
- PRIVATE_KEY_UNLOCK();
- 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);
- PRIVATE_KEY_LOCK();
- #else
- /* Pseudo random function must be enabled in the configuration. */
- ret = PRF_MISSING;
- WOLFSSL_ERROR_VERBOSE(ret);
- 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)
- WC_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(NO_CERTS) && defined(HAVE_PK_CALLBACKS)
- ret = PROTOCOLCB_UNAVAILABLE;
- if (ssl->ctx->GenSessionKeyCb) {
- void* ctx = wolfSSL_GetGenSessionKeyCtx(ssl);
- ret = ssl->ctx->GenSessionKeyCb(ssl, ctx);
- }
- if (!ssl->ctx->GenSessionKeyCb || ret == PROTOCOLCB_UNAVAILABLE)
- #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);
- #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)
- byte seed[SEED_LEN];
- #else
- WC_DECLARE_VAR(seed, byte, SEED_LEN, heap);
- if (seed == NULL)
- return MEMORY_E;
- #endif
- XMEMCPY(seed, cr, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, sr, RAN_LEN);
- #ifdef WOLFSSL_HAVE_PRF
- PRIVATE_KEY_UNLOCK();
- ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ,
- seed, SEED_LEN, tls1_2, hash_type, heap, devId);
- PRIVATE_KEY_LOCK();
- #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)
- WC_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
- PRIVATE_KEY_UNLOCK();
- ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ,
- sHash, sHashLen, tls1_2, hash_type, heap, devId);
- PRIVATE_KEY_LOCK();
- #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;
- #if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_KEYLOGFILE)
- /* If this is called from a sniffer session with keylog file support, obtain
- * the master secret from the callback */
- if (ssl->snifferSecretCb != NULL) {
- ret = ssl->snifferSecretCb(ssl->arrays->clientRandom,
- SNIFFER_SECRET_TLS12_MASTER_SECRET,
- ssl->arrays->masterSecret);
- if (ret != 0) {
- return ret;
- }
- ret = DeriveTlsKeys(ssl);
- return ret;
- }
- #endif /* WOLFSSL_SNIFFER && WOLFSSL_SNIFFER_KEYLOGFILE */
- #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);
- ForceZero(handshake_hash, hashSz);
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST);
- #elif defined(WOLFSSL_CHECK_MEM_ZERO)
- wc_MemZero_Check(handshake_hash, HSHASH_SZ);
- #endif
- }
- else
- #endif /* HAVE_EXTENDED_MASTER */
- {
- #if !defined(NO_CERTS) && defined(HAVE_PK_CALLBACKS)
- ret = PROTOCOLCB_UNAVAILABLE;
- if (ssl->ctx->GenMasterCb) {
- void* ctx = wolfSSL_GetGenMasterSecretCtx(ssl);
- ret = ssl->ctx->GenMasterCb(ssl, ctx);
- }
- if (!ssl->ctx->GenMasterCb || ret == PROTOCOLCB_UNAVAILABLE)
- #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
- PRIVATE_KEY_UNLOCK();
- 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);
- PRIVATE_KEY_LOCK();
- #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;
- }
- int wolfSSL_GetHmacType_ex(CipherSpecs* specs)
- {
- if (specs == NULL)
- return BAD_FUNC_ARG;
- switch (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
- #ifdef WOLFSSL_SM3
- case sm3_mac:
- {
- return WC_SM3;
- }
- #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;
- }
- }
- }
- /* return HMAC digest type in wolfSSL format */
- int wolfSSL_GetHmacType(WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return wolfSSL_GetHmacType_ex(&ssl->specs);
- }
- 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 */
- #ifdef WOLFSSL_SM3
- case WC_SM3:
- ret = wc_Sm3Update(&hmac->hash.sm3, data, sz);
- break;
- #endif /* WOLFSSL_SM3 */
- default:
- break;
- }
- 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 */
- #ifdef WOLFSSL_SM3
- case WC_SM3:
- ret = wc_Sm3FinalRaw(&hmac->hash.sm3, hash);
- break;
- #endif /* WOLFSSL_SM3 */
- default:
- break;
- }
- 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, int macLen, byte* header)
- {
- byte lenBytes[8];
- int i, j;
- unsigned int k;
- int blockBits, blockMask;
- int lastBlockLen, extraLen, eocIndex;
- int blocks, safeBlocks, lenBlock, eocBlock;
- unsigned 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;
- 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;
- 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;
- 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;
- padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA512 */
- #ifdef WOLFSSL_SM3
- case WC_SM3:
- blockSz = WC_SM3_BLOCK_SIZE;
- blockBits = 6;
- padSz = WC_SM3_BLOCK_SIZE - WC_SM3_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SM3 */
- 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++) {
- 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];
- k++;
- 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 = 0;
- word32 msgSz, blockSz, macSz, padSz, maxSz, realSz;
- word32 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_BLAKE2 */
- #ifdef WOLFSSL_SM3
- case WC_SM3:
- blockSz = WC_SM3_BLOCK_SIZE;
- blockBits = 6;
- macSz = WC_SM3_DIGEST_SIZE;
- padSz = WC_SM3_BLOCK_SIZE - WC_SM3_PAD_SIZE + 1;
- break;
- #endif
- default:
- WOLFSSL_MSG("ERROR: Hmac_UpdateFinal failed, no hmac->macType");
- 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) ? 1 : 0);
- /* 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. */
- word32 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);
- 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, hashSz, 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 72 flags. Increase as needed. */
- #define SEMAPHORE_SIZE 9
- /**
- * 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.
- *
- * Update TLSX_Parse for duplicate detection if more added above 62.
- */
- static WC_INLINE word16 TLSX_ToSemaphore(word16 type)
- {
- switch (type) {
- case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */
- return 63;
- #ifdef WOLFSSL_QUIC
- case TLSX_KEY_QUIC_TP_PARAMS_DRAFT: /* 0xffa5 */
- return 64;
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- case TLSX_ECH: /* 0xfe0d */
- return 65;
- #endif
- 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, const void* data, void* heap)
- {
- TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX);
- (void)heap;
- if (extension) {
- extension->type = type;
- extension->data = (void*)data;
- extension->resp = 0;
- extension->next = NULL;
- }
- return extension;
- }
- /**
- * Creates a new extension and appends it to the provided list.
- * Checks for duplicate extensions, keeps the newest.
- */
- int TLSX_Append(TLSX** list, TLSX_Type type, const void* data, void* heap)
- {
- TLSX* extension = TLSX_New(type, data, heap);
- TLSX* cur;
- TLSX** prevNext = list;
- if (extension == NULL)
- return MEMORY_E;
- for (cur = *list; cur != NULL;) {
- if (cur->type == type) {
- *prevNext = cur->next;
- cur->next = NULL;
- TLSX_FreeAll(cur, heap);
- cur = *prevNext;
- }
- else {
- prevNext = &cur->next;
- cur = cur->next;
- }
- }
- /* Append the extension to the list */
- *prevNext = extension;
- return 0;
- }
- /**
- * Creates a new extension and pushes it to the provided list.
- * Checks for duplicate extensions, keeps the newest.
- */
- int TLSX_Push(TLSX** list, TLSX_Type type, const 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;
- }
- #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);
- WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_EXTENSION);
- return UNSUPPORTED_EXTENSION;
- }
- #else
- #define TLSX_CheckUnsupportedExtension(ssl, type) 0
- #define TLSX_HandleUnsupportedExtension(ssl) 0
- #endif
- #if !defined(NO_WOLFSSL_SERVER) || defined(WOLFSSL_TLS13)
- void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type);
- /** Mark an extension to be sent back to the client. */
- void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type)
- {
- TLSX *extension = TLSX_Find(ssl->extensions, type);
- if (extension)
- extension->resp = 1;
- }
- #endif
- /******************************************************************************/
- /* 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;
- }
- static int ALPN_find_match(WOLFSSL *ssl, TLSX **pextension,
- const byte **psel, byte *psel_len,
- const byte *alpn_val, word16 alpn_val_len)
- {
- TLSX *extension;
- ALPN *alpn, *list;
- const byte *sel = NULL, *s;
- byte sel_len = 0, wlen;
- extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
- if (extension == NULL)
- extension = TLSX_Find(ssl->ctx->extensions,
- TLSX_APPLICATION_LAYER_PROTOCOL);
- /* No ALPN configured here */
- if (extension == NULL || extension->data == NULL) {
- *pextension = NULL;
- *psel = NULL;
- *psel_len = 0;
- return 0;
- }
- list = (ALPN*)extension->data;
- for (s = alpn_val;
- (s - alpn_val) < alpn_val_len;
- s += wlen) {
- wlen = *s++; /* bounds already checked on save */
- alpn = TLSX_ALPN_Find(list, (char*)s, wlen);
- if (alpn != NULL) {
- WOLFSSL_MSG("ALPN protocol match");
- sel = s,
- sel_len = wlen;
- break;
- }
- }
- if (sel == NULL) {
- 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");
- }
- else {
- SendAlert(ssl, alert_fatal, no_application_protocol);
- WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E);
- return UNKNOWN_ALPN_PROTOCOL_NAME_E;
- }
- }
- *pextension = extension;
- *psel = sel;
- *psel_len = sel_len;
- return 0;
- }
- int ALPN_Select(WOLFSSL *ssl)
- {
- TLSX *extension;
- const byte *sel = NULL;
- byte sel_len = 0;
- int r = 0;
- WOLFSSL_ENTER("ALPN_Select");
- if (ssl->alpn_peer_requested == NULL)
- return 0;
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- if (ssl->alpnSelect != NULL && ssl->options.side == WOLFSSL_SERVER_END) {
- r = ssl->alpnSelect(ssl, &sel, &sel_len, ssl->alpn_peer_requested,
- ssl->alpn_peer_requested_length, ssl->alpnSelectArg);
- switch (r) {
- case SSL_TLSEXT_ERR_OK:
- WOLFSSL_MSG("ALPN protocol match");
- break;
- case SSL_TLSEXT_ERR_NOACK:
- WOLFSSL_MSG("ALPN cb no match but not fatal");
- sel = NULL;
- sel_len = 0;
- break;
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- default:
- WOLFSSL_MSG("ALPN cb no match and fatal");
- SendAlert(ssl, alert_fatal, no_application_protocol);
- WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E);
- return UNKNOWN_ALPN_PROTOCOL_NAME_E;
- }
- }
- else
- #endif
- {
- r = ALPN_find_match(ssl, &extension, &sel, &sel_len,
- ssl->alpn_peer_requested,
- ssl->alpn_peer_requested_length);
- if (r != 0)
- return r;
- }
- if (sel != NULL) {
- /* set the matching negotiated protocol */
- r = TLSX_SetALPN(&ssl->extensions, sel, sel_len, ssl->heap);
- if (r != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("TLSX_SetALPN failed");
- return BUFFER_ERROR;
- }
- /* reply to ALPN extension sent from peer */
- #ifndef NO_WOLFSSL_SERVER
- TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL);
- #endif
- }
- return 0;
- }
- /** Parses a buffer of ALPN extensions and set the first one matching
- * client and server requirements */
- static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length,
- byte isRequest)
- {
- word16 size = 0, offset = 0, wlen;
- int r = BUFFER_ERROR;
- const byte *s;
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
- ato16(input, &size);
- offset += OPAQUE16_LEN;
- /* validating alpn list length */
- if (size == 0 || length != OPAQUE16_LEN + size)
- return BUFFER_ERROR;
- /* validating length of entries before accepting */
- for (s = input + offset; (s - input) < size; s += wlen) {
- wlen = *s++;
- if (wlen == 0 || (s + wlen - input) > length)
- return BUFFER_ERROR;
- }
- if (isRequest) {
- /* keep the list sent by peer, if this is from a request. We
- * use it later in ALPN_Select() for evaluation. */
- if (ssl->alpn_peer_requested != NULL) {
- XFREE(ssl->alpn_peer_requested, ssl->heap, DYNAMIC_TYPE_ALPN);
- ssl->alpn_peer_requested_length = 0;
- }
- ssl->alpn_peer_requested = (byte *)XMALLOC(size, ssl->heap,
- DYNAMIC_TYPE_ALPN);
- if (ssl->alpn_peer_requested == NULL) {
- return MEMORY_ERROR;
- }
- ssl->alpn_peer_requested_length = size;
- XMEMCPY(ssl->alpn_peer_requested, (char*)input + offset, size);
- }
- else {
- /* a response, we should find the value in our config */
- const byte *sel = NULL;
- byte sel_len = 0;
- TLSX *extension = NULL;
- r = ALPN_find_match(ssl, &extension, &sel, &sel_len, input + offset, size);
- if (r != 0)
- return r;
- if (sel != NULL) {
- /* set the matching negotiated protocol */
- r = TLSX_SetALPN(&ssl->extensions, sel, sel_len, ssl->heap);
- if (r != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("TLSX_SetALPN failed");
- return BUFFER_ERROR;
- }
- }
- /* If we had nothing configured, the response is unexpected */
- else if (extension == NULL) {
- r = TLSX_HandleUnsupportedExtension(ssl);
- if (r != 0)
- return r;
- }
- }
- 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;
- *data = NULL;
- *dataSz = 0;
- extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
- if (extension == NULL) {
- WOLFSSL_MSG("TLS extension not found");
- WOLFSSL_ERROR_VERBOSE(WOLFSSL_ALPN_NOT_FOUND);
- return WOLFSSL_ALPN_NOT_FOUND;
- }
- alpn = (ALPN *)extension->data;
- if (alpn == NULL) {
- WOLFSSL_MSG("ALPN extension not found");
- WOLFSSL_ERROR_VERBOSE(WOLFSSL_FATAL_ERROR);
- 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");
- WOLFSSL_ERROR_VERBOSE(WOLFSSL_FATAL_ERROR);
- return WOLFSSL_FATAL_ERROR;
- }
- /* continue without negotiated protocol */
- WOLFSSL_MSG("No protocol match with peer -> Continue");
- WOLFSSL_ERROR_VERBOSE(WOLFSSL_ALPN_NOT_FOUND);
- return WOLFSSL_ALPN_NOT_FOUND;
- }
- if (alpn->next != NULL) {
- WOLFSSL_MSG("Only one protocol name must be accepted");
- WOLFSSL_ERROR_VERBOSE(WOLFSSL_FATAL_ERROR);
- 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) WC_DO_NOTHING
- #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;
- }
- #if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER))
- /** 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;
- }
- #endif
- /** 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, const byte* input, word16 length,
- byte isRequest)
- {
- #ifndef NO_WOLFSSL_SERVER
- word16 size = 0;
- word16 offset = 0;
- int cacheOnly = 0;
- SNI *sni = NULL;
- byte type;
- byte matched;
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- WOLFSSL_ECH* ech = NULL;
- WOLFSSL_EchConfig* workingConfig;
- TLSX* echX;
- #endif
- #endif /* !NO_WOLFSSL_SERVER */
- 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) {
- /* 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.
- */
- #ifdef WOLFSSL_ALWAYS_KEEP_SNI
- cacheOnly = 1;
- #endif
- if (ssl->ctx->sniRecvCb) {
- cacheOnly = 1;
- }
- if (cacheOnly) {
- WOLFSSL_MSG("Forcing SSL object to store SNI parameter");
- }
- else {
- /* Skipping, SNI not enabled at server side. */
- return 0;
- }
- }
- 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 defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- echX = TLSX_Find(ssl->extensions, TLSX_ECH);
- if (echX != NULL)
- ech = (WOLFSSL_ECH*)(echX->data);
- if (!matched && ech != NULL) {
- workingConfig = ech->echConfig;
- while (workingConfig != NULL) {
- matched = XSTRLEN(workingConfig->publicName) == size &&
- XSTRNCMP(workingConfig->publicName,
- (const char*)input + offset, size) == 0;
- if (matched)
- break;
- workingConfig = workingConfig->next;
- }
- }
- #endif
- if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) {
- int matchStat;
- 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);
- WOLFSSL_ERROR_VERBOSE(UNKNOWN_SNI_HOST_NAME_E);
- return UNKNOWN_SNI_HOST_NAME_E;
- }
- #else
- (void)input;
- #endif /* !NO_WOLFSSL_SERVER */
- #if defined(NO_WOLFSSL_CLIENT) && defined(NO_WOLFSSL_SERVER)
- (void)length;
- #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);
- WOLFSSL_ERROR_VERBOSE(SNI_ABSENT_ERROR);
- 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);
- WOLFSSL_ERROR_VERBOSE(SNI_ABSENT_ERROR);
- 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;
- WOLFSSL_ERROR_VERBOSE(SNI_UNSUPPORTED);
- return SNI_UNSUPPORTED;
- }
- return BUFFER_ERROR;
- }
- if (clientHello[offset++] != SSLv3_MAJOR)
- return BUFFER_ERROR;
- if (clientHello[offset++] < TLSv1_MINOR) {
- WOLFSSL_ERROR_VERBOSE(SNI_UNSUPPORTED);
- 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) WC_DO_NOTHING
- #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:
- WOLFSSL_ERROR_VERBOSE(TCA_INVALID_ID_TYPE);
- 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);
- WOLFSSL_ERROR_VERBOSE(TCA_ABSENT_ERROR);
- 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) WC_DO_NOTHING
- #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, const 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);
- WOLFSSL_ERROR_VERBOSE(UNKNOWN_MAX_FRAG_LEN_E);
- 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) WC_DO_NOTHING
- #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, const 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;
- }
- #ifdef WOLFSSL_TLS13
- if (csr->response.buffer != NULL) {
- XFREE(csr->response.buffer, csr->ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- 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, const 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 = 0;
- #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 == 0 ? -1 : 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;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- 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 = (byte*)XMALLOC(resp_length, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (csr->response.buffer == NULL)
- ret = MEMORY_ERROR;
- }
- if (ret == 0) {
- XMEMCPY(csr->response.buffer, input + offset, resp_length);
- 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_CM(ssl) == NULL || !SSL_CM(ssl)->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 == 0 ? -1 : ret; /* throw error */
- #if defined(WOLFSSL_TLS13)
- if (ssl->options.tls1_3) {
- if (ssl->buffers.certificate == NULL) {
- WOLFSSL_MSG("Certificate buffer not set!");
- return BUFFER_ERROR;
- }
- 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_CM(ssl));
- if (ret != 0 ) {
- FreeDecodedCert(cert);
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- return ret;
- }
- ret = TLSX_CSR_InitRequest(ssl->extensions, cert, ssl->heap);
- if (ret != 0 ) {
- FreeDecodedCert(cert);
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- return ret;
- }
- FreeDecodedCert(cert);
- 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;
- }
- }
- 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_CM(ssl)->ocspEnabled) {
- csr->request.ocsp.ssl = ssl;
- return CheckOcspRequest(SSL_CM(ssl)->ocsp,
- &csr->request.ocsp, NULL, NULL);
- }
- else {
- WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL);
- 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) WC_DO_NOTHING
- #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, const 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_CM(ssl) == NULL
- || !SSL_CM(ssl)->ocspStaplingEnabled)
- continue;
- break;
- default:
- /* unknown status type, skipping! */
- offset += request_length;
- continue;
- }
- /* if using status_request and already sending it, remove it
- * and prefer to use the v2 version */
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- if (ssl->status_request) {
- ssl->status_request = 0;
- TLSX_Remove(&ssl->extensions, TLSX_STATUS_REQUEST, ssl->heap);
- }
- #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;
- }
- }
- }
- 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_CM(ssl)->ocspEnabled) {
- csr2->request.ocsp[0].ssl = ssl;
- return CheckOcspRequest(SSL_CM(ssl)->ocsp,
- &csr2->request.ocsp[0], NULL, NULL);
- }
- else {
- WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL);
- 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) WC_DO_NOTHING
- #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) && !defined(HAVE_PQC)
- #error Elliptic Curves Extension requires Elliptic Curve Cryptography or liboqs groups. \
- Use --enable-ecc and/or --enable-liboqs in the configure script or \
- define HAVE_ECC. Alternatively use FFDHE for DH cipher suites.
- #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)
- #if defined(HAVE_FFDHE) && (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
- defined(HAVE_CURVE448))
- static void TLSX_SupportedCurve_ValidateRequest(const WOLFSSL* ssl,
- const byte* semaphore)
- {
- /* If all pre-defined parameter types for key exchange are supported then
- * always send SupportedGroups extension.
- */
- (void)ssl;
- (void)semaphore;
- }
- #else
- static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
- {
- word16 i;
- const Suites* suites = WOLFSSL_SUITES(ssl);
- for (i = 0; i < suites->suiteSz; i += 2) {
- if (suites->suites[i] == TLS13_BYTE)
- return;
- #ifdef BUILD_TLS_SM4_GCM_SM3
- if ((suites->suites[i] == CIPHER_BYTE) &&
- (suites->suites[i+1] == TLS_SM4_GCM_SM3))
- return;
- #endif
- #ifdef BUILD_TLS_SM4_CCM_SM3
- if ((suites->suites[i] == CIPHER_BYTE) &&
- (suites->suites[i+1] == TLS_SM4_CCM_SM3))
- return;
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
- if ((suites->suites[i] == SM_BYTE) &&
- (suites->suites[i+1] == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
- return;
- #endif
- if ((suites->suites[i] == ECC_BYTE) ||
- (suites->suites[i] == ECDHE_PSK_BYTE) ||
- (suites->suites[i] == CHACHA_BYTE)) {
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
- defined(HAVE_CURVE448)
- return;
- #endif
- }
- #ifdef HAVE_FFDHE
- else {
- return;
- }
- #endif
- }
- /* turns semaphore on to avoid sending this extension. */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS));
- }
- #endif
- /* Only send PointFormats if TLSv13, ECC or CHACHA cipher suite present.
- */
- static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
- {
- #ifdef HAVE_FFDHE
- (void)ssl;
- (void)semaphore;
- #else
- word16 i;
- const Suites* suites = WOLFSSL_SUITES(ssl);
- if (suites == NULL)
- return;
- for (i = 0; i < suites->suiteSz; i += 2) {
- if (suites->suites[i] == TLS13_BYTE)
- return;
- #ifdef BUILD_TLS_SM4_GCM_SM3
- if ((suites->suites[i] == CIPHER_BYTE) &&
- (suites->suites[i+1] == TLS_SM4_GCM_SM3))
- return;
- #endif
- #ifdef BUILD_TLS_SM4_CCM_SM3
- if ((suites->suites[i] == CIPHER_BYTE) &&
- (suites->suites[i+1] == TLS_SM4_CCM_SM3))
- return;
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
- if ((suites->suites[i] == SM_BYTE) &&
- (suites->suites[i+1] == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
- return;
- #endif
- if ((suites->suites[i] == ECC_BYTE) ||
- (suites->suites[i] == ECDHE_PSK_BYTE) ||
- (suites->suites[i] == CHACHA_BYTE)) {
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
- defined(HAVE_CURVE448)
- return;
- #endif
- }
- }
- /* turns semaphore on to avoid sending this extension. */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- #endif
- }
- #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;
- #ifdef BUILD_TLS_SM4_GCM_SM3
- if ((ssl->options.cipherSuite0 == CIPHER_BYTE) &&
- (ssl->options.cipherSuite == TLS_SM4_GCM_SM3))
- return;
- #endif
- #ifdef BUILD_TLS_SM4_CCM_SM3
- if ((ssl->options.cipherSuite0 == CIPHER_BYTE) &&
- (ssl->options.cipherSuite == TLS_SM4_CCM_SM3))
- return;
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
- if ((ssl->options.cipherSuite0 == SM_BYTE) &&
- (ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
- return;
- #endif
- #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
- if (ssl->options.cipherSuite0 == ECC_BYTE ||
- ssl->options.cipherSuite0 == ECDHE_PSK_BYTE ||
- ssl->options.cipherSuite0 == CHACHA_BYTE) {
- return;
- }
- #endif
- /* turns semaphore on to avoid sending this extension. */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- }
- #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))
- int TLSX_SupportedCurve_Parse(const WOLFSSL* ssl, const byte* input,
- word16 length, byte isRequest, TLSX** extensions)
- {
- 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(*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(extensions, name, ssl->heap);
- /* If it is BAD_FUNC_ARG then it is a group we do not support, but
- * that is fine. */
- if (ret != WOLFSSL_SUCCESS && ret != BAD_FUNC_ARG) {
- return ret;
- }
- }
- 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;
- ret = TLSX_PopulateSupportedGroups(ssl, &priority);
- if (ret != WOLFSSL_SUCCESS) {
- TLSX_FreeAll(priority, ssl->heap);
- return ret;
- }
- ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
- if (ext == NULL) {
- WOLFSSL_MSG("Could not find supported groups extension");
- TLSX_FreeAll(priority, ssl->heap);
- 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)
- #ifdef HAVE_PUBLIC_FFDHE
- static int tlsx_ffdhe_find_group(WOLFSSL* ssl, SupportedCurve* clientGroup,
- SupportedCurve* serverGroup)
- {
- int ret = 0;
- SupportedCurve* group;
- const DhParams* params = NULL;
- for (; serverGroup != NULL; serverGroup = serverGroup->next) {
- if (!WOLFSSL_NAMED_GROUP_IS_FFHDE(serverGroup->name))
- 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
- default:
- break;
- }
- if (params == NULL) {
- ret = BAD_FUNC_ARG;
- break;
- }
- if (params->p_len >= ssl->options.minDhKeySz &&
- params->p_len <= ssl->options.maxDhKeySz) {
- break;
- }
- }
- if (ret != 0)
- break;
- if ((group != NULL) && (serverGroup->name == group->name))
- break;
- }
- if ((ret == 0) && (serverGroup != NULL) && (params != NULL)) {
- 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;
- }
- return ret;
- }
- #else
- static int tlsx_ffdhe_find_group(WOLFSSL* ssl, SupportedCurve* clientGroup,
- SupportedCurve* serverGroup)
- {
- int ret = 0;
- SupportedCurve* group;
- word32 p_len;
- for (; serverGroup != NULL; serverGroup = serverGroup->next) {
- if (!WOLFSSL_NAMED_GROUP_IS_FFHDE(serverGroup->name))
- continue;
- for (group = clientGroup; group != NULL; group = group->next) {
- if (serverGroup->name != group->name)
- continue;
- wc_DhGetNamedKeyParamSize(serverGroup->name, &p_len, NULL, NULL);
- if (p_len == 0) {
- ret = BAD_FUNC_ARG;
- break;
- }
- if (p_len >= ssl->options.minDhKeySz &&
- p_len <= ssl->options.maxDhKeySz) {
- break;
- }
- }
- if (ret != 0)
- break;
- if ((group != NULL) && (serverGroup->name == group->name))
- break;
- }
- if ((ret == 0) && (serverGroup != NULL)) {
- word32 pSz, gSz;
- ssl->buffers.serverDH_P.buffer = NULL;
- ssl->buffers.serverDH_G.buffer = NULL;
- ret = wc_DhGetNamedKeyParamSize(serverGroup->name, &pSz, &gSz, NULL);
- if (ret == 0) {
- ssl->buffers.serverDH_P.buffer =
- (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (ssl->buffers.serverDH_P.buffer == NULL)
- ret = MEMORY_E;
- else
- ssl->buffers.serverDH_P.length = pSz;
- }
- if (ret == 0) {
- ssl->buffers.serverDH_G.buffer =
- (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (ssl->buffers.serverDH_G.buffer == NULL) {
- ret = MEMORY_E;
- } else
- ssl->buffers.serverDH_G.length = gSz;
- }
- if (ret == 0) {
- ret = wc_DhCopyNamedKey(serverGroup->name,
- ssl->buffers.serverDH_P.buffer, &pSz,
- ssl->buffers.serverDH_G.buffer, &gSz,
- NULL, NULL);
- }
- if (ret == 0) {
- ssl->buffers.weOwnDH = 1;
- 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;
- }
- else {
- if (ssl->buffers.serverDH_P.buffer != NULL) {
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- ssl->buffers.serverDH_P.length = 0;
- ssl->buffers.serverDH_P.buffer = NULL;
- }
- if (ssl->buffers.serverDH_G.buffer != NULL) {
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- ssl->buffers.serverDH_G.length = 0;
- ssl->buffers.serverDH_G.buffer = NULL;
- }
- }
- }
- return ret;
- }
- #endif
- /* 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;
- TLSX* priority = NULL;
- TLSX* ext = NULL;
- TLSX* extension;
- SupportedCurve* clientGroup;
- SupportedCurve* group;
- 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 (WOLFSSL_NAMED_GROUP_IS_FFHDE(group->name)) {
- 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;
- ret = TLSX_PopulateSupportedGroups(ssl, &priority);
- if (ret == WOLFSSL_SUCCESS) {
- SupportedCurve* serverGroup;
- ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
- serverGroup = (SupportedCurve*)ext->data;
- ret = tlsx_ffdhe_find_group(ssl, clientGroup, serverGroup);
- }
- 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, const 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(const WOLFSSL* ssl, byte first, byte second,
- word32* ecdhCurveOID) {
- TLSX* extension = NULL;
- SupportedCurve* curve = NULL;
- word32 oid = 0;
- 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 key = 0; /* validate key */
- (void)oid;
- 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 == ECDHE_PSK_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 && !key;
- curve = curve->next) {
- #ifdef OPENSSL_EXTRA
- /* skip if name is not in supported ECC range
- * or disabled by user */
- if (curve->name > WOLFSSL_ECC_MAX ||
- wolfSSL_curve_is_disabled(ssl, 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:
- oid = ECC_SECP160R1_OID;
- octets = 20;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_SECPR2
- case WOLFSSL_ECC_SECP160R2:
- oid = ECC_SECP160R2_OID;
- octets = 20;
- break;
- #endif /* HAVE_ECC_SECPR2 */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP160K1:
- 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:
- oid = ECC_SECP192R1_OID;
- octets = 24;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP192K1:
- 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:
- oid = ECC_SECP224R1_OID;
- octets = 28;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP224K1:
- 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:
- 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;
- 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:
- oid = ECC_SECP256K1_OID;
- octets = 32;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP256R1:
- oid = ECC_BRAINPOOLP256R1_OID;
- octets = 32;
- break;
- #endif /* HAVE_ECC_BRAINPOOL */
- #ifdef WOLFSSL_SM2
- case WOLFSSL_ECC_SM2P256V1:
- oid = ECC_SM2P256V1_OID;
- octets = 32;
- break;
- #endif /* WOLFSSL_SM2 */
- #endif
- #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP384R1:
- oid = ECC_SECP384R1_OID;
- octets = 48;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP384R1:
- 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;
- 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:
- 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:
- 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:
- 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;
- }
- 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:
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
- #if defined(HAVE_ECC) && defined(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;
- }
- key |= ssl->pkCurveOID == oid;
- break;
- #endif /* HAVE_ECC && 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;
- }
- 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 :
- 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 :
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
- #endif
- default:
- key = 1;
- break;
- }
- }
- }
- *ecdhCurveOID = ssl->ecdhCurveOID;
- /* Choose the default if it is at the required strength. */
- #ifdef HAVE_ECC
- if (*ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz)
- #else
- if (*ecdhCurveOID == 0)
- #endif
- {
- key = 1;
- *ecdhCurveOID = defOid;
- }
- /* Choose any curve at the required strength. */
- if (*ecdhCurveOID == 0) {
- key = 1;
- *ecdhCurveOID = currOid;
- }
- /* Choose the default if it is at the next highest strength. */
- if (*ecdhCurveOID == 0 && defSz == nextSz)
- *ecdhCurveOID = defOid;
- /* Choose any curve at the next highest strength. */
- if (*ecdhCurveOID == 0)
- *ecdhCurveOID = nextOid;
- /* No curve and ephemeral ECC suite requires a matching curve. */
- if (*ecdhCurveOID == 0 && ephmSuite)
- key = 0;
- return key;
- }
- #endif
- #endif /* NO_WOLFSSL_SERVER */
- int TLSX_SupportedCurve_Copy(TLSX* src, TLSX** dst, void* heap)
- {
- TLSX* extension;
- int ret;
- extension = TLSX_Find(src, TLSX_SUPPORTED_GROUPS);
- if (extension != NULL) {
- SupportedCurve* curve;
- for (curve = (SupportedCurve*)extension->data; curve != NULL;
- curve = curve->next) {
- ret = TLSX_UseSupportedCurve(dst, curve->name, heap);
- if (ret != WOLFSSL_SUCCESS)
- return MEMORY_E;
- }
- }
- return 0;
- }
- int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap)
- {
- TLSX* extension = NULL;
- SupportedCurve* curve = NULL;
- int ret;
- if (extensions == NULL) {
- return BAD_FUNC_ARG;
- }
- #ifdef WOLFSSL_TLS13
- if (! TLSX_KeyShare_IsSupported(name)) {
- return BAD_FUNC_ARG;
- }
- #endif
- 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, e) 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) WC_DO_NOTHING
- #define EC_GET_SIZE(list) 0
- #define EC_WRITE(a, b) 0
- #define EC_PARSE(a, b, c, d, e) 0
- #define EC_VALIDATE_REQUEST(a, b) WC_DO_NOTHING
- #define PF_FREE_ALL(list, heap) WC_DO_NOTHING
- #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) WC_DO_NOTHING
- #define PF_VALIDATE_RESPONSE(a, b) WC_DO_NOTHING
- #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, const 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 == NULL) {
- }
- 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) {
- WOLFSSL_ERROR_VERBOSE(ret);
- 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) WC_DO_NOTHING
- #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 || HAVE_SERVER_RENEGOTIATION_INFO */
- /******************************************************************************/
- /* 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 /* WOLFSSL_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, const 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;
- }
- #ifdef HAVE_SECURE_RENEGOTIATION
- if (IsSCR(ssl)) {
- WOLFSSL_MSG("Client sent session ticket during SCR. Ignoring.");
- return 0;
- }
- #endif
- if (length > SESSION_TICKET_LEN) {
- ret = BAD_TICKET_MSG_SZ;
- WOLFSSL_ERROR_VERBOSE(ret);
- } 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;
- /* SERVER: ticket is peer auth. */
- ssl->options.peerAuthGood = 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;
- /* SERVER: ticket is peer auth. */
- ssl->options.peerAuthGood = 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) {
- WOLFSSL_MSG("Process client ticket fatal error, not using");
- } else if (ret < 0) {
- WOLFSSL_MSG("Process client ticket unknown error, not using");
- }
- }
- }
- #endif /* NO_WOLFSSL_SERVER */
- #if defined(NO_WOLFSSL_CLIENT) && defined(NO_WOLFSSL_SERVER)
- (void)ssl;
- #endif
- 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) WC_DO_NOTHING
- #define WOLF_STK_VALIDATE_REQUEST(a) WC_DO_NOTHING
- #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 */
- #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) {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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) {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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, const byte* input,
- word16 length, byte msgType)
- {
- int ret;
- (void)input;
- if (msgType != client_hello && msgType != server_hello) {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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;
- }
- return 0;
- }
- /* Server Hello */
- if (ssl->options.disallowEncThenMac) {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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;
- }
- /**
- * Set the Encrypt-Then-MAC extension as one to respond too.
- *
- * ssl SSL object
- * return EXT_MISSING when EncryptThenMac extension not in list.
- */
- int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl)
- {
- TLSX* extension;
- extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC);
- if (extension == NULL)
- return EXT_MISSING;
- extension->resp = 1;
- 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 */
- #ifdef WOLFSSL_SRTP
- /******************************************************************************/
- /* DTLS SRTP (Secure Real-time Transport Protocol) */
- /******************************************************************************/
- /* Only support single SRTP profile */
- typedef struct TlsxSrtp {
- word16 profileCount;
- word16 ids; /* selected bits */
- } TlsxSrtp;
- static int TLSX_UseSRTP_GetSize(TlsxSrtp *srtp)
- {
- /* SRTP Profile Len (2)
- * SRTP Profiles (2)
- * MKI (master key id) Length */
- return (OPAQUE16_LEN + (srtp->profileCount * OPAQUE16_LEN) + 1);
- }
- static TlsxSrtp* TLSX_UseSRTP_New(word16 ids, void* heap)
- {
- TlsxSrtp* srtp;
- int i;
- srtp = (TlsxSrtp*)XMALLOC(sizeof(TlsxSrtp), heap, DYNAMIC_TYPE_TLSX);
- if (srtp == NULL) {
- WOLFSSL_MSG("TLSX SRTP Memory failure");
- return NULL;
- }
- /* count and test each bit set */
- srtp->profileCount = 0;
- for (i=0; i<16; i++) {
- if (ids & (1 << i)) {
- srtp->profileCount++;
- }
- }
- srtp->ids = ids;
- return srtp;
- }
- static void TLSX_UseSRTP_Free(TlsxSrtp *srtp, void* heap)
- {
- if (srtp != NULL) {
- XFREE(srtp, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
- }
- static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length,
- byte isRequest)
- {
- int ret = BAD_FUNC_ARG;
- word16 profile_len = 0;
- word16 profile_value = 0;
- word16 offset = 0;
- #ifndef NO_WOLFSSL_SERVER
- int i;
- TlsxSrtp* srtp = NULL;
- #endif
- if (length < OPAQUE16_LEN) {
- return BUFFER_ERROR;
- }
- /* reset selected DTLS SRTP profile ID */
- ssl->dtlsSrtpId = 0;
- /* total length, not include itself */
- ato16(input, &profile_len);
- offset += OPAQUE16_LEN;
- if (!isRequest) {
- #ifndef NO_WOLFSSL_CLIENT
- if (length < offset + OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input + offset, &profile_value);
- /* check that the profile received was in the ones we support */
- if (profile_value < 16 &&
- (ssl->dtlsSrtpProfiles & (1 << profile_value))) {
- ssl->dtlsSrtpId = profile_value;
- ret = 0; /* success */
- }
- #endif
- }
- #ifndef NO_WOLFSSL_SERVER
- else {
- /* parse remainder one profile at a time, looking for match in CTX */
- ret = 0;
- for (i=offset; i<length; i+=OPAQUE16_LEN) {
- ato16(input+i, &profile_value);
- /* find first match */
- if (profile_value < 16 &&
- ssl->dtlsSrtpProfiles & (1 << profile_value)) {
- ssl->dtlsSrtpId = profile_value;
- /* make sure we respond with selected SRTP id selected */
- srtp = TLSX_UseSRTP_New((1 << profile_value), ssl->heap);
- if (srtp != NULL) {
- ret = TLSX_Push(&ssl->extensions, TLSX_USE_SRTP,
- (void*)srtp, ssl->heap);
- if (ret == 0) {
- TLSX_SetResponse(ssl, TLSX_USE_SRTP);
- /* successfully set extension */
- }
- }
- else {
- ret = MEMORY_E;
- }
- break;
- }
- }
- }
- if (ret == 0 && ssl->dtlsSrtpId == 0) {
- WOLFSSL_MSG("TLSX_UseSRTP_Parse profile not found!");
- /* not fatal */
- }
- else if (ret != 0) {
- ssl->dtlsSrtpId = 0;
- TLSX_UseSRTP_Free(srtp, ssl->heap);
- }
- #endif
- (void)profile_len;
- return ret;
- }
- static word16 TLSX_UseSRTP_Write(TlsxSrtp* srtp, byte* output)
- {
- word16 offset = 0;
- int i, j;
- c16toa(srtp->profileCount * 2, output + offset);
- offset += OPAQUE16_LEN;
- j = 0;
- for (i = 0; i < srtp->profileCount; i++) {
- for (; j < 16; j++) {
- if (srtp->ids & (1 << j)) {
- c16toa(j, output + offset);
- offset += OPAQUE16_LEN;
- }
- }
- }
- output[offset++] = 0x00; /* MKI Length */
- return offset;
- }
- static int TLSX_UseSRTP(TLSX** extensions, word16 profiles, void* heap)
- {
- int ret = 0;
- TLSX* extension;
- if (extensions == NULL) {
- return BAD_FUNC_ARG;
- }
- extension = TLSX_Find(*extensions, TLSX_USE_SRTP);
- if (extension == NULL) {
- TlsxSrtp* srtp = TLSX_UseSRTP_New(profiles, heap);
- if (srtp == NULL) {
- return MEMORY_E;
- }
- ret = TLSX_Push(extensions, TLSX_USE_SRTP, (void*)srtp, heap);
- if (ret != 0) {
- TLSX_UseSRTP_Free(srtp, heap);
- }
- }
- return ret;
- }
- #ifndef NO_WOLFSSL_SERVER
- #define SRTP_FREE TLSX_UseSRTP_Free
- #define SRTP_PARSE TLSX_UseSRTP_Parse
- #define SRTP_WRITE TLSX_UseSRTP_Write
- #define SRTP_GET_SIZE TLSX_UseSRTP_GetSize
- #else
- #define SRTP_FREE(a, b) WC_DO_NOTHING
- #define SRTP_PARSE(a, b, c, d) 0
- #define SRTP_WRITE(a, b) 0
- #define SRTP_GET_SIZE(a) 0
- #endif
- #endif /* WOLFSSL_SRTP */
- /******************************************************************************/
- /* Supported Versions */
- /******************************************************************************/
- #ifdef WOLFSSL_TLS13
- static WC_INLINE int versionIsGreater(byte isDtls, byte a, byte b)
- {
- (void)isDtls;
- #ifdef WOLFSSL_DTLS
- /* DTLS version increases backwards (-1,-2,-3,etc) */
- if (isDtls)
- return a < b;
- #endif /* WOLFSSL_DTLS */
- return a > b;
- }
- static WC_INLINE int versionIsLesser(byte isDtls, byte a, byte b)
- {
- (void)isDtls;
- #ifdef WOLFSSL_DTLS
- /* DTLS version increases backwards (-1,-2,-3,etc) */
- if (isDtls)
- return a > b;
- #endif /* WOLFSSL_DTLS */
- return a < b;
- }
- static WC_INLINE int versionIsAtLeast(byte isDtls, byte a, byte b)
- {
- (void)isDtls;
- #ifdef WOLFSSL_DTLS
- /* DTLS version increases backwards (-1,-2,-3,etc) */
- if (isDtls)
- return a <= b;
- #endif /* WOLFSSL_DTLS */
- return a >= b;
- }
- static WC_INLINE int versionIsLessEqual(byte isDtls, byte a, byte b)
- {
- (void)isDtls;
- #ifdef WOLFSSL_DTLS
- /* DTLS version increases backwards (-1,-2,-3,etc) */
- if (isDtls)
- return a >= b;
- #endif /* WOLFSSL_DTLS */
- return a <= b;
- }
- /* 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;
- byte tls13Minor, tls12Minor, tls11Minor, isDtls;
- isDtls = !!ssl->options.dtls;
- tls13Minor = (byte)(isDtls ? DTLSv1_3_MINOR : TLSv1_3_MINOR);
- tls12Minor = (byte)(isDtls ? DTLSv1_2_MINOR : TLSv1_2_MINOR);
- tls11Minor = (byte)(isDtls ? DTLS_MINOR : TLSv1_1_MINOR);
- /* unused on some configuration */
- (void)tls12Minor;
- (void)tls13Minor;
- (void)tls11Minor;
- if (msgType == client_hello) {
- /* TLS v1.2 and TLS v1.3 */
- int cnt = 0;
- if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls13Minor)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0
- #endif
- ) {
- cnt++;
- }
- if (ssl->options.downgrade) {
- #ifndef WOLFSSL_NO_TLS12
- if (versionIsLessEqual(
- isDtls, ssl->options.minDowngrade, tls12Minor)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0
- #endif
- ) {
- cnt++;
- }
- #endif
- #ifndef NO_OLD_TLS
- if (versionIsLessEqual(
- isDtls, ssl->options.minDowngrade, tls11Minor)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0
- #endif
- ) {
- cnt++;
- }
- #ifdef WOLFSSL_ALLOW_TLSV10
- if (!ssl->options.dtls && (ssl->options.minDowngrade <= TLSv1_MINOR)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (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 {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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 tls13minor, tls12minor, tls11minor, isDtls = 0;
- tls13minor = (byte)TLSv1_3_MINOR;
- tls12minor = (byte)TLSv1_2_MINOR;
- tls11minor = (byte)TLSv1_1_MINOR;
- /* unused in some configuration */
- (void)tls11minor;
- (void)tls12minor;
- #ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls) {
- tls13minor = (byte)DTLSv1_3_MINOR;
- tls12minor = (byte)DTLSv1_2_MINOR;
- tls11minor = (byte)DTLS_MINOR;
- isDtls = 1;
- }
- #endif /* WOLFSSL_DTLS13 */
- if (msgType == client_hello) {
- byte major = ssl->ctx->method->version.major;
- byte* cnt = output++;
- *cnt = 0;
- if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls13minor)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (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++) = tls13minor;
- #endif
- }
- if (ssl->options.downgrade) {
- #ifndef WOLFSSL_NO_TLS12
- if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls12minor)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0
- #endif
- ) {
- *cnt += OPAQUE16_LEN;
- *(output++) = major;
- *(output++) = tls12minor;
- }
- #endif
- #ifndef NO_OLD_TLS
- if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls11minor)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0
- #endif
- ) {
- *cnt += OPAQUE16_LEN;
- *(output++) = major;
- *(output++) = tls11minor;
- }
- #ifdef WOLFSSL_ALLOW_TLSV10
- if (!ssl->options.dtls && (ssl->options.minDowngrade <= TLSv1_MINOR)
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
- defined(WOLFSSL_WPAS_SMALL)
- && (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 {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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.
- * pv The output ProtocolVersion for the negotiated version
- * opts The output options structure. Can be NULL.
- * exts The output extensions list. Can be NULL.
- * returns 0 on success, otherwise failure.
- */
- int TLSX_SupportedVersions_Parse(const WOLFSSL* ssl, const byte* input,
- word16 length, byte msgType, ProtocolVersion* pv, Options* opts,
- TLSX** exts)
- {
- /* The client's greatest minor version that we support */
- byte clientGreatestMinor = SSLv3_MINOR;
- int ret;
- byte major, minor;
- byte tls13minor, tls12minor;
- byte isDtls;
- tls13minor = TLSv1_3_MINOR;
- tls12minor = TLSv1_2_MINOR;
- isDtls = ssl->options.dtls == 1;
- #ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls) {
- tls13minor = DTLSv1_3_MINOR;
- tls12minor = DTLSv1_2_MINOR;
- clientGreatestMinor = DTLS_MINOR;
- }
- #endif /* WOLFSSL_DTLS13 */
- if (msgType == client_hello) {
- int i;
- int len;
- int set = 0;
- /* 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 != ssl->ctx->method->version.major)
- continue;
- /* No upgrade allowed. */
- if (versionIsGreater(isDtls, minor, ssl->version.minor))
- continue;
- /* Check downgrade. */
- if (versionIsLesser(isDtls, minor, ssl->version.minor)) {
- if (!ssl->options.downgrade)
- continue;
- if (versionIsLesser(isDtls, minor, ssl->options.minDowngrade))
- continue;
- }
- if (versionIsGreater(isDtls, minor, clientGreatestMinor))
- clientGreatestMinor = minor;
- set = 1;
- }
- if (!set) {
- /* No common supported version was negotiated */
- SendAlert((WOLFSSL*)ssl, alert_fatal,
- wolfssl_alert_protocol_version);
- WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
- return VERSION_ERROR;
- }
- pv->minor = clientGreatestMinor;
- if (versionIsAtLeast(isDtls, clientGreatestMinor, tls13minor)) {
- if (opts != NULL)
- opts->tls1_3 = 1;
- /* TLS v1.3 requires supported version extension */
- if (exts != NULL &&
- TLSX_Find(*exts, TLSX_SUPPORTED_VERSIONS) == NULL) {
- ret = TLSX_Push(exts,
- TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap);
- if (ret != 0) {
- return ret;
- }
- /* *exts should be pointing to the TLSX_SUPPORTED_VERSIONS
- * ext in the list since it was pushed. */
- (*exts)->resp = 1;
- }
- }
- }
- 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 != ssl->ctx->method->version.major) {
- WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
- return VERSION_ERROR;
- }
- /* Can't downgrade with this extension below TLS v1.3. */
- if (versionIsLesser(isDtls, minor, tls13minor)) {
- WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
- return VERSION_ERROR;
- }
- /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */
- if (ssl->options.downgrade && ssl->version.minor == tls12minor) {
- /* Set minor version back to TLS v1.3+ */
- pv->minor = ssl->ctx->method->version.minor;
- }
- /* No upgrade allowed. */
- if (versionIsLesser(isDtls, ssl->version.minor, minor)) {
- WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
- return VERSION_ERROR;
- }
- /* Check downgrade. */
- if (versionIsGreater(isDtls, ssl->version.minor, minor)) {
- if (!ssl->options.downgrade) {
- WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
- return VERSION_ERROR;
- }
- if (versionIsLesser(
- isDtls, minor, ssl->options.minDowngrade)) {
- WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
- return VERSION_ERROR;
- }
- /* Downgrade the version. */
- pv->minor = minor;
- }
- }
- else {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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, 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, e, f, g) 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 {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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 {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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, const byte* input, word16 length,
- byte msgType)
- {
- word16 len;
- word16 idx = 0;
- TLSX* extension;
- Cookie* cookie;
- if (msgType != client_hello && msgType != hello_retry_request) {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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,
- &ssl->extensions);
- /* client_hello */
- extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
- if (extension == NULL) {
- #ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
- /* Allow a cookie extension with DTLS 1.3 because it is possible
- * that a different SSL instance sent the cookie but we are now
- * receiving it. */
- return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0,
- &ssl->extensions);
- else
- #endif
- {
- WOLFSSL_ERROR_VERBOSE(HRR_COOKIE_ERROR);
- return HRR_COOKIE_ERROR;
- }
- }
- cookie = (Cookie*)extension->data;
- if (cookie->len != len || XMEMCMP(cookie->data, input + idx, len) != 0) {
- WOLFSSL_ERROR_VERBOSE(HRR_COOKIE_ERROR);
- 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(const WOLFSSL* ssl, const byte* data, word16 len, byte* mac,
- byte macSz, int resp, TLSX** exts)
- {
- int ret = 0;
- TLSX* extension;
- Cookie* cookie;
- /* Find the cookie extension if it exists. */
- extension = TLSX_Find(*exts, TLSX_COOKIE);
- if (extension == NULL) {
- /* Push new cookie extension. */
- ret = TLSX_Push(exts, TLSX_COOKIE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(*exts, TLSX_COOKIE);
- if (extension == NULL)
- return MEMORY_E;
- }
- cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz, 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(WOLFSSL_TLS13) && !defined(NO_CERTS) && \
- !defined(WOLFSSL_NO_CA_NAMES) && defined(OPENSSL_EXTRA)
- /* Currently only settable through compatibility API */
- /******************************************************************************/
- /* Certificate Authorities */
- /******************************************************************************/
- static word16 TLSX_CA_Names_GetSize(void* data)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
- word16 size = 0;
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- /* To add support use a different member like ssl->ca_names and
- * add accessor functions:
- * - *_set0_CA_list
- * - *_get0_CA_list */
- WOLFSSL_MSG("We don't currently support sending the client's list.");
- return 0;
- }
- /* Length of names */
- size += OPAQUE16_LEN;
- for (names = SSL_CA_NAMES(ssl); names != NULL; names = names->next) {
- byte seq[MAX_SEQ_SZ];
- WOLFSSL_X509_NAME* name = names->data.name;
- if (name != NULL) {
- /* 16-bit length | SEQ | Len | DER of name */
- size += (word16)(OPAQUE16_LEN + SetSequence(name->rawLen, seq) +
- name->rawLen);
- }
- }
- return size;
- }
- static word16 TLSX_CA_Names_Write(void* data, byte* output)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
- byte* len;
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- /* To add support use a different member like ssl->ca_names and
- * add accessor functions:
- * - *_set0_CA_list
- * - *_get0_CA_list */
- WOLFSSL_MSG("We don't currently support sending the client's list.");
- return 0;
- }
- /* Reserve space for the length value */
- len = output;
- output += OPAQUE16_LEN;
- for (names = SSL_CA_NAMES(ssl); names != NULL; names = names->next) {
- byte seq[MAX_SEQ_SZ];
- WOLFSSL_X509_NAME* name = names->data.name;
- if (name != NULL) {
- c16toa((word16)name->rawLen +
- (word16)SetSequence(name->rawLen, seq), output);
- output += OPAQUE16_LEN;
- output += SetSequence(name->rawLen, output);
- XMEMCPY(output, name->raw, name->rawLen);
- output += name->rawLen;
- }
- }
- /* Write the total length */
- c16toa((word16)(output - len - OPAQUE16_LEN), len);
- return (word16)(output - len);
- }
- static int TLSX_CA_Names_Parse(WOLFSSL *ssl, const byte* input,
- word16 length, byte isRequest)
- {
- word16 extLen;
- (void)isRequest;
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- /* To add support use a different member like ssl->ca_names and
- * add accessor functions:
- * - *_set0_CA_list
- * - *_get0_CA_list */
- WOLFSSL_MSG("We don't currently support parsing the client's list.");
- return 0;
- }
- if (ssl->client_ca_names != ssl->ctx->client_ca_names)
- wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
- ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
- if (ssl->client_ca_names == NULL)
- return MEMORY_ERROR;
- if (length < OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input, &extLen);
- input += OPAQUE16_LEN;
- length -= OPAQUE16_LEN;
- if (extLen != length)
- return BUFFER_ERROR;
- while (length) {
- word32 idx = 0;
- WOLFSSL_X509_NAME* name = NULL;
- int ret = 0;
- int didInit = FALSE;
- /* Use a DecodedCert struct to get access to GetName to
- * parse DN name */
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert *cert = (DecodedCert *)XMALLOC(
- sizeof(*cert), ssl->heap, DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_ERROR;
- #else
- DecodedCert cert[1];
- #endif
- if (length < OPAQUE16_LEN)
- return BUFFER_ERROR;
- ato16(input, &extLen);
- idx += OPAQUE16_LEN;
- if (idx + extLen > length)
- ret = BUFFER_ERROR;
- if (ret == 0) {
- InitDecodedCert(cert, input + idx, extLen, ssl->heap);
- didInit = TRUE;
- idx += extLen;
- ret = GetName(cert, SUBJECT, extLen);
- }
- if (ret == 0 && (name = wolfSSL_X509_NAME_new()) == NULL)
- ret = MEMORY_ERROR;
- if (ret == 0) {
- CopyDecodedName(name, cert, SUBJECT);
- if (wolfSSL_sk_X509_NAME_push(ssl->client_ca_names, name)
- == WOLFSSL_FAILURE)
- ret = MEMORY_ERROR;
- }
- if (didInit)
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- #endif
- if (ret != 0)
- return ret;
- input += idx;
- length -= (word16)idx;
- }
- return 0;
- }
- #define CAN_GET_SIZE TLSX_CA_Names_GetSize
- #define CAN_WRITE TLSX_CA_Names_Write
- #define CAN_PARSE TLSX_CA_Names_Parse
- #else
- #define CAN_GET_SIZE(...) 0
- #define CAN_WRITE(...) 0
- #define CAN_PARSE(...) 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)
- {
- SignatureAlgorithms* sa = (SignatureAlgorithms*)data;
- if (sa->hashSigAlgoSz == 0)
- return OPAQUE16_LEN + WOLFSSL_SUITES(sa->ssl)->hashSigAlgoSz;
- else
- return OPAQUE16_LEN + sa->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, const 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)
- {
- SignatureAlgorithms* sa = (SignatureAlgorithms*)data;
- const Suites* suites = WOLFSSL_SUITES(sa->ssl);
- word16 hashSigAlgoSz;
- if (sa->hashSigAlgoSz == 0) {
- c16toa(suites->hashSigAlgoSz, output);
- XMEMCPY(output + OPAQUE16_LEN, suites->hashSigAlgo,
- suites->hashSigAlgoSz);
- hashSigAlgoSz = suites->hashSigAlgoSz;
- }
- else {
- c16toa(sa->hashSigAlgoSz, output);
- XMEMCPY(output + OPAQUE16_LEN, sa->hashSigAlgo,
- sa->hashSigAlgoSz);
- hashSigAlgoSz = sa->hashSigAlgoSz;
- }
- #ifndef NO_RSA
- TLSX_SignatureAlgorithms_MapPss(sa->ssl, output + OPAQUE16_LEN,
- hashSigAlgoSz);
- #endif
- return OPAQUE16_LEN + 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, const 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, WOLFSSL* ssl,
- void* heap)
- {
- SignatureAlgorithms* sa;
- int ret;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- /* Already present */
- if (TLSX_Find(*extensions, TLSX_SIGNATURE_ALGORITHMS) != NULL)
- return 0;
- sa = TLSX_SignatureAlgorithms_New(ssl, 0, heap);
- if (sa == NULL)
- return MEMORY_ERROR;
- ret = TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, sa, heap);
- if (ret != 0)
- TLSX_SignatureAlgorithms_FreeAll(sa, heap);
- return ret;
- }
- SignatureAlgorithms* TLSX_SignatureAlgorithms_New(WOLFSSL* ssl,
- word16 hashSigAlgoSz, void* heap)
- {
- SignatureAlgorithms* sa;
- (void)heap;
- sa = (SignatureAlgorithms*)XMALLOC(sizeof(*sa) + hashSigAlgoSz, heap,
- DYNAMIC_TYPE_TLSX);
- if (sa != NULL) {
- XMEMSET(sa, 0, sizeof(*sa) + hashSigAlgoSz);
- sa->ssl = ssl;
- sa->hashSigAlgoSz = hashSigAlgoSz;
- }
- return sa;
- }
- void TLSX_SignatureAlgorithms_FreeAll(SignatureAlgorithms* sa,
- void* heap)
- {
- XFREE(sa, heap, DYNAMIC_TYPE_TLSX);
- (void)heap;
- }
- #define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize
- #define SA_WRITE TLSX_SignatureAlgorithms_Write
- #define SA_PARSE TLSX_SignatureAlgorithms_Parse
- #define SA_FREE_ALL TLSX_SignatureAlgorithms_FreeAll
- #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, const 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 WOLFSSL* data, void* heap)
- {
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, 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 = 0;
- #if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK))
- word32 pSz = 0, pvtSz = 0;
- DhKey* dhKey = (DhKey*)kse->key;
- /* Pick the parameters from the named group. */
- #ifdef HAVE_PUBLIC_FFDHE
- const DhParams* params = NULL;
- switch (kse->group) {
- #ifdef HAVE_FFDHE_2048
- case WOLFSSL_FFDHE_2048:
- params = wc_Dh_ffdhe2048_Get();
- pvtSz = 29;
- break;
- #endif
- #ifdef HAVE_FFDHE_3072
- case WOLFSSL_FFDHE_3072:
- params = wc_Dh_ffdhe3072_Get();
- pvtSz = 34;
- break;
- #endif
- #ifdef HAVE_FFDHE_4096
- case WOLFSSL_FFDHE_4096:
- params = wc_Dh_ffdhe4096_Get();
- pvtSz = 39;
- break;
- #endif
- #ifdef HAVE_FFDHE_6144
- case WOLFSSL_FFDHE_6144:
- params = wc_Dh_ffdhe6144_Get();
- pvtSz = 46;
- break;
- #endif
- #ifdef HAVE_FFDHE_8192
- case WOLFSSL_FFDHE_8192:
- params = wc_Dh_ffdhe8192_Get();
- pvtSz = 52;
- break;
- #endif
- default:
- break;
- }
- if (params == NULL)
- return BAD_FUNC_ARG;
- pSz = params->p_len;
- #else
- pvtSz = wc_DhGetNamedKeyMinSize(kse->group);
- if (pvtSz == 0) {
- return BAD_FUNC_ARG;
- }
- ret = wc_DhGetNamedKeyParamSize(kse->group, &pSz, NULL, NULL);
- if (ret != 0) {
- return BAD_FUNC_ARG;
- }
- #endif
- /* Trigger Key Generation */
- if (kse->pubKey == NULL || kse->privKey == NULL) {
- if (kse->key == NULL) {
- kse->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap,
- DYNAMIC_TYPE_DH);
- if (kse->key == NULL)
- return MEMORY_E;
- /* Setup Key */
- ret = wc_InitDhKey_ex((DhKey*)kse->key, ssl->heap, ssl->devId);
- if (ret == 0) {
- dhKey = (DhKey*)kse->key;
- #ifdef HAVE_PUBLIC_FFDHE
- ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g,
- params->g_len);
- #else
- ret = wc_DhSetNamedKey(dhKey, kse->group);
- #endif
- }
- }
- /* Allocate space for the private and public key */
- if (ret == 0 && kse->pubKey == NULL) {
- kse->pubKey = (byte*)XMALLOC(pSz, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (kse->pubKey == NULL)
- ret = MEMORY_E;
- }
- if (ret == 0 && kse->privKey == NULL) {
- kse->privKey = (byte*)XMALLOC(pvtSz, ssl->heap,
- DYNAMIC_TYPE_PRIVATE_KEY);
- if (kse->privKey == NULL)
- ret = MEMORY_E;
- }
- if (ret == 0) {
- #if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA)
- ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_DH, kse->key);
- kse->pubKeyLen = pSz;
- kse->keyLen = pvtSz;
- if (ret == 0) {
- ret = wc_DhExportKeyPair(dhKey,
- (byte*)kse->privKey, &kse->keyLen, /* private */
- kse->pubKey, &kse->pubKeyLen /* public */
- );
- }
- else
- #endif
- {
- /* Generate a new key pair */
- /* For async this is called once and when event is done, the
- * provided buffers will be populated.
- * Final processing is zero pad below. */
- kse->pubKeyLen = pSz;
- kse->keyLen = pvtSz;
- ret = DhGenKeyPair(ssl, dhKey,
- (byte*)kse->privKey, &kse->keyLen, /* private */
- kse->pubKey, &kse->pubKeyLen /* public */
- );
- #ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
- return ret;
- }
- #endif
- }
- }
- }
- if (ret == 0) {
- if (pSz != kse->pubKeyLen) {
- /* Zero pad the front of the public key to match prime "p" size */
- XMEMMOVE(kse->pubKey + pSz - kse->pubKeyLen, kse->pubKey,
- kse->pubKeyLen);
- XMEMSET(kse->pubKey, 0, pSz - kse->pubKeyLen);
- kse->pubKeyLen = pSz;
- }
- if (pvtSz != kse->keyLen) {
- /* Zero pad the front of the private key */
- XMEMMOVE(kse->privKey + pvtSz - kse->keyLen, kse->privKey,
- kse->keyLen);
- XMEMSET(kse->privKey, 0, pvtSz - kse->keyLen);
- kse->keyLen = pvtSz;
- }
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public DH Key");
- WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
- #endif
- }
- /* Always release the DH key to free up memory.
- * The DhKey will be setup again in TLSX_KeyShare_ProcessDh */
- if (dhKey != NULL)
- wc_FreeDhKey(dhKey);
- if (kse->key != NULL) {
- XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_DH);
- kse->key = NULL;
- }
- if (ret != 0) {
- /* Cleanup on error, otherwise data owned by key share entry */
- if (kse->privKey != NULL) {
- XFREE(kse->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- kse->privKey = NULL;
- }
- if (kse->pubKey != NULL) {
- XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- kse->pubKey = NULL;
- }
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- WOLFSSL_ERROR_VERBOSE(ret);
- #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 = 0;
- #ifdef HAVE_CURVE25519
- curve25519_key* key = (curve25519_key*)kse->key;
- if (kse->key == NULL) {
- /* Allocate a Curve25519 key to hold private key. */
- kse->key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap,
- DYNAMIC_TYPE_PRIVATE_KEY);
- if (kse->key == NULL) {
- WOLFSSL_MSG("GenX25519Key memory error");
- return MEMORY_E;
- }
- /* Make an Curve25519 key. */
- ret = wc_curve25519_init_ex((curve25519_key*)kse->key, ssl->heap,
- INVALID_DEVID);
- if (ret == 0) {
- /* setting "key" means okay to call wc_curve25519_free */
- key = (curve25519_key*)kse->key;
- #ifdef WOLFSSL_STATIC_EPHEMERAL
- ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE25519, kse->key);
- if (ret != 0)
- #endif
- {
- ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
- }
- }
- }
- if (ret == 0 && kse->pubKey == NULL) {
- /* Allocate space for the public key. */
- kse->pubKey = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (kse->pubKey == NULL) {
- WOLFSSL_MSG("GenX25519Key pub memory error");
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- /* Export Curve25519 public key. */
- kse->pubKeyLen = CURVE25519_KEYSIZE;
- if (wc_curve25519_export_public_ex(key, kse->pubKey, &kse->pubKeyLen,
- EC25519_LITTLE_ENDIAN) != 0) {
- ret = ECC_EXPORT_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- kse->pubKeyLen = CURVE25519_KEYSIZE; /* always CURVE25519_KEYSIZE */
- }
- #ifdef WOLFSSL_DEBUG_TLS
- if (ret == 0) {
- WOLFSSL_MSG("Public Curve25519 Key");
- WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
- }
- #endif
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (kse->pubKey != NULL) {
- XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- kse->pubKey = NULL;
- }
- if (key != NULL)
- wc_curve25519_free(key);
- if (kse->key != NULL) {
- XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- kse->key = NULL;
- }
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- WOLFSSL_ERROR_VERBOSE(ret);
- #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 = 0;
- #ifdef HAVE_CURVE448
- curve448_key* key = (curve448_key*)kse->key;
- if (kse->key == NULL) {
- /* Allocate a Curve448 key to hold private key. */
- kse->key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap,
- DYNAMIC_TYPE_PRIVATE_KEY);
- if (kse->key == NULL) {
- WOLFSSL_MSG("GenX448Key memory error");
- return MEMORY_E;
- }
- /* Make an Curve448 key. */
- ret = wc_curve448_init((curve448_key*)kse->key);
- if (ret == 0) {
- key = (curve448_key*)kse->key;
- #ifdef WOLFSSL_STATIC_EPHEMERAL
- ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE448, kse->key);
- if (ret != 0)
- #endif
- {
- ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key);
- }
- }
- }
- if (ret == 0 && kse->pubKey == NULL) {
- /* Allocate space for the public key. */
- kse->pubKey = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (kse->pubKey == NULL) {
- WOLFSSL_MSG("GenX448Key pub memory error");
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- /* Export Curve448 public key. */
- kse->pubKeyLen = CURVE448_KEY_SIZE;
- if (wc_curve448_export_public_ex(key, kse->pubKey, &kse->pubKeyLen,
- EC448_LITTLE_ENDIAN) != 0) {
- ret = ECC_EXPORT_ERROR;
- }
- kse->pubKeyLen = CURVE448_KEY_SIZE; /* always CURVE448_KEY_SIZE */
- }
- #ifdef WOLFSSL_DEBUG_TLS
- if (ret == 0) {
- WOLFSSL_MSG("Public Curve448 Key");
- WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
- }
- #endif
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (kse->pubKey != NULL) {
- XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- kse->pubKey = NULL;
- }
- if (key != NULL)
- wc_curve448_free(key);
- if (kse->key != NULL) {
- XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- kse->key = NULL;
- }
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- WOLFSSL_ERROR_VERBOSE(ret);
- #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 = 0;
- #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
- word32 keySize = 0;
- word16 curveId = (word16) ECC_CURVE_INVALID;
- ecc_key* eccKey = (ecc_key*)kse->key;
- /* TODO: [TLS13] Get key sizes using wc_ecc_get_curve_size_from_id. */
- /* 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;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef WOLFSSL_SM2
- case WOLFSSL_ECC_SM2P256V1:
- curveId = ECC_SM2P256V1;
- keySize = 32;
- 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;
- 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;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- default:
- WOLFSSL_ERROR_VERBOSE(BAD_FUNC_ARG);
- return BAD_FUNC_ARG;
- }
- if (kse->key == NULL) {
- #if defined(WOLFSSL_RENESAS_TSIP_TLS)
- ret = tsip_Tls13GenEccKeyPair(ssl, kse);
- if (ret != CRYPTOCB_UNAVAILABLE) {
- return ret;
- }
- #endif
- /* Allocate an ECC key to hold private key. */
- kse->key = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC);
- if (kse->key == NULL) {
- WOLFSSL_MSG("EccTempKey Memory error");
- return MEMORY_E;
- }
- /* Initialize an ECC key struct for the ephemeral key */
- ret = wc_ecc_init_ex((ecc_key*)kse->key, ssl->heap, ssl->devId);
- if (ret == 0) {
- kse->keyLen = keySize;
- kse->pubKeyLen = keySize * 2 + 1;
- /* setting eccKey means okay to call wc_ecc_free */
- eccKey = (ecc_key*)kse->key;
- #ifdef WOLFSSL_STATIC_EPHEMERAL
- ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_ECDH, kse->key);
- if (ret != 0)
- #endif
- {
- /* set curve info for EccMakeKey "peer" info */
- ret = wc_ecc_set_curve(eccKey, kse->keyLen, curveId);
- if (ret == 0) {
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* Detect when private key generation is done */
- if (ssl->error == WC_PENDING_E &&
- eccKey->type == ECC_PRIVATEKEY) {
- ret = 0; /* ECC Key Generation is done */
- }
- else
- #endif
- {
- /* Generate ephemeral ECC key */
- /* For async this is called once and when event is done, the
- * provided buffers in key be populated.
- * Final processing is x963 key export below. */
- ret = EccMakeKey(ssl, eccKey, eccKey);
- }
- }
- #ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
- return ret;
- #endif
- }
- }
- }
- if (ret == 0 && kse->pubKey == NULL) {
- /* Allocate space for the public key */
- kse->pubKey = (byte*)XMALLOC(kse->pubKeyLen, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (kse->pubKey == NULL) {
- WOLFSSL_MSG("Key data Memory error");
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- XMEMSET(kse->pubKey, 0, kse->pubKeyLen);
- /* Export public key. */
- PRIVATE_KEY_UNLOCK();
- if (wc_ecc_export_x963(eccKey, kse->pubKey, &kse->pubKeyLen) != 0) {
- ret = ECC_EXPORT_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- PRIVATE_KEY_LOCK();
- }
- #ifdef WOLFSSL_DEBUG_TLS
- if (ret == 0) {
- WOLFSSL_MSG("Public ECC Key");
- WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
- }
- #endif
- if (ret != 0) {
- /* Cleanup on error, otherwise data owned by key share entry */
- if (kse->pubKey != NULL) {
- XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- kse->pubKey = NULL;
- }
- if (eccKey != NULL)
- wc_ecc_free(eccKey);
- if (kse->key != NULL) {
- XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- kse->key = NULL;
- }
- }
- #else
- (void)ssl;
- (void)kse;
- ret = NOT_COMPILED_IN;
- WOLFSSL_ERROR_VERBOSE(ret);
- #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
- return ret;
- }
- #ifdef HAVE_PQC
- static int kyber_id2type(int id, int *type)
- {
- int ret = 0;
- switch (id) {
- #ifdef WOLFSSL_KYBER512
- case WOLFSSL_KYBER_LEVEL1:
- *type = KYBER512;
- break;
- #endif
- #ifdef WOLFSSL_KYBER768
- case WOLFSSL_KYBER_LEVEL3:
- *type = KYBER768;
- break;
- #endif
- #ifdef WOLFSSL_KYBER1024
- case WOLFSSL_KYBER_LEVEL5:
- *type = KYBER1024;
- break;
- #endif
- default:
- ret = NOT_COMPILED_IN;
- break;
- }
- return ret;
- }
- typedef struct PqcHybridMapping {
- int hybrid;
- int ecc;
- int pqc;
- } PqcHybridMapping;
- static const PqcHybridMapping pqc_hybrid_mapping[] = {
- {.hybrid = WOLFSSL_P256_KYBER_LEVEL1, .ecc = WOLFSSL_ECC_SECP256R1,
- .pqc = WOLFSSL_KYBER_LEVEL1},
- {.hybrid = WOLFSSL_P384_KYBER_LEVEL3, .ecc = WOLFSSL_ECC_SECP384R1,
- .pqc = WOLFSSL_KYBER_LEVEL3},
- {.hybrid = WOLFSSL_P521_KYBER_LEVEL5, .ecc = WOLFSSL_ECC_SECP521R1,
- .pqc = WOLFSSL_KYBER_LEVEL5},
- {.hybrid = 0, .ecc = 0, .pqc = 0}
- };
- /* This will map an ecc-pqs hybrid group into its ecc group and pqc kem group.
- * If it cannot find a mapping then *pqc is set to group. ecc is optional. */
- static void findEccPqc(int *ecc, int *pqc, int group)
- {
- int i;
- if (pqc == NULL) {
- return;
- }
- *pqc = 0;
- if (ecc != NULL) {
- *ecc = 0;
- }
- for (i = 0; pqc_hybrid_mapping[i].hybrid != 0; i++) {
- if (pqc_hybrid_mapping[i].hybrid == group) {
- *pqc = pqc_hybrid_mapping[i].pqc;
- if (ecc != NULL) {
- *ecc = pqc_hybrid_mapping[i].ecc;
- }
- break;
- }
- }
- if (*pqc == 0) {
- /* It is not a hybrid, so maybe its simple. */
- *pqc = group;
- }
- }
- /* Create a key share entry using liboqs 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_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
- {
- int ret = 0;
- int type = 0;
- KyberKey kem[1];
- byte* pubKey = NULL;
- byte* privKey = NULL;
- KeyShareEntry *ecc_kse = NULL;
- int oqs_group = 0;
- int ecc_group = 0;
- word32 privSz = 0;
- word32 pubSz = 0;
- findEccPqc(&ecc_group, &oqs_group, kse->group);
- ret = kyber_id2type(oqs_group, &type);
- if (ret == NOT_COMPILED_IN) {
- WOLFSSL_MSG("Invalid Kyber algorithm specified.");
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId);
- if (ret != 0) {
- WOLFSSL_MSG("Failed to initialize Kyber Key.");
- }
- }
- if (ret == 0) {
- ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (ecc_kse == NULL) {
- WOLFSSL_MSG("ecc_kse memory allocation failure");
- ret = MEMORY_ERROR;
- }
- }
- if (ret == 0) {
- XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
- ret = wc_KyberKey_PrivateKeySize(kem, &privSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_PublicKeySize(kem, &pubSz);
- }
- if (ret == 0 && ecc_group != 0) {
- ecc_kse->group = ecc_group;
- ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse);
- /* If fail, no error message, TLSX_KeyShare_GenEccKey will do it. */
- }
- if (ret == 0) {
- pubKey = (byte*)XMALLOC(ecc_kse->pubKeyLen + pubSz, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pubKey == NULL) {
- WOLFSSL_MSG("pubkey memory allocation failure");
- ret = MEMORY_ERROR;
- }
- }
- if (ret == 0) {
- privKey = (byte*)XMALLOC(privSz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- if (privKey == NULL) {
- WOLFSSL_MSG("privkey memory allocation failure");
- ret = MEMORY_ERROR;
- }
- }
- if (ret == 0) {
- ret = wc_KyberKey_MakeKey(kem, ssl->rng);
- if (ret != 0) {
- WOLFSSL_MSG("Kyber keygen failure");
- }
- }
- if (ret == 0) {
- ret = wc_KyberKey_EncodePublicKey(kem, pubKey + ecc_kse->pubKeyLen,
- pubSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_EncodePrivateKey(kem, privKey, privSz);
- }
- if (ret == 0) {
- XMEMCPY(pubKey, ecc_kse->pubKey, ecc_kse->pubKeyLen);
- kse->pubKey = pubKey;
- kse->pubKeyLen = ecc_kse->pubKeyLen + pubSz;
- pubKey = NULL;
- /* Note we are saving the OQS private key and ECC private key
- * separately. That's because the ECC private key is not simply a
- * buffer. Its is an ecc_key struct.
- */
- kse->privKey = privKey;
- privKey = NULL;
- kse->key = ecc_kse->key;
- ecc_kse->key = NULL;
- }
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public Kyber Key");
- WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen );
- #endif
- wc_KyberKey_Free(kem);
- TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
- if (pubKey != NULL)
- XFREE(pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (privKey != NULL)
- XFREE(privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- return ret;
- }
- #endif /* HAVE_PQC */
- /* Generate a secret/key using the key share entry.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry holding peer data.
- */
- int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
- {
- int ret;
- /* Named FFDHE groups have a bit set to identify them. */
- if (WOLFSSL_NAMED_GROUP_IS_FFHDE(kse->group))
- ret = TLSX_KeyShare_GenDhKey(ssl, kse);
- else if (kse->group == WOLFSSL_ECC_X25519)
- ret = TLSX_KeyShare_GenX25519Key(ssl, kse);
- else if (kse->group == WOLFSSL_ECC_X448)
- ret = TLSX_KeyShare_GenX448Key(ssl, kse);
- #ifdef HAVE_PQC
- else if (WOLFSSL_NAMED_GROUP_IS_PQC(kse->group))
- ret = TLSX_KeyShare_GenPqcKey(ssl, kse);
- #endif
- else
- ret = TLSX_KeyShare_GenEccKey(ssl, kse);
- #ifdef WOLFSSL_ASYNC_CRYPT
- kse->lastRet = ret;
- #endif
- return ret;
- }
- /* 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 (WOLFSSL_NAMED_GROUP_IS_FFHDE(current->group)) {
- #ifndef NO_DH
- wc_FreeDhKey((DhKey*)current->key);
- #endif
- }
- else 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
- }
- #ifdef HAVE_PQC
- else if (WOLFSSL_NAMED_GROUP_IS_PQC(current->group) &&
- current->key != NULL) {
- ForceZero((byte*)current->key, current->keyLen);
- }
- #endif
- else {
- #ifdef HAVE_ECC
- wc_ecc_free((ecc_key*)current->key);
- #endif
- }
- XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY);
- #if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK))
- XFREE(current->privKey, heap, DYNAMIC_TYPE_PRIVATE_KEY);
- #endif
- 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->pubKey == NULL)
- continue;
- len += (word16)(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->pubKey == 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)
- {
- int ret = 0;
- #if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK))
- word32 pSz = 0;
- DhKey* dhKey = (DhKey*)keyShareEntry->key;
- #ifdef HAVE_PUBLIC_FFDHE
- const DhParams* params = NULL;
- 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:
- break;
- }
- if (params == NULL) {
- WOLFSSL_ERROR_VERBOSE(PEER_KEY_ERROR);
- return PEER_KEY_ERROR;
- }
- pSz = params->p_len;
- #else
- ret = wc_DhGetNamedKeyParamSize(keyShareEntry->group, &pSz, NULL, NULL);
- if (ret != 0 || pSz == 0) {
- WOLFSSL_ERROR_VERBOSE(PEER_KEY_ERROR);
- return PEER_KEY_ERROR;
- }
- #endif
- /* if DhKey is not setup, do it now */
- if (keyShareEntry->key == NULL) {
- keyShareEntry->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap,
- DYNAMIC_TYPE_DH);
- if (keyShareEntry->key == NULL)
- return MEMORY_E;
- /* Setup Key */
- ret = wc_InitDhKey_ex((DhKey*)keyShareEntry->key, ssl->heap, ssl->devId);
- if (ret == 0) {
- dhKey = (DhKey*)keyShareEntry->key;
- /* Set key */
- #ifdef HAVE_PUBLIC_FFDHE
- ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g,
- params->g_len);
- #else
- ret = wc_DhSetNamedKey(dhKey, keyShareEntry->group);
- #endif
- }
- }
- if (ret == 0
- #ifdef WOLFSSL_ASYNC_CRYPT
- && keyShareEntry->lastRet == 0 /* don't enter here if WC_PENDING_E */
- #endif
- ) {
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer DH Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
- #endif
- ssl->options.dhKeySz = (word16)pSz;
- /* Derive secret from private key and peer's public key. */
- ret = DhAgree(ssl, dhKey,
- (const byte*)keyShareEntry->privKey, keyShareEntry->keyLen, /* our private */
- keyShareEntry->ke, keyShareEntry->keLen, /* peer's public key */
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, /* secret */
- NULL, 0
- );
- #ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
- return ret;
- }
- #endif
- }
- /* RFC 8446 Section 7.4.1:
- * ... left-padded with zeros up to the size of the prime. ...
- */
- if (ret == 0 && (word32)ssl->options.dhKeySz > ssl->arrays->preMasterSz) {
- word32 diff = (word32)ssl->options.dhKeySz - ssl->arrays->preMasterSz;
- XMEMMOVE(ssl->arrays->preMasterSecret + diff,
- ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
- XMEMSET(ssl->arrays->preMasterSecret, 0, diff);
- ssl->arrays->preMasterSz = ssl->options.dhKeySz;
- }
- /* done with key share, release resources */
- if (dhKey)
- wc_FreeDhKey(dhKey);
- if (keyShareEntry->key) {
- XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_DH);
- keyShareEntry->key = NULL;
- }
- if (keyShareEntry->privKey != NULL) {
- XFREE(keyShareEntry->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- keyShareEntry->privKey = NULL;
- }
- if (keyShareEntry->pubKey != 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;
- #else
- (void)ssl;
- (void)keyShareEntry;
- ret = PEER_KEY_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- #endif
- return ret;
- }
- /* 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;
- ssl->peerEccKeyPresent = 0;
- }
- #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;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- if (ret == 0) {
- if (wc_curve25519_import_public_ex(keyShareEntry->ke,
- keyShareEntry->keLen, peerX25519Key,
- EC25519_LITTLE_ENDIAN) != 0) {
- ret = ECC_PEERKEY_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- }
- 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;
- WOLFSSL_ERROR_VERBOSE(ret);
- #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;
- ssl->peerEccKeyPresent = 0;
- }
- #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;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- if (ret == 0) {
- if (wc_curve448_import_public_ex(keyShareEntry->ke,
- keyShareEntry->keLen, peerX448Key,
- EC448_LITTLE_ENDIAN) != 0) {
- ret = ECC_PEERKEY_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- }
- 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;
- WOLFSSL_ERROR_VERBOSE(ret);
- #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 = 0;
- #ifdef HAVE_ECC
- int curveId = ECC_CURVE_INVALID;
- ecc_key* eccKey = (ecc_key*)keyShareEntry->key;
- /* 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 */
- #ifdef WOLFSSL_SM2
- case WOLFSSL_ECC_SM2P256V1:
- curveId = ECC_SM2P256V1;
- break;
- #endif
- #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 */
- WOLFSSL_ERROR_VERBOSE(ECC_PEERKEY_ERROR);
- return ECC_PEERKEY_ERROR;
- }
- #ifdef WOLFSSL_ASYNC_CRYPT
- if (keyShareEntry->lastRet == 0) /* don't enter here if WC_PENDING_E */
- #endif
- {
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer ECC Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
- #endif
- if (ssl->peerEccKey != NULL) {
- wc_ecc_free(ssl->peerEccKey);
- XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
- ssl->peerEccKeyPresent = 0;
- }
- #if defined(WOLFSSL_RENESAS_TSIP_TLS)
- ret = tsip_Tls13GenSharedSecret(ssl, keyShareEntry);
- if (ret != CRYPTOCB_UNAVAILABLE) {
- return ret;
- }
- ret = 0;
- #endif
- ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
- DYNAMIC_TYPE_ECC);
- if (ssl->peerEccKey == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- ret = MEMORY_ERROR;
- }
- if (ret == 0) {
- ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId);
- }
- /* Point is validated by import function. */
- if (ret == 0) {
- ret = wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen,
- ssl->peerEccKey, curveId);
- if (ret != 0) {
- ret = ECC_PEERKEY_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- }
- if (ret == 0) {
- ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum;
- ssl->peerEccKeyPresent = 1;
- }
- }
- if (ret == 0 && eccKey == NULL)
- ret = BAD_FUNC_ARG;
- if (ret == 0) {
- ret = EccSharedSecret(ssl, eccKey, ssl->peerEccKey,
- keyShareEntry->ke, &keyShareEntry->keLen,
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
- ssl->options.side
- );
- #ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
- return ret;
- #endif
- }
- /* done with key share, release resources */
- if (ssl->peerEccKey != NULL
- #ifdef HAVE_PK_CALLBACKS
- && ssl->ctx->EccSharedSecretCb == NULL
- #endif
- ) {
- wc_ecc_free(ssl->peerEccKey);
- XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
- ssl->peerEccKey = NULL;
- ssl->peerEccKeyPresent = 0;
- }
- if (keyShareEntry->key) {
- wc_ecc_free((ecc_key*)keyShareEntry->key);
- XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_ECC);
- keyShareEntry->key = NULL;
- }
- XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- keyShareEntry->ke = NULL;
- #else
- (void)ssl;
- (void)keyShareEntry;
- ret = PEER_KEY_ERROR;
- WOLFSSL_ERROR_VERBOSE(ret);
- #endif /* HAVE_ECC */
- return ret;
- }
- #ifdef HAVE_PQC
- /* Process the Kyber 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_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
- {
- int ret = 0;
- int type;
- KyberKey kem[1];
- byte* sharedSecret = NULL;
- word32 sharedSecretLen = 0;
- int oqs_group = 0;
- int ecc_group = 0;
- ecc_key eccpubkey;
- word32 outlen = 0;
- word32 privSz = 0;
- word32 ctSz = 0;
- word32 ssSz = 0;
- if (keyShareEntry->ke == NULL) {
- WOLFSSL_MSG("Invalid OQS algorithm specified.");
- return BAD_FUNC_ARG;
- }
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- /* I am the server, the shared secret has already been generated and
- * is in keyShareEntry->ke; copy it to the pre-master secret
- * pre-allocated buffer. */
- if (keyShareEntry->keLen > ENCRYPT_LEN) {
- WOLFSSL_MSG("shared secret is too long.");
- return LENGTH_ERROR;
- }
- XMEMCPY(ssl->arrays->preMasterSecret, keyShareEntry->ke,
- keyShareEntry->keLen);
- ssl->arrays->preMasterSz = keyShareEntry->keLen;
- XFREE(keyShareEntry->ke, sl->heap, DYNAMIC_TYPE_SECRET)
- keyShareEntry->ke = NULL;
- keyShareEntry->keLen = 0;
- return 0;
- }
- /* I am the client, the ciphertext is in keyShareEntry->ke */
- findEccPqc(&ecc_group, &oqs_group, keyShareEntry->group);
- ret = kyber_id2type(oqs_group, &type);
- if (ret != 0) {
- WOLFSSL_MSG("Invalid OQS algorithm specified.");
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_KyberKey_Init(type, kem, ssl->heap, INVALID_DEVID);
- if (ret != 0) {
- WOLFSSL_MSG("Error creating Kyber KEM");
- }
- }
- if (ret == 0) {
- ret = wc_KyberKey_SharedSecretSize(kem, &ssSz);
- }
- if (ret == 0) {
- sharedSecretLen = ssSz;
- switch (ecc_group) {
- case WOLFSSL_ECC_SECP256R1:
- sharedSecretLen += 32;
- outlen = 32;
- break;
- case WOLFSSL_ECC_SECP384R1:
- sharedSecretLen += 48;
- outlen = 48;
- break;
- case WOLFSSL_ECC_SECP521R1:
- sharedSecretLen += 66;
- outlen = 66;
- break;
- default:
- break;
- }
- ret = wc_ecc_init_ex(&eccpubkey, ssl->heap, ssl->devId);
- if (ret != 0) {
- WOLFSSL_MSG("Memory allocation error.");
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- sharedSecret = (byte*)XMALLOC(sharedSecretLen, ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (sharedSecret == NULL) {
- WOLFSSL_MSG("Memory allocation error.");
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- ret = wc_KyberKey_CipherTextSize(kem, &ctSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_PrivateKeySize(kem, &privSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_DecodePrivateKey(kem, keyShareEntry->privKey, privSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_Decapsulate(kem, sharedSecret + outlen,
- keyShareEntry->ke + keyShareEntry->keLen - ctSz, ctSz);
- if (ret != 0) {
- WOLFSSL_MSG("wc_KyberKey decapsulation failure.");
- ret = BAD_FUNC_ARG;
- }
- }
- if (ecc_group != 0) {
- if (ret == 0) {
- /* Point is validated by import function. */
- ret = wc_ecc_import_x963(keyShareEntry->ke,
- keyShareEntry->keLen - ctSz,
- &eccpubkey);
- if (ret != 0) {
- WOLFSSL_MSG("ECC Public key import error.");
- }
- }
- #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
- (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
- !defined(HAVE_SELFTEST)
- if (ret == 0) {
- ret = wc_ecc_set_rng(keyShareEntry->key, ssl->rng);
- if (ret != 0) {
- WOLFSSL_MSG("Failure to set the ECC private key RNG.");
- }
- }
- #endif
- if (ret == 0) {
- PRIVATE_KEY_UNLOCK();
- ret = wc_ecc_shared_secret(keyShareEntry->key, &eccpubkey,
- sharedSecret, &outlen);
- PRIVATE_KEY_LOCK();
- if (outlen != sharedSecretLen - ssSz) {
- WOLFSSL_MSG("ECC shared secret derivation error.");
- ret = BAD_FUNC_ARG;
- }
- }
- }
- if ((ret == 0) && (sharedSecretLen > ENCRYPT_LEN)) {
- WOLFSSL_MSG("shared secret is too long.");
- ret = LENGTH_ERROR;
- }
- if (ret == 0) {
- /* Copy the shared secret to the pre-master secret pre-allocated
- * buffer. */
- XMEMCPY(ssl->arrays->preMasterSecret, sharedSecret, sharedSecretLen);
- ssl->arrays->preMasterSz = (word32) sharedSecretLen;
- }
- if (sharedSecret != NULL) {
- XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
- }
- wc_ecc_free(&eccpubkey);
- wc_KyberKey_Free(kem);
- return ret;
- }
- #endif /* HAVE_PQC */
- /* 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 = keyShareEntry->group;
- #endif
- /* reset the pre master secret size */
- if (ssl->arrays->preMasterSz == 0)
- ssl->arrays->preMasterSz = ENCRYPT_LEN;
- /* Use Key Share Data from server. */
- if (WOLFSSL_NAMED_GROUP_IS_FFHDE(keyShareEntry->group))
- 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);
- #ifdef HAVE_PQC
- else if (WOLFSSL_NAMED_GROUP_IS_PQC(keyShareEntry->group))
- ret = TLSX_KeyShare_ProcessPqc(ssl, keyShareEntry);
- #endif
- else
- ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry);
- #ifdef WOLFSSL_DEBUG_TLS
- if (ret == 0) {
- WOLFSSL_MSG("KE Secret");
- WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
- }
- #endif
- #ifdef WOLFSSL_ASYNC_CRYPT
- keyShareEntry->lastRet = ret;
- #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(const WOLFSSL* ssl, const byte* input,
- word16 length, KeyShareEntry **kse, TLSX** extensions)
- {
- 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;
- #ifdef HAVE_PQC
- if (WOLFSSL_NAMED_GROUP_IS_PQC(group) &&
- ssl->options.side == WOLFSSL_SERVER_END) {
- /* For KEMs, the public key is not stored. Casting away const because
- * we know for KEMs, it will be read-only.*/
- ke = (byte *)&input[offset];
- } else
- #endif
- {
- /* 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, extensions);
- if (ret != 0) {
- if (ke != &input[offset]) {
- 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(const WOLFSSL* ssl, word16 name,
- TLSX* extensions)
- {
- #ifdef HAVE_SUPPORTED_CURVES
- TLSX* extension;
- SupportedCurve* curve = NULL;
- if ((extension = TLSX_Find(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;
- }
- int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl,
- const byte* input, word16 length, TLSX** extensions)
- {
- int ret;
- int offset = 0;
- word16 len;
- TLSX* extension;
- /* Add a KeyShare extension if it doesn't exist even if peer sent no
- * entries. The presence of this extension signals that the peer can be
- * negotiated with. */
- extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(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 - (word16)offset, NULL, extensions);
- if (ret < 0)
- return ret;
- offset += ret;
- }
- 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.
- */
- int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length,
- byte msgType)
- {
- int ret;
- KeyShareEntry *keyShareEntry = NULL;
- word16 group;
- if (msgType == client_hello) {
- ret = TLSX_KeyShare_Parse_ClientHello(ssl, input, length,
- &ssl->extensions);
- }
- 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, ssl->extensions)) {
- WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
- return BAD_KEY_SHARE_DATA;
- }
- /* Check if the group was sent. */
- if (!TLSX_KeyShare_Find(ssl, group)) {
- WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
- return BAD_KEY_SHARE_DATA;
- }
- /* ServerHello contains one key share entry. */
- len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry,
- &ssl->extensions);
- if (len != (int)length)
- return BUFFER_ERROR;
- /* Not in list sent if there isn't a private key. */
- if (keyShareEntry == NULL || (keyShareEntry->key == NULL
- #if !defined(NO_DH) || defined(HAVE_PQC)
- && keyShareEntry->privKey == NULL
- #endif
- )) {
- WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
- 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);
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* only perform find and clear TLSX if not returning from async */
- if (ssl->error != WC_PENDING_E)
- #endif
- {
- /* Check the selected group was supported by ClientHello extensions. */
- if (!TLSX_SupportedGroups_Find(ssl, group, ssl->extensions)) {
- WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
- return BAD_KEY_SHARE_DATA;
- }
- /* Check if the group was sent. */
- if (TLSX_KeyShare_Find(ssl, group)) {
- WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
- return BAD_KEY_SHARE_DATA;
- }
- /* Clear out unusable key shares. */
- ret = TLSX_KeyShare_Empty(ssl);
- if (ret != 0)
- return ret;
- }
- #ifdef HAVE_PQC
- /* For post-quantum groups, do this in TLSX_PopulateExtensions(). */
- if (!WOLFSSL_NAMED_GROUP_IS_PQC(group))
- #endif
- ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL, &ssl->extensions);
- if (ret == 0)
- ssl->session->namedGroup = ssl->namedGroup = group;
- }
- else {
- /* Not a message type that is allowed to have this extension. */
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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;
- }
- #ifdef HAVE_PQC
- static int server_generate_pqc_ciphertext(WOLFSSL* ssl,
- KeyShareEntry* keyShareEntry, byte* data, word16 len)
- {
- /* I am the server. The data parameter is the client's public key. I need
- * to generate the public information (AKA ciphertext) and shared secret
- * here. Note the "public information" is equivalent to a the public key in
- * key exchange parlance. That's why it is being assigned to pubKey.
- */
- int type;
- KyberKey kem[1];
- byte* sharedSecret = NULL;
- byte* ciphertext = NULL;
- int ret = 0;
- int oqs_group = 0;
- int ecc_group = 0;
- KeyShareEntry *ecc_kse = NULL;
- ecc_key eccpubkey;
- word32 outlen = 0;
- word32 pubSz = 0;
- word32 ctSz = 0;
- word32 ssSz = 0;
- findEccPqc(&ecc_group, &oqs_group, keyShareEntry->group);
- ret = kyber_id2type(oqs_group, &type);
- if (ret != 0) {
- WOLFSSL_MSG("Invalid Kyber algorithm specified.");
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- ret = wc_ecc_init_ex(&eccpubkey, ssl->heap, ssl->devId);
- if (ret != 0) {
- WOLFSSL_MSG("Could not do ECC public key initialization.");
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (ecc_kse == NULL) {
- WOLFSSL_MSG("ecc_kse memory allocation failure");
- ret = MEMORY_ERROR;
- }
- }
- if (ret == 0) {
- XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
- }
- if (ret == 0 && ecc_group != 0) {
- ecc_kse->group = ecc_group;
- ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse);
- if (ret != 0) {
- /* No message, TLSX_KeyShare_GenEccKey() will do it. */
- return ret;
- }
- ret = 0;
- }
- if (ret == 0) {
- ret = wc_KyberKey_Init(type, kem, ssl->heap, INVALID_DEVID);
- if (ret != 0) {
- WOLFSSL_MSG("Error creating Kyber KEM");
- }
- }
- if (ret == 0) {
- ret = wc_KyberKey_PublicKeySize(kem, &pubSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_CipherTextSize(kem, &ctSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_SharedSecretSize(kem, &ssSz);
- }
- if (ret == 0 && len != pubSz + ecc_kse->pubKeyLen) {
- WOLFSSL_MSG("Invalid public key.");
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- sharedSecret = (byte*)XMALLOC(ecc_kse->keyLen + ssSz, ssl->heap,
- DYNAMIC_TYPE_TLSX);
- ciphertext = (byte*)XMALLOC(ecc_kse->pubKeyLen + ctSz, ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (sharedSecret == NULL || ciphertext == NULL) {
- WOLFSSL_MSG("Ciphertext/shared secret memory allocation failure.");
- ret = MEMORY_E;
- }
- }
- if (ecc_group != 0) {
- if (ret == 0) {
- /* Point is validated by import function. */
- ret = wc_ecc_import_x963(data, len - pubSz, &eccpubkey);
- if (ret != 0) {
- WOLFSSL_MSG("Bad ECC public key.");
- }
- }
- #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
- (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
- !defined(HAVE_SELFTEST)
- if (ret == 0) {
- ret = wc_ecc_set_rng(ecc_kse->key, ssl->rng);
- }
- #endif
- if (ret == 0) {
- outlen = ecc_kse->keyLen;
- PRIVATE_KEY_UNLOCK();
- ret = wc_ecc_shared_secret(ecc_kse->key, &eccpubkey,
- sharedSecret,
- &outlen);
- PRIVATE_KEY_LOCK();
- if (outlen != ecc_kse->keyLen) {
- WOLFSSL_MSG("Data length mismatch.");
- ret = BAD_FUNC_ARG;
- }
- }
- }
- if (ret == 0) {
- ret = wc_KyberKey_DecodePublicKey(kem, data + ecc_kse->pubKeyLen,
- pubSz);
- }
- if (ret == 0) {
- ret = wc_KyberKey_Encapsulate(kem, ciphertext + ecc_kse->pubKeyLen,
- sharedSecret + outlen, ssl->rng);
- if (ret != 0) {
- WOLFSSL_MSG("wc_KyberKey encapsulation failure.");
- }
- }
- if (ret == 0) {
- if (keyShareEntry->ke != NULL) {
- XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- keyShareEntry->ke = sharedSecret;
- keyShareEntry->keLen = outlen + ssSz;
- sharedSecret = NULL;
- XMEMCPY(ciphertext, ecc_kse->pubKey, ecc_kse->pubKeyLen);
- keyShareEntry->pubKey = ciphertext;
- keyShareEntry->pubKeyLen = (word32)(ecc_kse->pubKeyLen + ctSz);
- ciphertext = NULL;
- /* Set namedGroup so wolfSSL_get_curve_name() can function properly on
- * the server side. */
- ssl->namedGroup = keyShareEntry->group;
- }
- TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
- if (sharedSecret != NULL)
- XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_TLSX);
- if (ciphertext != NULL)
- XFREE(ciphertext, ssl->heap, DYNAMIC_TYPE_TLSX);
- wc_ecc_free(&eccpubkey);
- wc_KyberKey_Free(kem);
- return ret;
- }
- #endif /* HAVE_PQC */
- /* 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(const WOLFSSL* ssl, word16 group, word16 len, byte* data,
- KeyShareEntry **kse, TLSX** extensions)
- {
- int ret = 0;
- TLSX* extension;
- KeyShareEntry* keyShareEntry = NULL;
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(*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;
- }
- #ifdef HAVE_PQC
- if (WOLFSSL_NAMED_GROUP_IS_PQC(group) &&
- ssl->options.side == WOLFSSL_SERVER_END) {
- ret = server_generate_pqc_ciphertext((WOLFSSL*)ssl, keyShareEntry, data,
- len);
- if (ret != 0)
- return ret;
- }
- else
- #endif
- 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. Casting to non-const since changes inside are
- * minimal but would require an extensive redesign to refactor. Also
- * this path shouldn't be taken when parsing a ClientHello in stateless
- * mode. */
- ret = TLSX_KeyShare_GenKey((WOLFSSL*)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
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP256K1:
- break;
- #endif
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP256R1:
- break;
- #endif
- #ifdef WOLFSSL_SM2
- case WOLFSSL_ECC_SM2P256V1:
- break;
- #endif /* WOLFSSL_SM2 */
- #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 */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP384R1:
- break;
- #endif
- #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
- #if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP160K1:
- break;
- #endif
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP160R1:
- break;
- #endif
- #ifdef HAVE_ECC_SECPR2
- case WOLFSSL_ECC_SECP160R2:
- break;
- #endif
- #endif
- #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP192K1:
- break;
- #endif
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP192R1:
- break;
- #endif
- #endif
- #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP224K1:
- break;
- #endif
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP224R1:
- break;
- #endif
- #endif
- #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP512R1:
- break;
- #endif
- #endif
- #ifdef HAVE_PQC
- #ifdef WOLFSSL_WC_KYBER
- #ifdef WOLFSSL_KYBER512
- case WOLFSSL_KYBER_LEVEL1:
- #endif
- #ifdef WOLFSSL_KYBER768
- case WOLFSSL_KYBER_LEVEL3:
- #endif
- #ifdef WOLFSSL_KYBER1024
- case WOLFSSL_KYBER_LEVEL5:
- #endif
- break;
- #elif defined(HAVE_LIBOQS)
- case WOLFSSL_KYBER_LEVEL1:
- case WOLFSSL_KYBER_LEVEL3:
- case WOLFSSL_KYBER_LEVEL5:
- case WOLFSSL_P256_KYBER_LEVEL1:
- case WOLFSSL_P384_KYBER_LEVEL3:
- case WOLFSSL_P521_KYBER_LEVEL5:
- {
- int ret;
- int id;
- findEccPqc(NULL, &namedGroup, namedGroup);
- ret = kyber_id2type(namedGroup, &id);
- if (ret == NOT_COMPILED_IN) {
- return 0;
- }
- if (! ext_kyber_enabled(id)) {
- return 0;
- }
- break;
- }
- #elif defined(HAVE_PQM4)
- case WOLFSSL_KYBER_LEVEL1:
- break;
- #endif
- #endif /* HAVE_PQC */
- default:
- return 0;
- }
- return 1;
- }
- 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,
- #if !defined(HAVE_FIPS) && defined(WOLFSSL_SM2)
- WOLFSSL_ECC_SM2P256V1,
- #endif
- #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
- #ifdef WOLFSSL_WC_KYBER
- #ifdef WOLFSSL_KYBER512
- WOLFSSL_KYBER_LEVEL1,
- #endif
- #ifdef WOLFSSL_KYBER768
- WOLFSSL_KYBER_LEVEL3,
- #endif
- #ifdef WOLFSSL_KYBER1024
- WOLFSSL_KYBER_LEVEL5,
- #endif
- #elif defined(HAVE_LIBOQS)
- /* These require a runtime call to TLSX_KeyShare_IsSupported to use */
- WOLFSSL_KYBER_LEVEL1,
- WOLFSSL_KYBER_LEVEL3,
- WOLFSSL_KYBER_LEVEL5,
- WOLFSSL_P256_KYBER_LEVEL1,
- WOLFSSL_P384_KYBER_LEVEL3,
- WOLFSSL_P521_KYBER_LEVEL5,
- #elif defined(HAVE_PQM4)
- WOLFSSL_KYBER_LEVEL1,
- #endif
- WOLFSSL_NAMED_GROUP_INVALID
- };
- #define PREFERRED_GROUP_SZ \
- ((sizeof(preferredGroup)/sizeof(*preferredGroup)) - 1)
- /* -1 for the invalid group */
- /* 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(const WOLFSSL* ssl, int group)
- {
- byte i;
- const word16* groups;
- byte numGroups;
- if (ssl->numGroups == 0) {
- groups = preferredGroup;
- numGroups = PREFERRED_GROUP_SZ;
- }
- else {
- groups = ssl->group;
- numGroups = ssl->numGroups;
- }
- #ifdef HAVE_LIBOQS
- if (!TLSX_KeyShare_IsSupported(group))
- return -1;
- #endif
- for (i = 0; i < numGroups; i++)
- if (groups[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.
- */
- int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions)
- {
- int ret;
- #ifdef HAVE_SUPPORTED_CURVES
- TLSX* extension;
- SupportedCurve* curve = NULL;
- SupportedCurve* preferredCurve = NULL;
- KeyShareEntry* kse = NULL;
- int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
- int rank;
- extension = TLSX_Find(*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;
- if (wolfSSL_curve_is_disabled(ssl, 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) {
- WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
- return BAD_KEY_SHARE_DATA;
- }
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* Check the old key share data list. */
- extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
- if (extension != NULL) {
- kse = (KeyShareEntry*)extension->data;
- /* We should not be computing keys if we are only going to advertise
- * our choice here. */
- if (kse != NULL && kse->lastRet == WC_PENDING_E) {
- WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
- return BAD_KEY_SHARE_DATA;
- }
- }
- #endif
- /* Push new KeyShare extension. This will also free the old one */
- ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- /* Extension got pushed to head */
- extension = *extensions;
- /* Push the selected curve */
- ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, curve->name,
- ssl->heap, &kse);
- if (ret != 0)
- return ret;
- /* Set extension to be in response. */
- extension->resp = 1;
- #else
- (void)ssl;
- WOLFSSL_ERROR_VERBOSE(NOT_COMPILED_IN);
- ret = NOT_COMPILED_IN;
- #endif
- return ret;
- }
- /* Server side KSE processing */
- int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
- byte cipherSuite0, byte cipherSuite, KeyShareEntry** kse, byte* searched)
- {
- TLSX* extension;
- KeyShareEntry* clientKSE = NULL;
- KeyShareEntry* list = NULL;
- KeyShareEntry* preferredKSE = NULL;
- int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
- int rank;
- (void)cipherSuite0;
- (void)cipherSuite;
- if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END)
- return BAD_FUNC_ARG;
- *searched = 0;
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(extensions, TLSX_KEY_SHARE);
- if (extension != NULL)
- list = (KeyShareEntry*)extension->data;
- if (extension && extension->resp == 1) {
- /* Outside of the async case this path should not be taken. */
- int ret = INCOMPLETE_DATA;
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* in async case make sure key generation is finalized */
- KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data;
- if (serverKSE && serverKSE->lastRet == WC_PENDING_E) {
- if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
- *searched = 1;
- ret = TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE);
- }
- #endif
- return ret;
- }
- /* Use server's preference order. */
- for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) {
- if (clientKSE->ke == NULL)
- continue;
- #ifdef WOLFSSL_SM2
- if ((cipherSuite0 == CIPHER_BYTE) &&
- ((cipherSuite == TLS_SM4_GCM_SM3) ||
- (cipherSuite == TLS_SM4_CCM_SM3))) {
- if (clientKSE->group != WOLFSSL_ECC_SM2P256V1) {
- continue;
- }
- }
- else if (clientKSE->group == WOLFSSL_ECC_SM2P256V1) {
- continue;
- }
- #endif
- /* Check consistency now - extensions in any order. */
- if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group, extensions))
- continue;
- if (!WOLFSSL_NAMED_GROUP_IS_FFHDE(clientKSE->group)) {
- /* Check max value supported. */
- if (clientKSE->group > WOLFSSL_ECC_MAX) {
- #ifdef HAVE_PQC
- if (!WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group))
- #endif
- continue;
- }
- if (wolfSSL_curve_is_disabled(ssl, clientKSE->group))
- continue;
- }
- 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;
- }
- }
- *kse = preferredKSE;
- *searched = 1;
- return 0;
- }
- /* Server side KSE processing */
- int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE)
- {
- int ret;
- TLSX* extension;
- KeyShareEntry* serverKSE;
- KeyShareEntry* list = NULL;
- if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END)
- return BAD_FUNC_ARG;
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL)
- return BAD_STATE_E;
- if (clientKSE == NULL) {
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* Not necessarily an error. The key may have already been setup. */
- if (extension != NULL && extension->resp == 1) {
- serverKSE = (KeyShareEntry*)extension->data;
- if (serverKSE != NULL) {
- /* in async case make sure key generation is finalized */
- if (serverKSE->lastRet == WC_PENDING_E)
- return TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE);
- else if (serverKSE->lastRet == 0)
- return 0;
- }
- }
- #endif
- return BAD_FUNC_ARG;
- }
- /* Generate a new key pair except in the case of OQS KEM because we
- * are going to encapsulate and that does not require us to generate a
- * key pair.
- */
- ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE);
- if (ret != 0)
- return ret;
- if (clientKSE->key == NULL) {
- #ifdef HAVE_PQC
- if (WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group)) {
- /* Going to need the public key (AKA ciphertext). */
- serverKSE->pubKey = clientKSE->pubKey;
- clientKSE->pubKey = NULL;
- serverKSE->pubKeyLen = clientKSE->pubKeyLen;
- clientKSE->pubKeyLen = 0;
- }
- else
- #endif
- {
- ret = TLSX_KeyShare_GenKey(ssl, serverKSE);
- }
- /* for async do setup of serverKSE below, but return WC_PENDING_E */
- if (ret != 0
- #ifdef WOLFSSL_ASYNC_CRYPT
- && ret != WC_PENDING_E
- #endif
- ) {
- TLSX_KeyShare_FreeAll(list, ssl->heap);
- return ret;
- }
- }
- else {
- /* transfer buffers to serverKSE */
- serverKSE->key = clientKSE->key;
- clientKSE->key = NULL;
- serverKSE->keyLen = clientKSE->keyLen;
- serverKSE->pubKey = clientKSE->pubKey;
- clientKSE->pubKey = NULL;
- serverKSE->pubKeyLen = clientKSE->pubKeyLen;
- #ifndef NO_DH
- serverKSE->privKey = clientKSE->privKey;
- clientKSE->privKey = NULL;
- #endif
- }
- 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 ret;
- }
- /* Ensure there is a key pair that can be used for key exchange.
- *
- * ssl The SSL/TLS object.
- * doHelloRetry If set to non-zero will do hello_retry
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry)
- {
- int ret;
- KeyShareEntry* clientKSE = NULL;
- byte searched = 0;
- *doHelloRetry = 0;
- ret = TLSX_KeyShare_Choose(ssl, ssl->extensions, ssl->cipher.cipherSuite0,
- ssl->cipher.cipherSuite, &clientKSE, &searched);
- if (ret != 0 || !searched)
- return ret;
- /* No supported group found - send HelloRetryRequest. */
- if (clientKSE == NULL) {
- /* Set KEY_SHARE_ERROR to indicate HelloRetryRequest required. */
- *doHelloRetry = 1;
- return TLSX_KeyShare_SetSupported(ssl, &ssl->extensions);
- }
- return TLSX_KeyShare_Setup(ssl, clientKSE);
- }
- /* 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;
- #ifdef WOLFSSL_ASYNC_CRYPT
- ret = wolfSSL_AsyncPop(ssl, NULL);
- /* Check for error */
- if (ret != WC_NO_PENDING_E && ret < 0) {
- return ret;
- }
- #endif
- /* 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);
- 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) WC_DO_NOTHING
- #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 + (word16)list->binderLen;
- list = list->next;
- }
- *pSz += len;
- return 0;
- }
- if (msgType == server_hello) {
- *pSz += OPAQUE16_LEN;
- return 0;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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) {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- return SANITY_MSG_E;
- }
- /* Length of all binders. */
- len = OPAQUE16_LEN;
- while (list != NULL) {
- len += OPAQUE8_LEN + (word16)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) {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- return SANITY_MSG_E;
- }
- /* Skip length of all binders. */
- lenIdx = idx;
- idx += OPAQUE16_LEN;
- while (current != NULL) {
- /* Binder data length. */
- output[idx++] = (byte)current->binderLen;
- /* Binder data. */
- XMEMCPY(output + idx, current->binder, current->binderLen);
- idx += (word16)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 identities 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 identities. */
- 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) {
- WOLFSSL_ERROR_VERBOSE(BUILD_MSG_ERROR);
- 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 {
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- return SANITY_MSG_E;
- }
- return 0;
- }
- int TLSX_PreSharedKey_Parse_ClientHello(TLSX** extensions, const byte* input,
- word16 length, void* heap)
- {
- int ret;
- word16 len;
- word16 idx = 0;
- TLSX* extension;
- PreSharedKey* list;
- TLSX_Remove(extensions, TLSX_PRE_SHARED_KEY, 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) {
- const 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(extensions, identity, identityLen, age, no_mac,
- 0, 0, 1, NULL, heap);
- 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(*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 += (word16)list->binderLen;
- /* Done with binder entry. */
- len -= OPAQUE8_LEN + (word16)list->binderLen;
- /* Next identity. */
- list = list->next;
- }
- if (list != NULL || len != 0)
- return BUFFER_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, const byte* input,
- word16 length, byte msgType)
- {
- if (msgType == client_hello) {
- return TLSX_PreSharedKey_Parse_ClientHello(&ssl->extensions, input,
- length, ssl->heap);
- }
- if (msgType == server_hello) {
- word16 idx;
- PreSharedKey* list;
- TLSX* extension;
- /* 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) {
- WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
- 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) {
- WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
- return PSK_KEY_ERROR;
- }
- }
- #endif
- return 0;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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, const 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 + NULL_TERM_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;
- /* Use a NULL terminator in case it is a C string */
- psk->identity[psk->identityLen] = '\0';
- /* 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
- #ifdef WOLFSSL_SM3
- case sm3_mac:
- return WC_SM3_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 cipher suite to use.
- * cipherSuite The second byte of the cipher suite 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(TLSX** extensions, const byte* identity, word16 len,
- word32 age, byte hmac, byte cipherSuite0,
- byte cipherSuite, byte resumption,
- PreSharedKey **preSharedKey, void* heap)
- {
- int ret = 0;
- TLSX* extension;
- PreSharedKey* psk = NULL;
- /* Find the pre-shared key extension if it exists. */
- extension = TLSX_Find(*extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL) {
- /* Push new pre-shared key extension. */
- ret = TLSX_Push(extensions, TLSX_PRE_SHARED_KEY, NULL, heap);
- if (ret != 0)
- return ret;
- extension = TLSX_Find(*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, 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) WC_DO_NOTHING
- #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;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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* */
- word16 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] = (byte)(idx - OPAQUE8_LEN);
- *pSz += idx;
- return 0;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- return SANITY_MSG_E;
- }
- int TLSX_PskKeyModes_Parse_Modes(const byte* input, word16 length, byte msgType,
- byte* modes)
- {
- if (msgType == client_hello) {
- /* Format: Len | Modes* */
- int idx = 0;
- word16 len;
- *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--;
- }
- return 0;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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, const byte* input, word16 length,
- byte msgType)
- {
- int ret;
- byte modes;
- ret = TLSX_PskKeyModes_Parse_Modes(input, length, msgType, &modes);
- if (ret == 0)
- ret = TLSX_PskKeyModes_Use(ssl, modes);
- if (ret != 0) {
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- return ret;
- }
- /* 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_PskKeyModes_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;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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, const 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;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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;
- WOLFSSL_ERROR_VERBOSE(ret);
- }
- 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;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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, const byte* input, word16 length,
- byte msgType)
- {
- WOLFSSL_ENTER("TLSX_EarlyData_Parse");
- if (msgType == client_hello) {
- if (length != 0)
- return BUFFER_E;
- if (ssl->earlyData == expecting_early_data) {
- if (ssl->options.maxEarlyDataSz != 0)
- ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_ACCEPTED;
- else
- ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_REJECTED;
- return TLSX_EarlyData_Use(ssl, 0, 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) {
- WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
- return PSK_KEY_ERROR;
- }
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- /* the extension from server comes in */
- ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_ACCEPTED;
- }
- return TLSX_EarlyData_Use(ssl, 1, 1);
- }
- if (msgType == session_ticket) {
- word32 maxSz;
- if (length != OPAQUE32_LEN)
- return BUFFER_E;
- ato32(input, &maxSz);
- ssl->session->maxEarlyDataSz = maxSz;
- return 0;
- }
- WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
- 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.
- * is_response if this extension is part of a response
- * returns 0 on success and other values indicate failure.
- */
- int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 maxSz, int is_response)
- {
- 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 = is_response;
- /* In QUIC, earlydata size is either 0 or 0xffffffff.
- * Override any size between, possibly left from our initial value */
- extension->val = (WOLFSSL_IS_QUIC(ssl) && is_response && maxSz > 0) ?
- WOLFSSL_MAX_32BIT : 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
- /******************************************************************************/
- /* QUIC transport parameter extension */
- /******************************************************************************/
- #ifdef WOLFSSL_QUIC
- static word16 TLSX_QuicTP_GetSize(TLSX* extension)
- {
- const QuicTransportParam *tp = (QuicTransportParam*)extension->data;
- return tp ? tp->len : 0;
- }
- int TLSX_QuicTP_Use(WOLFSSL* ssl, TLSX_Type ext_type, int is_response)
- {
- int ret = 0;
- TLSX* extension;
- WOLFSSL_ENTER("TLSX_QuicTP_Use");
- if (ssl->quic.transport_local == NULL) {
- /* RFC9000, ch 7.3: "An endpoint MUST treat the absence of [...]
- * from either endpoint [...] as a connection error of type
- * TRANSPORT_PARAMETER_ERROR."
- */
- ret = QUIC_TP_MISSING_E;
- goto cleanup;
- }
- extension = TLSX_Find(ssl->extensions, ext_type);
- if (extension == NULL) {
- ret = TLSX_Push(&ssl->extensions, ext_type, NULL, ssl->heap);
- if (ret != 0)
- goto cleanup;
- extension = TLSX_Find(ssl->extensions, ext_type);
- if (extension == NULL) {
- ret = MEMORY_E;
- goto cleanup;
- }
- }
- if (extension->data) {
- QuicTransportParam_free((QuicTransportParam*)extension->data, ssl->heap);
- extension->data = NULL;
- }
- extension->resp = is_response;
- extension->data = (void*)QuicTransportParam_dup(ssl->quic.transport_local, ssl->heap);
- if (!extension->data) {
- ret = MEMORY_E;
- goto cleanup;
- }
- cleanup:
- WOLFSSL_LEAVE("TLSX_QuicTP_Use", ret);
- return ret;
- }
- static word16 TLSX_QuicTP_Write(QuicTransportParam *tp, byte* output)
- {
- word16 len = 0;
- WOLFSSL_ENTER("TLSX_QuicTP_Write");
- if (tp && tp->len) {
- XMEMCPY(output, tp->data, tp->len);
- len = tp->len;
- }
- WOLFSSL_LEAVE("TLSX_QuicTP_Write", len);
- return len;
- }
- static int TLSX_QuicTP_Parse(WOLFSSL *ssl, const byte *input, size_t len, int ext_type, int msgType)
- {
- const QuicTransportParam *tp, **ptp;
- (void)msgType;
- tp = QuicTransportParam_new(input, len, ssl->heap);
- if (!tp) {
- return MEMORY_E;
- }
- ptp = (ext_type == TLSX_KEY_QUIC_TP_PARAMS_DRAFT) ?
- &ssl->quic.transport_peer_draft : &ssl->quic.transport_peer;
- if (*ptp) {
- QTP_FREE(*ptp, ssl->heap);
- }
- *ptp = tp;
- return 0;
- }
- #define QTP_GET_SIZE TLSX_QuicTP_GetSize
- #define QTP_USE TLSX_QuicTP_Use
- #define QTP_WRITE TLSX_QuicTP_Write
- #define QTP_PARSE TLSX_QuicTP_Parse
- #endif /* WOLFSSL_QUIC */
- #if defined(WOLFSSL_DTLS_CID)
- #define CID_GET_SIZE TLSX_ConnectionID_GetSize
- #define CID_WRITE TLSX_ConnectionID_Write
- #define CID_PARSE TLSX_ConnectionID_Parse
- #define CID_FREE TLSX_ConnectionID_Free
- #else
- #define CID_GET_SIZE(a) 0
- #define CID_WRITE(a, b) 0
- #define CID_PARSE(a, b, c, d) 0
- #define CID_FREE(a, b) 0
- #endif /* defined(WOLFSSL_DTLS_CID) */
- #if defined(HAVE_RPK)
- /******************************************************************************/
- /* Client_Certificate_Type extension */
- /******************************************************************************/
- /* return 1 if specified type is included in the given list, otherwise 0 */
- static int IsCertTypeListed(byte type, byte cnt, const byte* list)
- {
- int ret = 0;
- int i;
- if (cnt == 0 || list == NULL)
- return ret;
- if (cnt > 0 && cnt <= MAX_CLIENT_CERT_TYPE_CNT) {
- for (i = 0; i < cnt; i++) {
- if (list[i] == type)
- return 1;
- }
- }
- return 0;
- }
- /* Search both arrays from above to find a common value between the two given
- * arrays(a and b). return 1 if it finds a common value, otherwise return 0.
- */
- static int GetCommonItem(const byte* a, byte aLen, const byte* b, byte bLen,
- byte* type)
- {
- int i, j;
- if (a == NULL || b == NULL)
- return 0;
- for (i = 0; i < aLen; i++) {
- for (j = 0; j < bLen; j++) {
- if (a[i] == b[j]) {
- *type = a[i];
- return 1;
- }
- }
- }
- return 0;
- }
- /* Creates a "client certificate type" extension if necessary.
- * Returns 0 if no error occurred, negative value otherwise.
- * A return of 0, it does not indicae that the extension was created.
- */
- static int TLSX_ClientCertificateType_Use(WOLFSSL* ssl, byte isServer)
- {
- int ret = 0;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (isServer) {
- /* [in server side]
- */
- if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
- ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
- ssl->options.rpkConfig.preferred_ClientCertTypes)) {
- WOLFSSL_MSG("Adding Client Certificate Type extension");
- ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE, ssl,
- ssl->heap);
- if (ret == 0) {
- TLSX_SetResponse(ssl, TLSX_CLIENT_CERTIFICATE_TYPE);
- }
- }
- }
- else {
- /* [in client side]
- * This extension MUST be omitted from the ClientHello unless the RPK
- * certificate is preferred by the user and actually loaded.
- */
- if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
- ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
- ssl->options.rpkConfig.preferred_ClientCertTypes)) {
- if (ssl->options.rpkState.isRPKLoaded) {
- ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
- ssl->options.rpkState.sending_ClientCertTypes[0] =
- WOLFSSL_CERT_TYPE_RPK;
- /* Push new client_certificate_type extension. */
- WOLFSSL_MSG("Adding Client Certificate Type extension");
- ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE,
- ssl, ssl->heap);
- }
- else {
- WOLFSSL_MSG("Willing to use RPK cert but not loaded it");
- }
- }
- else {
- WOLFSSL_MSG("No will to use RPK cert");
- }
- }
- return ret;
- }
- /* Parse a "client certificate type" extension received from peer.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_ClientCertificateType_Parse(WOLFSSL* ssl, const byte* input,
- word16 length, byte msgType)
- {
- byte typeCnt;
- int idx = 0;
- int ret = 0;
- int i;
- int populate = 0;
- byte cmnType;
- if (msgType == client_hello) {
- /* [parse ClientHello in server end]
- * case 1) if peer verify is disabled, this extension must be omitted
- * from ServerHello.
- * case 2) if user have not set his preference, find X509 in parsed
- * result, then populate "Client Certificate Type" extension.
- * case 3) if user have not set his preference and X509 isn't included
- * in parsed result, send "unsupported certificate" alert.
- * case 4) if user have set his preference, find a common cert type
- * in users preference and received cert types.
- * case 5) if user have set his preference, but no common cert type
- * found.
- */
- /* case 1 */
- if (ssl->options.verifyNone) {
- return ret;
- }
- /* parse extension */
- if (length < OPAQUE8_LEN)
- return BUFFER_E;
- typeCnt = input[idx];
- if (typeCnt > MAX_CLIENT_CERT_TYPE_CNT)
- return BUFFER_E;
- if ((typeCnt + 1) * OPAQUE8_LEN != length){
- return BUFFER_E;
- }
- ssl->options.rpkState.received_ClientCertTypeCnt = input[idx];
- idx += OPAQUE8_LEN;
- for (i = 0; i < typeCnt; i++) {
- ssl->options.rpkState.received_ClientCertTypes[i] = input[idx];
- idx += OPAQUE8_LEN;
- }
- if (ssl->options.rpkConfig.preferred_ClientCertTypeCnt == 0) {
- /* case 2 */
- if (IsCertTypeListed(WOLFSSL_CERT_TYPE_X509,
- ssl->options.rpkState.received_ClientCertTypeCnt,
- ssl->options.rpkState.received_ClientCertTypes)) {
- ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
- ssl->options.rpkState.sending_ClientCertTypes[0] =
- WOLFSSL_CERT_TYPE_X509;
- populate = 1;
- }
- /* case 3 */
- else {
- WOLFSSL_MSG("No common cert type found in client_certificate_type ext");
- SendAlert(ssl, alert_fatal, unsupported_certificate);
- return UNSUPPORTED_CERTIFICATE;
- }
- }
- else if (ssl->options.rpkConfig.preferred_ClientCertTypeCnt > 0) {
- /* case 4 */
- if (GetCommonItem(
- ssl->options.rpkConfig.preferred_ClientCertTypes,
- ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
- ssl->options.rpkState.received_ClientCertTypes,
- ssl->options.rpkState.received_ClientCertTypeCnt,
- &cmnType)) {
- ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
- ssl->options.rpkState.sending_ClientCertTypes[0] = cmnType;
- populate = 1;
- }
- /* case 5 */
- else {
- WOLFSSL_MSG("No common cert type found in client_certificate_type ext");
- SendAlert(ssl, alert_fatal, unsupported_certificate);
- return UNSUPPORTED_CERTIFICATE;
- }
- }
- /* populate client_certificate_type extension */
- if (populate) {
- WOLFSSL_MSG("Adding Client Certificate Type extension");
- ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE, ssl,
- ssl->heap);
- if (ret == 0) {
- TLSX_SetResponse(ssl, TLSX_CLIENT_CERTIFICATE_TYPE);
- }
- }
- }
- else if (msgType == server_hello || msgType == encrypted_extensions) {
- /* parse it in client side */
- if (length == 1) {
- ssl->options.rpkState.received_ClientCertTypeCnt = 1;
- ssl->options.rpkState.received_ClientCertTypes[0] = *input;
- }
- else {
- return BUFFER_E;
- }
- }
- return ret;
- }
- /* Write out the "client certificate type" extension data into the given buffer.
- * return the size wrote in the buffer on success, negative value on error.
- */
- static word16 TLSX_ClientCertificateType_Write(void* data, byte* output,
- byte msgType)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- word16 idx = 0;
- byte cnt = 0;
- int i;
- /* skip to write extension if count is zero */
- cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;
- if (cnt == 0)
- return 0;
- if (msgType == client_hello) {
- /* client side */
- *(output + idx) = cnt;
- idx += OPAQUE8_LEN;
- for (i = 0; i < cnt; i++) {
- *(output + idx) = ssl->options.rpkState.sending_ClientCertTypes[i];
- idx += OPAQUE8_LEN;
- }
- return idx;
- }
- else if (msgType == server_hello || msgType == encrypted_extensions) {
- /* sever side */
- if (cnt == 1) {
- *(output + idx) = ssl->options.rpkState.sending_ClientCertTypes[0];
- idx += OPAQUE8_LEN;
- }
- }
- return idx;
- }
- /* Calculate then return the size of the "client certificate type" extension
- * data.
- * return the extension data size on success, negative value on error.
- */
- static int TLSX_ClientCertificateType_GetSize(WOLFSSL* ssl, byte msgType)
- {
- int ret = 0;
- byte cnt;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (msgType == client_hello) {
- /* client side */
- cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;
- ret = (int)(OPAQUE8_LEN + cnt * OPAQUE8_LEN);
- }
- else if (msgType == server_hello || msgType == encrypted_extensions) {
- /* sever side */
- cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;/* must be one */
- ret = OPAQUE8_LEN;
- }
- else {
- return SANITY_MSG_E;
- }
- return ret;
- }
- #define CCT_GET_SIZE TLSX_ClientCertificateType_GetSize
- #define CCT_WRITE TLSX_ClientCertificateType_Write
- #define CCT_PARSE TLSX_ClientCertificateType_Parse
- #else
- #define CCT_GET_SIZE(a) 0
- #define CCT_WRITE(a, b) 0
- #define CCT_PARSE(a, b, c, d) 0
- #endif /* HAVE_RPK */
- #if defined(HAVE_RPK)
- /******************************************************************************/
- /* Server_Certificate_Type extension */
- /******************************************************************************/
- /* Creates a "server certificate type" extension if necessary.
- * Returns 0 if no error occurred, negative value otherwise.
- * A return of 0, it does not indicae that the extension was created.
- */
- static int TLSX_ServerCertificateType_Use(WOLFSSL* ssl, byte isServer)
- {
- int ret = 0;
- byte ctype;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (isServer) {
- /* [in server side] */
- /* find common cert type to both end */
- if (GetCommonItem(
- ssl->options.rpkConfig.preferred_ServerCertTypes,
- ssl->options.rpkConfig.preferred_ServerCertTypeCnt,
- ssl->options.rpkState.received_ServerCertTypes,
- ssl->options.rpkState.received_ServerCertTypeCnt,
- &ctype)) {
- ssl->options.rpkState.sending_ServerCertTypeCnt = 1;
- ssl->options.rpkState.sending_ServerCertTypes[0] = ctype;
- /* Push new server_certificate_type extension. */
- WOLFSSL_MSG("Adding Server Certificate Type extension");
- ret = TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE, ssl,
- ssl->heap);
- if (ret == 0) {
- TLSX_SetResponse(ssl, TLSX_SERVER_CERTIFICATE_TYPE);
- }
- }
- else {
- /* no common cert type found */
- WOLFSSL_MSG("No common cert type found in server_certificate_type ext");
- SendAlert(ssl, alert_fatal, unsupported_certificate);
- ret = UNSUPPORTED_CERTIFICATE;
- }
- }
- else {
- /* [in client side] */
- if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
- ssl->options.rpkConfig.preferred_ServerCertTypeCnt,
- ssl->options.rpkConfig.preferred_ServerCertTypes)) {
- ssl->options.rpkState.sending_ServerCertTypeCnt =
- ssl->options.rpkConfig.preferred_ServerCertTypeCnt;
- XMEMCPY(ssl->options.rpkState.sending_ServerCertTypes,
- ssl->options.rpkConfig.preferred_ServerCertTypes,
- ssl->options.rpkConfig.preferred_ServerCertTypeCnt);
- /* Push new server_certificate_type extension. */
- WOLFSSL_MSG("Adding Server Certificate Type extension");
- ret = TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE, ssl,
- ssl->heap);
- }
- else {
- WOLFSSL_MSG("No will to accept RPK cert");
- }
- }
- return ret;
- }
- /* Parse a "server certificate type" extension received from peer.
- * returns 0 on success and other values indicate failure.
- */
- static int TLSX_ServerCertificateType_Parse(WOLFSSL* ssl, const byte* input,
- word16 length, byte msgType)
- {
- byte typeCnt;
- int idx = 0;
- int ret = 0;
- int i;
- if (msgType == client_hello) {
- /* in server side */
- if (length < OPAQUE8_LEN)
- return BUFFER_E;
- typeCnt = input[idx];
- if (typeCnt > MAX_SERVER_CERT_TYPE_CNT)
- return BUFFER_E;
- if ((typeCnt + 1) * OPAQUE8_LEN != length){
- return BUFFER_E;
- }
- ssl->options.rpkState.received_ServerCertTypeCnt = input[idx];
- idx += OPAQUE8_LEN;
- for (i = 0; i < typeCnt; i++) {
- ssl->options.rpkState.received_ServerCertTypes[i] = input[idx];
- idx += OPAQUE8_LEN;
- }
- ret = TLSX_ServerCertificateType_Use(ssl, 1);
- if (ret == 0) {
- TLSX_SetResponse(ssl, TLSX_SERVER_CERTIFICATE_TYPE);
- }
- }
- else if (msgType == server_hello || msgType == encrypted_extensions) {
- /* in client side */
- if (length != 1) /* length slould be 1 */
- return BUFFER_E;
- ssl->options.rpkState.received_ServerCertTypeCnt = 1;
- ssl->options.rpkState.received_ServerCertTypes[0] = *input;
- }
- return 0;
- }
- /* Write out the "server certificate type" extension data into the given buffer.
- * return the size wrote in the buffer on success, negative value on error.
- */
- static word16 TLSX_ServerCertificateType_Write(void* data, byte* output,
- byte msgType)
- {
- WOLFSSL* ssl = (WOLFSSL*)data;
- word16 idx = 0;
- int cnt = 0;
- int i;
- /* skip to write extension if count is zero */
- cnt = ssl->options.rpkState.sending_ServerCertTypeCnt;
- if (cnt == 0)
- return 0;
- if (msgType == client_hello) {
- /* in client side */
- *(output + idx) = cnt;
- idx += OPAQUE8_LEN;
- for (i = 0; i < cnt; i++) {
- *(output + idx) = ssl->options.rpkState.sending_ServerCertTypes[i];
- idx += OPAQUE8_LEN;
- }
- }
- else if (msgType == server_hello || msgType == encrypted_extensions) {
- /* in server side */
- /* ensure cnt is one */
- if (cnt != 1)
- return 0;
- *(output + idx) = ssl->options.rpkState.sending_ServerCertTypes[0];
- idx += OPAQUE8_LEN;
- }
- return idx;
- }
- /* Calculate then return the size of the "server certificate type" extension
- * data.
- * return the extension data size on success, negative value on error.
- */
- static int TLSX_ServerCertificateType_GetSize(WOLFSSL* ssl, byte msgType)
- {
- int ret = 0;
- int cnt;
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (msgType == client_hello) {
- /* in clent side */
- cnt = ssl->options.rpkState.sending_ServerCertTypeCnt;
- if (cnt > 0) {
- ret = (int)(OPAQUE8_LEN + cnt * OPAQUE8_LEN);
- }
- }
- else if (msgType == server_hello || msgType == encrypted_extensions) {
- /* in server side */
- ret = (int)OPAQUE8_LEN;
- }
- else {
- return SANITY_MSG_E;
- }
- return ret;
- }
- #define SCT_GET_SIZE TLSX_ServerCertificateType_GetSize
- #define SCT_WRITE TLSX_ServerCertificateType_Write
- #define SCT_PARSE TLSX_ServerCertificateType_Parse
- #else
- #define SCT_GET_SIZE(a) 0
- #define SCT_WRITE(a, b) 0
- #define SCT_PARSE(a, b, c, d) 0
- #endif /* HAVE_RPK */
- /******************************************************************************/
- /* 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;
- TLSX** next;
- if (list == NULL)
- return;
- extension = *list;
- 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);
- }
- }
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- #define GREASE_ECH_SIZE 160
- #define MAX_PUBLIC_NAME_SZ 256
- #define TLS_INFO_CONST_STRING "tls ech"
- #define TLS_INFO_CONST_STRING_SZ 7
- /* return status after setting up ech to write a grease ech */
- static int TLSX_GreaseECH_Use(TLSX** extensions, void* heap, WC_RNG* rng)
- {
- int ret = 0;
- WOLFSSL_ECH* ech;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- ech = (WOLFSSL_ECH*)XMALLOC(sizeof(WOLFSSL_ECH), heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (ech == NULL)
- return MEMORY_E;
- ForceZero(ech, sizeof(WOLFSSL_ECH));
- ech->state = ECH_WRITE_GREASE;
- /* 0 for outer */
- ech->type = ECH_TYPE_OUTER;
- /* kemId */
- ech->kemId = DHKEM_X25519_HKDF_SHA256;
- /* cipherSuite kdf */
- ech->cipherSuite.kdfId = HKDF_SHA256;
- /* cipherSuite aead */
- ech->cipherSuite.aeadId = HPKE_AES_128_GCM;
- /* random configId */
- ret = wc_RNG_GenerateByte(rng, &(ech->configId));
- /* curve25519 encLen */
- ech->encLen = DHKEM_X25519_ENC_LEN;
- if (ret == 0)
- ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
- if (ret != 0) {
- XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- return ret;
- }
- /* return status after setting up ech to write real ech */
- static int TLSX_ECH_Use(WOLFSSL_EchConfig* echConfig, TLSX** extensions,
- void* heap, WC_RNG* rng)
- {
- int ret = 0;
- int suiteIndex;
- WOLFSSL_ECH* ech;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- /* find a supported cipher suite */
- suiteIndex = EchConfigGetSupportedCipherSuite(echConfig);
- if (suiteIndex < 0)
- return suiteIndex;
- ech = (WOLFSSL_ECH*)XMALLOC(sizeof(WOLFSSL_ECH), heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (ech == NULL)
- return MEMORY_E;
- ForceZero(ech, sizeof(WOLFSSL_ECH));
- ech->state = ECH_WRITE_REAL;
- ech->echConfig = echConfig;
- /* 0 for outer */
- ech->type = ECH_TYPE_OUTER;
- /* kemId */
- ech->kemId = echConfig->kemId;
- /* cipherSuite kdf */
- ech->cipherSuite.kdfId = echConfig->cipherSuites[suiteIndex].kdfId;
- /* cipherSuite aead */
- ech->cipherSuite.aeadId = echConfig->cipherSuites[suiteIndex].aeadId;
- /* configId */
- ech->configId = echConfig->configId;
- /* encLen */
- switch (echConfig->kemId)
- {
- case DHKEM_P256_HKDF_SHA256:
- ech->encLen = DHKEM_P256_ENC_LEN;
- break;
- case DHKEM_P384_HKDF_SHA384:
- ech->encLen = DHKEM_P384_ENC_LEN;
- break;
- case DHKEM_P521_HKDF_SHA512:
- ech->encLen = DHKEM_P521_ENC_LEN;
- break;
- case DHKEM_X25519_HKDF_SHA256:
- ech->encLen = DHKEM_X25519_ENC_LEN;
- break;
- case DHKEM_X448_HKDF_SHA512:
- ech->encLen = DHKEM_X448_ENC_LEN;
- break;
- }
- /* setup hpke */
- ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ech->hpke == NULL) {
- XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
- ret = wc_HpkeInit(ech->hpke, ech->kemId, ech->cipherSuite.kdfId,
- ech->cipherSuite.aeadId, heap);
- /* setup the ephemeralKey */
- if (ret == 0)
- ret = wc_HpkeGenerateKeyPair(ech->hpke, &ech->ephemeralKey, rng);
- if (ret == 0)
- ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
- if (ret != 0) {
- XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- return ret;
- }
- /* return status after setting up ech to read and decrypt */
- static int TLSX_ServerECH_Use(TLSX** extensions, void* heap,
- WOLFSSL_EchConfig* configs)
- {
- int ret;
- WOLFSSL_ECH* ech;
- TLSX* echX;
- if (extensions == NULL)
- return BAD_FUNC_ARG;
- /* if we already have ech don't override it */
- echX = TLSX_Find(*extensions, TLSX_ECH);
- if (echX != NULL)
- return 0;
- ech = (WOLFSSL_ECH*)XMALLOC(sizeof(WOLFSSL_ECH), heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (ech == NULL)
- return MEMORY_E;
- ForceZero(ech, sizeof(WOLFSSL_ECH));
- ech->state = ECH_WRITE_NONE;
- /* 0 for outer */
- ech->type = ECH_TYPE_OUTER;
- ech->echConfig = configs;
- /* setup the rest of the settings when we receive ech from the client */
- ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
- if (ret != 0)
- XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- /* return length after writing the ech */
- static int TLSX_ECH_Write(WOLFSSL_ECH* ech, byte* writeBuf, word16* offset)
- {
- int ret = 0;
- int rngRet = -1;
- word32 configsLen = 0;
- void* ephemeralKey = NULL;
- byte* writeBuf_p = writeBuf;
- #ifdef WOLFSSL_SMALL_STACK
- Hpke* hpke = NULL;
- WC_RNG* rng = NULL;
- #else
- Hpke hpke[1];
- WC_RNG rng[1];
- #endif
- WOLFSSL_MSG("TLSX_ECH_Write");
- if (ech->state == ECH_WRITE_NONE || ech->state == ECH_PARSED_INTERNAL)
- return 0;
- if (ech->state == ECH_WRITE_RETRY_CONFIGS) {
- /* get size then write */
- ret = GetEchConfigsEx(ech->echConfig, NULL, &configsLen);
- if (ret != LENGTH_ONLY_E)
- return ret;
- ret = GetEchConfigsEx(ech->echConfig, writeBuf, &configsLen);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- *offset += configsLen;
- return 0;
- }
- #ifdef WOLFSSL_SMALL_STACK
- hpke = (Hpke*)XMALLOC(sizeof(Hpke), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (hpke == NULL)
- return MEMORY_E;
- rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (rng == NULL) {
- XFREE(hpke, NULL, DYNAMIC_TYPE_RNG);
- return MEMORY_E;
- }
- #endif
- /* type */
- *writeBuf_p = ech->type;
- writeBuf_p += sizeof(ech->type);
- /* outer has body, inner does not */
- if (ech->type == ECH_TYPE_OUTER) {
- /* kdfId */
- c16toa(ech->cipherSuite.kdfId, writeBuf_p);
- writeBuf_p += sizeof(ech->cipherSuite.kdfId);
- /* aeadId */
- c16toa(ech->cipherSuite.aeadId, writeBuf_p);
- writeBuf_p += sizeof(ech->cipherSuite.aeadId);
- /* configId */
- *writeBuf_p = ech->configId;
- writeBuf_p += sizeof(ech->configId);
- /* encLen */
- c16toa(ech->encLen, writeBuf_p);
- writeBuf_p += 2;
- if (ech->state == ECH_WRITE_GREASE) {
- /* hpke init */
- ret = wc_HpkeInit(hpke, ech->kemId, ech->cipherSuite.kdfId,
- ech->cipherSuite.aeadId, NULL);
- if (ret == 0)
- rngRet = ret = wc_InitRng(rng);
- /* create the ephemeralKey */
- if (ret == 0)
- ret = wc_HpkeGenerateKeyPair(hpke, &ephemeralKey, rng);
- /* enc */
- if (ret == 0) {
- ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, writeBuf_p,
- &ech->encLen);
- writeBuf_p += ech->encLen;
- }
- if (ret == 0) {
- /* innerClientHelloLen */
- c16toa(GREASE_ECH_SIZE + ((writeBuf_p + 2 - writeBuf) % 32),
- writeBuf_p);
- writeBuf_p += 2;
- /* innerClientHello */
- ret = wc_RNG_GenerateBlock(rng, writeBuf_p, GREASE_ECH_SIZE +
- ((writeBuf_p - writeBuf) % 32));
- writeBuf_p += GREASE_ECH_SIZE + ((writeBuf_p - writeBuf) % 32);
- }
- if (rngRet == 0)
- wc_FreeRng(rng);
- if (ephemeralKey != NULL)
- wc_HpkeFreeKey(hpke, hpke->kem, ephemeralKey, hpke->heap);
- }
- else {
- /* write enc to writeBuf_p */
- ret = wc_HpkeSerializePublicKey(ech->hpke, ech->ephemeralKey,
- writeBuf_p, &ech->encLen);
- writeBuf_p += ech->encLen;
- /* innerClientHelloLen */
- c16toa(ech->innerClientHelloLen, writeBuf_p);
- writeBuf_p += 2;
- /* set payload offset for when we finalize */
- ech->outerClientPayload = writeBuf_p;
- /* write zeros for payload */
- XMEMSET(writeBuf_p, 0, ech->innerClientHelloLen);
- writeBuf_p += ech->innerClientHelloLen;
- }
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(hpke, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
- if (ret == 0)
- *offset += (writeBuf_p - writeBuf);
- return ret;
- }
- /* return the size needed for the ech extension */
- static int TLSX_ECH_GetSize(WOLFSSL_ECH* ech)
- {
- int ret;
- word32 size;
- if (ech->state == ECH_WRITE_GREASE) {
- size = sizeof(ech->type) + sizeof(ech->cipherSuite) +
- sizeof(ech->configId) + sizeof(word16) + ech->encLen +
- sizeof(word16);
- size += GREASE_ECH_SIZE + (size % 32);
- }
- else if (ech->state == ECH_WRITE_NONE ||
- ech->state == ECH_PARSED_INTERNAL) {
- size = 0;
- }
- else if (ech->state == ECH_WRITE_RETRY_CONFIGS) {
- /* get the size of the raw configs */
- ret = GetEchConfigsEx(ech->echConfig, NULL, &size);
- if (ret != LENGTH_ONLY_E)
- return ret;
- }
- else if (ech->type == ECH_TYPE_INNER)
- {
- size = sizeof(ech->type);
- }
- else
- {
- size = sizeof(ech->type) + sizeof(ech->cipherSuite) +
- sizeof(ech->configId) + sizeof(word16) + ech->encLen +
- sizeof(word16) + ech->innerClientHelloLen;
- }
- return (int)size;
- }
- /* return status after attempting to open the hpke encrypted ech extension, if
- * successful the inner client hello will be stored in
- * ech->innerClientHelloLen */
- static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
- byte* aad, word32 aadLen, void* heap)
- {
- int ret = 0;
- int expectedEncLen;
- int i;
- word32 rawConfigLen = 0;
- byte* info = NULL;
- word32 infoLen = 0;
- if (ech == NULL || echConfig == NULL || aad == NULL)
- return BAD_FUNC_ARG;
- /* verify the kem and key len */
- switch (echConfig->kemId)
- {
- case DHKEM_P256_HKDF_SHA256:
- expectedEncLen = DHKEM_P256_ENC_LEN;
- break;
- case DHKEM_P384_HKDF_SHA384:
- expectedEncLen = DHKEM_P384_ENC_LEN;
- break;
- case DHKEM_P521_HKDF_SHA512:
- expectedEncLen = DHKEM_P521_ENC_LEN;
- break;
- case DHKEM_X25519_HKDF_SHA256:
- expectedEncLen = DHKEM_X25519_ENC_LEN;
- break;
- case DHKEM_X448_HKDF_SHA512:
- expectedEncLen = DHKEM_X448_ENC_LEN;
- break;
- default:
- expectedEncLen = 0;
- break;
- }
- if (expectedEncLen != ech->encLen)
- return BAD_FUNC_ARG;
- /* verify the cipher suite */
- for (i = 0; i < echConfig->numCipherSuites; i++) {
- if (echConfig->cipherSuites[i].kdfId == ech->cipherSuite.kdfId &&
- echConfig->cipherSuites[i].aeadId == ech->cipherSuite.aeadId) {
- break;
- }
- }
- if (i >= echConfig->numCipherSuites) {
- return BAD_FUNC_ARG;
- }
- ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ech->hpke == NULL)
- return MEMORY_E;
- ret = wc_HpkeInit(ech->hpke, echConfig->kemId, ech->cipherSuite.kdfId,
- ech->cipherSuite.aeadId, heap);
- /* get the rawConfigLen */
- if (ret == 0)
- ret = GetEchConfig(echConfig, NULL, &rawConfigLen);
- if (ret == LENGTH_ONLY_E)
- ret = 0;
- /* create info */
- if (ret == 0) {
- infoLen = TLS_INFO_CONST_STRING_SZ + 1 + rawConfigLen;
- info = (byte*)XMALLOC(infoLen, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL)
- ret = MEMORY_E;
- else {
- XMEMCPY(info, (byte*)TLS_INFO_CONST_STRING,
- TLS_INFO_CONST_STRING_SZ + 1);
- ret = GetEchConfig(echConfig, info +
- TLS_INFO_CONST_STRING_SZ + 1, &rawConfigLen);
- }
- }
- /* decrypt the ech payload */
- if (ret == 0)
- ret = wc_HpkeOpenBase(ech->hpke, echConfig->receiverPrivkey, ech->enc,
- ech->encLen, info, infoLen, aad, aadLen, ech->outerClientPayload,
- ech->innerClientHelloLen,
- ech->innerClientHello + HANDSHAKE_HEADER_SZ);
- if (ret != 0) {
- XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
- ech->hpke = NULL;
- }
- if (info != NULL)
- XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
- /* parse the ech extension, if internal update ech->state and return, if
- * external attempt to extract the inner client_hello, return the status */
- static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
- byte msgType)
- {
- int ret = 0;
- int i;
- TLSX* echX;
- WOLFSSL_ECH* ech;
- WOLFSSL_EchConfig* echConfig;
- byte* aadCopy;
- byte* readBuf_p = (byte*)readBuf;
- WOLFSSL_MSG("TLSX_ECH_Parse");
- if (size == 0)
- return BAD_FUNC_ARG;
- if (msgType == encrypted_extensions) {
- ret = wolfSSL_SetEchConfigs(ssl, readBuf, size);
- if (ret == WOLFSSL_SUCCESS)
- ret = 0;
- }
- else if (msgType == client_hello && ssl->ctx->echConfigs != NULL) {
- echX = TLSX_Find(ssl->extensions, TLSX_ECH);
- if (echX == NULL)
- return BAD_FUNC_ARG;
- ech = (WOLFSSL_ECH*)echX->data;
- /* read the ech parameters before the payload */
- ech->type = *readBuf_p;
- readBuf_p++;
- if (ech->type == ECH_TYPE_INNER) {
- ech->state = ECH_PARSED_INTERNAL;
- return 0;
- }
- /* technically the payload would only be 1 byte at this length */
- if (size < 11 + ech->encLen)
- return BAD_FUNC_ARG;
- ato16(readBuf_p, &ech->cipherSuite.kdfId);
- readBuf_p += 2;
- ato16(readBuf_p, &ech->cipherSuite.aeadId);
- readBuf_p += 2;
- ech->configId = *readBuf_p;
- readBuf_p++;
- ato16(readBuf_p, &ech->encLen);
- readBuf_p += 2;
- if (ech->encLen > HPKE_Npk_MAX)
- return BAD_FUNC_ARG;
- XMEMCPY(ech->enc, readBuf_p, ech->encLen);
- readBuf_p += ech->encLen;
- ato16(readBuf_p, &ech->innerClientHelloLen);
- ech->innerClientHelloLen -= AES_BLOCK_SIZE;
- readBuf_p += 2;
- ech->outerClientPayload = readBuf_p;
- /* make a copy of the aad */
- aadCopy = (byte*)XMALLOC(ech->aadLen, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (aadCopy == NULL)
- return MEMORY_E;
- XMEMCPY(aadCopy, ech->aad, ech->aadLen);
- /* set the ech payload of the copy to zeros */
- XMEMSET(aadCopy + (readBuf_p - ech->aad), 0,
- ech->innerClientHelloLen + AES_BLOCK_SIZE);
- /* allocate the inner payload buffer */
- ech->innerClientHello =
- (byte*)XMALLOC(ech->innerClientHelloLen + HANDSHAKE_HEADER_SZ,
- ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ech->innerClientHello == NULL) {
- XFREE(aadCopy, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
- /* first check if the config id matches */
- echConfig = ssl->ctx->echConfigs;
- while (echConfig != NULL) {
- /* decrypt with this config */
- if (echConfig->configId == ech->configId) {
- ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
- ssl->heap);
- break;
- }
- echConfig = echConfig->next;
- }
- /* try to decrypt with all configs */
- if (echConfig == NULL || ret != 0) {
- echConfig = ssl->ctx->echConfigs;
- while (echConfig != NULL) {
- ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
- ssl->heap);
- if (ret== 0)
- break;
- echConfig = echConfig->next;
- }
- }
- /* if we failed to extract */
- if (ret != 0) {
- XFREE(ech->innerClientHello, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- ech->innerClientHello = NULL;
- ech->state = ECH_WRITE_RETRY_CONFIGS;
- }
- else {
- i = 0;
- /* decrement until before the padding */
- while (ech->innerClientHello[ech->innerClientHelloLen +
- HANDSHAKE_HEADER_SZ - i - 1] != ECH_TYPE_INNER) {
- i++;
- }
- /* subtract the length of the padding from the length */
- ech->innerClientHelloLen -= i;
- }
- XFREE(aadCopy, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return 0;
- }
- return ret;
- }
- /* free the ech struct and the dynamic buffer it uses */
- static void TLSX_ECH_Free(WOLFSSL_ECH* ech, void* heap)
- {
- if (ech->innerClientHello != NULL)
- XFREE(ech->innerClientHello, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ech->ephemeralKey != NULL)
- wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
- ech->hpke->heap);
- if (ech->hpke != NULL)
- XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
- (void)heap;
- }
- /* encrypt the client hello and store it in ech->outerClientPayload, return
- * status */
- int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
- {
- int ret;
- void* receiverPubkey = NULL;
- byte* info;
- int infoLen;
- byte* aadCopy;
- /* import the server public key */
- ret = wc_HpkeDeserializePublicKey(ech->hpke, &receiverPubkey,
- ech->echConfig->receiverPubkey, ech->encLen);
- if (ret == 0) {
- /* create info */
- infoLen = TLS_INFO_CONST_STRING_SZ + 1 + ech->echConfig->rawLen;
- info = (byte*)XMALLOC(infoLen, ech->hpke->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (info == NULL)
- ret = MEMORY_E;
- if (ret == 0) {
- /* puts the null byte in for me */
- XMEMCPY(info, (byte*)TLS_INFO_CONST_STRING, TLS_INFO_CONST_STRING_SZ
- + 1);
- XMEMCPY(info + TLS_INFO_CONST_STRING_SZ + 1, ech->echConfig->raw,
- ech->echConfig->rawLen);
- /* make a copy of the aad since we overwrite it */
- aadCopy = (byte*)XMALLOC(aadLen, ech->hpke->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (aadCopy == NULL) {
- XFREE(info, ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
- ret = MEMORY_E;
- }
- }
- if (ret == 0) {
- XMEMCPY(aadCopy, aad, aadLen);
- /* seal the payload */
- ret = wc_HpkeSealBase(ech->hpke, ech->ephemeralKey, receiverPubkey,
- info, infoLen, aadCopy, aadLen, ech->innerClientHello,
- ech->innerClientHelloLen - ech->hpke->Nt,
- ech->outerClientPayload);
- XFREE(info, ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(aadCopy, ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- }
- if (receiverPubkey != NULL)
- wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, receiverPubkey,
- ech->hpke->heap);
- return ret;
- }
- #define GREASE_ECH_USE TLSX_GreaseECH_Use
- #define ECH_USE TLSX_ECH_Use
- #define SERVER_ECH_USE TLSX_ServerECH_Use
- #define ECH_WRITE TLSX_ECH_Write
- #define ECH_GET_SIZE TLSX_ECH_GetSize
- #define ECH_PARSE TLSX_ECH_Parse
- #define ECH_FREE TLSX_ECH_Free
- #endif
- /** 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) {
- #if defined(HAVE_RPK)
- case TLSX_CLIENT_CERTIFICATE_TYPE:
- case TLSX_SERVER_CERTIFICATE_TYPE:
- /* nothing to do */
- break;
- #endif
- #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_APPLICATION_LAYER_PROTOCOL:
- ALPN_FREE_ALL((ALPN*)extension->data, heap);
- break;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- case TLSX_SIGNATURE_ALGORITHMS:
- SA_FREE_ALL((SignatureAlgorithms*)extension->data, heap);
- 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;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- case TLSX_CERTIFICATE_AUTHORITIES:
- break;
- #endif
- #endif
- #ifdef WOLFSSL_SRTP
- case TLSX_USE_SRTP:
- SRTP_FREE((TlsxSrtp*)extension->data, heap);
- break;
- #endif
- #ifdef WOLFSSL_QUIC
- case TLSX_KEY_QUIC_TP_PARAMS:
- FALL_THROUGH;
- case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
- QTP_FREE((QuicTransportParam*)extension->data, heap);
- break;
- #endif
- #ifdef WOLFSSL_DTLS_CID
- case TLSX_CONNECTION_ID:
- CID_FREE((byte*)extension->data, heap);
- break;
- #endif /* WOLFSSL_DTLS_CID */
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- case TLSX_ECH:
- ECH_FREE((WOLFSSL_ECH*)extension->data, heap);
- break;
- #endif
- default:
- break;
- }
- 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_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((byte)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;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- case TLSX_CERTIFICATE_AUTHORITIES:
- length += CAN_GET_SIZE(extension->data);
- break;
- #endif
- #endif
- #ifdef WOLFSSL_SRTP
- case TLSX_USE_SRTP:
- length += SRTP_GET_SIZE((TlsxSrtp*)extension->data);
- break;
- #endif
- #ifdef HAVE_RPK
- case TLSX_CLIENT_CERTIFICATE_TYPE:
- length += CCT_GET_SIZE((WOLFSSL*)extension->data, msgType);
- break;
- case TLSX_SERVER_CERTIFICATE_TYPE:
- length += SCT_GET_SIZE((WOLFSSL*)extension->data, msgType);
- break;
- #endif /* HAVE_RPK */
- #ifdef WOLFSSL_QUIC
- case TLSX_KEY_QUIC_TP_PARAMS:
- FALL_THROUGH; /* followed by */
- case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
- length += QTP_GET_SIZE(extension);
- break;
- #endif
- #ifdef WOLFSSL_DTLS_CID
- case TLSX_CONNECTION_ID:
- length += CID_GET_SIZE((byte*)extension->data);
- break;
- #endif /* WOLFSSL_DTLS_CID */
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- case TLSX_ECH:
- length += ECH_GET_SIZE((WOLFSSL_ECH*)extension->data);
- break;
- #endif
- default:
- break;
- }
- /* 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_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((byte)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;
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- case TLSX_CERTIFICATE_AUTHORITIES:
- WOLFSSL_MSG("Certificate Authorities extension to write");
- offset += CAN_WRITE(extension->data, output + offset);
- break;
- #endif
- #endif
- #ifdef WOLFSSL_SRTP
- case TLSX_USE_SRTP:
- offset += SRTP_WRITE((TlsxSrtp*)extension->data, output+offset);
- break;
- #endif
- #ifdef HAVE_RPK
- case TLSX_CLIENT_CERTIFICATE_TYPE:
- WOLFSSL_MSG("Client Certificate Type extension to write");
- offset += CCT_WRITE(extension->data, output + offset, msgType);
- break;
- case TLSX_SERVER_CERTIFICATE_TYPE:
- WOLFSSL_MSG("Server Certificate Type extension to write");
- offset += SCT_WRITE(extension->data, output + offset, msgType);
- break;
- #endif /* HAVE_RPK */
- #ifdef WOLFSSL_QUIC
- case TLSX_KEY_QUIC_TP_PARAMS:
- FALL_THROUGH;
- case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
- WOLFSSL_MSG("QUIC transport parameter to write");
- offset += QTP_WRITE((QuicTransportParam*)extension->data,
- output + offset);
- break;
- #endif
- #ifdef WOLFSSL_DTLS_CID
- case TLSX_CONNECTION_ID:
- offset += CID_WRITE((byte*)extension->data, output+offset);
- break;
- #endif /* WOLFSSL_DTLS_CID */
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- case TLSX_ECH:
- ret = ECH_WRITE((WOLFSSL_ECH*)extension->data,
- output + offset, &offset);
- break;
- #endif
- default:
- break;
- }
- /* 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));
- /* if we encountered an error propagate it */
- if (ret != 0)
- break;
- }
- *pOffset += offset;
- return ret;
- }
- #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
- #ifdef WOLFSSL_SM2
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SM2P256V1, 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
- #ifdef HAVE_PQC
- #ifdef WOLFSSL_WC_KYBER
- #ifdef WOLFSSL_KYBER512
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1,
- ssl->heap);
- #endif
- #ifdef WOLFSSL_KYBER768
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL3,
- ssl->heap);
- #endif
- #ifdef WOLFSSL_KYBER768
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5,
- ssl->heap);
- #endif
- #elif defined(HAVE_LIBOQS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap);
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL3,
- ssl->heap);
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5,
- ssl->heap);
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL1,
- ssl->heap);
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL3,
- ssl->heap);
- if (ret == WOLFSSL_SUCCESS)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5,
- ssl->heap);
- #elif defined(HAVE_PQM4)
- ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap);
- #endif /* HAVE_LIBOQS */
- #endif /* HAVE_PQC */
- (void)ssl;
- (void)extensions;
- return ret;
- }
- #endif /* 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
- #if defined(HAVE_SUPPORTED_CURVES) && defined(WOLFSSL_TLS13)
- TLSX* extension = NULL;
- word16 namedGroup = WOLFSSL_NAMED_GROUP_INVALID;
- #endif
- /* server will add extension depending on what is parsed from client */
- if (!isServer) {
- #if defined(HAVE_RPK)
- ret = TLSX_ClientCertificateType_Use(ssl, isServer);
- if (ret != 0)
- return ret;
- ret = TLSX_ServerCertificateType_Use(ssl, isServer);
- if (ret != 0)
- return ret;
- #endif /* HAVE_RPK */
- #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 */
- #ifdef WOLFSSL_SRTP
- if (ssl->options.dtls && ssl->dtlsSrtpProfiles != 0) {
- WOLFSSL_MSG("Adding DTLS SRTP extension");
- if ((ret = TLSX_UseSRTP(&ssl->extensions, ssl->dtlsSrtpProfiles,
- ssl->heap)) != 0) {
- return ret;
- }
- }
- #endif
- } /* 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 !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- if (isServer && IsAtLeastTLSv1_3(ssl->version)) {
- if (SSL_CA_NAMES(ssl) != NULL) {
- WOLFSSL_MSG("Adding certificate authorities extension");
- if ((ret = TLSX_Push(&ssl->extensions,
- TLSX_CERTIFICATE_AUTHORITIES, ssl, ssl->heap)) != 0) {
- return ret;
- }
- }
- }
- #endif
- 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 value will be overwritten in !NO_PSK case */
- #ifdef NO_PSK
- ret = 0;
- #endif
- }
- #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)
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (ssl->options.resuming && ssl->session->namedGroup != 0)
- namedGroup = ssl->session->namedGroup;
- else
- #endif
- if (ssl->numGroups > 0) {
- int set = 0;
- int i, j;
- /* try to find the highest element in ssl->group[]
- * that is contained in preferredGroup[].
- */
- namedGroup = preferredGroup[0];
- for (i = 0; i < ssl->numGroups && !set; i++) {
- for (j = 0; preferredGroup[j] != WOLFSSL_NAMED_GROUP_INVALID; j++) {
- if (preferredGroup[j] == ssl->group[i]
- #ifdef HAVE_LIBOQS
- && TLSX_KeyShare_IsSupported(preferredGroup[j])
- #endif
- ) {
- namedGroup = ssl->group[i];
- set = 1;
- break;
- }
- }
- }
- if (!set)
- namedGroup = WOLFSSL_NAMED_GROUP_INVALID;
- }
- else {
- /* Choose the most preferred group. */
- namedGroup = preferredGroup[0];
- #ifdef HAVE_LIBOQS
- if (!TLSX_KeyShare_IsSupported(namedGroup)) {
- int i = 1;
- for (;preferredGroup[i] != WOLFSSL_NAMED_GROUP_INVALID;
- i++) {
- if (TLSX_KeyShare_IsSupported(preferredGroup[i]))
- break;
- }
- namedGroup = preferredGroup[i];
- }
- #endif
- }
- }
- else {
- KeyShareEntry* kse = (KeyShareEntry*)extension->data;
- if (kse)
- namedGroup = kse->group;
- }
- if (namedGroup != WOLFSSL_NAMED_GROUP_INVALID) {
- #ifdef HAVE_PQC
- /* For KEMs, the key share has already been generated, but not
- * if we are resuming. */
- if (!WOLFSSL_NAMED_GROUP_IS_PQC(namedGroup)
- #ifdef HAVE_SESSION_TICKET
- || ssl->options.resuming
- #endif /* HAVE_SESSION_TICKET */
- )
- #endif /* HAVE_PQC */
- {
- ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL,
- &ssl->extensions);
- }
- if (ret != 0)
- return ret;
- }
- #endif /* HAVE_SUPPORTED_CURVES */
- #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;
- #ifdef WOLFSSL_32BIT_MILLI_TIME
- word32 now, milli;
- #else
- word64 now, milli;
- #endif
- 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;
- now = TimeNowInMilliseconds();
- if (now == 0)
- return GETTIME_ERROR;
- #ifdef WOLFSSL_32BIT_MILLI_TIME
- if (now < sess->ticketSeen)
- milli = (0xFFFFFFFFU - sess->ticketSeen) + 1 + now;
- else
- milli = now - sess->ticketSeen;
- milli += sess->ticketAdd;
- /* Pre-shared key is mandatory extension for resumption. */
- ret = TLSX_PreSharedKey_Use(&ssl->extensions, sess->ticket,
- sess->ticketLen, milli, ssl->specs.mac_algorithm,
- ssl->options.cipherSuite0, ssl->options.cipherSuite, 1,
- NULL, ssl->heap);
- #else
- milli = now - sess->ticketSeen + sess->ticketAdd;
- /* Pre-shared key is mandatory extension for resumption. */
- ret = TLSX_PreSharedKey_Use(&ssl->extensions, sess->ticket,
- sess->ticketLen, (word32)milli, ssl->specs.mac_algorithm,
- ssl->options.cipherSuite0, ssl->options.cipherSuite, 1,
- NULL, ssl->heap);
- #endif
- if (ret != 0)
- return ret;
- usingPSK = 1;
- }
- #endif
- #ifndef NO_PSK
- #ifndef WOLFSSL_PSK_ONE_ID
- if (ssl->options.client_psk_cs_cb != NULL) {
- int i;
- const Suites* suites = WOLFSSL_SUITES(ssl);
- for (i = 0; i < suites->suiteSz; i += 2) {
- byte cipherSuite0 = suites->suites[i + 0];
- byte cipherSuite = suites->suites[i + 1];
- unsigned int keySz;
- #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
- int cnt = 0;
- #endif
- #ifdef HAVE_NULL_CIPHER
- if (cipherSuite0 == ECC_BYTE ||
- cipherSuite0 == ECDHE_PSK_BYTE) {
- if (cipherSuite != TLS_SHA256_SHA256 &&
- cipherSuite != TLS_SHA384_SHA384) {
- continue;
- }
- }
- else
- #endif
- #if (defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)) && \
- defined(WOLFSSL_SM3)
- if (cipherSuite0 == CIPHER_BYTE) {
- if ((cipherSuite != TLS_SM4_GCM_SM3) &&
- (cipherSuite != TLS_SM4_CCM_SM3)) {
- continue;
- }
- }
- else
- #endif
- if (cipherSuite0 != TLS13_BYTE)
- continue;
- #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
- do {
- ssl->arrays->client_identity[0] = cnt;
- #endif
- ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0';
- keySz = ssl->options.client_psk_cs_cb(
- ssl, ssl->arrays->server_hint,
- ssl->arrays->client_identity, MAX_PSK_ID_LEN,
- ssl->arrays->psk_key, MAX_PSK_KEY_LEN,
- GetCipherNameInternal(cipherSuite0, cipherSuite));
- if (keySz > 0) {
- ssl->arrays->psk_keySz = keySz;
- ret = TLSX_PreSharedKey_Use(&ssl->extensions,
- (byte*)ssl->arrays->client_identity,
- (word16)XSTRLEN(ssl->arrays->client_identity),
- 0, SuiteMac(WOLFSSL_SUITES(ssl)->suites + i),
- cipherSuite0, cipherSuite, 0, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
- cnt++;
- #endif
- }
- #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
- }
- while (keySz > 0);
- #endif
- }
- usingPSK = 1;
- }
- else
- #endif
- if (ssl->options.client_psk_cb != NULL ||
- ssl->options.client_psk_tls13_cb != NULL) {
- /* Default cipher suite. */
- 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 defined(OPENSSL_EXTRA)
- /* OpenSSL treats 0 as a PSK key length of 0
- * and meaning no PSK available.
- */
- if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
- return PSK_KEY_ERROR;
- }
- if (ssl->arrays->psk_keySz > 0) {
- #else
- if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
- return PSK_KEY_ERROR;
- }
- #endif
- 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->extensions,
- (byte*)ssl->arrays->client_identity,
- (word16)XSTRLEN(ssl->arrays->client_identity),
- 0, ssl->specs.mac_algorithm,
- cipherSuite0, cipherSuite, 0,
- NULL, ssl->heap);
- if (ret != 0)
- return ret;
- usingPSK = 1;
- #if defined(OPENSSL_EXTRA)
- }
- #endif
- }
- #endif /* !NO_PSK */
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- /* Some servers do not generate session tickets unless
- * the extension is seen in a non-resume client hello.
- * We used to send it only if we were otherwise using PSK.
- * Now always send it. Define NO_TLSX_PSKKEM_PLAIN_ANNOUNCE
- * to revert to the old behaviour. */
- #ifdef NO_TLSX_PSKKEM_PLAIN_ANNOUNCE
- if (usingPSK)
- #endif
- {
- byte modes = 0;
- (void)usingPSK;
- /* Pre-shared key modes: mandatory extension for resumption. */
- #ifdef HAVE_SUPPORTED_CURVES
- if (!ssl->options.onlyPskDheKe)
- #endif
- {
- 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_PskKeyModes_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
- #if defined(HAVE_ECH)
- /* GREASE ECH */
- if (ssl->echConfigs == NULL) {
- ret = GREASE_ECH_USE(&(ssl->extensions), ssl->heap, ssl->rng);
- }
- else if (ssl->echConfigs != NULL) {
- ret = ECH_USE(ssl->echConfigs, &(ssl->extensions), ssl->heap,
- ssl->rng);
- }
- #endif
- }
- #if defined(HAVE_ECH)
- else if (IsAtLeastTLSv1_3(ssl->version)) {
- if (ssl->ctx->echConfigs != NULL) {
- ret = SERVER_ECH_USE(&(ssl->extensions), ssl->heap,
- ssl->ctx->echConfigs);
- if (ret == 0)
- TLSX_SetResponse(ssl, TLSX_ECH);
- }
- }
- #endif
- #endif
- (void)isServer;
- (void)public_key;
- (void)public_key_len;
- (void)ssl;
- return ret;
- }
- #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- /* because the size of ech depends on the size of other extensions we need to
- * get the size with ech special and process ech last, return status */
- static int TLSX_GetSizeWithEch(WOLFSSL* ssl, byte* semaphore, byte msgType,
- word16* pLength)
- {
- int ret = 0;
- TLSX* echX = NULL;
- TLSX* serverNameX = NULL;
- TLSX** extensions = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- char* tmpServerName = NULL;
- #else
- char tmpServerName[MAX_PUBLIC_NAME_SZ];
- #endif
- /* calculate the rest of the extensions length with inner ech */
- if (ssl->extensions)
- echX = TLSX_Find(ssl->extensions, TLSX_ECH);
- if (echX == NULL && ssl->ctx && ssl->ctx->extensions)
- echX = TLSX_Find(ssl->ctx->extensions, TLSX_ECH);
- /* if type is outer change sni to public name */
- if (echX != NULL && ((WOLFSSL_ECH*)echX->data)->type == ECH_TYPE_OUTER) {
- if (ssl->extensions) {
- serverNameX = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
- if (serverNameX != NULL)
- extensions = &ssl->extensions;
- }
- if (serverNameX == NULL && ssl->ctx && ssl->ctx->extensions) {
- serverNameX = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
- extensions = &ssl->ctx->extensions;
- }
- /* store the inner server name */
- if (serverNameX != NULL) {
- char* hostName = ((SNI*)serverNameX->data)->data.host_name;
- word32 hostNameSz = (word32)XSTRLEN(hostName) + 1;
- #ifdef WOLFSSL_SMALL_STACK
- tmpServerName = (char*)XMALLOC(hostNameSz, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (tmpServerName == NULL)
- return MEMORY_E;
- #else
- /* truncate if too long */
- if (hostNameSz > MAX_PUBLIC_NAME_SZ)
- hostNameSz = MAX_PUBLIC_NAME_SZ;
- #endif
- XMEMCPY(tmpServerName, hostName, hostNameSz);
- }
- /* remove the inner server name */
- TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
- ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
- ((WOLFSSL_ECH*)echX->data)->echConfig->publicName,
- XSTRLEN(((WOLFSSL_ECH*)echX->data)->echConfig->publicName),
- ssl->heap);
- /* set the public name as the server name */
- if (ret == WOLFSSL_SUCCESS)
- ret = 0;
- }
- if (ret == 0 && ssl->extensions)
- ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, pLength);
- if (ret == 0 && ssl->ctx && ssl->ctx->extensions)
- ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, pLength);
- if (serverNameX != NULL) {
- /* remove the public name SNI */
- TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
- ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
- tmpServerName, XSTRLEN(tmpServerName), ssl->heap);
- /* restore the inner server name */
- if (ret == WOLFSSL_SUCCESS)
- ret = 0;
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpServerName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
- #endif
- /** 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);
- WOLF_STK_VALIDATE_REQUEST(ssl);
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- if (WOLFSSL_SUITES(ssl)->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
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- TURN_ON(semaphore,
- TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
- #endif
- }
- #endif
- #endif /* WOLFSSL_TLS13 */
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- if (!SSL_CM(ssl)->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
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- if (SSL_CA_NAMES(ssl) != NULL)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
- #endif
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, OID_FILTERS
- * TLSX_STATUS_REQUEST
- */
- }
- #endif
- #if defined(HAVE_ECH)
- if (ssl->options.useEch == 1 && msgType == client_hello) {
- ret = TLSX_GetSizeWithEch(ssl, semaphore, msgType, &length);
- if (ret != 0)
- return ret;
- }
- else
- #endif /* HAVE_ECH */
- #endif /* WOLFSSL_TLS13 */
- {
- 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;
- }
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- /* return status after writing the extensions with ech written last */
- static int TLSX_WriteWithEch(WOLFSSL* ssl, byte* output, byte* semaphore,
- byte msgType, word16* pOffset)
- {
- int ret = 0;
- TLSX* echX = NULL;
- TLSX* serverNameX = NULL;
- TLSX** extensions = NULL;
- #ifdef WOLFSSL_SMALL_STACK
- char* tmpServerName = NULL;
- #else
- char tmpServerName[MAX_PUBLIC_NAME_SZ];
- #endif
- /* get the echX from either extensions or ctx */
- if (ssl->extensions)
- echX = TLSX_Find(ssl->extensions, TLSX_ECH);
- if (echX == NULL && ssl->ctx && ssl->ctx->extensions) {
- /* if not NULL the semaphore will stop it from being counted */
- if (echX == NULL)
- echX = TLSX_Find(ssl->ctx->extensions, TLSX_ECH);
- }
- /* if type is outer change sni to public name */
- if (echX != NULL && ((WOLFSSL_ECH*)echX->data)->type == ECH_TYPE_OUTER) {
- if (ssl->extensions) {
- serverNameX = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
- if (serverNameX != NULL)
- extensions = &ssl->extensions;
- }
- if (serverNameX == NULL && ssl->ctx && ssl->ctx->extensions) {
- serverNameX = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
- extensions = &ssl->ctx->extensions;
- }
- /* store the inner server name */
- if (serverNameX != NULL) {
- char* hostName = ((SNI*)serverNameX->data)->data.host_name;
- word32 hostNameSz = (word32)XSTRLEN(hostName) + 1;
- #ifdef WOLFSSL_SMALL_STACK
- tmpServerName = (char*)XMALLOC(hostNameSz, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (tmpServerName == NULL)
- return MEMORY_E;
- #else
- /* truncate if too long */
- if (hostNameSz > MAX_PUBLIC_NAME_SZ)
- hostNameSz = MAX_PUBLIC_NAME_SZ;
- #endif
- XMEMCPY(tmpServerName, hostName, hostNameSz);
- }
- /* remove the inner server name */
- TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
- ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
- ((WOLFSSL_ECH*)echX->data)->echConfig->publicName,
- XSTRLEN(((WOLFSSL_ECH*)echX->data)->echConfig->publicName),
- ssl->heap);
- /* set the public name as the server name */
- if (ret == WOLFSSL_SUCCESS)
- ret = 0;
- }
- if (echX != NULL) {
- /* turn ech on so it doesn't write, then write it last */
- TURN_ON(semaphore, TLSX_ToSemaphore(echX->type));
- }
- if (ret == 0 && ssl->extensions) {
- ret = TLSX_Write(ssl->extensions, output + *pOffset, semaphore,
- msgType, pOffset);
- }
- if (ret == 0 && ssl->ctx && ssl->ctx->extensions) {
- ret = TLSX_Write(ssl->ctx->extensions, output + *pOffset, semaphore,
- msgType, pOffset);
- }
- if (echX != NULL) {
- /* turn off and write it last */
- TURN_OFF(semaphore, TLSX_ToSemaphore(echX->type));
- }
- if (ret == 0 && ssl->extensions) {
- ret = TLSX_Write(ssl->extensions, output + *pOffset, semaphore,
- msgType, pOffset);
- }
- if (ret == 0 && ssl->ctx && ssl->ctx->extensions) {
- ret = TLSX_Write(ssl->ctx->extensions, output + *pOffset, semaphore,
- msgType, pOffset);
- }
- if (serverNameX != NULL) {
- /* remove the public name SNI */
- TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
- ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME, tmpServerName,
- XSTRLEN(tmpServerName), ssl->heap);
- /* restore the inner server name */
- if (ret == WOLFSSL_SUCCESS)
- ret = 0;
- }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpServerName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- return ret;
- }
- #endif
- /** 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);
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
- if (WOLFSSL_SUITES(ssl)->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
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- TURN_ON(semaphore,
- TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
- #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 /* WOLFSSL_TLS13 */
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- /* mark already sent, so it won't send it */
- if (!SSL_CM(ssl)->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
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- if (SSL_CA_NAMES(ssl) != NULL) {
- TURN_OFF(semaphore,
- TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
- }
- #endif
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, TLSX_OID_FILTERS
- * TLSX_STATUS_REQUEST
- */
- }
- #endif
- #endif
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- if (ssl->options.useEch == 1 && msgType == client_hello) {
- ret = TLSX_WriteWithEch(ssl, output, semaphore,
- msgType, &offset);
- if (ret != 0)
- return ret;
- }
- else
- #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));
- #if defined(HAVE_SUPPORTED_CURVES)
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (!ssl->options.noPskDheKe)
- #endif
- {
- /* Expect KeyShare extension in ServerHello. */
- 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
- #ifdef WOLFSSL_DTLS_CID
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
- #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 /* WOLFSSL_TLS13 */
- 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 defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (!ssl->options.noPskDheKe)
- #endif
- {
- /* Expect KeyShare extension in HelloRetryRequest. */
- 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_SERVER_RENEGOTIATION_INFO)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
- #endif
- #ifdef WOLFSSL_DTLS_CID
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
- #endif /* WOLFSSL_DTLS_CID */
- 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_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 defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (!ssl->options.noPskDheKe)
- #endif
- {
- /* Write out KeyShare in ServerHello. */
- 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
- #ifdef WOLFSSL_DTLS_CID
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
- #endif /* WOLFSSL_DTLS_CID */
- }
- #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 defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (!ssl->options.noPskDheKe)
- #endif
- {
- /* Write out KeyShare in HelloRetryRequest. */
- 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_SERVER_RENEGOTIATION_INFO)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
- #endif
- #ifdef WOLFSSL_DTLS_CID
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
- #endif /* WOLFSSL_DTLS_CID */
- 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
- default:
- break;
- }
- 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, const 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, &ssl->version,
- &ssl->options, &ssl->extensions);
- break;
- }
- offset += size;
- }
- return ret;
- }
- #endif
- /** Parses a buffer of TLS extensions. */
- int TLSX_Parse(WOLFSSL* ssl, const 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
- byte seenType[SEMAPHORE_SIZE]; /* Seen known extensions. */
- if (!ssl || !input || (isRequest && !suites))
- return BAD_FUNC_ARG;
- /* No known extensions seen yet. */
- XMEMSET(seenType, 0, sizeof(seenType));
- 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) {
- WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
- 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;
- /* Check we have a bit for extension type. */
- if ((type <= 62) || (type == TLSX_RENEGOTIATION_INFO)
- #ifdef WOLFSSL_QUIC
- || (type == TLSX_KEY_QUIC_TP_PARAMS_DRAFT)
- #endif
- )
- {
- /* Detect duplicate recognized extensions. */
- if (IS_OFF(seenType, TLSX_ToSemaphore(type))) {
- TURN_ON(seenType, TLSX_ToSemaphore(type));
- }
- else {
- return DUPLICATE_TLS_EXT_E;
- }
- }
- if (length - offset < size)
- 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
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- if (msgType != client_hello &&
- msgType != encrypted_extensions)
- return EXT_NOT_ALLOWED;
- }
- else
- #endif
- {
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- }
- 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
- #ifdef WOLFSSL_TLS13
- /* RFC 8446 4.2.4 states trusted_ca_keys is not used
- in TLS 1.3. */
- if (IsAtLeastTLSv1_3(ssl->version)) {
- return EXT_NOT_ALLOWED;
- }
- else
- #endif
- {
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- }
- 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
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- if (msgType != client_hello &&
- msgType != encrypted_extensions) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- }
- else
- #endif
- {
- if (msgType != client_hello &&
- msgType != server_hello) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- }
- 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
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- if (msgType != client_hello)
- return EXT_NOT_ALLOWED;
- 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
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- if (msgType != client_hello &&
- msgType != encrypted_extensions) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- }
- else
- #endif
- {
- if (msgType != client_hello) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- }
- ret = EC_PARSE(ssl, input + offset, size, isRequest,
- &ssl->extensions);
- break;
- case TLSX_EC_POINT_FORMATS:
- WOLFSSL_MSG("Point Formats extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- if (msgType != client_hello &&
- msgType != server_hello) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- 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
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- if (msgType != client_hello &&
- msgType != certificate_request &&
- msgType != certificate)
- return EXT_NOT_ALLOWED;
- }
- else
- #endif
- {
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- }
- 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)) {
- if (msgType != client_hello &&
- msgType != certificate_request &&
- msgType != certificate)
- return EXT_NOT_ALLOWED;
- }
- else
- #endif
- {
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- }
- 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 (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- 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
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version))
- break;
- #endif
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- 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)) {
- if (msgType != client_hello)
- return EXT_NOT_ALLOWED;
- }
- else
- #endif
- {
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- }
- ret = WOLF_STK_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)) {
- if (msgType != client_hello &&
- msgType != encrypted_extensions)
- return EXT_NOT_ALLOWED;
- }
- else
- #endif
- {
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- }
- 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)) {
- if (msgType != client_hello &&
- msgType != certificate_request)
- return EXT_NOT_ALLOWED;
- }
- else
- #endif
- {
- if (msgType != client_hello)
- return EXT_NOT_ALLOWED;
- }
- 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;
- if (msgType != client_hello &&
- msgType != server_hello)
- return EXT_NOT_ALLOWED;
- 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
- if (msgType != client_hello &&
- msgType != server_hello &&
- msgType != hello_retry_request)
- return EXT_NOT_ALLOWED;
- 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) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- 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) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- 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) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- 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) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- 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) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- ret = SAC_PARSE(ssl, input + offset, size, isRequest);
- break;
- #endif
- #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
- case TLSX_CERTIFICATE_AUTHORITIES:
- WOLFSSL_MSG("Certificate Authorities 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) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- ret = CAN_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) {
- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
- return EXT_NOT_ALLOWED;
- }
- #endif
- ret = KS_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
- #ifdef WOLFSSL_SRTP
- case TLSX_USE_SRTP:
- WOLFSSL_MSG("Use SRTP extension received");
- ret = SRTP_PARSE(ssl, input + offset, size, isRequest);
- break;
- #endif
- #ifdef WOLFSSL_QUIC
- case TLSX_KEY_QUIC_TP_PARAMS:
- FALL_THROUGH;
- case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
- WOLFSSL_MSG("QUIC transport parameter received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
- 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;
- }
- else if (WOLFSSL_IS_QUIC(ssl)) {
- ret = QTP_PARSE(ssl, input + offset, size, type, msgType);
- }
- else {
- WOLFSSL_MSG("QUIC transport param TLS extension type, but no QUIC");
- return EXT_NOT_ALLOWED; /* be safe, this should not happen */
- }
- break;
- #endif /* WOLFSSL_QUIC */
- #if defined(WOLFSSL_DTLS_CID)
- case TLSX_CONNECTION_ID:
- /* connection ID not supported in DTLSv1.2 */
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
- if (msgType != client_hello && msgType != server_hello)
- return EXT_NOT_ALLOWED;
- WOLFSSL_MSG("ConnectionID extension received");
- ret = CID_PARSE(ssl, input + offset, size, isRequest);
- break;
- #endif /* defined(WOLFSSL_DTLS_CID) */
- #if defined(HAVE_RPK)
- case TLSX_CLIENT_CERTIFICATE_TYPE:
- WOLFSSL_MSG("Client Certificate Type extension received");
- ret = CCT_PARSE(ssl, input + offset, size, msgType);
- break;
- case TLSX_SERVER_CERTIFICATE_TYPE:
- WOLFSSL_MSG("Server Certificate Type extension received");
- ret = SCT_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif /* HAVE_RPK */
- #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
- case TLSX_ECH:
- ret = ECH_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 (IsAtLeastTLSv1_3(ssl->version) && msgType == hello_retry_request) {
- /* Don't change EMS status until server_hello received.
- * Second ClientHello must have same extensions.
- */
- }
- else 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_DTLS13)
- InitSSL_Method(method, MakeDTLSv1_3());
- #elif !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 WOLFSSL_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 WOLFSSL_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 WOLFSSL_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 WOLFSSL_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_DTLS13)
- InitSSL_Method(method, MakeDTLSv1_3());
- #elif !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 */
|