1 Star 0 Fork 36

yueyuankun/secGear

forked from src-openEuler/secGear 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0060-supprot-kunpeng-remote-attestation.patch 168.52 KB
一键复制 编辑 原始数据 按行查看 历史
qsW 提交于 2023-09-13 15:40 . syncchronous features
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493
From 826207b3d8e51cf57af7e4f6a3df61b150561b60 Mon Sep 17 00:00:00 2001
From: houmingyong <houmingyong@huawei.com>
Date: Wed, 17 May 2023 10:36:16 +0800
Subject: [PATCH] supprot kunpeng remote attestation
---
CMakeLists.txt | 8 +-
component/CMakeLists.txt | 4 +-
component/remote_attest/CMakeLists.txt | 22 +
.../remote_attest/ra_report/CMakeLists.txt | 48 +
.../remote_attest/ra_report/gp_ra_helper.c | 136 +
.../remote_attest/ra_report/gp_ra_helper.h | 34 +
.../remote_attest/ra_report/gp_ra_report.c | 69 +
.../remote_attest/ra_report/gp_ra_report.h | 24 +
.../remote_attest/ra_report/sg_ra_report.c | 26 +
.../remote_attest/ra_report/sg_ra_report.h | 34 +
.../remote_attest/ra_verify/CMakeLists.txt | 44 +
.../ra_verify/gp_ra_report_verify.c | 50 +
.../ra_verify/gp_ra_report_verify.h | 30 +
.../ra_verify/sg_ra_report_verify.c | 20 +
.../ra_verify/sg_ra_report_verify.h | 30 +
component/remote_attest/sg_report_st.h | 43 +
inc/host_inc/status.h | 8 +
thirdparty/cjson/cJSON.bak | 3110 +++++++++++++++++
thirdparty/cjson/cJSON.h | 293 ++
.../kunpengsecl/verifier/custom_base64url.h | 20 +
thirdparty/kunpengsecl/verifier/teeverifier.h | 50 +
thirdparty/libqca/ra_client_api.h | 22 +
tools/sign_tool/generate_signature.py | 56 -
tools/sign_tool/manifest.py | 322 --
tools/sign_tool/sign_tool.sh | 252 +-
tools/sign_tool/signtool_v3.py | 428 ---
26 files changed, 4224 insertions(+), 959 deletions(-)
create mode 100644 component/remote_attest/CMakeLists.txt
create mode 100644 component/remote_attest/ra_report/CMakeLists.txt
create mode 100644 component/remote_attest/ra_report/gp_ra_helper.c
create mode 100644 component/remote_attest/ra_report/gp_ra_helper.h
create mode 100644 component/remote_attest/ra_report/gp_ra_report.c
create mode 100644 component/remote_attest/ra_report/gp_ra_report.h
create mode 100644 component/remote_attest/ra_report/sg_ra_report.c
create mode 100644 component/remote_attest/ra_report/sg_ra_report.h
create mode 100644 component/remote_attest/ra_verify/CMakeLists.txt
create mode 100644 component/remote_attest/ra_verify/gp_ra_report_verify.c
create mode 100644 component/remote_attest/ra_verify/gp_ra_report_verify.h
create mode 100644 component/remote_attest/ra_verify/sg_ra_report_verify.c
create mode 100644 component/remote_attest/ra_verify/sg_ra_report_verify.h
create mode 100644 component/remote_attest/sg_report_st.h
create mode 100644 thirdparty/cjson/cJSON.bak
create mode 100644 thirdparty/cjson/cJSON.h
create mode 100644 thirdparty/kunpengsecl/verifier/custom_base64url.h
create mode 100644 thirdparty/kunpengsecl/verifier/teeverifier.h
create mode 100644 thirdparty/libqca/ra_client_api.h
delete mode 100644 tools/sign_tool/generate_signature.py
delete mode 100644 tools/sign_tool/manifest.py
delete mode 100644 tools/sign_tool/signtool_v3.py
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c3c25b..079be3b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -92,10 +92,4 @@ install(FILES ${LOCAL_ROOT_PATH}/conf/rsyslog.d/secgear.conf
install(FILES ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh
DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/usr/bin/
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
-set(SIGN_FILE
- ${LOCAL_ROOT_PATH}/tools/sign_tool/generate_signature.py
- ${LOCAL_ROOT_PATH}/tools/sign_tool/manifest.py
- ${LOCAL_ROOT_PATH}/tools/sign_tool/signtool_v3.py
-)
-install(FILES ${SIGN_FILE}
- DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/lib/secGear/)
+
diff --git a/component/CMakeLists.txt b/component/CMakeLists.txt
index 6cff34c..ee0a669 100644
--- a/component/CMakeLists.txt
+++ b/component/CMakeLists.txt
@@ -9,6 +9,8 @@
# See the Mulan PSL v2 for more details.
ADD_SUBDIRECTORY(secure_channel)
-
+if(CC_GP)
+ ADD_SUBDIRECTORY(remote_attest)
+endif()
diff --git a/component/remote_attest/CMakeLists.txt b/component/remote_attest/CMakeLists.txt
new file mode 100644
index 0000000..0b86c6f
--- /dev/null
+++ b/component/remote_attest/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+# secGear is licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+
+ADD_SUBDIRECTORY(ra_report)
+ADD_SUBDIRECTORY(ra_verify)
+
+
+file(GLOB RA_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/sg_report_st.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ra_report/sg_ra_report.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ra_report/gp_ra_helper.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ra_verify/sg_ra_report_verify.h)
+
+install(FILES ${RA_HEADERS}
+ DESTINATION /usr/include/secGear
+ PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
diff --git a/component/remote_attest/ra_report/CMakeLists.txt b/component/remote_attest/ra_report/CMakeLists.txt
new file mode 100644
index 0000000..6b459d7
--- /dev/null
+++ b/component/remote_attest/ra_report/CMakeLists.txt
@@ -0,0 +1,48 @@
+# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+# secGear is licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+
+project(sg_ra_report C)
+
+set(TARGET secgear_ra)
+aux_source_directory(. SRC_FILES)
+aux_source_directory(${LOCAL_ROOT_PATH}/thirdparty/cjson/ CJSON_SRC)
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+
+if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
+ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
+endif()
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+ ${LOCAL_ROOT_PATH}/inc/host_inc
+ ${SDK_PATH}/include/CA
+ ${LOCAL_ROOT_PATH}/thirdparty/cjson
+ ${LOCAL_ROOT_PATH}/thirdparty/libqca
+ ${LOCAL_ROOT_PATH}/thirdparty/kunpengsecl/verifier
+)
+add_library(${TARGET} SHARED ${SRC_FILES} ${CJSON_SRC})
+
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ target_link_directories(${TARGET} PRIVATE /usr/lib64)
+endif()
+
+target_link_libraries(${TARGET} teec_adaptor)
+
+set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64)
+
+install(TARGETS ${TARGET}
+ LIBRARY
+ DESTINATION ${LIBRARY_INSTALL}
+ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
+
+
diff --git a/component/remote_attest/ra_report/gp_ra_helper.c b/component/remote_attest/ra_report/gp_ra_helper.c
new file mode 100644
index 0000000..80a01e9
--- /dev/null
+++ b/component/remote_attest/ra_report/gp_ra_helper.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#include "gp_ra_helper.h"
+
+#include <string.h>
+#include "cJSON.h"
+#include "custom_base64url.h"
+#include "enclave_log.h"
+
+void free_gp_ra_buf(cc_ra_buf_t *ra_buf)
+{
+ if (ra_buf->buf != NULL) {
+ free(ra_buf->buf);
+ }
+ if (ra_buf != NULL) {
+ free(ra_buf);
+ }
+}
+
+/* caller need to free (cc_ra_buf_t **in) */
+cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in)
+{
+ cc_enclave_result_t ret = CC_SUCCESS;
+ cJSON *in_json = cJSON_CreateObject();
+ cJSON_AddStringToObject(in_json, "handler", "provisioning-input");
+
+ cJSON *in_payload = cJSON_CreateObject();
+ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0");
+ cJSON_AddStringToObject(in_payload, "scenario", "sce_no_as");
+ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256");
+
+ cJSON_AddItemToObject(in_json, "payload", in_payload);
+
+ // char *in_buf = cJSON_PrintUnformatted(in_json);
+ char *in_buf = cJSON_Print(in_json);
+ uint32_t in_buf_len = strlen(in_buf) + 1;
+
+ print_debug("provision input json buf:%s\n", in_buf);
+
+ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t));
+ if (tmp_ra_buf == NULL) {
+ ret = CC_ERROR_RA_MEMORY;
+ goto end;
+ }
+ tmp_ra_buf->buf = calloc(1, in_buf_len);
+ if (tmp_ra_buf->buf == NULL) {
+ ret = CC_ERROR_RA_MEMORY;
+ free(tmp_ra_buf);
+ goto end;
+ }
+ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len);
+ tmp_ra_buf->len = in_buf_len;
+
+ *in = tmp_ra_buf;
+end:
+ cJSON_free(in_buf);
+ cJSON_Delete(in_json);
+ return ret;
+}
+
+/* caller need to free (cc_ra_buf_t **in) */
+cc_enclave_result_t gen_ra_report_in_buff(gp_get_ra_report_input_t *param, cc_ra_buf_t **json_buf)
+{
+ cc_enclave_result_t ret = CC_SUCCESS;
+ cJSON *in_json = cJSON_CreateObject();
+ cJSON_AddStringToObject(in_json, "handler", "report-input");
+
+ char b64_nonce[MAX_NONCE_BUF_LEN] = {0};
+ int b64_nonce_len = MAX_NONCE_BUF_LEN;
+ base64urlencode(param->nonce, param->nonce_len, (uint8_t *)b64_nonce, &b64_nonce_len);
+ print_debug("nonce_buf_len:%d, nonce_buf:%s\n", b64_nonce_len, b64_nonce);
+
+ cJSON *in_payload = cJSON_CreateObject();
+ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0");
+ cJSON_AddStringToObject(in_payload, "nonce", b64_nonce);
+ cJSON_AddStringToObject(in_payload, "uuid", (char *)param->uuid);
+ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256");
+ cJSON_AddBoolToObject(in_payload, "with_tcb", param->with_tcb);
+
+ cJSON_AddItemToObject(in_json, "payload", in_payload);
+
+ // char *in_buf = cJSON_PrintUnformatted(in_json);
+ char *in_buf = cJSON_Print(in_json);
+ uint32_t in_buf_len = strlen(in_buf) + 1;
+
+ print_debug("get ra report input json buf:%s\n", in_buf);
+
+ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t));
+ if (tmp_ra_buf == NULL) {
+ ret = CC_ERROR_RA_MEMORY;
+ goto end;
+ }
+ tmp_ra_buf->buf = calloc(1, in_buf_len);
+ if (tmp_ra_buf->buf == NULL) {
+ ret = CC_ERROR_RA_MEMORY;
+ free(tmp_ra_buf);
+ goto end;
+ }
+ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len);
+ tmp_ra_buf->len = in_buf_len;
+
+ *json_buf = (cc_ra_buf_t *)tmp_ra_buf;
+end:
+ cJSON_free(in_buf);
+ cJSON_Delete(in_json);
+ return ret;
+}
+
+void print_ra_report(cc_ra_buf_t *report)
+{
+ cJSON *cj_report = cJSON_ParseWithLength((char *)report->buf, report->len);
+ if (cj_report == NULL) {
+ print_debug("cjson parse report error!\n");
+ return;
+ }
+ char *str_report = cJSON_Print(cj_report);
+
+ print_debug("report:%s\n", str_report);
+
+ cJSON_free(str_report);
+ cJSON_Delete(cj_report);
+ return;
+}
+
+
+
diff --git a/component/remote_attest/ra_report/gp_ra_helper.h b/component/remote_attest/ra_report/gp_ra_helper.h
new file mode 100644
index 0000000..6bee143
--- /dev/null
+++ b/component/remote_attest/ra_report/gp_ra_helper.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#ifndef SECGEAR_RA_HELPER_H
+#define SECGEAR_RA_HELPER_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "status.h"
+#include "sg_report_st.h"
+
+#define MAX_NONCE_BUF_LEN 512
+typedef struct {
+ uint8_t *uuid;
+ uint32_t nonce_len;
+ uint8_t nonce[MAX_NONCE_BUF_LEN];
+ bool with_tcb;
+} gp_get_ra_report_input_t;
+
+cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in);
+cc_enclave_result_t gen_ra_report_in_buff(gp_get_ra_report_input_t *param, cc_ra_buf_t **json_buf);
+void print_ra_report(cc_ra_buf_t *report);
+void free_gp_ra_buf(cc_ra_buf_t *ra_buf);
+#endif
+
diff --git a/component/remote_attest/ra_report/gp_ra_report.c b/component/remote_attest/ra_report/gp_ra_report.c
new file mode 100644
index 0000000..dd02d7d
--- /dev/null
+++ b/component/remote_attest/ra_report/gp_ra_report.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#include "gp_ra_report.h"
+
+#include <stdlib.h>
+#include "gp_ra_helper.h"
+#include "ra_client_api.h"
+#include "enclave_log.h"
+
+#define TEST_REPORT_OUT_LEN 0x3000
+cc_enclave_result_t gp_ra_provision_no_as()
+{
+ cc_ra_buf_t *in = NULL;
+ cc_enclave_result_t ret;
+
+ ret = gen_provision_no_as_in_buff(&in);
+ if (ret != CC_SUCCESS) {
+ return ret;
+ }
+ uint8_t data[TEST_REPORT_OUT_LEN] = {0};
+ cc_ra_buf_t report = {TEST_REPORT_OUT_LEN, data};
+
+ TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)in, (struct ra_buffer_data *)&report);
+ free_gp_ra_buf(in);
+
+ if (gp_ret != TEEC_SUCCESS) {
+ print_error_term("gp ra provision no as failed ret:%x\n", gp_ret);
+ return CC_ERROR_RA_PROVISION_NO_AS;
+ }
+
+ return CC_SUCCESS;
+}
+
+cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario)
+{
+ cc_enclave_result_t ret = CC_SUCCESS;
+ switch(scenario) {
+ case CC_RA_SCENARIO_NO_AS:
+ ret = gp_ra_provision_no_as();
+ break;
+ default:
+ return CC_ERROR_RA_PRE_ENV_INVALID_SCENARIO;
+ }
+ return ret;
+}
+
+cc_enclave_result_t gp_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report)
+{
+ TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)in, (struct ra_buffer_data *)report);
+ if (gp_ret != TEEC_SUCCESS) {
+ print_error_term("get ra report failed, ret:%x\n", gp_ret);
+ return CC_ERROR_RA_GET_REPORT;
+ }
+
+ return CC_SUCCESS;
+}
+
+
+
diff --git a/component/remote_attest/ra_report/gp_ra_report.h b/component/remote_attest/ra_report/gp_ra_report.h
new file mode 100644
index 0000000..9d02ce3
--- /dev/null
+++ b/component/remote_attest/ra_report/gp_ra_report.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#ifndef SECGEAR_GP_RA_REPORT_H
+#define SECGEAR_GP_RA_REPORT_H
+
+#include "status.h"
+#include "sg_report_st.h"
+
+cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario);
+
+cc_enclave_result_t gp_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report);
+
+#endif
+
diff --git a/component/remote_attest/ra_report/sg_ra_report.c b/component/remote_attest/ra_report/sg_ra_report.c
new file mode 100644
index 0000000..1cc4bdc
--- /dev/null
+++ b/component/remote_attest/ra_report/sg_ra_report.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#include "gp_ra_report.h"
+
+cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario)
+{
+ return gp_prepare_ra_env(scenario);
+}
+
+cc_enclave_result_t cc_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report)
+{
+ return gp_get_ra_report(in, report);
+}
+
+
+
diff --git a/component/remote_attest/ra_report/sg_ra_report.h b/component/remote_attest/ra_report/sg_ra_report.h
new file mode 100644
index 0000000..960cb02
--- /dev/null
+++ b/component/remote_attest/ra_report/sg_ra_report.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#ifndef SECGEAR_REMOTE_REPORT_H
+#define SECGEAR_REMOTE_REPORT_H
+
+#include <stdint.h>
+#include "status.h"
+#include "secgear_defs.h"
+#include "sg_report_st.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CC_API_SPEC cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario);
+
+CC_API_SPEC cc_enclave_result_t cc_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/component/remote_attest/ra_verify/CMakeLists.txt b/component/remote_attest/ra_verify/CMakeLists.txt
new file mode 100644
index 0000000..fc92d9c
--- /dev/null
+++ b/component/remote_attest/ra_verify/CMakeLists.txt
@@ -0,0 +1,44 @@
+# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+# secGear is licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+
+project(sg_ra_verify C)
+
+set(TARGET secgear_verify)
+aux_source_directory(. SRC_FILES)
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+
+if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
+ link_directories(/usr/lib64)
+endif()
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+ ${LOCAL_ROOT_PATH}/inc/host_inc
+ ${LOCAL_ROOT_PATH}/thirdparty/kunpengsecl/verifier
+)
+add_library(${TARGET} SHARED ${SRC_FILES})
+
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
+ target_link_directories(${TARGET} PRIVATE /usr/lib64)
+endif()
+
+target_link_libraries(${TARGET})
+
+set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64)
+
+install(TARGETS ${TARGET}
+ LIBRARY
+ DESTINATION ${LIBRARY_INSTALL}
+ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
+
+
diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.c b/component/remote_attest/ra_verify/gp_ra_report_verify.c
new file mode 100644
index 0000000..0917f7a
--- /dev/null
+++ b/component/remote_attest/ra_verify/gp_ra_report_verify.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#include "gp_ra_report_verify.h"
+
+#include "teeverifier.h"
+#include "enclave_log.h"
+
+int convert_cctype_to_gptype(cc_ra_verify_type_t type)
+{
+ // gp type, 1: compare image hash; 2: compare mem hash; 3: compare image and mem hash
+ if (type == CC_RA_VERIFY_TYPE_LOOSE) {
+ return 1;
+ } else if (type == CC_RA_VERIFY_TYPE_STRICT) {
+ return 3;
+ } else {
+ return CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE;
+ }
+}
+
+cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue)
+{
+ int gp_type = convert_cctype_to_gptype(type);
+ if (gp_type == (int)CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE) {
+ return CC_FAIL;
+ }
+ int ret = tee_verify_report((buffer_data *)report, (buffer_data *)nonce, gp_type, basevalue);
+ switch (ret) {
+ case TVS_ALL_SUCCESSED:
+ return CC_SUCCESS;
+ case TVS_VERIFIED_NONCE_FAILED:
+ return CC_ERROR_RA_REPORT_VERIFY_NONCE;
+ case TVS_VERIFIED_SIGNATURE_FAILED:
+ return CC_ERROR_RA_REPORT_VERIFY_SIGNATURE;
+ case TVS_VERIFIED_HASH_FAILED:
+ return CC_ERROR_RA_REPORT_VERIFY_HASH;
+ default:
+ print_debug("verify report failed, unknown errorcode:%d!\n", ret);
+ }
+ return ret;
+}
\ No newline at end of file
diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.h b/component/remote_attest/ra_verify/gp_ra_report_verify.h
new file mode 100644
index 0000000..ffd8387
--- /dev/null
+++ b/component/remote_attest/ra_verify/gp_ra_report_verify.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#ifndef SECGEAR_GP_VERIFY_REPORT_H
+#define SECGEAR_GP_VERIFY_REPORT_H
+
+#include "status.h"
+#include "secgear_defs.h"
+#include "sg_report_st.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CC_API_SPEC cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/component/remote_attest/ra_verify/sg_ra_report_verify.c b/component/remote_attest/ra_verify/sg_ra_report_verify.c
new file mode 100644
index 0000000..63f26c4
--- /dev/null
+++ b/component/remote_attest/ra_verify/sg_ra_report_verify.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#include "gp_ra_report_verify.h"
+
+#include "enclave_log.h"
+
+cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue)
+{
+ return gp_verify_report(report, nonce, type, basevalue);
+}
\ No newline at end of file
diff --git a/component/remote_attest/ra_verify/sg_ra_report_verify.h b/component/remote_attest/ra_verify/sg_ra_report_verify.h
new file mode 100644
index 0000000..92ca953
--- /dev/null
+++ b/component/remote_attest/ra_verify/sg_ra_report_verify.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#ifndef SECGEAR_VERIFY_REPORT_H
+#define SECGEAR_VERIFY_REPORT_H
+
+#include "status.h"
+#include "secgear_defs.h"
+#include "sg_report_st.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CC_API_SPEC cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/component/remote_attest/sg_report_st.h b/component/remote_attest/sg_report_st.h
new file mode 100644
index 0000000..89ee25a
--- /dev/null
+++ b/component/remote_attest/sg_report_st.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+ * secGear is licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+#ifndef SECGEAR_REPORT_STRUCT_H
+#define SECGEAR_REPORT_STRUCT_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct cc_ra_buf {
+ uint32_t len;
+ uint8_t *buf;
+} cc_ra_buf_t;
+
+typedef enum {
+ CC_RA_SCENARIO_NO_AS,
+ // CC_RA_SCENARIO_AS_NO_DAA,
+ // CC_RA_SCENARIO_AS_WITH_DAA
+} cc_ra_scenario_t;
+
+typedef enum {
+ CC_RA_VERIFY_TYPE_LOOSE,
+ CC_RA_VERIFY_TYPE_STRICT,
+ CC_RA_VERIFY_TYPE_MAX
+} cc_ra_verify_type_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/inc/host_inc/status.h b/inc/host_inc/status.h
index 40e9f1c..ea7b93b 100644
--- a/inc/host_inc/status.h
+++ b/inc/host_inc/status.h
@@ -78,6 +78,14 @@ typedef enum _enclave_result_t
CC_ERROR_ATT_KEY_UNINITIALIZED, /* attestation key is not initialized*/
CC_ERROR_INVALID_ATT_KEY_CERT_DATA, /* attestation data is not valid*/
CC_ERROR_PLATFORM_CERT_UNAVAILABLE, /* cert is not available*/
+ CC_ERROR_RA_PRE_ENV_INVALID_SCENARIO,
+ CC_ERROR_RA_MEMORY,
+ CC_ERROR_RA_PROVISION_NO_AS,
+ CC_ERROR_RA_GET_REPORT,
+ CC_ERROR_RA_REPORT_VERIFY_NONCE,
+ CC_ERROR_RA_REPORT_VERIFY_SIGNATURE,
+ CC_ERROR_RA_REPORT_VERIFY_HASH,
+ CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE,
/* secure channel */
CC_ERROR_SEC_CHL_INVALID_CONN, /* invalid connection */
CC_ERROR_SEC_CHL_LEN_NOT_ENOUGH, /* the buf length to store secure channle encrypt/decrypt is not enough */
diff --git a/thirdparty/cjson/cJSON.bak b/thirdparty/cjson/cJSON.bak
new file mode 100644
index 0000000..3063f74
--- /dev/null
+++ b/thirdparty/cjson/cJSON.bak
@@ -0,0 +1,3110 @@
+/*
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <float.h>
+
+#ifdef ENABLE_LOCALES
+#include <locale.h>
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+#include "cJSON.h"
+
+/* define our own boolean type */
+#ifdef true
+#undef true
+#endif
+#define true ((cJSON_bool)1)
+
+#ifdef false
+#undef false
+#endif
+#define false ((cJSON_bool)0)
+
+/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
+#ifndef isinf
+#define isinf(d) (isnan((d - d)) && !isnan(d))
+#endif
+#ifndef isnan
+#define isnan(d) (d != d)
+#endif
+
+#ifndef NAN
+#ifdef _WIN32
+#define NAN sqrt(-1.0)
+#else
+#define NAN 0.0/0.0
+#endif
+#endif
+
+typedef struct {
+ const unsigned char *json;
+ size_t position;
+} error;
+static error global_error = { NULL, 0 };
+
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
+{
+ return (const char*) (global_error.json + global_error.position);
+}
+
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
+{
+ if (!cJSON_IsString(item))
+ {
+ return NULL;
+ }
+
+ return item->valuestring;
+}
+
+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
+{
+ if (!cJSON_IsNumber(item))
+ {
+ return (double) NAN;
+ }
+
+ return item->valuedouble;
+}
+
+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15)
+ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#endif
+
+CJSON_PUBLIC(const char*) cJSON_Version(void)
+{
+ static char version[15];
+ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
+
+ return version;
+}
+
+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
+{
+ if ((string1 == NULL) || (string2 == NULL))
+ {
+ return 1;
+ }
+
+ if (string1 == string2)
+ {
+ return 0;
+ }
+
+ for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
+ {
+ if (*string1 == '\0')
+ {
+ return 0;
+ }
+ }
+
+ return tolower(*string1) - tolower(*string2);
+}
+
+typedef struct internal_hooks
+{
+ void *(CJSON_CDECL *allocate)(size_t size);
+ void (CJSON_CDECL *deallocate)(void *pointer);
+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+#if defined(_MSC_VER)
+/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
+static void * CJSON_CDECL internal_malloc(size_t size)
+{
+ return malloc(size);
+}
+static void CJSON_CDECL internal_free(void *pointer)
+{
+ free(pointer);
+}
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
+{
+ return realloc(pointer, size);
+}
+#else
+#define internal_malloc malloc
+#define internal_free free
+#define internal_realloc realloc
+#endif
+
+/* strlen of character literals resolved at compile time */
+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
+
+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
+
+static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
+{
+ size_t length = 0;
+ unsigned char *copy = NULL;
+
+ if (string == NULL)
+ {
+ return NULL;
+ }
+
+ length = strlen((const char*)string) + sizeof("");
+ copy = (unsigned char*)hooks->allocate(length);
+ if (copy == NULL)
+ {
+ return NULL;
+ }
+ memcpy(copy, string, length);
+
+ return copy;
+}
+
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (hooks == NULL)
+ {
+ /* Reset hooks */
+ global_hooks.allocate = malloc;
+ global_hooks.deallocate = free;
+ global_hooks.reallocate = realloc;
+ return;
+ }
+
+ global_hooks.allocate = malloc;
+ if (hooks->malloc_fn != NULL)
+ {
+ global_hooks.allocate = hooks->malloc_fn;
+ }
+
+ global_hooks.deallocate = free;
+ if (hooks->free_fn != NULL)
+ {
+ global_hooks.deallocate = hooks->free_fn;
+ }
+
+ /* use realloc only if both free and malloc are used */
+ global_hooks.reallocate = NULL;
+ if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
+ {
+ global_hooks.reallocate = realloc;
+ }
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
+{
+ cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
+ if (node)
+ {
+ memset(node, '\0', sizeof(cJSON));
+ }
+
+ return node;
+}
+
+/* Delete a cJSON structure. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
+{
+ cJSON *next = NULL;
+ while (item != NULL)
+ {
+ next = item->next;
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL))
+ {
+ cJSON_Delete(item->child);
+ }
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
+ {
+ global_hooks.deallocate(item->valuestring);
+ }
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+ {
+ global_hooks.deallocate(item->string);
+ }
+ global_hooks.deallocate(item);
+ item = next;
+ }
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+#ifdef ENABLE_LOCALES
+ struct lconv *lconv = localeconv();
+ return (unsigned char) lconv->decimal_point[0];
+#else
+ return '.';
+#endif
+}
+
+typedef struct
+{
+ const unsigned char *content;
+ size_t length;
+ size_t offset;
+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+ internal_hooks hooks;
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
+{
+ double number = 0;
+ unsigned char *after_end = NULL;
+ unsigned char number_c_string[64];
+ unsigned char decimal_point = get_decimal_point();
+ size_t i = 0;
+
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
+ {
+ return false;
+ }
+
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
+ * of the current locale (for strtod)
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
+ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
+ {
+ switch (buffer_at_offset(input_buffer)[i])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case 'e':
+ case 'E':
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
+ break;
+
+ case '.':
+ number_c_string[i] = decimal_point;
+ break;
+
+ default:
+ goto loop_end;
+ }
+ }
+loop_end:
+ number_c_string[i] = '\0';
+
+ number = strtod((const char*)number_c_string, (char**)&after_end);
+ if (number_c_string == after_end)
+ {
+ return false; /* parse_error */
+ }
+
+ item->valuedouble = number;
+
+ /* use saturation in case of overflow */
+ if (number >= INT_MAX)
+ {
+ item->valueint = INT_MAX;
+ }
+ else if (number <= (double)INT_MIN)
+ {
+ item->valueint = INT_MIN;
+ }
+ else
+ {
+ item->valueint = (int)number;
+ }
+
+ item->type = cJSON_Number;
+
+ input_buffer->offset += (size_t)(after_end - number_c_string);
+ return true;
+}
+
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
+{
+ if (number >= INT_MAX)
+ {
+ object->valueint = INT_MAX;
+ }
+ else if (number <= (double)INT_MIN)
+ {
+ object->valueint = INT_MIN;
+ }
+ else
+ {
+ object->valueint = (int)number;
+ }
+
+ return object->valuedouble = number;
+}
+
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
+{
+ char *copy = NULL;
+ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
+ if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
+ {
+ return NULL;
+ }
+ if (strlen(valuestring) <= strlen(object->valuestring))
+ {
+ strcpy(object->valuestring, valuestring);
+ return object->valuestring;
+ }
+ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
+ if (copy == NULL)
+ {
+ return NULL;
+ }
+ if (object->valuestring != NULL)
+ {
+ cJSON_free(object->valuestring);
+ }
+ object->valuestring = copy;
+
+ return copy;
+}
+
+typedef struct
+{
+ unsigned char *buffer;
+ size_t length;
+ size_t offset;
+ size_t depth; /* current nesting depth (for formatted printing) */
+ cJSON_bool noalloc;
+ cJSON_bool format; /* is this print a formatted print */
+ internal_hooks hooks;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static unsigned char* ensure(printbuffer * const p, size_t needed)
+{
+ unsigned char *newbuffer = NULL;
+ size_t newsize = 0;
+
+ if ((p == NULL) || (p->buffer == NULL))
+ {
+ return NULL;
+ }
+
+ if ((p->length > 0) && (p->offset >= p->length))
+ {
+ /* make sure that offset is valid */
+ return NULL;
+ }
+
+ if (needed > INT_MAX)
+ {
+ /* sizes bigger than INT_MAX are currently not supported */
+ return NULL;
+ }
+
+ needed += p->offset + 1;
+ if (needed <= p->length)
+ {
+ return p->buffer + p->offset;
+ }
+
+ if (p->noalloc) {
+ return NULL;
+ }
+
+ /* calculate new buffer size */
+ if (needed > (INT_MAX / 2))
+ {
+ /* overflow of int, use INT_MAX if possible */
+ if (needed <= INT_MAX)
+ {
+ newsize = INT_MAX;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ newsize = needed * 2;
+ }
+
+ if (p->hooks.reallocate != NULL)
+ {
+ /* reallocate with realloc if available */
+ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
+ if (newbuffer == NULL)
+ {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ }
+ else
+ {
+ /* otherwise reallocate manually */
+ newbuffer = (unsigned char*)p->hooks.allocate(newsize);
+ if (!newbuffer)
+ {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+
+ memcpy(newbuffer, p->buffer, p->offset + 1);
+ p->hooks.deallocate(p->buffer);
+ }
+ p->length = newsize;
+ p->buffer = newbuffer;
+
+ return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer * const buffer)
+{
+ const unsigned char *buffer_pointer = NULL;
+ if ((buffer == NULL) || (buffer->buffer == NULL))
+ {
+ return;
+ }
+ buffer_pointer = buffer->buffer + buffer->offset;
+
+ buffer->offset += strlen((const char*)buffer_pointer);
+}
+
+/* securely comparison of floating-point variables */
+static cJSON_bool compare_double(double a, double b)
+{
+ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
+ return (fabs(a - b) <= maxVal * DBL_EPSILON);
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ double d = item->valuedouble;
+ int length = 0;
+ size_t i = 0;
+ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
+ unsigned char decimal_point = get_decimal_point();
+ double test = 0.0;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* This checks for NaN and Infinity */
+ if (isnan(d) || isinf(d))
+ {
+ length = sprintf((char*)number_buffer, "null");
+ }
+ else
+ {
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+ length = sprintf((char*)number_buffer, "%1.15g", d);
+
+ /* Check whether the original double can be recovered */
+ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
+ {
+ /* If not, print with 17 decimal places of precision */
+ length = sprintf((char*)number_buffer, "%1.17g", d);
+ }
+ }
+
+ /* sprintf failed or buffer overrun occurred */
+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
+ {
+ return false;
+ }
+
+ /* reserve appropriate space in the output */
+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ /* copy the printed number to the output and replace locale
+ * dependent decimal point with '.' */
+ for (i = 0; i < ((size_t)length); i++)
+ {
+ if (number_buffer[i] == decimal_point)
+ {
+ output_pointer[i] = '.';
+ continue;
+ }
+
+ output_pointer[i] = number_buffer[i];
+ }
+ output_pointer[i] = '\0';
+
+ output_buffer->offset += (size_t)length;
+
+ return true;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const unsigned char * const input)
+{
+ unsigned int h = 0;
+ size_t i = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ /* parse digit */
+ if ((input[i] >= '0') && (input[i] <= '9'))
+ {
+ h += (unsigned int) input[i] - '0';
+ }
+ else if ((input[i] >= 'A') && (input[i] <= 'F'))
+ {
+ h += (unsigned int) 10 + input[i] - 'A';
+ }
+ else if ((input[i] >= 'a') && (input[i] <= 'f'))
+ {
+ h += (unsigned int) 10 + input[i] - 'a';
+ }
+ else /* invalid */
+ {
+ return 0;
+ }
+
+ if (i < 3)
+ {
+ /* shift left to make place for the next nibble */
+ h = h << 4;
+ }
+ }
+
+ return h;
+}
+
+/* converts a UTF-16 literal to UTF-8
+ * A literal can be one or two sequences of the form \uXXXX */
+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
+{
+ long unsigned int codepoint = 0;
+ unsigned int first_code = 0;
+ const unsigned char *first_sequence = input_pointer;
+ unsigned char utf8_length = 0;
+ unsigned char utf8_position = 0;
+ unsigned char sequence_length = 0;
+ unsigned char first_byte_mark = 0;
+
+ if ((input_end - first_sequence) < 6)
+ {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ /* get the first utf16 sequence */
+ first_code = parse_hex4(first_sequence + 2);
+
+ /* check that the code is valid */
+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
+ {
+ goto fail;
+ }
+
+ /* UTF16 surrogate pair */
+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
+ {
+ const unsigned char *second_sequence = first_sequence + 6;
+ unsigned int second_code = 0;
+ sequence_length = 12; /* \uXXXX\uXXXX */
+
+ if ((input_end - second_sequence) < 6)
+ {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
+ {
+ /* missing second half of the surrogate pair */
+ goto fail;
+ }
+
+ /* get the second utf16 sequence */
+ second_code = parse_hex4(second_sequence + 2);
+ /* check that the code is valid */
+ if ((second_code < 0xDC00) || (second_code > 0xDFFF))
+ {
+ /* invalid second half of the surrogate pair */
+ goto fail;
+ }
+
+
+ /* calculate the unicode codepoint from the surrogate pair */
+ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+ }
+ else
+ {
+ sequence_length = 6; /* \uXXXX */
+ codepoint = first_code;
+ }
+
+ /* encode as UTF-8
+ * takes at maximum 4 bytes to encode:
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ if (codepoint < 0x80)
+ {
+ /* normal ascii, encoding 0xxxxxxx */
+ utf8_length = 1;
+ }
+ else if (codepoint < 0x800)
+ {
+ /* two bytes, encoding 110xxxxx 10xxxxxx */
+ utf8_length = 2;
+ first_byte_mark = 0xC0; /* 11000000 */
+ }
+ else if (codepoint < 0x10000)
+ {
+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 3;
+ first_byte_mark = 0xE0; /* 11100000 */
+ }
+ else if (codepoint <= 0x10FFFF)
+ {
+ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 4;
+ first_byte_mark = 0xF0; /* 11110000 */
+ }
+ else
+ {
+ /* invalid unicode codepoint */
+ goto fail;
+ }
+
+ /* encode as utf8 */
+ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
+ {
+ /* 10xxxxxx */
+ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
+ codepoint >>= 6;
+ }
+ /* encode first byte */
+ if (utf8_length > 1)
+ {
+ (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
+ }
+ else
+ {
+ (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
+ }
+
+ *output_pointer += utf8_length;
+
+ return sequence_length;
+
+fail:
+ return 0;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
+{
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+ unsigned char *output_pointer = NULL;
+ unsigned char *output = NULL;
+
+ /* not a string */
+ if (buffer_at_offset(input_buffer)[0] != '\"')
+ {
+ goto fail;
+ }
+
+ {
+ /* calculate approximate size of the output (overestimate) */
+ size_t allocation_length = 0;
+ size_t skipped_bytes = 0;
+ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
+ {
+ /* is escape sequence */
+ if (input_end[0] == '\\')
+ {
+ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
+ {
+ /* prevent buffer overflow when last input character is a backslash */
+ goto fail;
+ }
+ skipped_bytes++;
+ input_end++;
+ }
+ input_end++;
+ }
+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
+ {
+ goto fail; /* string ended unexpectedly */
+ }
+
+ /* This is at most how much we need for the output */
+ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
+ output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
+ if (output == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+ }
+
+ output_pointer = output;
+ /* loop through the string literal */
+ while (input_pointer < input_end)
+ {
+ if (*input_pointer != '\\')
+ {
+ *output_pointer++ = *input_pointer++;
+ }
+ /* escape sequence */
+ else
+ {
+ unsigned char sequence_length = 2;
+ if ((input_end - input_pointer) < 1)
+ {
+ goto fail;
+ }
+
+ switch (input_pointer[1])
+ {
+ case 'b':
+ *output_pointer++ = '\b';
+ break;
+ case 'f':
+ *output_pointer++ = '\f';
+ break;
+ case 'n':
+ *output_pointer++ = '\n';
+ break;
+ case 'r':
+ *output_pointer++ = '\r';
+ break;
+ case 't':
+ *output_pointer++ = '\t';
+ break;
+ case '\"':
+ case '\\':
+ case '/':
+ *output_pointer++ = input_pointer[1];
+ break;
+
+ /* UTF-16 literal */
+ case 'u':
+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
+ if (sequence_length == 0)
+ {
+ /* failed to convert UTF16-literal to UTF-8 */
+ goto fail;
+ }
+ break;
+
+ default:
+ goto fail;
+ }
+ input_pointer += sequence_length;
+ }
+ }
+
+ /* zero terminate the output */
+ *output_pointer = '\0';
+
+ item->type = cJSON_String;
+ item->valuestring = (char*)output;
+
+ input_buffer->offset = (size_t) (input_end - input_buffer->content);
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (output != NULL)
+ {
+ input_buffer->hooks.deallocate(output);
+ }
+
+ if (input_pointer != NULL)
+ {
+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+ }
+
+ return false;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
+{
+ const unsigned char *input_pointer = NULL;
+ unsigned char *output = NULL;
+ unsigned char *output_pointer = NULL;
+ size_t output_length = 0;
+ /* numbers of additional characters needed for escaping */
+ size_t escape_characters = 0;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* empty string */
+ if (input == NULL)
+ {
+ output = ensure(output_buffer, sizeof("\"\""));
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "\"\"");
+
+ return true;
+ }
+
+ /* set "flag" to 1 if something needs to be escaped */
+ for (input_pointer = input; *input_pointer; input_pointer++)
+ {
+ switch (*input_pointer)
+ {
+ case '\"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ /* one character escape sequence */
+ escape_characters++;
+ break;
+ default:
+ if (*input_pointer < 32)
+ {
+ /* UTF-16 escape sequence uXXXX */
+ escape_characters += 5;
+ }
+ break;
+ }
+ }
+ output_length = (size_t)(input_pointer - input) + escape_characters;
+
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
+ if (output == NULL)
+ {
+ return false;
+ }
+
+ /* no characters have to be escaped */
+ if (escape_characters == 0)
+ {
+ output[0] = '\"';
+ memcpy(output + 1, input, output_length);
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+ }
+
+ output[0] = '\"';
+ output_pointer = output + 1;
+ /* copy the string */
+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
+ {
+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
+ {
+ /* normal character, copy */
+ *output_pointer = *input_pointer;
+ }
+ else
+ {
+ /* character needs to be escaped */
+ *output_pointer++ = '\\';
+ switch (*input_pointer)
+ {
+ case '\\':
+ *output_pointer = '\\';
+ break;
+ case '\"':
+ *output_pointer = '\"';
+ break;
+ case '\b':
+ *output_pointer = 'b';
+ break;
+ case '\f':
+ *output_pointer = 'f';
+ break;
+ case '\n':
+ *output_pointer = 'n';
+ break;
+ case '\r':
+ *output_pointer = 'r';
+ break;
+ case '\t':
+ *output_pointer = 't';
+ break;
+ default:
+ /* escape and print as unicode codepoint */
+ sprintf((char*)output_pointer, "u%04x", *input_pointer);
+ output_pointer += 4;
+ break;
+ }
+ }
+ }
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
+{
+ return print_string_ptr((unsigned char*)item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL))
+ {
+ return NULL;
+ }
+
+ if (cannot_access_at_index(buffer, 0))
+ {
+ return buffer;
+ }
+
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
+ {
+ buffer->offset++;
+ }
+
+ if (buffer->offset == buffer->length)
+ {
+ buffer->offset--;
+ }
+
+ return buffer;
+}
+
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
+ {
+ return NULL;
+ }
+
+ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
+ {
+ buffer->offset += 3;
+ }
+
+ return buffer;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+ size_t buffer_length;
+
+ if (NULL == value)
+ {
+ return NULL;
+ }
+
+ /* Adding null character size due to require_null_terminated. */
+ buffer_length = strlen(value) + sizeof("");
+
+ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
+ cJSON *item = NULL;
+
+ /* reset error position */
+ global_error.json = NULL;
+ global_error.position = 0;
+
+ if (value == NULL || 0 == buffer_length)
+ {
+ goto fail;
+ }
+
+ buffer.content = (const unsigned char*)value;
+ buffer.length = buffer_length;
+ buffer.offset = 0;
+ buffer.hooks = global_hooks;
+
+ item = cJSON_New_Item(&global_hooks);
+ if (item == NULL) /* memory fail */
+ {
+ goto fail;
+ }
+
+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
+ {
+ /* parse failure. ep is set. */
+ goto fail;
+ }
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated)
+ {
+ buffer_skip_whitespace(&buffer);
+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
+ {
+ goto fail;
+ }
+ }
+ if (return_parse_end)
+ {
+ *return_parse_end = (const char*)buffer_at_offset(&buffer);
+ }
+
+ return item;
+
+fail:
+ if (item != NULL)
+ {
+ cJSON_Delete(item);
+ }
+
+ if (value != NULL)
+ {
+ error local_error;
+ local_error.json = (const unsigned char*)value;
+ local_error.position = 0;
+
+ if (buffer.offset < buffer.length)
+ {
+ local_error.position = buffer.offset;
+ }
+ else if (buffer.length > 0)
+ {
+ local_error.position = buffer.length - 1;
+ }
+
+ if (return_parse_end != NULL)
+ {
+ *return_parse_end = (const char*)local_error.json + local_error.position;
+ }
+
+ global_error = local_error;
+ }
+
+ return NULL;
+}
+
+/* Default options for cJSON_Parse */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
+{
+ return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
+{
+ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
+}
+
+#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
+
+static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
+{
+ static const size_t default_buffer_size = 256;
+ printbuffer buffer[1];
+ unsigned char *printed = NULL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* create buffer */
+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
+ buffer->length = default_buffer_size;
+ buffer->format = format;
+ buffer->hooks = *hooks;
+ if (buffer->buffer == NULL)
+ {
+ goto fail;
+ }
+
+ /* print the value */
+ if (!print_value(item, buffer))
+ {
+ goto fail;
+ }
+ update_offset(buffer);
+
+ /* check if reallocate is available */
+ if (hooks->reallocate != NULL)
+ {
+ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ buffer->buffer = NULL;
+ }
+ else /* otherwise copy the JSON over to a new buffer */
+ {
+ printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
+ if (printed == NULL)
+ {
+ goto fail;
+ }
+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
+ printed[buffer->offset] = '\0'; /* just to be sure */
+
+ /* free the buffer */
+ hooks->deallocate(buffer->buffer);
+ }
+
+ return printed;
+
+fail:
+ if (buffer->buffer != NULL)
+ {
+ hooks->deallocate(buffer->buffer);
+ }
+
+ if (printed != NULL)
+ {
+ hooks->deallocate(printed);
+ }
+
+ return NULL;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
+{
+ return (char*)print(item, true, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
+{
+ return (char*)print(item, false, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if (prebuffer < 0)
+ {
+ return NULL;
+ }
+
+ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
+ if (!p.buffer)
+ {
+ return NULL;
+ }
+
+ p.length = (size_t)prebuffer;
+ p.offset = 0;
+ p.noalloc = false;
+ p.format = fmt;
+ p.hooks = global_hooks;
+
+ if (!print_value(item, &p))
+ {
+ global_hooks.deallocate(p.buffer);
+ return NULL;
+ }
+
+ return (char*)p.buffer;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if ((length < 0) || (buffer == NULL))
+ {
+ return false;
+ }
+
+ p.buffer = (unsigned char*)buffer;
+ p.length = (size_t)length;
+ p.offset = 0;
+ p.noalloc = true;
+ p.format = format;
+ p.hooks = global_hooks;
+
+ return print_value(item, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
+{
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
+ {
+ return false; /* no input */
+ }
+
+ /* parse the different types of values */
+ /* null */
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
+ {
+ item->type = cJSON_NULL;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* false */
+ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
+ {
+ item->type = cJSON_False;
+ input_buffer->offset += 5;
+ return true;
+ }
+ /* true */
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
+ {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* string */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
+ {
+ return parse_string(item, input_buffer);
+ }
+ /* number */
+ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
+ {
+ return parse_number(item, input_buffer);
+ }
+ /* array */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
+ {
+ return parse_array(item, input_buffer);
+ }
+ /* object */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
+ {
+ return parse_object(item, input_buffer);
+ }
+
+ return false;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output = NULL;
+
+ if ((item == NULL) || (output_buffer == NULL))
+ {
+ return false;
+ }
+
+ switch ((item->type) & 0xFF)
+ {
+ case cJSON_NULL:
+ output = ensure(output_buffer, 5);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "null");
+ return true;
+
+ case cJSON_False:
+ output = ensure(output_buffer, 6);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "false");
+ return true;
+
+ case cJSON_True:
+ output = ensure(output_buffer, 5);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "true");
+ return true;
+
+ case cJSON_Number:
+ return print_number(item, output_buffer);
+
+ case cJSON_Raw:
+ {
+ size_t raw_length = 0;
+ if (item->valuestring == NULL)
+ {
+ return false;
+ }
+
+ raw_length = strlen(item->valuestring) + sizeof("");
+ output = ensure(output_buffer, raw_length);
+ if (output == NULL)
+ {
+ return false;
+ }
+ memcpy(output, item->valuestring, raw_length);
+ return true;
+ }
+
+ case cJSON_String:
+ return print_string(item, output_buffer);
+
+ case cJSON_Array:
+ return print_array(item, output_buffer);
+
+ case cJSON_Object:
+ return print_object(item, output_buffer);
+
+ default:
+ return false;
+ }
+}
+
+/* Build an array from input text. */
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* head of the linked list */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+ {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (buffer_at_offset(input_buffer)[0] != '[')
+ {
+ /* not an array */
+ goto fail;
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
+ {
+ /* empty array */
+ goto success;
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0))
+ {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do
+ {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL)
+ {
+ /* start the linked list */
+ current_item = head = new_item;
+ }
+ else
+ {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse next value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ }
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
+ {
+ goto fail; /* expected end of array */
+ }
+
+success:
+ input_buffer->depth--;
+
+ if (head != NULL) {
+ head->prev = current_item;
+ }
+
+ item->type = cJSON_Array;
+ item->child = head;
+
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (head != NULL)
+ {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_element = item->child;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* Compose the output array. */
+ /* opening square bracket */
+ output_pointer = ensure(output_buffer, 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ *output_pointer = '[';
+ output_buffer->offset++;
+ output_buffer->depth++;
+
+ while (current_element != NULL)
+ {
+ if (!print_value(current_element, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+ if (current_element->next)
+ {
+ length = (size_t) (output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ',';
+ if(output_buffer->format)
+ {
+ *output_pointer++ = ' ';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+ }
+ current_element = current_element->next;
+ }
+
+ output_pointer = ensure(output_buffer, 2);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ']';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Build an object from the text. */
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* linked list head */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+ {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
+ {
+ goto fail; /* not an object */
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
+ {
+ goto success; /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0))
+ {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do
+ {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL)
+ {
+ /* start the linked list */
+ current_item = head = new_item;
+ }
+ else
+ {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse the name of the child */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_string(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse name */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ /* swap valuestring and string, because we parsed the name */
+ current_item->string = current_item->valuestring;
+ current_item->valuestring = NULL;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
+ {
+ goto fail; /* invalid object */
+ }
+
+ /* parse the value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ }
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
+ {
+ goto fail; /* expected end of object */
+ }
+
+success:
+ input_buffer->depth--;
+
+ if (head != NULL) {
+ head->prev = current_item;
+ }
+
+ item->type = cJSON_Object;
+ item->child = head;
+
+ input_buffer->offset++;
+ return true;
+
+fail:
+ if (head != NULL)
+ {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_item = item->child;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* Compose the output: */
+ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ *output_pointer++ = '{';
+ output_buffer->depth++;
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\n';
+ }
+ output_buffer->offset += length;
+
+ while (current_item)
+ {
+ if (output_buffer->format)
+ {
+ size_t i;
+ output_pointer = ensure(output_buffer, output_buffer->depth);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ for (i = 0; i < output_buffer->depth; i++)
+ {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += output_buffer->depth;
+ }
+
+ /* print key */
+ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ length = (size_t) (output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ':';
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += length;
+
+ /* print value */
+ if (!print_value(current_item, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ /* print comma if not last */
+ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ if (current_item->next)
+ {
+ *output_pointer++ = ',';
+ }
+
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\n';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+
+ current_item = current_item->next;
+ }
+
+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ if (output_buffer->format)
+ {
+ size_t i;
+ for (i = 0; i < (output_buffer->depth - 1); i++)
+ {
+ *output_pointer++ = '\t';
+ }
+ }
+ *output_pointer++ = '}';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Get Array size/item / object item. */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
+{
+ cJSON *child = NULL;
+ size_t size = 0;
+
+ if (array == NULL)
+ {
+ return 0;
+ }
+
+ child = array->child;
+
+ while(child != NULL)
+ {
+ size++;
+ child = child->next;
+ }
+
+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
+
+ return (int)size;
+}
+
+static cJSON* get_array_item(const cJSON *array, size_t index)
+{
+ cJSON *current_child = NULL;
+
+ if (array == NULL)
+ {
+ return NULL;
+ }
+
+ current_child = array->child;
+ while ((current_child != NULL) && (index > 0))
+ {
+ index--;
+ current_child = current_child->next;
+ }
+
+ return current_child;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
+{
+ if (index < 0)
+ {
+ return NULL;
+ }
+
+ return get_array_item(array, (size_t)index);
+}
+
+static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
+{
+ cJSON *current_element = NULL;
+
+ if ((object == NULL) || (name == NULL))
+ {
+ return NULL;
+ }
+
+ current_element = object->child;
+ if (case_sensitive)
+ {
+ while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
+ {
+ current_element = current_element->next;
+ }
+ }
+ else
+ {
+ while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
+ {
+ current_element = current_element->next;
+ }
+ }
+
+ if ((current_element == NULL) || (current_element->string == NULL)) {
+ return NULL;
+ }
+
+ return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
+{
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
+{
+ cJSON *reference = NULL;
+ if (item == NULL)
+ {
+ return NULL;
+ }
+
+ reference = cJSON_New_Item(hooks);
+ if (reference == NULL)
+ {
+ return NULL;
+ }
+
+ memcpy(reference, item, sizeof(cJSON));
+ reference->string = NULL;
+ reference->type |= cJSON_IsReference;
+ reference->next = reference->prev = NULL;
+ return reference;
+}
+
+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
+{
+ cJSON *child = NULL;
+
+ if ((item == NULL) || (array == NULL) || (array == item))
+ {
+ return false;
+ }
+
+ child = array->child;
+ /*
+ * To find the last item in array quickly, we use prev in array
+ */
+ if (child == NULL)
+ {
+ /* list is empty, start new one */
+ array->child = item;
+ item->prev = item;
+ item->next = NULL;
+ }
+ else
+ {
+ /* append to the end */
+ if (child->prev)
+ {
+ suffix_object(child->prev, item);
+ array->child->prev = item;
+ }
+ }
+
+ return true;
+}
+
+/* Add item to array/object. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+ return add_item_to_array(array, item);
+}
+
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+/* helper function to cast away const */
+static void* cast_away_const(const void* string)
+{
+ return (void*)string;
+}
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic pop
+#endif
+
+
+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
+{
+ char *new_key = NULL;
+ int new_type = cJSON_Invalid;
+
+ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
+ {
+ return false;
+ }
+
+ if (constant_key)
+ {
+ new_key = (char*)cast_away_const(string);
+ new_type = item->type | cJSON_StringIsConst;
+ }
+ else
+ {
+ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
+ if (new_key == NULL)
+ {
+ return false;
+ }
+
+ new_type = item->type & ~cJSON_StringIsConst;
+ }
+
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+ {
+ hooks->deallocate(item->string);
+ }
+
+ item->string = new_key;
+ item->type = new_type;
+
+ return add_item_to_array(object, item);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ return add_item_to_object(object, string, item, &global_hooks, false);
+}
+
+/* Add an item to an object with constant string as key */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+{
+ return add_item_to_object(object, string, item, &global_hooks, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ if (array == NULL)
+ {
+ return false;
+ }
+
+ return add_item_to_array(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+ if ((object == NULL) || (string == NULL))
+ {
+ return false;
+ }
+
+ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
+{
+ cJSON *null = cJSON_CreateNull();
+ if (add_item_to_object(object, name, null, &global_hooks, false))
+ {
+ return null;
+ }
+
+ cJSON_Delete(null);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
+{
+ cJSON *true_item = cJSON_CreateTrue();
+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
+ {
+ return true_item;
+ }
+
+ cJSON_Delete(true_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
+{
+ cJSON *false_item = cJSON_CreateFalse();
+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
+ {
+ return false_item;
+ }
+
+ cJSON_Delete(false_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
+{
+ cJSON *bool_item = cJSON_CreateBool(boolean);
+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
+ {
+ return bool_item;
+ }
+
+ cJSON_Delete(bool_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
+{
+ cJSON *number_item = cJSON_CreateNumber(number);
+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
+ {
+ return number_item;
+ }
+
+ cJSON_Delete(number_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
+{
+ cJSON *string_item = cJSON_CreateString(string);
+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
+ {
+ return string_item;
+ }
+
+ cJSON_Delete(string_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
+{
+ cJSON *raw_item = cJSON_CreateRaw(raw);
+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
+ {
+ return raw_item;
+ }
+
+ cJSON_Delete(raw_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
+{
+ cJSON *object_item = cJSON_CreateObject();
+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
+ {
+ return object_item;
+ }
+
+ cJSON_Delete(object_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
+{
+ cJSON *array = cJSON_CreateArray();
+ if (add_item_to_object(object, name, array, &global_hooks, false))
+ {
+ return array;
+ }
+
+ cJSON_Delete(array);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
+{
+ if ((parent == NULL) || (item == NULL))
+ {
+ return NULL;
+ }
+
+ if (item != parent->child)
+ {
+ /* not the first element */
+ item->prev->next = item->next;
+ }
+ if (item->next != NULL)
+ {
+ /* not the last element */
+ item->next->prev = item->prev;
+ }
+
+ if (item == parent->child)
+ {
+ /* first element */
+ parent->child = item->next;
+ }
+ else if (item->next == NULL)
+ {
+ /* last element */
+ parent->child->prev = item->prev;
+ }
+
+ /* make sure the detached item doesn't point anywhere anymore */
+ item->prev = NULL;
+ item->next = NULL;
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+ if (which < 0)
+ {
+ return NULL;
+ }
+
+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
+}
+
+/* Replace array/object items with new ones. */
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *after_inserted = NULL;
+
+ if (which < 0)
+ {
+ return false;
+ }
+
+ after_inserted = get_array_item(array, (size_t)which);
+ if (after_inserted == NULL)
+ {
+ return add_item_to_array(array, newitem);
+ }
+
+ newitem->next = after_inserted;
+ newitem->prev = after_inserted->prev;
+ after_inserted->prev = newitem;
+ if (after_inserted == array->child)
+ {
+ array->child = newitem;
+ }
+ else
+ {
+ newitem->prev->next = newitem;
+ }
+ return true;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
+{
+ if ((parent == NULL) || (replacement == NULL) || (item == NULL))
+ {
+ return false;
+ }
+
+ if (replacement == item)
+ {
+ return true;
+ }
+
+ replacement->next = item->next;
+ replacement->prev = item->prev;
+
+ if (replacement->next != NULL)
+ {
+ replacement->next->prev = replacement;
+ }
+ if (parent->child == item)
+ {
+ if (parent->child->prev == parent->child)
+ {
+ replacement->prev = replacement;
+ }
+ parent->child = replacement;
+ }
+ else
+ { /*
+ * To find the last item in array quickly, we use prev in array.
+ * We can't modify the last item's next pointer where this item was the parent's child
+ */
+ if (replacement->prev != NULL)
+ {
+ replacement->prev->next = replacement;
+ }
+ if (replacement->next == NULL)
+ {
+ parent->child->prev = replacement;
+ }
+ }
+
+ item->next = NULL;
+ item->prev = NULL;
+ cJSON_Delete(item);
+
+ return true;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ if (which < 0)
+ {
+ return false;
+ }
+
+ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
+{
+ if ((replacement == NULL) || (string == NULL))
+ {
+ return false;
+ }
+
+ /* replace the name in the replacement */
+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
+ {
+ cJSON_free(replacement->string);
+ }
+ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ replacement->type &= ~cJSON_StringIsConst;
+
+ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+ return replace_item_in_object(object, string, newitem, false);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
+{
+ return replace_item_in_object(object, string, newitem, true);
+}
+
+/* Create basic types: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_NULL;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_True;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = boolean ? cJSON_True : cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+
+ /* use saturation in case of overflow */
+ if (num >= INT_MAX)
+ {
+ item->valueint = INT_MAX;
+ }
+ else if (num <= (double)INT_MIN)
+ {
+ item->valueint = INT_MIN;
+ }
+ else
+ {
+ item->valueint = (int)num;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_String;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL)
+ {
+ item->type = cJSON_String | cJSON_IsReference;
+ item->valuestring = (char*)cast_away_const(string);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Object | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Array | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Raw;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type=cJSON_Array;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item)
+ {
+ item->type = cJSON_Object;
+ }
+
+ return item;
+}
+
+/* Create Arrays: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber((double)numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (strings == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for (i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateString(strings[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p,n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+/* Duplication */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
+{
+ cJSON *newitem = NULL;
+ cJSON *child = NULL;
+ cJSON *next = NULL;
+ cJSON *newchild = NULL;
+
+ /* Bail on bad ptr */
+ if (!item)
+ {
+ goto fail;
+ }
+ /* Create new item */
+ newitem = cJSON_New_Item(&global_hooks);
+ if (!newitem)
+ {
+ goto fail;
+ }
+ /* Copy over all vars */
+ newitem->type = item->type & (~cJSON_IsReference);
+ newitem->valueint = item->valueint;
+ newitem->valuedouble = item->valuedouble;
+ if (item->valuestring)
+ {
+ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
+ if (!newitem->valuestring)
+ {
+ goto fail;
+ }
+ }
+ if (item->string)
+ {
+ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
+ if (!newitem->string)
+ {
+ goto fail;
+ }
+ }
+ /* If non-recursive, then we're done! */
+ if (!recurse)
+ {
+ return newitem;
+ }
+ /* Walk the ->next chain for the child. */
+ child = item->child;
+ while (child != NULL)
+ {
+ newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild)
+ {
+ goto fail;
+ }
+ if (next != NULL)
+ {
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ next->next = newchild;
+ newchild->prev = next;
+ next = newchild;
+ }
+ else
+ {
+ /* Set newitem->child and move to it */
+ newitem->child = newchild;
+ next = newchild;
+ }
+ child = child->next;
+ }
+ if (newitem && newitem->child)
+ {
+ newitem->child->prev = newchild;
+ }
+
+ return newitem;
+
+fail:
+ if (newitem != NULL)
+ {
+ cJSON_Delete(newitem);
+ }
+
+ return NULL;
+}
+
+static void skip_oneline_comment(char **input)
+{
+ *input += static_strlen("//");
+
+ for (; (*input)[0] != '\0'; ++(*input))
+ {
+ if ((*input)[0] == '\n') {
+ *input += static_strlen("\n");
+ return;
+ }
+ }
+}
+
+static void skip_multiline_comment(char **input)
+{
+ *input += static_strlen("/*");
+
+ for (; (*input)[0] != '\0'; ++(*input))
+ {
+ if (((*input)[0] == '*') && ((*input)[1] == '/'))
+ {
+ *input += static_strlen("*/");
+ return;
+ }
+ }
+}
+
+static void minify_string(char **input, char **output) {
+ (*output)[0] = (*input)[0];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+
+
+ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
+ (*output)[0] = (*input)[0];
+
+ if ((*input)[0] == '\"') {
+ (*output)[0] = '\"';
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+ return;
+ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
+ (*output)[1] = (*input)[1];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+ }
+ }
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+ char *into = json;
+
+ if (json == NULL)
+ {
+ return;
+ }
+
+ while (json[0] != '\0')
+ {
+ switch (json[0])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ json++;
+ break;
+
+ case '/':
+ if (json[1] == '/')
+ {
+ skip_oneline_comment(&json);
+ }
+ else if (json[1] == '*')
+ {
+ skip_multiline_comment(&json);
+ } else {
+ json++;
+ }
+ break;
+
+ case '\"':
+ minify_string(&json, (char**)&into);
+ break;
+
+ default:
+ into[0] = json[0];
+ json++;
+ into++;
+ }
+ }
+
+ /* and null-terminate. */
+ *into = '\0';
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_False;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xff) == cJSON_True;
+}
+
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_NULL;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Number;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_String;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Array;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Object;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Raw;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
+{
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
+ {
+ return false;
+ }
+
+ /* check if type is valid */
+ switch (a->type & 0xFF)
+ {
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ case cJSON_Number:
+ case cJSON_String:
+ case cJSON_Raw:
+ case cJSON_Array:
+ case cJSON_Object:
+ break;
+
+ default:
+ return false;
+ }
+
+ /* identical objects are equal */
+ if (a == b)
+ {
+ return true;
+ }
+
+ switch (a->type & 0xFF)
+ {
+ /* in these cases and equal type is enough */
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ return true;
+
+ case cJSON_Number:
+ if (compare_double(a->valuedouble, b->valuedouble))
+ {
+ return true;
+ }
+ return false;
+
+ case cJSON_String:
+ case cJSON_Raw:
+ if ((a->valuestring == NULL) || (b->valuestring == NULL))
+ {
+ return false;
+ }
+ if (strcmp(a->valuestring, b->valuestring) == 0)
+ {
+ return true;
+ }
+
+ return false;
+
+ case cJSON_Array:
+ {
+ cJSON *a_element = a->child;
+ cJSON *b_element = b->child;
+
+ for (; (a_element != NULL) && (b_element != NULL);)
+ {
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
+ {
+ return false;
+ }
+
+ a_element = a_element->next;
+ b_element = b_element->next;
+ }
+
+ /* one of the arrays is longer than the other */
+ if (a_element != b_element) {
+ return false;
+ }
+
+ return true;
+ }
+
+ case cJSON_Object:
+ {
+ cJSON *a_element = NULL;
+ cJSON *b_element = NULL;
+ cJSON_ArrayForEach(a_element, a)
+ {
+ /* TODO This has O(n^2) runtime, which is horrible! */
+ b_element = get_object_item(b, a_element->string, case_sensitive);
+ if (b_element == NULL)
+ {
+ return false;
+ }
+
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
+ {
+ return false;
+ }
+ }
+
+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
+ * TODO: Do this the proper way, this is just a fix for now */
+ cJSON_ArrayForEach(b_element, b)
+ {
+ a_element = get_object_item(a, b_element->string, case_sensitive);
+ if (a_element == NULL)
+ {
+ return false;
+ }
+
+ if (!cJSON_Compare(b_element, a_element, case_sensitive))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
+{
+ return global_hooks.allocate(size);
+}
+
+CJSON_PUBLIC(void) cJSON_free(void *object)
+{
+ global_hooks.deallocate(object);
+}
diff --git a/thirdparty/cjson/cJSON.h b/thirdparty/cjson/cJSON.h
new file mode 100644
index 0000000..92907a2
--- /dev/null
+++ b/thirdparty/cjson/cJSON.h
@@ -0,0 +1,293 @@
+/*
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
+
+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+For *nix builds that support visibility attribute, you can define similar behavior by
+
+setting default visibility to hidden by adding
+-fvisibility=hidden (for gcc)
+or
+-xldscope=hidden (for sun cc)
+to CFLAGS
+
+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+*/
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type) type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
+/* project version */
+#define CJSON_VERSION_MAJOR 1
+#define CJSON_VERSION_MINOR 7
+#define CJSON_VERSION_PATCH 15
+
+#include <stddef.h>
+
+/* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False (1 << 0)
+#define cJSON_True (1 << 1)
+#define cJSON_NULL (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw (1 << 7) /* raw json */
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON
+{
+ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *next;
+ struct cJSON *prev;
+ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+ struct cJSON *child;
+
+ /* The type of the item, as above. */
+ int type;
+
+ /* The item's string, if type==cJSON_String and type == cJSON_Raw */
+ char *valuestring;
+ /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
+ int valueint;
+ /* The item's number, if type==cJSON_Number */
+ double valuedouble;
+
+ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+ char *string;
+} cJSON;
+
+typedef struct cJSON_Hooks
+{
+ /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+ void *(CJSON_CDECL *malloc_fn)(size_t sz);
+ void (CJSON_CDECL *free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef int cJSON_bool;
+
+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_NESTING_LIMIT
+#define CJSON_NESTING_LIMIT 1000
+#endif
+
+/* returns the version of cJSON as a string */
+CJSON_PUBLIC(const char*) cJSON_Version(void);
+
+/* Supply malloc, realloc and free functions to cJSON */
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
+
+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
+
+/* Render a cJSON entity to text for transfer/storage. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. */
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
+/* Delete a cJSON entity and all subentities. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
+
+/* Returns the number of items in an array (or object). */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
+/* Get item "string" from object. Case insensitive. */
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+
+/* Check item type and return its value */
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
+
+/* These functions check the type of an item */
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
+
+/* These calls create a cJSON item of the appropriate type. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
+/* raw json */
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
+
+/* Create a string where valuestring references a string so
+ * it will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
+/* Create an object/array that only references it's elements so
+ * they will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
+
+/* These utilities create an Array of count items.
+ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
+
+/* Append item to the specified array/object. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
+ * writing to `item->string` */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detach items from Arrays/Objects. */
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
+
+/* Update array items. */
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.
+ * The item->next and ->prev pointers are always zero on return from Duplicate. */
+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
+
+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
+ * The input pointer json cannot point to a read-only address area, such as a string constant,
+ * but should point to a readable and writable address area. */
+CJSON_PUBLIC(void) cJSON_Minify(char *json);
+
+/* Helper functions for creating and adding items to an object at the same time.
+ * They return the added item or NULL on failure. */
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+/* helper for the cJSON_SetNumberValue macro */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
+
+/* Macro for iterating over an array or object */
+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
+
+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
+CJSON_PUBLIC(void) cJSON_free(void *object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/kunpengsecl/verifier/custom_base64url.h b/thirdparty/kunpengsecl/verifier/custom_base64url.h
new file mode 100644
index 0000000..1e003da
--- /dev/null
+++ b/thirdparty/kunpengsecl/verifier/custom_base64url.h
@@ -0,0 +1,20 @@
+/*
+kunpengsecl licensed under the Mulan PSL v2.
+You can use this software according to the terms and conditions of
+the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
+ http://license.coscl.org.cn/MulanPSL2
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+See the Mulan PSL v2 for more details.
+*/
+
+#ifndef CUSTOM_BASE64URL_H
+#define CUSTOM_BASE64URL_H
+
+#include <stdlib.h>
+
+void base64urlencode(const uint8_t *src, int src_len, uint8_t *cipher, int *dest_len);
+uint8_t *base64urldecode(const uint8_t *src, int src_len, int *dest_len);
+
+#endif
diff --git a/thirdparty/kunpengsecl/verifier/teeverifier.h b/thirdparty/kunpengsecl/verifier/teeverifier.h
new file mode 100644
index 0000000..4a311f6
--- /dev/null
+++ b/thirdparty/kunpengsecl/verifier/teeverifier.h
@@ -0,0 +1,50 @@
+/*
+kunpengsecl licensed under the Mulan PSL v2.
+You can use this software according to the terms and conditions of
+the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
+ http://license.coscl.org.cn/MulanPSL2
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+See the Mulan PSL v2 for more details.
+*/
+
+#ifndef __VERIFIER_LIB__
+#define __VERIFIER_LIB__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#define UUID_SIZE 16
+#define HASH_SIZE 32
+//Attester will send the report by this type
+typedef struct{
+ uint32_t size;
+ uint8_t *buf;
+} buffer_data;
+
+typedef struct
+{
+ uint8_t uuid[UUID_SIZE];
+ uint8_t valueinfo[2][HASH_SIZE]; // valueinfo[0]=img measurement and valueinfo[1]=mem measurement
+} base_value;
+
+enum error_status_code {
+ TVS_ALL_SUCCESSED = 0,
+ TVS_VERIFIED_NONCE_FAILED = -1,
+ TVS_VERIFIED_SIGNATURE_FAILED = -2,
+ TVS_VERIFIED_HASH_FAILED = -3,
+};
+
+int tee_verify_report(buffer_data *data_buf,buffer_data *nonce,int type, char *filename);
+int tee_validate_report(buffer_data *buf_data, buffer_data *nonce);
+int tee_verify_report2(buffer_data *buf_data, int type,base_value *baseval);
+bool tee_verify_akcert(buffer_data *akcert, int type, const char *refval);
+bool tee_get_akcert_data(buffer_data *akcert, buffer_data *akpub, buffer_data *drkcrt);
+
+#endif
diff --git a/thirdparty/libqca/ra_client_api.h b/thirdparty/libqca/ra_client_api.h
new file mode 100644
index 0000000..dd793a3
--- /dev/null
+++ b/thirdparty/libqca/ra_client_api.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
+ * Licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+#ifndef LIBQCA_H
+#define LIBQCA_H
+#include <tee_client_type.h>
+
+struct ra_buffer_data {
+ uint32_t size;
+ uint8_t *buf;
+};
+
+TEEC_Result RemoteAttest(struct ra_buffer_data *in, struct ra_buffer_data *out);
+#endif
diff --git a/tools/sign_tool/generate_signature.py b/tools/sign_tool/generate_signature.py
deleted file mode 100644
index b3264ba..0000000
--- a/tools/sign_tool/generate_signature.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# coding:utf-8
-#----------------------------------------------------------------------------
-# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
-# iTrustee licensed under the Mulan PSL v2.
-# You can use this software according to the terms and conditions of the Mulan
-# PSL v2.
-# You may obtain a copy of Mulan PSL v2 at:
-# http://license.coscl.org.cn/MulanPSL2
-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
-# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-# See the Mulan PSL v2 for more details.
-# Description: tools for generating a trusted application load image
-# Author: Li mingjuan
-# Create: 2020-10-27
-#----------------------------------------------------------------------------
-
-import struct
-import os
-import hashlib
-import subprocess
-
-HASH256 = 0
-HASH512 = 1
-
-def gen_hash(hash_type, in_file_path, out_file_path):
- in_file_size = os.path.getsize(in_file_path)
- # Initialize a SHA256 object from the Python hash library
- if int(hash_type) == HASH256:
- hash_op = hashlib.sha256()
- elif int(hash_type) == HASH512:
- hash_op = hashlib.sha512()
- # Set the input buffer and return the output digest
- with open(in_file_path, 'rb') as in_file:
- hash_op.update(in_file.read(in_file_size))
-
- #-----hash file used for ras sign---
- with open(out_file_path, 'wb') as hash_fp:
- # fixed hash prefix value
- hash_fp.write(struct.pack('B'*19, 0x30, 0x31, 0x30, 0x0d, 0x06, \
- 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, \
- 0x05, 0x00, 0x04, 0x20))
- hash_fp.write(hash_op.digest())
- return
-
-def gen_ta_signature(cfg, hash_file_path, out_file_path):
- cmd = "openssl rsautl -sign -inkey {} -in {} -out {}".\
- format(cfg.sign_key, hash_file_path, out_file_path)
- try:
- subprocess.check_output(cmd.split(), shell=False)
- except Exception:
- print("sign operation failed")
- raise RuntimeError
- return
-
diff --git a/tools/sign_tool/manifest.py b/tools/sign_tool/manifest.py
deleted file mode 100644
index 9cc2360..0000000
--- a/tools/sign_tool/manifest.py
+++ /dev/null
@@ -1,322 +0,0 @@
-#!/usr/bin/env python
-# coding:utf-8
-#----------------------------------------------------------------------------
-# Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved.
-# iTrustee licensed under the Mulan PSL v2.
-# You can use this software according to the terms and conditions of the Mulan
-# PSL v2.
-# You may obtain a copy of Mulan PSL v2 at:
-# http://license.coscl.org.cn/MulanPSL2
-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
-# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-# See the Mulan PSL v2 for more details.
-# Description: tools for generating a trusted application load image
-# Author: Li mingjuan
-# Create: 2018-02-20
-#----------------------------------------------------------------------------
-import string
-import struct
-import uuid
-import os
-
-PRODUCT_TA_IMAGE = 1
-PRODUCT_DYN_LIB = 2
-PRODUCT_SERVICE_IMAGE = 3
-
-
-class PackUuid:
- # Structure object to align and package the TEE_UUID
- data = struct.Struct('IHH8b')
-
- def __init__(self, data):
- unpacked_data = (PackUuid.data).unpack(str.encode(data))
- self.unpacked_data = unpacked_data
- self.time_low = unpacked_data[0]
- self.time_mid = unpacked_data[1]
- self.time_hi_version = unpacked_data[2]
- self.clock_seq_node = unpacked_data[3]
-
- def print_values(self):
- print("ATTRIBUTE / VALUE")
- for attr, value in self.__dict__.items():
- print(attr, value)
-
- def get_pack_data(self):
- values = [self.time_low,
- self.time_mid,
- self.time_hi_version,
- self.clock_seq_node,
- ]
-
- return (PackUuid.data).pack(*values)
-
-
-#----------------------------------------------------------------------------
-# Manifest
-#----------------------------------------------------------------------------
-class Manifest:
-
- # Structure object to align and package the Manifest
- data = struct.Struct('I' * 6)
-
- def __init__(self, data):
- unpacked_data = (Manifest.data).unpack(str.encode(data))
- self.unpacked_data = unpacked_data
- self.single_instance = unpacked_data[0]
- self.multi_session = unpacked_data[1]
- self.multi_command = unpacked_data[2]
- self.heap_size = unpacked_data[3]
- self.stack_size = unpacked_data[4]
- self.instancekeepalive = unpacked_data[5]
-
- def print_values(self):
- print("ATTRIBUTE / VALUE")
- for attr, value in self.__dict__.items():
- print(attr, value)
-
- def get_pack_data(self):
- values = [self.single_instance,
- self.multi_session,
- self.multi_command,
- self.heap_size,
- self.stack_size,
- self.instancekeepalive,
- ]
-
- return (Manifest.data).pack(*values)
-
-
-#----------------------------------------------------------------------------
-# verify property name in manifest file
-#----------------------------------------------------------------------------
-def verify_property_name(str_line):
- print('verify property name')
- alphas = string.ascii_letters + string.digits
- cont = "".join([alphas, '-', '_', '.'])
- if len(str_line) > 1:
- if str_line[0] not in alphas:
- print('invalid first letter in property name')
- return False
- else:
- for otherchar in str_line[1:]:
- if otherchar not in cont:
- print('invalid char in property name')
- return False
- else:
- print('invalid property name')
- return False
-
- return True
-
-
-#----------------------------------------------------------------------------
-# verify property value in manifest file
-#----------------------------------------------------------------------------
-def verify_property_value(str_line):
- print('verify property value')
- filt_letter = chr(0) + chr(10) + chr(13)
- for thechar in str_line:
- if thechar in filt_letter:
- print('invalid letter in prop value')
- return False
- return True
-
-
-#----------------------------------------------------------------------------
-# remove tabs and space in property value
-#----------------------------------------------------------------------------
-def trailing_space_tabs(str_line):
- print('trailing space tabs in value head and trail')
- space_tabs = chr(9) + chr(32) + chr(160)
- space_tabs_newlines = space_tabs + chr(10) + chr(13)
- print('tab: {}'.format(space_tabs))
-
- print('str in: {}'.format(str_line))
- index = 0
- for thechar in str_line:
- if thechar in space_tabs:
- index += 1
- else:
- break
- headvalue = str_line[index:]
-
- strlen = len(headvalue)
-
- strlen -= 1
-
- while strlen > 0:
- if headvalue[strlen] in space_tabs_newlines:
- strlen -= 1
- else:
- break
-
- str_ret = headvalue[0:strlen+1] + chr(10)
- print('str ret: {}'.format(str_ret))
-
- return str_ret
-
-
-#----------------------------------------------------------------------------
-# verify manifest file, parse manifest file, generate a new manfiest file
-#----------------------------------------------------------------------------
-def parser_manifest(manifest, manifest_data_path, mani_ext):
- print('verify manifest')
- target_type = PRODUCT_TA_IMAGE
-
- uuid_val = PackUuid('\0' * 16)
-
- #manifest default
- manifest_val = Manifest('\0'*24)
-
- manifest_val.single_instance = 1
- manifest_val.multi_session = 0
- manifest_val.multi_command = 0
- manifest_val.instancekeepalive = 0
- manifest_val.heap_size = 16384
- manifest_val.stack_size = 2048
-
- service_name = 'external_service'
-
- with open(manifest, 'r') as mani_fp, open(mani_ext, 'wb') as mani_ext_fp:
- for each_line in mani_fp:
- print(each_line)
- if each_line.startswith("#") or not len(each_line.strip()):
- continue
- index = each_line.find(':', 1, len(each_line))
-
- prop_name = each_line[0:index]
- prop_name_t = each_line[0:index+1]
- prop_value_t = each_line[index+1:]
- print('name is: {}; value is: {}'.format(prop_name, prop_value_t))
-
- prop_value = trailing_space_tabs(prop_value_t)
- prop_len = len(prop_value)
- prop_value_v = prop_value[0:prop_len-1]
- print('prop value_v: {}'.format(prop_value_v))
-
- if verify_property_name(prop_name) is False:
- print('manifest format invalid, please check it')
- return (False, 0)
-
- if verify_property_value(prop_value_v) is False:
- print('manifest format invalid, please check it')
- return (False, 0)
-
- # name:value to lowcase, and parse manifest
- prop_name_low = prop_name.lower()
- print("name lower: {}".format(prop_name_low))
- if 'gpd.ta.appid' == prop_name_low:
- print("compare name is srv id")
- uuid_val = uuid.UUID(prop_value_v)
- print('uuid str {}'.format(uuid_val))
- print('val fields {}'.format(uuid_val.fields))
-
- elif 'gpd.ta.singleinstance' == prop_name_low:
- prop_value_low = prop_value_v.lower()
- if 'true' == prop_value_low:
- manifest_val.single_instance = 1
- elif 'false' == prop_value_low:
- manifest_val.single_instance = 0
- else:
- print('single_instance value error!')
-
- elif 'gpd.ta.multisession' == prop_name_low:
- prop_value_low = prop_value_v.lower()
- if 'true' == prop_value_low:
- manifest_val.multi_session = 1
- elif 'false' == prop_value_low:
- manifest_val.multi_session = 0
- else:
- print('multi_session value error!')
-
- elif 'gpd.ta.multicommand' == prop_name_low:
- prop_value_low = prop_value_v.lower()
- if 'true' == prop_value_low:
- manifest_val.multi_command = 1
- elif 'false' == prop_value_low:
- manifest_val.multi_command = 0
- else:
- print('multi_command value error!')
-
- elif 'gpd.ta.instancekeepalive' == prop_name_low:
- prop_value_low = prop_value_v.lower()
- if 'true' == prop_value_low:
- manifest_val.instancekeepalive = 1
- elif 'false' == prop_value_low:
- manifest_val.instancekeepalive = 0
- else:
- print('instancekeepalive value error!')
-
- elif 'gpd.ta.datasize' == prop_name_low:
- manifest_val.heap_size = int(prop_value_v)
- print('b')
-
- elif 'gpd.ta.stacksize' == prop_name_low:
- manifest_val.stack_size = int(prop_value_v)
- print('b')
-
- elif 'gpd.ta.service_name' == prop_name_low:
- service_name = prop_value_v
- print('b')
-
- else:
- print('b')
- #write have not paresed manifest into sample.manifest file
- mani_ext_fp.write(str.encode(prop_name_t))
- mani_ext_fp.write(str.encode(prop_value))
- if 'gpd.ta.is_tee_service' == prop_name_low:
- prop_value_low = prop_value_v.lower()
- if 'true' == prop_value_low:
- target_type = PRODUCT_SERVICE_IMAGE
- elif 'gpd.ta.is_lib' == prop_name_low:
- prop_value_low = prop_value_v.lower()
- if 'true' == prop_value_low:
- target_type = PRODUCT_DYN_LIB
-
- #write the whole parsed manifest into sample.manifest file
-
- service_name_len = len(service_name)
- print('service name: {}'.format(service_name))
- print('service name len: {}'.format(service_name_len))
- if service_name_len > 64:
- print("service name len exceed MAX value 27")
- raise RuntimeError
-
- # get manifest string file len
- manifest_str_size = os.path.getsize(mani_ext)
- print('manifest str size {}'.format(manifest_str_size))
-
- # 2> manifest + service_name
- print("bytes len {}".format(len(uuid_val.bytes_le)))
- print("bytes len {}".format(len(manifest_val.get_pack_data())))
- print("bytes len {}".format(len(service_name)))
-
- # 3> unparsed manifest, string manifest
- with open(mani_ext, 'rb') as string_mani_fp:
- print("read manifest string size {}".format(manifest_str_size))
- manifest_string_buf = string_mani_fp.read(manifest_str_size)
- print("manifest strint: {}".format(manifest_string_buf))
-
- #---- write manifest parse context to manifest file
- with open(manifest_data_path, 'wb') as out_manifest_fp:
- out_manifest_fp.write(uuid_val.bytes_le)
- out_manifest_fp.write(str.encode(service_name))
- out_manifest_fp.write(manifest_val.get_pack_data())
-
- product_name = str(uuid_val)
- if target_type == PRODUCT_TA_IMAGE:
- print("product type is ta image")
- product_name = "".join([product_name, ".sec"])
- elif target_type == PRODUCT_SERVICE_IMAGE:
- print("product type is service")
- product_name = "".join([product_name, service_name, "_svr.sec"])
- elif target_type == PRODUCT_DYN_LIB:
- print("product type is dyn lib")
- product_name = "".join([product_name, service_name, ".so.sec"])
- else:
- print("invalid product type!")
- raise RuntimeError
-
- return (True, product_name)
-
diff --git a/tools/sign_tool/sign_tool.sh b/tools/sign_tool/sign_tool.sh
index daca711..f150aed 100755
--- a/tools/sign_tool/sign_tool.sh
+++ b/tools/sign_tool/sign_tool.sh
@@ -1,27 +1,10 @@
-# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
-# secGear is licensed under the Mulan PSL v2.
-# You can use this software according to the terms and conditions of the Mulan PSL v2.
-# You may obtain a copy of Mulan PSL v2 at:
-# http://license.coscl.org.cn/MulanPSL2
-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
-# PURPOSE.
-# See the Mulan PSL v2 for more details.
-
#!/bin/bash
-VERSION=3
API_LEVEL=2
ONE_STEP_MODE=1
-localpath="$(cd "$(dirname "$0")"; pwd)"
-pypath="/lib/secGear"
-if [ -f ${localpath}/signtool_v3.py ]; then
- signtoolpath=${localpath}
-else
- signtoolpath=${pypath}
-fi
+signtoolpath="/opt/itrustee_sdk/build/signtools/"
-print_help(){
+print_help() {
echo "sign tool usage: ./sign_tool.sh [options] ..."
echo "[options]"
echo "-c <file> basic config file."
@@ -31,8 +14,8 @@ print_help(){
echo " The dump command is used to generate metadata for sgx signed enclave."
echo "-i <file> input parameter, which is enclave to be signed for digest/sign command, and signed enclave for"
echo " dump command."
- echo "-k <file> private key required for single-step method. NOTE: single-step method is only for the dubug mode,"
- echo " plaintext private key does exist in the production environment."
+ echo "-k <file> private key required for single-step method. Note: single-step method is only for the debug mode,"
+ echo "-k <file> plaintext private key does exist in the production environment."
echo "-m <file> additional config_cloud.ini for trustzone."
echo "-o <file> output parameter, the sign command outputs signed enclave, the digest command outputs signing"
echo " material, the dump command outputs data containing the SIGStruct metadata for the SGX signed"
@@ -45,81 +28,81 @@ print_help(){
}
-while getopts "c:d:i:k:m:o:p:s:x:h" opt
-do
+while getopts "c:d:i:k:m:o:p:s:x:h" opt; do
case $opt in
c)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -c is missing or incorrect"
- exit -1
- fi
- CONFIG_FILE=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -c is missing or incorrect"
+ exit 1
+ fi
+ CONFIG_FILE=$OPTARG
+ ;;
d)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -d is missing or incorrect"
- exit -1
- fi
- typeset -l CMD
- CMD=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -d is missing or incorrect"
+ exit 1
+ fi
+ typeset -l CMD
+ CMD=$OPTARG
+ ;;
i)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -i is missing or incorrect"
- exit -1
- fi
- IN_ENCLAVE=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -i is missing or incorrect"
+ exit 1
+ fi
+ IN_ENCLAVE=$OPTARG
+ ;;
k)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -k is missing or incorrect"
- exit -1
- fi
- SIG_KEY=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -k is missing or incorrect"
+ exit 1
+ fi
+ SIG_KEY=$OPTARG
+ ;;
m)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -m is missing or incorrect"
- exit -1
- fi
- A_CONFIG_FILE=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -m is missing or incorrect"
+ exit 1
+ fi
+ A_CONFIG_FILE=$OPTARG
+ ;;
o)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -o is missing or incorrect"
- exit -1
- fi
- OUT_FILE=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -o is missing or incorrect"
+ exit 1
+ fi
+ OUT_FILE=$OPTARG
+ ;;
p)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -p is missing or incorrect"
- exit -1
- fi
- SERVER_PUBKEY=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -p is missing or incorrect"
+ exit 1
+ fi
+ SERVER_PUBKEY=$OPTARG
+ ;;
s)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -s is missing or incorrect"
- exit -1
- fi
- SIGNATURE=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -s is missing or incorrect"
+ exit 1
+ fi
+ SIGNATURE=$OPTARG
+ ;;
x)
- if [[ $OPTARG == -* ]]; then
- echo "Error: parameter for -x is missing or incorrect"
- exit -1
- fi
- typeset -l ENCLAVE_TYPE
- ENCLAVE_TYPE=$OPTARG
- ;;
+ if [[ $OPTARG == -* ]]; then
+ echo "Error: parameter for -x is missing or incorrect"
+ exit 1
+ fi
+ typeset -l ENCLAVE_TYPE
+ ENCLAVE_TYPE=$OPTARG
+ ;;
h)
- print_help
- exit 0
- ;;
+ print_help
+ exit 0
+ ;;
?)
- print_help
- exit -1
+ print_help
+ exit 1
+ ;;
esac
done
if [ ${OPTIND} == 1 ]; then
@@ -127,103 +110,82 @@ if [ ${OPTIND} == 1 ]; then
exit 0
fi
-itrustee_start_sign(){
-# check_native_sign
- if [ -z $A_CONFIG_FILE ]; then
+itrustee_start_sign() {
+ # check_native_sign
+ if [ -z "$A_CONFIG_FILE" ]; then
echo "Error: missing additional config_cloud.ini file for signing iTrustee enclave"
- exit -1
+ exit 1
fi
if [ "${CMD}"x == "sign"x ]; then
- if [ -z $SIGNATURE ]; then
- ONE_STEP_MODE=1
- if [ -z $CONFIG_FILE ]; then
- echo "Error: missing basic config file for signing iTrustee enclave"
- exit -1
- fi
- if [ -z $IN_ENCLAVE ]; then
- echo "Error: missing enclave file"
- exit -1
- fi
- python ${signtoolpath}/signtool_v3.py "sign" "${ONE_STEP_MODE}" "${IN_ENCLAVE}" "${OUT_FILE}" "${CONFIG_FILE}" "${A_CONFIG_FILE}" "${API_LEVEL}"
- else
- ONE_STEP_MODE=0
- python ${signtoolpath}/signtool_v3.py "sign" "${ONE_STEP_MODE}" "NULL" "${OUT_FILE}" "NULL" "${A_CONFIG_FILE}" "${API_LEVEL}" "${SIGNATURE}"
- fi
- elif [ "${CMD}"x == "digest"x ]; then
- ONE_STEP_MODE=0
- if [ -z $CONFIG_FILE ]; then
- echo "Error: missing config file for signing iTrustee enclave"
- exit -1
- fi
- if [ -z $IN_ENCLAVE ]; then
- echo "Error: missing enclave file"
- exit -1
- fi
- python ${signtoolpath}/signtool_v3.py "digest" "${ONE_STEP_MODE}" "${IN_ENCLAVE}" "${OUT_FILE}" "${CONFIG_FILE}" "${A_CONFIG_FILE}" "${API_LEVEL}"
+ IN_PATH=$(dirname ${CONFIG_FILE})
+ cp ${IN_ENCLAVE} ${IN_PATH}/libcombine.so
+ OUT_PATH=$(dirname ${OUT_FILE})
+ echo ${IN_PATH} ${OUT_PATH}
+ python -B ${signtoolpath}/signtool_v3.py ${IN_PATH} ${OUT_PATH} --privateCfg ${A_CONFIG_FILE}
+ #rm -rf ${IN_PATH}/libcombine.so
else
echo "Error: illegal command"
fi
}
-sgx_start_sign(){
- if [ -z $IN_ENCLAVE ]; then
+sgx_start_sign() {
+ if [ -z "$IN_ENCLAVE" ]; then
echo "Error: missing enclave file"
- exit -1
+ exit 1
fi
SIGDATA_FILE="signdata"
if [ "${CMD}"x == "sign"x ]; then
- if [ -z $SIGNATURE ]; then
- if [ -z $SIG_KEY ]; then
- echo "Error: missing sign key"
- exit -1
- fi
- if [ -z $CONFIG_FILE ]; then
- sgx_sign sign -enclave ${IN_ENCLAVE} -key ${SIG_KEY} -out ${OUT_FILE}
+ if [ -z "$SIGNATURE" ]; then
+ if [ -z "$SIG_KEY" ]; then
+ echo "Error: missing sign key"
+ exit 1
+ fi
+ if [ -z "$CONFIG_FILE" ]; then
+ sgx_sign sign -enclave "${IN_ENCLAVE}" -key "${SIG_KEY}" -out "${OUT_FILE}"
else
- sgx_sign sign -enclave ${IN_ENCLAVE} -key ${SIG_KEY} -out ${OUT_FILE} -config ${CONFIG_FILE}
+ sgx_sign sign -enclave "${IN_ENCLAVE}" -key "${SIG_KEY}" -out "${OUT_FILE}" -config "${CONFIG_FILE}"
fi
else
- if [ -z $SERVER_PUBKEY ]; then
+ if [ -z "$SERVER_PUBKEY" ]; then
echo "Error: missing server public key"
- exit -1
- fi
- if [ -z $CONFIG_FILE ]; then
- sgx_sign catsig -enclave ${IN_ENCLAVE} -key ${SERVER_PUBKEY} -sig ${SIGNATURE} -unsigned ${SIGDATA_FILE} -out ${OUT_FILE}
+ exit 1
+ fi
+ if [ -z "$CONFIG_FILE" ]; then
+ sgx_sign catsig -enclave "${IN_ENCLAVE}" -key "${SERVER_PUBKEY}" -sig "${SIGNATURE}" -unsigned "${SIGDATA_FILE}" -out "${OUT_FILE}"
else
- sgx_sign catsig -enclave ${IN_ENCLAVE} -key ${SERVER_PUBKEY} -sig ${SIGNATURE} -unsigned ${SIGDATA_FILE} -out ${OUT_FILE} -config ${CONFIG_FILE}
+ sgx_sign catsig -enclave "${IN_ENCLAVE}" -key "${SERVER_PUBKEY}" -sig "${SIGNATURE}" -unsigned "${SIGDATA_FILE}" -out "${OUT_FILE}" -config "${CONFIG_FILE}"
fi
rm -rf ${SIGDATA_FILE}
fi
elif [ "${CMD}"x == "digest"x ]; then
- if [ -z $CONFIG_FILE ]; then
- sgx_sign gendata -enclave ${IN_ENCLAVE} -out ${SIGDATA_FILE}
+ if [ -z "$CONFIG_FILE" ]; then
+ sgx_sign gendata -enclave "${IN_ENCLAVE}" -out "${SIGDATA_FILE}"
else
- sgx_sign gendata -enclave ${IN_ENCLAVE} -out ${SIGDATA_FILE} -config ${CONFIG_FILE}
+ sgx_sign gendata -enclave "${IN_ENCLAVE}" -out "${SIGDATA_FILE}" -config "${CONFIG_FILE}"
fi
- cp ${SIGDATA_FILE} ${OUT_FILE}
+ cp "${SIGDATA_FILE}" "${OUT_FILE}"
elif [ "${CMD}"x == "dump"x ]; then
- sgx_sign dump -enclave ${IN_ENCLAVE} -dumpfile ${OUT_FILE}
+ sgx_sign dump -enclave "${IN_ENCLAVE}" -dumpfile "${OUT_FILE}"
else
echo "Error: illegal command"
fi
}
-
-if [ -z $CMD ]; then
+if [ -z "$CMD" ]; then
echo "Error: missing command"
- exit -1
+ exit 1
fi
-if [ -z $ENCLAVE_TYPE ]; then
+if [ -z "$ENCLAVE_TYPE" ]; then
echo "Error: missing enclave type"
- exit -1
+ exit 1
fi
-if [ -z $OUT_FILE ]; then
+if [ -z "$OUT_FILE" ]; then
echo "Error: missing out file"
- exit -1
+ exit 1
fi
umask 0077
-check_results=`uname -m`
+check_results=$(uname -m)
if [ "${ENCLAVE_TYPE}"x == "sgx"x ]; then
if [ "${check_results}"x != "x86_64"x ]; then
echo "Warning: the enclave type does not comply with current architecture"
@@ -236,5 +198,5 @@ elif [ "${ENCLAVE_TYPE}"x == "trustzone"x ]; then
itrustee_start_sign
else
echo "Error: illegal enclave type"
- exit -1
+ exit 1
fi
diff --git a/tools/sign_tool/signtool_v3.py b/tools/sign_tool/signtool_v3.py
deleted file mode 100644
index dae036f..0000000
--- a/tools/sign_tool/signtool_v3.py
+++ /dev/null
@@ -1,428 +0,0 @@
-#!/usr/bin/env python
-# coding:utf-8
-#----------------------------------------------------------------------------
-# Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved.
-# iTrustee licensed under the Mulan PSL v2.
-# You can use this software according to the terms and conditions of the Mulan
-# PSL v2.
-# You may obtain a copy of Mulan PSL v2 at:
-# http://license.coscl.org.cn/MulanPSL2
-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
-# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-# See the Mulan PSL v2 for more details.
-# Description: tools for generating a trusted application load image
-# Author: Li mingjuan
-# Create: 2018-02-20
-#----------------------------------------------------------------------------
-
-import struct
-import os
-import sys
-import stat
-import hashlib
-import binascii
-import subprocess
-import shutil
-import getpass
-import argparse
-
-try:
- from configparser import SafeConfigParser
-except ImportError:
- from ConfigParser import SafeConfigParser
-
-from manifest import parser_manifest
-from generate_signature import gen_ta_signature
-from generate_signature import gen_hash
-
-# fixed value, {1, 2} version are abandoned.
-VERSION = 3
-TA_VERSION = 3
-
-MAX_EXT_PROP_LEN = 152
-
-MAGIC1 = 0xA5A55A5A
-MAGIC2 = 0x55AA
-
-# ELF Definitions
-ELF_TYPE = 32
-ELF_HDR_SIZE = 52
-ELF_PHDR_SIZE = 32
-ELF_INFO_MAGIC0_INDEX = 0
-ELF_INFO_MAGIC1_INDEX = 1
-ELF_INFO_MAGIC2_INDEX = 2
-ELF_INFO_MAGIC3_INDEX = 3
-#'\x7f'
-ELF_INFO_MAGIC0 = 127
-#'E'
-ELF_INFO_MAGIC1 = 69
-#'L'
-ELF_INFO_MAGIC2 = 76
-#'F'
-ELF_INFO_MAGIC3 = 70
-ELF_INFO_CLASS_INDEX = 4
-ELF_INFO_CLASS_32 = 1
-ELF_INFO_CLASS_64 = 2
-ELF_INFO_VERSION_INDEX = 6
-ELF_INFO_VERSION_CURRENT = 1
-ELF_BLOCK_ALIGN = 0x1000
-
-
-#----------------------------------------------------------------------------
-# Verify ELF header contents from an input ELF file
-#----------------------------------------------------------------------------
-def verify_elf_header(elf_path):
- elf_type = 0
- with open(elf_path, 'rb') as elf:
- elf_data = struct.unpack('B'*16, elf.read(16))
- elf_type = elf_data[4]
- if ((elf_data[ELF_INFO_MAGIC0_INDEX] != ELF_INFO_MAGIC0) or \
- (elf_data[ELF_INFO_MAGIC1_INDEX] != ELF_INFO_MAGIC1) or \
- (elf_data[ELF_INFO_MAGIC2_INDEX] != ELF_INFO_MAGIC2) or \
- (elf_data[ELF_INFO_MAGIC3_INDEX] != ELF_INFO_MAGIC3) or \
- (elf_data[ELF_INFO_VERSION_INDEX] != \
- ELF_INFO_VERSION_CURRENT)):
- print("invalid elf header info")
- raise RuntimeError
-
- if ((elf_type == 1 and elf_data[ELF_INFO_CLASS_INDEX] != \
- ELF_INFO_CLASS_32) or \
- (elf_type == 2 and elf_data[ELF_INFO_CLASS_INDEX] != \
- ELF_INFO_CLASS_64) or \
- (elf_type != 1 and elf_type != 2)):
- print("invliad elf format")
- raise RuntimeError
- return
-
-
-class Configuration:
- release_type = 0
- otrp_flag = 0
- sign_type = 0
- public_key = ""
- pub_key_len = 0
- server_ip = ""
- config_path = ""
- sign_key = ""
- sign_key_len = 2048
- hash_type = 0
- padding_type = 0
-
- def __init__(self, file_name):
- parser = SafeConfigParser()
- parser.read(file_name)
- self.release_type = parser.get("config", "releaseType")
- self.otrp_flag = parser.get("config", "otrpFlag")
- self.sign_type = parser.get("config", "signType")
- self.public_key = parser.get("config", "encryptKey")
- self.pub_key_len = parser.get("config", "encryptKeyLen")
- self.server_ip = parser.get("config", "serverIp")
- self.config_path = parser.get("config", "configPath")
- self.sign_key = parser.get("config", "signKey")
- self.sign_key_len = parser.get("config", "signKeyLen")
- self.hash_type = parser.get("config", "hashType")
- self.padding_type = parser.get("config", "paddingType")
-
-
-def gen_header(content_len, key_version):
- return struct.pack('IHHII', MAGIC1, MAGIC2, VERSION, content_len, \
- key_version)
-
-
-def gen_aes_key_info(cfg, iv_file_path, key_file_path, out_file_path):
- rand_iv_cmd = "openssl rand -out {} 16".format(iv_file_path)
- rand_key_cmd = "openssl rand -out {} 32".format(key_file_path)
- try:
- subprocess.check_output(rand_iv_cmd.split(), shell=False)
- subprocess.check_output(rand_key_cmd.split(), shell=False)
- except Exception:
- print("rand operation failed")
- raise RuntimeError
-
- os.chmod(iv_file_path, stat.S_IWUSR | stat.S_IRUSR)
- os.chmod(key_file_path, stat.S_IWUSR | stat.S_IRUSR)
-
- sign_alg = 0
- sign_alg = sign_alg | (int(cfg.release_type) << 28)
- sign_alg = sign_alg | (int(cfg.padding_type) << 27)
- sign_alg = sign_alg | (int(cfg.hash_type) << 26)
- if cfg.sign_key_len == "2048":
- sign_alg = sign_alg | 0x00002048
- elif cfg.sign_key_len == "4096":
- sign_alg = sign_alg | 0x00004096
-
- print("sign_alg value is 0x%x" % sign_alg)
- with open(out_file_path, 'wb') as out_file:
- out_file.write(struct.pack('I', 32))
- out_file.write(struct.pack('I', 16))
- out_file.write(struct.pack('I', sign_alg))
-
- with open(key_file_path, 'rb') as key_file:
- out_file.write(key_file.read(32))
-
- with open(iv_file_path, 'rb') as iv_file:
- out_file.write(iv_file.read(16))
-
- os.chmod(out_file_path, stat.S_IWUSR | stat.S_IRUSR)
- return
-
-
-def encrypt_aes_key(pubkey_path, in_path, out_path):
- cmd = "openssl rsautl -encrypt -pubin -oaep -inkey {} -in {} -out {}". \
- format(pubkey_path, in_path, out_path)
- try:
- subprocess.check_output(cmd.split(), shell=False)
- except Exception:
- print("RSA encrypt operation failed")
- raise RuntimeError
- os.chmod(out_path, stat.S_IWUSR | stat.S_IRUSR)
- return
-
-def gen_signature(cfg, uuid_str, raw_data_path, hash_file_path, out_file_path):
- gen_ta_signature(cfg, uuid_str, raw_data_path, hash_file_path, out_file_path)
- os.chmod(out_file_path, stat.S_IWUSR | stat.S_IRUSR)
- return
-
-def gen_raw_data(manifest_data_path, manifest_ext_path, elf_file_path, \
- config_path, raw_file_path):
- manifest_size = os.path.getsize(manifest_data_path)
- manifest_ext_size = os.path.getsize(manifest_ext_path)
- elf_size = os.path.getsize(elf_file_path)
- config_size = 0
-
- if manifest_ext_size > MAX_EXT_PROP_LEN:
- print("too much data in \"manifest.txt\" to be handled. \
- extra string len %d" \
- % manifest_ext_size)
- raise RuntimeError
-
- verify_elf_header(elf_file_path)
-
- with open(raw_file_path, 'wb') as file_op:
- header = ""
- if os.path.isfile(config_path):
- config_size = os.path.getsize(config_path)
- header = struct.pack('IIIII', TA_VERSION, manifest_size, \
- manifest_ext_size, \
- elf_size, config_size)
- file_op.write(header)
-
- with open(manifest_data_path, 'rb') as manifest_data:
- file_op.write(manifest_data.read(manifest_size))
-
- with open(manifest_ext_path, 'rb') as manifest_ext:
- file_op.write(manifest_ext.read(manifest_ext_size))
-
- with open(elf_file_path, 'rb') as elf:
- file_op.write(elf.read(elf_size))
- if config_size != 0:
- with open(config_path, 'rb') as config:
- file_op.write(config.read(config_size))
- return
-
-
-def aes_encrypt(key_path, iv_path, in_file_path, out_file_path):
- key_size = os.path.getsize(key_path)
- with open(key_path, 'rb') as key_file:
- key_data = key_file.read(key_size)
- hex_key_str = binascii.b2a_hex(key_data)
-
- iv_size = os.path.getsize(iv_path)
- with open(iv_path, 'rb') as iv_file:
- iv_data = iv_file.read(iv_size)
- hex_iv_str = binascii.b2a_hex(iv_data)
-
- cmd = "openssl enc -aes-256-cbc -in {} -out {} -K {} -iv {}".\
- format(in_file_path, out_file_path, \
- bytes.decode(hex_key_str), bytes.decode(hex_iv_str))
- try:
- subprocess.check_output(cmd.split(), shell=False)
- except Exception:
- print("AES encrypt operation failed")
- raise RuntimeError
-
- os.chmod(out_file_path, stat.S_IWUSR | stat.S_IRUSR)
- return
-
-def update_api_level(api_level, manifest):
- data = ''
- with open(manifest, 'r') as file_op:
- for line in file_op:
- if line.startswith("#") or not "gpd.ta.api_level" in line:
- data += line
- line = "\ngpd.ta.api_level:{}\n".format(api_level)
- data += line
- with open(manifest, "w") as file_op:
- file_op.writelines(data)
-
-
-def update_otrp_flag(manifest):
- data = ''
- with open(manifest, 'r') as file_op:
- for line in file_op:
- if line.startswith("#") or not "gpd.ta.otrp_flag" in line:
- data += line
- line = "\ngpd.ta.otrp_flag:{}\n".format('true')
- data += line
- with open(manifest, "w") as file_op:
- file_op.writelines(data)
-
-
-def gen_data_for_sign(header, key_info, raw_file, data_sign):
- key_info_len = os.path.getsize(key_info)
- raw_file_len = os.path.getsize(raw_file)
-
- with open(data_sign, 'wb') as data_fp, \
- open(key_info, 'rb') as key_fp, open(raw_file, 'rb') as raw_fp:
- data_fp.write(header)
- data_fp.write(key_fp.read(key_info_len))
- data_fp.write(raw_fp.read(raw_file_len))
-
-
-def gen_key_version(cfg):
- if cfg.pub_key_len == '3072':
- return int(0x0202)
- if cfg.pub_key_len == '2048':
- return int(0x0002)
- print("unhandled pulic key len %s" % cfg.pub_key_len)
- raise RuntimeError
-
-
-def generate_digest(cfg, api_level, enclave_file, manifest_file, hash_path, enc_key_path, enc_raw_path):
- # temporary files
- in_path = os.path.dirname(os.path.abspath(manifest_file))
- temp_path = os.path.join(in_path, "temp")
- shutil.rmtree(temp_path, ignore_errors=True)
- os.mkdir(temp_path)
- os.chmod(temp_path, stat.S_IRWXU)
- iv_file_path = os.path.join(temp_path, "iv.bin")
- key_file_path = os.path.join(temp_path, "aeskey.bin")
- key_info_path = os.path.join(temp_path, "KeyInfo")
- raw_file_path = os.path.join(temp_path, "rawData")
- manifest_data_path = os.path.join(temp_path, "manifestData.bin")
- manifest_ext_path = os.path.join(temp_path, "manifestExt.bin")
- data_for_sign_path = os.path.join(temp_path, "dataForSign.bin")
- signature_path = os.path.join(temp_path, "signature.bin")
-
- # mandentory input files
- manifest_path = manifest_file
- elf_file_path = enclave_file
-
- ret, product_name = parser_manifest(manifest_path, \
- manifest_data_path, manifest_ext_path)
- if ret is False:
- raise RuntimeError
-
- update_api_level(api_level, manifest_ext_path)
-
- if cfg.otrp_flag == 1:
- print("package otrp sec file\n")
- update_otrp_flag(manifest_ext_path)
-
- gen_raw_data(manifest_data_path, manifest_ext_path, elf_file_path, \
- cfg.config_path, raw_file_path)
-
- # generate AES key info to encrypt raw data
- gen_aes_key_info(cfg, iv_file_path, key_file_path, key_info_path)
- encrypt_aes_key(cfg.public_key, key_info_path, enc_key_path)
-
- aes_encrypt(key_file_path, iv_file_path, raw_file_path, enc_raw_path)
-
- # generate Main Header
- content_len = os.path.getsize(enc_key_path) + \
- (int(cfg.sign_key_len) / 8) + \
- os.path.getsize(enc_raw_path)
- key_version = gen_key_version(cfg)
- header = gen_header(int(content_len), key_version)
-
- gen_data_for_sign(header, key_info_path, raw_file_path, data_for_sign_path)
-
- gen_hash(cfg.hash_type, data_for_sign_path, hash_path)
-
- #remove temp files
- os.remove(iv_file_path)
- os.remove(key_file_path)
- os.remove(key_info_path)
- os.remove(raw_file_path)
- os.remove(manifest_data_path)
- os.remove(manifest_ext_path)
- os.remove(data_for_sign_path)
- return
-
-def gen_sec_image(cfg, enc_raw_path, enc_key_path, signature_path, out_file):
- content_len = os.path.getsize(enc_key_path) + \
- (int(cfg.sign_key_len) / 8) + \
- os.path.getsize(enc_raw_path)
- key_version = gen_key_version(cfg)
- header = gen_header(int(content_len), key_version)
- sec_img_path = out_file
- with open(sec_img_path, 'wb') as sec_image:
- # write to sec file [1.header info]
- sec_image.write(header)
- # write to sec file [2.AES key info]
- enc_key_size = os.path.getsize(enc_key_path)
- with open(enc_key_path, 'rb') as enc_key_info:
- sec_image.write(enc_key_info.read(enc_key_size))
- # write to sec file [3.signature]
- signature_size = os.path.getsize(signature_path)
- with open(signature_path, 'rb') as signature_file:
- sec_image.write(signature_file.read(signature_size))
- # write to sec file [4.encrypted raw data]
- enc_raw_size = os.path.getsize(enc_raw_path)
- with open(enc_raw_path, 'rb') as enc_raw_data:
- sec_image.write(enc_raw_data.read(enc_raw_size))
-
- print("=========================SUCCESS============================")
- print("generate TA(V3 format) load image success: ")
- print(sec_img_path)
- print("============================================================")
-
- return
-
-
-def main():
- argvs = sys.argv
- cmd = argvs[1]
- one_step_mode = int(argvs[2])
- enclave_path = argvs[3]
- out_file = argvs[4]
- manifest_file = argvs[5]
- cloud_config = argvs[6]
- cfg = Configuration(cloud_config)
- api_level = int(argvs[7])
-
- os.umask(127)
-
- in_path = os.path.dirname(os.path.abspath(cloud_config))
- temp_path = os.path.join(in_path, "temp")
- enc_key_path = os.path.join(temp_path, "KeyInfo.enc")
- enc_raw_path = os.path.join(temp_path, "rawData.enc")
- hash_path = os.path.join(temp_path, "rawDataHash.bin")
- temp_signature = os.path.join(temp_path, "tempSignature")
-
- sign_tool_dir = os.path.dirname(os.path.abspath(__file__))
- os.chdir(sign_tool_dir)
- if cmd == "digest":
- generate_digest(cfg, api_level, enclave_path, manifest_file, hash_path, enc_key_path, enc_raw_path)
- shutil.copy(hash_path, out_file)
- elif cmd == "sign":
- if one_step_mode == 0:
- in_signature = argvs[8]
- gen_sec_image(cfg, enc_raw_path, enc_key_path, in_signature, out_file)
- else:
- generate_digest(cfg, api_level, enclave_path, manifest_file, hash_path, enc_key_path, enc_raw_path)
- gen_ta_signature(cfg, hash_path, temp_signature)
- in_signature = temp_signature
- gen_sec_image(cfg, enc_raw_path, enc_key_path, in_signature, out_file)
- os.remove(temp_signature)
- os.remove(enc_key_path)
- os.remove(enc_raw_path)
- os.remove(hash_path)
- #remove temp files
- shutil.rmtree(temp_path)
-
-
-if __name__ == '__main__':
- main()
-
--
2.33.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/yue-yuankun/secGear.git
git@gitee.com:yue-yuankun/secGear.git
yue-yuankun
secGear
secGear
master

搜索帮助