1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830 |
- /* internal.c
- *
- * Copyright (C) 2006-2011 Sawtooth Consulting Ltd.
- *
- * This file is part of CyaSSL.
- *
- * CyaSSL 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.
- *
- * CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <cyassl/internal.h>
- #include <cyassl/error.h>
- #include <cyassl/ctaocrypt/asn.h>
- #ifdef HAVE_LIBZ
- #include "zlib.h"
- #endif
- #ifdef HAVE_NTRU
- #include "crypto_ntru.h"
- #endif
- #if defined(DEBUG_CYASSL) || defined(SHOW_SECRETS)
- #include <stdio.h>
- #endif
- #ifdef __sun
- #include <sys/filio.h>
- #endif
- #define TRUE 1
- #define FALSE 0
- #if defined(OPENSSL_EXTRA) && defined(NO_DH)
- #error OPENSSL_EXTRA needs DH, please remove NO_DH
- #endif
- #ifndef NO_CYASSL_CLIENT
- static int DoHelloVerifyRequest(CYASSL* ssl, const byte* input, word32*);
- static int DoServerHello(CYASSL* ssl, const byte* input, word32*);
- static int DoCertificateRequest(CYASSL* ssl, const byte* input, word32*);
- static int DoServerKeyExchange(CYASSL* ssl, const byte* input, word32*);
- #endif
- #ifndef NO_CYASSL_SERVER
- static int DoClientHello(CYASSL* ssl, const byte* input, word32*, word32,
- word32);
- static int DoCertificateVerify(CYASSL* ssl, byte*, word32*, word32);
- static int DoClientKeyExchange(CYASSL* ssl, byte* input, word32*);
- #endif
- typedef enum {
- doProcessInit = 0,
- #ifndef NO_CYASSL_SERVER
- runProcessOldClientHello,
- #endif
- getRecordLayerHeader,
- getData,
- runProcessingOneMessage
- } processReply;
- static void Hmac(CYASSL* ssl, byte* digest, const byte* buffer, word32 sz,
- int content, int verify);
- static void BuildCertHashes(CYASSL* ssl, Hashes* hashes);
- #ifndef min
- static INLINE word32 min(word32 a, word32 b)
- {
- return a > b ? b : a;
- }
- #endif /* min */
- int IsTLS(const CYASSL* ssl)
- {
- if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
- return 1;
- return 0;
- }
- int IsAtLeastTLSv1_2(const CYASSL* ssl)
- {
- if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
- return 1;
- return 0;
- }
- #ifdef HAVE_NTRU
- static byte GetEntropy(ENTROPY_CMD cmd, byte* out)
- {
- /* TODO: add locking? */
- static RNG rng;
- if (cmd == INIT) {
- int ret = InitRng(&rng);
- if (ret == 0)
- return 1;
- else
- return 0;
- }
- if (out == NULL)
- return 0;
- if (cmd == GET_BYTE_OF_ENTROPY) {
- RNG_GenerateBlock(&rng, out, 1);
- return 1;
- }
- if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
- *out = 1;
- return 1;
- }
- return 0;
- }
- #endif /* HAVE_NTRU */
- /* used by ssl.c too */
- void c32to24(word32 in, word24 out)
- {
- out[0] = (in >> 16) & 0xff;
- out[1] = (in >> 8) & 0xff;
- out[2] = in & 0xff;
- }
- #ifdef CYASSL_DTLS
- static INLINE void c32to48(word32 in, byte out[6])
- {
- out[0] = 0;
- out[1] = 0;
- out[2] = (in >> 24) & 0xff;
- out[3] = (in >> 16) & 0xff;
- out[4] = (in >> 8) & 0xff;
- out[5] = in & 0xff;
- }
- #endif /* CYASSL_DTLS */
- /* convert 16 bit integer to opaque */
- static INLINE void c16toa(word16 u16, byte* c)
- {
- c[0] = (u16 >> 8) & 0xff;
- c[1] = u16 & 0xff;
- }
- /* convert 32 bit integer to opaque */
- static INLINE void c32toa(word32 u32, byte* c)
- {
- c[0] = (u32 >> 24) & 0xff;
- c[1] = (u32 >> 16) & 0xff;
- c[2] = (u32 >> 8) & 0xff;
- c[3] = u32 & 0xff;
- }
- /* convert a 24 bit integer into a 32 bit one */
- static INLINE void c24to32(const word24 u24, word32* u32)
- {
- *u32 = 0;
- *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
- }
- /* convert opaque to 16 bit integer */
- static INLINE void ato16(const byte* c, word16* u16)
- {
- *u16 = 0;
- *u16 = (c[0] << 8) | (c[1]);
- }
- #ifdef CYASSL_DTLS
- /* convert opaque to 32 bit integer */
- static INLINE void ato32(const byte* c, word32* u32)
- {
- *u32 = 0;
- *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
- }
- #endif /* CYASSL_DTLS */
- #ifdef HAVE_LIBZ
- /* alloc user allocs to work with zlib */
- static void* myAlloc(void* opaque, unsigned int item, unsigned int size)
- {
- (void)opaque;
- return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
- }
- static void myFree(void* opaque, void* memory)
- {
- (void)opaque;
- XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
- }
- /* init zlib comp/decomp streams, 0 on success */
- static int InitStreams(CYASSL* ssl)
- {
- ssl->c_stream.zalloc = (alloc_func)myAlloc;
- ssl->c_stream.zfree = (free_func)myFree;
- ssl->c_stream.opaque = (voidpf)ssl->heap;
- if (deflateInit(&ssl->c_stream, 8) != Z_OK) return ZLIB_INIT_ERROR;
- ssl->didStreamInit = 1;
- ssl->d_stream.zalloc = (alloc_func)myAlloc;
- ssl->d_stream.zfree = (free_func)myFree;
- ssl->d_stream.opaque = (voidpf)ssl->heap;
- if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
- return 0;
- }
- static void FreeStreams(CYASSL* ssl)
- {
- if (ssl->didStreamInit) {
- deflateEnd(&ssl->c_stream);
- inflateEnd(&ssl->d_stream);
- }
- }
- /* compress in to out, return out size or error */
- static int Compress(CYASSL* ssl, byte* in, int inSz, byte* out, int outSz)
- {
- int err;
- int currTotal = ssl->c_stream.total_out;
- /* put size in front of compression */
- c16toa((word16)inSz, out);
- out += 2;
- outSz -= 2;
- ssl->c_stream.next_in = in;
- ssl->c_stream.avail_in = inSz;
- ssl->c_stream.next_out = out;
- ssl->c_stream.avail_out = outSz;
- err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
- if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
- return ssl->c_stream.total_out - currTotal + sizeof(word16);
- }
-
- /* decompress in to out, returnn out size or error */
- static int DeCompress(CYASSL* ssl, byte* in, int inSz, byte* out, int outSz)
- {
- int err;
- int currTotal = ssl->d_stream.total_out;
- word16 len;
- /* find size in front of compression */
- ato16(in, &len);
- in += 2;
- inSz -= 2;
- ssl->d_stream.next_in = in;
- ssl->d_stream.avail_in = inSz;
- ssl->d_stream.next_out = out;
- ssl->d_stream.avail_out = outSz;
- err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
- if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
- return ssl->d_stream.total_out - currTotal;
- }
-
- #endif /* HAVE_LIBZ */
- void InitSSL_Method(CYASSL_METHOD* method, ProtocolVersion pv)
- {
- method->version = pv;
- method->side = CLIENT_END;
- method->verifyPeer = 0;
- method->verifyNone = 0;
- method->failNoCert = 0;
- method->downgrade = 0;
- }
- void InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
- {
- ctx->method = method;
- ctx->certificate.buffer = 0;
- ctx->certChain.buffer = 0;
- ctx->privateKey.buffer = 0;
- ctx->serverDH_P.buffer = 0;
- ctx->serverDH_G.buffer = 0;
- ctx->haveDH = 0;
- ctx->haveNTRU = 0; /* start off */
- ctx->haveECDSA = 0; /* start off */
- ctx->heap = ctx; /* defaults to self */
- #ifndef NO_PSK
- ctx->havePSK = 0;
- ctx->server_hint[0] = 0;
- ctx->client_psk_cb = 0;
- ctx->server_psk_cb = 0;
- #endif /* NO_PSK */
- #ifdef OPENSSL_EXTRA
- ctx->passwd_cb = 0;
- ctx->userdata = 0;
- #endif /* OPENSSL_EXTRA */
- #ifndef CYASSL_USER_IO
- ctx->CBIORecv = EmbedReceive;
- ctx->CBIOSend = EmbedSend;
- #else
- /* user will set */
- ctx->CBIORecv = NULL;
- ctx->CBIOSend = NULL;
- #endif
- ctx->partialWrite = 0;
- ctx->verifyCallback = 0;
- ctx->caList = 0;
- #ifdef HAVE_NTRU
- if (method->side == CLIENT_END)
- ctx->haveNTRU = 1; /* always on cliet side */
- /* server can turn on by loading key */
- #endif
- #ifdef HAVE_ECC
- if (method->side == CLIENT_END)
- ctx->haveECDSA = 1; /* always on cliet side */
- /* server can turn on by loading key */
- #endif
- ctx->suites.setSuites = 0; /* user hasn't set yet */
- /* remove DH later if server didn't set, add psk later */
- InitSuites(&ctx->suites, method->version, TRUE, FALSE, ctx->haveNTRU,
- ctx->haveECDSA, method->side);
- ctx->verifyPeer = 0;
- ctx->verifyNone = 0;
- ctx->failNoCert = 0;
- ctx->sessionCacheOff = 0; /* initially on */
- ctx->sessionCacheFlushOff = 0; /* initially on */
- ctx->sendVerify = 0;
- ctx->quietShutdown = 0;
- }
- /* In case contexts are held in array and don't want to free actual ctx */
- void SSL_CtxResourceFree(CYASSL_CTX* ctx)
- {
- XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH);
- XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH);
- XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
- XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
- XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
- XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
- FreeSigners(ctx->caList, ctx->heap);
- }
- void FreeSSL_Ctx(CYASSL_CTX* ctx)
- {
- SSL_CtxResourceFree(ctx);
- XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
- }
-
- void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
- byte haveNTRU, byte haveECDSA, int side)
- {
- word16 idx = 0;
- int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
- int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
- int haveRSA = 1;
- (void)tls; /* shut up compiler */
- (void)haveDH;
- (void)havePSK;
- (void)haveNTRU;
- if (suites->setSuites)
- return; /* trust user settings, don't override */
- if (side == SERVER_END && haveECDSA)
- haveRSA = 0; /* can't do RSA with ECDSA cert */
- #ifdef CYASSL_DTLS
- if (pv.major == DTLS_MAJOR && pv.minor == DTLS_MINOR)
- tls = 1;
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
- if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
- if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
- }
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveNTRU && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- if (tls && haveECDSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- if (tls && haveECDSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- if (tls && haveECDSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveECDSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
- }
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = ECC_BYTE;
- suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- if (tls1_2 && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
- }
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
- }
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- if (tls && haveDH && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
- if (tls1_2 && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
- }
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
- }
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
- if (tls && havePSK) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
- if (tls && havePSK) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
- }
- #endif
- #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
- if (haveRSA ) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
- }
- #endif
- #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
- if (haveRSA ) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
- }
- #endif
- #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
- if (haveRSA ) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_MD5;
- }
- #endif
-
- #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_SHA;
- }
- #endif
- #ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
- if (tls && haveRSA) {
- suites->suites[idx++] = 0;
- suites->suites[idx++] = TLS_RSA_WITH_RABBIT_CBC_SHA;
- }
- #endif
- suites->suiteSz = idx;
- }
- int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
- {
- int ret;
- byte havePSK = 0;
- ssl->ctx = ctx; /* only for passing to calls, options could change */
- ssl->version = ctx->method->version;
- ssl->suites = ctx->suites;
- #ifdef HAVE_LIBZ
- ssl->didStreamInit = 0;
- #endif
-
- ssl->buffers.certificate.buffer = 0;
- ssl->buffers.key.buffer = 0;
- ssl->buffers.certChain.buffer = 0;
- ssl->buffers.inputBuffer.length = 0;
- ssl->buffers.inputBuffer.idx = 0;
- ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
- ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
- ssl->buffers.inputBuffer.dynamicFlag = 0;
- ssl->buffers.outputBuffer.length = 0;
- ssl->buffers.outputBuffer.idx = 0;
- ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
- ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
- ssl->buffers.outputBuffer.dynamicFlag = 0;
- ssl->buffers.domainName.buffer = 0;
- ssl->buffers.serverDH_P.buffer = 0;
- ssl->buffers.serverDH_G.buffer = 0;
- ssl->buffers.serverDH_Pub.buffer = 0;
- ssl->buffers.serverDH_Priv.buffer = 0;
- ssl->buffers.clearOutputBuffer.buffer = 0;
- ssl->buffers.clearOutputBuffer.length = 0;
- ssl->buffers.prevSent = 0;
- ssl->buffers.plainSz = 0;
- if ( (ret = InitRng(&ssl->rng)) != 0)
- return ret;
- InitMd5(&ssl->hashMd5);
- InitSha(&ssl->hashSha);
- #ifndef NO_SHA256
- InitSha256(&ssl->hashSha256);
- #endif
- InitRsaKey(&ssl->peerRsaKey, ctx->heap);
- ssl->verifyCallback = ctx->verifyCallback;
- ssl->peerRsaKeyPresent = 0;
- ssl->options.side = ctx->method->side;
- ssl->options.downgrade = ctx->method->downgrade;
- ssl->error = 0;
- ssl->options.connReset = 0;
- ssl->options.isClosed = 0;
- ssl->options.closeNotify = 0;
- ssl->options.sentNotify = 0;
- ssl->options.usingCompression = 0;
- if (ssl->options.side == SERVER_END)
- ssl->options.haveDH = ctx->haveDH;
- else
- ssl->options.haveDH = 0;
- ssl->options.haveNTRU = ctx->haveNTRU;
- ssl->options.haveECDSA = ctx->haveECDSA;
- ssl->options.havePeerCert = 0;
- ssl->options.usingPSK_cipher = 0;
- ssl->options.sendAlertState = 0;
- #ifndef NO_PSK
- havePSK = ctx->havePSK;
- ssl->options.havePSK = ctx->havePSK;
- ssl->options.client_psk_cb = ctx->client_psk_cb;
- ssl->options.server_psk_cb = ctx->server_psk_cb;
- #endif /* NO_PSK */
- ssl->options.serverState = NULL_STATE;
- ssl->options.clientState = NULL_STATE;
- ssl->options.connectState = CONNECT_BEGIN;
- ssl->options.acceptState = ACCEPT_BEGIN;
- ssl->options.handShakeState = NULL_STATE;
- ssl->options.processReply = doProcessInit;
- #ifdef CYASSL_DTLS
- ssl->keys.dtls_sequence_number = 0;
- ssl->keys.dtls_peer_sequence_number = 0;
- ssl->keys.dtls_handshake_number = 0;
- ssl->keys.dtls_epoch = 0;
- ssl->keys.dtls_peer_epoch = 0;
- #endif
- ssl->keys.encryptionOn = 0; /* initially off */
- ssl->options.sessionCacheOff = ctx->sessionCacheOff;
- ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
- ssl->options.verifyPeer = ctx->verifyPeer;
- ssl->options.verifyNone = ctx->verifyNone;
- ssl->options.failNoCert = ctx->failNoCert;
- ssl->options.sendVerify = ctx->sendVerify;
-
- ssl->options.resuming = 0;
- ssl->hmac = Hmac; /* default to SSLv3 */
- ssl->heap = ctx->heap; /* defaults to self */
- ssl->options.tls = 0;
- ssl->options.tls1_1 = 0;
- ssl->options.dtls = 0;
- ssl->options.partialWrite = ctx->partialWrite;
- ssl->options.quietShutdown = ctx->quietShutdown;
- ssl->options.certOnly = 0;
- /* ctx still owns certificate, certChain, key, dh, and caList buffers */
- ssl->buffers.certificate = ctx->certificate;
- ssl->buffers.certChain = ctx->certChain;
- ssl->buffers.key = ctx->privateKey;
- if (ssl->options.side == SERVER_END) {
- ssl->buffers.serverDH_P = ctx->serverDH_P;
- ssl->buffers.serverDH_G = ctx->serverDH_G;
- }
- ssl->buffers.weOwnCert = 0;
- ssl->buffers.weOwnKey = 0;
- ssl->buffers.weOwnDH = 0;
- #ifdef OPENSSL_EXTRA
- ssl->peerCert.issuer.sz = 0;
- ssl->peerCert.subject.sz = 0;
- #endif
-
- /* make sure server has cert and key unless using PSK */
- if (ssl->options.side == SERVER_END && !havePSK)
- if (!ssl->buffers.certificate.buffer || !ssl->buffers.key.buffer) {
- CYASSL_MSG("Server missing certificate and/or private key");
- return NO_PRIVATE_KEY;
- }
- #ifndef NO_PSK
- ssl->arrays.client_identity[0] = 0;
- if (ctx->server_hint[0]) /* set in CTX */
- XSTRNCPY(ssl->arrays.server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
- else
- ssl->arrays.server_hint[0] = 0;
- #endif /* NO_PSK */
- #ifdef CYASSL_CALLBACKS
- ssl->hsInfoOn = 0;
- ssl->toInfoOn = 0;
- #endif
- #ifdef HAVE_ECC
- ssl->peerEccKeyPresent = 0;
- ecc_init(&ssl->peerEccKey);
- ssl->peerEccDsaKeyPresent = 0;
- ecc_init(&ssl->peerEccDsaKey);
- ssl->eccDsaKeyPresent = 0;
- ecc_init(&ssl->eccDsaKey);
- ssl->eccTempKeyPresent = 0;
- ecc_init(&ssl->eccTempKey);
- /* make ECDHE for server side */
- if (ssl->options.side == SERVER_END) {
- if (ecc_make_key(&ssl->rng, ECDHE_SIZE, &ssl->eccTempKey) != 0)
- return ECC_MAKEKEY_ERROR;
- ssl->eccTempKeyPresent = 1;
- }
- #endif
- /* make sure server has DH parms, and add PSK if there, add NTRU too */
- if (ssl->options.side == SERVER_END)
- InitSuites(&ssl->suites, ssl->version,ssl->options.haveDH, havePSK,
- ssl->options.haveNTRU, ssl->options.haveECDSA,
- ssl->ctx->method->side);
- else
- InitSuites(&ssl->suites, ssl->version, TRUE, havePSK,
- ssl->options.haveNTRU, ssl->options.haveECDSA,
- ssl->ctx->method->side);
- ssl->rfd = -1; /* set to invalid descriptor */
- ssl->wfd = -1;
- ssl->biord = 0;
- ssl->biowr = 0;
- ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer acess if not */
- ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
- #ifdef SESSION_CERTS
- ssl->session.chain.count = 0;
- #endif
- ssl->cipher.ssl = ssl;
- return 0;
- }
- /* In case holding SSL object in array and don't want to free actual ssl */
- void SSL_ResourceFree(CYASSL* ssl)
- {
- XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
- XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
- /* parameters (p,g) may be owned by ctx */
- if (ssl->buffers.weOwnDH) {
- XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
- XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
- }
- XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
- /* CYASSL_CTX always owns certChain */
- if (ssl->buffers.weOwnCert)
- XFREE(ssl->buffers.certificate.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
- if (ssl->buffers.weOwnKey)
- XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY);
- FreeRsaKey(&ssl->peerRsaKey);
- if (ssl->buffers.inputBuffer.dynamicFlag)
- ShrinkInputBuffer(ssl, FORCED_FREE);
- if (ssl->buffers.outputBuffer.dynamicFlag)
- ShrinkOutputBuffer(ssl);
- #if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
- CyaSSL_BIO_free(ssl->biord);
- if (ssl->biord != ssl->biowr) /* in case same as write */
- CyaSSL_BIO_free(ssl->biowr);
- #endif
- #ifdef HAVE_LIBZ
- FreeStreams(ssl);
- #endif
- #ifdef HAVE_ECC
- ecc_free(&ssl->peerEccKey);
- ecc_free(&ssl->peerEccDsaKey);
- ecc_free(&ssl->eccTempKey);
- ecc_free(&ssl->eccDsaKey);
- #endif
- }
- void FreeSSL(CYASSL* ssl)
- {
- SSL_ResourceFree(ssl);
- XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL);
- }
- ProtocolVersion MakeSSLv3(void)
- {
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = SSLv3_MINOR;
- return pv;
- }
- #ifdef CYASSL_DTLS
- ProtocolVersion MakeDTLSv1(void)
- {
- ProtocolVersion pv;
- pv.major = DTLS_MAJOR;
- pv.minor = DTLS_MINOR;
- return pv;
- }
- #endif /* CYASSL_DTLS */
- #ifdef USE_WINDOWS_API
- timer_d Timer(void)
- {
- static int init = 0;
- static LARGE_INTEGER freq;
- LARGE_INTEGER count;
-
- if (!init) {
- QueryPerformanceFrequency(&freq);
- init = 1;
- }
- QueryPerformanceCounter(&count);
- return (double)count.QuadPart / freq.QuadPart;
- }
- word32 LowResTimer(void)
- {
- return (word32)Timer();
- }
- #elif defined(THREADX)
- #include "rtptime.h"
- word32 LowResTimer(void)
- {
- return (word32)rtp_get_system_sec();
- }
- #elif defined(MICRIUM)
- word32 LowResTimer(void)
- {
- NET_SECURE_OS_TICK clk;
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- clk = NetSecure_OS_TimeGet();
- #endif
- return (word32)clk;
- }
- #elif defined(USER_TICKS)
- word32 LowResTimer(void)
- {
- /*
- write your own clock tick function if don't want time(0)
- needs second accuracy but doesn't have to correlated to EPOCH
- */
- }
- #else /* !USE_WINDOWS_API && !THREADX && !MICRIUM && !USER_TICKS */
- #include <time.h>
- word32 LowResTimer(void)
- {
- return time(0);
- }
- #endif /* USE_WINDOWS_API */
- /* add output to md5 and sha handshake hashes, exclude record header */
- static void HashOutput(CYASSL* ssl, const byte* output, int sz, int ivSz)
- {
- const byte* adj = output + RECORD_HEADER_SZ + ivSz;
- sz -= RECORD_HEADER_SZ;
-
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- adj += DTLS_RECORD_EXTRA;
- sz -= DTLS_RECORD_EXTRA;
- }
- #endif
- Md5Update(&ssl->hashMd5, adj, sz);
- ShaUpdate(&ssl->hashSha, adj, sz);
- #ifndef NO_SHA256
- if (IsAtLeastTLSv1_2(ssl))
- Sha256Update(&ssl->hashSha256, adj, sz);
- #endif
- }
- /* add input to md5 and sha handshake hashes, include handshake header */
- static void HashInput(CYASSL* ssl, const byte* input, int sz)
- {
- const byte* adj = input - HANDSHAKE_HEADER_SZ;
- sz += HANDSHAKE_HEADER_SZ;
-
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- adj -= DTLS_HANDSHAKE_EXTRA;
- sz += DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- Md5Update(&ssl->hashMd5, adj, sz);
- ShaUpdate(&ssl->hashSha, adj, sz);
- #ifndef NO_SHA256
- if (IsAtLeastTLSv1_2(ssl))
- Sha256Update(&ssl->hashSha256, adj, sz);
- #endif
- }
- /* add record layer header for message */
- static void AddRecordHeader(byte* output, word32 length, byte type, CYASSL* ssl)
- {
- RecordLayerHeader* rl;
-
- /* record layer header */
- rl = (RecordLayerHeader*)output;
- rl->type = type;
- rl->version = ssl->version; /* type and version same in each */
- if (!ssl->options.dtls)
- c16toa((word16)length, rl->length);
- else {
- #ifdef CYASSL_DTLS
- DtlsRecordLayerHeader* dtls;
-
- /* dtls record layer header extensions */
- dtls = (DtlsRecordLayerHeader*)output;
- c16toa(ssl->keys.dtls_epoch, dtls->epoch);
- c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
- c16toa((word16)length, dtls->length);
- #endif
- }
- }
- /* add handshake header for message */
- static void AddHandShakeHeader(byte* output, word32 length, byte type,
- CYASSL* ssl)
- {
- HandShakeHeader* hs;
- (void)ssl;
-
- /* handshake header */
- hs = (HandShakeHeader*)output;
- hs->type = type;
- c32to24(length, hs->length); /* type and length same for each */
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- DtlsHandShakeHeader* dtls;
-
- /* dtls handshake header extensions */
- dtls = (DtlsHandShakeHeader*)output;
- c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
- c32to24(0, dtls->fragment_offset);
- c32to24(length, dtls->fragment_length);
- }
- #endif
- }
- /* add both headers for handshake message */
- static void AddHeaders(byte* output, word32 length, byte type, CYASSL* ssl)
- {
- if (!ssl->options.dtls) {
- AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl);
- AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, ssl);
- }
- #ifdef CYASSL_DTLS
- else {
- AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl);
- AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl);
- }
- #endif
- }
- /* return bytes received, -1 on error */
- static int Receive(CYASSL* ssl, byte* buf, word32 sz)
- {
- int recvd;
- retry:
- recvd = ssl->ctx->CBIORecv((char *)buf, (int)sz, ssl->IOCB_ReadCtx);
- if (recvd < 0)
- switch (recvd) {
- case IO_ERR_GENERAL: /* general/unknown error */
- return -1;
- case IO_ERR_WANT_READ: /* want read, would block */
- return WANT_READ;
- case IO_ERR_CONN_RST: /* connection reset */
- ssl->options.connReset = 1;
- return -1;
- case IO_ERR_ISR: /* interrupt */
- /* see if we got our timeout */
- #ifdef CYASSL_CALLBACKS
- if (ssl->toInfoOn) {
- struct itimerval timeout;
- getitimer(ITIMER_REAL, &timeout);
- if (timeout.it_value.tv_sec == 0 &&
- timeout.it_value.tv_usec == 0) {
- XSTRNCPY(ssl->timeoutInfo.timeoutName,
- "recv() timeout", MAX_TIMEOUT_NAME_SZ);
- CYASSL_MSG("Got our timeout");
- return WANT_READ;
- }
- }
- #endif
- goto retry;
- case IO_ERR_CONN_CLOSE: /* peer closed connection */
- ssl->options.isClosed = 1;
- return -1;
- default:
- return recvd;
- }
- return recvd;
- }
- /* Switch dynamic output buffer back to static, buffer is assumed clear */
- void ShrinkOutputBuffer(CYASSL* ssl)
- {
- CYASSL_MSG("Shrinking output buffer\n");
- XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
- ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
- ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
- ssl->buffers.outputBuffer.dynamicFlag = 0;
- }
- /* Switch dynamic input buffer back to static, keep any remaining input */
- /* forced free means cleaning up */
- void ShrinkInputBuffer(CYASSL* ssl, int forcedFree)
- {
- int usedLength = ssl->buffers.inputBuffer.length -
- ssl->buffers.inputBuffer.idx;
- if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
- return;
- CYASSL_MSG("Shrinking input buffer\n");
- if (!forcedFree && usedLength)
- XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
- ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
- usedLength);
- XFREE(ssl->buffers.inputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
- ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
- ssl->buffers.inputBuffer.dynamicFlag = 0;
- ssl->buffers.inputBuffer.idx = 0;
- ssl->buffers.inputBuffer.length = usedLength;
- }
- int SendBuffered(CYASSL* ssl)
- {
- while (ssl->buffers.outputBuffer.length > 0) {
- int sent = ssl->ctx->CBIOSend((char*)ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx,
- (int)ssl->buffers.outputBuffer.length,
- ssl->IOCB_WriteCtx);
- if (sent < 0) {
- switch (sent) {
- case IO_ERR_WANT_WRITE: /* would block */
- return WANT_WRITE;
- case IO_ERR_CONN_RST: /* connection reset */
- ssl->options.connReset = 1;
- break;
- case IO_ERR_ISR: /* interrupt */
- /* see if we got our timeout */
- #ifdef CYASSL_CALLBACKS
- if (ssl->toInfoOn) {
- struct itimerval timeout;
- getitimer(ITIMER_REAL, &timeout);
- if (timeout.it_value.tv_sec == 0 &&
- timeout.it_value.tv_usec == 0) {
- XSTRNCPY(ssl->timeoutInfo.timeoutName,
- "send() timeout", MAX_TIMEOUT_NAME_SZ);
- CYASSL_MSG("Got our timeout");
- return WANT_WRITE;
- }
- }
- #endif
- continue;
- case IO_ERR_CONN_CLOSE: /* epipe / conn closed, same as reset */
- ssl->options.connReset = 1;
- break;
- default:
- return SOCKET_ERROR_E;
- }
- return SOCKET_ERROR_E;
- }
- ssl->buffers.outputBuffer.idx += sent;
- ssl->buffers.outputBuffer.length -= sent;
- }
-
- ssl->buffers.outputBuffer.idx = 0;
- if (ssl->buffers.outputBuffer.dynamicFlag)
- ShrinkOutputBuffer(ssl);
- return 0;
- }
- /* Grow the output buffer, should only be to send cert, should be blank */
- static INLINE int GrowOutputBuffer(CYASSL* ssl, int size)
- {
- byte* tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length,
- ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
- CYASSL_MSG("growing output buffer\n");
-
- if (!tmp) return MEMORY_E;
- if (ssl->buffers.outputBuffer.length)
- XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
- ssl->buffers.outputBuffer.length);
- if (ssl->buffers.outputBuffer.dynamicFlag)
- XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap,
- DYNAMIC_TYPE_OUT_BUFFER);
- ssl->buffers.outputBuffer.dynamicFlag = 1;
- ssl->buffers.outputBuffer.buffer = tmp;
- ssl->buffers.outputBuffer.bufferSize = size +
- ssl->buffers.outputBuffer.length;
- return 0;
- }
- /* Grow the input buffer, should only be to read cert or big app data */
- static INLINE int GrowInputBuffer(CYASSL* ssl, int size, int usedLength)
- {
- byte* tmp = (byte*) XMALLOC(size + usedLength, ssl->heap,
- DYNAMIC_TYPE_IN_BUFFER);
- CYASSL_MSG("growing input buffer\n");
-
- if (!tmp) return MEMORY_E;
- if (usedLength)
- XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx, usedLength);
- if (ssl->buffers.inputBuffer.dynamicFlag)
- XFREE(ssl->buffers.inputBuffer.buffer,ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
- ssl->buffers.inputBuffer.dynamicFlag = 1;
- ssl->buffers.inputBuffer.buffer = tmp;
- ssl->buffers.inputBuffer.bufferSize = size + usedLength;
- ssl->buffers.inputBuffer.idx = 0;
- ssl->buffers.inputBuffer.length = usedLength;
- return 0;
- }
- /* check avalaible size into output buffer */
- static INLINE int CheckAvalaibleSize(CYASSL *ssl, int size)
- {
- if ((word32)size > ssl->buffers.outputBuffer.bufferSize)
- if (GrowOutputBuffer(ssl, size) < 0)
- return MEMORY_E;
- if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
- < (word32)size) {
- if (SendBuffered(ssl) == SOCKET_ERROR_E)
- return SOCKET_ERROR_E;
- if (ssl->buffers.outputBuffer.bufferSize -
- ssl->buffers.outputBuffer.length < (word32)size)
- return WANT_WRITE;
- }
- return 0;
- }
- /* do all verify and sanity checks on record header */
- static int GetRecordHeader(CYASSL* ssl, const byte* input, word32* inOutIdx,
- RecordLayerHeader* rh, word16 *size)
- {
- if (!ssl->options.dtls) {
- XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
- *inOutIdx += RECORD_HEADER_SZ;
- ato16(rh->length, size);
- }
- else {
- #ifdef CYASSL_DTLS
- /* type and version in same sport */
- XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
- *inOutIdx += ENUM_LEN + VERSION_SZ;
- *inOutIdx += 4; /* skip epoch and first 2 seq bytes for now */
- ato32(input + *inOutIdx, &ssl->keys.dtls_peer_sequence_number);
- *inOutIdx += 4; /* advance past rest of seq */
- ato16(input + *inOutIdx, size);
- *inOutIdx += LENGTH_SZ;
- #endif
- }
- /* catch version mismatch */
- if (rh->version.major != ssl->version.major ||
- rh->version.minor != ssl->version.minor) {
-
- if (ssl->options.side == SERVER_END &&
- ssl->options.acceptState == ACCEPT_BEGIN)
- CYASSL_MSG("Client attempting to connect with different version");
- else if (ssl->options.side == CLIENT_END && ssl->options.downgrade &&
- ssl->options.connectState < FIRST_REPLY_DONE)
- CYASSL_MSG("Server attempting to accept with different version");
- else {
- CYASSL_MSG("SSL version error");
- return VERSION_ERROR; /* only use requested version */
- }
- }
- /* record layer length check */
- if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
- return LENGTH_ERROR;
- /* verify record type here as well */
- switch ((enum ContentType)rh->type) {
- case handshake:
- case change_cipher_spec:
- case application_data:
- case alert:
- break;
- case no_type:
- default:
- CYASSL_MSG("Unknown Record Type");
- return UNKNOWN_RECORD_TYPE;
- }
- return 0;
- }
- static int GetHandShakeHeader(CYASSL* ssl, const byte* input, word32* inOutIdx,
- byte *type, word32 *size)
- {
- const byte *ptr = input + *inOutIdx;
- (void)ssl;
- *inOutIdx += HANDSHAKE_HEADER_SZ;
-
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls)
- *inOutIdx += DTLS_HANDSHAKE_EXTRA;
- #endif
- *type = ptr[0];
- c24to32(&ptr[1], size);
- return 0;
- }
- /* fill with MD5 pad size since biggest required */
- static const byte PAD1[PAD_MD5] =
- { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
- };
- static const byte PAD2[PAD_MD5] =
- { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
- };
- /* calculate MD5 hash for finished */
- static void BuildMD5(CYASSL* ssl, Hashes* hashes, const byte* sender)
- {
- byte md5_result[MD5_DIGEST_SIZE];
- /* make md5 inner */
- Md5Update(&ssl->hashMd5, sender, SIZEOF_SENDER);
- Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
- Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
- Md5Final(&ssl->hashMd5, md5_result);
- /* make md5 outer */
- Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
- Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
- Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
- Md5Final(&ssl->hashMd5, hashes->md5);
- }
- /* calculate SHA hash for finished */
- static void BuildSHA(CYASSL* ssl, Hashes* hashes, const byte* sender)
- {
- byte sha_result[SHA_DIGEST_SIZE];
- /* make sha inner */
- ShaUpdate(&ssl->hashSha, sender, SIZEOF_SENDER);
- ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
- ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
- ShaFinal(&ssl->hashSha, sha_result);
- /* make sha outer */
- ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
- ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
- ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
- ShaFinal(&ssl->hashSha, hashes->sha);
- }
- static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
- {
- /* store current states, building requires get_digest which resets state */
- Md5 md5 = ssl->hashMd5;
- Sha sha = ssl->hashSha;
- #ifndef NO_SHA256
- Sha256 sha256;
- InitSha256(&sha256);
- if (IsAtLeastTLSv1_2(ssl))
- sha256 = ssl->hashSha256;
- #endif
- if (ssl->options.tls)
- BuildTlsFinished(ssl, hashes, sender);
- else {
- BuildMD5(ssl, hashes, sender);
- BuildSHA(ssl, hashes, sender);
- }
-
- /* restore */
- ssl->hashMd5 = md5;
- ssl->hashSha = sha;
- #ifndef NO_SHA256
- if (IsAtLeastTLSv1_2(ssl))
- ssl->hashSha256 = sha256;
- #endif
- }
- static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx)
- {
- word32 listSz, i = *inOutIdx;
- int ret = 0;
- int anyError = 0;
- int totalCerts = 0; /* number of certs in certs buffer */
- int count;
- char domain[ASN_NAME_MAX];
- buffer certs[MAX_CHAIN_DEPTH];
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
- if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo);
- #endif
- c24to32(&input[i], &listSz);
- i += CERT_HEADER_SZ;
- CYASSL_MSG("Loading peer's cert chain");
- /* first put cert chain into buffer so can verify top down
- we're sent bottom up */
- while (listSz) {
- /* cert size */
- word32 certSz;
- if (totalCerts >= MAX_CHAIN_DEPTH)
- return BUFFER_E;
- c24to32(&input[i], &certSz);
- i += CERT_HEADER_SZ;
-
- if (listSz > MAX_RECORD_SIZE || certSz > MAX_RECORD_SIZE)
- return BUFFER_E;
- certs[totalCerts].length = certSz;
- certs[totalCerts].buffer = input + i;
- #ifdef SESSION_CERTS
- if (ssl->session.chain.count < MAX_CHAIN_DEPTH &&
- certSz < MAX_X509_SIZE) {
- ssl->session.chain.certs[ssl->session.chain.count].length = certSz;
- XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer,
- input + i, certSz);
- ssl->session.chain.count++;
- } else {
- CYASSL_MSG("Couldn't store chain cert for session");
- }
- #endif
- i += certSz;
- listSz -= certSz + CERT_HEADER_SZ;
- totalCerts++;
- CYASSL_MSG(" Put another cert into chain");
- }
- count = totalCerts;
- /* verify up to peer's first */
- while (count > 1) {
- buffer myCert = certs[count - 1];
- DecodedCert dCert;
- InitDecodedCert(&dCert, myCert.buffer, myCert.length, ssl->heap);
- ret = ParseCertRelative(&dCert, CERT_TYPE, !ssl->options.verifyNone,
- ssl->ctx->caList);
- if (ret == 0 && !IsCA(ssl->ctx, dCert.subjectHash)) {
- buffer add;
- add.length = myCert.length;
- add.buffer = (byte*)XMALLOC(myCert.length, ssl->heap,
- DYNAMIC_TYPE_CA);
- CYASSL_MSG("Adding CA from chain");
- if (add.buffer == NULL)
- return MEMORY_E;
- XMEMCPY(add.buffer, myCert.buffer, myCert.length);
- ret = AddCA(ssl->ctx, add);
- if (ret == 1) ret = 0; /* SSL_SUCCESS for external */
- }
- else if (ret != 0) {
- CYASSL_MSG("Failed to verify CA from chain");
- (void)ret;
- }
- else {
- CYASSL_MSG("Verified CA from chain and already had it");
- (void)ret;
- }
- if (ret != 0 && anyError == 0)
- anyError = ret; /* save error from last time */
- FreeDecodedCert(&dCert);
- count--;
- }
- /* peer's, may not have one if blank client cert sent by TLSv1.2 */
- if (count) {
- buffer myCert = certs[0];
- DecodedCert dCert;
- CYASSL_MSG("Veriying Peer's cert");
- InitDecodedCert(&dCert, myCert.buffer, myCert.length, ssl->heap);
- ret = ParseCertRelative(&dCert, CERT_TYPE, !ssl->options.verifyNone,
- ssl->ctx->caList);
- if (ret != 0) {
- CYASSL_MSG("Failed to verify Peer's cert");
- (void)ret;
- }
- ssl->options.havePeerCert = 1;
- /* set X509 format */
- #ifdef OPENSSL_EXTRA
- ssl->peerCert.issuer.sz = (int)XSTRLEN(dCert.issuer) + 1;
- XSTRNCPY(ssl->peerCert.issuer.name, dCert.issuer, ASN_NAME_MAX);
- ssl->peerCert.subject.sz = (int)XSTRLEN(dCert.subject) + 1;
- XSTRNCPY(ssl->peerCert.subject.name, dCert.subject, ASN_NAME_MAX);
- XMEMCPY(ssl->peerCert.serial, dCert.serial, EXTERNAL_SERIAL_SIZE);
- ssl->peerCert.serialSz = dCert.serialSz;
- if (dCert.subjectCNLen < ASN_NAME_MAX) {
- XMEMCPY(ssl->peerCert.subjectCN,dCert.subjectCN,dCert.subjectCNLen);
- ssl->peerCert.subjectCN[dCert.subjectCNLen] = '\0';
- }
- else
- ssl->peerCert.subjectCN[0] = '\0';
- #endif
- /* store for callback use */
- if (dCert.subjectCNLen < ASN_NAME_MAX) {
- XMEMCPY(domain, dCert.subjectCN, dCert.subjectCNLen);
- domain[dCert.subjectCNLen] = '\0';
- }
- else
- domain[0] = '\0';
- if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer)
- if (XSTRNCMP((char*)ssl->buffers.domainName.buffer,
- dCert.subjectCN,
- ssl->buffers.domainName.length - 1)) {
- ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */
- }
- /* decode peer key */
- if (dCert.keyOID == RSAk) {
- word32 idx = 0;
- if (RsaPublicKeyDecode(dCert.publicKey, &idx,
- &ssl->peerRsaKey, dCert.pubKeySize) != 0) {
- ret = PEER_KEY_ERROR;
- }
- ssl->peerRsaKeyPresent = 1;
- }
- #ifdef HAVE_NTRU
- else if (dCert.keyOID == NTRUk) {
- if (dCert.pubKeySize > sizeof(ssl->peerNtruKey)) {
- ret = PEER_KEY_ERROR;
- }
- XMEMCPY(ssl->peerNtruKey, dCert.publicKey, dCert.pubKeySize);
- ssl->peerNtruKeyLen = (word16)dCert.pubKeySize;
- ssl->peerNtruKeyPresent = 1;
- }
- #endif /* HAVE_NTRU */
- #ifdef HAVE_ECC
- else if (dCert.keyOID == ECDSAk) {
- if (ecc_import_x963(dCert.publicKey, dCert.pubKeySize,
- &ssl->peerEccDsaKey) != 0) {
- ret = PEER_KEY_ERROR;
- }
- ssl->peerEccDsaKeyPresent = 1;
- }
- #endif /* HAVE_ECC */
- FreeDecodedCert(&dCert);
- }
-
- if (anyError != 0 && ret == 0)
- ret = anyError;
- if (ret == 0 && ssl->options.side == CLIENT_END)
- ssl->options.serverState = SERVER_CERT_COMPLETE;
- if (ret != 0) {
- if (!ssl->options.verifyNone) {
- int why = bad_certificate;
- if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E)
- why = certificate_expired;
- if (ssl->verifyCallback) {
- int ok;
- CYASSL_X509_STORE_CTX store;
- store.error = ret;
- store.error_depth = totalCerts;
- store.domain = domain;
- #ifdef OPENSSL_EXTRA
- store.current_cert = &ssl->peerCert;
- #else
- store.current_cert = NULL;
- #endif
- ok = ssl->verifyCallback(0, &store);
- if (ok) {
- CYASSL_MSG("Verify callback overriding error!");
- ret = 0;
- }
- }
- if (ret != 0) {
- SendAlert(ssl, alert_fatal, why); /* try to send */
- ssl->options.isClosed = 1;
- }
- }
- ssl->error = ret;
- }
- *inOutIdx = i;
- return ret;
- }
- int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
- {
- byte verifyMAC[SHA256_DIGEST_SIZE];
- int finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ;
- int headerSz = HANDSHAKE_HEADER_SZ;
- word32 macSz = finishedSz + HANDSHAKE_HEADER_SZ,
- idx = *inOutIdx,
- padSz = ssl->keys.encryptSz - HANDSHAKE_HEADER_SZ - finishedSz -
- ssl->specs.hash_size;
- const byte* mac;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- headerSz += DTLS_HANDSHAKE_EXTRA;
- macSz += DTLS_HANDSHAKE_EXTRA;
- padSz -= DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
- if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
- #endif
- if (sniff == NO_SNIFF) {
- if (XMEMCMP(input + idx, &ssl->verifyHashes, finishedSz)) {
- CYASSL_MSG("Verify finished error on hashes");
- return VERIFY_FINISHED_ERROR;
- }
- }
- ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
- handshake, 1);
- idx += finishedSz;
- /* read mac and fill */
- mac = input + idx;
- idx += ssl->specs.hash_size;
- if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
- padSz -= ssl->specs.block_size;
- idx += padSz;
- /* verify mac */
- if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) {
- CYASSL_MSG("Verify finished error on mac");
- return VERIFY_MAC_ERROR;
- }
- if (ssl->options.side == CLIENT_END) {
- ssl->options.serverState = SERVER_FINISHED_COMPLETE;
- if (!ssl->options.resuming)
- ssl->options.handShakeState = HANDSHAKE_DONE;
- }
- else {
- ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
- if (ssl->options.resuming)
- ssl->options.handShakeState = HANDSHAKE_DONE;
- }
- *inOutIdx = idx;
- return 0;
- }
- static int DoHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx,
- word32 totalSz)
- {
- byte type;
- word32 size;
- int ret = 0;
- CYASSL_ENTER("DoHandShakeMsg()");
- if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size) != 0)
- return PARSE_ERROR;
- if (*inOutIdx + size > totalSz)
- return INCOMPLETE_DATA;
-
- HashInput(ssl, input + *inOutIdx, size);
- #ifdef CYASSL_CALLBACKS
- /* add name later, add on record and handshake header part back on */
- if (ssl->toInfoOn) {
- int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add,
- size + add, ssl->heap);
- AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
- }
- #endif
- switch (type) {
- #ifndef NO_CYASSL_CLIENT
- case hello_verify_request:
- CYASSL_MSG("processing hello verify request");
- ret = DoHelloVerifyRequest(ssl, input,inOutIdx);
- break;
-
- case server_hello:
- CYASSL_MSG("processing server hello");
- ret = DoServerHello(ssl, input, inOutIdx);
- break;
- case certificate_request:
- CYASSL_MSG("processing certificate request");
- ret = DoCertificateRequest(ssl, input, inOutIdx);
- break;
- case server_key_exchange:
- CYASSL_MSG("processing server key exchange");
- ret = DoServerKeyExchange(ssl, input, inOutIdx);
- break;
- #endif
- case certificate:
- CYASSL_MSG("processing certificate");
- ret = DoCertificate(ssl, input, inOutIdx);
- break;
- case server_hello_done:
- CYASSL_MSG("processing server hello done");
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("ServerHelloDone", &ssl->timeoutInfo);
- #endif
- ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
- break;
- case finished:
- CYASSL_MSG("processing finished");
- ret = DoFinished(ssl, input, inOutIdx, NO_SNIFF);
- break;
- #ifndef NO_CYASSL_SERVER
- case client_hello:
- CYASSL_MSG("processing client hello");
- ret = DoClientHello(ssl, input, inOutIdx, totalSz, size);
- break;
- case client_key_exchange:
- CYASSL_MSG("processing client key exchange");
- ret = DoClientKeyExchange(ssl, input, inOutIdx);
- break;
- case certificate_verify:
- CYASSL_MSG("processing certificate verify");
- ret = DoCertificateVerify(ssl, input, inOutIdx, totalSz);
- break;
- #endif
- default:
- CYASSL_MSG("Unknown handshake message type");
- ret = UNKNOWN_HANDSHAKE_TYPE;
- }
- CYASSL_LEAVE("DoHandShakeMsg()", ret);
- return ret;
- }
- static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
- {
- switch (ssl->specs.bulk_cipher_algorithm) {
- #ifdef BUILD_ARC4
- case rc4:
- Arc4Process(&ssl->encrypt.arc4, out, input, sz);
- break;
- #endif
- #ifdef BUILD_DES3
- case triple_des:
- Des3_CbcEncrypt(&ssl->encrypt.des3, out, input, sz);
- break;
- #endif
- #ifdef BUILD_AES
- case aes:
- #ifdef CYASSL_AESNI
- if ((word)input % 16) {
- byte buffer[MAX_RECORD_SIZE + MAX_COMP_EXTRA+MAX_MSG_EXTRA];
- XMEMCPY(buffer, input, sz);
- AesCbcEncrypt(&ssl->encrypt.aes, buffer, buffer, sz);
- XMEMCPY(out, buffer, sz);
- break;
- }
- #endif
- AesCbcEncrypt(&ssl->encrypt.aes, out, input, sz);
- break;
- #endif
- #ifdef HAVE_HC128
- case hc128:
- Hc128_Process(&ssl->encrypt.hc128, out, input, sz);
- break;
- #endif
- #ifdef BUILD_RABBIT
- case rabbit:
- RabbitProcess(&ssl->encrypt.rabbit, out, input, sz);
- break;
- #endif
- default:
- CYASSL_MSG("CyaSSL Encrypt programming error");
- }
- }
- static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input,
- word32 sz)
- {
- switch (ssl->specs.bulk_cipher_algorithm) {
- #ifdef BUILD_ARC4
- case rc4:
- Arc4Process(&ssl->decrypt.arc4, plain, input, sz);
- break;
- #endif
- #ifdef BUILD_DES3
- case triple_des:
- Des3_CbcDecrypt(&ssl->decrypt.des3, plain, input, sz);
- break;
- #endif
- #ifdef BUILD_AES
- case aes:
- AesCbcDecrypt(&ssl->decrypt.aes, plain, input, sz);
- break;
- #endif
- #ifdef HAVE_HC128
- case hc128:
- Hc128_Process(&ssl->decrypt.hc128, plain, input, sz);
- break;
- #endif
- #ifdef BUILD_RABBIT
- case rabbit:
- RabbitProcess(&ssl->decrypt.rabbit, plain, input, sz);
- break;
- #endif
- default:
- CYASSL_MSG("CyaSSL Decrypt programming error");
- }
- }
- /* decrypt input message in place */
- static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx)
- {
- Decrypt(ssl, input, input, sz);
- ssl->keys.encryptSz = sz;
- if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
- *idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
- return 0;
- }
- static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
- {
- if (verify)
- return ssl->keys.peer_sequence_number++;
- else
- return ssl->keys.sequence_number++;
- }
- int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
- {
- word32 msgSz = ssl->keys.encryptSz;
- word32 pad = 0,
- padByte = 0,
- idx = *inOutIdx,
- digestSz = ssl->specs.hash_size;
- int dataSz;
- int ivExtra = 0;
- byte* rawData = input + idx; /* keep current for hmac */
- #ifdef HAVE_LIBZ
- byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
- #endif
- byte verify[SHA256_DIGEST_SIZE];
- const byte* mac;
- if (ssl->specs.cipher_type == block) {
- if (ssl->options.tls1_1)
- ivExtra = ssl->specs.block_size;
- pad = *(input + idx + msgSz - ivExtra - 1);
- padByte = 1;
- }
- dataSz = msgSz - ivExtra - digestSz - pad - padByte;
- if (dataSz < 0) {
- CYASSL_MSG("App data buffer error, malicious input?");
- return BUFFER_ERROR;
- }
- /* read data */
- if (dataSz) {
- int rawSz = dataSz; /* keep raw size for hmac */
- ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
- #ifdef HAVE_LIBZ
- if (ssl->options.usingCompression) {
- dataSz = DeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp));
- if (dataSz < 0) return dataSz;
- }
- #endif
- if (ssl->options.usingCompression)
- idx += rawSz;
- else
- idx += dataSz;
- ssl->buffers.clearOutputBuffer.buffer = rawData;
- ssl->buffers.clearOutputBuffer.length = dataSz;
- }
- /* read mac and fill */
- mac = input + idx;
- idx += digestSz;
-
- idx += pad;
- if (padByte)
- idx++;
- #ifdef HAVE_LIBZ
- if (ssl->options.usingCompression)
- XMEMMOVE(rawData, decomp, dataSz);
- #endif
- /* verify */
- if (dataSz) {
- if (XMEMCMP(mac, verify, digestSz)) {
- CYASSL_MSG("App data verify mac error");
- return VERIFY_MAC_ERROR;
- }
- }
- else
- GetSEQIncrement(ssl, 1); /* even though no data, increment verify */
- *inOutIdx = idx;
- return 0;
- }
- /* process alert, return level */
- static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type)
- {
- byte level;
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("Alert", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- /* add record header back on to info + 2 byte level, data */
- AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx -
- RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap);
- #endif
- level = input[(*inOutIdx)++];
- *type = (int)input[(*inOutIdx)++];
- CYASSL_MSG("Got alert");
- if (*type == close_notify) {
- CYASSL_MSG(" close notify");
- ssl->options.closeNotify = 1;
- }
- CYASSL_ERROR(*type);
- if (ssl->keys.encryptionOn) {
- int aSz = ALERT_SIZE;
- const byte* mac;
- byte verify[SHA256_DIGEST_SIZE];
- int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size;
-
- ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1);
- /* read mac and fill */
- mac = input + *inOutIdx;
- *inOutIdx += (ssl->specs.hash_size + padSz);
- /* verify */
- if (XMEMCMP(mac, verify, ssl->specs.hash_size)) {
- CYASSL_MSG(" alert verify mac error");
- return VERIFY_MAC_ERROR;
- }
- }
- return level;
- }
- static int GetInputData(CYASSL *ssl, word32 size)
- {
- int in;
- int inSz;
- int maxLength;
- int usedLength;
-
- /* check max input length */
- usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
- maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength;
- inSz = (int)(size - usedLength); /* from last partial read */
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls)
- inSz = MAX_MTU; /* read ahead up to MTU */
- #endif
-
- if (inSz > maxLength) {
- if (GrowInputBuffer(ssl, size, usedLength) < 0)
- return MEMORY_E;
- }
-
- if (inSz <= 0)
- return BUFFER_ERROR;
-
- /* Put buffer data at start if not there */
- if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
- XMEMMOVE(ssl->buffers.inputBuffer.buffer,
- ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
- usedLength);
-
- /* remove processed data */
- ssl->buffers.inputBuffer.idx = 0;
- ssl->buffers.inputBuffer.length = usedLength;
-
- /* read data from network */
- do {
- in = Receive(ssl,
- ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.length,
- inSz);
- if (in == -1)
- return SOCKET_ERROR_E;
-
- if (in == WANT_READ)
- return WANT_READ;
-
- ssl->buffers.inputBuffer.length += in;
- inSz -= in;
- } while (ssl->buffers.inputBuffer.length < size);
- return 0;
- }
- /* process input requests, return 0 is done, 1 is call again to complete, and
- negative number is error */
- int ProcessReply(CYASSL* ssl)
- {
- int ret, type, readSz;
- word32 startIdx = 0;
- #ifndef NO_CYASSL_SERVER
- byte b0, b1;
- #endif
- #ifdef CYASSL_DTLS
- int used;
- #endif
- for (;;) {
- switch ((processReply)ssl->options.processReply) {
- /* in the CYASSL_SERVER case, get the first byte for detecting
- * old client hello */
- case doProcessInit:
-
- readSz = RECORD_HEADER_SZ;
-
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls)
- readSz = DTLS_RECORD_HEADER_SZ;
- #endif
- /* get header or return error */
- if (!ssl->options.dtls) {
- if ((ret = GetInputData(ssl, readSz)) < 0)
- return ret;
- } else {
- #ifdef CYASSL_DTLS
- /* read ahead may already have header */
- used = ssl->buffers.inputBuffer.length -
- ssl->buffers.inputBuffer.idx;
- if (used < readSz)
- if ((ret = GetInputData(ssl, readSz)) < 0)
- return ret;
- #endif
- }
- #ifndef NO_CYASSL_SERVER
- /* see if sending SSLv2 client hello */
- if ( ssl->options.side == SERVER_END &&
- ssl->options.clientState == NULL_STATE &&
- ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
- != handshake) {
- ssl->options.processReply = runProcessOldClientHello;
- /* how many bytes need ProcessOldClientHello */
- b0 =
- ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
- b1 =
- ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
- ssl->curSize = ((b0 & 0x7f) << 8) | b1;
- }
- else {
- ssl->options.processReply = getRecordLayerHeader;
- continue;
- }
- /* in the CYASSL_SERVER case, run the old client hello */
- case runProcessOldClientHello:
- /* get sz bytes or return error */
- if (!ssl->options.dtls) {
- if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
- return ret;
- } else {
- #ifdef CYASSL_DTLS
- /* read ahead may already have */
- used = ssl->buffers.inputBuffer.length -
- ssl->buffers.inputBuffer.idx;
- if (used < ssl->curSize)
- if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
- return ret;
- #endif /* CYASSL_DTLS */
- }
- ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
- &ssl->buffers.inputBuffer.idx,
- ssl->buffers.inputBuffer.length -
- ssl->buffers.inputBuffer.idx,
- ssl->curSize);
- if (ret < 0)
- return ret;
- else if (ssl->buffers.inputBuffer.idx ==
- ssl->buffers.inputBuffer.length) {
- ssl->options.processReply = doProcessInit;
- return 0;
- }
- #endif /* NO_CYASSL_SERVER */
- /* get the record layer header */
- case getRecordLayerHeader:
- ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
- &ssl->buffers.inputBuffer.idx,
- &ssl->curRL, &ssl->curSize);
- if (ret != 0)
- return ret;
- ssl->options.processReply = getData;
- /* retrieve record layer data */
- case getData:
- /* get sz bytes or return error */
- if (!ssl->options.dtls) {
- if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
- return ret;
- } else {
- #ifdef CYASSL_DTLS
- /* read ahead may already have */
- used = ssl->buffers.inputBuffer.length -
- ssl->buffers.inputBuffer.idx;
- if (used < ssl->curSize)
- if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
- return ret;
- #endif
- }
-
- ssl->options.processReply = runProcessingOneMessage;
- startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
- /* the record layer is here */
- case runProcessingOneMessage:
- if (ssl->keys.encryptionOn)
- if (DecryptMessage(ssl, ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx,
- ssl->curSize,
- &ssl->buffers.inputBuffer.idx) < 0)
- return DECRYPT_ERROR;
- CYASSL_MSG("received record layer msg");
- switch (ssl->curRL.type) {
- case handshake :
- /* debugging in DoHandShakeMsg */
- if ((ret = DoHandShakeMsg(ssl,
- ssl->buffers.inputBuffer.buffer,
- &ssl->buffers.inputBuffer.idx,
- ssl->buffers.inputBuffer.length))
- != 0)
- return ret;
- break;
- case change_cipher_spec:
- CYASSL_MSG("got CHANGE CIPHER SPEC");
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ChangeCipher", &ssl->handShakeInfo);
- /* add record header back on info */
- if (ssl->toInfoOn) {
- AddPacketInfo("ChangeCipher", &ssl->timeoutInfo,
- ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
- 1 + RECORD_HEADER_SZ, ssl->heap);
- AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
- }
- #endif
- ssl->buffers.inputBuffer.idx++;
- ssl->keys.encryptionOn = 1;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls)
- ssl->keys.dtls_peer_epoch++;
- #endif
- #ifdef HAVE_LIBZ
- if (ssl->options.usingCompression)
- if ( (ret = InitStreams(ssl)) != 0)
- return ret;
- #endif
- if (ssl->options.resuming && ssl->options.side ==
- CLIENT_END)
- BuildFinished(ssl, &ssl->verifyHashes, server);
- else if (!ssl->options.resuming && ssl->options.side ==
- SERVER_END)
- BuildFinished(ssl, &ssl->verifyHashes, client);
- break;
- case application_data:
- CYASSL_MSG("got app DATA");
- if ((ret = DoApplicationData(ssl,
- ssl->buffers.inputBuffer.buffer,
- &ssl->buffers.inputBuffer.idx))
- != 0) {
- CYASSL_ERROR(ret);
- return ret;
- }
- break;
- case alert:
- CYASSL_MSG("got ALERT!");
- if (DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
- &ssl->buffers.inputBuffer.idx, &type) == alert_fatal)
- return FATAL_ERROR;
- /* catch warnings that are handled as errors */
- if (type == close_notify)
- return ssl->error = ZERO_RETURN;
-
- if (type == decrypt_error)
- return FATAL_ERROR;
- break;
-
- default:
- CYASSL_ERROR(UNKNOWN_RECORD_TYPE);
- return UNKNOWN_RECORD_TYPE;
- }
- ssl->options.processReply = doProcessInit;
- /* input exhausted? */
- if (ssl->buffers.inputBuffer.idx == ssl->buffers.inputBuffer.length)
- return 0;
- /* more messages per record */
- else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
- CYASSL_MSG("More messages in record");
- #ifdef CYASSL_DTLS
- /* read-ahead but dtls doesn't bundle messages per record */
- if (ssl->options.dtls) {
- ssl->options.processReply = doProcessInit;
- continue;
- }
- #endif
- ssl->options.processReply = runProcessingOneMessage;
- continue;
- }
- /* more records */
- else {
- CYASSL_MSG("More records in input");
- ssl->options.processReply = doProcessInit;
- continue;
- }
- default:
- CYASSL_MSG("Bad process input state, programming error");
- return INPUT_CASE_ERROR;
- }
- }
- }
- int SendChangeCipher(CYASSL* ssl)
- {
- byte *output;
- int sendSz = RECORD_HEADER_SZ + ENUM_LEN;
- int idx = RECORD_HEADER_SZ;
- int ret;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA;
- idx += DTLS_RECORD_EXTRA;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddRecordHeader(output, 1, change_cipher_spec, ssl);
- output[idx] = 1; /* turn it on */
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- static INLINE const byte* GetMacSecret(CYASSL* ssl, int verify)
- {
- if ( (ssl->options.side == CLIENT_END && !verify) ||
- (ssl->options.side == SERVER_END && verify) )
- return ssl->keys.client_write_MAC_secret;
- else
- return ssl->keys.server_write_MAC_secret;
- }
- static void Hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz,
- int content, int verify)
- {
- byte result[SHA256_DIGEST_SIZE]; /* max possible sizes */
- word32 digestSz = ssl->specs.hash_size; /* actual sizes */
- word32 padSz = ssl->specs.pad_size;
- Md5 md5;
- Sha sha;
- /* data */
- byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
- byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
- const byte* macSecret = GetMacSecret(ssl, verify);
-
- conLen[0] = (byte)content;
- c16toa((word16)sz, &conLen[ENUM_LEN]);
- c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
- if (ssl->specs.mac_algorithm == md5_mac) {
- InitMd5(&md5);
- /* inner */
- Md5Update(&md5, macSecret, digestSz);
- Md5Update(&md5, PAD1, padSz);
- Md5Update(&md5, seq, SEQ_SZ);
- Md5Update(&md5, conLen, sizeof(conLen));
- /* in buffer */
- Md5Update(&md5, in, sz);
- Md5Final(&md5, result);
- /* outer */
- Md5Update(&md5, macSecret, digestSz);
- Md5Update(&md5, PAD2, padSz);
- Md5Update(&md5, result, digestSz);
- Md5Final(&md5, digest);
- }
- else {
- InitSha(&sha);
- /* inner */
- ShaUpdate(&sha, macSecret, digestSz);
- ShaUpdate(&sha, PAD1, padSz);
- ShaUpdate(&sha, seq, SEQ_SZ);
- ShaUpdate(&sha, conLen, sizeof(conLen));
- /* in buffer */
- ShaUpdate(&sha, in, sz);
- ShaFinal(&sha, result);
- /* outer */
- ShaUpdate(&sha, macSecret, digestSz);
- ShaUpdate(&sha, PAD2, padSz);
- ShaUpdate(&sha, result, digestSz);
- ShaFinal(&sha, digest);
- }
- }
- static void BuildMD5_CertVerify(CYASSL* ssl, byte* digest)
- {
- byte md5_result[MD5_DIGEST_SIZE];
- /* make md5 inner */
- Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
- Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
- Md5Final(&ssl->hashMd5, md5_result);
- /* make md5 outer */
- Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
- Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
- Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
- Md5Final(&ssl->hashMd5, digest);
- }
- static void BuildSHA_CertVerify(CYASSL* ssl, byte* digest)
- {
- byte sha_result[SHA_DIGEST_SIZE];
-
- /* make sha inner */
- ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
- ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
- ShaFinal(&ssl->hashSha, sha_result);
- /* make sha outer */
- ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
- ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
- ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
- ShaFinal(&ssl->hashSha, digest);
- }
- static void BuildCertHashes(CYASSL* ssl, Hashes* hashes)
- {
- /* store current states, building requires get_digest which resets state */
- Md5 md5 = ssl->hashMd5;
- Sha sha = ssl->hashSha;
- #ifndef NO_SHA256 /* for possible future changes */
- Sha256 sha256;
- InitSha256(&sha256);
- if (IsAtLeastTLSv1_2(ssl))
- sha256 = ssl->hashSha256;
- #endif
- if (ssl->options.tls) {
- Md5Final(&ssl->hashMd5, hashes->md5);
- ShaFinal(&ssl->hashSha, hashes->sha);
- }
- else {
- BuildMD5_CertVerify(ssl, hashes->md5);
- BuildSHA_CertVerify(ssl, hashes->sha);
- }
-
- /* restore */
- ssl->hashMd5 = md5;
- ssl->hashSha = sha;
- #ifndef NO_SHA256
- if (IsAtLeastTLSv1_2(ssl))
- ssl->hashSha256 = sha256;
- #endif
- }
- /* Build SSL Message, encrypted */
- static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
- int type)
- {
- word32 digestSz = ssl->specs.hash_size;
- word32 sz = RECORD_HEADER_SZ + inSz + digestSz;
- word32 pad = 0, i;
- word32 idx = RECORD_HEADER_SZ;
- word32 ivSz = 0; /* TLSv1.1 IV */
- word32 headerSz = RECORD_HEADER_SZ;
- word16 size;
- byte iv[AES_BLOCK_SIZE]; /* max size */
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sz += DTLS_RECORD_EXTRA;
- idx += DTLS_RECORD_EXTRA;
- headerSz += DTLS_RECORD_EXTRA;
- }
- #endif
- if (ssl->specs.cipher_type == block) {
- word32 blockSz = ssl->specs.block_size;
- if (ssl->options.tls1_1) {
- ivSz = blockSz;
- sz += ivSz;
- RNG_GenerateBlock(&ssl->rng, iv, ivSz);
- }
- sz += 1; /* pad byte */
- pad = (sz - headerSz) % blockSz;
- pad = blockSz - pad;
- sz += pad;
- }
- size = (word16)(sz - headerSz); /* include mac and digest */
- AddRecordHeader(output, size, (byte)type, ssl);
- /* write to output */
- if (ivSz) {
- XMEMCPY(output + idx, iv, ivSz);
- idx += ivSz;
- }
- XMEMCPY(output + idx, input, inSz);
- idx += inSz;
- if (type == handshake)
- HashOutput(ssl, output, headerSz + inSz, ivSz);
- ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
- idx += digestSz;
- if (ssl->specs.cipher_type == block)
- for (i = 0; i <= pad; i++)
- output[idx++] = (byte)pad; /* pad byte gets pad value too */
- Encrypt(ssl, output + headerSz, output + headerSz, size);
- return sz;
- }
- int SendFinished(CYASSL* ssl)
- {
- int sendSz,
- finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
- FINISHED_SZ;
- byte input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ]; /* max */
- byte *output;
- Hashes* hashes;
- int ret;
- int headerSz = HANDSHAKE_HEADER_SZ;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- headerSz += DTLS_HANDSHAKE_EXTRA;
- ssl->keys.dtls_epoch++;
- ssl->keys.dtls_sequence_number = 0; /* reset after epoch change */
- }
- #endif
-
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sizeof(input) + MAX_MSG_EXTRA)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHandShakeHeader(input, finishedSz, finished, ssl);
- /* make finished hashes */
- hashes = (Hashes*)&input[headerSz];
- BuildFinished(ssl, hashes, ssl->options.side == CLIENT_END ? client :
- server);
- if ( (sendSz = BuildMessage(ssl, output, input, headerSz +
- finishedSz, handshake)) < 0)
- return BUILD_MSG_ERROR;
- if (!ssl->options.resuming) {
- #ifndef NO_SESSION_CACHE
- AddSession(ssl); /* just try */
- #endif
- if (ssl->options.side == CLIENT_END)
- BuildFinished(ssl, &ssl->verifyHashes, server);
- else
- ssl->options.handShakeState = HANDSHAKE_DONE;
- }
- else {
- if (ssl->options.side == CLIENT_END)
- ssl->options.handShakeState = HANDSHAKE_DONE;
- else
- BuildFinished(ssl, &ssl->verifyHashes, client);
- }
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- int SendCertificate(CYASSL* ssl)
- {
- int sendSz, length, ret = 0;
- word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- word32 certSz, listSz;
- byte* output = 0;
- if (ssl->options.usingPSK_cipher) return 0; /* not needed */
- if (ssl->options.sendVerify == SEND_BLANK_CERT) {
- certSz = 0;
- length = CERT_HEADER_SZ;
- listSz = 0;
- }
- else {
- certSz = ssl->buffers.certificate.length;
- /* list + cert size */
- length = certSz + 2 * CERT_HEADER_SZ;
- listSz = certSz + CERT_HEADER_SZ;
- /* may need to send rest of chain, already has leading size(s) */
- if (ssl->buffers.certChain.buffer) {
- length += ssl->buffers.certChain.length;
- listSz += ssl->buffers.certChain.length;
- }
- }
- sendSz = length + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, length, certificate, ssl);
- /* list total */
- c32to24(listSz, output + i);
- i += CERT_HEADER_SZ;
- /* member */
- if (certSz) {
- c32to24(certSz, output + i);
- i += CERT_HEADER_SZ;
- XMEMCPY(output + i, ssl->buffers.certificate.buffer, certSz);
- i += certSz;
- /* send rest of chain? */
- if (ssl->buffers.certChain.buffer) {
- XMEMCPY(output + i, ssl->buffers.certChain.buffer,
- ssl->buffers.certChain.length);
- i += ssl->buffers.certChain.length;
- }
- }
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
- #endif
- if (ssl->options.side == SERVER_END)
- ssl->options.serverState = SERVER_CERT_COMPLETE;
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- int SendCertificateRequest(CYASSL* ssl)
- {
- byte *output;
- int ret;
- int sendSz;
- word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-
- int typeTotal = 1; /* only rsa for now */
- int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
- if (IsAtLeastTLSv1_2(ssl))
- reqSz += LENGTH_SZ + HASH_SIG_SIZE;
- if (ssl->options.usingPSK_cipher) return 0; /* not needed */
- sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.idx;
- AddHeaders(output, reqSz, certificate_request, ssl);
- /* write to output */
- output[i++] = (byte)typeTotal; /* # of types */
- output[i++] = rsa_sign;
- /* supported hash/sig */
- if (IsAtLeastTLSv1_2(ssl)) {
- c16toa(HASH_SIG_SIZE, &output[i]);
- i += LENGTH_SZ;
- output[i++] = sha_mac; /* hash */
- output[i++] = rsa_sa_algo; /* sig */
- }
- c16toa(0, &output[i]); /* auth's */
- i += REQ_HEADER_SZ;
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("CertificateRequest", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output,
- sendSz, ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- int SendData(CYASSL* ssl, const void* data, int sz)
- {
- int sent = 0, /* plainText size */
- sendSz,
- ret;
- if (ssl->error == WANT_WRITE)
- ssl->error = 0;
- if (ssl->options.handShakeState != HANDSHAKE_DONE) {
- int err;
- CYASSL_MSG("handshake not complete, trying to finish");
- if ( (err = CyaSSL_negotiate(ssl)) != 0)
- return err;
- }
- /* last time system socket output buffer was full, try again to send */
- if (ssl->buffers.outputBuffer.length > 0) {
- CYASSL_MSG("output buffer was full, trying to send again");
- if ( (ssl->error = SendBuffered(ssl)) < 0) {
- CYASSL_ERROR(ssl->error);
- if (ssl->error == SOCKET_ERROR_E && ssl->options.connReset)
- return 0; /* peer reset */
- return ssl->error;
- }
- else {
- /* advance sent to previous sent + plain size just sent */
- sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
- CYASSL_MSG("sent write buffered data");
- }
- }
- for (;;) {
- int len = min(sz - sent, OUTPUT_RECORD_SIZE);
- byte* out;
- byte* sendBuffer = (byte*)data + sent; /* may switch on comp */
- int buffSz = len; /* may switch on comp */
- #ifdef HAVE_LIBZ
- byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
- #endif
- if (sent == sz) break;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- len = min(len, MAX_UDP_SIZE);
- buffSz = len;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, len + COMP_EXTRA +
- MAX_MSG_EXTRA)) != 0)
- return ret;
- /* get ouput buffer */
- out = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- #ifdef HAVE_LIBZ
- if (ssl->options.usingCompression) {
- buffSz = Compress(ssl, sendBuffer, buffSz, comp, sizeof(comp));
- if (buffSz < 0) {
- return buffSz;
- }
- sendBuffer = comp;
- }
- #endif
- sendSz = BuildMessage(ssl, out, sendBuffer, buffSz,
- application_data);
- ssl->buffers.outputBuffer.length += sendSz;
- if ( (ret = SendBuffered(ssl)) < 0) {
- CYASSL_ERROR(ret);
- /* store for next call if WANT_WRITE or user embedSend() that
- doesn't present like WANT_WRITE */
- ssl->buffers.plainSz = len;
- ssl->buffers.prevSent = sent;
- if (ret == SOCKET_ERROR_E && ssl->options.connReset)
- return 0; /* peer reset */
- return ssl->error = ret;
- }
- sent += len;
- /* only one message per attempt */
- if (ssl->options.partialWrite == 1) {
- CYASSL_MSG("Paritial Write on, only sending one record");
- break;
- }
- }
-
- return sent;
- }
- /* process input data */
- int ReceiveData(CYASSL* ssl, byte* output, int sz)
- {
- int size;
- CYASSL_ENTER("ReceiveData()");
- if (ssl->error == WANT_READ)
- ssl->error = 0;
- if (ssl->options.handShakeState != HANDSHAKE_DONE) {
- int err;
- CYASSL_MSG("Handshake not complete, trying to finish");
- if ( (err = CyaSSL_negotiate(ssl)) != 0)
- return err;
- }
- while (ssl->buffers.clearOutputBuffer.length == 0)
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- CYASSL_ERROR(ssl->error);
- if (ssl->error == ZERO_RETURN) {
- CYASSL_MSG("Zero return, no more data coming");
- ssl->options.isClosed = 1;
- return 0; /* no more data coming */
- }
- if (ssl->error == SOCKET_ERROR_E) {
- if (ssl->options.connReset || ssl->options.isClosed) {
- CYASSL_MSG("Peer reset or closed, connection done");
- return 0; /* peer reset or closed */
- }
- }
- return ssl->error;
- }
- if (sz < (int)ssl->buffers.clearOutputBuffer.length)
- size = sz;
- else
- size = ssl->buffers.clearOutputBuffer.length;
- XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
- ssl->buffers.clearOutputBuffer.length -= size;
- ssl->buffers.clearOutputBuffer.buffer += size;
-
- if (ssl->buffers.clearOutputBuffer.length == 0 &&
- ssl->buffers.inputBuffer.dynamicFlag)
- ShrinkInputBuffer(ssl, NO_FORCED_FREE);
- CYASSL_LEAVE("ReceiveData()", size);
- return size;
- }
- /* send alert message */
- int SendAlert(CYASSL* ssl, int severity, int type)
- {
- byte input[ALERT_SIZE];
- byte *output;
- int sendSz;
- int ret;
- /* if sendalert is called again for nonbloking */
- if (ssl->options.sendAlertState != 0) {
- ret = SendBuffered(ssl);
- if (ret == 0)
- ssl->options.sendAlertState = 0;
- return ret;
- }
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, ALERT_SIZE + MAX_MSG_EXTRA)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- input[0] = (byte)severity;
- input[1] = (byte)type;
- if (ssl->keys.encryptionOn)
- sendSz = BuildMessage(ssl, output, input, ALERT_SIZE, alert);
- else {
- RecordLayerHeader *const rl = (RecordLayerHeader*)output;
- rl->type = alert;
- rl->version = ssl->version;
- c16toa(ALERT_SIZE, rl->length);
- XMEMCPY(output + RECORD_HEADER_SZ, input, ALERT_SIZE);
- sendSz = RECORD_HEADER_SZ + ALERT_SIZE;
- }
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("Alert", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- ssl->options.sendAlertState = 1;
- return SendBuffered(ssl);
- }
- void SetErrorString(int error, char* str)
- {
- const int max = MAX_ERROR_SZ; /* shorthand */
- #ifdef NO_ERROR_STRINGS
- XSTRNCPY(str, "no support for error strings built in", max);
- #else
- /* pass to CTaoCrypt */
- if (error < MAX_CODE_E && error > MIN_CODE_E) {
- CTaoCryptErrorString(error, str);
- return;
- }
- switch (error) {
- case UNSUPPORTED_SUITE :
- XSTRNCPY(str, "unsupported cipher suite", max);
- break;
- case INPUT_CASE_ERROR :
- XSTRNCPY(str, "input state error", max);
- break;
- case PREFIX_ERROR :
- XSTRNCPY(str, "bad index to key rounds", max);
- break;
- case MEMORY_ERROR :
- XSTRNCPY(str, "out of memory", max);
- break;
- case VERIFY_FINISHED_ERROR :
- XSTRNCPY(str, "verify problem on finished", max);
- break;
- case VERIFY_MAC_ERROR :
- XSTRNCPY(str, "verify mac problem", max);
- break;
- case PARSE_ERROR :
- XSTRNCPY(str, "parse error on header", max);
- break;
- case SIDE_ERROR :
- XSTRNCPY(str, "wrong client/server type", max);
- break;
- case NO_PEER_CERT :
- XSTRNCPY(str, "peer didn't send cert", max);
- break;
- case UNKNOWN_HANDSHAKE_TYPE :
- XSTRNCPY(str, "weird handshake type", max);
- break;
- case SOCKET_ERROR_E :
- XSTRNCPY(str, "error state on socket", max);
- break;
- case SOCKET_NODATA :
- XSTRNCPY(str, "expected data, not there", max);
- break;
- case INCOMPLETE_DATA :
- XSTRNCPY(str, "don't have enough data to complete task", max);
- break;
- case UNKNOWN_RECORD_TYPE :
- XSTRNCPY(str, "unknown type in record hdr", max);
- break;
- case DECRYPT_ERROR :
- XSTRNCPY(str, "error during decryption", max);
- break;
- case FATAL_ERROR :
- XSTRNCPY(str, "revcd alert fatal error", max);
- break;
- case ENCRYPT_ERROR :
- XSTRNCPY(str, "error during encryption", max);
- break;
- case FREAD_ERROR :
- XSTRNCPY(str, "fread problem", max);
- break;
- case NO_PEER_KEY :
- XSTRNCPY(str, "need peer's key", max);
- break;
- case NO_PRIVATE_KEY :
- XSTRNCPY(str, "need the private key", max);
- break;
- case NO_DH_PARAMS :
- XSTRNCPY(str, "server missing DH params", max);
- break;
- case RSA_PRIVATE_ERROR :
- XSTRNCPY(str, "error during rsa priv op", max);
- break;
- case MATCH_SUITE_ERROR :
- XSTRNCPY(str, "can't match cipher suite", max);
- break;
- case BUILD_MSG_ERROR :
- XSTRNCPY(str, "build message failure", max);
- break;
- case BAD_HELLO :
- XSTRNCPY(str, "client hello malformed", max);
- break;
- case DOMAIN_NAME_MISMATCH :
- XSTRNCPY(str, "peer subject name mismatch", max);
- break;
- case WANT_READ :
- XSTRNCPY(str, "non-blocking socket wants data to be read", max);
- break;
- case NOT_READY_ERROR :
- XSTRNCPY(str, "handshake layer not ready yet, complete first", max);
- break;
- case PMS_VERSION_ERROR :
- XSTRNCPY(str, "premaster secret version mismatch error", max);
- break;
- case VERSION_ERROR :
- XSTRNCPY(str, "record layer version error", max);
- break;
- case WANT_WRITE :
- XSTRNCPY(str, "non-blocking socket write buffer full", max);
- break;
- case BUFFER_ERROR :
- XSTRNCPY(str, "malformed buffer input error", max);
- break;
- case VERIFY_CERT_ERROR :
- XSTRNCPY(str, "verify problem on certificate", max);
- break;
- case VERIFY_SIGN_ERROR :
- XSTRNCPY(str, "verify problem based on signature", max);
- break;
- case CLIENT_ID_ERROR :
- XSTRNCPY(str, "psk client identity error", max);
- break;
- case SERVER_HINT_ERROR:
- XSTRNCPY(str, "psk server hint error", max);
- break;
- case PSK_KEY_ERROR:
- XSTRNCPY(str, "psk key callback error", max);
- break;
- case NTRU_KEY_ERROR:
- XSTRNCPY(str, "NTRU key error", max);
- break;
- case NTRU_DRBG_ERROR:
- XSTRNCPY(str, "NTRU drbg error", max);
- break;
- case NTRU_ENCRYPT_ERROR:
- XSTRNCPY(str, "NTRU encrypt error", max);
- break;
- case NTRU_DECRYPT_ERROR:
- XSTRNCPY(str, "NTRU decrypt error", max);
- break;
- case ZLIB_INIT_ERROR:
- XSTRNCPY(str, "zlib init error", max);
- break;
- case ZLIB_COMPRESS_ERROR:
- XSTRNCPY(str, "zlib compress error", max);
- break;
- case ZLIB_DECOMPRESS_ERROR:
- XSTRNCPY(str, "zlib decompress error", max);
- break;
- case GETTIME_ERROR:
- XSTRNCPY(str, "gettimeofday() error", max);
- break;
- case GETITIMER_ERROR:
- XSTRNCPY(str, "getitimer() error", max);
- break;
- case SIGACT_ERROR:
- XSTRNCPY(str, "sigaction() error", max);
- break;
- case SETITIMER_ERROR:
- XSTRNCPY(str, "setitimer() error", max);
- break;
- case LENGTH_ERROR:
- XSTRNCPY(str, "record layer length error", max);
- break;
- case PEER_KEY_ERROR:
- XSTRNCPY(str, "cant decode peer key", max);
- break;
- case ZERO_RETURN:
- XSTRNCPY(str, "peer sent close notify alert", max);
- break;
- case ECC_CURVETYPE_ERROR:
- XSTRNCPY(str, "Bad ECC Curve Type or unsupported", max);
- break;
- case ECC_CURVE_ERROR:
- XSTRNCPY(str, "Bad ECC Curve or unsupported", max);
- break;
- case ECC_PEERKEY_ERROR:
- XSTRNCPY(str, "Bad ECC Peer Key", max);
- break;
- case ECC_MAKEKEY_ERROR:
- XSTRNCPY(str, "ECC Make Key failure", max);
- break;
- case ECC_EXPORT_ERROR:
- XSTRNCPY(str, "ECC Export Key failure", max);
- break;
- case ECC_SHARED_ERROR:
- XSTRNCPY(str, "ECC DHE shared failure", max);
- break;
- case BAD_MUTEX_ERROR:
- XSTRNCPY(str, "Bad mutex, operation failed", max);
- break;
- default :
- XSTRNCPY(str, "unknown error number", max);
- }
- #endif /* NO_ERROR_STRINGS */
- }
- /* be sure to add to cipher_name_idx too !!!! */
- const char* const cipher_names[] =
- {
- #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
- "RC4-SHA",
- #endif
- #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
- "RC4-MD5",
- #endif
- #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
- "DES-CBC3-SHA",
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
- "AES128-SHA",
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
- "AES256-SHA",
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- "DHE-RSA-AES128-SHA",
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- "DHE-RSA-AES256-SHA",
- #endif
- #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
- "PSK-AES128-CBC-SHA",
- #endif
- #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
- "PSK-AES256-CBC-SHA",
- #endif
- #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
- "HC128-MD5",
- #endif
-
- #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
- "HC128-SHA",
- #endif
- #ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
- "RABBIT-SHA",
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
- "NTRU-RC4-SHA",
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
- "NTRU-DES-CBC3-SHA",
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
- "NTRU-AES128-SHA",
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
- "NTRU-AES256-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- "ECDHE-RSA-AES128-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- "ECDHE-RSA-AES256-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- "ECDHE-ECDSA-AES128-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- "ECDHE-ECDSA-AES256-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- "ECDHE-RSA-RC4-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- "ECDHE-RSA-DES-CBC3-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- "ECDHE-ECDSA-RC4-SHA",
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- "ECDHE-ECDSA-DES-CBC3-SHA",
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
- "AES128-SHA256",
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
- "AES256-SHA256",
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- "DHE-RSA-AES128-SHA256",
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- "DHE-RSA-AES256-SHA256"
- #endif
- };
- /* cipher suite number that matches above name table */
- int cipher_name_idx[] =
- {
- #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
- SSL_RSA_WITH_RC4_128_SHA,
- #endif
- #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
- SSL_RSA_WITH_RC4_128_MD5,
- #endif
- #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_128_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_256_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
- TLS_PSK_WITH_AES_128_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
- TLS_PSK_WITH_AES_256_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
- TLS_RSA_WITH_HC_128_CBC_MD5,
- #endif
- #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
- TLS_RSA_WITH_HC_128_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
- TLS_RSA_WITH_RABBIT_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
- TLS_NTRU_RSA_WITH_RC4_128_SHA,
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
- TLS_NTRU_RSA_WITH_AES_128_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
- TLS_NTRU_RSA_WITH_AES_256_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- TLS_ECDHE_RSA_WITH_RC4_128_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
- #endif
- #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA256,
- #endif
- #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA256,
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
- #endif
- #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- #endif
- };
- /* return true if set, else false */
- /* only supports full name from cipher_name[] delimited by : */
- int SetCipherList(Suites* s, const char* list)
- {
- int ret = 0, i;
- char name[MAX_SUITE_NAME];
- char needle[] = ":";
- char* haystack = (char*)list;
- char* prev;
- const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]);
- int idx = 0;
- if (!list)
- return 0;
-
- if (*list == 0) return 1; /* CyaSSL default */
- if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL defualt */
- for(;;) {
- word32 len;
- prev = haystack;
- haystack = XSTRSTR(haystack, needle);
- if (!haystack) /* last cipher */
- len = min(sizeof(name), XSTRLEN(prev));
- else
- len = min(sizeof(name), (word32)(haystack - prev));
- XSTRNCPY(name, prev, len);
- name[(len == sizeof(name)) ? len - 1 : len] = 0;
- for (i = 0; i < suiteSz; i++)
- if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
- if (XSTRSTR(name, "EC"))
- s->suites[idx++] = ECC_BYTE; /* ECC suite */
- else
- s->suites[idx++] = 0x00; /* normal */
- s->suites[idx++] = (byte)cipher_name_idx[i];
- if (!ret) ret = 1; /* found at least one */
- break;
- }
- if (!haystack) break;
- haystack++;
- }
- if (ret) {
- s->setSuites = 1;
- s->suiteSz = (word16)idx;
- }
- return ret;
- }
- #ifdef CYASSL_CALLBACKS
- /* Initialisze HandShakeInfo */
- void InitHandShakeInfo(HandShakeInfo* info)
- {
- int i;
- info->cipherName[0] = 0;
- for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
- info->packetNames[i][0] = 0;
- info->numberPackets = 0;
- info->negotiationError = 0;
- }
- /* Set Final HandShakeInfo parameters */
- void FinishHandShakeInfo(HandShakeInfo* info, const CYASSL* ssl)
- {
- int i;
- int sz = sizeof(cipher_name_idx)/sizeof(int);
- for (i = 0; i < sz; i++)
- if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) {
- if (ssl->options.cipherSuite0 == ECC_BYTE)
- continue; /* ECC suites at end */
- XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ);
- break;
- }
- /* error max and min are negative numbers */
- if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR)
- info->negotiationError = ssl->error;
- }
-
- /* Add name to info packet names, increase packet name count */
- void AddPacketName(const char* name, HandShakeInfo* info)
- {
- if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
- XSTRNCPY(info->packetNames[info->numberPackets++], name,
- MAX_PACKETNAME_SZ);
- }
- }
- /* Initialisze TimeoutInfo */
- void InitTimeoutInfo(TimeoutInfo* info)
- {
- int i;
- info->timeoutName[0] = 0;
- info->flags = 0;
- for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
- info->packets[i].packetName[0] = 0;
- info->packets[i].timestamp.tv_sec = 0;
- info->packets[i].timestamp.tv_usec = 0;
- info->packets[i].bufferValue = 0;
- info->packets[i].valueSz = 0;
- }
- info->numberPackets = 0;
- info->timeoutValue.tv_sec = 0;
- info->timeoutValue.tv_usec = 0;
- }
- /* Free TimeoutInfo */
- void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
- {
- int i;
- for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
- if (info->packets[i].bufferValue) {
- XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
- info->packets[i].bufferValue = 0;
- }
- }
- /* Add PacketInfo to TimeoutInfo */
- void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data,
- int sz, void* heap)
- {
- if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
- Timeval currTime;
- /* may add name after */
- if (name)
- XSTRNCPY(info->packets[info->numberPackets].packetName, name,
- MAX_PACKETNAME_SZ);
- /* add data, put in buffer if bigger than static buffer */
- info->packets[info->numberPackets].valueSz = sz;
- if (sz < MAX_VALUE_SZ)
- XMEMCPY(info->packets[info->numberPackets].value, data, sz);
- else {
- info->packets[info->numberPackets].bufferValue =
- XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
- if (!info->packets[info->numberPackets].bufferValue)
- /* let next alloc catch, just don't fill, not fatal here */
- info->packets[info->numberPackets].valueSz = 0;
- else
- XMEMCPY(info->packets[info->numberPackets].bufferValue,
- data, sz);
- }
- gettimeofday(&currTime, 0);
- info->packets[info->numberPackets].timestamp.tv_sec =
- currTime.tv_sec;
- info->packets[info->numberPackets].timestamp.tv_usec =
- currTime.tv_usec;
- info->numberPackets++;
- }
- }
- /* Add packet name to previsouly added packet info */
- void AddLateName(const char* name, TimeoutInfo* info)
- {
- /* make sure we have a valid previous one */
- if (info->numberPackets > 0 && info->numberPackets <
- MAX_PACKETS_HANDSHAKE) {
- XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name,
- MAX_PACKETNAME_SZ);
- }
- }
- /* Add record header to previsouly added packet info */
- void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
- {
- /* make sure we have a valid previous one */
- if (info->numberPackets > 0 && info->numberPackets <
- MAX_PACKETS_HANDSHAKE) {
- if (info->packets[info->numberPackets - 1].bufferValue)
- XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
- RECORD_HEADER_SZ);
- else
- XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
- RECORD_HEADER_SZ);
- }
- }
- #endif /* CYASSL_CALLBACKS */
- /* client only parts */
- #ifndef NO_CYASSL_CLIENT
- int SendClientHello(CYASSL* ssl)
- {
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- int idSz = ssl->options.resuming ? ID_LEN : 0;
- int ret;
- length = sizeof(ProtocolVersion) + RAN_LEN
- + idSz + ENUM_LEN
- + ssl->suites.suiteSz + SUITE_LEN
- + COMP_LEN + ENUM_LEN;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- length += ENUM_LEN; /* cookie */
- sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
- idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, length, client_hello, ssl);
- /* client hello, first version */
- XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
- idx += sizeof(ProtocolVersion);
- ssl->chVersion = ssl->version; /* store in case changed */
- /* then random */
- if (ssl->options.connectState == CONNECT_BEGIN) {
- RNG_GenerateBlock(&ssl->rng, output + idx, RAN_LEN);
-
- /* store random */
- XMEMCPY(ssl->arrays.clientRandom, output + idx, RAN_LEN);
- } else {
- #ifdef CYASSL_DTLS
- /* send same random on hello again */
- XMEMCPY(output + idx, ssl->arrays.clientRandom, RAN_LEN);
- #endif
- }
- idx += RAN_LEN;
- /* then session id */
- output[idx++] = (byte)idSz;
- if (idSz) {
- XMEMCPY(output + idx, ssl->session.sessionID, ID_LEN);
- idx += ID_LEN;
- }
-
- /* then DTLS cookie */
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- output[idx++] = 0;
- }
- #endif
- /* then cipher suites */
- c16toa(ssl->suites.suiteSz, output + idx);
- idx += 2;
- XMEMCPY(output + idx, &ssl->suites.suites, ssl->suites.suiteSz);
- idx += ssl->suites.suiteSz;
- /* last, compression */
- output[idx++] = COMP_LEN;
- if (ssl->options.usingCompression)
- output[idx++] = ZLIB_COMPRESSION;
- else
- output[idx++] = NO_COMPRESSION;
-
- HashOutput(ssl, output, sendSz, 0);
- ssl->options.clientState = CLIENT_HELLO_COMPLETE;
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- static int DoHelloVerifyRequest(CYASSL* ssl, const byte* input,
- word32* inOutIdx)
- {
- ProtocolVersion pv;
- byte cookieSz;
-
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
- &ssl->handShakeInfo);
- if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
- #endif
- XMEMCPY(&pv, input + *inOutIdx, sizeof(pv));
- *inOutIdx += sizeof(pv);
-
- cookieSz = input[(*inOutIdx)++];
-
- if (cookieSz)
- *inOutIdx += cookieSz; /* skip for now */
-
- ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
- return 0;
- }
- static int DoServerHello(CYASSL* ssl, const byte* input, word32* inOutIdx)
- {
- byte b;
- byte compression;
- ProtocolVersion pv;
- word32 i = *inOutIdx;
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
- if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
- #endif
- XMEMCPY(&pv, input + i, sizeof(pv));
- i += sizeof(pv);
- if (pv.minor > ssl->version.minor) {
- CYASSL_MSG("Server using higher version, fatal error");
- return VERSION_ERROR;
- }
- else if (pv.minor < ssl->version.minor) {
- CYASSL_MSG("server using lower version");
- if (!ssl->options.downgrade) {
- CYASSL_MSG(" no downgrade allowed, fatal error");
- return VERSION_ERROR;
- }
- else if (pv.minor == SSLv3_MINOR) {
- /* turn off tls */
- CYASSL_MSG(" downgrading to SSLv3");
- ssl->options.tls = 0;
- ssl->options.tls1_1 = 0;
- ssl->version.minor = SSLv3_MINOR;
- }
- else if (pv.minor == TLSv1_MINOR) {
- /* turn off tls 1.1+ */
- CYASSL_MSG(" downgrading to TLSv1");
- ssl->options.tls1_1 = 0;
- ssl->version.minor = TLSv1_MINOR;
- }
- else if (pv.minor == TLSv1_1_MINOR) {
- CYASSL_MSG(" downgrading to TLSv1.1");
- ssl->version.minor = TLSv1_1_MINOR;
- }
- }
- XMEMCPY(ssl->arrays.serverRandom, input + i, RAN_LEN);
- i += RAN_LEN;
- b = input[i++];
- if (b) {
- XMEMCPY(ssl->arrays.sessionID, input + i, b);
- i += b;
- }
- ssl->options.cipherSuite0 = input[i++];
- ssl->options.cipherSuite = input[i++];
- compression = input[i++];
- if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) {
- CYASSL_MSG("Server refused compression, turning off");
- ssl->options.usingCompression = 0; /* turn off if server refused */
- }
-
- ssl->options.serverState = SERVER_HELLO_COMPLETE;
- *inOutIdx = i;
- if (ssl->options.resuming) {
- if (XMEMCMP(ssl->arrays.sessionID, ssl->session.sessionID, ID_LEN)
- == 0) {
- if (SetCipherSpecs(ssl) == 0) {
- int ret;
- XMEMCPY(ssl->arrays.masterSecret, ssl->session.masterSecret,
- SECRET_LEN);
- if (ssl->options.tls)
- ret = DeriveTlsKeys(ssl);
- else
- ret = DeriveKeys(ssl);
- ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
- return ret;
- }
- else
- return UNSUPPORTED_SUITE;
- }
- else {
- CYASSL_MSG("Server denied resumption attempt");
- ssl->options.resuming = 0; /* server denied resumption try */
- }
- }
- return SetCipherSpecs(ssl);
- }
- /* just read in and ignore for now TODO: */
- static int DoCertificateRequest(CYASSL* ssl, const byte* input, word32*
- inOutIdx)
- {
- word16 len;
-
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("CertificateRequest", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("CertificateRequest", &ssl->timeoutInfo);
- #endif
- len = input[(*inOutIdx)++];
- /* types, read in here */
- *inOutIdx += len;
- ato16(&input[*inOutIdx], &len);
- *inOutIdx += LENGTH_SZ;
- if (IsAtLeastTLSv1_2(ssl)) {
- /* hash sig format */
- *inOutIdx += len;
- ato16(&input[*inOutIdx], &len);
- *inOutIdx += LENGTH_SZ;
- }
- /* authorities */
- while (len) {
- word16 dnSz;
-
- ato16(&input[*inOutIdx], &dnSz);
- *inOutIdx += (REQUEST_HEADER + dnSz);
- len -= dnSz + REQUEST_HEADER;
- }
- /* don't send client cert or cert verify if user hasn't provided
- cert and private key */
- if (ssl->buffers.certificate.buffer && ssl->buffers.key.buffer)
- ssl->options.sendVerify = SEND_CERT;
- else if (IsAtLeastTLSv1_2(ssl))
- ssl->options.sendVerify = SEND_BLANK_CERT;
- return 0;
- }
- static int DoServerKeyExchange(CYASSL* ssl, const byte* input,
- word32* inOutIdx)
- {
- #if defined(OPENSSL_EXTRA) || defined(HAVE_ECC)
- word16 length = 0;
- word16 sigLen = 0;
- word16 verifySz = (word16)*inOutIdx; /* keep start idx */
- byte* signature = 0;
- #endif
- (void)ssl;
- (void)input;
- (void)inOutIdx;
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
- #endif
- #ifndef NO_PSK
- if (ssl->specs.kea == psk_kea) {
- word16 pskLen = 0;
- ato16(&input[*inOutIdx], &pskLen);
- *inOutIdx += LENGTH_SZ;
- XMEMCPY(ssl->arrays.server_hint, &input[*inOutIdx],
- min(pskLen, MAX_PSK_ID_LEN));
- if (pskLen < MAX_PSK_ID_LEN)
- ssl->arrays.server_hint[pskLen] = 0;
- else
- ssl->arrays.server_hint[MAX_PSK_ID_LEN - 1] = 0;
- *inOutIdx += pskLen;
- return 0;
- }
- #endif
- #ifdef OPENSSL_EXTRA
- if (ssl->specs.kea == diffie_hellman_kea)
- {
- /* p */
- ato16(&input[*inOutIdx], &length);
- *inOutIdx += LENGTH_SZ;
- ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_P.buffer)
- ssl->buffers.serverDH_P.length = length;
- else
- return MEMORY_ERROR;
- XMEMCPY(ssl->buffers.serverDH_P.buffer, &input[*inOutIdx], length);
- *inOutIdx += length;
- /* g */
- ato16(&input[*inOutIdx], &length);
- *inOutIdx += LENGTH_SZ;
- ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_G.buffer)
- ssl->buffers.serverDH_G.length = length;
- else
- return MEMORY_ERROR;
- XMEMCPY(ssl->buffers.serverDH_G.buffer, &input[*inOutIdx], length);
- *inOutIdx += length;
- /* pub */
- ato16(&input[*inOutIdx], &length);
- *inOutIdx += LENGTH_SZ;
- ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_Pub.buffer)
- ssl->buffers.serverDH_Pub.length = length;
- else
- return MEMORY_ERROR;
- XMEMCPY(ssl->buffers.serverDH_Pub.buffer, &input[*inOutIdx], length);
- *inOutIdx += length;
- } /* dh_kea */
- #endif /* OPENSSL_EXTRA */
- #ifdef HAVE_ECC
- if (ssl->specs.kea == ecc_diffie_hellman_kea)
- {
- byte b = input[*inOutIdx];
- *inOutIdx += 1;
- if (b != named_curve)
- return ECC_CURVETYPE_ERROR;
- *inOutIdx += 1; /* curve type, eat leading 0 */
- b = input[*inOutIdx];
- *inOutIdx += 1;
- if (b != secp256r1 && b != secp384r1 && b != secp521r1 && b !=
- secp160r1 && b != secp192r1 && b != secp224r1)
- return ECC_CURVE_ERROR;
- length = input[*inOutIdx];
- *inOutIdx += 1;
- if (ecc_import_x963(&input[*inOutIdx], length, &ssl->peerEccKey) != 0)
- return ECC_PEERKEY_ERROR;
- *inOutIdx += length;
- ssl->peerEccKeyPresent = 1;
- }
- #endif /* HAVE_ECC */
- #if defined(OPENSSL_EXTRA) || defined(HAVE_ECC)
- {
- Md5 md5;
- Sha sha;
- byte hash[FINISHED_SZ];
- byte messageVerify[MAX_DH_SZ];
- /* adjust from start idx */
- verifySz = (word16)(*inOutIdx - verifySz);
- /* save message for hash verify */
- if (verifySz > sizeof(messageVerify))
- return BUFFER_ERROR;
- XMEMCPY(messageVerify, &input[*inOutIdx - verifySz], verifySz);
- if (IsAtLeastTLSv1_2(ssl)) {
- /* just advance for now TODO: validate hash algo params */
- *inOutIdx += LENGTH_SZ;
- }
- /* signature */
- ato16(&input[*inOutIdx], &length);
- *inOutIdx += LENGTH_SZ;
- signature = (byte*)&input[*inOutIdx];
- *inOutIdx += length;
- sigLen = length;
- /* verify signature */
- /* md5 */
- InitMd5(&md5);
- Md5Update(&md5, ssl->arrays.clientRandom, RAN_LEN);
- Md5Update(&md5, ssl->arrays.serverRandom, RAN_LEN);
- Md5Update(&md5, messageVerify, verifySz);
- Md5Final(&md5, hash);
- /* sha */
- InitSha(&sha);
- ShaUpdate(&sha, ssl->arrays.clientRandom, RAN_LEN);
- ShaUpdate(&sha, ssl->arrays.serverRandom, RAN_LEN);
- ShaUpdate(&sha, messageVerify, verifySz);
- ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]);
- /* rsa */
- if (ssl->specs.sig_algo == rsa_sa_algo)
- {
- int ret;
- byte* out;
- if (!ssl->peerRsaKeyPresent)
- return NO_PEER_KEY;
- ret = RsaSSL_VerifyInline(signature, sigLen,&out, &ssl->peerRsaKey);
- if (IsAtLeastTLSv1_2(ssl)) {
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- word32 encSigSz;
- byte* digest;
- int typeH;
- int digestSz;
- /* sha1 for now */
- digest = &hash[MD5_DIGEST_SIZE];
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- encSigSz = EncodeSignature(encodedSig, digest, digestSz, typeH);
- if (encSigSz != (word32)ret || XMEMCMP(out, encodedSig,
- encSigSz) != 0)
- return VERIFY_SIGN_ERROR;
- }
- else {
- if (ret != sizeof(hash) || XMEMCMP(out, hash, sizeof(hash)))
- return VERIFY_SIGN_ERROR;
- }
- }
- #ifdef HAVE_ECC
- /* ecdsa */
- else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
- int verify = 0, ret;
- if (!ssl->peerEccDsaKeyPresent)
- return NO_PEER_KEY;
- ret = ecc_verify_hash(signature, sigLen, &hash[MD5_DIGEST_SIZE],
- SHA_DIGEST_SIZE, &verify, &ssl->peerEccDsaKey);
- if (ret != 0 || verify == 0)
- return VERIFY_SIGN_ERROR;
- }
- #endif /* HAVE_ECC */
- else
- return ALGO_ID_E;
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
- return 0;
- }
- #else /* HAVE_OPENSSL or HAVE_ECC */
- return NOT_COMPILED_IN; /* not supported by build */
- #endif /* HAVE_OPENSSL or HAVE_ECC */
- }
- int SendClientKeyExchange(CYASSL* ssl)
- {
- byte encSecret[MAX_NTRU_ENCRYPT_SZ];
- word32 encSz = 0;
- word32 idx = 0;
- int ret = 0;
- if (ssl->specs.kea == rsa_kea) {
- RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
- SECRET_LEN);
- ssl->arrays.preMasterSecret[0] = ssl->chVersion.major;
- ssl->arrays.preMasterSecret[1] = ssl->chVersion.minor;
- ssl->arrays.preMasterSz = SECRET_LEN;
- if (ssl->peerRsaKeyPresent == 0)
- return NO_PEER_KEY;
- ret = RsaPublicEncrypt(ssl->arrays.preMasterSecret, SECRET_LEN,
- encSecret, sizeof(encSecret), &ssl->peerRsaKey,
- &ssl->rng);
- if (ret > 0) {
- encSz = ret;
- ret = 0; /* set success to 0 */
- }
- #ifdef OPENSSL_EXTRA
- } else if (ssl->specs.kea == diffie_hellman_kea) {
- buffer serverP = ssl->buffers.serverDH_P;
- buffer serverG = ssl->buffers.serverDH_G;
- buffer serverPub = ssl->buffers.serverDH_Pub;
- byte priv[ENCRYPT_LEN];
- word32 privSz = 0;
- DhKey key;
- if (serverP.buffer == 0 || serverG.buffer == 0 ||
- serverPub.buffer == 0)
- return NO_PEER_KEY;
- InitDhKey(&key);
- ret = DhSetKey(&key, serverP.buffer, serverP.length,
- serverG.buffer, serverG.length);
- if (ret == 0)
- /* for DH, encSecret is Yc, agree is pre-master */
- ret = DhGenerateKeyPair(&key, &ssl->rng, priv, &privSz,
- encSecret, &encSz);
- if (ret == 0)
- ret = DhAgree(&key, ssl->arrays.preMasterSecret,
- &ssl->arrays.preMasterSz, priv, privSz,
- serverPub.buffer, serverPub.length);
- FreeDhKey(&key);
- #endif /* OPENSSL_EXTRA */
- #ifndef NO_PSK
- } else if (ssl->specs.kea == psk_kea) {
- byte* pms = ssl->arrays.preMasterSecret;
- ssl->arrays.psk_keySz = ssl->options.client_psk_cb(ssl,
- ssl->arrays.server_hint, ssl->arrays.client_identity,
- MAX_PSK_ID_LEN, ssl->arrays.psk_key, MAX_PSK_KEY_LEN);
- if (ssl->arrays.psk_keySz == 0 ||
- ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN)
- return PSK_KEY_ERROR;
- encSz = (word32)XSTRLEN(ssl->arrays.client_identity);
- if (encSz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
- XMEMCPY(encSecret, ssl->arrays.client_identity, encSz);
- /* make psk pre master secret */
- /* length of key + length 0s + length of key + key */
- c16toa((word16)ssl->arrays.psk_keySz, pms);
- pms += 2;
- XMEMSET(pms, 0, ssl->arrays.psk_keySz);
- pms += ssl->arrays.psk_keySz;
- c16toa((word16)ssl->arrays.psk_keySz, pms);
- pms += 2;
- XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
- ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
- #endif /* NO_PSK */
- #ifdef HAVE_NTRU
- } else if (ssl->specs.kea == ntru_kea) {
- word32 rc;
- word16 cipherLen = sizeof(encSecret);
- DRBG_HANDLE drbg;
- static uint8_t const cyasslStr[] = {
- 'C', 'y', 'a', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U'
- };
- RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
- SECRET_LEN);
- ssl->arrays.preMasterSz = SECRET_LEN;
- if (ssl->peerNtruKeyPresent == 0)
- return NO_PEER_KEY;
- rc = crypto_drbg_instantiate(MAX_NTRU_BITS, cyasslStr,
- sizeof(cyasslStr), GetEntropy, &drbg);
- if (rc != DRBG_OK)
- return NTRU_DRBG_ERROR;
- rc = crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,ssl->peerNtruKey,
- ssl->arrays.preMasterSz,
- ssl->arrays.preMasterSecret,
- &cipherLen, encSecret);
- crypto_drbg_uninstantiate(drbg);
- if (rc != NTRU_OK)
- return NTRU_ENCRYPT_ERROR;
- encSz = cipherLen;
- ret = 0;
- #endif /* HAVE_NTRU */
- #ifdef HAVE_ECC
- } else if (ssl->specs.kea == ecc_diffie_hellman_kea) {
- ecc_key myKey;
- word32 size = sizeof(encSecret);
- if (!ssl->peerEccKeyPresent || !ssl->peerEccKey.dp)
- return NO_PEER_KEY;
- ecc_init(&myKey);
- ret = ecc_make_key(&ssl->rng, ssl->peerEccKey.dp->size, &myKey);
- if (ret != 0)
- return ECC_MAKEKEY_ERROR;
- /* precede export with 1 byte length */
- ret = ecc_export_x963(&myKey, encSecret + 1, &size);
- encSecret[0] = size;
- encSz = size + 1;
- if (ret != 0)
- ret = ECC_EXPORT_ERROR;
- else {
- size = sizeof(ssl->arrays.preMasterSecret);
- ret = ecc_shared_secret(&myKey, &ssl->peerEccKey,
- ssl->arrays.preMasterSecret, &size);
- if (ret != 0)
- ret = ECC_SHARED_ERROR;
- }
- ssl->arrays.preMasterSz = size;
- ecc_free(&myKey);
- #endif /* HAVE_ECC */
- } else
- return ALGO_ID_E; /* unsupported kea */
- if (ret == 0) {
- byte *output;
- int sendSz;
- word32 tlsSz = 0;
-
- if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea)
- tlsSz = 2;
- if (ssl->specs.kea == ecc_diffie_hellman_kea) /* always off */
- tlsSz = 0;
- sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
- idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl);
- if (tlsSz) {
- c16toa((word16)encSz, &output[idx]);
- idx += 2;
- }
- XMEMCPY(output + idx, encSecret, encSz);
- idx += encSz;
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- ret = SendBuffered(ssl);
- }
-
- if (ret == 0 || ret == WANT_WRITE) {
- int tmpRet = MakeMasterSecret(ssl);
- if (tmpRet != 0)
- ret = tmpRet; /* save WANT_WRITE unless more serious */
- ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
- }
- return ret;
- }
- int SendCertificateVerify(CYASSL* ssl)
- {
- byte *output;
- int sendSz = 0, length, ret;
- word32 idx = 0;
- RsaKey key;
- if (ssl->options.sendVerify == SEND_BLANK_CERT)
- return 0; /* sent blank cert, can't verify */
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, MAX_CERT_VERIFY_SZ)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- BuildCertHashes(ssl, &ssl->certHashes);
- /* TODO: when add DSS support check here */
- InitRsaKey(&key, ssl->heap);
- ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
- ssl->buffers.key.length);
- if (ret == 0) {
- byte* verify = (byte*)&output[RECORD_HEADER_SZ +
- HANDSHAKE_HEADER_SZ];
- byte* signBuffer = ssl->certHashes.md5;
- word32 signSz = sizeof(Hashes);
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- word32 extraSz = 0; /* tls 1.2 hash/sig */
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls)
- verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- #endif
- length = RsaEncryptSize(&key);
- if (IsAtLeastTLSv1_2(ssl)) {
- verify[0] = sha_mac;
- verify[1] = rsa_sa_algo;
- extraSz = HASH_SIG_SIZE;
- }
- c16toa((word16)length, verify + extraSz); /* prepend verify header*/
- if (IsAtLeastTLSv1_2(ssl)) {
- byte* digest;
- int typeH;
- int digestSz;
- /* sha1 for now */
- digest = ssl->certHashes.sha;
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- signSz = EncodeSignature(encodedSig, digest, digestSz, typeH);
- signBuffer = encodedSig;
- }
- ret = RsaSSL_Sign(signBuffer, signSz, verify + extraSz +
- VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);
- if (ret > 0) {
- ret = 0; /* reset */
- AddHeaders(output, length + extraSz + VERIFY_HEADER,
- certificate_verify, ssl);
- sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
- extraSz + VERIFY_HEADER;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls)
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- #endif
- HashOutput(ssl, output, sendSz, 0);
- }
- }
- FreeRsaKey(&key);
- if (ret == 0) {
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("CertificateVerify", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("CertificateVerify", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- else
- return ret;
- }
- #endif /* NO_CYASSL_CLIENT */
- #ifndef NO_CYASSL_SERVER
- int SendServerHello(CYASSL* ssl)
- {
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- int ret;
- length = sizeof(ProtocolVersion) + RAN_LEN
- + ID_LEN + ENUM_LEN
- + SUITE_LEN
- + ENUM_LEN;
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, MAX_HELLO_SZ)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- AddHeaders(output, length, server_hello, ssl);
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- /* now write to output */
- /* first version */
- XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
- idx += sizeof(ProtocolVersion);
- /* then random */
- if (!ssl->options.resuming)
- RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
- XMEMCPY(output + idx, ssl->arrays.serverRandom, RAN_LEN);
- idx += RAN_LEN;
- #ifdef SHOW_SECRETS
- {
- int j;
- printf("server random: ");
- for (j = 0; j < RAN_LEN; j++)
- printf("%02x", ssl->arrays.serverRandom[j]);
- printf("\n");
- }
- #endif
- /* then session id */
- output[idx++] = ID_LEN;
- if (!ssl->options.resuming)
- RNG_GenerateBlock(&ssl->rng, ssl->arrays.sessionID, ID_LEN);
- XMEMCPY(output + idx, ssl->arrays.sessionID, ID_LEN);
- idx += ID_LEN;
- /* then cipher suite */
- output[idx++] = ssl->options.cipherSuite0;
- output[idx++] = ssl->options.cipherSuite;
- /* last, compression */
- if (ssl->options.usingCompression)
- output[idx++] = ZLIB_COMPRESSION;
- else
- output[idx++] = NO_COMPRESSION;
-
- ssl->buffers.outputBuffer.length += sendSz;
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerHello", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
- #endif
- ssl->options.serverState = SERVER_HELLO_COMPLETE;
- return SendBuffered(ssl);
- }
- #ifdef HAVE_ECC
- static byte SetCurveId(int size)
- {
- switch(size) {
- case 20:
- return secp160r1;
- break;
- case 24:
- return secp192r1;
- break;
- case 28:
- return secp224r1;
- break;
- case 32:
- return secp256r1;
- break;
- case 48:
- return secp384r1;
- break;
- case 66:
- return secp521r1;
- break;
- default:
- return 0;
- }
- }
- #endif /* HAVE_ECC */
- int SendServerKeyExchange(CYASSL* ssl)
- {
- int ret = 0;
- (void)ssl;
- #ifndef NO_PSK
- if (ssl->specs.kea == psk_kea)
- {
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- if (ssl->arrays.server_hint[0] == 0) return 0; /* don't send */
- /* include size part */
- length = (word32)XSTRLEN(ssl->arrays.server_hint);
- if (length > MAX_PSK_ID_LEN) return SERVER_HINT_ERROR;
- length += HINT_LEN_SZ;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, length, server_key_exchange, ssl);
- /* key data */
- c16toa((word16)(length - HINT_LEN_SZ), output + idx);
- idx += HINT_LEN_SZ;
- XMEMCPY(output + idx, ssl->arrays.server_hint, length -HINT_LEN_SZ);
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- ret = SendBuffered(ssl);
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
- }
- #endif /*NO_PSK */
- #ifdef HAVE_ECC
- if (ssl->specs.kea == ecc_diffie_hellman_kea)
- {
- byte *output;
- word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- byte export[MAX_EXPORT_ECC_SZ];
- word32 expSz = sizeof(export);
- word32 sigSz;
- word32 preSigSz, preSigIdx;
- RsaKey rsaKey;
- ecc_key dsaKey;
- /* curve type, named curve, length(1) */
- length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
- /* pub key size */
- if (ecc_export_x963(&ssl->eccTempKey, export, &expSz) != 0)
- return ECC_EXPORT_ERROR;
- length += expSz;
- preSigSz = length;
- preSigIdx = idx;
- InitRsaKey(&rsaKey, ssl->heap);
- ecc_init(&dsaKey);
- /* sig length */
- length += LENGTH_SZ;
- if (!ssl->buffers.key.buffer) {
- FreeRsaKey(&rsaKey);
- ecc_free(&dsaKey);
- return NO_PRIVATE_KEY;
- }
- if (ssl->specs.sig_algo == rsa_sa_algo) {
- /* rsa sig size */
- word32 i = 0;
- ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i,
- &rsaKey, ssl->buffers.key.length);
- if (ret != 0) return ret;
- sigSz = RsaEncryptSize(&rsaKey);
- }
- else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
- /* ecdsa sig size */
- word32 i = 0;
- ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &i,
- &dsaKey, ssl->buffers.key.length);
- if (ret != 0) return ret;
- sigSz = ecc_sig_size(&dsaKey);
- }
- else {
- FreeRsaKey(&rsaKey);
- ecc_free(&dsaKey);
- return ALGO_ID_E; /* unsupported type */
- }
- length += sigSz;
- if (IsAtLeastTLSv1_2(ssl))
- length += HASH_SIG_SIZE;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- preSigIdx = idx;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0) {
- FreeRsaKey(&rsaKey);
- ecc_free(&dsaKey);
- return ret;
- }
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, length, server_key_exchange, ssl);
- /* key exchange data */
- output[idx++] = named_curve;
- output[idx++] = 0x00; /* leading zero */
- output[idx++] = SetCurveId(ecc_size(&ssl->eccTempKey));
- output[idx++] = expSz;
- XMEMCPY(output + idx, export, expSz);
- idx += expSz;
- if (IsAtLeastTLSv1_2(ssl)) {
- output[idx++] = sha_mac;
- output[idx++] = ssl->specs.sig_algo;
- }
- c16toa(sigSz, output + idx);
- idx += LENGTH_SZ;
- /* do signature */
- {
- Md5 md5;
- Sha sha;
- byte hash[FINISHED_SZ];
- byte* signBuffer = hash;
- word32 signSz = sizeof(hash);
- /* md5 */
- InitMd5(&md5);
- Md5Update(&md5, ssl->arrays.clientRandom, RAN_LEN);
- Md5Update(&md5, ssl->arrays.serverRandom, RAN_LEN);
- Md5Update(&md5, output + preSigIdx, preSigSz);
- Md5Final(&md5, hash);
- /* sha */
- InitSha(&sha);
- ShaUpdate(&sha, ssl->arrays.clientRandom, RAN_LEN);
- ShaUpdate(&sha, ssl->arrays.serverRandom, RAN_LEN);
- ShaUpdate(&sha, output + preSigIdx, preSigSz);
- ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]);
- if (ssl->specs.sig_algo == rsa_sa_algo) {
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- if (IsAtLeastTLSv1_2(ssl)) {
- byte* digest;
- int hType;
- int digestSz;
- /* sha1 for now */
- digest = &hash[MD5_DIGEST_SIZE];
- hType = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- signSz = EncodeSignature(encodedSig, digest, digestSz,
- hType);
- signBuffer = encodedSig;
- }
- ret = RsaSSL_Sign(signBuffer, signSz, output + idx, sigSz,
- &rsaKey, &ssl->rng);
- FreeRsaKey(&rsaKey);
- if (ret > 0)
- ret = 0; /* reset on success */
- else
- return ret;
- }
- else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) {
- word32 sz = sigSz;
- FreeRsaKey(&rsaKey);
- ret = ecc_sign_hash(&hash[MD5_DIGEST_SIZE], SHA_DIGEST_SIZE,
- output + idx, &sz, &ssl->rng, &dsaKey);
- if (ret < 0) return ret;
- }
- }
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- ret = SendBuffered(ssl);
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
- }
- #endif /* HAVE_ECC */
- #ifdef OPENSSL_EXTRA
- if (ssl->specs.kea == diffie_hellman_kea) {
- byte *output;
- word32 length = 0, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int sendSz;
- word32 sigSz = 0, i = 0;
- word32 preSigSz = 0, preSigIdx = 0;
- RsaKey rsaKey;
- DhKey dhKey;
-
- if (ssl->buffers.serverDH_P.buffer == NULL ||
- ssl->buffers.serverDH_G.buffer == NULL)
- return NO_DH_PARAMS;
- if (ssl->buffers.serverDH_Pub.buffer == NULL) {
- ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
- ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_Pub.buffer == NULL)
- return MEMORY_E;
- }
- if (ssl->buffers.serverDH_Priv.buffer == NULL) {
- ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
- ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap,
- DYNAMIC_TYPE_DH);
- if (ssl->buffers.serverDH_Priv.buffer == NULL)
- return MEMORY_E;
- }
- InitDhKey(&dhKey);
- ret = DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length,
- ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- if (ret == 0)
- ret = DhGenerateKeyPair(&dhKey, &ssl->rng,
- ssl->buffers.serverDH_Priv.buffer,
- &ssl->buffers.serverDH_Priv.length,
- ssl->buffers.serverDH_Pub.buffer,
- &ssl->buffers.serverDH_Pub.length);
- FreeDhKey(&dhKey);
- if (ret == 0) {
- length = LENGTH_SZ * 3; /* p, g, pub */
- length += ssl->buffers.serverDH_P.length +
- ssl->buffers.serverDH_G.length +
- ssl->buffers.serverDH_Pub.length;
- preSigIdx = idx;
- preSigSz = length;
- /* sig length */
- length += LENGTH_SZ;
- if (!ssl->buffers.key.buffer)
- return NO_PRIVATE_KEY;
- InitRsaKey(&rsaKey, ssl->heap);
- ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i, &rsaKey,
- ssl->buffers.key.length);
- if (ret == 0) {
- sigSz = RsaEncryptSize(&rsaKey);
- length += sigSz;
- }
- }
- if (ret != 0) {
- FreeRsaKey(&rsaKey);
- return ret;
- }
-
- if (IsAtLeastTLSv1_2(ssl))
- length += HASH_SIG_SIZE;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls) {
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- preSigIdx = idx;
- }
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0) {
- FreeRsaKey(&rsaKey);
- return ret;
- }
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, length, server_key_exchange, ssl);
- /* add p, g, pub */
- c16toa((word16)ssl->buffers.serverDH_P.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length);
- idx += ssl->buffers.serverDH_P.length;
- /* g */
- c16toa((word16)ssl->buffers.serverDH_G.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- idx += ssl->buffers.serverDH_G.length;
- /* pub */
- c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx);
- idx += LENGTH_SZ;
- XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer,
- ssl->buffers.serverDH_Pub.length);
- idx += ssl->buffers.serverDH_Pub.length;
- /* Add signature */
- if (IsAtLeastTLSv1_2(ssl)) {
- output[idx++] = sha_mac;
- output[idx++] = ssl->specs.sig_algo;
- }
- /* size */
- c16toa((word16)sigSz, output + idx);
- idx += LENGTH_SZ;
- /* do signature */
- {
- Md5 md5;
- Sha sha;
- byte hash[FINISHED_SZ];
- byte* signBuffer = hash;
- word32 signSz = sizeof(hash);
- /* md5 */
- InitMd5(&md5);
- Md5Update(&md5, ssl->arrays.clientRandom, RAN_LEN);
- Md5Update(&md5, ssl->arrays.serverRandom, RAN_LEN);
- Md5Update(&md5, output + preSigIdx, preSigSz);
- Md5Final(&md5, hash);
- /* sha */
- InitSha(&sha);
- ShaUpdate(&sha, ssl->arrays.clientRandom, RAN_LEN);
- ShaUpdate(&sha, ssl->arrays.serverRandom, RAN_LEN);
- ShaUpdate(&sha, output + preSigIdx, preSigSz);
- ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]);
- if (ssl->specs.sig_algo == rsa_sa_algo) {
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- if (IsAtLeastTLSv1_2(ssl)) {
- byte* digest;
- int typeH;
- int digestSz;
- /* sha1 for now */
- digest = &hash[MD5_DIGEST_SIZE];
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- signSz = EncodeSignature(encodedSig, digest, digestSz,
- typeH);
- signBuffer = encodedSig;
- }
- ret = RsaSSL_Sign(signBuffer, signSz, output + idx, sigSz,
- &rsaKey, &ssl->rng);
- FreeRsaKey(&rsaKey);
- if (ret > 0)
- ret = 0; /* reset on success */
- else
- return ret;
- }
- }
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
- output, sendSz, ssl->heap);
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
- ret = SendBuffered(ssl);
- ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
- }
- #endif /* OPENSSL_EXTRA */
- return ret;
- }
- static int MatchSuite(CYASSL* ssl, Suites* peerSuites)
- {
- word16 i, j;
- /* & 0x1 equivalent % 2 */
- if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
- return MATCH_SUITE_ERROR;
- /* start with best, if a match we are good */
- for (i = 0; i < ssl->suites.suiteSz; i += 2)
- for (j = 0; j < peerSuites->suiteSz; j += 2)
- if (ssl->suites.suites[i] == peerSuites->suites[j] &&
- ssl->suites.suites[i+1] == peerSuites->suites[j+1] ) {
- ssl->options.cipherSuite0 = ssl->suites.suites[i];
- ssl->options.cipherSuite = ssl->suites.suites[i+1];
- return SetCipherSpecs(ssl);
- }
- return MATCH_SUITE_ERROR;
- }
- /* process old style client hello, deprecate? */
- int ProcessOldClientHello(CYASSL* ssl, const byte* input, word32* inOutIdx,
- word32 inSz, word16 sz)
- {
- word32 idx = *inOutIdx;
- word16 sessionSz;
- word16 randomSz;
- word16 i, j;
- ProtocolVersion pv;
- Suites clSuites;
- (void)inSz;
- CYASSL_MSG("Got old format client hello");
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ClientHello", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("ClientHello", &ssl->timeoutInfo);
- #endif
- /* manually hash input since different format */
- Md5Update(&ssl->hashMd5, input + idx, sz);
- ShaUpdate(&ssl->hashSha, input + idx, sz);
- #ifndef NO_SHA256
- if (IsAtLeastTLSv1_2(ssl))
- Sha256Update(&ssl->hashSha256, input + idx, sz);
- #endif
- /* does this value mean client_hello? */
- idx++;
- /* version */
- pv.major = input[idx++];
- pv.minor = input[idx++];
- ssl->chVersion = pv; /* store */
- if (ssl->version.minor > pv.minor) {
- byte havePSK = 0;
- if (!ssl->options.downgrade) {
- CYASSL_MSG("Client trying to connect with lesser version");
- return VERSION_ERROR;
- }
- if (pv.minor == SSLv3_MINOR) {
- /* turn off tls */
- CYASSL_MSG(" downgrading to SSLv3");
- ssl->options.tls = 0;
- ssl->options.tls1_1 = 0;
- ssl->version.minor = SSLv3_MINOR;
- }
- else if (pv.minor == TLSv1_MINOR) {
- CYASSL_MSG(" downgrading to TLSv1");
- /* turn off tls 1.1+ */
- ssl->options.tls1_1 = 0;
- ssl->version.minor = TLSv1_MINOR;
- }
- else if (pv.minor == TLSv1_1_MINOR) {
- CYASSL_MSG(" downgrading to TLSv1.1");
- ssl->version.minor = TLSv1_1_MINOR;
- }
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #endif
- InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK,
- ssl->options.haveNTRU, ssl->options.haveECDSA,
- ssl->ctx->method->side);
- }
- /* suite size */
- ato16(&input[idx], &clSuites.suiteSz);
- idx += 2;
- if (clSuites.suiteSz > MAX_SUITE_SZ)
- return BUFFER_ERROR;
- /* session size */
- ato16(&input[idx], &sessionSz);
- idx += 2;
- if (sessionSz > ID_LEN)
- return BUFFER_ERROR;
-
- /* random size */
- ato16(&input[idx], &randomSz);
- idx += 2;
- if (randomSz > RAN_LEN)
- return BUFFER_ERROR;
- /* suites */
- for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
- byte first = input[idx++];
- if (!first) { /* implicit: skip sslv2 type */
- XMEMCPY(&clSuites.suites[j], &input[idx], 2);
- j += 2;
- }
- idx += 2;
- }
- clSuites.suiteSz = j;
- /* session id */
- if (sessionSz) {
- XMEMCPY(ssl->arrays.sessionID, input + idx, sessionSz);
- idx += sessionSz;
- ssl->options.resuming = 1;
- }
- /* random */
- if (randomSz < RAN_LEN)
- XMEMSET(ssl->arrays.clientRandom, 0, RAN_LEN - randomSz);
- XMEMCPY(&ssl->arrays.clientRandom[RAN_LEN - randomSz], input + idx,
- randomSz);
- idx += randomSz;
- if (ssl->options.usingCompression)
- ssl->options.usingCompression = 0; /* turn off */
- ssl->options.clientState = CLIENT_HELLO_COMPLETE;
- *inOutIdx = idx;
- /* DoClientHello uses same resume code */
- while (ssl->options.resuming) { /* let's try */
- int ret;
- CYASSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
- if (!session) {
- ssl->options.resuming = 0;
- break; /* session lookup failed */
- }
- if (MatchSuite(ssl, &clSuites) < 0)
- return UNSUPPORTED_SUITE;
- RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
- if (ssl->options.tls)
- ret = DeriveTlsKeys(ssl);
- else
- ret = DeriveKeys(ssl);
- ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
- return ret;
- }
- return MatchSuite(ssl, &clSuites);
- }
- static int DoClientHello(CYASSL* ssl, const byte* input, word32* inOutIdx,
- word32 totalSz, word32 helloSz)
- {
- byte b;
- ProtocolVersion pv;
- Suites clSuites;
- word32 i = *inOutIdx;
- word32 begin = i;
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
- if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
- #endif
- /* make sure can read up to session */
- if (i + sizeof(pv) + RAN_LEN + ENUM_LEN > totalSz)
- return INCOMPLETE_DATA;
- XMEMCPY(&pv, input + i, sizeof(pv));
- ssl->chVersion = pv; /* store */
- i += sizeof(pv);
- if (ssl->version.minor > pv.minor) {
- byte havePSK = 0;
- if (!ssl->options.downgrade) {
- CYASSL_MSG("Client trying to connect with lesser version");
- return VERSION_ERROR;
- }
- if (pv.minor == SSLv3_MINOR) {
- /* turn off tls */
- CYASSL_MSG(" downgrading to SSLv3");
- ssl->options.tls = 0;
- ssl->options.tls1_1 = 0;
- ssl->version.minor = SSLv3_MINOR;
- }
- else if (pv.minor == TLSv1_MINOR) {
- /* turn off tls 1.1+ */
- CYASSL_MSG(" downgrading to TLSv1");
- ssl->options.tls1_1 = 0;
- ssl->version.minor = TLSv1_MINOR;
- }
- else if (pv.minor == TLSv1_1_MINOR) {
- CYASSL_MSG(" downgrading to TLSv1.1");
- ssl->version.minor = TLSv1_1_MINOR;
- }
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #endif
- InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK,
- ssl->options.haveNTRU, ssl->options.haveECDSA,
- ssl->ctx->method->side);
- }
- /* random */
- XMEMCPY(ssl->arrays.clientRandom, input + i, RAN_LEN);
- i += RAN_LEN;
- #ifdef SHOW_SECRETS
- {
- int j;
- printf("client random: ");
- for (j = 0; j < RAN_LEN; j++)
- printf("%02x", ssl->arrays.clientRandom[j]);
- printf("\n");
- }
- #endif
- /* session id */
- b = input[i++];
- if (b) {
- if (i + ID_LEN > totalSz)
- return INCOMPLETE_DATA;
- XMEMCPY(ssl->arrays.sessionID, input + i, ID_LEN);
- i += b;
- ssl->options.resuming= 1; /* client wants to resume */
- CYASSL_MSG("Client wants to resume session");
- }
-
- #ifdef CYASSL_DTLS
- /* cookie */
- if (ssl->options.dtls) {
- b = input[i++];
- if (b) {
- if (b > MAX_COOKIE_LEN)
- return BUFFER_ERROR;
- if (i + b > totalSz)
- return INCOMPLETE_DATA;
- XMEMCPY(ssl->arrays.cookie, input + i, b);
- i += b;
- }
- }
- #endif
- if (i + LENGTH_SZ > totalSz)
- return INCOMPLETE_DATA;
- /* suites */
- ato16(&input[i], &clSuites.suiteSz);
- i += 2;
- /* suites and comp len */
- if (i + clSuites.suiteSz + ENUM_LEN > totalSz)
- return INCOMPLETE_DATA;
- if (clSuites.suiteSz > MAX_SUITE_SZ)
- return BUFFER_ERROR;
- XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
- i += clSuites.suiteSz;
- b = input[i++]; /* comp len */
- if (i + b > totalSz)
- return INCOMPLETE_DATA;
- if (ssl->options.usingCompression) {
- int match = 0;
- while (b--) {
- byte comp = input[i++];
- if (comp == ZLIB_COMPRESSION)
- match = 1;
- }
- if (!match) {
- CYASSL_MSG("Not matching compression, turning off");
- ssl->options.usingCompression = 0; /* turn off */
- }
- }
- else
- i += b; /* ignore, since we're not on */
- ssl->options.clientState = CLIENT_HELLO_COMPLETE;
- *inOutIdx = i;
- if ( (i - begin) < helloSz)
- *inOutIdx = begin + helloSz; /* skip extensions */
-
- /* ProcessOld uses same resume code */
- while (ssl->options.resuming) { /* let's try */
- int ret;
- CYASSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
- if (!session) {
- ssl->options.resuming = 0;
- CYASSL_MSG("Session lookup for resume failed");
- break; /* session lookup failed */
- }
- if (MatchSuite(ssl, &clSuites) < 0)
- return UNSUPPORTED_SUITE;
- RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
- if (ssl->options.tls)
- ret = DeriveTlsKeys(ssl);
- else
- ret = DeriveKeys(ssl);
- ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
- return ret;
- }
- return MatchSuite(ssl, &clSuites);
- }
- static int DoCertificateVerify(CYASSL* ssl, byte* input, word32* inOutsz,
- word32 totalSz)
- {
- word16 sz = 0;
- word32 i = *inOutsz;
- int ret = VERIFY_CERT_ERROR; /* start in error state */
- byte* sig;
- byte* out;
- int outLen;
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("CertificateVerify", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("CertificateVerify", &ssl->timeoutInfo);
- #endif
- if ( (i + VERIFY_HEADER) > totalSz)
- return INCOMPLETE_DATA;
- if (IsAtLeastTLSv1_2(ssl))
- i += HASH_SIG_SIZE;
- ato16(&input[i], &sz);
- i += VERIFY_HEADER;
- if ( (i + sz) > totalSz)
- return INCOMPLETE_DATA;
- if (sz > ENCRYPT_LEN)
- return BUFFER_ERROR;
- sig = &input[i];
- *inOutsz = i + sz;
- /* TODO: when add DSS support check here */
- if (ssl->peerRsaKeyPresent != 0) {
- outLen = RsaSSL_VerifyInline(sig, sz, &out, &ssl->peerRsaKey);
- if (IsAtLeastTLSv1_2(ssl)) {
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- word32 sigSz;
- byte* digest;
- int typeH;
- int digestSz;
- /* sha1 for now */
- digest = ssl->certHashes.sha;
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- sigSz = EncodeSignature(encodedSig, digest, digestSz, typeH);
- if (outLen == (int)sigSz && XMEMCMP(out, encodedSig,sigSz) == 0)
- ret = 0;
- }
- else {
- if (outLen == sizeof(ssl->certHashes) && XMEMCMP(out,
- ssl->certHashes.md5, sizeof(ssl->certHashes)) == 0)
- ret = 0;
- }
- }
- return ret;
- }
- int SendServerHelloDone(CYASSL* ssl)
- {
- byte *output;
- int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
- int ret;
- #ifdef CYASSL_DTLS
- if (ssl->options.dtls)
- sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
- #endif
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, 0, server_hello_done, ssl);
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz,
- ssl->heap);
- #endif
- ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- int SendHelloVerifyRequest(CYASSL* ssl)
- {
- byte* output;
- int length = VERSION_SZ + ENUM_LEN;
- int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
- int sendSz = length + idx;
- int ret;
- /* check for avalaible size */
- if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
- return ret;
- /* get ouput buffer */
- output = ssl->buffers.outputBuffer.buffer +
- ssl->buffers.outputBuffer.idx;
- AddHeaders(output, length, hello_verify_request, ssl);
- XMEMCPY(output + idx, &ssl->chVersion, VERSION_SZ);
- idx += VERSION_SZ;
- output[idx++] = 0; /* no cookie for now */
- HashOutput(ssl, output, sendSz, 0);
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output,
- sendSz, ssl->heap);
- #endif
- ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
- ssl->buffers.outputBuffer.length += sendSz;
- return SendBuffered(ssl);
- }
- static int DoClientKeyExchange(CYASSL* ssl, byte* input,
- word32* inOutIdx)
- {
- int ret = 0;
- word32 length = 0;
- byte* out;
- if (ssl->options.verifyPeer && ssl->options.failNoCert)
- if (!ssl->options.havePeerCert) {
- CYASSL_MSG("client didn't present peer cert");
- return NO_PEER_CERT;
- }
- #ifdef CYASSL_CALLBACKS
- if (ssl->hsInfoOn)
- AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
- if (ssl->toInfoOn)
- AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
- #endif
- if (ssl->specs.kea == rsa_kea) {
- word32 idx = 0;
- RsaKey key;
- byte* tmp = 0;
- InitRsaKey(&key, ssl->heap);
- if (ssl->buffers.key.buffer)
- ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
- ssl->buffers.key.length);
- else
- return NO_PRIVATE_KEY;
- if (ret == 0) {
- length = RsaEncryptSize(&key);
- ssl->arrays.preMasterSz = SECRET_LEN;
- if (ssl->options.tls)
- (*inOutIdx) += 2;
- tmp = input + *inOutIdx;
- *inOutIdx += length;
- if (RsaPrivateDecryptInline(tmp, length, &out, &key) ==
- SECRET_LEN) {
- XMEMCPY(ssl->arrays.preMasterSecret, out, SECRET_LEN);
- if (ssl->arrays.preMasterSecret[0] != ssl->chVersion.major
- ||
- ssl->arrays.preMasterSecret[1] != ssl->chVersion.minor)
- ret = PMS_VERSION_ERROR;
- else
- ret = MakeMasterSecret(ssl);
- }
- else
- ret = RSA_PRIVATE_ERROR;
- }
- FreeRsaKey(&key);
- #ifndef NO_PSK
- } else if (ssl->specs.kea == psk_kea) {
- byte* pms = ssl->arrays.preMasterSecret;
- word16 ci_sz;
- ato16(&input[*inOutIdx], &ci_sz);
- *inOutIdx += LENGTH_SZ;
- if (ci_sz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
- XMEMCPY(ssl->arrays.client_identity, &input[*inOutIdx], ci_sz);
- *inOutIdx += ci_sz;
- ssl->arrays.client_identity[ci_sz] = 0;
- ssl->arrays.psk_keySz = ssl->options.server_psk_cb(ssl,
- ssl->arrays.client_identity, ssl->arrays.psk_key,
- MAX_PSK_KEY_LEN);
- if (ssl->arrays.psk_keySz == 0 ||
- ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN) return PSK_KEY_ERROR;
-
- /* make psk pre master secret */
- /* length of key + length 0s + length of key + key */
- c16toa((word16)ssl->arrays.psk_keySz, pms);
- pms += 2;
- XMEMSET(pms, 0, ssl->arrays.psk_keySz);
- pms += ssl->arrays.psk_keySz;
- c16toa((word16)ssl->arrays.psk_keySz, pms);
- pms += 2;
- XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
- ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
- ret = MakeMasterSecret(ssl);
- #endif /* NO_PSK */
- #ifdef HAVE_NTRU
- } else if (ssl->specs.kea == ntru_kea) {
- word32 rc;
- word16 cipherLen;
- word16 plainLen = sizeof(ssl->arrays.preMasterSecret);
- byte* tmp;
- if (!ssl->buffers.key.buffer)
- return NO_PRIVATE_KEY;
- ato16(&input[*inOutIdx], &cipherLen);
- *inOutIdx += LENGTH_SZ;
- if (cipherLen > MAX_NTRU_ENCRYPT_SZ)
- return NTRU_KEY_ERROR;
- tmp = input + *inOutIdx;
- rc = crypto_ntru_decrypt((word16)ssl->buffers.key.length,
- ssl->buffers.key.buffer, cipherLen, tmp, &plainLen,
- ssl->arrays.preMasterSecret);
- if (rc != NTRU_OK || plainLen != SECRET_LEN)
- return NTRU_DECRYPT_ERROR;
- *inOutIdx += cipherLen;
- ssl->arrays.preMasterSz = plainLen;
- ret = MakeMasterSecret(ssl);
- #endif /* HAVE_NTRU */
- #ifdef HAVE_ECC
- } else if (ssl->specs.kea == ecc_diffie_hellman_kea) {
- word32 size;
- word32 bLength = input[*inOutIdx]; /* one byte length */
- *inOutIdx += 1;
- ret = ecc_import_x963(&input[*inOutIdx], bLength, &ssl->peerEccKey);
- if (ret != 0)
- return ECC_PEERKEY_ERROR;
- *inOutIdx += bLength;
- ssl->peerEccKeyPresent = 1;
- size = sizeof(ssl->arrays.preMasterSecret);
- ret = ecc_shared_secret(&ssl->eccTempKey, &ssl->peerEccKey,
- ssl->arrays.preMasterSecret, &size);
- if (ret != 0)
- return ECC_SHARED_ERROR;
- ssl->arrays.preMasterSz = size;
- ret = MakeMasterSecret(ssl);
- #endif /* HAVE_ECC */
- #ifdef OPENSSL_EXTRA
- } else if (ssl->specs.kea == diffie_hellman_kea) {
- byte* clientPub;
- word16 clientPubSz;
- DhKey dhKey;
- ato16(&input[*inOutIdx], &clientPubSz);
- *inOutIdx += LENGTH_SZ;
- clientPub = &input[*inOutIdx];
- *inOutIdx += clientPubSz;
- InitDhKey(&dhKey);
- ret = DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
- ssl->buffers.serverDH_P.length,
- ssl->buffers.serverDH_G.buffer,
- ssl->buffers.serverDH_G.length);
- if (ret == 0)
- ret = DhAgree(&dhKey, ssl->arrays.preMasterSecret,
- &ssl->arrays.preMasterSz,
- ssl->buffers.serverDH_Priv.buffer,
- ssl->buffers.serverDH_Priv.length,
- clientPub, clientPubSz);
- FreeDhKey(&dhKey);
- if (ret == 0)
- ret = MakeMasterSecret(ssl);
- #endif /* OPENSSL_EXTRA */
- }
- if (ret == 0) {
- ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
- if (ssl->options.verifyPeer)
- BuildCertHashes(ssl, &ssl->certHashes);
- }
- return ret;
- }
- #endif /* NO_CYASSL_SERVER */
- #ifdef SINGLE_THREADED
- int InitMutex(CyaSSL_Mutex* m)
- {
- return 0;
- }
- int FreeMutex(CyaSSL_Mutex* m)
- {
- return 0;
- }
- int LockMutex(CyaSSL_Mutex* m)
- {
- return 0;
- }
- int UnLockMutex(CyaSSL_Mutex* m)
- {
- return 0;
- }
- #else /* MULTI_THREAD */
- #ifdef USE_WINDOWS_API
- int InitMutex(CyaSSL_Mutex* m)
- {
- InitializeCriticalSection(m);
- return 0;
- }
- int FreeMutex(CyaSSL_Mutex* m)
- {
- DeleteCriticalSection(m);
- return 0;
- }
- int LockMutex(CyaSSL_Mutex* m)
- {
- EnterCriticalSection(m);
- return 0;
- }
- int UnLockMutex(CyaSSL_Mutex* m)
- {
- LeaveCriticalSection(m);
- return 0;
- }
- #elif defined(CYASSL_PTHREADS)
- int InitMutex(CyaSSL_Mutex* m)
- {
- if (pthread_mutex_init(m, 0) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- int FreeMutex(CyaSSL_Mutex* m)
- {
- if (pthread_mutex_destroy(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- int LockMutex(CyaSSL_Mutex* m)
- {
- if (pthread_mutex_lock(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- int UnLockMutex(CyaSSL_Mutex* m)
- {
- if (pthread_mutex_unlock(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- #elif defined(THREADX)
- int InitMutex(CyaSSL_Mutex* m)
- {
- if (tx_mutex_create(m, "CyaSSL Mutex", TX_NO_INHERIT) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- int FreeMutex(CyaSSL_Mutex* m)
- {
- if (tx_mutex_delete(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- int LockMutex(CyaSSL_Mutex* m)
- {
- if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- int UnLockMutex(CyaSSL_Mutex* m)
- {
- if (tx_mutex_put(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- }
- #elif defined(MICRIUM)
- int InitMutex(CyaSSL_Mutex* m)
- {
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- if (NetSecure_OS_MutexCreate(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- #else
- return 0;
- #endif
- }
- int FreeMutex(CyaSSL_Mutex* m)
- {
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- if (NetSecure_OS_FreeMutex(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- #else
- return 0;
- #endif
- }
- int LockMutex(CyaSSL_Mutex* m)
- {
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- if (NetSecure_OS_LockMutex(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- #else
- return 0;
- #endif
- }
- int UnLockMutex(CyaSSL_Mutex* m)
- {
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- if (NetSecure_OS_UnLockMutex(m) == 0)
- return 0;
- else
- return BAD_MUTEX_ERROR;
- #else
- return 0;
- #endif
- }
- #endif /* USE_WINDOWS_API */
- #endif /* SINGLE_THREADED */
|