| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326 |
- /******************************************************************************
- *
- * Copyright (C) 1999-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
- /******************************************************************************
- *
- * This file contains functions for the Bluetooth Security Manager
- *
- ******************************************************************************/
- //#define LOG_TAG "bt_btm_sec"
- #include <stdarg.h>
- #include <string.h>
- #include "stack/bt_types.h"
- #include "device/controller.h"
- #include "stack/hcimsgs.h"
- #include "stack/btu.h"
- #include "btm_int.h"
- #include "l2c_int.h"
- #include "osi/fixed_queue.h"
- #include "osi/alarm.h"
- #include "stack/btm_ble_api.h"
- #if (BT_USE_TRACES == TRUE && BT_TRACE_VERBOSE == FALSE)
- /* needed for sprintf() */
- #include <stdio.h>
- #endif
- #if BLE_INCLUDED == TRUE
- #include "gatt_int.h"
- #endif
- #define BTM_SEC_MAX_COLLISION_DELAY (5000)
- #ifdef APPL_AUTH_WRITE_EXCEPTION
- BOOLEAN (APPL_AUTH_WRITE_EXCEPTION)(BD_ADDR bd_addr);
- #endif
- /********************************************************************************
- ** L O C A L F U N C T I O N P R O T O T Y P E S *
- *********************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static tBTM_SEC_SERV_REC *btm_sec_find_next_serv (tBTM_SEC_SERV_REC *p_cur);
- static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm,
- UINT32 mx_proto_id,
- UINT32 mx_chan_id);
- static tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_sec_start_get_name (tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_sec_start_authentication (tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_sec_start_encryption (tBTM_SEC_DEV_REC *p_dev_rec);
- static void btm_sec_collision_timeout (TIMER_LIST_ENT *p_tle);
- static void btm_restore_mode(void);
- static void btm_sec_pairing_timeout (TIMER_LIST_ENT *p_tle);
- static tBTM_STATUS btm_sec_dd_create_conn (tBTM_SEC_DEV_REC *p_dev_rec);
- static void btm_sec_change_pairing_state (tBTM_PAIRING_STATE new_state);
- #endif ///SMP_INCLUDED == TRUE
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- static char *btm_pair_state_descr (tBTM_PAIRING_STATE state);
- #endif
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_check_pending_reqs(void);
- static BOOLEAN btm_sec_queue_mx_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_orig,
- UINT32 mx_proto_id, UINT32 mx_chan_id,
- tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
- static void btm_sec_bond_cancel_complete (void);
- static void btm_send_link_key_notif (tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC *p_dev_rec);
- static UINT8 btm_sec_start_authorization (tBTM_SEC_DEV_REC *p_dev_rec);
- #endif ///SMP_INCLUDED == TRUE
- BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[]);
- #if (SMP_INCLUDED == TRUE)
- static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason, UINT16 conn_handle);
- #endif ///SMP_INCLUDED == TRUE
- UINT8 btm_sec_start_role_switch (tBTM_SEC_DEV_REC *p_dev_rec);
- tBTM_SEC_DEV_REC *btm_sec_find_dev_by_sec_state (UINT8 state);
- static BOOLEAN btm_sec_set_security_level ( CONNECTION_TYPE conn_type, const char *p_name, UINT8 service_id,
- UINT16 sec_level, UINT16 psm, UINT32 mx_proto_id,
- UINT32 mx_chan_id);
- #if (SMP_INCLUDED == TRUE)
- static BOOLEAN btm_dev_authenticated(tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_dev_encrypted(tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_dev_authorized(tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec);
- static BOOLEAN btm_sec_is_serv_level0 (UINT16 psm);
- static UINT16 btm_sec_set_serv_level4_flags (UINT16 cur_security, BOOLEAN is_originator);
- static BOOLEAN btm_sec_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT transport,
- tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
- static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRANSPORT transport,
- UINT8 encr_enable);
- static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec);
- static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec);
- #endif ///SMP_INCLUDED == TRUE
- /* TRUE - authenticated link key is possible */
- static const BOOLEAN btm_sec_io_map [BTM_IO_CAP_MAX][BTM_IO_CAP_MAX] = {
- /* OUT, IO, IN, NONE */
- /* OUT */ {FALSE, FALSE, TRUE, FALSE},
- /* IO */ {FALSE, TRUE, TRUE, FALSE},
- /* IN */ {TRUE, TRUE, TRUE, FALSE},
- /* NONE */ {FALSE, FALSE, FALSE, FALSE}
- };
- /* BTM_IO_CAP_OUT 0 DisplayOnly */
- /* BTM_IO_CAP_IO 1 DisplayYesNo */
- /* BTM_IO_CAP_IN 2 KeyboardOnly */
- /* BTM_IO_CAP_NONE 3 NoInputNoOutput */
- /*******************************************************************************
- **
- ** Function btm_dev_authenticated
- **
- ** Description check device is authenticated
- **
- ** Returns BOOLEAN TRUE or FALSE
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static BOOLEAN btm_dev_authenticated (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- if (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED) {
- return (TRUE);
- }
- return (FALSE);
- }
- /*******************************************************************************
- **
- ** Function btm_dev_encrypted
- **
- ** Description check device is encrypted
- **
- ** Returns BOOLEAN TRUE or FALSE
- **
- *******************************************************************************/
- static BOOLEAN btm_dev_encrypted (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- if (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED) {
- return (TRUE);
- }
- return (FALSE);
- }
- /*******************************************************************************
- **
- ** Function btm_dev_authorized
- **
- ** Description check device is authorized
- **
- ** Returns BOOLEAN TRUE or FALSE
- **
- *******************************************************************************/
- static BOOLEAN btm_dev_authorized (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- if (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED) {
- return (TRUE);
- }
- return (FALSE);
- }
- /*******************************************************************************
- **
- ** Function btm_dev_16_digit_authenticated
- **
- ** Description check device is authenticated by using 16 digit pin or MITM
- **
- ** Returns BOOLEAN TRUE or FALSE
- **
- *******************************************************************************/
- static BOOLEAN btm_dev_16_digit_authenticated(tBTM_SEC_DEV_REC *p_dev_rec)
- {
- // BTM_SEC_16_DIGIT_PIN_AUTHED is set if MITM or 16 digit pin is used
- if (p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED) {
- return (TRUE);
- }
- return (FALSE);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_serv_trusted
- **
- ** Description check service is trusted
- **
- ** Returns BOOLEAN TRUE or FALSE
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec)
- {
- if (BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask, p_serv_rec->service_id)) {
- return (TRUE);
- }
- return (FALSE);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_SecRegister
- **
- ** Description Application manager calls this function to register for
- ** security services. There can be one and only one application
- ** saving link keys. BTM allows only first registration.
- **
- ** Returns TRUE if registered OK, else FALSE
- **
- *******************************************************************************/
- BOOLEAN BTM_SecRegister(tBTM_APPL_INFO *p_cb_info)
- {
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- BT_OCTET16 temp_value = {0};
- #endif
- BTM_TRACE_EVENT("%s application registered\n", __func__);
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- BTM_TRACE_DEBUG("%s p_cb_info->p_le_callback == 0x%p\n", __func__, p_cb_info->p_le_callback);
- if (p_cb_info->p_le_callback) {
- BTM_TRACE_EVENT("%s SMP_Register( btm_proc_smp_cback )\n", __func__);
- SMP_Register(btm_proc_smp_cback);
- /* if no IR is loaded, need to regenerate all the keys */
- if (memcmp(btm_cb.devcb.id_keys.ir, &temp_value, sizeof(BT_OCTET16)) == 0) {
- btm_ble_reset_id();
- }
- } else {
- BTM_TRACE_WARNING("%s p_cb_info->p_le_callback == NULL\n", __func__);
- }
- #endif
- btm_cb.api = *p_cb_info;
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- BTM_TRACE_DEBUG("%s btm_cb.api.p_le_callback = 0x%p\n", __func__, btm_cb.api.p_le_callback);
- #endif
- BTM_TRACE_EVENT("%s application registered\n", __func__);
- return (TRUE);
- }
- /*******************************************************************************
- **
- ** Function BTM_SecRegisterLinkKeyNotificationCallback
- **
- ** Description Application manager calls this function to register for
- ** link key notification. When there is nobody registered
- ** we should avoid changing link key
- **
- ** Returns TRUE if registered OK, else FALSE
- **
- *******************************************************************************/
- BOOLEAN BTM_SecRegisterLinkKeyNotificationCallback (tBTM_LINK_KEY_CALLBACK *p_callback)
- {
- btm_cb.api.p_link_key_callback = p_callback;
- return TRUE;
- }
- /*******************************************************************************
- **
- ** Function BTM_SecAddRmtNameNotifyCallback
- **
- ** Description Any profile can register to be notified when name of the
- ** remote device is resolved.
- **
- ** Returns TRUE if registered OK, else FALSE
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE) || (CLASSIC_BT_INCLUDED == TRUE)
- BOOLEAN BTM_SecAddRmtNameNotifyCallback (tBTM_RMT_NAME_CALLBACK *p_callback)
- {
- int i;
- for (i = 0; i < BTM_SEC_MAX_RMT_NAME_CALLBACKS; i++) {
- if (btm_cb.p_rmt_name_callback[i] == NULL) {
- btm_cb.p_rmt_name_callback[i] = p_callback;
- return (TRUE);
- }
- }
- return (FALSE);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_SecDeleteRmtNameNotifyCallback
- **
- ** Description Any profile can deregister notification when a new Link Key
- ** is generated per connection.
- **
- ** Returns TRUE if OK, else FALSE
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE) || (CLASSIC_BT_INCLUDED == TRUE)
- BOOLEAN BTM_SecDeleteRmtNameNotifyCallback (tBTM_RMT_NAME_CALLBACK *p_callback)
- {
- int i;
- for (i = 0; i < BTM_SEC_MAX_RMT_NAME_CALLBACKS; i++) {
- if (btm_cb.p_rmt_name_callback[i] == p_callback) {
- btm_cb.p_rmt_name_callback[i] = NULL;
- return (TRUE);
- }
- }
- return (FALSE);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_GetSecurityFlags
- **
- ** Description Get security flags for the device
- **
- ** Returns BOOLEAN TRUE or FALSE is device found
- **
- *******************************************************************************/
- BOOLEAN BTM_GetSecurityFlags (BD_ADDR bd_addr, UINT8 *p_sec_flags)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL) {
- *p_sec_flags = (UINT8) p_dev_rec->sec_flags;
- return (TRUE);
- }
- BTM_TRACE_ERROR ("BTM_GetSecurityFlags false");
- return (FALSE);
- }
- /*******************************************************************************
- **
- ** Function BTM_GetSecurityFlagsByTransport
- **
- ** Description Get security flags for the device on a particular transport
- **
- ** Returns BOOLEAN TRUE or FALSE is device found
- **
- *******************************************************************************/
- BOOLEAN BTM_GetSecurityFlagsByTransport (BD_ADDR bd_addr, UINT8 *p_sec_flags,
- tBT_TRANSPORT transport)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL) {
- if (transport == BT_TRANSPORT_BR_EDR) {
- *p_sec_flags = (UINT8) p_dev_rec->sec_flags;
- } else {
- *p_sec_flags = (UINT8) (p_dev_rec->sec_flags >> 8);
- }
- return (TRUE);
- }
- BTM_TRACE_ERROR ("BTM_GetSecurityFlags false\n");
- return (FALSE);
- }
- #if (CLASSIC_BT_INCLUDED == TRUE)
- /*******************************************************************************
- **
- ** Function BTM_SetPinType
- **
- ** Description Set PIN type for the device.
- **
- ** Returns void
- **
- *******************************************************************************/
- void BTM_SetPinType (UINT8 pin_type, PIN_CODE pin_code, UINT8 pin_code_len)
- {
- BTM_TRACE_API ("BTM_SetPinType: pin type %d [variable-0, fixed-1], code %s, length %d\n",
- pin_type, (char *) pin_code, pin_code_len);
- /* If device is not up security mode will be set as a part of startup */
- if ( (btm_cb.cfg.pin_type != pin_type)
- && controller_get_interface()->get_is_ready() ) {
- btsnd_hcic_write_pin_type (pin_type);
- }
- btm_cb.cfg.pin_type = pin_type;
- btm_cb.cfg.pin_code_len = pin_code_len;
- memcpy (btm_cb.cfg.pin_code, pin_code, pin_code_len);
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_SetPairableMode
- **
- ** Description Enable or disable pairing
- **
- ** Parameters allow_pairing - (TRUE or FALSE) whether or not the device
- ** allows pairing.
- ** connect_only_paired - (TRUE or FALSE) whether or not to
- ** only allow paired devices to connect.
- **
- ** Returns void
- **
- *******************************************************************************/
- void BTM_SetPairableMode (BOOLEAN allow_pairing, BOOLEAN connect_only_paired)
- {
- BTM_TRACE_API ("BTM_SetPairableMode() allow_pairing: %u connect_only_paired: %u\n", allow_pairing, connect_only_paired);
- btm_cb.pairing_disabled = !allow_pairing;
- btm_cb.connect_only_paired = connect_only_paired;
- }
- /*******************************************************************************
- **
- ** Function BTM_SetSecureConnectionsOnly
- **
- ** Description Enable or disable default treatment for Mode 4 Level 0 services
- **
- ** Parameter secure_connections_only_mode - (TRUE or FALSE) whether or not the device
- ** TRUE means that the device should treat Mode 4 Level 0 services as
- ** services of other levels. (Secure_connections_only_mode)
- ** FALSE means that the device should provide default treatment for
- ** Mode 4 Level 0 services.
- **
- ** Returns void
- **
- *******************************************************************************/
- void BTM_SetSecureConnectionsOnly (BOOLEAN secure_connections_only_mode)
- {
- BTM_TRACE_API("%s: Mode : %u\n", __FUNCTION__,
- secure_connections_only_mode);
- btm_cb.devcb.secure_connections_only = secure_connections_only_mode;
- btm_cb.security_mode = BTM_SEC_MODE_SC;
- }
- #define BTM_NO_AVAIL_SEC_SERVICES ((UINT16) 0xffff)
- /*******************************************************************************
- **
- ** Function BTM_SetSecurityLevel
- **
- ** Description Register service security level with Security Manager
- **
- ** Parameters: is_originator - TRUE if originating the connection, FALSE if not
- ** p_name - Name of the service relevant only if
- ** authorization will show this name to user. ignored
- ** if BTM_SEC_SERVICE_NAME_LEN is 0.
- ** service_id - service ID for the service passed to authorization callback
- ** sec_level - bit mask of the security features
- ** psm - L2CAP PSM
- ** mx_proto_id - protocol ID of multiplexing proto below
- ** mx_chan_id - channel ID of multiplexing proto below
- **
- ** Returns TRUE if registered OK, else FALSE
- **
- *******************************************************************************/
- BOOLEAN BTM_SetSecurityLevel (BOOLEAN is_originator, const char *p_name, UINT8 service_id,
- UINT16 sec_level, UINT16 psm, UINT32 mx_proto_id,
- UINT32 mx_chan_id)
- {
- #if (L2CAP_UCD_INCLUDED == TRUE)
- CONNECTION_TYPE conn_type;
- if (is_originator) {
- conn_type = CONN_ORIENT_ORIG;
- } else {
- conn_type = CONN_ORIENT_TERM;
- }
- return (btm_sec_set_security_level (conn_type, p_name, service_id,
- sec_level, psm, mx_proto_id, mx_chan_id));
- #else
- return (btm_sec_set_security_level (is_originator, p_name, service_id,
- sec_level, psm, mx_proto_id, mx_chan_id));
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_sec_set_security_level
- **
- ** Description Register service security level with Security Manager
- **
- ** Parameters: conn_type - TRUE if originating the connection, FALSE if not
- ** p_name - Name of the service relevant only if
- ** authorization will show this name to user. ignored
- ** if BTM_SEC_SERVICE_NAME_LEN is 0.
- ** service_id - service ID for the service passed to authorization callback
- ** sec_level - bit mask of the security features
- ** psm - L2CAP PSM
- ** mx_proto_id - protocol ID of multiplexing proto below
- ** mx_chan_id - channel ID of multiplexing proto below
- **
- ** Returns TRUE if registered OK, else FALSE
- **
- *******************************************************************************/
- static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, const char *p_name, UINT8 service_id,
- UINT16 sec_level, UINT16 psm, UINT32 mx_proto_id,
- UINT32 mx_chan_id)
- {
- #if (SMP_INCLUDED == TRUE)
- tBTM_SEC_SERV_REC *p_srec;
- UINT16 index;
- UINT16 first_unused_record = BTM_NO_AVAIL_SEC_SERVICES;
- BOOLEAN record_allocated = FALSE;
- BOOLEAN is_originator;
- #if (L2CAP_UCD_INCLUDED == TRUE)
- BOOLEAN is_ucd;
- if (conn_type & CONNECTION_TYPE_ORIG_MASK) {
- is_originator = TRUE;
- } else {
- is_originator = FALSE;
- }
- if (conn_type & CONNECTION_TYPE_CONNLESS_MASK ) {
- is_ucd = TRUE;
- } else {
- is_ucd = FALSE;
- }
- #else
- is_originator = conn_type;
- #endif
- BTM_TRACE_API("%s : sec: 0x%x\n", __func__, sec_level);
- /* See if the record can be reused (same service name, psm, mx_proto_id,
- service_id, and mx_chan_id), or obtain the next unused record */
- p_srec = &btm_cb.sec_serv_rec[0];
- for (index = 0; index < BTM_SEC_MAX_SERVICE_RECORDS; index++, p_srec++) {
- /* Check if there is already a record for this service */
- if (p_srec->security_flags & BTM_SEC_IN_USE) {
- #if BTM_SEC_SERVICE_NAME_LEN > 0
- if (p_srec->psm == psm &&
- p_srec->mx_proto_id == mx_proto_id &&
- service_id == p_srec->service_id &&
- (!strncmp (p_name, (char *) p_srec->orig_service_name,
- BTM_SEC_SERVICE_NAME_LEN) ||
- !strncmp (p_name, (char *) p_srec->term_service_name,
- BTM_SEC_SERVICE_NAME_LEN)))
- #else
- if (p_srec->psm == psm &&
- p_srec->mx_proto_id == mx_proto_id &&
- service_id == p_srec->service_id)
- #endif
- {
- record_allocated = TRUE;
- break;
- }
- }
- /* Mark the first available service record */
- else if (!record_allocated) {
- memset (p_srec, 0, sizeof(tBTM_SEC_SERV_REC));
- record_allocated = TRUE;
- first_unused_record = index;
- }
- }
- if (!record_allocated) {
- BTM_TRACE_WARNING("BTM_SEC_REG: Out of Service Records (%d)\n", BTM_SEC_MAX_SERVICE_RECORDS);
- return (record_allocated);
- }
- /* Process the request if service record is valid */
- /* If a duplicate service wasn't found, use the first available */
- if (index >= BTM_SEC_MAX_SERVICE_RECORDS) {
- index = first_unused_record;
- p_srec = &btm_cb.sec_serv_rec[index];
- }
- p_srec->psm = psm;
- p_srec->service_id = service_id;
- p_srec->mx_proto_id = mx_proto_id;
- if (is_originator) {
- p_srec->orig_mx_chan_id = mx_chan_id;
- #if BTM_SEC_SERVICE_NAME_LEN > 0
- BCM_STRNCPY_S ((char *)p_srec->orig_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN);
- #endif
- /* clear out the old setting, just in case it exists */
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if ( is_ucd ) {
- p_srec->ucd_security_flags &=
- ~(BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_MITM |
- BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE);
- } else
- #endif
- {
- p_srec->security_flags &=
- ~(BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_MITM |
- BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE);
- }
- /* Parameter validation. Originator should not set requirements for incoming connections */
- sec_level &= ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE
- | BTM_SEC_IN_MITM | BTM_SEC_IN_MIN_16_DIGIT_PIN );
- if (btm_cb.security_mode == BTM_SEC_MODE_SP ||
- btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
- btm_cb.security_mode == BTM_SEC_MODE_SC) {
- if (sec_level & BTM_SEC_OUT_AUTHENTICATE) {
- sec_level |= BTM_SEC_OUT_MITM;
- }
- }
- /* Make sure the authenticate bit is set, when encrypt bit is set */
- if (sec_level & BTM_SEC_OUT_ENCRYPT) {
- sec_level |= BTM_SEC_OUT_AUTHENTICATE;
- }
- /* outgoing connections usually set the security level right before
- * the connection is initiated.
- * set it to be the outgoing service */
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if ( is_ucd == FALSE )
- #endif
- {
- btm_cb.p_out_serv = p_srec;
- }
- } else {
- p_srec->term_mx_chan_id = mx_chan_id;
- #if BTM_SEC_SERVICE_NAME_LEN > 0
- BCM_STRNCPY_S ((char *)p_srec->term_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN);
- #endif
- /* clear out the old setting, just in case it exists */
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if ( is_ucd ) {
- p_srec->ucd_security_flags &=
- ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM |
- BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE
- | BTM_SEC_IN_MIN_16_DIGIT_PIN);
- } else
- #endif
- {
- p_srec->security_flags &=
- ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM |
- BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE
- | BTM_SEC_IN_MIN_16_DIGIT_PIN);
- }
- /* Parameter validation. Acceptor should not set requirements for outgoing connections */
- sec_level &= ~(BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_MITM);
- if (btm_cb.security_mode == BTM_SEC_MODE_SP ||
- btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
- btm_cb.security_mode == BTM_SEC_MODE_SC) {
- if (sec_level & BTM_SEC_IN_AUTHENTICATE) {
- sec_level |= BTM_SEC_IN_MITM;
- }
- }
- /* Make sure the authenticate bit is set, when encrypt bit is set */
- if (sec_level & BTM_SEC_IN_ENCRYPT) {
- sec_level |= BTM_SEC_IN_AUTHENTICATE;
- }
- }
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if ( is_ucd ) {
- p_srec->security_flags |= (UINT16)(BTM_SEC_IN_USE);
- p_srec->ucd_security_flags |= (UINT16)(sec_level | BTM_SEC_IN_USE);
- } else {
- p_srec->security_flags |= (UINT16)(sec_level | BTM_SEC_IN_USE);
- }
- BTM_TRACE_API("BTM_SEC_REG[%d]: id %d, conn_type 0x%x, psm 0x%04x, proto_id %d, chan_id %d\n",
- index, service_id, conn_type, psm, mx_proto_id, mx_chan_id);
- BTM_TRACE_API(" : security_flags: 0x%04x, ucd_security_flags: 0x%04x\n",
- p_srec->security_flags, p_srec->ucd_security_flags);
- #if BTM_SEC_SERVICE_NAME_LEN > 0
- BTM_TRACE_API(" : service name [%s] (up to %d chars saved)\n",
- p_name, BTM_SEC_SERVICE_NAME_LEN);
- #endif
- #else
- p_srec->security_flags |= (UINT16)(sec_level | BTM_SEC_IN_USE);
- BTM_TRACE_API("BTM_SEC_REG[%d]: id %d, is_orig %d, psm 0x%04x, proto_id %d, chan_id %d\n",
- index, service_id, is_originator, psm, mx_proto_id, mx_chan_id);
- #if BTM_SEC_SERVICE_NAME_LEN > 0
- BTM_TRACE_API(" : sec: 0x%x, service name [%s] (up to %d chars saved)\n",
- p_srec->security_flags, p_name, BTM_SEC_SERVICE_NAME_LEN);
- #endif
- #endif
- return (record_allocated);
- #else
- return FALSE;
- #endif ///SMP_INCLUDED == TRUE
- }
- /*******************************************************************************
- **
- ** Function BTM_SecClrService
- **
- ** Description Removes specified service record(s) from the security database.
- ** All service records with the specified name are removed.
- ** Typically used only by devices with limited RAM so that it can
- ** reuse an old security service record.
- **
- ** Note: Unpredictable results may occur if a service is cleared
- ** that is still in use by an application/profile.
- **
- ** Parameters Service ID - Id of the service to remove. ('0' removes all service
- ** records (except SDP).
- **
- ** Returns Number of records that were freed.
- **
- *******************************************************************************/
- #if (SDP_INCLUDED == TRUE)
- UINT8 BTM_SecClrService (UINT8 service_id)
- {
- tBTM_SEC_SERV_REC *p_srec = &btm_cb.sec_serv_rec[0];
- UINT8 num_freed = 0;
- int i;
- for (i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_srec++) {
- /* Delete services with specified name (if in use and not SDP) */
- if ((p_srec->security_flags & BTM_SEC_IN_USE) && (p_srec->psm != BT_PSM_SDP) &&
- (!service_id || (service_id == p_srec->service_id))) {
- BTM_TRACE_API("BTM_SEC_CLR[%d]: id %d\n", i, service_id);
- p_srec->security_flags = 0;
- #if (L2CAP_UCD_INCLUDED == TRUE)
- p_srec->ucd_security_flags = 0;
- #endif
- num_freed++;
- }
- }
- return (num_freed);
- }
- #endif ///SDP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_clr_service_by_psm
- **
- ** Description Removes specified service record from the security database.
- ** All service records with the specified psm are removed.
- ** Typically used by L2CAP to free up the service record used
- ** by dynamic PSM clients when the channel is closed.
- ** The given psm must be a virtual psm.
- **
- ** Parameters Service ID - Id of the service to remove. ('0' removes all service
- ** records (except SDP).
- **
- ** Returns Number of records that were freed.
- **
- *******************************************************************************/
- #if (SDP_INCLUDED== TRUE)
- UINT8 btm_sec_clr_service_by_psm (UINT16 psm)
- {
- tBTM_SEC_SERV_REC *p_srec = &btm_cb.sec_serv_rec[0];
- UINT8 num_freed = 0;
- int i;
- for (i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_srec++) {
- /* Delete services with specified name (if in use and not SDP) */
- if ((p_srec->security_flags & BTM_SEC_IN_USE) && (p_srec->psm == psm) ) {
- BTM_TRACE_API("BTM_SEC_CLR[%d]: id %d\n", i, p_srec->service_id);
- p_srec->security_flags = 0;
- num_freed++;
- }
- }
- BTM_TRACE_API("btm_sec_clr_service_by_psm psm:0x%x num_freed:%d\n", psm, num_freed);
- return (num_freed);
- }
- #endif ///SDP_INCLUDED== TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_clr_temp_auth_service
- **
- ** Description Removes specified device record's temporary authorization
- ** flag from the security database.
- **
- ** Parameters Device address to be cleared
- **
- ** Returns void.
- **
- *******************************************************************************/
- void btm_sec_clr_temp_auth_service (BD_ADDR bda)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- if ((p_dev_rec = btm_find_dev (bda)) == NULL) {
- BTM_TRACE_WARNING ("btm_sec_clr_temp_auth_service() - no dev CB\n");
- return;
- }
- /* Reset the temporary authorized flag so that next time (untrusted) service is accessed autorization will take place */
- if (p_dev_rec->last_author_service_id != BTM_SEC_NO_LAST_SERVICE_ID && p_dev_rec->p_cur_service) {
- BTM_TRACE_DEBUG ("btm_sec_clr_auth_service_by_psm [clearing device: %02x:%02x:%02x:%02x:%02x:%02x]\n",
- bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
- p_dev_rec->last_author_service_id = BTM_SEC_NO_LAST_SERVICE_ID;
- }
- }
- /*******************************************************************************
- **
- ** Function BTM_PINCodeReply
- **
- ** Description This function is called after Security Manager submitted
- ** PIN code request to the UI.
- **
- ** Parameters: bd_addr - Address of the device for which PIN was requested
- ** res - result of the operation BTM_SUCCESS if success
- ** pin_len - length in bytes of the PIN Code
- ** p_pin - pointer to array with the PIN Code
- ** trusted_mask - bitwise OR of trusted services (array of UINT32)
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- #if (CLASSIC_BT_INCLUDED == TRUE)
- void BTM_PINCodeReply (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_API ("BTM_PINCodeReply(): PairState: %s PairFlags: 0x%02x PinLen:%d Result:%d\n",
- btm_pair_state_descr(btm_cb.pairing_state), btm_cb.pairing_flags, pin_len, res);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- /* If timeout already expired or has been canceled, ignore the reply */
- if (btm_cb.pairing_state != BTM_PAIR_STATE_WAIT_LOCAL_PIN) {
- BTM_TRACE_WARNING ("BTM_PINCodeReply() - Wrong State: %d\n", btm_cb.pairing_state);
- return;
- }
- if (memcmp (bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN) != 0) {
- BTM_TRACE_ERROR ("BTM_PINCodeReply() - Wrong BD Addr\n");
- return;
- }
- if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL) {
- BTM_TRACE_ERROR ("BTM_PINCodeReply() - no dev CB\n");
- return;
- }
- if ( (pin_len > PIN_CODE_LEN) || (pin_len == 0) || (p_pin == NULL) ) {
- res = BTM_ILLEGAL_VALUE;
- }
- if (res != BTM_SUCCESS) {
- /* if peer started dd OR we started dd and pre-fetch pin was not used send negative reply */
- if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_PEER_STARTED_DD) ||
- ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) &&
- (btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE)) ) {
- /* use BTM_PAIR_STATE_WAIT_AUTH_COMPLETE to report authentication failed event */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
- btsnd_hcic_pin_code_neg_reply (bd_addr);
- } else {
- p_dev_rec->security_required = BTM_SEC_NONE;
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- }
- return;
- }
- if (trusted_mask) {
- BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
- }
- p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
- if (pin_len >= 16) {
- p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
- }
- if ( (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)
- && (p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE)
- && (btm_cb.security_mode_changed == FALSE) ) {
- /* This is start of the dedicated bonding if local device is 2.0 */
- btm_cb.pin_code_len = pin_len;
- p_dev_rec->pin_code_length = pin_len;
- memcpy (btm_cb.pin_code, p_pin, pin_len);
- btm_cb.security_mode_changed = TRUE;
- #ifdef APPL_AUTH_WRITE_EXCEPTION
- if (!(APPL_AUTH_WRITE_EXCEPTION)(p_dev_rec->bd_addr))
- #endif
- {
- btsnd_hcic_write_auth_enable (TRUE);
- }
- btm_cb.acl_disc_reason = 0xff ;
- /* if we rejected incoming connection request, we have to wait HCI_Connection_Complete event */
- /* before originating */
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_REJECTED_CONNECT) {
- BTM_TRACE_WARNING ("BTM_PINCodeReply(): waiting HCI_Connection_Complete after rejected incoming connection\n");
- /* we change state little bit early so btm_sec_connected() will originate connection */
- /* when existing ACL link is down completely */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
- }
- /* if we already accepted incoming connection from pairing device */
- else if (p_dev_rec->sm4 & BTM_SM4_CONN_PEND) {
- BTM_TRACE_WARNING ("BTM_PINCodeReply(): link is connecting so wait pin code request from peer\n");
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
- } else if (btm_sec_dd_create_conn(p_dev_rec) != BTM_CMD_STARTED) {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_AUTHED;
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_ERR_AUTH_FAILURE);
- }
- }
- return;
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- btm_cb.acl_disc_reason = HCI_SUCCESS;
- #ifdef PORCHE_PAIRING_CONFLICT
- BTM_TRACE_EVENT("BTM_PINCodeReply(): Saving pin_len: %d btm_cb.pin_code_len: %d\n", pin_len, btm_cb.pin_code_len);
- /* if this was not pre-fetched, save the PIN */
- if (btm_cb.pin_code_len == 0) {
- memcpy (btm_cb.pin_code, p_pin, pin_len);
- }
- btm_cb.pin_code_len_saved = pin_len;
- #endif
- btsnd_hcic_pin_code_req_reply (bd_addr, pin_len, p_pin);
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_bond_by_transport
- **
- ** Description this is the bond function that will start either SSP or SMP.
- **
- ** Parameters: bd_addr - Address of the device to bond
- ** pin_len - length in bytes of the PIN Code
- ** p_pin - pointer to array with the PIN Code
- ** trusted_mask - bitwise OR of trusted services (array of UINT32)
- **
- ** Note: After 2.1 parameters are not used and preserved here not to change API
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
- UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_STATUS status;
- #if (!CONFIG_BT_STACK_NO_LOG)
- UINT8 *p_features;
- #endif
- UINT8 ii;
- tACL_CONN *p = btm_bda_to_acl(bd_addr, transport);
- BTM_TRACE_API ("btm_sec_bond_by_transport BDA: %02x:%02x:%02x:%02x:%02x:%02x\n",
- bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
- BTM_TRACE_DEBUG("btm_sec_bond_by_transport: Transport used %d\n" , transport);
- /* Other security process is in progress */
- if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_ERROR ("BTM_SecBond: already busy in state: %s\n", btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- return (BTM_WRONG_MODE);
- }
- if ((p_dev_rec = btm_find_or_alloc_dev (bd_addr)) == NULL) {
- return (BTM_NO_RESOURCES);
- }
- BTM_TRACE_DEBUG ("before update sec_flags=0x%x\n", p_dev_rec->sec_flags);
- /* Finished if connection is active and already paired */
- if ( ((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_BR_EDR
- && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))
- #if (BLE_INCLUDED == TRUE)
- || ((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_LE
- && (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))
- #endif
- ) {
- BTM_TRACE_WARNING("BTM_SecBond -> Already Paired\n");
- return (BTM_SUCCESS);
- }
- /* Tell controller to get rid of the link key if it has one stored */
- if ((BTM_DeleteStoredLinkKey (bd_addr, NULL)) != BTM_SUCCESS) {
- return (BTM_NO_RESOURCES);
- }
- #if (CLASSIC_BT_INCLUDED == TRUE)
- /* Save the PIN code if we got a valid one */
- if (p_pin && (pin_len <= PIN_CODE_LEN) && (pin_len != 0)) {
- btm_cb.pin_code_len = pin_len;
- p_dev_rec->pin_code_length = pin_len;
- memcpy (btm_cb.pin_code, p_pin, PIN_CODE_LEN);
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- memcpy (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN);
- btm_cb.pairing_flags = BTM_PAIR_FLAGS_WE_STARTED_DD;
- p_dev_rec->security_required = BTM_SEC_OUT_AUTHENTICATE;
- p_dev_rec->is_originator = TRUE;
- if (trusted_mask) {
- BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
- }
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (transport == BT_TRANSPORT_LE) {
- btm_ble_init_pseudo_addr (p_dev_rec, bd_addr);
- p_dev_rec->sec_flags &= ~ BTM_SEC_LE_MASK;
- if (SMP_Pair(bd_addr) == SMP_STARTED) {
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
- p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- return BTM_CMD_STARTED;
- }
- btm_cb.pairing_flags = 0;
- return (BTM_NO_RESOURCES);
- }
- #endif
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
- | BTM_SEC_ROLE_SWITCHED | BTM_SEC_LINK_KEY_AUTHED);
- BTM_TRACE_DEBUG ("after update sec_flags=0x%x\n", p_dev_rec->sec_flags);
- #if (CLASSIC_BT_INCLUDED == TRUE)
- if (!controller_get_interface()->supports_simple_pairing()) {
- /* The special case when we authenticate keyboard. Set pin type to fixed */
- /* It would be probably better to do it from the application, but it is */
- /* complicated */
- if (((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) == BTM_COD_MAJOR_PERIPHERAL)
- && (p_dev_rec->dev_class[2] & BTM_COD_MINOR_KEYBOARD)
- && (btm_cb.cfg.pin_type != HCI_PIN_TYPE_FIXED)) {
- btm_cb.pin_type_changed = TRUE;
- btsnd_hcic_write_pin_type (HCI_PIN_TYPE_FIXED);
- }
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- for (ii = 0; ii <= HCI_EXT_FEATURES_PAGE_MAX; ii++) {
- #if (!CONFIG_BT_STACK_NO_LOG)
- p_features = p_dev_rec->features[ii];
- #endif
- BTM_TRACE_EVENT(" remote_features page[%1d] = %02x-%02x-%02x-%02x\n",
- ii, p_features[0], p_features[1], p_features[2], p_features[3]);
- BTM_TRACE_EVENT(" %02x-%02x-%02x-%02x\n",
- p_features[4], p_features[5], p_features[6], p_features[7]);
- }
- BTM_TRACE_EVENT ("BTM_SecBond: Remote sm4: 0x%x HCI Handle: 0x%04x\n", p_dev_rec->sm4, p_dev_rec->hci_handle);
- #if BTM_SEC_FORCE_RNR_FOR_DBOND == TRUE
- p_dev_rec->sec_flags &= ~BTM_SEC_NAME_KNOWN;
- #endif
- /* If connection already exists... */
- if (p && p->hci_handle != BTM_SEC_INVALID_HANDLE) {
- if (!btm_sec_start_authentication (p_dev_rec)) {
- return (BTM_NO_RESOURCES);
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
- /* Mark lcb as bonding */
- l2cu_update_lcb_4_bonding (bd_addr, TRUE);
- return (BTM_CMD_STARTED);
- }
- BTM_TRACE_DEBUG ("sec mode: %d sm4:x%x\n", btm_cb.security_mode, p_dev_rec->sm4);
- if (!controller_get_interface()->supports_simple_pairing()
- || (p_dev_rec->sm4 == BTM_SM4_KNOWN)) {
- if ( btm_sec_check_prefetch_pin (p_dev_rec) ) {
- return (BTM_CMD_STARTED);
- }
- }
- if ((btm_cb.security_mode == BTM_SEC_MODE_SP ||
- btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
- btm_cb.security_mode == BTM_SEC_MODE_SC) &&
- BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
- /* local is 2.1 and peer is unknown */
- if ((p_dev_rec->sm4 & BTM_SM4_CONN_PEND) == 0) {
- /* we are not accepting connection request from peer
- * -> RNR (to learn if peer is 2.1)
- * RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
- BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
- } else {
- /* We are accepting connection request from peer */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
- }
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_DEBUG ("State:%s sm4: 0x%x sec_state:%d\n",
- btm_pair_state_descr (btm_cb.pairing_state), p_dev_rec->sm4, p_dev_rec->sec_state);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- return BTM_CMD_STARTED;
- }
- /* both local and peer are 2.1 */
- status = btm_sec_dd_create_conn(p_dev_rec);
- if (status != BTM_CMD_STARTED) {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- }
- return status;
- }
- /*******************************************************************************
- **
- ** Function BTM_SecBondByTransport
- **
- ** Description This function is called to perform bonding with peer device.
- ** If the connection is already up, but not secure, pairing
- ** is attempted. If already paired BTM_SUCCESS is returned.
- **
- ** Parameters: bd_addr - Address of the device to bond
- ** transport - doing SSP over BR/EDR or SMP over LE
- ** pin_len - length in bytes of the PIN Code
- ** p_pin - pointer to array with the PIN Code
- ** trusted_mask - bitwise OR of trusted services (array of UINT32)
- **
- ** Note: After 2.1 parameters are not used and preserved here not to change API
- *******************************************************************************/
- tBTM_STATUS BTM_SecBondByTransport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
- UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
- {
- #if (BLE_INCLUDED == TRUE)
- tBT_DEVICE_TYPE dev_type;
- tBLE_ADDR_TYPE addr_type;
- BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
- /* LE device, do SMP pairing */
- if ((transport == BT_TRANSPORT_LE && (dev_type & BT_DEVICE_TYPE_BLE) == 0) ||
- (transport == BT_TRANSPORT_BR_EDR && (dev_type & BT_DEVICE_TYPE_BREDR) == 0)) {
- return BTM_ILLEGAL_ACTION;
- }
- #endif ///BLE_INCLUDED == TRUE
- return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin, trusted_mask);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_SecBond
- **
- ** Description This function is called to perform bonding with peer device.
- ** If the connection is already up, but not secure, pairing
- ** is attempted. If already paired BTM_SUCCESS is returned.
- **
- ** Parameters: bd_addr - Address of the device to bond
- ** pin_len - length in bytes of the PIN Code
- ** p_pin - pointer to array with the PIN Code
- ** trusted_mask - bitwise OR of trusted services (array of UINT32)
- **
- ** Note: After 2.1 parameters are not used and preserved here not to change API
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
- {
- tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
- #if (BLE_INCLUDED == TRUE)
- if (BTM_UseLeLink(bd_addr)) {
- transport = BT_TRANSPORT_LE;
- }
- #endif ///BLE_INCLUDED == TRUE
- return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin, trusted_mask);
- }
- /*******************************************************************************
- **
- ** Function BTM_SecBondCancel
- **
- ** Description This function is called to cancel ongoing bonding process
- ** with peer device.
- **
- ** Parameters: bd_addr - Address of the peer device
- ** transport - FALSE for BR/EDR link; TRUE for LE link
- **
- *******************************************************************************/
- tBTM_STATUS BTM_SecBondCancel (BD_ADDR bd_addr)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_API ("BTM_SecBondCancel() State: %s flags:0x%x\n",
- btm_pair_state_descr (btm_cb.pairing_state), btm_cb.pairing_flags);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- if (((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
- || (memcmp (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN) != 0) ) {
- return BTM_UNKNOWN_ADDR;
- }
- #if SMP_INCLUDED == TRUE
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_LE_ACTIVE) {
- if (p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING) {
- BTM_TRACE_DEBUG ("Cancel LE pairing\n");
- if (SMP_PairCancel(bd_addr)) {
- return BTM_CMD_STARTED;
- }
- }
- return BTM_WRONG_MODE;
- }
- #endif
- BTM_TRACE_DEBUG ("hci_handle:0x%x sec_state:%d\n", p_dev_rec->hci_handle, p_dev_rec->sec_state );
- if (BTM_PAIR_STATE_WAIT_LOCAL_PIN == btm_cb.pairing_state &&
- BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags) {
- /* pre-fetching pin for dedicated bonding */
- btm_sec_bond_cancel_complete();
- return BTM_SUCCESS;
- }
- /* If this BDA is in a bonding procedure */
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)) {
- /* If the HCI link is up */
- if (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) {
- /* If some other thread disconnecting, we do not send second command */
- if ((p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING) ||
- (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING_BOTH)) {
- return (BTM_CMD_STARTED);
- }
- /* If the HCI link was set up by Bonding process */
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) {
- return btm_sec_send_hci_disconnect(p_dev_rec, HCI_ERR_PEER_USER, p_dev_rec->hci_handle);
- } else {
- l2cu_update_lcb_4_bonding(bd_addr, FALSE);
- }
- return BTM_NOT_AUTHORIZED;
- } else { /*HCI link is not up */
- /* If the HCI link creation was started by Bonding process */
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) {
- if (btsnd_hcic_create_conn_cancel(bd_addr)) {
- return BTM_CMD_STARTED;
- }
- return BTM_NO_RESOURCES;
- }
- if (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME) {
- BTM_CancelRemoteDeviceName();
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_WE_CANCEL_DD;
- return BTM_CMD_STARTED;
- }
- return BTM_NOT_AUTHORIZED;
- }
- }
- return BTM_WRONG_MODE;
- }
- /*******************************************************************************
- **
- ** Function BTM_SecGetDeviceLinkKey
- **
- ** Description This function is called to obtain link key for the device
- ** it returns BTM_SUCCESS if link key is available, or
- ** BTM_UNKNOWN_ADDR if Security Manager does not know about
- ** the device or device record does not contain link key info
- **
- ** Parameters: bd_addr - Address of the device
- ** link_key - Link Key is copied into this array
- **
- *******************************************************************************/
- tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr, LINK_KEY link_key)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- if (((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
- && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) {
- memcpy (link_key, p_dev_rec->link_key, LINK_KEY_LEN);
- return (BTM_SUCCESS);
- }
- return (BTM_UNKNOWN_ADDR);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_SecGetDeviceLinkKeyType
- **
- ** Description This function is called to obtain link key type for the
- ** device.
- ** it returns BTM_SUCCESS if link key is available, or
- ** BTM_UNKNOWN_ADDR if Security Manager does not know about
- ** the device or device record does not contain link key info
- **
- ** Returns BTM_LKEY_TYPE_IGNORE if link key is unknown, link type
- ** otherwise.
- **
- *******************************************************************************/
- tBTM_LINK_KEY_TYPE BTM_SecGetDeviceLinkKeyType (BD_ADDR bd_addr)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
- if ((p_dev_rec != NULL) && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) {
- return p_dev_rec->link_key_type;
- }
- return BTM_LKEY_TYPE_IGNORE;
- }
- /*******************************************************************************
- **
- ** Function BTM_SetEncryption
- **
- ** Description This function is called to ensure that connection is
- ** encrypted. Should be called only on an open connection.
- ** Typically only needed for connections that first want to
- ** bring up unencrypted links, then later encrypt them.
- **
- ** Parameters: bd_addr - Address of the peer device
- ** p_callback - Pointer to callback function called if
- ** this function returns PENDING after required
- ** procedures are completed. Can be set to NULL
- ** if status is not desired.
- ** p_ref_data - pointer to any data the caller wishes to receive
- ** in the callback function upon completion.
- * can be set to NULL if not used.
- ** transport - TRUE to encryption the link over LE transport
- ** or FALSE for BR/EDR transport
- **
- ** Returns BTM_SUCCESS - already encrypted
- ** BTM_PENDING - command will be returned in the callback
- ** BTM_WRONG_MODE- connection not up.
- ** BTM_BUSY - security procedures are currently active
- ** BTM_MODE_UNSUPPORTED - if security manager not linked in.
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CBACK *p_callback,
- void *p_ref_data)
- {
- tBTM_STATUS rc = 0;
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
- if (!p_dev_rec ||
- (transport == BT_TRANSPORT_BR_EDR && p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE)
- #if BLE_INCLUDED == TRUE
- || (transport == BT_TRANSPORT_LE && p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE)
- #endif
- ) {
- /* Connection should be up and runnning */
- BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption not connected\n");
- if (p_callback) {
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_WRONG_MODE);
- }
- return (BTM_WRONG_MODE);
- }
- if ((transport == BT_TRANSPORT_BR_EDR &&
- (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- || (transport == BT_TRANSPORT_LE &&
- (p_dev_rec->sec_flags & BTM_SEC_LE_ENCRYPTED))
- #endif
- ) {
- BTM_TRACE_EVENT ("Security Manager: BTM_SetEncryption already encrypted\n");
- if (p_callback) {
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_SUCCESS);
- }
- return (BTM_SUCCESS);
- }
- p_dev_rec->enc_init_by_we = TRUE;
- /* enqueue security request if security is active */
- if (p_dev_rec->p_callback || (p_dev_rec->sec_state != BTM_SEC_STATE_IDLE)) {
- BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption busy, enqueue request\n");
- if (btm_sec_queue_encrypt_request(bd_addr, transport, p_callback, p_ref_data)) {
- return BTM_CMD_STARTED;
- } else {
- if (p_callback) {
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_NO_RESOURCES);
- }
- return BTM_NO_RESOURCES;
- }
- }
- p_dev_rec->p_callback = p_callback;
- p_dev_rec->p_ref_data = p_ref_data;
- p_dev_rec->security_required |= (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT);
- p_dev_rec->is_originator = FALSE;
- BTM_TRACE_API ("Security Manager: BTM_SetEncryption Handle:%d State:%d Flags:0x%x Required:0x%x\n",
- p_dev_rec->hci_handle, p_dev_rec->sec_state, p_dev_rec->sec_flags,
- p_dev_rec->security_required);
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (transport == BT_TRANSPORT_LE) {
- tACL_CONN *p = btm_bda_to_acl(bd_addr, transport);
- if (p) {
- rc = btm_ble_set_encryption(bd_addr, p_ref_data, p->link_role);
- } else {
- rc = BTM_WRONG_MODE;
- BTM_TRACE_WARNING("%s: cannot call btm_ble_set_encryption, p is NULL\n", __FUNCTION__);
- }
- } else
- #endif
- {
- rc = btm_sec_execute_procedure (p_dev_rec);
- }
- if (rc != BTM_CMD_STARTED && rc != BTM_BUSY) {
- if (p_callback) {
- p_dev_rec->p_callback = NULL;
- (*p_callback) (bd_addr, transport, p_dev_rec->p_ref_data, rc);
- }
- }
- return (rc);
- }
- /*******************************************************************************
- * disconnect the ACL link, if it's not done yet.
- *******************************************************************************/
- static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason, UINT16 conn_handle)
- {
- UINT8 old_state = p_dev_rec->sec_state;
- tBTM_STATUS status = BTM_CMD_STARTED;
- BTM_TRACE_EVENT ("btm_sec_send_hci_disconnect: handle:0x%x, reason=0x%x\n",
- conn_handle, reason);
- /* send HCI_Disconnect on a transport only once */
- switch (old_state) {
- case BTM_SEC_STATE_DISCONNECTING:
- if (conn_handle == p_dev_rec->hci_handle) {
- return status;
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING_BOTH;
- break;
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- case BTM_SEC_STATE_DISCONNECTING_BLE:
- if (conn_handle == p_dev_rec->ble_hci_handle) {
- return status;
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING_BOTH;
- break;
- case BTM_SEC_STATE_DISCONNECTING_BOTH:
- return status;
- #endif
- default:
- p_dev_rec->sec_state = (conn_handle == p_dev_rec->hci_handle) ?
- BTM_SEC_STATE_DISCONNECTING : BTM_SEC_STATE_DISCONNECTING_BLE;
- break;
- }
- /* If a role switch is in progress, delay the HCI Disconnect to avoid controller problem */
- if (p_dev_rec->rs_disc_pending == BTM_SEC_RS_PENDING && p_dev_rec->hci_handle == conn_handle) {
- BTM_TRACE_DEBUG("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect\n");
- p_dev_rec->rs_disc_pending = BTM_SEC_DISC_PENDING;
- status = BTM_SUCCESS;
- }
- /* Tear down the HCI link */
- else if (!btsnd_hcic_disconnect (conn_handle, reason)) {
- /* could not send disconnect. restore old state */
- p_dev_rec->sec_state = old_state;
- status = BTM_NO_RESOURCES;
- }
- return status;
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_ConfirmReqReply
- **
- ** Description This function is called to confirm the numeric value for
- ** Simple Pairing in response to BTM_SP_CFM_REQ_EVT
- **
- ** Parameters: res - result of the operation BTM_SUCCESS if success
- ** bd_addr - Address of the peer device
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void BTM_ConfirmReqReply(tBTM_STATUS res, BD_ADDR bd_addr)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("BTM_ConfirmReqReply() State: %s Res: %u",
- btm_pair_state_descr(btm_cb.pairing_state), res);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- /* If timeout already expired or has been canceled, ignore the reply */
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_WAIT_NUMERIC_CONFIRM)
- || (memcmp (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN) != 0) ) {
- return;
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- if ( (res == BTM_SUCCESS) || (res == BTM_SUCCESS_NO_SECURITY) ) {
- btm_cb.acl_disc_reason = HCI_SUCCESS;
- if (res == BTM_SUCCESS) {
- if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL) {
- p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
- }
- p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
- }
- btsnd_hcic_user_conf_reply (bd_addr, TRUE);
- } else {
- /* Report authentication failed event from state BTM_PAIR_STATE_WAIT_AUTH_COMPLETE */
- btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
- btsnd_hcic_user_conf_reply (bd_addr, FALSE);
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_PasskeyReqReply
- **
- ** Description This function is called to provide the passkey for
- ** Simple Pairing in response to BTM_SP_KEY_REQ_EVT
- **
- ** Parameters: res - result of the operation BTM_SUCCESS if success
- ** bd_addr - Address of the peer device
- ** passkey - numeric value in the range of
- ** BTM_MIN_PASSKEY_VAL(0) - BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
- **
- *******************************************************************************/
- #if (BT_SSP_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
- void BTM_PasskeyReqReply(tBTM_STATUS res, BD_ADDR bd_addr, UINT32 passkey)
- {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_API ("BTM_PasskeyReqReply: State: %s res:%d\n",
- btm_pair_state_descr(btm_cb.pairing_state), res);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- if ( (btm_cb.pairing_state == BTM_PAIR_STATE_IDLE)
- || (memcmp (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN) != 0) ) {
- return;
- }
- /* If timeout already expired or has been canceled, ignore the reply */
- if ( (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_AUTH_COMPLETE) && (res != BTM_SUCCESS) ) {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
- if (p_dev_rec != NULL) {
- btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
- if (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) {
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
- } else {
- BTM_SecBondCancel(bd_addr);
- }
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_AUTHED | BTM_SEC_LINK_KEY_KNOWN);
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- return;
- }
- } else if (btm_cb.pairing_state != BTM_PAIR_STATE_KEY_ENTRY) {
- return;
- }
- if (passkey > BTM_MAX_PASSKEY_VAL) {
- res = BTM_ILLEGAL_VALUE;
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- if (res != BTM_SUCCESS) {
- /* use BTM_PAIR_STATE_WAIT_AUTH_COMPLETE to report authentication failed event */
- btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
- btsnd_hcic_user_passkey_neg_reply (bd_addr);
- } else {
- btm_cb.acl_disc_reason = HCI_SUCCESS;
- btsnd_hcic_user_passkey_reply (bd_addr, passkey);
- }
- }
- #endif ///BT_SSP_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_SendKeypressNotif
- **
- ** Description This function is used during the passkey entry model
- ** by a device with KeyboardOnly IO capabilities
- ** (very likely to be a HID Device).
- ** It is called by a HID Device to inform the remote device when
- ** a key has been entered or erased.
- **
- ** Parameters: bd_addr - Address of the peer device
- ** type - notification type
- **
- *******************************************************************************/
- #if (BT_SSP_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
- void BTM_SendKeypressNotif(BD_ADDR bd_addr, tBTM_SP_KEY_TYPE type)
- {
- /* This API only make sense between PASSKEY_REQ and SP complete */
- if (btm_cb.pairing_state == BTM_PAIR_STATE_KEY_ENTRY) {
- btsnd_hcic_send_keypress_notif (bd_addr, type);
- }
- }
- #endif ///BT_SSP_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- #if BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_IoCapRsp
- **
- ** Description This function is called in response to BTM_SP_IO_REQ_EVT
- ** When the event data io_req.oob_data is set to BTM_OOB_UNKNOWN
- ** by the tBTM_SP_CALLBACK implementation, this function is
- ** called to provide the actual response
- **
- ** Parameters: bd_addr - Address of the peer device
- ** io_cap - The IO capability of local device.
- ** oob - BTM_OOB_NONE or BTM_OOB_PRESENT.
- ** auth_req- MITM protection required or not.
- **
- *******************************************************************************/
- void BTM_IoCapRsp(BD_ADDR bd_addr, tBTM_IO_CAP io_cap, tBTM_OOB_DATA oob, tBTM_AUTH_REQ auth_req)
- {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("BTM_IoCapRsp: state: %s oob: %d io_cap: %d\n",
- btm_pair_state_descr(btm_cb.pairing_state), oob, io_cap);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_WAIT_LOCAL_IOCAPS)
- || (memcmp (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN) != 0) ) {
- return;
- }
- if (oob < BTM_OOB_UNKNOWN && io_cap < BTM_IO_CAP_MAX) {
- btm_cb.devcb.loc_auth_req = auth_req;
- btm_cb.devcb.loc_io_caps = io_cap;
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
- auth_req = (BTM_AUTH_DD_BOND | (auth_req & BTM_AUTH_YN_BIT));
- }
- btsnd_hcic_io_cap_req_reply (bd_addr, io_cap, oob, auth_req);
- }
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadLocalOobData
- **
- ** Description This function is called to read the local OOB data from
- ** LM
- **
- *******************************************************************************/
- tBTM_STATUS BTM_ReadLocalOobData(void)
- {
- tBTM_STATUS status = BTM_SUCCESS;
- if (btsnd_hcic_read_local_oob_data() == FALSE) {
- status = BTM_NO_RESOURCES;
- }
- return status;
- }
- /*******************************************************************************
- **
- ** Function BTM_RemoteOobDataReply
- **
- ** Description This function is called to provide the remote OOB data for
- ** Simple Pairing in response to BTM_SP_RMT_OOB_EVT
- **
- ** Parameters: bd_addr - Address of the peer device
- ** c - simple pairing Hash C.
- ** r - simple pairing Randomizer C.
- **
- *******************************************************************************/
- void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r)
- {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("%s() - State: %s res: %d\n", __func__,
- btm_pair_state_descr(btm_cb.pairing_state), res);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- /* If timeout already expired or has been canceled, ignore the reply */
- if (btm_cb.pairing_state != BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP) {
- return;
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- if (res != BTM_SUCCESS) {
- /* use BTM_PAIR_STATE_WAIT_AUTH_COMPLETE to report authentication failed event */
- btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
- btsnd_hcic_rem_oob_neg_reply (bd_addr);
- } else {
- btm_cb.acl_disc_reason = HCI_SUCCESS;
- btsnd_hcic_rem_oob_reply (bd_addr, c, r);
- }
- }
- /*******************************************************************************
- **
- ** Function BTM_BuildOobData
- **
- ** Description This function is called to build the OOB data payload to
- ** be sent over OOB (non-Bluetooth) link
- **
- ** Parameters: p_data - the location for OOB data
- ** max_len - p_data size.
- ** c - simple pairing Hash C.
- ** r - simple pairing Randomizer C.
- ** name_len- 0, local device name would not be included.
- ** otherwise, the local device name is included for
- ** up to this specified length
- **
- ** Returns Number of bytes in p_data.
- **
- *******************************************************************************/
- UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c,
- BT_OCTET16 r, UINT8 name_len)
- {
- UINT8 *p = p_data;
- UINT16 len = 0;
- #if BTM_MAX_LOC_BD_NAME_LEN > 0
- UINT16 name_size;
- UINT8 name_type = BTM_EIR_SHORTENED_LOCAL_NAME_TYPE;
- #endif
- if (p_data && max_len >= BTM_OOB_MANDATORY_SIZE) {
- /* add mandatory part */
- UINT16_TO_STREAM(p, len);
- BDADDR_TO_STREAM(p, controller_get_interface()->get_address()->address);
- len = BTM_OOB_MANDATORY_SIZE;
- max_len -= len;
- /* now optional part */
- /* add Hash C */
- UINT16 delta = BTM_OOB_HASH_C_SIZE + 2;
- if (max_len >= delta) {
- *p++ = BTM_OOB_HASH_C_SIZE + 1;
- *p++ = BTM_EIR_OOB_SSP_HASH_C_TYPE;
- ARRAY_TO_STREAM(p, c, BTM_OOB_HASH_C_SIZE);
- len += delta;
- max_len -= delta;
- }
- /* add Rand R */
- delta = BTM_OOB_RAND_R_SIZE + 2;
- if (max_len >= delta) {
- *p++ = BTM_OOB_RAND_R_SIZE + 1;
- *p++ = BTM_EIR_OOB_SSP_RAND_R_TYPE;
- ARRAY_TO_STREAM(p, r, BTM_OOB_RAND_R_SIZE);
- len += delta;
- max_len -= delta;
- }
- /* add class of device */
- delta = BTM_OOB_COD_SIZE + 2;
- if (max_len >= delta) {
- *p++ = BTM_OOB_COD_SIZE + 1;
- *p++ = BTM_EIR_OOB_COD_TYPE;
- DEVCLASS_TO_STREAM(p, btm_cb.devcb.dev_class);
- len += delta;
- max_len -= delta;
- }
- #if BTM_MAX_LOC_BD_NAME_LEN > 0
- name_size = name_len;
- if (name_size > strlen(btm_cb.cfg.bd_name)) {
- name_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE;
- name_size = (UINT16)strlen(btm_cb.cfg.bd_name);
- }
- delta = name_size + 2;
- if (max_len >= delta) {
- *p++ = name_size + 1;
- *p++ = name_type;
- ARRAY_TO_STREAM (p, btm_cb.cfg.bd_name, name_size);
- len += delta;
- max_len -= delta;
- }
- #endif
- /* update len */
- p = p_data;
- UINT16_TO_STREAM(p, len);
- }
- return len;
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadOobData
- **
- ** Description This function is called to parse the OOB data payload
- ** received over OOB (non-Bluetooth) link
- **
- ** Parameters: p_data - the location for OOB data
- ** eir_tag - The associated EIR tag to read the data.
- ** *p_len(output) - the length of the data with the given tag.
- **
- ** Returns the beginning of the data with the given tag.
- ** NULL, if the tag is not found.
- **
- *******************************************************************************/
- UINT8 *BTM_ReadOobData(UINT8 *p_data, UINT8 eir_tag, UINT8 *p_len)
- {
- UINT8 *p = p_data;
- UINT16 max_len;
- UINT8 len, type;
- UINT8 *p_ret = NULL;
- UINT8 ret_len = 0;
- if (p_data) {
- STREAM_TO_UINT16(max_len, p);
- if (max_len >= BTM_OOB_MANDATORY_SIZE) {
- if (BTM_EIR_OOB_BD_ADDR_TYPE == eir_tag) {
- p_ret = p; /* the location for bd_addr */
- ret_len = BTM_OOB_BD_ADDR_SIZE;
- } else {
- p += BD_ADDR_LEN;
- max_len -= BTM_OOB_MANDATORY_SIZE;
- /* now the optional data in EIR format */
- while (max_len > 0) {
- len = *p++; /* tag data len + 1 */
- type = *p++;
- if (eir_tag == type) {
- p_ret = p;
- ret_len = len - 1;
- break;
- }
- /* the data size of this tag is len + 1 (tag data len + 2) */
- if (max_len > len) {
- max_len -= len;
- max_len--;
- len--;
- p += len;
- } else {
- max_len = 0;
- }
- }
- }
- }
- }
- if (p_len) {
- *p_len = ret_len;
- }
- return p_ret;
- }
- #endif ///BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- #if (CLASSIC_BT_INCLUDED == TRUE)
- /*******************************************************************************
- **
- ** Function BTM_BothEndsSupportSecureConnections
- **
- ** Description This function is called to check if both the local device and the peer device
- ** specified by bd_addr support BR/EDR Secure Connections.
- **
- ** Parameters: bd_addr - address of the peer
- **
- ** Returns TRUE if BR/EDR Secure Connections are supported by both local
- ** and the remote device.
- ** else FALSE.
- **
- *******************************************************************************/
- BOOLEAN BTM_BothEndsSupportSecureConnections(BD_ADDR bd_addr)
- {
- return ((controller_get_interface()->supports_secure_connections()) &&
- (BTM_PeerSupportsSecureConnections(bd_addr)));
- }
- /*******************************************************************************
- **
- ** Function BTM_PeerSupportsSecureConnections
- **
- ** Description This function is called to check if the peer supports
- ** BR/EDR Secure Connections.
- **
- ** Parameters: bd_addr - address of the peer
- **
- ** Returns TRUE if BR/EDR Secure Connections are supported by the peer,
- ** else FALSE.
- **
- *******************************************************************************/
- BOOLEAN BTM_PeerSupportsSecureConnections(BD_ADDR bd_addr)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- if ((p_dev_rec = btm_find_dev(bd_addr)) == NULL) {
- BTM_TRACE_WARNING("%s: unknown BDA: %08x%04x\n", __FUNCTION__,
- (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
- (bd_addr[4] << 8) + bd_addr[5]);
- return FALSE;
- }
- return (p_dev_rec->remote_supports_secure_connections);
- }
- /*******************************************************************************
- **
- ** Function BTM_SetOutService
- **
- ** Description This function is called to set the service for
- ** outgoing connections.
- **
- ** If the profile/application calls BTM_SetSecurityLevel
- ** before initiating a connection, this function does not
- ** need to be called.
- **
- ** Returns void
- **
- *******************************************************************************/
- void BTM_SetOutService(BD_ADDR bd_addr, UINT8 service_id, UINT32 mx_chan_id)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
- btm_cb.p_out_serv = p_serv_rec;
- p_dev_rec = btm_find_dev (bd_addr);
- for (int i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++) {
- if ((p_serv_rec->security_flags & BTM_SEC_IN_USE)
- && (p_serv_rec->service_id == service_id)
- && (p_serv_rec->orig_mx_chan_id == mx_chan_id)) {
- BTM_TRACE_API("BTM_SetOutService p_out_serv id %d, psm 0x%04x, proto_id %d, chan_id %d\n",
- p_serv_rec->service_id, p_serv_rec->psm, p_serv_rec->mx_proto_id, p_serv_rec->orig_mx_chan_id);
- btm_cb.p_out_serv = p_serv_rec;
- if (p_dev_rec) {
- p_dev_rec->p_cur_service = p_serv_rec;
- }
- break;
- }
- }
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- /************************************************************************
- ** I N T E R N A L F U N C T I O N S
- *************************************************************************/
- /*******************************************************************************
- **
- ** Function btm_sec_is_upgrade_possible
- **
- ** Description This function returns TRUE if the existing link key
- ** can be upgraded or if the link key does not exist.
- **
- ** Returns BOOLEAN
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
- {
- UINT16 mtm_check = is_originator ? BTM_SEC_OUT_MITM : BTM_SEC_IN_MITM;
- BOOLEAN is_possible = TRUE;
- if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) {
- is_possible = FALSE;
- if (p_dev_rec->p_cur_service) {
- BTM_TRACE_DEBUG ("%s() id: %d, link_key_typet: %d, rmt_io_caps: %d, chk flags: 0x%x, flags: 0x%x\n",
- __func__, p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type,
- p_dev_rec->rmt_io_caps, mtm_check, p_dev_rec->p_cur_service->security_flags);
- } else {
- BTM_TRACE_DEBUG ("%s() link_key_typet: %d, rmt_io_caps: %d, chk flags: 0x%x\n",
- __func__, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps, mtm_check);
- }
- /* Already have a link key to the connected peer. Is the link key secure enough?
- ** Is a link key upgrade even possible?
- */
- if ((p_dev_rec->security_required & mtm_check) /* needs MITM */
- && ((p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB) ||
- (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256))
- /* has unauthenticated
- link key */
- && (p_dev_rec->rmt_io_caps < BTM_IO_CAP_MAX) /* a valid peer IO cap */
- && (btm_sec_io_map[p_dev_rec->rmt_io_caps][btm_cb.devcb.loc_io_caps]))
- /* authenticated
- link key is possible */
- {
- /* upgrade is possible: check if the application wants the upgrade.
- * If the application is configured to use a global MITM flag,
- * it probably would not want to upgrade the link key based on the security level database */
- is_possible = TRUE;
- }
- }
- BTM_TRACE_DEBUG ("%s() is_possible: %d sec_flags: 0x%x\n", __func__, is_possible, p_dev_rec->sec_flags);
- return is_possible;
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_check_upgrade
- **
- ** Description This function is called to check if the existing link key
- ** needs to be upgraded.
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
- {
- BTM_TRACE_DEBUG ("%s()\n", __func__);
- /* Only check if link key already exists */
- if (!(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) {
- return;
- }
- if (btm_sec_is_upgrade_possible (p_dev_rec, is_originator) == TRUE) {
- BTM_TRACE_DEBUG ("need upgrade!! sec_flags:0x%x\n", p_dev_rec->sec_flags);
- /* upgrade is possible: check if the application wants the upgrade.
- * If the application is configured to use a global MITM flag,
- * it probably would not want to upgrade the link key based on the security level database */
- tBTM_SP_UPGRADE evt_data;
- memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- evt_data.upgrade = TRUE;
- if (btm_cb.api.p_sp_callback) {
- (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
- }
- BTM_TRACE_DEBUG ("evt_data.upgrade:0x%x\n", evt_data.upgrade);
- if (evt_data.upgrade) {
- /* if the application confirms the upgrade, set the upgrade bit */
- p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
- /* Clear the link key known to go through authentication/pairing again */
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
- p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED;
- BTM_TRACE_DEBUG ("sec_flags:0x%x\n", p_dev_rec->sec_flags);
- }
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_l2cap_access_req
- **
- ** Description This function is called by the L2CAP to grant permission to
- ** establish L2CAP connection to or from the peer device.
- **
- ** Parameters: bd_addr - Address of the peer device
- ** psm - L2CAP PSM
- ** is_originator - TRUE if protocol above L2CAP originates
- ** connection
- ** p_callback - Pointer to callback function called if
- ** this function returns PENDING after required
- ** procedures are complete. MUST NOT BE NULL.
- **
- ** Returns tBTM_STATUS
- **
- *******************************************************************************/
- tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle,
- CONNECTION_TYPE conn_type,
- tBTM_SEC_CALLBACK *p_callback,
- void *p_ref_data)
- {
- #if (SMP_INCLUDED == TRUE)
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_SEC_SERV_REC *p_serv_rec;
- UINT16 security_required;
- UINT16 old_security_required;
- BOOLEAN old_is_originator;
- tBTM_STATUS rc = BTM_SUCCESS;
- BOOLEAN chk_acp_auth_done = FALSE;
- BOOLEAN is_originator;
- BOOLEAN transport = FALSE; /* should check PSM range in LE connection oriented L2CAP connection */
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if (conn_type & CONNECTION_TYPE_ORIG_MASK) {
- is_originator = TRUE;
- } else {
- is_originator = FALSE;
- }
- BTM_TRACE_DEBUG ("%s() conn_type: 0x%x, %p\n", __func__, conn_type, p_ref_data);
- #else
- is_originator = conn_type;
- BTM_TRACE_DEBUG ("%s() is_originator:%d, %p\n", __func__, is_originator, p_ref_data);
- #endif
- /* Find or get oldest record */
- p_dev_rec = btm_find_or_alloc_dev (bd_addr);
- p_dev_rec->hci_handle = handle;
- /* Find the service record for the PSM */
- p_serv_rec = btm_sec_find_first_serv (conn_type, psm);
- /* If there is no application registered with this PSM do not allow connection */
- if (!p_serv_rec) {
- BTM_TRACE_WARNING ("%s() PSM: %d no application registerd\n", __func__, psm);
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_MODE_UNSUPPORTED);
- return (BTM_MODE_UNSUPPORTED);
- }
- /* Services level0 by default have no security */
- if ((btm_sec_is_serv_level0(psm)) && (!btm_cb.devcb.secure_connections_only)) {
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_SUCCESS_NO_SECURITY);
- return (BTM_SUCCESS);
- }
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if ( conn_type & CONNECTION_TYPE_CONNLESS_MASK ) {
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- security_required = btm_sec_set_serv_level4_flags (p_serv_rec->ucd_security_flags,
- is_originator);
- } else {
- security_required = p_serv_rec->ucd_security_flags;
- }
- rc = BTM_CMD_STARTED;
- if (is_originator) {
- if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_FLAGS) && (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED))) ) {
- rc = BTM_SUCCESS;
- }
- } else {
- if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) && (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED))) ) {
- // Check for 16 digits (or MITM)
- if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) ||
- (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == BTM_SEC_IN_MIN_16_DIGIT_PIN) &&
- btm_dev_16_digit_authenticated(p_dev_rec))) {
- rc = BTM_SUCCESS;
- }
- }
- }
- if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- rc = BTM_CMD_STARTED;
- }
- if (rc == BTM_SUCCESS) {
- if (p_callback) {
- (*p_callback) (bd_addr, transport, (void *)p_ref_data, BTM_SUCCESS);
- }
- return (BTM_SUCCESS);
- }
- } else
- #endif
- {
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- security_required = btm_sec_set_serv_level4_flags (p_serv_rec->security_flags,
- is_originator);
- } else {
- security_required = p_serv_rec->security_flags;
- }
- }
- BTM_TRACE_DEBUG("%s: security_required 0x%04x, is_originator 0x%02x, psm 0x%04x\n",
- __FUNCTION__, security_required, is_originator, psm);
- if ((!is_originator) && (security_required & BTM_SEC_MODE4_LEVEL4)) {
- BOOLEAN local_supports_sc = controller_get_interface()->supports_secure_connections();
- /* acceptor receives L2CAP Channel Connect Request for Secure Connections Only service */
- if (!(local_supports_sc) || !(p_dev_rec->remote_supports_secure_connections)) {
- BTM_TRACE_DEBUG("%s: SC only service, local_support_for_sc %d\n"
- "rmt_support_for_sc : %d -> fail pairing\n", __FUNCTION__,
- local_supports_sc,
- p_dev_rec->remote_supports_secure_connections);
- if (p_callback) {
- (*p_callback) (bd_addr, transport, (void *)p_ref_data,
- BTM_MODE4_LEVEL4_NOT_SUPPORTED);
- }
- return (BTM_MODE4_LEVEL4_NOT_SUPPORTED);
- }
- }
- /* there are some devices (moto KRZR) which connects to several services at the same time */
- /* we will process one after another */
- if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) ) {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("%s() - busy - PSM:%d delayed state: %s mode:%d, sm4:0x%x\n", __func__,
- psm, btm_pair_state_descr(btm_cb.pairing_state), btm_cb.security_mode, p_dev_rec->sm4);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- BTM_TRACE_EVENT ("security_flags:x%x, sec_flags:x%x\n", security_required, p_dev_rec->sec_flags);
- rc = BTM_CMD_STARTED;
- if ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED ||
- btm_cb.security_mode == BTM_SEC_MODE_NONE ||
- btm_cb.security_mode == BTM_SEC_MODE_SERVICE ||
- btm_cb.security_mode == BTM_SEC_MODE_LINK) ||
- (BTM_SM4_KNOWN == p_dev_rec->sm4) || (BTM_SEC_IS_SM4(p_dev_rec->sm4) &&
- (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))) {
- /* legacy mode - local is legacy or local is lisbon/peer is legacy
- * or SM4 with no possibility of link key upgrade */
- if (is_originator) {
- if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && btm_dev_encrypted(p_dev_rec))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_FLAGS) && btm_dev_authorized(p_dev_rec) && btm_dev_encrypted(p_dev_rec))) ) {
- rc = BTM_SUCCESS;
- }
- } else {
- if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
- (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec)) ||
- (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && btm_dev_encrypted(p_dev_rec)) ||
- (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHORIZE) && (btm_dev_authorized(p_dev_rec) || btm_serv_trusted(p_dev_rec, p_serv_rec))) ||
- (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_AUTHORIZE)) && ((btm_dev_authorized(p_dev_rec) || btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_authenticated(p_dev_rec))) ||
- (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHORIZE)) && ((btm_dev_authorized(p_dev_rec) || btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_encrypted(p_dev_rec))) ||
- (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) && btm_dev_encrypted(p_dev_rec) && (btm_dev_authorized(p_dev_rec) || btm_serv_trusted(p_dev_rec, p_serv_rec)))) {
- // Check for 16 digits (or MITM)
- if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) ||
- (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == BTM_SEC_IN_MIN_16_DIGIT_PIN) && btm_dev_16_digit_authenticated(p_dev_rec))) {
- rc = BTM_SUCCESS;
- }
- }
- }
- if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- rc = BTM_CMD_STARTED;
- }
- if (rc == BTM_SUCCESS) {
- if (p_callback) {
- (*p_callback) (bd_addr, transport, (void *)p_ref_data, BTM_SUCCESS);
- }
- return (BTM_SUCCESS);
- }
- }
- btm_cb.sec_req_pending = TRUE;
- return (BTM_CMD_STARTED);
- }
- /* Save pointer to service record */
- p_dev_rec->p_cur_service = p_serv_rec;
- /* Modify security_required in btm_sec_l2cap_access_req for Lisbon */
- if (btm_cb.security_mode == BTM_SEC_MODE_SP ||
- btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
- btm_cb.security_mode == BTM_SEC_MODE_SC) {
- if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) {
- if (is_originator) {
- /* SM4 to SM4 -> always authenticate & encrypt */
- security_required |= (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT);
- } else { /* acceptor */
- /* SM4 to SM4: the acceptor needs to make sure the authentication is already done */
- chk_acp_auth_done = TRUE;
- /* SM4 to SM4 -> always authenticate & encrypt */
- security_required |= (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT);
- }
- } else if (!(BTM_SM4_KNOWN & p_dev_rec->sm4)) {
- /* the remote features are not known yet */
- BTM_TRACE_ERROR("%s: (%s) remote features unknown!!sec_flags:0x%02x\n", __FUNCTION__,
- (is_originator) ? "initiator" : "acceptor", p_dev_rec->sec_flags);
- p_dev_rec->sm4 |= BTM_SM4_REQ_PEND;
- return (BTM_CMD_STARTED);
- }
- }
- BTM_TRACE_DEBUG ("%s() sm4:0x%x, sec_flags:0x%x, security_required:0x%x chk:%d\n", __func__,
- p_dev_rec->sm4, p_dev_rec->sec_flags, security_required, chk_acp_auth_done);
- old_security_required = p_dev_rec->security_required;
- old_is_originator = p_dev_rec->is_originator;
- p_dev_rec->security_required = security_required;
- p_dev_rec->p_ref_data = p_ref_data;
- p_dev_rec->is_originator = is_originator;
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if ( conn_type & CONNECTION_TYPE_CONNLESS_MASK ) {
- p_dev_rec->is_ucd = TRUE;
- } else {
- p_dev_rec->is_ucd = FALSE;
- }
- #endif
- /* If there are multiple service records used through the same PSM */
- /* leave security decision for the multiplexor on the top */
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if (((btm_sec_find_next_serv (p_serv_rec)) != NULL)
- && (!( conn_type & CONNECTION_TYPE_CONNLESS_MASK ))) /* if not UCD */
- #else
- if ((btm_sec_find_next_serv (p_serv_rec)) != NULL)
- #endif
- {
- BTM_TRACE_DEBUG ("no next_serv sm4:0x%x, chk:%d\n", p_dev_rec->sm4, chk_acp_auth_done);
- if (!BTM_SEC_IS_SM4(p_dev_rec->sm4)) {
- BTM_TRACE_EVENT ("Security Manager: l2cap_access_req PSM:%d postponed for multiplexer\n", psm);
- /* pre-Lisbon: restore the old settings */
- p_dev_rec->security_required = old_security_required;
- p_dev_rec->is_originator = old_is_originator;
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_SUCCESS);
- return (BTM_SUCCESS);
- }
- }
- /* if the originator is using dynamic PSM in legacy mode, do not start any security process now
- * The layer above L2CAP needs to carry out the security requirement after L2CAP connect
- * response is received */
- if (is_originator &&
- ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED ||
- btm_cb.security_mode == BTM_SEC_MODE_NONE ||
- btm_cb.security_mode == BTM_SEC_MODE_SERVICE ||
- btm_cb.security_mode == BTM_SEC_MODE_LINK) ||
- !BTM_SEC_IS_SM4(p_dev_rec->sm4)) && (psm >= 0x1001)) {
- BTM_TRACE_EVENT ("dynamic PSM:0x%x in legacy mode - postponed for upper layer\n", psm);
- /* restore the old settings */
- p_dev_rec->security_required = old_security_required;
- p_dev_rec->is_originator = old_is_originator;
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_SUCCESS);
- return (BTM_SUCCESS);
- }
- if (chk_acp_auth_done) {
- BTM_TRACE_DEBUG ("(SM4 to SM4) btm_sec_l2cap_access_req rspd. authenticated: x%x, enc: x%x\n",
- (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED), (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED));
- /* SM4, but we do not know for sure which level of security we need.
- * as long as we have a link key, it's OK */
- if ((0 == (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))
- || (0 == (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) {
- rc = BTM_DELAY_CHECK;
- /*
- 2046 may report HCI_Encryption_Change and L2C Connection Request out of sequence
- because of data path issues. Delay this disconnect a little bit
- */
- BTM_TRACE_API("%s peer should have initiated security process by now (SM4 to SM4)\n", __func__);
- p_dev_rec->p_callback = p_callback;
- p_dev_rec->sec_state = BTM_SEC_STATE_DELAY_FOR_ENC;
- (*p_callback) (bd_addr, transport, p_ref_data, rc);
- return BTM_SUCCESS;
- }
- }
- p_dev_rec->p_callback = p_callback;
- if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
- || p_dev_rec->last_author_service_id != p_dev_rec->p_cur_service->service_id) {
- /* Although authentication and encryption are per connection
- ** authorization is per access request. For example when serial connection
- ** is up and authorized and client requests to read file (access to other
- ** scn), we need to request user's permission again.
- */
- p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED;
- }
- if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) {
- if ((p_dev_rec->security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- /* BTM_LKEY_TYPE_AUTH_COMB_P_256 is the only acceptable key in this case */
- if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) != 0) {
- p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
- }
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED |
- BTM_SEC_AUTHENTICATED);
- BTM_TRACE_DEBUG ("%s: sec_flags:0x%x", __FUNCTION__, p_dev_rec->sec_flags);
- } else {
- /* If we already have a link key to the connected peer, is it secure enough? */
- btm_sec_check_upgrade(p_dev_rec, is_originator);
- }
- }
- BTM_TRACE_EVENT ("%s() PSM:%d Handle:%d State:%d Flags: 0x%x Required: 0x%x Service ID:%d\n",
- __func__, psm, handle, p_dev_rec->sec_state, p_dev_rec->sec_flags,
- p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
- if ((rc = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED) {
- p_dev_rec->p_callback = NULL;
- (*p_callback) (bd_addr, transport, p_dev_rec->p_ref_data, (UINT8)rc);
- }
- return (rc);
- #else
- return BTM_MODE_UNSUPPORTED;
- #endif ///SMP_INCLUDED == TRUE
- }
- /*******************************************************************************
- **
- ** Function btm_sec_mx_access_request
- **
- ** Description This function is called by all Multiplexing Protocols during
- ** establishing connection to or from peer device to grant
- ** permission to establish application connection.
- **
- ** Parameters: bd_addr - Address of the peer device
- ** psm - L2CAP PSM
- ** is_originator - TRUE if protocol above L2CAP originates
- ** connection
- ** mx_proto_id - protocol ID of the multiplexer
- ** mx_chan_id - multiplexer channel to reach application
- ** p_callback - Pointer to callback function called if
- ** this function returns PENDING after required
- ** procedures are completed
- ** p_ref_data - Pointer to any reference data needed by the
- ** the callback function.
- **
- ** Returns BTM_CMD_STARTED
- **
- *******************************************************************************/
- tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator,
- UINT32 mx_proto_id, UINT32 mx_chan_id,
- tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
- {
- #if (SMP_INCLUDED == TRUE)
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_SEC_SERV_REC *p_serv_rec;
- tBTM_STATUS rc;
- UINT16 security_required;
- BOOLEAN transport = FALSE;/* should check PSM range in LE connection oriented L2CAP connection */
- BTM_TRACE_DEBUG ("%s() is_originator: %d\n", __func__, is_originator);
- /* Find or get oldest record */
- p_dev_rec = btm_find_or_alloc_dev (bd_addr);
- /* Find the service record for the PSM */
- p_serv_rec = btm_sec_find_mx_serv (is_originator, psm, mx_proto_id, mx_chan_id);
- /* If there is no application registered with this PSM do not allow connection */
- if (!p_serv_rec) {
- if (p_callback) {
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_MODE_UNSUPPORTED);
- }
- BTM_TRACE_ERROR ("Security Manager: MX service not found PSM:%d Proto:%d SCN:%d\n",
- psm, mx_proto_id, mx_chan_id);
- return BTM_NO_RESOURCES;
- }
- if ((btm_cb.security_mode == BTM_SEC_MODE_SC) && (!btm_sec_is_serv_level0(psm))) {
- security_required = btm_sec_set_serv_level4_flags (p_serv_rec->security_flags,
- is_originator);
- } else {
- security_required = p_serv_rec->security_flags;
- }
- /* there are some devices (moto phone) which connects to several services at the same time */
- /* we will process one after another */
- if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) ) {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("%s() service PSM:%d Proto:%d SCN:%d delayed state: %s\n", __func__,
- psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- rc = BTM_CMD_STARTED;
- if ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED ||
- btm_cb.security_mode == BTM_SEC_MODE_NONE ||
- btm_cb.security_mode == BTM_SEC_MODE_SERVICE ||
- btm_cb.security_mode == BTM_SEC_MODE_LINK) ||
- (BTM_SM4_KNOWN == p_dev_rec->sm4) || (BTM_SEC_IS_SM4(p_dev_rec->sm4) &&
- (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))) {
- /* legacy mode - local is legacy or local is lisbon/peer is legacy
- * or SM4 with no possibility of link key upgrade */
- if (is_originator) {
- if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && btm_dev_encrypted(p_dev_rec)))
- ) {
- rc = BTM_SUCCESS;
- }
- } else {
- if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && btm_dev_authenticated(p_dev_rec))) ||
- (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHORIZE) && (btm_dev_authorized(p_dev_rec) || btm_serv_trusted(p_dev_rec, p_serv_rec))) ||
- (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_AUTHENTICATE)) && ((btm_dev_authorized(p_dev_rec) || btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_authenticated(p_dev_rec))) ||
- (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT)) && ((btm_dev_authorized(p_dev_rec) || btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_encrypted(p_dev_rec))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && btm_dev_encrypted(p_dev_rec)))
- ) {
- // Check for 16 digits (or MITM)
- if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) ||
- (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == BTM_SEC_IN_MIN_16_DIGIT_PIN) && btm_dev_16_digit_authenticated(p_dev_rec))) {
- rc = BTM_SUCCESS;
- }
- }
- }
- if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- rc = BTM_CMD_STARTED;
- }
- }
- if (rc == BTM_SUCCESS) {
- BTM_TRACE_EVENT("%s: allow to bypass, checking authorization\n", __FUNCTION__);
- /* the security in BTM_SEC_IN_FLAGS is fullfilled so far, check the requirements in */
- /* btm_sec_execute_procedure */
- if ((is_originator && (p_serv_rec->security_flags & BTM_SEC_OUT_AUTHORIZE)) ||
- (!is_originator && (p_serv_rec->security_flags & BTM_SEC_IN_AUTHORIZE))) {
- BTM_TRACE_EVENT("%s: still need authorization\n", __FUNCTION__);
- rc = BTM_CMD_STARTED;
- }
- }
- /* Check whether there is a pending security procedure, if so we should always queue */
- /* the new security request */
- if (p_dev_rec->sec_state != BTM_SEC_STATE_IDLE) {
- BTM_TRACE_EVENT("%s: There is a pending security procedure\n", __FUNCTION__);
- rc = BTM_CMD_STARTED;
- }
- if (rc == BTM_CMD_STARTED) {
- BTM_TRACE_EVENT("%s: call btm_sec_queue_mx_request\n", __FUNCTION__);
- btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id,
- mx_chan_id, p_callback, p_ref_data);
- } else { /* rc == BTM_SUCCESS */
- /* access granted */
- if (p_callback) {
- (*p_callback) (bd_addr, transport, p_ref_data, (UINT8)rc);
- }
- }
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT("%s: return with rc = 0x%02x in delayed state %s\n", __FUNCTION__, rc,
- btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- return rc;
- }
- if ((!is_originator) && ((security_required & BTM_SEC_MODE4_LEVEL4) ||
- (btm_cb.security_mode == BTM_SEC_MODE_SC))) {
- BOOLEAN local_supports_sc = controller_get_interface()->supports_secure_connections();
- /* acceptor receives service connection establishment Request for */
- /* Secure Connections Only service */
- if (!(local_supports_sc) || !(p_dev_rec->remote_supports_secure_connections)) {
- BTM_TRACE_DEBUG("%s: SC only service,local_support_for_sc %d,\n"
- "remote_support_for_sc %d: fail pairing\n", __FUNCTION__,
- local_supports_sc, p_dev_rec->remote_supports_secure_connections);
- if (p_callback) {
- (*p_callback) (bd_addr, transport, (void *)p_ref_data,
- BTM_MODE4_LEVEL4_NOT_SUPPORTED);
- }
- return (BTM_MODE4_LEVEL4_NOT_SUPPORTED);
- }
- }
- p_dev_rec->p_cur_service = p_serv_rec;
- p_dev_rec->security_required = security_required;
- if (btm_cb.security_mode == BTM_SEC_MODE_SP ||
- btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
- btm_cb.security_mode == BTM_SEC_MODE_SC) {
- if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) {
- if ((p_dev_rec->security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- /* BTM_LKEY_TYPE_AUTH_COMB_P_256 is the only acceptable key in this case */
- if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) != 0) {
- p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
- }
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED |
- BTM_SEC_AUTHENTICATED);
- BTM_TRACE_DEBUG("%s: sec_flags:0x%x\n", __FUNCTION__, p_dev_rec->sec_flags);
- } else {
- /* If we already have a link key, check if that link key is good enough */
- btm_sec_check_upgrade(p_dev_rec, is_originator);
- }
- }
- }
- p_dev_rec->is_originator = is_originator;
- p_dev_rec->p_callback = p_callback;
- p_dev_rec->p_ref_data = p_ref_data;
- /* Although authentication and encryption are per connection */
- /* authorization is per access request. For example when serial connection */
- /* is up and authorized and client requests to read file (access to other */
- /* scn, we need to request user's permission again. */
- p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED);
- BTM_TRACE_EVENT ("%s() proto_id:%d chan_id:%d State:%d Flags:0x%x Required:0x%x Service ID:%d\n",
- __func__, mx_proto_id, mx_chan_id, p_dev_rec->sec_state, p_dev_rec->sec_flags,
- p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
- if ((rc = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED) {
- if (p_callback) {
- p_dev_rec->p_callback = NULL;
- (*p_callback) (bd_addr, transport, p_ref_data, (UINT8)rc);
- }
- }
- return rc;
- #else
- return BTM_MODE_UNSUPPORTED;
- #endif ///SMP_INCLUDED == TRUE
- }
- /*******************************************************************************
- **
- ** Function btm_sec_conn_req
- **
- ** Description This function is when the peer device is requesting
- ** connection
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_conn_req (UINT8 *bda, UINT8 *dc)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
- /* Some device may request a connection before we are done with the HCI_Reset sequence */
- if (!controller_get_interface()->get_is_ready()) {
- BTM_TRACE_ERROR ("Security Manager: connect request when device not ready\n");
- btsnd_hcic_reject_conn (bda, HCI_ERR_HOST_REJECT_DEVICE);
- return;
- }
- /* Security guys wants us not to allow connection from not paired devices */
- /* Check if connection is allowed for only paired devices */
- if (btm_cb.connect_only_paired) {
- if (!p_dev_rec || !(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED)) {
- BTM_TRACE_ERROR ("Security Manager: connect request from non-paired device\n");
- btsnd_hcic_reject_conn (bda, HCI_ERR_HOST_REJECT_DEVICE);
- return;
- }
- }
- #if BTM_ALLOW_CONN_IF_NONDISCOVER == FALSE
- /* If non-discoverable, only allow known devices to connect */
- if (btm_cb.btm_inq_vars.discoverable_mode == BTM_NON_DISCOVERABLE) {
- if (!p_dev_rec) {
- BTM_TRACE_ERROR ("Security Manager: connect request from not paired device\n");
- btsnd_hcic_reject_conn (bda, HCI_ERR_HOST_REJECT_DEVICE);
- return;
- }
- }
- #endif
- if ((btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)
- && (!memcmp (btm_cb.pairing_bda, bda, BD_ADDR_LEN))) {
- BTM_TRACE_ERROR ("Security Manager: reject connect request from bonding device\n");
- /* incoming connection from bonding device is rejected */
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_REJECTED_CONNECT;
- btsnd_hcic_reject_conn (bda, HCI_ERR_HOST_REJECT_DEVICE);
- return;
- }
- /* Host is not interested or approved connection. Save BDA and DC and */
- /* pass request to L2CAP */
- memcpy (btm_cb.connecting_bda, bda, BD_ADDR_LEN);
- memcpy (btm_cb.connecting_dc, dc, DEV_CLASS_LEN);
- if (l2c_link_hci_conn_req (bda)) {
- if (!p_dev_rec) {
- /* accept the connection -> allocate a device record */
- p_dev_rec = btm_sec_alloc_dev (bda);
- }
- if (p_dev_rec) {
- p_dev_rec->sm4 |= BTM_SM4_CONN_PEND;
- }
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_bond_cancel_complete
- **
- ** Description This function is called to report bond cancel complete
- ** event.
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_bond_cancel_complete (void)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) ||
- (BTM_PAIR_STATE_WAIT_LOCAL_PIN == btm_cb.pairing_state &&
- BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags) ||
- (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME &&
- BTM_PAIR_FLAGS_WE_CANCEL_DD & btm_cb.pairing_flags)) {
- /* for dedicated bonding in legacy mode, authentication happens at "link level"
- * btm_sec_connected is called with failed status.
- * In theory, the code that handles is_pairing_device/TRUE should clean out security related code.
- * However, this function may clean out the security related flags and btm_sec_connected would not know
- * this function also needs to do proper clean up.
- */
- if ((p_dev_rec = btm_find_dev (btm_cb.pairing_bda)) != NULL) {
- p_dev_rec->security_required = BTM_SEC_NONE;
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- /* Notify application that the cancel succeeded */
- if (btm_cb.api.p_bond_cancel_cmpl_callback) {
- btm_cb.api.p_bond_cancel_cmpl_callback(BTM_SUCCESS);
- }
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_create_conn_cancel_complete
- **
- ** Description This function is called when the command complete message
- ** is received from the HCI for the create connection cancel
- ** command.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_create_conn_cancel_complete (UINT8 *p)
- {
- UINT8 status;
- STREAM_TO_UINT8 (status, p);
- //BTM_TRACE_EVENT ("btm_create_conn_cancel_complete(): in State: %s status:%d\n",
- // btm_pair_state_descr(btm_cb.pairing_state), status);
- /* if the create conn cancel cmd was issued by the bond cancel,
- ** the application needs to be notified that bond cancel succeeded
- */
- switch (status) {
- case HCI_SUCCESS:
- #if (SMP_INCLUDED == TRUE)
- btm_sec_bond_cancel_complete();
- #endif ///SMP_INCLUDED == TRUE
- break;
- case HCI_ERR_CONNECTION_EXISTS:
- case HCI_ERR_NO_CONNECTION:
- default:
- /* Notify application of the error */
- if (btm_cb.api.p_bond_cancel_cmpl_callback) {
- btm_cb.api.p_bond_cancel_cmpl_callback(BTM_ERR_PROCESSING);
- }
- break;
- }
- }
- /*******************************************************************************
- **
- ** Function btm_sec_check_pending_reqs
- **
- ** Description This function is called at the end of the security procedure
- ** to let L2CAP and RFCOMM know to re-submit any pending requests
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_check_pending_reqs (void)
- {
- tBTM_SEC_QUEUE_ENTRY *p_e;
- fixed_queue_t *bq;
- if (btm_cb.pairing_state == BTM_PAIR_STATE_IDLE) {
- /* First, resubmit L2CAP requests */
- if (btm_cb.sec_req_pending) {
- btm_cb.sec_req_pending = FALSE;
- #if (CLASSIC_BT_INCLUDED == TRUE)
- l2cu_resubmit_pending_sec_req (NULL);
- #endif ///SMP_INCLUDED == TRUE
- }
- /* Now, re-submit anything in the mux queue */
- bq = btm_cb.sec_pending_q;
- btm_cb.sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX);
- while ((p_e = (tBTM_SEC_QUEUE_ENTRY *)fixed_queue_dequeue(bq, 0)) != NULL) {
- /* Check that the ACL is still up before starting security procedures */
- if (btm_bda_to_acl(p_e->bd_addr, p_e->transport) != NULL) {
- if (p_e->psm != 0) {
- BTM_TRACE_EVENT("%s PSM:0x%04x Is_Orig:%u mx_proto_id:%u mx_chan_id:%u\n",
- __FUNCTION__, p_e->psm, p_e->is_orig,
- p_e->mx_proto_id, p_e->mx_chan_id);
- btm_sec_mx_access_request (p_e->bd_addr, p_e->psm, p_e->is_orig,
- p_e->mx_proto_id, p_e->mx_chan_id,
- p_e->p_callback, p_e->p_ref_data);
- } else {
- BTM_SetEncryption(p_e->bd_addr, p_e->transport, p_e->p_callback,
- p_e->p_ref_data);
- }
- }
- osi_free (p_e);
- }
- fixed_queue_free(bq, NULL);
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_init
- **
- ** Description This function is on the SEC startup
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_init (UINT8 sec_mode)
- {
- btm_cb.security_mode = sec_mode;
- memset (btm_cb.pairing_bda, 0xff, BD_ADDR_LEN);
- btm_cb.max_collision_delay = BTM_SEC_MAX_COLLISION_DELAY;
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_device_down
- **
- ** Description This function should be called when device is disabled or
- ** turned off
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_device_down (void)
- {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("%s() State: %s\n", __func__, btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_dev_reset
- **
- ** Description This function should be called after device reset
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_dev_reset (void)
- {
- if (controller_get_interface()->supports_simple_pairing()) {
- /* set the default IO capabilities */
- btm_cb.devcb.loc_io_caps = BTM_LOCAL_IO_CAPS;
- /* add mx service to use no security */
- BTM_SetSecurityLevel(FALSE, "RFC_MUX\n", BTM_SEC_SERVICE_RFC_MUX,
- BTM_SEC_NONE, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, 0);
- } else {
- btm_cb.security_mode = BTM_SEC_MODE_SERVICE;
- }
- BTM_TRACE_DEBUG ("btm_sec_dev_reset sec mode: %d\n", btm_cb.security_mode);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_abort_access_req
- **
- ** Description This function is called by the L2CAP or RFCOMM to abort
- ** the pending operation.
- **
- ** Parameters: bd_addr - Address of the peer device
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_abort_access_req (BD_ADDR bd_addr)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
- if (!p_dev_rec) {
- return;
- }
- if ((p_dev_rec->sec_state != BTM_SEC_STATE_AUTHORIZING)
- && (p_dev_rec->sec_state != BTM_SEC_STATE_AUTHENTICATING)) {
- return;
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
- p_dev_rec->p_callback = NULL;
- }
- /*******************************************************************************
- **
- ** Function btm_sec_dd_create_conn
- **
- ** Description This function is called to create the ACL connection for
- ** the dedicated boding process
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static tBTM_STATUS btm_sec_dd_create_conn (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR);
- if (p_lcb && (p_lcb->link_state == LST_CONNECTED || p_lcb->link_state == LST_CONNECTING)) {
- BTM_TRACE_WARNING("%s Connection already exists\n", __func__);
- return BTM_CMD_STARTED;
- }
- /* Make sure an L2cap link control block is available */
- if (!p_lcb && (p_lcb = l2cu_allocate_lcb (p_dev_rec->bd_addr, TRUE, BT_TRANSPORT_BR_EDR)) == NULL) {
- BTM_TRACE_WARNING ("Security Manager: failed allocate LCB [%02x%02x%02x%02x%02x%02x]\n",
- p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
- p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]);
- return (BTM_NO_RESOURCES);
- }
- /* set up the control block to indicated dedicated bonding */
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_DISC_WHEN_DONE;
- if (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE) {
- BTM_TRACE_WARNING ("Security Manager: failed create [%02x%02x%02x%02x%02x%02x]\n",
- p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
- p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]);
- l2cu_release_lcb(p_lcb);
- return (BTM_NO_RESOURCES);
- }
- btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
- BTM_TRACE_DEBUG ("Security Manager: btm_sec_dd_create_conn [%02x%02x%02x%02x%02x%02x]\n",
- p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
- p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]);
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
- return (BTM_CMD_STARTED);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_rmt_name_request_complete
- **
- ** Description This function is called when remote name was obtained from
- ** the peer device
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT8 status)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- int i;
- DEV_CLASS dev_class;
- UINT8 old_sec_state;
- BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete\n");
- if (((p_bd_addr == NULL) && !BTM_ACL_IS_CONNECTED(btm_cb.connecting_bda))
- || ((p_bd_addr != NULL) && !BTM_ACL_IS_CONNECTED(p_bd_addr))) {
- btm_acl_resubmit_page();
- }
- /* If remote name request failed, p_bd_addr is null and we need to search */
- /* based on state assuming that we are doing 1 at a time */
- if (p_bd_addr) {
- p_dev_rec = btm_find_dev (p_bd_addr);
- } else {
- p_dev_rec = &btm_cb.sec_dev_rec[0];
- for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
- if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
- && (p_dev_rec->sec_state == BTM_SEC_STATE_GETTING_NAME)) {
- p_bd_addr = p_dev_rec->bd_addr;
- break;
- }
- }
- if (i == BTM_SEC_MAX_DEVICE_RECORDS) {
- p_dev_rec = NULL;
- }
- }
- /* Commenting out trace due to obf/compilation problems.
- */
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- if (!p_bd_name) {
- p_bd_name = (UINT8 *)"";
- }
- if (p_dev_rec) {
- BTM_TRACE_EVENT ("Security Manager: rmt_name_complete PairState: %s RemName: %s status: %d State:%d p_dev_rec: %p \n",
- btm_pair_state_descr (btm_cb.pairing_state), p_bd_name,
- status, p_dev_rec->sec_state, p_dev_rec);
- } else {
- BTM_TRACE_EVENT ("Security Manager: rmt_name_complete PairState: %s RemName: %s status: %d\n",
- btm_pair_state_descr (btm_cb.pairing_state), p_bd_name,
- status);
- }
- #endif
- if (p_dev_rec) {
- old_sec_state = p_dev_rec->sec_state;
- if (status == HCI_SUCCESS) {
- BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, (char *)p_bd_name, BTM_MAX_REM_BD_NAME_LEN);
- p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
- BTM_TRACE_EVENT ("setting BTM_SEC_NAME_KNOWN sec_flags:0x%x\n", p_dev_rec->sec_flags);
- } else {
- /* Notify all clients waiting for name to be resolved even if it failed so clients can continue */
- p_dev_rec->sec_bd_name[0] = 0;
- }
- if (p_dev_rec->sec_state == BTM_SEC_STATE_GETTING_NAME) {
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
- }
- /* Notify all clients waiting for name to be resolved */
- for (i = 0; i < BTM_SEC_MAX_RMT_NAME_CALLBACKS; i++) {
- if (btm_cb.p_rmt_name_callback[i] && p_bd_addr) {
- (*btm_cb.p_rmt_name_callback[i])(p_bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name);
- }
- }
- } else {
- dev_class[0] = 0;
- dev_class[1] = 0;
- dev_class[2] = 0;
- /* Notify all clients waiting for name to be resolved even if not found so clients can continue */
- for (i = 0; i < BTM_SEC_MAX_RMT_NAME_CALLBACKS; i++) {
- if (btm_cb.p_rmt_name_callback[i] && p_bd_addr) {
- (*btm_cb.p_rmt_name_callback[i])(p_bd_addr, dev_class, (UINT8 *)"");
- }
- }
- return;
- }
- /* If we were delaying asking UI for a PIN because name was not resolved, ask now */
- if ( (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_LOCAL_PIN) && p_bd_addr
- && (memcmp (btm_cb.pairing_bda, p_bd_addr, BD_ADDR_LEN) == 0) ) {
- BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete() delayed pin now being requested flags:0x%x, (p_pin_callback=%p)\n", btm_cb.pairing_flags, btm_cb.api.p_pin_callback);
- if (((btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) == 0) &&
- ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_PIN_REQD) == 0) &&
- btm_cb.api.p_pin_callback) {
- BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete() calling pin_callback\n");
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD;
- (*btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_bd_name,
- (p_dev_rec->p_cur_service == NULL) ? FALSE
- : (p_dev_rec->p_cur_service->security_flags & BTM_SEC_IN_MIN_16_DIGIT_PIN));
- }
- /* Set the same state again to force the timer to be restarted */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_LOCAL_PIN);
- return;
- }
- /* Check if we were delaying bonding because name was not resolved */
- if ( btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME) {
- if (p_bd_addr && memcmp (btm_cb.pairing_bda, p_bd_addr, BD_ADDR_LEN) == 0) {
- BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete() continue bonding sm4: 0x%04x, status:0x%x\n", p_dev_rec->sm4, status);
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_CANCEL_DD) {
- btm_sec_bond_cancel_complete();
- return;
- }
- if (status != HCI_SUCCESS) {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- if (btm_cb.api.p_auth_complete_callback)
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, status);
- return;
- }
- /* if peer is very old legacy devices, HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT is not reported */
- if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
- /* set the KNOWN flag only if BTM_PAIR_FLAGS_REJECTED_CONNECT is not set.*/
- /* If it is set, there may be a race condition */
- BTM_TRACE_DEBUG ("btm_sec_rmt_name_request_complete IS_SM4_UNKNOWN Flags:0x%04x\n",
- btm_cb.pairing_flags);
- if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_REJECTED_CONNECT) == 0) {
- p_dev_rec->sm4 |= BTM_SM4_KNOWN;
- }
- }
- BTM_TRACE_DEBUG("%s, SM4 Value: %x, Legacy:%d,IS SM4:%d, Unknown:%d\n", __FUNCTION__,
- p_dev_rec->sm4, BTM_SEC_IS_SM4_LEGACY(p_dev_rec->sm4),
- BTM_SEC_IS_SM4(p_dev_rec->sm4), BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4));
- /* BT 2.1 or carkit, bring up the connection to force the peer to request PIN.
- ** Else prefetch (btm_sec_check_prefetch_pin will do the prefetching if needed)
- */
- if ((p_dev_rec->sm4 != BTM_SM4_KNOWN) || !btm_sec_check_prefetch_pin(p_dev_rec)) {
- /* if we rejected incoming connection request, we have to wait HCI_Connection_Complete event */
- /* before originating */
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_REJECTED_CONNECT) {
- BTM_TRACE_WARNING ("btm_sec_rmt_name_request_complete: waiting HCI_Connection_Complete after rejecting connection\n");
- }
- /* Both we and the peer are 2.1 - continue to create connection */
- else if (btm_sec_dd_create_conn(p_dev_rec) != BTM_CMD_STARTED) {
- BTM_TRACE_WARNING ("btm_sec_rmt_name_request_complete: failed to start connection\n");
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_ERR_MEMORY_FULL);
- }
- }
- }
- return;
- } else {
- BTM_TRACE_WARNING ("btm_sec_rmt_name_request_complete: wrong BDA, retry with pairing BDA\n");
- BTM_ReadRemoteDeviceName (btm_cb.pairing_bda, NULL, BT_TRANSPORT_BR_EDR);
- return;
- }
- }
- /* check if we were delaying link_key_callback because name was not resolved */
- if (p_dev_rec->link_key_not_sent) {
- /* If HCI connection complete has not arrived, wait for it */
- if (p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE) {
- return;
- }
- p_dev_rec->link_key_not_sent = FALSE;
- btm_send_link_key_notif(p_dev_rec);
- /* If its not us who perform authentication, we should tell stackserver */
- /* that some authentication has been completed */
- /* This is required when different entities receive link notification and auth complete */
- if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)) {
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_SUCCESS);
- }
- }
- }
- /* If this is a bonding procedure can disconnect the link now */
- if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)
- && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) {
- BTM_TRACE_WARNING ("btm_sec_rmt_name_request_complete (none/ce)\n");
- p_dev_rec->security_required &= ~(BTM_SEC_OUT_AUTHENTICATE);
- l2cu_start_post_bond_timer(p_dev_rec->hci_handle);
- return;
- }
- if (old_sec_state != BTM_SEC_STATE_GETTING_NAME) {
- return;
- }
- /* If get name failed, notify the waiting layer */
- if (status != HCI_SUCCESS) {
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
- return;
- }
- if (p_dev_rec->sm4 & BTM_SM4_REQ_PEND) {
- BTM_TRACE_EVENT ("waiting for remote features!!\n");
- return;
- }
- /* Remote Name succeeded, execute the next security procedure, if any */
- status = (UINT8)btm_sec_execute_procedure (p_dev_rec);
- /* If result is pending reply from the user or from the device is pending */
- if (status == BTM_CMD_STARTED) {
- return;
- }
- /* There is no next procedure or start of procedure failed, notify the waiting layer */
- btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_rmt_host_support_feat_evt
- **
- ** Description This function is called when the
- ** HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT is received
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_rmt_host_support_feat_evt (UINT8 *p)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- BD_ADDR bd_addr; /* peer address */
- BD_FEATURES features;
- STREAM_TO_BDADDR (bd_addr, p);
- p_dev_rec = btm_find_or_alloc_dev (bd_addr);
- BTM_TRACE_EVENT ("btm_sec_rmt_host_support_feat_evt sm4: 0x%x p[0]: 0x%x\n", p_dev_rec->sm4, p[0]);
- if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
- p_dev_rec->sm4 = BTM_SM4_KNOWN;
- STREAM_TO_ARRAY(features, p, HCI_FEATURE_BYTES_PER_PAGE);
- if (HCI_SSP_HOST_SUPPORTED(features)) {
- p_dev_rec->sm4 = BTM_SM4_TRUE;
- }
- BTM_TRACE_EVENT ("btm_sec_rmt_host_support_feat_evt sm4: 0x%x features[0]: 0x%x\n", p_dev_rec->sm4, features[0]);
- }
- }
- /*******************************************************************************
- **
- ** Function btm_io_capabilities_req
- **
- ** Description This function is called when LM request for the IO
- ** capability of the local device and
- ** if the OOB data is present for the device in the event
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_io_capabilities_req (UINT8 *p)
- {
- tBTM_SP_IO_REQ evt_data;
- UINT8 err_code = 0;
- tBTM_SEC_DEV_REC *p_dev_rec;
- BOOLEAN is_orig = TRUE;
- UINT8 callback_rc = BTM_SUCCESS;
- STREAM_TO_BDADDR (evt_data.bd_addr, p);
- /* setup the default response according to compile options */
- /* assume that the local IO capability does not change
- * loc_io_caps is initialized with the default value */
- evt_data.io_cap = btm_cb.devcb.loc_io_caps;
- evt_data.oob_data = BTM_OOB_NONE;
- evt_data.auth_req = BTM_DEFAULT_AUTH_REQ;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT("%s: State: %s\n", __FUNCTION__, btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- p_dev_rec = btm_find_or_alloc_dev (evt_data.bd_addr);
- BTM_TRACE_DEBUG("%s:Security mode: %d, Num Read Remote Feat pages: %d\n", __FUNCTION__,
- btm_cb.security_mode, p_dev_rec->num_read_pages);
- if ((btm_cb.security_mode == BTM_SEC_MODE_SC) && (p_dev_rec->num_read_pages == 0)) {
- BTM_TRACE_EVENT("%s: Device security mode is SC only.\n"
- "To continue need to know remote features.\n", __FUNCTION__);
- p_dev_rec->remote_features_needed = TRUE;
- return;
- }
- p_dev_rec->sm4 |= BTM_SM4_TRUE;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT("%s: State: %s Flags: 0x%04x p_cur_service: %p\n",
- __FUNCTION__, btm_pair_state_descr(btm_cb.pairing_state),
- btm_cb.pairing_flags, p_dev_rec->p_cur_service);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- if (p_dev_rec->p_cur_service) {
- BTM_TRACE_EVENT("%s: cur_service psm: 0x%04x, security_flags: 0x%04x\n",
- __FUNCTION__, p_dev_rec->p_cur_service->psm,
- p_dev_rec->p_cur_service->security_flags);
- }
- switch (btm_cb.pairing_state) {
- /* initiator connecting */
- case BTM_PAIR_STATE_IDLE:
- //TODO: Handle Idle pairing state
- //security_required = p_dev_rec->security_required;
- break;
- /* received IO capability response already->acceptor */
- case BTM_PAIR_STATE_INCOMING_SSP:
- is_orig = FALSE;
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_PEER_STARTED_DD) {
- /* acceptor in dedicated bonding */
- evt_data.auth_req = BTM_DEFAULT_DD_AUTH_REQ;
- }
- break;
- /* initiator, at this point it is expected to be dedicated bonding
- initiated by local device */
- case BTM_PAIR_STATE_WAIT_PIN_REQ:
- if (!memcmp (evt_data.bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN)) {
- evt_data.auth_req = BTM_DEFAULT_DD_AUTH_REQ;
- } else {
- err_code = HCI_ERR_HOST_BUSY_PAIRING;
- }
- break;
- /* any other state is unexpected */
- default:
- err_code = HCI_ERR_HOST_BUSY_PAIRING;
- BTM_TRACE_ERROR("%s: Unexpected Pairing state received %d\n", __FUNCTION__,
- btm_cb.pairing_state);
- break;
- }
- if (btm_cb.pairing_disabled) {
- /* pairing is not allowed */
- BTM_TRACE_DEBUG("%s: Pairing is not allowed -> fail pairing.\n", __FUNCTION__);
- err_code = HCI_ERR_PAIRING_NOT_ALLOWED;
- } else if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- BOOLEAN local_supports_sc = controller_get_interface()->supports_secure_connections();
- /* device in Secure Connections Only mode */
- if (!(local_supports_sc) || !(p_dev_rec->remote_supports_secure_connections)) {
- BTM_TRACE_DEBUG("%s: SC only service, local_support_for_sc %d,\n"
- " remote_support_for_sc 0x%02x -> fail pairing\n", __FUNCTION__,
- local_supports_sc, p_dev_rec->remote_supports_secure_connections);
- err_code = HCI_ERR_PAIRING_NOT_ALLOWED;
- }
- }
- if (err_code != 0) {
- /* coverity[uninit_use_in_call]
- Event uninit_use_in_call: Using uninitialized element of array "evt_data.bd_addr" in call to function "memcmp"
- False-positive: evt_data.bd_addr is set at the beginning with: STREAM_TO_BDADDR (evt_data.bd_addr, p);
- */
- btsnd_hcic_io_cap_req_neg_reply(evt_data.bd_addr, err_code);
- return;
- }
- evt_data.is_orig = is_orig;
- if (is_orig) {
- /* local device initiated the pairing non-bonding -> use p_cur_service */
- if (!(btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) &&
- p_dev_rec->p_cur_service &&
- (p_dev_rec->p_cur_service->security_flags & BTM_SEC_OUT_AUTHENTICATE)) {
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- /* SC only mode device requires MITM protection */
- evt_data.auth_req = BTM_AUTH_SP_YES;
- } else {
- evt_data.auth_req = (p_dev_rec->p_cur_service->security_flags &
- BTM_SEC_OUT_MITM) ? BTM_AUTH_SP_YES : BTM_AUTH_SP_NO;
- }
- }
- }
- /* Notify L2CAP to increase timeout */
- l2c_pin_code_request (evt_data.bd_addr);
- memcpy (btm_cb.pairing_bda, evt_data.bd_addr, BD_ADDR_LEN);
- /* coverity[uninit_use_in_call]
- Event uninit_use_in_call: Using uninitialized element of array "evt_data.bd_addr" in call to function "memcmp"
- False-positive: False-positive: evt_data.bd_addr is set at the beginning with: STREAM_TO_BDADDR (evt_data.bd_addr, p);
- */
- if (!memcmp (evt_data.bd_addr, btm_cb.connecting_bda, BD_ADDR_LEN)) {
- memcpy (p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_LOCAL_IOCAPS);
- callback_rc = BTM_SUCCESS;
- if (p_dev_rec->sm4 & BTM_SM4_UPGRADE) {
- p_dev_rec->sm4 &= ~BTM_SM4_UPGRADE;
- /* link key upgrade: always use SPGB_YES - assuming we want to save the link key */
- evt_data.auth_req = BTM_AUTH_SPGB_YES;
- } else if (btm_cb.api.p_sp_callback) {
- /* the callback function implementation may change the IO capability... */
- callback_rc = (*btm_cb.api.p_sp_callback) (BTM_SP_IO_REQ_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
- }
- #if BTM_OOB_INCLUDED == TRUE
- if ((callback_rc == BTM_SUCCESS) || (BTM_OOB_UNKNOWN != evt_data.oob_data))
- #else
- if (callback_rc == BTM_SUCCESS)
- #endif
- {
- if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)) {
- evt_data.auth_req = (BTM_AUTH_DD_BOND | (evt_data.auth_req & BTM_AUTH_YN_BIT));
- }
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- /* At this moment we know that both sides are SC capable, device in */
- /* SC only mode requires MITM for any service so let's set MITM bit */
- evt_data.auth_req |= BTM_AUTH_YN_BIT;
- BTM_TRACE_DEBUG("%s: for device in \"SC only\" mode set auth_req to 0x%02x\n",
- __FUNCTION__, evt_data.auth_req);
- }
- /* if the user does not indicate "reply later" by setting the oob_data to unknown */
- /* send the response right now. Save the current IO capability in the control block */
- btm_cb.devcb.loc_auth_req = evt_data.auth_req;
- btm_cb.devcb.loc_io_caps = evt_data.io_cap;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT("%s: State: %s IO_CAP:%d oob_data:%d auth_req:%d",
- __FUNCTION__, btm_pair_state_descr(btm_cb.pairing_state), evt_data.io_cap,
- evt_data.oob_data, evt_data.auth_req);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- btsnd_hcic_io_cap_req_reply(evt_data.bd_addr, evt_data.io_cap,
- evt_data.oob_data, evt_data.auth_req);
- }
- }
- /*******************************************************************************
- **
- ** Function btm_io_capabilities_rsp
- **
- ** Description This function is called when the IO capability of the
- ** specified device is received
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_io_capabilities_rsp (UINT8 *p)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_SP_IO_RSP evt_data;
- STREAM_TO_BDADDR (evt_data.bd_addr, p);
- STREAM_TO_UINT8 (evt_data.io_cap, p);
- STREAM_TO_UINT8 (evt_data.oob_data, p);
- STREAM_TO_UINT8 (evt_data.auth_req, p);
- /* Allocate a new device record or reuse the oldest one */
- p_dev_rec = btm_find_or_alloc_dev (evt_data.bd_addr);
- /* If no security is in progress, this indicates incoming security */
- if (btm_cb.pairing_state == BTM_PAIR_STATE_IDLE) {
- memcpy (btm_cb.pairing_bda, evt_data.bd_addr, BD_ADDR_LEN);
- btm_sec_change_pairing_state (BTM_PAIR_STATE_INCOMING_SSP);
- /* Make sure we reset the trusted mask to help against attacks */
- BTM_SEC_CLR_TRUSTED_DEVICE(p_dev_rec->trusted_mask);
- /* work around for FW bug */
- btm_inq_stop_on_ssp();
- }
- /* Notify L2CAP to increase timeout */
- l2c_pin_code_request (evt_data.bd_addr);
- /* We must have a device record here.
- * Use the connecting device's CoD for the connection */
- /* coverity[uninit_use_in_call]
- Event uninit_use_in_call: Using uninitialized element of array "evt_data.bd_addr" in call to function "memcmp"
- FALSE-POSITIVE error from Coverity test-tool. evt_data.bd_addr is set at the beginning with: STREAM_TO_BDADDR (evt_data.bd_addr, p);
- */
- if (!memcmp (evt_data.bd_addr, btm_cb.connecting_bda, BD_ADDR_LEN)) {
- memcpy (p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);
- }
- /* peer sets dedicated bonding bit and we did not initiate dedicated bonding */
- if (btm_cb.pairing_state == BTM_PAIR_STATE_INCOMING_SSP /* peer initiated bonding */
- && (evt_data.auth_req & BTM_AUTH_DD_BOND) ) { /* and dedicated bonding bit is set */
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PEER_STARTED_DD;
- }
- /* save the IO capability in the device record */
- p_dev_rec->rmt_io_caps = evt_data.io_cap;
- p_dev_rec->rmt_auth_req = evt_data.auth_req;
- if (btm_cb.api.p_sp_callback) {
- (*btm_cb.api.p_sp_callback) (BTM_SP_IO_RSP_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
- }
- }
- /*******************************************************************************
- **
- ** Function btm_proc_sp_req_evt
- **
- ** Description This function is called to process/report
- ** HCI_USER_CONFIRMATION_REQUEST_EVT
- ** or HCI_USER_PASSKEY_REQUEST_EVT
- ** or HCI_USER_PASSKEY_NOTIFY_EVT
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_proc_sp_req_evt (tBTM_SP_EVT event, UINT8 *p)
- {
- tBTM_STATUS status = BTM_ERR_PROCESSING;
- tBTM_SP_EVT_DATA evt_data;
- UINT8 *p_bda = evt_data.cfm_req.bd_addr;
- tBTM_SEC_DEV_REC *p_dev_rec;
- /* All events start with bd_addr */
- STREAM_TO_BDADDR (p_bda, p);
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("btm_proc_sp_req_evt() BDA: %08x%04x event: 0x%x, State: %s\n",
- (p_bda[0] << 24) + (p_bda[1] << 16) + (p_bda[2] << 8) + p_bda[3], (p_bda[4] << 8) + p_bda[5],
- event, btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- if ( ((p_dev_rec = btm_find_dev (p_bda)) != NULL)
- && (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (memcmp (btm_cb.pairing_bda, p_bda, BD_ADDR_LEN) == 0) ) {
- memcpy (evt_data.cfm_req.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- memcpy (evt_data.cfm_req.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);
- BCM_STRCPY_S ((char *)evt_data.cfm_req.bd_name,(char *)p_dev_rec->sec_bd_name);
- switch (event) {
- case BTM_SP_CFM_REQ_EVT:
- /* Numeric confirmation. Need user to conf the passkey */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_NUMERIC_CONFIRM);
- /* The device record must be allocated in the "IO cap exchange" step */
- STREAM_TO_UINT32 (evt_data.cfm_req.num_val, p);
- evt_data.cfm_req.just_works = TRUE;
- /* process user confirm req in association with the auth_req param */
- // #if (BTM_LOCAL_IO_CAPS == BTM_IO_CAP_IO)
- if ( (p_dev_rec->rmt_io_caps == BTM_IO_CAP_IO)
- && (btm_cb.devcb.loc_io_caps == BTM_IO_CAP_IO)
- && ((p_dev_rec->rmt_auth_req & BTM_AUTH_SP_YES) || (btm_cb.devcb.loc_auth_req & BTM_AUTH_SP_YES)) ) {
- /* Both devices are DisplayYesNo and one or both devices want to authenticate
- -> use authenticated link key */
- evt_data.cfm_req.just_works = FALSE;
- }
- // #endif
- BTM_TRACE_DEBUG ("btm_proc_sp_req_evt() just_works:%d, io loc:%d, rmt:%d, auth loc:%d, rmt:%d\n",
- evt_data.cfm_req.just_works, btm_cb.devcb.loc_io_caps, p_dev_rec->rmt_io_caps,
- btm_cb.devcb.loc_auth_req, p_dev_rec->rmt_auth_req);
- evt_data.cfm_req.loc_auth_req = btm_cb.devcb.loc_auth_req;
- evt_data.cfm_req.rmt_auth_req = p_dev_rec->rmt_auth_req;
- evt_data.cfm_req.loc_io_caps = btm_cb.devcb.loc_io_caps;
- evt_data.cfm_req.rmt_io_caps = p_dev_rec->rmt_io_caps;
- break;
- case BTM_SP_KEY_NOTIF_EVT:
- /* Passkey notification (other side is a keyboard) */
- STREAM_TO_UINT32 (evt_data.key_notif.passkey, p);
- BTM_TRACE_DEBUG ("BTM_SP_KEY_NOTIF_EVT: passkey: %u\n", evt_data.key_notif.passkey);
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- break;
- #if (BT_SSP_INCLUDED == TRUE)
- case BTM_SP_KEY_REQ_EVT:
- /* HCI_USER_PASSKEY_REQUEST_EVT */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_KEY_ENTRY);
- break;
- #endif
- }
- if (btm_cb.api.p_sp_callback) {
- status = (*btm_cb.api.p_sp_callback) (event, (tBTM_SP_EVT_DATA *)&evt_data);
- if (status != BTM_NOT_AUTHORIZED) {
- return;
- }
- /* else BTM_NOT_AUTHORIZED means when the app wants to reject the req right now */
- } else if ( (event == BTM_SP_CFM_REQ_EVT) && (evt_data.cfm_req.just_works == TRUE) ) {
- /* automatically reply with just works if no sp_cback */
- status = BTM_SUCCESS;
- }
- if (event == BTM_SP_CFM_REQ_EVT) {
- BTM_TRACE_DEBUG ("calling BTM_ConfirmReqReply with status: %d\n", status);
- BTM_ConfirmReqReply (status, p_bda);
- }
- #if (BT_SSP_INCLUDED == TRUE)
- else if (event == BTM_SP_KEY_REQ_EVT) {
- BTM_PasskeyReqReply(status, p_bda, 0);
- }
- #endif
- return;
- }
- /* Something bad. we can only fail this connection */
- btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
- if (BTM_SP_CFM_REQ_EVT == event) {
- btsnd_hcic_user_conf_reply (p_bda, FALSE);
- } else if (BTM_SP_KEY_NOTIF_EVT == event) {
- /* do nothing -> it very unlikely to happen.
- This event is most likely to be received by a HID host when it first connects to a HID device.
- Usually the Host initiated the connection in this case.
- On Mobile platforms, if there's a security process happening,
- the host probably can not initiate another connection.
- BTW (PC) is another story. */
- if (NULL != (p_dev_rec = btm_find_dev (p_bda)) ) {
- btm_sec_disconnect (p_dev_rec->hci_handle, HCI_ERR_AUTH_FAILURE);
- }
- }
- #if (BT_SSP_INCLUDED == TRUE)
- else {
- btsnd_hcic_user_passkey_neg_reply(p_bda);
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_keypress_notif_evt
- **
- ** Description This function is called when a key press notification is
- ** received
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_keypress_notif_evt (UINT8 *p)
- {
- tBTM_SP_KEYPRESS evt_data;
- UINT8 *p_bda;
- /* parse & report BTM_SP_KEYPRESS_EVT */
- if (btm_cb.api.p_sp_callback) {
- p_bda = evt_data.bd_addr;
- STREAM_TO_BDADDR (p_bda, p);
- evt_data.notif_type = *p;
- (*btm_cb.api.p_sp_callback) (BTM_SP_KEYPRESS_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
- }
- }
- /*******************************************************************************
- **
- ** Function btm_simple_pair_complete
- **
- ** Description This function is called when simple pairing process is
- ** complete
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_simple_pair_complete (UINT8 *p)
- {
- tBTM_SP_COMPLT evt_data;
- tBTM_SEC_DEV_REC *p_dev_rec;
- UINT8 status;
- BOOLEAN disc = FALSE;
- status = *p++;
- STREAM_TO_BDADDR (evt_data.bd_addr, p);
- if ((p_dev_rec = btm_find_dev (evt_data.bd_addr)) == NULL) {
- BTM_TRACE_ERROR ("btm_simple_pair_complete() with unknown BDA: %08x%04x\n",
- (evt_data.bd_addr[0] << 24) + (evt_data.bd_addr[1] << 16) + (evt_data.bd_addr[2] << 8) + evt_data.bd_addr[3],
- (evt_data.bd_addr[4] << 8) + evt_data.bd_addr[5]);
- return;
- }
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("btm_simple_pair_complete() Pair State: %s Status:%d sec_state: %u\n",
- btm_pair_state_descr(btm_cb.pairing_state), status, p_dev_rec->sec_state);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- evt_data.status = BTM_ERR_PROCESSING;
- if (status == HCI_SUCCESS) {
- evt_data.status = BTM_SUCCESS;
- p_dev_rec->sec_flags |= BTM_SEC_AUTHENTICATED;
- } else {
- if (status == HCI_ERR_PAIRING_NOT_ALLOWED) {
- /* The test spec wants the peer device to get this failure code. */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_DISCONNECT);
- /* Change the timer to 1 second */
- btu_start_timer (&btm_cb.pairing_tle, BTU_TTYPE_USER_FUNC, BT_1SEC_TIMEOUT);
- } else if (memcmp (btm_cb.pairing_bda, evt_data.bd_addr, BD_ADDR_LEN) == 0) {
- /* stop the timer */
- btu_stop_timer (&btm_cb.pairing_tle);
- if (p_dev_rec->sec_state != BTM_SEC_STATE_AUTHENTICATING) {
- /* the initiating side: will receive auth complete event. disconnect ACL at that time */
- disc = TRUE;
- }
- } else {
- disc = TRUE;
- }
- }
- /* Let the pairing state stay active, p_auth_complete_callback will report the failure */
- memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- memcpy (evt_data.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);
- if (btm_cb.api.p_sp_callback) {
- (*btm_cb.api.p_sp_callback) (BTM_SP_COMPLT_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
- }
- if (disc) {
- /* simple pairing failed */
- /* Avoid sending disconnect on HCI_ERR_PEER_USER */
- if ((status != HCI_ERR_PEER_USER) && (status != HCI_ERR_CONN_CAUSE_LOCAL_HOST)) {
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
- }
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- #if BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_rem_oob_req
- **
- ** Description This function is called to process/report
- ** HCI_REMOTE_OOB_DATA_REQUEST_EVT
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_rem_oob_req (UINT8 *p)
- {
- UINT8 *p_bda;
- tBTM_SP_RMT_OOB evt_data;
- tBTM_SEC_DEV_REC *p_dev_rec;
- BT_OCTET16 c;
- BT_OCTET16 r;
- p_bda = evt_data.bd_addr;
- STREAM_TO_BDADDR (p_bda, p);
- BTM_TRACE_EVENT ("btm_rem_oob_req() BDA: %02x:%02x:%02x:%02x:%02x:%02x\n",
- p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
- if ( (NULL != (p_dev_rec = btm_find_dev (p_bda))) &&
- btm_cb.api.p_sp_callback) {
- memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- memcpy (evt_data.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);
- BCM_STRNCPY_S((char *)evt_data.bd_name, (char *)p_dev_rec->sec_bd_name, BTM_MAX_REM_BD_NAME_LEN);
- evt_data.bd_name[BTM_MAX_REM_BD_NAME_LEN] = 0;
- btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP);
- if ((*btm_cb.api.p_sp_callback) (BTM_SP_RMT_OOB_EVT, (tBTM_SP_EVT_DATA *)&evt_data) == BTM_NOT_AUTHORIZED) {
- BTM_RemoteOobDataReply(TRUE, p_bda, c, r);
- }
- return;
- }
- /* something bad. we can only fail this connection */
- btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
- btsnd_hcic_rem_oob_neg_reply (p_bda);
- }
- /*******************************************************************************
- **
- ** Function btm_read_local_oob_complete
- **
- ** Description This function is called when read local oob data is
- ** completed by the LM
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_read_local_oob_complete (UINT8 *p)
- {
- tBTM_SP_LOC_OOB evt_data;
- UINT8 status = *p++;
- BTM_TRACE_EVENT ("btm_read_local_oob_complete:%d\n", status);
- if (status == HCI_SUCCESS) {
- evt_data.status = BTM_SUCCESS;
- STREAM_TO_ARRAY16(evt_data.c, p);
- STREAM_TO_ARRAY16(evt_data.r, p);
- } else {
- evt_data.status = BTM_ERR_PROCESSING;
- }
- if (btm_cb.api.p_sp_callback) {
- (*btm_cb.api.p_sp_callback) (BTM_SP_LOC_OOB_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
- }
- }
- #endif /* BTM_OOB_INCLUDED */
- /*******************************************************************************
- **
- ** Function btm_sec_auth_collision
- **
- ** Description This function is called when authentication or encryption
- ** needs to be retried at a later time.
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_auth_collision (UINT16 handle)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- if (!btm_cb.collision_start_time) {
- btm_cb.collision_start_time = osi_time_get_os_boottime_ms();
- }
- if ((osi_time_get_os_boottime_ms() - btm_cb.collision_start_time) < btm_cb.max_collision_delay)
- {
- if (handle == BTM_SEC_INVALID_HANDLE)
- {
- if ((p_dev_rec = btm_sec_find_dev_by_sec_state (BTM_SEC_STATE_AUTHENTICATING)) == NULL) {
- p_dev_rec = btm_sec_find_dev_by_sec_state (BTM_SEC_STATE_ENCRYPTING);
- }
- } else {
- p_dev_rec = btm_find_dev_by_handle (handle);
- }
- if (p_dev_rec != NULL) {
- BTM_TRACE_DEBUG ("btm_sec_auth_collision: state %d (retrying in a moment...)\n", p_dev_rec->sec_state);
- /* We will restart authentication after timeout */
- if (p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING || p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING) {
- p_dev_rec->sec_state = 0;
- }
- btm_cb.p_collided_dev_rec = p_dev_rec;
- btm_cb.sec_collision_tle.param = (UINT32) btm_sec_collision_timeout;
- btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, BT_1SEC_TIMEOUT);
- }
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_auth_complete
- **
- ** Description This function is when authentication of the connection is
- ** completed by the LM
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_auth_complete (UINT16 handle, UINT8 status)
- {
- UINT8 old_sm4;
- tBTM_PAIRING_STATE old_state = btm_cb.pairing_state;
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
- BOOLEAN are_bonding = FALSE;
- /* Commenting out trace due to obf/compilation problems.
- */
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- if (p_dev_rec) {
- BTM_TRACE_EVENT ("Security Manager: auth_complete PairState: %s handle:%u status:%d dev->sec_state: %u Bda:%08x, RName:%s\n",
- btm_pair_state_descr (btm_cb.pairing_state),
- handle, status,
- p_dev_rec->sec_state,
- (p_dev_rec->bd_addr[2] << 24) + (p_dev_rec->bd_addr[3] << 16) + (p_dev_rec->bd_addr[4] << 8) + p_dev_rec->bd_addr[5],
- p_dev_rec->sec_bd_name);
- } else {
- BTM_TRACE_EVENT ("Security Manager: auth_complete PairState: %s handle:%u status:%d\n",
- btm_pair_state_descr (btm_cb.pairing_state),
- handle, status);
- }
- #endif
- /* For transaction collision we need to wait and repeat. There is no need */
- /* for random timeout because only slave should receive the result */
- if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) || (status == HCI_ERR_DIFF_TRANSACTION_COLLISION)) {
- btm_sec_auth_collision(handle);
- return;
- }
- btm_cb.collision_start_time = 0;
- btm_restore_mode();
- /* Check if connection was made just to do bonding. If we authenticate
- the connection that is up, this is the last event received.
- */
- if (p_dev_rec
- && (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)
- && !(btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE)) {
- p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
- l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
- }
- if (!p_dev_rec) {
- return;
- }
- /* keep the old sm4 flag and clear the retry bit in control block */
- old_sm4 = p_dev_rec->sm4;
- p_dev_rec->sm4 &= ~BTM_SM4_RETRY;
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)
- && (memcmp (p_dev_rec->bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN) == 0) ) {
- are_bonding = TRUE;
- }
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (memcmp (p_dev_rec->bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN) == 0) ) {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- }
- if (p_dev_rec->sec_state != BTM_SEC_STATE_AUTHENTICATING) {
- if ( (btm_cb.api.p_auth_complete_callback && status != HCI_SUCCESS)
- && (old_state != BTM_PAIR_STATE_IDLE) ) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, status);
- }
- return;
- }
- /* There can be a race condition, when we are starting authentication and
- ** the peer device is doing encryption.
- ** If first we receive encryption change up, then initiated authentication
- ** can not be performed. According to the spec we can not do authentication
- ** on the encrypted link, so device is correct.
- */
- if ((status == HCI_ERR_COMMAND_DISALLOWED)
- && ((p_dev_rec->sec_flags & (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED)) ==
- (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED))) {
- status = HCI_SUCCESS;
- }
- /* Currently we do not notify user if it is a keyboard which connects */
- /* User probably Disabled the keyboard while it was asleep. Let her try */
- if (btm_cb.api.p_auth_complete_callback) {
- /* report the authentication status */
- if (old_state != BTM_PAIR_STATE_IDLE) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, status);
- }
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
- #if (CLASSIC_BT_INCLUDED == TRUE)
- btm_sec_update_legacy_auth_state(btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR), BTM_ACL_LEGACY_AUTH_SELF);
- #endif
- /* If this is a bonding procedure can disconnect the link now */
- if (are_bonding) {
- p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
- if (status != HCI_SUCCESS) {
- if (((status != HCI_ERR_PEER_USER) && (status != HCI_ERR_CONN_CAUSE_LOCAL_HOST))) {
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_PEER_USER, p_dev_rec->hci_handle);
- }
- } else {
- BTM_TRACE_DEBUG ("TRYING TO DECIDE IF CAN USE SMP_BR_CHNL\n");
- if (p_dev_rec->new_encryption_key_is_p256 && (btm_sec_use_smp_br_chnl(p_dev_rec))
- /* no LE keys are available, do deriving */
- && (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_KNOWN) ||
- /* or BR key is higher security than existing LE keys */
- (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED) &&
- (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED)))) {
- BTM_TRACE_DEBUG ("link encrypted afer dedic bonding can use SMP_BR_CHNL\n");
- if (btm_sec_is_master(p_dev_rec)) {
- // Encryption is required to start SM over BR/EDR
- // indicate that this is encryption after authentication
- BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL);
- }
- }
- l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
- }
- return;
- }
- /* If authentication failed, notify the waiting layer */
- if (status != HCI_SUCCESS) {
- if ((old_sm4 & BTM_SM4_RETRY) == 0) {
- /* allow retry only once */
- if (status == HCI_ERR_LMP_ERR_TRANS_COLLISION) {
- /* not retried yet. set the retry bit */
- p_dev_rec->sm4 |= BTM_SM4_RETRY;
- BTM_TRACE_DEBUG ("Collision retry sm4:x%x sec_flags:0x%x\n", p_dev_rec->sm4, p_dev_rec->sec_flags);
- }
- /* this retry for missing key is for Lisbon or later only.
- * Legacy device do not need this. the controller will drive the retry automatically */
- else if (HCI_ERR_KEY_MISSING == status && BTM_SEC_IS_SM4(p_dev_rec->sm4)) {
- /* not retried yet. set the retry bit */
- p_dev_rec->sm4 |= BTM_SM4_RETRY;
- p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_KNOWN;
- BTM_TRACE_DEBUG ("Retry for missing key sm4:x%x sec_flags:0x%x\n", p_dev_rec->sm4, p_dev_rec->sec_flags);
- /* With BRCM controller, we do not need to delete the stored link key in controller.
- If the stack may sit on top of other controller, we may need this
- BTM_DeleteStoredLinkKey (bd_addr, NULL); */
- }
- if (p_dev_rec->sm4 & BTM_SM4_RETRY) {
- btm_sec_execute_procedure (p_dev_rec);
- return;
- }
- }
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) {
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
- }
- return;
- }
- p_dev_rec->sec_flags |= BTM_SEC_AUTHENTICATED;
- if (p_dev_rec->pin_code_length >= 16 ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) {
- // If we have MITM protection we have a higher level of security than
- // provided by 16 digits PIN
- p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
- }
- /* Authentication succeeded, execute the next security procedure, if any */
- status = btm_sec_execute_procedure (p_dev_rec);
- /* If there is no next procedure, or procedure failed to start, notify the caller */
- if (status != BTM_CMD_STARTED) {
- btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_encrypt_change
- **
- ** Description This function is when encryption of the connection is
- ** completed by the LM
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- tACL_CONN *p_acl = NULL;
- UINT8 acl_idx = btm_handle_to_acl_index(handle);
- #endif
- BTM_TRACE_EVENT ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d\n",
- status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable);
- BTM_TRACE_DEBUG ("before update p_dev_rec->sec_flags=0x%x\n", (p_dev_rec) ? p_dev_rec->sec_flags : 0 );
- /* For transaction collision we need to wait and repeat. There is no need */
- /* for random timeout because only slave should receive the result */
- if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) ||
- (status == HCI_ERR_DIFF_TRANSACTION_COLLISION)) {
- btm_sec_auth_collision(handle);
- return;
- }
- btm_cb.collision_start_time = 0;
- if (!p_dev_rec) {
- return;
- }
- if ((status == HCI_SUCCESS) && encr_enable) {
- if (p_dev_rec->hci_handle == handle) {
- p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED);
- if (p_dev_rec->pin_code_length >= 16 ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) {
- p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
- }
- } else {
- p_dev_rec->sec_flags |= BTM_SEC_LE_ENCRYPTED;
- }
- }
- /* It is possible that we decrypted the link to perform role switch */
- /* mark link not to be encrypted, so that when we execute security next time it will kick in again */
- if ((status == HCI_SUCCESS) && !encr_enable) {
- if (p_dev_rec->hci_handle == handle) {
- p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED;
- } else {
- p_dev_rec->sec_flags &= ~BTM_SEC_LE_ENCRYPTED;
- }
- }
- BTM_TRACE_DEBUG ("after update p_dev_rec->sec_flags=0x%x\n", p_dev_rec->sec_flags );
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (acl_idx != MAX_L2CAP_LINKS) {
- p_acl = &btm_cb.acl_db[acl_idx];
- }
- if (p_acl != NULL) {
- btm_sec_check_pending_enc_req(p_dev_rec, p_acl->transport, encr_enable);
- }
- if (p_acl && p_acl->transport == BT_TRANSPORT_LE) {
- if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE ||
- status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) {
- p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN);
- p_dev_rec->ble.key_type = BTM_LE_KEY_NONE;
- }
- btm_ble_link_encrypted(p_dev_rec->ble.pseudo_addr, encr_enable);
- return;
- } else {
- /* BR/EDR connection, update the encryption key size to be 16 as always */
- p_dev_rec->enc_key_size = 16;
- }
- BTM_TRACE_DEBUG ("in %s new_encr_key_256 is %d\n",
- __func__, p_dev_rec->new_encryption_key_is_p256);
- if ((status == HCI_SUCCESS) && encr_enable && (p_dev_rec->hci_handle == handle)) {
- if (p_dev_rec->new_encryption_key_is_p256) {
- if (btm_sec_use_smp_br_chnl(p_dev_rec) &&
- btm_sec_is_master(p_dev_rec) &&
- /* if LE key is not known, do deriving */
- (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_KNOWN) ||
- /* or BR key is higher security than existing LE keys */
- (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
- && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED)))) {
- /* BR/EDR is encrypted with LK that can be used to derive LE LTK */
- p_dev_rec->new_encryption_key_is_p256 = FALSE;
- if (p_dev_rec->no_smp_on_br) {
- BTM_TRACE_DEBUG ("%s NO SM over BR/EDR\n", __func__);
- } else {
- #if (CLASSIC_BT_INCLUDED == TRUE)
- BTM_TRACE_DEBUG ("%s start SM over BR/EDR\n", __func__);
- SMP_BR_PairWith(p_dev_rec->bd_addr);
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- }
- }
- } else {
- // BR/EDR is successfully encrypted. Correct LK type if needed
- // (BR/EDR LK derived from LE LTK was used for encryption)
- if ((encr_enable == 1) && /* encryption is ON for SSP */
- /* LK type is for BR/EDR SC */
- (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256 ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- if (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256) {
- p_dev_rec->link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
- } else { /* BTM_LKEY_TYPE_AUTH_COMB_P_256 */
- p_dev_rec->link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
- }
- BTM_TRACE_DEBUG("updated link key type to %d\n", p_dev_rec->link_key_type);
- btm_send_link_key_notif(p_dev_rec);
- }
- }
- }
- #else
- btm_sec_check_pending_enc_req (p_dev_rec, BT_TRANSPORT_BR_EDR, encr_enable);
- #endif /* BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE */
- /* If this encryption was started by peer do not need to do anything */
- if (p_dev_rec->sec_state != BTM_SEC_STATE_ENCRYPTING) {
- if (BTM_SEC_STATE_DELAY_FOR_ENC == p_dev_rec->sec_state) {
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
- p_dev_rec->p_callback = NULL;
- #if (CLASSIC_BT_INCLUDED == TRUE)
- l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr);
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- }
- return;
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
- /* If encryption setup failed, notify the waiting layer */
- if (status != HCI_SUCCESS) {
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
- return;
- }
- /* Encryption setup succeeded, execute the next security procedure, if any */
- status = (UINT8)btm_sec_execute_procedure (p_dev_rec);
- /* If there is no next procedure, or procedure failed to start, notify the caller */
- if (status != BTM_CMD_STARTED) {
- btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_connect_after_reject_timeout
- **
- ** Description Connection for bonding could not start because of the collision
- ** Initiate outgoing connection
- **
- ** Returns Pointer to the TLE struct
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_connect_after_reject_timeout (TIMER_LIST_ENT *p_tle)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_cb.p_collided_dev_rec;
- UNUSED(p_tle);
- BTM_TRACE_EVENT ("btm_sec_connect_after_reject_timeout()\n");
- btm_cb.sec_collision_tle.param = 0;
- btm_cb.p_collided_dev_rec = 0;
- if (btm_sec_dd_create_conn(p_dev_rec) != BTM_CMD_STARTED) {
- BTM_TRACE_WARNING ("Security Manager: btm_sec_connect_after_reject_timeout: failed to start connection\n");
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_ERR_MEMORY_FULL);
- }
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_connected
- **
- ** Description This function is when a connection to the peer device is
- ** establsihed
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
- UINT8 res;
- BOOLEAN is_pairing_device = FALSE;
- tACL_CONN *p_acl_cb;
- UINT8 bit_shift = 0;
- btm_acl_resubmit_page();
- /* Commenting out trace due to obf/compilation problems.
- */
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- if (p_dev_rec) {
- BTM_TRACE_EVENT ("Security Manager: btm_sec_connected in state: %s handle:%d status:%d enc_mode:%d bda:%x RName:%s\n",
- btm_pair_state_descr(btm_cb.pairing_state), handle, status, enc_mode,
- (bda[2] << 24) + (bda[3] << 16) + (bda[4] << 8) + bda[5],
- p_dev_rec->sec_bd_name);
- } else {
- BTM_TRACE_EVENT ("Security Manager: btm_sec_connected in state: %s handle:%d status:%d enc_mode:%d bda:%x \n",
- btm_pair_state_descr(btm_cb.pairing_state), handle, status, enc_mode,
- (bda[2] << 24) + (bda[3] << 16) + (bda[4] << 8) + bda[5]);
- }
- #endif
- if (!p_dev_rec) {
- /* There is no device record for new connection. Allocate one */
- if (status == HCI_SUCCESS) {
- p_dev_rec = btm_sec_alloc_dev (bda);
- } else {
- /* If the device matches with stored paring address
- * reset the paring state to idle */
- if ((btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) &&
- (memcmp (btm_cb.pairing_bda, bda, BD_ADDR_LEN) == 0)) {
- btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);
- }
- /* can not find the device record and the status is error,
- * just ignore it */
- return;
- }
- } else { /* Update the timestamp for this device */
- #if BLE_INCLUDED == TRUE
- bit_shift = (handle == p_dev_rec->ble_hci_handle) ? 8 : 0;
- #endif
- p_dev_rec->timestamp = btm_cb.dev_rec_count++;
- if (p_dev_rec->sm4 & BTM_SM4_CONN_PEND) {
- /* tell L2CAP it's a bonding connection. */
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)
- && (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) ) {
- /* if incoming connection failed while pairing, then try to connect and continue */
- /* Motorola S9 disconnects without asking pin code */
- if ((status != HCI_SUCCESS) && (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_PIN_REQ)) {
- BTM_TRACE_WARNING ("Security Manager: btm_sec_connected: incoming connection failed without asking PIN\n");
- p_dev_rec->sm4 &= ~BTM_SM4_CONN_PEND;
- if (p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN) {
- /* Start timer with 0 to initiate connection with new LCB */
- /* because L2CAP will delete current LCB with this event */
- btm_cb.p_collided_dev_rec = p_dev_rec;
- btm_cb.sec_collision_tle.param = (UINT32) btm_sec_connect_after_reject_timeout;
- btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, 0);
- } else {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
- BTM_ReadRemoteDeviceName(p_dev_rec->bd_addr, NULL, BT_TRANSPORT_BR_EDR);
- }
- #if BTM_DISC_DURING_RS == TRUE
- p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
- #endif
- return;
- } else {
- l2cu_update_lcb_4_bonding(p_dev_rec->bd_addr, TRUE);
- }
- }
- /* always clear the pending flag */
- p_dev_rec->sm4 &= ~BTM_SM4_CONN_PEND;
- }
- }
- #if BLE_INCLUDED == TRUE
- p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
- #endif
- #if BTM_DISC_DURING_RS == TRUE
- p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
- #endif
- p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (memcmp (btm_cb.pairing_bda, bda, BD_ADDR_LEN) == 0) ) {
- /* if we rejected incoming connection from bonding device */
- if ((status == HCI_ERR_HOST_REJECT_DEVICE)
- && (btm_cb.pairing_flags & BTM_PAIR_FLAGS_REJECTED_CONNECT)) {
- BTM_TRACE_WARNING ("Security Manager: btm_sec_connected: HCI_Conn_Comp Flags:0x%04x, sm4: 0x%x\n",
- btm_cb.pairing_flags, p_dev_rec->sm4);
- btm_cb.pairing_flags &= ~BTM_PAIR_FLAGS_REJECTED_CONNECT;
- if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
- /* Try again: RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
- BTM_ReadRemoteDeviceName(bda, NULL, BT_TRANSPORT_BR_EDR);
- return;
- }
- /* if we already have pin code */
- if (btm_cb.pairing_state != BTM_PAIR_STATE_WAIT_LOCAL_PIN) {
- /* Start timer with 0 to initiate connection with new LCB */
- /* because L2CAP will delete current LCB with this event */
- btm_cb.p_collided_dev_rec = p_dev_rec;
- btm_cb.sec_collision_tle.param = (UINT32) btm_sec_connect_after_reject_timeout;
- btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, 0);
- }
- return;
- }
- /* wait for incoming connection without resetting pairing state */
- else if (status == HCI_ERR_CONNECTION_EXISTS) {
- BTM_TRACE_WARNING ("Security Manager: btm_sec_connected: Wait for incoming connection\n");
- return;
- }
- is_pairing_device = TRUE;
- }
- /* If connection was made to do bonding restore link security if changed */
- btm_restore_mode();
- /* if connection fails during pin request, notify application */
- if (status != HCI_SUCCESS) {
- /* If connection failed because of during pairing, need to tell user */
- if (is_pairing_device) {
- p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
- p_dev_rec->sec_flags &= ~((BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED) << bit_shift);
- BTM_TRACE_DEBUG ("security_required:%x \n", p_dev_rec->security_required );
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- /* We need to notify host that the key is not known any more */
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, status);
- }
- }
- /*
- Do not send authentication failure, if following conditions hold good
- 1. BTM Sec Pairing state is idle
- 2. Link key for the remote device is present.
- 3. Remote is SSP capable.
- */
- else if ((p_dev_rec->link_key_type <= BTM_LKEY_TYPE_REMOTE_UNIT) &&
- (((status == HCI_ERR_AUTH_FAILURE) ||
- (status == HCI_ERR_KEY_MISSING) ||
- (status == HCI_ERR_HOST_REJECT_SECURITY) ||
- (status == HCI_ERR_PAIRING_NOT_ALLOWED) ||
- (status == HCI_ERR_UNIT_KEY_USED) ||
- (status == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) ||
- (status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) ||
- (status == HCI_ERR_REPEATED_ATTEMPTS)))) {
- p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
- p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN << bit_shift);
- #ifdef BRCM_NOT_4_BTE
- /* If we rejected pairing, pass this special result code */
- if (btm_cb.acl_disc_reason == HCI_ERR_HOST_REJECT_SECURITY) {
- status = HCI_ERR_HOST_REJECT_SECURITY;
- }
- #endif
- /* We need to notify host that the key is not known any more */
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, status);
- }
- }
- if (status == HCI_ERR_CONNECTION_TOUT || status == HCI_ERR_LMP_RESPONSE_TIMEOUT ||
- status == HCI_ERR_UNSPECIFIED || status == HCI_ERR_PAGE_TIMEOUT) {
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_DEVICE_TIMEOUT, FALSE);
- } else {
- btm_sec_dev_rec_cback_event (p_dev_rec, BTM_ERR_PROCESSING, FALSE);
- }
- return;
- }
- /* If initiated dedicated bonding, return the link key now, and initiate disconnect */
- /* If dedicated bonding, and we now have a link key, we are all done */
- if ( is_pairing_device
- && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) ) {
- if (p_dev_rec->link_key_not_sent) {
- p_dev_rec->link_key_not_sent = FALSE;
- btm_send_link_key_notif(p_dev_rec);
- }
- p_dev_rec->security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
- /* remember flag before it is initialized */
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
- res = TRUE;
- } else {
- res = FALSE;
- }
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_SUCCESS);
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- if ( res ) {
- /* Let l2cap start bond timer */
- l2cu_update_lcb_4_bonding (p_dev_rec->bd_addr, TRUE);
- }
- return;
- }
- p_dev_rec->hci_handle = handle;
- /* role may not be correct here, it will be updated by l2cap, but we need to */
- /* notify btm_acl that link is up, so starting of rmt name request will not */
- /* set paging flag up */
- p_acl_cb = btm_bda_to_acl(bda, BT_TRANSPORT_BR_EDR);
- if (p_acl_cb) {
- /* whatever is in btm_establish_continue() without reporting the BTM_BL_CONN_EVT event */
- #if (!defined(BTM_BYPASS_EXTRA_ACL_SETUP) || BTM_BYPASS_EXTRA_ACL_SETUP == FALSE)
- /* For now there are a some devices that do not like sending */
- /* commands events and data at the same time. */
- /* Set the packet types to the default allowed by the device */
- btm_set_packet_types (p_acl_cb, btm_cb.btm_acl_pkt_types_supported);
- if (btm_cb.btm_def_link_policy) {
- BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
- }
- #endif
- }
- btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, BT_TRANSPORT_BR_EDR);
- /* Initialize security flags. We need to do that because some */
- /* authorization complete could have come after the connection is dropped */
- /* and that would set wrong flag that link has been authorized already */
- p_dev_rec->sec_flags &= ~((BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED |
- BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED) << bit_shift);
- if (enc_mode != HCI_ENCRYPT_MODE_DISABLED) {
- p_dev_rec->sec_flags |= ((BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED) << bit_shift);
- }
- if (btm_cb.security_mode == BTM_SEC_MODE_LINK) {
- p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED << bit_shift);
- }
- if (p_dev_rec->pin_code_length >= 16 ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) {
- p_dev_rec->sec_flags |= (BTM_SEC_16_DIGIT_PIN_AUTHED << bit_shift);
- }
- p_dev_rec->link_key_changed = FALSE;
- /* After connection is established we perform security if we do not know */
- /* the name, or if we are originator because some procedure can have */
- /* been scheduled while connection was down */
- BTM_TRACE_DEBUG ("is_originator:%d \n", p_dev_rec->is_originator);
- if (!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN) || p_dev_rec->is_originator) {
- if ((res = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED) {
- btm_sec_dev_rec_cback_event (p_dev_rec, res, FALSE);
- }
- }
- return;
- }
- /*******************************************************************************
- **
- ** Function btm_sec_disconnect
- **
- ** Description This function is called to disconnect HCI link
- **
- ** Returns btm status
- **
- *******************************************************************************/
- tBTM_STATUS btm_sec_disconnect (UINT16 handle, UINT8 reason)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
- /* In some weird race condition we may not have a record */
- if (!p_dev_rec) {
- btsnd_hcic_disconnect (handle, reason);
- return (BTM_SUCCESS);
- }
- /* If we are in the process of bonding we need to tell client that auth failed */
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)
- && (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) ) {
- /* we are currently doing bonding. Link will be disconnected when done */
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_DISC_WHEN_DONE;
- return (BTM_BUSY);
- }
- return (btm_sec_send_hci_disconnect(p_dev_rec, reason, handle));
- }
- /*******************************************************************************
- **
- ** Function btm_sec_disconnected
- **
- ** Description This function is when a connection to the peer device is
- ** dropped
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_disconnected (UINT16 handle, UINT8 reason)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
- UINT8 old_pairing_flags = btm_cb.pairing_flags;
- int result = HCI_ERR_AUTH_FAILURE;
- tBTM_SEC_CALLBACK *p_callback = NULL;
- tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
- /* If page was delayed for disc complete, can do it now */
- btm_cb.discing = FALSE;
- #if (CLASSIC_BT_INCLUDED == TRUE)
- btm_acl_resubmit_page();
- #endif
- if (!p_dev_rec) {
- return;
- }
- p_dev_rec->enc_init_by_we = FALSE;
- transport = (handle == p_dev_rec->hci_handle) ? BT_TRANSPORT_BR_EDR : BT_TRANSPORT_LE;
- p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
- #if BTM_DISC_DURING_RS == TRUE
- p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
- #endif
- /* clear unused flags */
- p_dev_rec->sm4 &= BTM_SM4_TRUE;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- uint8_t *bd_addr = (uint8_t *)p_dev_rec->bd_addr;
- BTM_TRACE_EVENT("%s sec_req:x%x state:%s reason:%d bd_addr:%02x:%02x:%02x:%02x:%02x:%02x"
- " remote_name:%s\n", __func__, p_dev_rec->security_required, btm_pair_state_descr(btm_cb.pairing_state),
- reason, bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5], p_dev_rec->sec_bd_name);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- BTM_TRACE_EVENT("%s before update sec_flags=0x%x\n", __func__, p_dev_rec->sec_flags);
- /* If we are in the process of bonding we need to tell client that auth failed */
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)) {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_KNOWN;
- if (btm_cb.api.p_auth_complete_callback) {
- /* If the disconnection reason is REPEATED_ATTEMPTS,
- send this error message to complete callback function
- to display the error message of Repeated attempts.
- All others, send HCI_ERR_AUTH_FAILURE. */
- if (reason == HCI_ERR_REPEATED_ATTEMPTS) {
- result = HCI_ERR_REPEATED_ATTEMPTS;
- } else if (old_pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
- result = HCI_ERR_HOST_REJECT_SECURITY;
- }
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, result);
- }
- }
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, HCI_SUCCESS);
- /* see sec_flags processing in btm_acl_removed */
- if (transport == BT_TRANSPORT_LE) {
- p_dev_rec->ble_hci_handle = BTM_SEC_INVALID_HANDLE;
- p_dev_rec->sec_flags &= ~(BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED);
- p_dev_rec->enc_key_size = 0;
- } else
- #endif
- {
- p_dev_rec->hci_handle = BTM_SEC_INVALID_HANDLE;
- p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
- | BTM_SEC_ROLE_SWITCHED | BTM_SEC_16_DIGIT_PIN_AUTHED);
- }
- #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING_BOTH) {
- p_dev_rec->sec_state = (transport == BT_TRANSPORT_LE) ?
- BTM_SEC_STATE_DISCONNECTING : BTM_SEC_STATE_DISCONNECTING_BLE;
- return;
- }
- #endif
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
- p_dev_rec->security_required = BTM_SEC_NONE;
- p_callback = p_dev_rec->p_callback;
- /* if security is pending, send callback to clean up the security state */
- if (p_callback) {
- p_dev_rec->p_callback = NULL; /* when the peer device time out the authentication before
- we do, this call back must be reset here */
- (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, BTM_ERR_PROCESSING);
- }
- BTM_TRACE_EVENT("%s after update sec_flags=0x%x\n", __func__, p_dev_rec->sec_flags);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_link_key_notification
- **
- ** Description This function is called when a new connection link key is
- ** generated
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_type)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_bda);
- BOOLEAN we_are_bonding = FALSE;
- BOOLEAN ltk_derived_lk = FALSE;
- BTM_TRACE_EVENT ("btm_sec_link_key_notification() BDA:%04x%08x, TYPE: %d\n",
- (p_bda[0] << 8) + p_bda[1], (p_bda[2] << 24) + (p_bda[3] << 16) + (p_bda[4] << 8) + p_bda[5],
- key_type);
- if ((key_type >= BTM_LTK_DERIVED_LKEY_OFFSET + BTM_LKEY_TYPE_COMBINATION) &&
- (key_type <= BTM_LTK_DERIVED_LKEY_OFFSET + BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- ltk_derived_lk = TRUE;
- key_type -= BTM_LTK_DERIVED_LKEY_OFFSET;
- }
- /* If connection was made to do bonding restore link security if changed */
- btm_restore_mode();
- /* Store the previous state of secure connection as current state. Since
- * this is the first encounter with the remote device, whatever the remote
- * device's SC state is, it cannot lower the SC level from this. */
- p_dev_rec->remote_secure_connection_previous_state = p_dev_rec->remote_supports_secure_connections;
- if (p_dev_rec->remote_supports_secure_connections) {
- BTM_TRACE_EVENT ("Remote device supports Secure Connection");
- } else {
- BTM_TRACE_EVENT ("Remote device does not support Secure Connection");
- }
- if (key_type != BTM_LKEY_TYPE_CHANGED_COMB) {
- p_dev_rec->link_key_type = key_type;
- }
- p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
- #if (CLASSIC_BT_INCLUDED == TRUE)
- btm_sec_update_legacy_auth_state(btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR), BTM_ACL_LEGACY_AUTH_NONE);
- #endif
- /*
- * Until this point in time, we do not know if MITM was enabled, hence we
- * add the extended security flag here.
- */
- if (p_dev_rec->pin_code_length >= 16 ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB ||
- p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) {
- p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
- }
- #if (BLE_INCLUDED == TRUE)
- /* BR/EDR connection, update the encryption key size to be 16 as always */
- p_dev_rec->enc_key_size = 16;
- #endif
- memcpy (p_dev_rec->link_key, p_link_key, LINK_KEY_LEN);
- if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
- && (memcmp (btm_cb.pairing_bda, p_bda, BD_ADDR_LEN) == 0) ) {
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
- we_are_bonding = TRUE;
- } else {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- }
- }
- /* save LTK derived LK no matter what */
- if (ltk_derived_lk) {
- if (btm_cb.api.p_link_key_callback) {
- BTM_TRACE_DEBUG ("%s() Save LTK derived LK (key_type = %d)\n",
- __FUNCTION__, p_dev_rec->link_key_type);
- (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name,
- p_link_key, p_dev_rec->link_key_type,
- p_dev_rec->remote_supports_secure_connections);
- }
- } else {
- if ((p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256) ||
- (p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- p_dev_rec->new_encryption_key_is_p256 = TRUE;
- BTM_TRACE_DEBUG ("%s set new_encr_key_256 to %d\n",
- __func__, p_dev_rec->new_encryption_key_is_p256);
- }
- }
- /* If name is not known at this point delay calling callback until the name is */
- /* resolved. Unless it is a HID Device and we really need to send all link keys. */
- if ((!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN)
- && ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) != BTM_COD_MAJOR_PERIPHERAL))
- && !ltk_derived_lk) {
- BTM_TRACE_EVENT ("btm_sec_link_key_notification() Delayed BDA: %08x%04x Type:%d\n",
- (p_bda[0] << 24) + (p_bda[1] << 16) + (p_bda[2] << 8) + p_bda[3],
- (p_bda[4] << 8) + p_bda[5], key_type);
- p_dev_rec->link_key_not_sent = TRUE;
- /* If it is for bonding nothing else will follow, so we need to start name resolution */
- if (we_are_bonding) {
- if (!(btsnd_hcic_rmt_name_req (p_bda, HCI_PAGE_SCAN_REP_MODE_R1, HCI_MANDATARY_PAGE_SCAN_MODE, 0))) {
- btm_inq_rmt_name_failed();
- }
- }
- BTM_TRACE_EVENT ("rmt_io_caps:%d, sec_flags:x%x, dev_class[1]:x%02x\n", p_dev_rec->rmt_io_caps, p_dev_rec->sec_flags, p_dev_rec->dev_class[1])
- return;
- }
- /* If its not us who perform authentication, we should tell stackserver */
- /* that some authentication has been completed */
- /* This is required when different entities receive link notification and auth complete */
- if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)
- /* for derived key, always send authentication callback for BR channel */
- || ltk_derived_lk) {
- if (btm_cb.api.p_auth_complete_callback) {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_SUCCESS);
- }
- }
- /* We will save link key only if the user authorized it - BTE report link key in all cases */
- #ifdef BRCM_NONE_BTE
- if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED)
- #endif
- {
- if (btm_cb.api.p_link_key_callback) {
- if (ltk_derived_lk) {
- BTM_TRACE_DEBUG ("btm_sec_link_key_notification() LTK derived LK is saved already"
- " (key_type = %d)\n", p_dev_rec->link_key_type);
- } else {
- (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name,
- p_link_key, p_dev_rec->link_key_type,
- p_dev_rec->remote_supports_secure_connections);
- }
- }
- }
- }
- /*******************************************************************************
- **
- ** Function btm_sec_link_key_request
- **
- ** Description This function is called when controller requests link key
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- void btm_sec_link_key_request (UINT8 *p_bda)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_bda);
- BTM_TRACE_EVENT ("btm_sec_link_key_request() BDA: %02x:%02x:%02x:%02x:%02x:%02x\n",
- p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]);
- if ( (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_PIN_REQ) &&
- (btm_cb.collision_start_time != 0) &&
- (memcmp (btm_cb.p_collided_dev_rec->bd_addr, p_bda, BD_ADDR_LEN) == 0) ) {
- BTM_TRACE_EVENT ("btm_sec_link_key_request() rejecting link key req "
- "State: %d START_TIMEOUT : %d\n",
- btm_cb.pairing_state, btm_cb.collision_start_time);
- btsnd_hcic_link_key_neg_reply (p_bda);
- return;
- }
- if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) {
- btsnd_hcic_link_key_req_reply (p_bda, p_dev_rec->link_key);
- return;
- }
- /* Notify L2CAP to increase timeout */
- l2c_pin_code_request (p_bda);
- /* The link key is not in the database and it is not known to the manager */
- btsnd_hcic_link_key_neg_reply (p_bda);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_pairing_timeout
- **
- ** Description This function is called when host does not provide PIN
- ** within requested time
- **
- ** Returns Pointer to the TLE struct
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_pairing_timeout (TIMER_LIST_ENT *p_tle)
- {
- tBTM_CB *p_cb = &btm_cb;
- tBTM_SEC_DEV_REC *p_dev_rec;
- #if BTM_OOB_INCLUDED == TRUE
- #if (BTM_LOCAL_IO_CAPS == BTM_IO_CAP_NONE)
- tBTM_AUTH_REQ auth_req = BTM_AUTH_AP_NO;
- #else
- tBTM_AUTH_REQ auth_req = BTM_AUTH_AP_YES;
- #endif
- #endif
- UINT8 name[2];
- UNUSED(p_tle);
- p_cb->pairing_tle.param = 0;
- /* Coverity: FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
- /* coverity[UNUSED_VALUE] pointer p_dev_rec is actually used several times... This is a Coverity false-positive, i.e. a fake issue.
- */
- p_dev_rec = btm_find_dev (p_cb->pairing_bda);
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("btm_sec_pairing_timeout() State: %s Flags: %u\n",
- btm_pair_state_descr(p_cb->pairing_state), p_cb->pairing_flags);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- switch (p_cb->pairing_state) {
- case BTM_PAIR_STATE_WAIT_PIN_REQ:
- btm_sec_bond_cancel_complete();
- break;
- case BTM_PAIR_STATE_WAIT_LOCAL_PIN:
- if ( (btm_cb.pairing_flags & BTM_PAIR_FLAGS_PRE_FETCH_PIN) == 0) {
- btsnd_hcic_pin_code_neg_reply (p_cb->pairing_bda);
- }
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- /* We need to notify the UI that no longer need the PIN */
- if (btm_cb.api.p_auth_complete_callback) {
- if (p_dev_rec == NULL) {
- name[0] = 0;
- (*btm_cb.api.p_auth_complete_callback) (p_cb->pairing_bda,
- NULL,
- name, HCI_ERR_CONNECTION_TOUT);
- } else {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_ERR_CONNECTION_TOUT);
- }
- }
- break;
- case BTM_PAIR_STATE_WAIT_NUMERIC_CONFIRM:
- btsnd_hcic_user_conf_reply (p_cb->pairing_bda, FALSE);
- /* btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE); */
- break;
- #if (BT_SSP_INCLUDED == TRUE)
- case BTM_PAIR_STATE_KEY_ENTRY:
- btsnd_hcic_user_passkey_neg_reply(p_cb->pairing_bda);
- /* btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE); */
- break;
- #endif /* !BTM_IO_CAP_NONE */
- #if BTM_OOB_INCLUDED == TRUE
- case BTM_PAIR_STATE_WAIT_LOCAL_IOCAPS:
- if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
- auth_req |= BTM_AUTH_DD_BOND;
- }
- btsnd_hcic_io_cap_req_reply (p_cb->pairing_bda, btm_cb.devcb.loc_io_caps,
- BTM_OOB_NONE, auth_req);
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- break;
- case BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP:
- btsnd_hcic_rem_oob_neg_reply (p_cb->pairing_bda);
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- break;
- #endif /* BTM_OOB_INCLUDED */
- case BTM_PAIR_STATE_WAIT_DISCONNECT:
- /* simple pairing failed. Started a 1-sec timer at simple pairing complete.
- * now it's time to tear down the ACL link*/
- if (p_dev_rec == NULL) {
- BTM_TRACE_ERROR ("btm_sec_pairing_timeout() BTM_PAIR_STATE_WAIT_DISCONNECT unknown BDA: %08x%04x\n",
- (p_cb->pairing_bda[0] << 24) + (p_cb->pairing_bda[1] << 16) + (p_cb->pairing_bda[2] << 8) + p_cb->pairing_bda[3],
- (p_cb->pairing_bda[4] << 8) + p_cb->pairing_bda[5]);
- break;
- }
- btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_AUTH_FAILURE, p_dev_rec->hci_handle);
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- break;
- case BTM_PAIR_STATE_WAIT_AUTH_COMPLETE:
- case BTM_PAIR_STATE_GET_REM_NAME:
- /* We need to notify the UI that timeout has happened while waiting for authentication*/
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- if (btm_cb.api.p_auth_complete_callback) {
- if (p_dev_rec == NULL) {
- name[0] = 0;
- (*btm_cb.api.p_auth_complete_callback) (p_cb->pairing_bda,
- NULL,
- name, HCI_ERR_CONNECTION_TOUT);
- } else {
- (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, HCI_ERR_CONNECTION_TOUT);
- }
- }
- break;
- default:
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_WARNING ("btm_sec_pairing_timeout() not processed state: %s\n", btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
- break;
- }
- }
- #if (CLASSIC_BT_INCLUDED == TRUE)
- /*******************************************************************************
- **
- ** Function btm_sec_pin_code_request
- **
- ** Description This function is called when controller requests PIN code
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- void btm_sec_pin_code_request (UINT8 *p_bda)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_CB *p_cb = &btm_cb;
- #ifdef PORCHE_PAIRING_CONFLICT
- UINT8 default_pin_code_len = 4;
- PIN_CODE default_pin_code = {0x30, 0x30, 0x30, 0x30};
- #endif
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("btm_sec_pin_code_request() State: %s, BDA:%04x%08x\n",
- btm_pair_state_descr(btm_cb.pairing_state),
- (p_bda[0] << 8) + p_bda[1], (p_bda[2] << 24) + (p_bda[3] << 16) + (p_bda[4] << 8) + p_bda[5] );
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) {
- if ( (memcmp (p_bda, btm_cb.pairing_bda, BD_ADDR_LEN) == 0) &&
- (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_AUTH_COMPLETE) ) {
- /* fake this out - porshe carkit issue - */
- // btm_cb.pairing_state = BTM_PAIR_STATE_IDLE;
- if (! btm_cb.pin_code_len_saved) {
- btsnd_hcic_pin_code_neg_reply (p_bda);
- return;
- } else {
- btsnd_hcic_pin_code_req_reply (p_bda, btm_cb.pin_code_len_saved, p_cb->pin_code);
- return;
- }
- } else if ((btm_cb.pairing_state != BTM_PAIR_STATE_WAIT_PIN_REQ)
- || memcmp (p_bda, btm_cb.pairing_bda, BD_ADDR_LEN) != 0) {
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_WARNING ("btm_sec_pin_code_request() rejected - state: %s\n",
- btm_pair_state_descr(btm_cb.pairing_state));
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- #ifdef PORCHE_PAIRING_CONFLICT
- /* reply pin code again due to counter in_rand when local initiates pairing */
- BTM_TRACE_EVENT ("btm_sec_pin_code_request from remote dev. for local initiated pairing\n");
- if (! btm_cb.pin_code_len_saved) {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- btsnd_hcic_pin_code_req_reply (p_bda, default_pin_code_len, default_pin_code);
- } else {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- btsnd_hcic_pin_code_req_reply (p_bda, btm_cb.pin_code_len_saved, p_cb->pin_code);
- }
- #else
- btsnd_hcic_pin_code_neg_reply (p_bda);
- #endif
- return;
- }
- }
- p_dev_rec = btm_find_or_alloc_dev (p_bda);
- /* received PIN code request. must be non-sm4 */
- p_dev_rec->sm4 = BTM_SM4_KNOWN;
- if (btm_cb.pairing_state == BTM_PAIR_STATE_IDLE) {
- memcpy (btm_cb.pairing_bda, p_bda, BD_ADDR_LEN);
- btm_cb.pairing_flags = BTM_PAIR_FLAGS_PEER_STARTED_DD;
- /* Make sure we reset the trusted mask to help against attacks */
- BTM_SEC_CLR_TRUSTED_DEVICE(p_dev_rec->trusted_mask);
- }
- if (!p_cb->pairing_disabled && (p_cb->cfg.pin_type == HCI_PIN_TYPE_FIXED)) {
- BTM_TRACE_EVENT ("btm_sec_pin_code_request fixed pin replying\n");
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- btsnd_hcic_pin_code_req_reply (p_bda, p_cb->cfg.pin_code_len, p_cb->cfg.pin_code);
- return;
- }
- /* Use the connecting device's CoD for the connection */
- if ( (!memcmp (p_bda, p_cb->connecting_bda, BD_ADDR_LEN))
- && (p_cb->connecting_dc[0] || p_cb->connecting_dc[1] || p_cb->connecting_dc[2]) ) {
- memcpy (p_dev_rec->dev_class, p_cb->connecting_dc, DEV_CLASS_LEN);
- }
- /* We could have started connection after asking user for the PIN code */
- if (btm_cb.pin_code_len != 0) {
- BTM_TRACE_EVENT ("btm_sec_pin_code_request bonding sending reply\n");
- btsnd_hcic_pin_code_req_reply (p_bda, btm_cb.pin_code_len, p_cb->pin_code);
- #ifdef PORCHE_PAIRING_CONFLICT
- btm_cb.pin_code_len_saved = btm_cb.pin_code_len;
- #endif
- /* Mark that we forwarded received from the user PIN code */
- btm_cb.pin_code_len = 0;
- /* We can change mode back right away, that other connection being established */
- /* is not forced to be secure - found a FW issue, so we can not do this
- btm_restore_mode(); */
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
- }
- /* If pairing disabled OR (no PIN callback and not bonding) */
- /* OR we could not allocate entry in the database reject pairing request */
- else if (p_cb->pairing_disabled
- || (p_cb->api.p_pin_callback == NULL)
- /* OR Microsoft keyboard can for some reason try to establish connection */
- /* the only thing we can do here is to shut it up. Normally we will be originator */
- /* for keyboard bonding */
- || (!p_dev_rec->is_originator
- && ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) == BTM_COD_MAJOR_PERIPHERAL)
- && (p_dev_rec->dev_class[2] & BTM_COD_MINOR_KEYBOARD)) ) {
- BTM_TRACE_WARNING("btm_sec_pin_code_request(): Pairing disabled:%d; PIN callback:%p, Dev Rec:%p!\n",
- p_cb->pairing_disabled, p_cb->api.p_pin_callback, p_dev_rec);
- btsnd_hcic_pin_code_neg_reply (p_bda);
- }
- /* Notify upper layer of PIN request and start expiration timer */
- else {
- btm_cb.pin_code_len_saved = 0;
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_LOCAL_PIN);
- /* Pin code request can not come at the same time as connection request */
- memcpy (p_cb->connecting_bda, p_bda, BD_ADDR_LEN);
- memcpy (p_cb->connecting_dc, p_dev_rec->dev_class, DEV_CLASS_LEN);
- BTM_TRACE_EVENT ("btm_sec_pin_code_request going for callback\n");
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD;
- if (p_cb->api.p_pin_callback) {
- (*p_cb->api.p_pin_callback) (p_bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name,
- (p_dev_rec->p_cur_service == NULL) ? FALSE
- : (p_dev_rec->p_cur_service->security_flags
- & BTM_SEC_IN_MIN_16_DIGIT_PIN));
- }
- }
- return;
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_update_clock_offset
- **
- ** Description This function is called to update clock offset
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_update_clock_offset (UINT16 handle, UINT16 clock_offset)
- {
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_INQ_INFO *p_inq_info;
- if ((p_dev_rec = btm_find_dev_by_handle (handle)) == NULL) {
- return;
- }
- p_dev_rec->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
- if ((p_inq_info = BTM_InqDbRead(p_dev_rec->bd_addr)) == NULL) {
- return;
- }
- p_inq_info->results.clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
- }
- /******************************************************************
- ** S T A T I C F U N C T I O N S
- *******************************************************************/
- /*******************************************************************************
- **
- ** Function btm_sec_execute_procedure
- **
- ** Description This function is called to start required security
- ** procedure. There is a case when multiplexing protocol
- ** calls this function on the originating side, connection to
- ** the peer will not be established. This function in this
- ** case performs only authorization.
- **
- ** Returns BTM_SUCCESS - permission is granted
- ** BTM_CMD_STARTED - in process
- ** BTM_NO_RESOURCES - permission declined
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- BTM_TRACE_EVENT ("btm_sec_execute_procedure: Required:0x%x Flags:0x%x State:%d\n",
- p_dev_rec->security_required, p_dev_rec->sec_flags, p_dev_rec->sec_state);
- /* There is a chance that we are getting name. Wait until done. */
- if (p_dev_rec->sec_state != 0) {
- return (BTM_CMD_STARTED);
- }
- /* If any security is required, get the name first */
- if (!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN)
- && (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)) {
- BTM_TRACE_EVENT ("Security Manager: Start get name\n");
- if (!btm_sec_start_get_name (p_dev_rec)) {
- return (BTM_NO_RESOURCES);
- }
- return (BTM_CMD_STARTED);
- }
- /* If connection is not authenticated and authentication is required */
- /* start authentication and return PENDING to the caller */
- if ((((!(p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))
- && (( p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE))
- || (!p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_IN_AUTHENTICATE))))
- || (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED)
- && (!p_dev_rec->is_originator
- && (p_dev_rec->security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN))))
- && (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)) {
- /*
- * We rely on BTM_SEC_16_DIGIT_PIN_AUTHED being set if MITM is in use,
- * as 16 DIGIT is only needed if MITM is not used. Unfortunately, the
- * BTM_SEC_AUTHENTICATED is used for both MITM and non-MITM
- * authenticated connections, hence we cannot distinguish here.
- */
- #if (L2CAP_UCD_INCLUDED == TRUE)
- /* if incoming UCD packet, discard it */
- if ( !p_dev_rec->is_originator && (p_dev_rec->is_ucd == TRUE )) {
- return (BTM_FAILED_ON_SECURITY);
- }
- #endif
- BTM_TRACE_EVENT ("Security Manager: Start authentication\n");
- /*
- * If we do have a link-key, but we end up here because we need an
- * upgrade, then clear the link-key known and authenticated flag before
- * restarting authentication.
- * WARNING: If the controller has link-key, it is optional and
- * recommended for the controller to send a Link_Key_Request.
- * In case we need an upgrade, the only alternative would be to delete
- * the existing link-key. That could lead to very bad user experience
- * or even IOP issues, if a reconnect causes a new connection that
- * requires an upgrade.
- */
- if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)
- && (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED)
- && (!p_dev_rec->is_originator && (p_dev_rec->security_required
- & BTM_SEC_IN_MIN_16_DIGIT_PIN)))) {
- p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED
- | BTM_SEC_AUTHENTICATED);
- }
- if (!btm_sec_start_authentication (p_dev_rec)) {
- return (BTM_NO_RESOURCES);
- }
- return (BTM_CMD_STARTED);
- }
- /* If connection is not encrypted and encryption is required */
- /* start encryption and return PENDING to the caller */
- if (!(p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)
- && (( p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_OUT_ENCRYPT))
- || (!p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_IN_ENCRYPT)))
- && (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)) {
- #if (L2CAP_UCD_INCLUDED == TRUE)
- /* if incoming UCD packet, discard it */
- if ( !p_dev_rec->is_originator && (p_dev_rec->is_ucd == TRUE )) {
- return (BTM_FAILED_ON_SECURITY);
- }
- #endif
- BTM_TRACE_EVENT ("Security Manager: Start encryption\n");
- if (!btm_sec_start_encryption (p_dev_rec)) {
- return (BTM_NO_RESOURCES);
- }
- return (BTM_CMD_STARTED);
- }
- if ((p_dev_rec->security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- BTM_TRACE_EVENT("%s: Security Manager: SC only service, but link key type is 0x%02x -"
- "security failure\n", __FUNCTION__, p_dev_rec->link_key_type);
- return (BTM_FAILED_ON_SECURITY);
- }
- /* If connection is not authorized and authorization is required */
- /* start authorization and return PENDING to the caller */
- if (!(p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED)
- && (( p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_OUT_AUTHORIZE))
- || (!p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_IN_AUTHORIZE)))) {
- BTM_TRACE_EVENT ("service id:%d, is trusted:%d\n",
- p_dev_rec->p_cur_service->service_id,
- (BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask,
- p_dev_rec->p_cur_service->service_id)));
- if ((btm_sec_are_all_trusted(p_dev_rec->trusted_mask) == FALSE) &&
- (p_dev_rec->p_cur_service->service_id < BTM_SEC_MAX_SERVICES) &&
- (BTM_SEC_IS_SERVICE_TRUSTED(p_dev_rec->trusted_mask,
- p_dev_rec->p_cur_service->service_id) == FALSE)) {
- BTM_TRACE_EVENT ("Security Manager: Start authorization\n");
- return (btm_sec_start_authorization (p_dev_rec));
- }
- }
- /* All required security procedures already established */
- p_dev_rec->security_required &= ~(BTM_SEC_OUT_AUTHORIZE | BTM_SEC_IN_AUTHORIZE |
- BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_IN_AUTHENTICATE |
- BTM_SEC_OUT_ENCRYPT | BTM_SEC_IN_ENCRYPT |
- BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER |
- BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE);
- BTM_TRACE_EVENT ("Security Manager: trusted:0x%04x%04x\n", p_dev_rec->trusted_mask[1], p_dev_rec->trusted_mask[0]);
- BTM_TRACE_EVENT ("Security Manager: access granted\n");
- return (BTM_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_start_get_name
- **
- ** Description This function is called to start get name procedure
- **
- ** Returns TRUE if started
- **
- *******************************************************************************/
- static BOOLEAN btm_sec_start_get_name (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- UINT8 tempstate = p_dev_rec->sec_state;
- p_dev_rec->sec_state = BTM_SEC_STATE_GETTING_NAME;
- /* Device should be connected, no need to provide correct page params */
- /* 0 and NULL are as timeout and callback params because they are not used in security get name case */
- if ((btm_initiate_rem_name (p_dev_rec->bd_addr, NULL, BTM_RMT_NAME_SEC,
- 0, NULL)) != BTM_CMD_STARTED) {
- p_dev_rec->sec_state = tempstate;
- return (FALSE);
- }
- return (TRUE);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_start_authentication
- **
- ** Description This function is called to start authentication
- **
- ** Returns TRUE if started
- **
- *******************************************************************************/
- static BOOLEAN btm_sec_start_authentication (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
- return (btsnd_hcic_auth_request (p_dev_rec->hci_handle));
- }
- /*******************************************************************************
- **
- ** Function btm_sec_start_encryption
- **
- ** Description This function is called to start encryption
- **
- ** Returns TRUE if started
- **
- *******************************************************************************/
- static BOOLEAN btm_sec_start_encryption (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- if (!btsnd_hcic_set_conn_encrypt (p_dev_rec->hci_handle, TRUE)) {
- return (FALSE);
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
- return (TRUE);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_start_authorization
- **
- ** Description This function is called to start authorization
- **
- ** Returns TRUE if started
- **
- *******************************************************************************/
- static UINT8 btm_sec_start_authorization (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- UINT8 result;
- UINT8 *p_service_name = NULL;
- UINT8 service_id;
- if ((p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN)
- || (p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE)) {
- if (!btm_cb.api.p_authorize_callback) {
- return (BTM_MODE_UNSUPPORTED);
- }
- if (p_dev_rec->p_cur_service) {
- #if BTM_SEC_SERVICE_NAME_LEN > 0
- if (p_dev_rec->is_originator) {
- p_service_name = p_dev_rec->p_cur_service->orig_service_name;
- } else {
- p_service_name = p_dev_rec->p_cur_service->term_service_name;
- }
- #endif
- service_id = p_dev_rec->p_cur_service->service_id;
- } else {
- service_id = 0;
- }
- /* Send authorization request if not already sent during this service connection */
- if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
- || p_dev_rec->last_author_service_id != service_id) {
- p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING;
- result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr,
- p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name,
- p_service_name,
- service_id,
- p_dev_rec->is_originator);
- }
- else { /* Already authorized once for this L2CAP bringup */
- BTM_TRACE_DEBUG ("btm_sec_start_authorization: (Ignoring extra Authorization prompt for service %d)\n", service_id);
- return (BTM_SUCCESS);
- }
- if (result == BTM_SUCCESS) {
- p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED;
- /* Save the currently authorized service in case we are asked again by another multiplexer layer */
- if (!p_dev_rec->is_originator) {
- p_dev_rec->last_author_service_id = service_id;
- }
- p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
- }
- return (result);
- }
- btm_sec_start_get_name (p_dev_rec);
- return (BTM_CMD_STARTED);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_are_all_trusted
- **
- ** Description This function is called check if all services are trusted
- **
- ** Returns TRUE if all are trusted, otherwise FALSE
- **
- *******************************************************************************/
- BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[])
- {
- UINT32 trusted_inx;
- for (trusted_inx = 0; trusted_inx < BTM_SEC_SERVICE_ARRAY_SIZE; trusted_inx++) {
- if (p_mask[trusted_inx] != BTM_SEC_TRUST_ALL) {
- return (FALSE);
- }
- }
- return (TRUE);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_find_first_serv
- **
- ** Description Look for the first record in the service database
- ** with specified PSM
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- tBTM_SEC_SERV_REC *btm_sec_find_first_serv (CONNECTION_TYPE conn_type, UINT16 psm)
- {
- tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
- int i;
- BOOLEAN is_originator;
- #if (L2CAP_UCD_INCLUDED == TRUE)
- if ( conn_type & CONNECTION_TYPE_ORIG_MASK ) {
- is_originator = TRUE;
- } else {
- is_originator = FALSE;
- }
- #else
- is_originator = conn_type;
- #endif
- if (is_originator && btm_cb.p_out_serv && btm_cb.p_out_serv->psm == psm) {
- /* If this is outgoing connection and the PSM matches p_out_serv,
- * use it as the current service */
- return btm_cb.p_out_serv;
- }
- /* otherwise, just find the first record with the specified PSM */
- for (i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++) {
- if ( (p_serv_rec->security_flags & BTM_SEC_IN_USE) && (p_serv_rec->psm == psm) ) {
- return (p_serv_rec);
- }
- }
- return (NULL);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_find_next_serv
- **
- ** Description Look for the next record in the service database
- ** with specified PSM
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- static tBTM_SEC_SERV_REC *btm_sec_find_next_serv (tBTM_SEC_SERV_REC *p_cur)
- {
- tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
- int i;
- for (i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++) {
- if ((p_serv_rec->security_flags & BTM_SEC_IN_USE)
- && (p_serv_rec->psm == p_cur->psm) ) {
- if (p_cur != p_serv_rec) {
- return (p_serv_rec);
- }
- }
- }
- return (NULL);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_find_mx_serv
- **
- ** Description Look for the record in the service database with specified
- ** PSM and multiplexor channel information
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm,
- UINT32 mx_proto_id, UINT32 mx_chan_id)
- {
- tBTM_SEC_SERV_REC *p_out_serv = btm_cb.p_out_serv;
- tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
- int i;
- BTM_TRACE_DEBUG ("%s()\n", __func__);
- if (is_originator && p_out_serv && p_out_serv->psm == psm
- && p_out_serv->mx_proto_id == mx_proto_id
- && p_out_serv->orig_mx_chan_id == mx_chan_id) {
- /* If this is outgoing connection and the parameters match p_out_serv,
- * use it as the current service */
- return btm_cb.p_out_serv;
- }
- /* otherwise, the old way */
- for (i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++) {
- if ((p_serv_rec->security_flags & BTM_SEC_IN_USE)
- && (p_serv_rec->psm == psm)
- && (p_serv_rec->mx_proto_id == mx_proto_id)
- && (( is_originator && (p_serv_rec->orig_mx_chan_id == mx_chan_id))
- || (!is_originator && (p_serv_rec->term_mx_chan_id == mx_chan_id)))) {
- return (p_serv_rec);
- }
- }
- return (NULL);
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_collision_timeout
- **
- ** Description Encryption could not start because of the collision
- ** try to do it again
- **
- ** Returns Pointer to the TLE struct
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_collision_timeout (TIMER_LIST_ENT *p_tle)
- {
- UNUSED(p_tle);
- BTM_TRACE_EVENT ("%s()\n", __func__);
- btm_cb.sec_collision_tle.param = 0;
- tBTM_STATUS status = btm_sec_execute_procedure (btm_cb.p_collided_dev_rec);
- /* If result is pending reply from the user or from the device is pending */
- if (status != BTM_CMD_STARTED) {
- /* There is no next procedure or start of procedure failed, notify the waiting layer */
- btm_sec_dev_rec_cback_event (btm_cb.p_collided_dev_rec, status, FALSE);
- }
- }
- /*******************************************************************************
- **
- ** Function btm_send_link_key_notif
- **
- ** Description This function is called when controller requests link key
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- static void btm_send_link_key_notif (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- if (btm_cb.api.p_link_key_callback) {
- (*btm_cb.api.p_link_key_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, p_dev_rec->link_key,
- p_dev_rec->link_key_type,
- p_dev_rec->remote_supports_secure_connections);
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function BTM_ReadTrustedMask
- **
- ** Description Get trusted mask for the peer device
- **
- ** Parameters: bd_addr - Address of the device
- **
- ** Returns NULL, if the device record is not found.
- ** otherwise, the trusted mask
- **
- *******************************************************************************/
- UINT32 *BTM_ReadTrustedMask (BD_ADDR bd_addr)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
- if (p_dev_rec != NULL) {
- return (p_dev_rec->trusted_mask);
- }
- return NULL;
- }
- /*******************************************************************************
- **
- ** Function btm_restore_mode
- **
- ** Description This function returns the security mode to previous setting
- ** if it was changed during bonding.
- **
- **
- ** Parameters: void
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_restore_mode(void)
- {
- if (btm_cb.security_mode_changed) {
- btm_cb.security_mode_changed = FALSE;
- BTM_TRACE_DEBUG("%s() Auth enable -> %d\n", __func__, (btm_cb.security_mode == BTM_SEC_MODE_LINK));
- btsnd_hcic_write_auth_enable ((UINT8)(btm_cb.security_mode == BTM_SEC_MODE_LINK));
- }
- #if (CLASSIC_BT_INCLUDED == TRUE)
- if (btm_cb.pin_type_changed) {
- btm_cb.pin_type_changed = FALSE;
- btsnd_hcic_write_pin_type (btm_cb.cfg.pin_type);
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_find_dev_by_sec_state
- **
- ** Description Look for the record in the device database for the device
- ** which is being authenticated or encrypted
- **
- ** Returns Pointer to the record or NULL
- **
- *******************************************************************************/
- tBTM_SEC_DEV_REC *btm_sec_find_dev_by_sec_state (UINT8 state)
- {
- #if (SMP_INCLUDED == TRUE)
- tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
- for (int i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
- if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
- && (p_dev_rec->sec_state == state)) {
- return (p_dev_rec);
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- return (NULL);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_change_pairing_state
- **
- ** Description This function is called to change pairing state
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static void btm_sec_change_pairing_state (tBTM_PAIRING_STATE new_state)
- {
- tBTM_PAIRING_STATE old_state = btm_cb.pairing_state;
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- BTM_TRACE_EVENT ("%s() Old: %s\n", __func__, btm_pair_state_descr(btm_cb.pairing_state));
- BTM_TRACE_EVENT ("%s() New: %s pairing_flags:0x%x\n\n", __func__,
- btm_pair_state_descr(new_state), btm_cb.pairing_flags);
- #endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
- btm_cb.pairing_state = new_state;
- if (new_state == BTM_PAIR_STATE_IDLE) {
- btu_stop_timer (&btm_cb.pairing_tle);
- btm_cb.pairing_flags = 0;
- #if (CLASSIC_BT_INCLUDED == TRUE)
- btm_cb.pin_code_len = 0;
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- /* Make sure the the lcb shows we are not bonding */
- l2cu_update_lcb_4_bonding (btm_cb.pairing_bda, FALSE);
- btm_restore_mode();
- btm_sec_check_pending_reqs();
- btm_inq_clear_ssp();
- memset (btm_cb.pairing_bda, 0xFF, BD_ADDR_LEN);
- } else {
- /* If transitionng out of idle, mark the lcb as bonding */
- if (old_state == BTM_PAIR_STATE_IDLE) {
- l2cu_update_lcb_4_bonding (btm_cb.pairing_bda, TRUE);
- }
- btm_cb.pairing_tle.param = (TIMER_PARAM_TYPE)btm_sec_pairing_timeout;
- btu_start_timer (&btm_cb.pairing_tle, BTU_TTYPE_USER_FUNC, BTM_SEC_TIMEOUT_VALUE);
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_pair_state_descr
- **
- ** Description Return state description for tracing
- **
- *******************************************************************************/
- #if (BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE)
- static char *btm_pair_state_descr (tBTM_PAIRING_STATE state)
- {
- #if (BT_TRACE_VERBOSE == TRUE)
- switch (state) {
- case BTM_PAIR_STATE_IDLE: return ("IDLE");
- case BTM_PAIR_STATE_GET_REM_NAME: return ("GET_REM_NAME");
- case BTM_PAIR_STATE_WAIT_PIN_REQ: return ("WAIT_PIN_REQ");
- case BTM_PAIR_STATE_WAIT_LOCAL_PIN: return ("WAIT_LOCAL_PIN");
- case BTM_PAIR_STATE_WAIT_NUMERIC_CONFIRM: return ("WAIT_NUM_CONFIRM");
- case BTM_PAIR_STATE_KEY_ENTRY: return ("KEY_ENTRY");
- case BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP: return ("WAIT_LOCAL_OOB_RSP");
- case BTM_PAIR_STATE_WAIT_LOCAL_IOCAPS: return ("WAIT_LOCAL_IOCAPS");
- case BTM_PAIR_STATE_INCOMING_SSP: return ("INCOMING_SSP");
- case BTM_PAIR_STATE_WAIT_AUTH_COMPLETE: return ("WAIT_AUTH_COMPLETE");
- case BTM_PAIR_STATE_WAIT_DISCONNECT: return ("WAIT_DISCONNECT");
- }
- return ("???");
- #else
- sprintf(btm_cb.state_temp_buffer, "%d", state);
- return (btm_cb.state_temp_buffer);
- #endif
- }
- #endif
- /*******************************************************************************
- **
- ** Function btm_sec_dev_rec_cback_event
- **
- ** Description This function calls the callback function with the given
- ** result and clear the callback function.
- **
- ** Parameters: void
- **
- *******************************************************************************/
- void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN is_le_transport)
- {
- tBTM_SEC_CALLBACK *p_callback = p_dev_rec->p_callback;
- if (p_dev_rec->p_callback) {
- p_dev_rec->p_callback = NULL;
- #if BLE_INCLUDED == TRUE
- if (is_le_transport) {
- (*p_callback) (p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE, p_dev_rec->p_ref_data, res);
- } else
- #endif
- {
- (*p_callback) (p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, p_dev_rec->p_ref_data, res);
- }
- }
- #if (SMP_INCLUDED == TRUE)
- btm_sec_check_pending_reqs();
- #endif ///SMP_INCLUDED == TRUE
- }
- /*******************************************************************************
- **
- ** Function btm_sec_queue_mx_request
- **
- ** Description Return state description for tracing
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static BOOLEAN btm_sec_queue_mx_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_orig,
- UINT32 mx_proto_id, UINT32 mx_chan_id,
- tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
- {
- tBTM_SEC_QUEUE_ENTRY *p_e = (tBTM_SEC_QUEUE_ENTRY *)osi_malloc (sizeof(tBTM_SEC_QUEUE_ENTRY));
- if (p_e) {
- p_e->psm = psm;
- p_e->is_orig = is_orig;
- p_e->p_callback = p_callback;
- p_e->p_ref_data = p_ref_data;
- p_e->mx_proto_id = mx_proto_id;
- p_e->mx_chan_id = mx_chan_id;
- p_e->transport = BT_TRANSPORT_BR_EDR;
- memcpy (p_e->bd_addr, bd_addr, BD_ADDR_LEN);
- BTM_TRACE_EVENT ("%s() PSM: 0x%04x Is_Orig: %u mx_proto_id: %u mx_chan_id: %u\n",
- __func__, psm, is_orig, mx_proto_id, mx_chan_id);
- fixed_queue_enqueue(btm_cb.sec_pending_q, p_e, FIXED_QUEUE_MAX_TIMEOUT);
- return (TRUE);
- }
- return (FALSE);
- }
- static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- BOOLEAN rv = FALSE;
- #if (CLASSIC_BT_INCLUDED == TRUE)
- UINT8 major = (UINT8)(p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK);
- UINT8 minor = (UINT8)(p_dev_rec->dev_class[2] & BTM_COD_MINOR_CLASS_MASK);
- rv = TRUE;
- if ((major == BTM_COD_MAJOR_AUDIO)
- && ((minor == BTM_COD_MINOR_CONFM_HANDSFREE) || (minor == BTM_COD_MINOR_CAR_AUDIO)) ) {
- BTM_TRACE_EVENT ("%s() Skipping pre-fetch PIN for carkit COD Major: 0x%02x Minor: 0x%02x\n",
- __func__, major, minor);
- if (btm_cb.security_mode_changed == FALSE) {
- btm_cb.security_mode_changed = TRUE;
- #ifdef APPL_AUTH_WRITE_EXCEPTION
- if (!(APPL_AUTH_WRITE_EXCEPTION)(p_dev_rec->bd_addr))
- #endif
- {
- btsnd_hcic_write_auth_enable (TRUE);
- }
- }
- } else {
- btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_LOCAL_PIN);
- /* If we got a PIN, use that, else try to get one */
- if (btm_cb.pin_code_len) {
- BTM_PINCodeReply (p_dev_rec->bd_addr, BTM_SUCCESS, btm_cb.pin_code_len, btm_cb.pin_code, p_dev_rec->trusted_mask);
- } else {
- /* pin was not supplied - pre-fetch pin code now */
- if (btm_cb.api.p_pin_callback && ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_PIN_REQD) == 0)) {
- BTM_TRACE_DEBUG("%s() PIN code callback called\n", __func__);
- if (btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR) == NULL) {
- btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD;
- }
- (btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
- p_dev_rec->sec_bd_name, (p_dev_rec->p_cur_service == NULL) ? FALSE
- : (p_dev_rec->p_cur_service->security_flags
- & BTM_SEC_IN_MIN_16_DIGIT_PIN));
- }
- }
- rv = TRUE;
- }
- #endif ///CLASSIC_BT_INCLUDED == TRUE
- #
- return rv;
- }
- /*******************************************************************************
- **
- ** Function btm_sec_auth_payload_tout
- **
- ** Description Processes the HCI Autheniticated Payload Timeout Event
- ** indicating that a packet containing a valid MIC on the
- ** connection handle was not received within the programmed
- ** timeout value. (Spec Default is 30 secs, but can be
- ** changed via the BTM_SecSetAuthPayloadTimeout() function.
- **
- *******************************************************************************/
- void btm_sec_auth_payload_tout (UINT8 *p, UINT16 hci_evt_len)
- {
- UINT16 handle;
- STREAM_TO_UINT16 (handle, p);
- handle = HCID_GET_HANDLE (handle);
- /* Will be exposed to upper layers in the future if/when determined necessary */
- BTM_TRACE_ERROR ("%s on handle 0x%02x\n", __func__, handle);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_queue_encrypt_request
- **
- ** Description encqueue encryption request when device has active security
- ** process pending.
- **
- *******************************************************************************/
- static BOOLEAN btm_sec_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT transport,
- tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
- {
- tBTM_SEC_QUEUE_ENTRY *p_e;
- p_e = (tBTM_SEC_QUEUE_ENTRY *)osi_malloc(sizeof(tBTM_SEC_QUEUE_ENTRY) + 1);
- if (p_e) {
- p_e->psm = 0; /* if PSM 0, encryption request */
- p_e->p_callback = p_callback;
- p_e->p_ref_data = (void *)(p_e + 1);
- *(UINT8 *)p_e->p_ref_data = *(UINT8 *)(p_ref_data);
- p_e->transport = transport;
- memcpy(p_e->bd_addr, bd_addr, BD_ADDR_LEN);
- fixed_queue_enqueue(btm_cb.sec_pending_q, p_e, FIXED_QUEUE_MAX_TIMEOUT);
- return TRUE;
- }
- return FALSE;
- }
- /*******************************************************************************
- **
- ** Function btm_sec_set_peer_sec_caps
- **
- ** Description This function is called to set sm4 and rmt_sec_caps fields
- ** based on the available peer device features.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_set_peer_sec_caps(tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec)
- {
- BD_ADDR rem_bd_addr;
- UINT8 *p_rem_bd_addr;
- if ((btm_cb.security_mode == BTM_SEC_MODE_SP ||
- btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
- btm_cb.security_mode == BTM_SEC_MODE_SC) &&
- HCI_SSP_HOST_SUPPORTED(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_1])) {
- p_dev_rec->sm4 = BTM_SM4_TRUE;
- p_dev_rec->remote_supports_secure_connections =
- (HCI_SC_HOST_SUPPORTED(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_1]));
- } else {
- p_dev_rec->sm4 = BTM_SM4_KNOWN;
- p_dev_rec->remote_supports_secure_connections = FALSE;
- }
- BTM_TRACE_API("%s: sm4: 0x%02x, rmt_support_for_secure_connections %d\n", __FUNCTION__,
- p_dev_rec->sm4, p_dev_rec->remote_supports_secure_connections);
- /* Store previous state of remote device to check if peer device downgraded
- * it's secure connection state. */
- #if (CLASSIC_BT_INCLUDED == TRUE)
- if (p_dev_rec->remote_supports_secure_connections >= p_dev_rec->remote_secure_connection_previous_state) {
- p_dev_rec->remote_secure_connection_previous_state = p_dev_rec->remote_supports_secure_connections;
- } else {
- BTM_TRACE_ERROR("Remote Device downgraded security from SC, deleting Link Key");
- /* Mark in ACL packet that secure connection is downgraded. */
- p_acl_cb->sc_downgrade = 1;
- p_dev_rec->remote_secure_connection_previous_state = 0;
- /* As peer device downgraded it's security, peer device is a suspicious
- * device. Hence remove pairing information by removing link key
- * information. */
- memset(p_dev_rec->link_key, 0, LINK_KEY_LEN);
- p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED
- | BTM_SEC_ENCRYPTED | BTM_SEC_NAME_KNOWN
- | BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED
- | BTM_SEC_ROLE_SWITCHED | BTM_SEC_16_DIGIT_PIN_AUTHED);
- return;
- }
- #endif
- if (p_dev_rec->remote_features_needed) {
- BTM_TRACE_EVENT("%s: Now device in SC Only mode, waiting for peer remote features!\n",
- __FUNCTION__);
- p_rem_bd_addr = (UINT8 *) rem_bd_addr;
- BDADDR_TO_STREAM(p_rem_bd_addr, p_dev_rec->bd_addr);
- p_rem_bd_addr = (UINT8 *) rem_bd_addr;
- btm_io_capabilities_req(p_rem_bd_addr);
- p_dev_rec->remote_features_needed = FALSE;
- }
- }
- /*******************************************************************************
- **
- ** Function btm_sec_is_serv_level0
- **
- ** Description This function is called to check if the service corresponding
- ** to PSM is security mode 4 level 0 service.
- **
- ** Returns TRUE if the service is security mode 4 level 0 service
- **
- *******************************************************************************/
- static BOOLEAN btm_sec_is_serv_level0(UINT16 psm)
- {
- if (psm == BT_PSM_SDP) {
- BTM_TRACE_DEBUG("%s: PSM: 0x%04x -> mode 4 level 0 service\n", __FUNCTION__, psm);
- return TRUE;
- }
- return FALSE;
- }
- /*******************************************************************************
- **
- ** Function btm_sec_check_pending_enc_req
- **
- ** Description This function is called to send pending encryption callback if
- ** waiting
- **
- ** Returns void
- **
- *******************************************************************************/
- static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRANSPORT transport,
- UINT8 encr_enable)
- {
- if (fixed_queue_is_empty(btm_cb.sec_pending_q)) {
- return;
- }
- UINT8 res = encr_enable ? BTM_SUCCESS : BTM_ERR_PROCESSING;
- list_t *list = fixed_queue_get_list(btm_cb.sec_pending_q);
- for (const list_node_t *node = list_begin(list); node != list_end(list); ) {
- tBTM_SEC_QUEUE_ENTRY *p_e = (tBTM_SEC_QUEUE_ENTRY *)list_node(node);
- node = list_next(node);
- if (memcmp(p_e->bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0 && p_e->psm == 0
- #if BLE_INCLUDED == TRUE
- && p_e->transport == transport
- #endif
- ) {
- #if BLE_INCLUDED == TRUE
- UINT8 sec_act = *(UINT8 *)(p_e->p_ref_data);
- #endif
- if (encr_enable == 0 || transport == BT_TRANSPORT_BR_EDR
- #if BLE_INCLUDED == TRUE
- || (sec_act == BTM_BLE_SEC_ENCRYPT || sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
- || (sec_act == BTM_BLE_SEC_ENCRYPT_MITM && p_dev_rec->sec_flags
- & BTM_SEC_LE_AUTHENTICATED)
- #endif
- ) {
- if (p_e->p_callback) {
- (*p_e->p_callback) (p_dev_rec->bd_addr, transport, p_e->p_ref_data, res);
- }
- fixed_queue_try_remove_from_queue(btm_cb.sec_pending_q, (void *)p_e);
- }
- }
- }
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_set_serv_level4_flags
- **
- ** Description This function is called to set security mode 4 level 4 flags.
- **
- ** Returns service security requirements updated to include secure
- ** connections only mode.
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static UINT16 btm_sec_set_serv_level4_flags(UINT16 cur_security, BOOLEAN is_originator)
- {
- UINT16 sec_level4_flags = is_originator ? BTM_SEC_OUT_LEVEL4_FLAGS : BTM_SEC_IN_LEVEL4_FLAGS;
- return cur_security | sec_level4_flags;
- }
- #endif ///SMP_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_clear_ble_keys
- **
- ** Description This function is called to clear out the BLE keys.
- ** Typically when devices are removed in BTM_SecDeleteDevice,
- ** or when a new BT Link key is generated.
- **
- ** Returns void
- **
- *******************************************************************************/
- #if (BLE_INCLUDED == TRUE)
- void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- BTM_TRACE_DEBUG ("%s() Clearing BLE Keys\n", __func__);
- #if (SMP_INCLUDED== TRUE)
- p_dev_rec->ble.key_type = BTM_LE_KEY_NONE;
- memset (&p_dev_rec->ble.keys, 0, sizeof(tBTM_SEC_BLE_KEYS));
- #if (BLE_PRIVACY_SPT == TRUE)
- btm_ble_resolving_list_remove_dev(p_dev_rec);
- #endif
- #endif
- }
- #endif ///BLE_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_is_a_bonded_dev
- **
- ** Description Is the specified device is a bonded device
- **
- ** Returns TRUE - dev is bonded
- **
- *******************************************************************************/
- BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
- BOOLEAN is_bonded = FALSE;
- if (p_dev_rec &&
- #if (SMP_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
- ((p_dev_rec->ble.key_type && (p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_KNOWN)) ||
- #else
- (
- #endif
- (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN))) {
- is_bonded = TRUE;
- }
- BTM_TRACE_DEBUG ("%s() is_bonded=%d\n", __func__, is_bonded);
- return (is_bonded);
- }
- /*******************************************************************************
- **
- ** Function btm_sec_is_le_capable_dev
- **
- ** Description Is the specified device is dual mode or LE only device
- **
- ** Returns TRUE - dev is a dual mode
- **
- *******************************************************************************/
- BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda)
- {
- BOOLEAN le_capable = FALSE;
- #if (BLE_INCLUDED== TRUE)
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
- if (p_dev_rec && (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) {
- le_capable = TRUE;
- }
- #endif
- return le_capable;
- }
- /*******************************************************************************
- **
- ** Function btm_sec_find_bonded_dev
- **
- ** Description Find a bonded device starting from the specified index
- **
- ** Returns TRUE - found a bonded device
- **
- *******************************************************************************/
- #if (BLE_INCLUDED == TRUE)
- BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC **p_rec)
- {
- BOOLEAN found = FALSE;
- #if (SMP_INCLUDED== TRUE)
- tBTM_SEC_DEV_REC *p_dev_rec;
- int i;
- if (start_idx >= BTM_SEC_MAX_DEVICE_RECORDS) {
- BTM_TRACE_DEBUG ("LE bonded device not found\n");
- return found;
- }
- p_dev_rec = &btm_cb.sec_dev_rec[start_idx];
- for (i = start_idx; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
- if (p_dev_rec->ble.key_type || (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) {
- *p_found_idx = i;
- *p_rec = p_dev_rec;
- break;
- }
- }
- BTM_TRACE_DEBUG ("%s() found=%d\n", __func__, found);
- #endif
- return (found);
- }
- #endif ///BLE_INCLUDED == TRUE
- /*******************************************************************************
- **
- ** Function btm_sec_use_smp_br_chnl
- **
- ** Description The function checks if SMP BR connection can be used with
- ** the peer.
- ** Is called when authentication for dedicated bonding is
- ** successfully completed.
- **
- ** Returns TRUE - if SMP BR connection can be used (the link key is
- ** generated from P-256 and the peer supports Security
- ** Manager over BR).
- **
- *******************************************************************************/
- #if (SMP_INCLUDED == TRUE)
- static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec)
- {
- UINT32 ext_feat;
- UINT8 chnl_mask[L2CAP_FIXED_CHNL_ARRAY_SIZE];
- BTM_TRACE_DEBUG ("%s() link_key_type = 0x%x\n", __func__,
- p_dev_rec->link_key_type);
- if ((p_dev_rec->link_key_type != BTM_LKEY_TYPE_UNAUTH_COMB_P_256) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- return FALSE;
- }
- if (!L2CA_GetPeerFeatures (p_dev_rec->bd_addr, &ext_feat, chnl_mask)) {
- return FALSE;
- }
- if (!(chnl_mask[0] & L2CAP_FIXED_CHNL_SMP_BR_BIT)) {
- return FALSE;
- }
- return TRUE;
- }
- /*******************************************************************************
- **
- ** Function btm_sec_is_master
- **
- ** Description The function checks if the device is BR/EDR master after
- ** pairing is completed.
- **
- ** Returns TRUE - if the device is master.
- **
- *******************************************************************************/
- static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec)
- {
- tACL_CONN *p = btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR);
- return (p && (p->link_role == BTM_ROLE_MASTER));
- }
- #if (CLASSIC_BT_INCLUDED == TRUE)
- /*******************************************************************************
- **
- ** Function btm_sec_legacy_authentication_mutual
- **
- ** Description This function is called when legacy authentication is used
- ** and only remote device has completed the authentication
- **
- ** Returns TRUE if aunthentication command sent successfully
- **
- *******************************************************************************/
- BOOLEAN btm_sec_legacy_authentication_mutual (tBTM_SEC_DEV_REC *p_dev_rec)
- {
- return (btm_sec_start_authentication (p_dev_rec));
- }
- /*******************************************************************************
- **
- ** Function btm_sec_update_legacy_auth_state
- **
- ** Description This function updates the legacy authentication state
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_update_legacy_auth_state(tACL_CONN *p_acl_cb, UINT8 legacy_auth_state)
- {
- if (p_acl_cb) {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (p_acl_cb->hci_handle);
- if (p_dev_rec) {
- if ((BTM_BothEndsSupportSecureConnections(p_dev_rec->bd_addr) == 0) &&
- (legacy_auth_state != BTM_ACL_LEGACY_AUTH_NONE)) {
- p_acl_cb->legacy_auth_state |= legacy_auth_state;
- } else {
- p_acl_cb->legacy_auth_state = BTM_ACL_LEGACY_AUTH_NONE;
- }
- }
- }
- }
- /*******************************************************************************
- **
- ** Function btm_sec_handle_remote_legacy_auth_cmp
- **
- ** Description This function updates the legacy authneticaiton state
- ** to indicate that remote device has completed the authentication
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sec_handle_remote_legacy_auth_cmp(UINT16 handle)
- {
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
- tACL_CONN *p_acl_cb = btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR);
- btm_sec_update_legacy_auth_state(p_acl_cb, BTM_ACL_LEGACY_AUTH_REMOTE);
- }
- #endif /// (CLASSIC_BT_INCLUDED == TRUE)
- #endif ///SMP_INCLUDED == TRUE
- /******************************************************************************
- **
- ** Function btm_sec_dev_authorization
- **
- ** Description This function is used to authorize a specified device(BLE)
- **
- ******************************************************************************
- */
- #if (BLE_INCLUDED == TRUE)
- BOOLEAN btm_sec_dev_authorization(BD_ADDR bd_addr, BOOLEAN authorized)
- {
- #if (SMP_INCLUDED == TRUE)
- UINT8 sec_flag = 0;
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
- if (p_dev_rec) {
- sec_flag = (UINT8)(p_dev_rec->sec_flags >> 8);
- if (!(sec_flag & BTM_SEC_LINK_KEY_AUTHED)) {
- BTM_TRACE_ERROR("Authorized should after successful Authentication(MITM protection)\n");
- return FALSE;
- }
- if (authorized) {
- p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHORIZATION;
- } else {
- p_dev_rec->sec_flags &= ~(BTM_SEC_LE_AUTHORIZATION);
- }
- } else {
- BTM_TRACE_ERROR("%s, can't find device\n", __func__);
- return FALSE;
- }
- return TRUE;
- #endif ///SMP_INCLUDED == TRUE
- return FALSE;
- }
- #endif /// BLE_INCLUDE == TRUE
|