1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731 |
- /* sp.c
- *
- * Copyright (C) 2006-2020 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
- /* Implementation by Sean Parkinson. */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <wolfssl/wolfcrypt/settings.h>
- #include <wolfssl/wolfcrypt/error-crypt.h>
- #include <wolfssl/wolfcrypt/cpuid.h>
- #ifdef NO_INLINE
- #include <wolfssl/wolfcrypt/misc.h>
- #else
- #define WOLFSSL_MISC_INCLUDED
- #include <wolfcrypt/src/misc.c>
- #endif
- #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
- defined(WOLFSSL_HAVE_SP_ECC)
- #ifdef RSA_LOW_MEM
- #ifndef WOLFSSL_SP_SMALL
- #define WOLFSSL_SP_SMALL
- #endif
- #endif
- #include <wolfssl/wolfcrypt/sp.h>
- #ifdef WOLFSSL_SP_ARM_THUMB_ASM
- #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
- #ifndef WOLFSSL_SP_NO_2048
- /* Read big endian unsigned byte array into r.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a Byte array.
- * n Number of bytes in array to read.
- */
- static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
- {
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = n-1; i >= 0; i--) {
- r[j] |= (((sp_digit)a[i]) << s);
- if (s >= 24U) {
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- r[++j] = (sp_digit)a[i] >> s;
- s = 8U - s;
- }
- else {
- s += 8U;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- }
- /* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
- static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
- {
- #if DIGIT_BIT == 32
- int j;
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
- #elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #else
- int i, j = 0, s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #endif
- }
- /* Write r as big endian to byte array.
- * Fixed length number of bytes written: 256
- *
- * r A single precision integer.
- * a Byte array.
- */
- static void sp_2048_to_bin(sp_digit* r, byte* a)
- {
- int i, j, s = 0, b;
- j = 2048 / 8 - 1;
- a[j] = 0;
- for (i=0; i<64 && j>=0; i++) {
- b = 0;
- /* lint allow cast of mismatch sp_digit and int */
- a[j--] |= (byte)(r[i] << s); b += 8 - s; /*lint !e9033*/
- if (j < 0) {
- break;
- }
- while (b < 32) {
- a[j--] = r[i] >> b; b += 8;
- if (j < 0) {
- break;
- }
- }
- s = 8 - (b - 32);
- if (j >= 0) {
- a[j] = 0;
- }
- if (s != 0) {
- j++;
- }
- }
- }
- #ifndef WOLFSSL_SP_SMALL
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_2048_mul_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[8 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #32\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #28\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #56\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #64\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #28\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #32\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #56\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #60\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #64\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
- return c;
- }
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_sub_in_place_16(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
- return c;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_2048_mask_8(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<8; i++) {
- r[i] = a[i] & m;
- }
- #else
- r[0] = a[0] & m;
- r[1] = a[1] & m;
- r[2] = a[2] & m;
- r[3] = a[3] & m;
- r[4] = a[4] & m;
- r[5] = a[5] & m;
- r[6] = a[6] & m;
- r[7] = a[7] & m;
- #endif
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit* z0 = r;
- sp_digit z1[16];
- sp_digit a1[8];
- sp_digit b1[8];
- sp_digit z2[16];
- sp_digit u, ca, cb;
- ca = sp_2048_add_8(a1, a, &a[8]);
- cb = sp_2048_add_8(b1, b, &b[8]);
- u = ca & cb;
- sp_2048_mul_8(z1, a1, b1);
- sp_2048_mul_8(z2, &a[8], &b[8]);
- sp_2048_mul_8(z0, a, b);
- sp_2048_mask_8(r + 16, a1, 0 - cb);
- sp_2048_mask_8(b1, b1, 0 - ca);
- u += sp_2048_add_8(r + 16, r + 16, b1);
- u += sp_2048_sub_in_place_16(z1, z2);
- u += sp_2048_sub_in_place_16(z1, z0);
- u += sp_2048_add_16(r + 8, r + 8, z1);
- r[24] = u;
- XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
- (void)sp_2048_add_16(r + 16, r + 16, z2);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
- {
- sp_digit* z0 = r;
- sp_digit z2[16];
- sp_digit z1[16];
- sp_digit a1[8];
- sp_digit u;
- u = sp_2048_add_8(a1, a, &a[8]);
- sp_2048_sqr_8(z1, a1);
- sp_2048_sqr_8(z2, &a[8]);
- sp_2048_sqr_8(z0, a);
- sp_2048_mask_8(r + 16, a1, 0 - u);
- u += sp_2048_add_8(r + 16, r + 16, r + 16);
- u += sp_2048_sub_in_place_16(z1, z2);
- u += sp_2048_sub_in_place_16(z1, z0);
- u += sp_2048_add_16(r + 8, r + 8, z1);
- r[24] = u;
- XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
- (void)sp_2048_add_16(r + 16, r + 16, z2);
- }
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
- return c;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_2048_mask_16(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<16; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 16; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit* z0 = r;
- sp_digit z1[32];
- sp_digit a1[16];
- sp_digit b1[16];
- sp_digit z2[32];
- sp_digit u, ca, cb;
- ca = sp_2048_add_16(a1, a, &a[16]);
- cb = sp_2048_add_16(b1, b, &b[16]);
- u = ca & cb;
- sp_2048_mul_16(z1, a1, b1);
- sp_2048_mul_16(z2, &a[16], &b[16]);
- sp_2048_mul_16(z0, a, b);
- sp_2048_mask_16(r + 32, a1, 0 - cb);
- sp_2048_mask_16(b1, b1, 0 - ca);
- u += sp_2048_add_16(r + 32, r + 32, b1);
- u += sp_2048_sub_in_place_32(z1, z2);
- u += sp_2048_sub_in_place_32(z1, z0);
- u += sp_2048_add_32(r + 16, r + 16, z1);
- r[48] = u;
- XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
- (void)sp_2048_add_32(r + 32, r + 32, z2);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
- {
- sp_digit* z0 = r;
- sp_digit z2[32];
- sp_digit z1[32];
- sp_digit a1[16];
- sp_digit u;
- u = sp_2048_add_16(a1, a, &a[16]);
- sp_2048_sqr_16(z1, a1);
- sp_2048_sqr_16(z2, &a[16]);
- sp_2048_sqr_16(z0, a);
- sp_2048_mask_16(r + 32, a1, 0 - u);
- u += sp_2048_add_16(r + 32, r + 32, r + 32);
- u += sp_2048_sub_in_place_32(z1, z2);
- u += sp_2048_sub_in_place_32(z1, z0);
- u += sp_2048_add_32(r + 16, r + 16, z1);
- r[48] = u;
- XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
- (void)sp_2048_add_32(r + 32, r + 32, z2);
- }
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, #0\n\t"
- "mvn r7, r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r7"
- );
- return c;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_2048_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<32; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 32; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit* z0 = r;
- sp_digit z1[64];
- sp_digit a1[32];
- sp_digit b1[32];
- sp_digit z2[64];
- sp_digit u, ca, cb;
- ca = sp_2048_add_32(a1, a, &a[32]);
- cb = sp_2048_add_32(b1, b, &b[32]);
- u = ca & cb;
- sp_2048_mul_32(z1, a1, b1);
- sp_2048_mul_32(z2, &a[32], &b[32]);
- sp_2048_mul_32(z0, a, b);
- sp_2048_mask_32(r + 64, a1, 0 - cb);
- sp_2048_mask_32(b1, b1, 0 - ca);
- u += sp_2048_add_32(r + 64, r + 64, b1);
- u += sp_2048_sub_in_place_64(z1, z2);
- u += sp_2048_sub_in_place_64(z1, z0);
- u += sp_2048_add_64(r + 32, r + 32, z1);
- r[96] = u;
- XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1));
- (void)sp_2048_add_64(r + 64, r + 64, z2);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a)
- {
- sp_digit* z0 = r;
- sp_digit z2[64];
- sp_digit z1[64];
- sp_digit a1[32];
- sp_digit u;
- u = sp_2048_add_32(a1, a, &a[32]);
- sp_2048_sqr_32(z1, a1);
- sp_2048_sqr_32(z2, &a[32]);
- sp_2048_sqr_32(z0, a);
- sp_2048_mask_32(r + 64, a1, 0 - u);
- u += sp_2048_add_32(r + 64, r + 64, r + 64);
- u += sp_2048_sub_in_place_64(z1, z2);
- u += sp_2048_sub_in_place_64(z1, z0);
- u += sp_2048_add_64(r + 32, r + 32, z1);
- r[96] = u;
- XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1));
- (void)sp_2048_add_64(r + 64, r + 64, z2);
- }
- #endif /* !WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "mov r4, #1\n\t"
- "lsl r4, #8\n\t"
- "sub r7, #1\n\t"
- "add r6, r4\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Sub b from a into a. (a -= b)
- *
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, %[a]\n\t"
- "mov r5, #1\n\t"
- "lsl r5, #8\n\t"
- "add r7, r5\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a]]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b]]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a]]\n\t"
- "str r4, [%[a], #4]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #8\n\t"
- "add %[b], #8\n\t"
- "cmp %[a], r7\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[64 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #252\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #252\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #1\n\t"
- "lsl r3, r3, #8\n\t"
- "add r3, #252\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- #endif /* WOLFSSL_SP_SMALL */
- #if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
- #ifdef WOLFSSL_SP_SMALL
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_2048_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- int i;
- for (i=0; i<32; i++) {
- r[i] = a[i] & m;
- }
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "add r6, #128\n\t"
- "sub r7, #1\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Sub b from a into a. (a -= b)
- *
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, %[a]\n\t"
- "add r7, #128\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a]]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b]]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a]]\n\t"
- "str r4, [%[a], #4]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #8\n\t"
- "add %[b], #8\n\t"
- "cmp %[a], r7\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[32 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #128\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #124\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #124\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #128\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #252\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- #endif /* WOLFSSL_SP_SMALL */
- #endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
- /* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a A single precision number.
- * rho Bottom word of inverse.
- */
- static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
- {
- sp_digit x, b;
- b = a[0];
- x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
- x *= 2 - b * x; /* here x*a==1 mod 2**8 */
- x *= 2 - b * x; /* here x*a==1 mod 2**16 */
- x *= 2 - b * x; /* here x*a==1 mod 2**32 */
- /* rho = -1/m mod b */
- *rho = -x;
- }
- /* Mul a by digit b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision digit.
- */
- SP_NOINLINE static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a,
- sp_digit b)
- {
- __asm__ __volatile__ (
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, %[a]\n\t"
- "mov r8, %[r]\n\t"
- "mov r9, r6\n\t"
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "# A[] * B\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# A[] * B - Done\n\t"
- "mov %[r], r8\n\t"
- "str r3, [%[r]]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add %[r], #4\n\t"
- "add %[a], #4\n\t"
- "mov r8, %[r]\n\t"
- "cmp %[a], r9\n\t"
- "blt 1b\n\t"
- "str r3, [%[r]]\n\t"
- : [r] "+r" (r), [a] "+r" (a)
- : [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
- );
- }
- #if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
- /* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r A single precision number.
- * m A single precision number.
- */
- static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m)
- {
- XMEMSET(r, 0, sizeof(sp_digit) * 32);
- /* r = 2^n mod m */
- sp_2048_sub_in_place_32(r, m);
- }
- /* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
- SP_NOINLINE static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a,
- const sp_digit* b, sp_digit m)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r5, #128\n\t"
- "mov r8, r5\n\t"
- "mov r7, #0\n\t"
- "1:\n\t"
- "ldr r6, [%[b], r7]\n\t"
- "and r6, %[m]\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r5, [%[a], r7]\n\t"
- "sbc r5, r6\n\t"
- "sbc %[c], %[c]\n\t"
- "str r5, [%[r], r7]\n\t"
- "add r7, #4\n\t"
- "cmp r7, r8\n\t"
- "blt 1b\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
- : "memory", "r5", "r6", "r7", "r8"
- );
- return c;
- }
- /* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
- SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_digit ca = 0;
- __asm__ __volatile__ (
- "mov r8, %[mp]\n\t"
- "mov r12, %[ca]\n\t"
- "mov r14, %[m]\n\t"
- "mov r9, %[a]\n\t"
- "mov r4, #0\n\t"
- "# i = 0\n\t"
- "mov r11, r4\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "mov %[ca], #0\n\t"
- "# mu = a[i] * mp\n\t"
- "mov %[mp], r8\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mul %[mp], %[a]\n\t"
- "mov %[m], r14\n\t"
- "mov r10, r9\n\t"
- "\n2:\n\t"
- "# a[i+j] += m[j] * mu\n\t"
- "mov %[a], r10\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "# Multiply m[j] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add %[a], r7\n\t"
- "adc r5, %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "# Multiply m[j] and mu - Done\n\t"
- "add r4, %[a]\n\t"
- "adc r5, %[ca]\n\t"
- "mov %[a], r10\n\t"
- "str r4, [%[a]]\n\t"
- "mov r6, #4\n\t"
- "add %[m], #4\n\t"
- "add r10, r6\n\t"
- "mov r4, #124\n\t"
- "add r4, r9\n\t"
- "cmp r10, r4\n\t"
- "blt 2b\n\t"
- "# a[i+31] += m[31] * mu\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r12\n\t"
- "mov %[a], #0\n\t"
- "# Multiply m[31] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "adc r4, %[ca]\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "# Multiply m[31] and mu - Done\n\t"
- "mov %[ca], %[a]\n\t"
- "mov %[a], r10\n\t"
- "ldr r7, [%[a], #4]\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov r6, #0\n\t"
- "add r5, %[a]\n\t"
- "adc r7, r4\n\t"
- "adc %[ca], r6\n\t"
- "mov %[a], r10\n\t"
- "str r5, [%[a]]\n\t"
- "str r7, [%[a], #4]\n\t"
- "# i += 1\n\t"
- "mov r6, #4\n\t"
- "add r9, r6\n\t"
- "add r11, r6\n\t"
- "mov r12, %[ca]\n\t"
- "mov %[a], r9\n\t"
- "mov r4, #128\n\t"
- "cmp r11, r4\n\t"
- "blt 1b\n\t"
- "mov %[m], r14\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
- : [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
- );
- sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca);
- }
- /* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r Result of multiplication.
- * a First number to multiply in Montogmery form.
- * b Second number to multiply in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
- {
- sp_2048_mul_32(r, a, b);
- sp_2048_mont_reduce_32(r, m, mp);
- }
- /* Square the Montgomery form number. (r = a * a mod m)
- *
- * r Result of squaring.
- * a Number to square in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_2048_sqr_32(r, a);
- sp_2048_mont_reduce_32(r, m, mp);
- }
- /* Mul a by digit b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision digit.
- */
- SP_NOINLINE static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a,
- sp_digit b)
- {
- __asm__ __volatile__ (
- "mov r6, #128\n\t"
- "add r6, %[a]\n\t"
- "mov r8, %[r]\n\t"
- "mov r9, r6\n\t"
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "# A[] * B\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# A[] * B - Done\n\t"
- "mov %[r], r8\n\t"
- "str r3, [%[r]]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add %[r], #4\n\t"
- "add %[a], #4\n\t"
- "mov r8, %[r]\n\t"
- "cmp %[a], r9\n\t"
- "blt 1b\n\t"
- "str r3, [%[r]]\n\t"
- : [r] "+r" (r), [a] "+r" (a)
- : [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
- );
- }
- /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1 The high order half of the number to divide.
- * d0 The low order half of the number to divide.
- * div The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
- SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0,
- sp_digit div)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "lsr r5, %[div], #1\n\t"
- "add r5, #1\n\t"
- "mov r8, %[d0]\n\t"
- "mov r9, %[d1]\n\t"
- "# Do top 32\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "# Next 30 bits\n\t"
- "mov r4, #29\n\t"
- "1:\n\t"
- "lsl %[d0], %[d0], #1\n\t"
- "adc %[d1], %[d1]\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "sub r4, #1\n\t"
- "bpl 1b\n\t"
- "mov r7, #0\n\t"
- "add %[r], %[r]\n\t"
- "add %[r], #1\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "sub %[d1], r4\n\t"
- "mov r4, %[d1]\n\t"
- "mov %[d1], r9\n\t"
- "sbc %[d1], r5\n\t"
- "mov r5, %[d1]\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "mov r6, %[div]\n\t"
- "sub r6, r4\n\t"
- "sbc r6, r6\n\t"
- "sub %[r], r6\n\t"
- : [r] "+r" (r)
- : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
- : "r4", "r5", "r7", "r6", "r8", "r9"
- );
- return r;
- }
- /* Compare a with b in constant time.
- *
- * a A single precision integer.
- * b A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
- SP_NOINLINE static int32_t sp_2048_cmp_32(const sp_digit* a, const sp_digit* b)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mvn r3, r3\n\t"
- "mov r6, #124\n\t"
- "1:\n\t"
- "ldr r7, [%[a], r6]\n\t"
- "ldr r5, [%[b], r6]\n\t"
- "and r7, r3\n\t"
- "and r5, r3\n\t"
- "mov r4, r7\n\t"
- "sub r7, r5\n\t"
- "sbc r7, r7\n\t"
- "add %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r5, r4\n\t"
- "sbc r7, r7\n\t"
- "sub %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r6, #4\n\t"
- "cmp r6, #0\n\t"
- "bge 1b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "r3", "r4", "r5", "r6", "r7"
- );
- return r;
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[64], t2[33];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[31];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
- for (i=31; i>=0; i--) {
- r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div);
- sp_2048_mul_d_32(t2, d, r1);
- t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2);
- t1[32 + i] -= t2[32];
- sp_2048_mask_32(t2, d, t1[32 + i]);
- t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
- sp_2048_mask_32(t2, d, t1[32 + i]);
- t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
- }
- r1 = sp_2048_cmp_32(t1, d) >= 0;
- sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_2048_div_32(a, m, NULL, r);
- }
- #ifdef WOLFSSL_SP_SMALL
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[16][64];
- #else
- sp_digit* t[16];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 64, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<16; i++) {
- t[i] = td + i * 64;
- }
- #endif
- norm = t[0];
- sp_2048_mont_setup(m, &mp);
- sp_2048_mont_norm_32(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 32U);
- if (reduceA != 0) {
- err = sp_2048_mod_32(t[1] + 32, a, m);
- if (err == MP_OKAY) {
- err = sp_2048_mod_32(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
- err = sp_2048_mod_32(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
- sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
- sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
- sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
- sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
- sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
- sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
- sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
- sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
- sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
- sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
- sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
- sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
- sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 4;
- if (c == 32) {
- c = 28;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
- for (; i>=0 || c>=4; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 28;
- n <<= 4;
- c = 28;
- }
- else if (c < 4) {
- y = n >> 28;
- n = e[i--];
- c = 4 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 28) & 0xf;
- n <<= 4;
- c -= 4;
- }
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_mul_32(r, r, t[y], m, mp);
- }
- XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U);
- sp_2048_mont_reduce_32(r, m, mp);
- mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
- sp_2048_cond_sub_32(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #else
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[32][64];
- #else
- sp_digit* t[32];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<32; i++) {
- t[i] = td + i * 64;
- }
- #endif
- norm = t[0];
- sp_2048_mont_setup(m, &mp);
- sp_2048_mont_norm_32(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 32U);
- if (reduceA != 0) {
- err = sp_2048_mod_32(t[1] + 32, a, m);
- if (err == MP_OKAY) {
- err = sp_2048_mod_32(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
- err = sp_2048_mod_32(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
- sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
- sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
- sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
- sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
- sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
- sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
- sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
- sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
- sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
- sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
- sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
- sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
- sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
- sp_2048_mont_sqr_32(t[16], t[ 8], m, mp);
- sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp);
- sp_2048_mont_sqr_32(t[18], t[ 9], m, mp);
- sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp);
- sp_2048_mont_sqr_32(t[20], t[10], m, mp);
- sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp);
- sp_2048_mont_sqr_32(t[22], t[11], m, mp);
- sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp);
- sp_2048_mont_sqr_32(t[24], t[12], m, mp);
- sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp);
- sp_2048_mont_sqr_32(t[26], t[13], m, mp);
- sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp);
- sp_2048_mont_sqr_32(t[28], t[14], m, mp);
- sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp);
- sp_2048_mont_sqr_32(t[30], t[15], m, mp);
- sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_sqr_32(r, r, m, mp);
- sp_2048_mont_mul_32(r, r, t[y], m, mp);
- }
- XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U);
- sp_2048_mont_reduce_32(r, m, mp);
- mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
- sp_2048_cond_sub_32(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
- #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
- /* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r A single precision number.
- * m A single precision number.
- */
- static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m)
- {
- XMEMSET(r, 0, sizeof(sp_digit) * 64);
- /* r = 2^n mod m */
- sp_2048_sub_in_place_64(r, m);
- }
- #endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
- /* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
- SP_NOINLINE static sp_digit sp_2048_cond_sub_64(sp_digit* r, const sp_digit* a,
- const sp_digit* b, sp_digit m)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r5, #1\n\t"
- "lsl r5, r5, #8\n\t"
- "mov r8, r5\n\t"
- "mov r7, #0\n\t"
- "1:\n\t"
- "ldr r6, [%[b], r7]\n\t"
- "and r6, %[m]\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r5, [%[a], r7]\n\t"
- "sbc r5, r6\n\t"
- "sbc %[c], %[c]\n\t"
- "str r5, [%[r], r7]\n\t"
- "add r7, #4\n\t"
- "cmp r7, r8\n\t"
- "blt 1b\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
- : "memory", "r5", "r6", "r7", "r8"
- );
- return c;
- }
- /* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
- SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_digit ca = 0;
- __asm__ __volatile__ (
- "mov r8, %[mp]\n\t"
- "mov r12, %[ca]\n\t"
- "mov r14, %[m]\n\t"
- "mov r9, %[a]\n\t"
- "mov r4, #0\n\t"
- "# i = 0\n\t"
- "mov r11, r4\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "mov %[ca], #0\n\t"
- "# mu = a[i] * mp\n\t"
- "mov %[mp], r8\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mul %[mp], %[a]\n\t"
- "mov %[m], r14\n\t"
- "mov r10, r9\n\t"
- "\n2:\n\t"
- "# a[i+j] += m[j] * mu\n\t"
- "mov %[a], r10\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "# Multiply m[j] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add %[a], r7\n\t"
- "adc r5, %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "# Multiply m[j] and mu - Done\n\t"
- "add r4, %[a]\n\t"
- "adc r5, %[ca]\n\t"
- "mov %[a], r10\n\t"
- "str r4, [%[a]]\n\t"
- "mov r6, #4\n\t"
- "add %[m], #4\n\t"
- "add r10, r6\n\t"
- "mov r4, #252\n\t"
- "add r4, r9\n\t"
- "cmp r10, r4\n\t"
- "blt 2b\n\t"
- "# a[i+63] += m[63] * mu\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r12\n\t"
- "mov %[a], #0\n\t"
- "# Multiply m[63] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "adc r4, %[ca]\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "# Multiply m[63] and mu - Done\n\t"
- "mov %[ca], %[a]\n\t"
- "mov %[a], r10\n\t"
- "ldr r7, [%[a], #4]\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov r6, #0\n\t"
- "add r5, %[a]\n\t"
- "adc r7, r4\n\t"
- "adc %[ca], r6\n\t"
- "mov %[a], r10\n\t"
- "str r5, [%[a]]\n\t"
- "str r7, [%[a], #4]\n\t"
- "# i += 1\n\t"
- "mov r6, #4\n\t"
- "add r9, r6\n\t"
- "add r11, r6\n\t"
- "mov r12, %[ca]\n\t"
- "mov %[a], r9\n\t"
- "mov r4, #1\n\t"
- "lsl r4, r4, #8\n\t"
- "cmp r11, r4\n\t"
- "blt 1b\n\t"
- "mov %[m], r14\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
- : [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
- );
- sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca);
- }
- /* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r Result of multiplication.
- * a First number to multiply in Montogmery form.
- * b Second number to multiply in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
- {
- sp_2048_mul_64(r, a, b);
- sp_2048_mont_reduce_64(r, m, mp);
- }
- /* Square the Montgomery form number. (r = a * a mod m)
- *
- * r Result of squaring.
- * a Number to square in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_2048_sqr_64(r, a);
- sp_2048_mont_reduce_64(r, m, mp);
- }
- /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1 The high order half of the number to divide.
- * d0 The low order half of the number to divide.
- * div The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
- SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0,
- sp_digit div)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "lsr r5, %[div], #1\n\t"
- "add r5, #1\n\t"
- "mov r8, %[d0]\n\t"
- "mov r9, %[d1]\n\t"
- "# Do top 32\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "# Next 30 bits\n\t"
- "mov r4, #29\n\t"
- "1:\n\t"
- "lsl %[d0], %[d0], #1\n\t"
- "adc %[d1], %[d1]\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "sub r4, #1\n\t"
- "bpl 1b\n\t"
- "mov r7, #0\n\t"
- "add %[r], %[r]\n\t"
- "add %[r], #1\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "sub %[d1], r4\n\t"
- "mov r4, %[d1]\n\t"
- "mov %[d1], r9\n\t"
- "sbc %[d1], r5\n\t"
- "mov r5, %[d1]\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "mov r6, %[div]\n\t"
- "sub r6, r4\n\t"
- "sbc r6, r6\n\t"
- "sub %[r], r6\n\t"
- : [r] "+r" (r)
- : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
- : "r4", "r5", "r7", "r6", "r8", "r9"
- );
- return r;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_2048_mask_64(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<64; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 64; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Compare a with b in constant time.
- *
- * a A single precision integer.
- * b A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
- SP_NOINLINE static int32_t sp_2048_cmp_64(const sp_digit* a, const sp_digit* b)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mvn r3, r3\n\t"
- "mov r6, #252\n\t"
- "1:\n\t"
- "ldr r7, [%[a], r6]\n\t"
- "ldr r5, [%[b], r6]\n\t"
- "and r7, r3\n\t"
- "and r5, r3\n\t"
- "mov r4, r7\n\t"
- "sub r7, r5\n\t"
- "sbc r7, r7\n\t"
- "add %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r5, r4\n\t"
- "sbc r7, r7\n\t"
- "sub %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r6, #4\n\t"
- "cmp r6, #0\n\t"
- "bge 1b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "r3", "r4", "r5", "r6", "r7"
- );
- return r;
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_2048_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[128], t2[65];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[63];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 64);
- for (i=63; i>=0; i--) {
- r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div);
- sp_2048_mul_d_64(t2, d, r1);
- t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2);
- t1[64 + i] -= t2[64];
- sp_2048_mask_64(t2, d, t1[64 + i]);
- t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2);
- sp_2048_mask_64(t2, d, t1[64 + i]);
- t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2);
- }
- r1 = sp_2048_cmp_64(t1, d) >= 0;
- sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_2048_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_2048_div_64(a, m, NULL, r);
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_2048_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[128], t2[65];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[63];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 64);
- for (i=63; i>=0; i--) {
- r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div);
- sp_2048_mul_d_64(t2, d, r1);
- t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2);
- t1[64 + i] -= t2[64];
- if (t1[64 + i] != 0) {
- t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d);
- if (t1[64 + i] != 0)
- t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d);
- }
- }
- r1 = sp_2048_cmp_64(t1, d) >= 0;
- sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_2048_div_64_cond(a, m, NULL, r);
- }
- #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
- defined(WOLFSSL_HAVE_SP_DH)
- #ifdef WOLFSSL_SP_SMALL
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[16][128];
- #else
- sp_digit* t[16];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 128, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<16; i++) {
- t[i] = td + i * 128;
- }
- #endif
- norm = t[0];
- sp_2048_mont_setup(m, &mp);
- sp_2048_mont_norm_64(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 64U);
- if (reduceA != 0) {
- err = sp_2048_mod_64(t[1] + 64, a, m);
- if (err == MP_OKAY) {
- err = sp_2048_mod_64(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64);
- err = sp_2048_mod_64(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp);
- sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp);
- sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp);
- sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp);
- sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp);
- sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp);
- sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp);
- sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp);
- sp_2048_mont_sqr_64(t[10], t[ 5], m, mp);
- sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp);
- sp_2048_mont_sqr_64(t[12], t[ 6], m, mp);
- sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp);
- sp_2048_mont_sqr_64(t[14], t[ 7], m, mp);
- sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 4;
- if (c == 32) {
- c = 28;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
- for (; i>=0 || c>=4; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 28;
- n <<= 4;
- c = 28;
- }
- else if (c < 4) {
- y = n >> 28;
- n = e[i--];
- c = 4 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 28) & 0xf;
- n <<= 4;
- c -= 4;
- }
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_mul_64(r, r, t[y], m, mp);
- }
- XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U);
- sp_2048_mont_reduce_64(r, m, mp);
- mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
- sp_2048_cond_sub_64(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #else
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[32][128];
- #else
- sp_digit* t[32];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 128, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<32; i++) {
- t[i] = td + i * 128;
- }
- #endif
- norm = t[0];
- sp_2048_mont_setup(m, &mp);
- sp_2048_mont_norm_64(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 64U);
- if (reduceA != 0) {
- err = sp_2048_mod_64(t[1] + 64, a, m);
- if (err == MP_OKAY) {
- err = sp_2048_mod_64(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64);
- err = sp_2048_mod_64(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp);
- sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp);
- sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp);
- sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp);
- sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp);
- sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp);
- sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp);
- sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp);
- sp_2048_mont_sqr_64(t[10], t[ 5], m, mp);
- sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp);
- sp_2048_mont_sqr_64(t[12], t[ 6], m, mp);
- sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp);
- sp_2048_mont_sqr_64(t[14], t[ 7], m, mp);
- sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp);
- sp_2048_mont_sqr_64(t[16], t[ 8], m, mp);
- sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp);
- sp_2048_mont_sqr_64(t[18], t[ 9], m, mp);
- sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp);
- sp_2048_mont_sqr_64(t[20], t[10], m, mp);
- sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp);
- sp_2048_mont_sqr_64(t[22], t[11], m, mp);
- sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp);
- sp_2048_mont_sqr_64(t[24], t[12], m, mp);
- sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp);
- sp_2048_mont_sqr_64(t[26], t[13], m, mp);
- sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp);
- sp_2048_mont_sqr_64(t[28], t[14], m, mp);
- sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp);
- sp_2048_mont_sqr_64(t[30], t[15], m, mp);
- sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_mul_64(r, r, t[y], m, mp);
- }
- XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U);
- sp_2048_mont_reduce_64(r, m, mp);
- mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
- sp_2048_cond_sub_64(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
- #ifdef WOLFSSL_HAVE_SP_RSA
- /* RSA public key operation.
- *
- * in Array of bytes representing the number to exponentiate, base.
- * inLen Number of bytes in base.
- * em Public exponent.
- * mm Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 256 bytes long.
- * outLen Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
- int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit ad[128], md[64], rd[128];
- #else
- sp_digit* d = NULL;
- #endif
- sp_digit* a;
- sp_digit *ah;
- sp_digit* m;
- sp_digit* r;
- sp_digit e[1];
- int err = MP_OKAY;
- if (*outLen < 256)
- err = MP_TO_E;
- if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 ||
- mp_count_bits(mm) != 2048))
- err = MP_READ_E;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL,
- DYNAMIC_TYPE_RSA);
- if (d == NULL)
- err = MEMORY_E;
- }
- if (err == MP_OKAY) {
- a = d;
- r = a + 64 * 2;
- m = r + 64 * 2;
- ah = a + 64;
- }
- #else
- a = ad;
- m = md;
- r = rd;
- ah = a + 64;
- #endif
- if (err == MP_OKAY) {
- sp_2048_from_bin(ah, 64, in, inLen);
- #if DIGIT_BIT >= 32
- e[0] = em->dp[0];
- #else
- e[0] = em->dp[0];
- if (em->used > 1)
- e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
- #endif
- if (e[0] == 0)
- err = MP_EXPTMOD_E;
- }
- if (err == MP_OKAY) {
- sp_2048_from_mp(m, 64, mm);
- if (e[0] == 0x3) {
- if (err == MP_OKAY) {
- sp_2048_sqr_64(r, ah);
- err = sp_2048_mod_64_cond(r, r, m);
- }
- if (err == MP_OKAY) {
- sp_2048_mul_64(r, ah, r);
- err = sp_2048_mod_64_cond(r, r, m);
- }
- }
- else {
- int i;
- sp_digit mp;
- sp_2048_mont_setup(m, &mp);
- /* Convert to Montgomery form. */
- XMEMSET(a, 0, sizeof(sp_digit) * 64);
- err = sp_2048_mod_64_cond(a, a, m);
- if (err == MP_OKAY) {
- for (i=31; i>=0; i--)
- if (e[0] >> i)
- break;
- XMEMCPY(r, a, sizeof(sp_digit) * 64);
- for (i--; i>=0; i--) {
- sp_2048_mont_sqr_64(r, r, m, mp);
- if (((e[0] >> i) & 1) == 1)
- sp_2048_mont_mul_64(r, r, a, m, mp);
- }
- XMEMSET(&r[64], 0, sizeof(sp_digit) * 64);
- sp_2048_mont_reduce_64(r, m, mp);
- for (i = 63; i > 0; i--) {
- if (r[i] != m[i])
- break;
- }
- if (r[i] >= m[i])
- sp_2048_sub_in_place_64(r, m);
- }
- }
- }
- if (err == MP_OKAY) {
- sp_2048_to_bin(r, out);
- *outLen = 256;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL)
- XFREE(d, NULL, DYNAMIC_TYPE_RSA);
- #endif
- return err;
- }
- /* RSA private key operation.
- *
- * in Array of bytes representing the number to exponentiate, base.
- * inLen Number of bytes in base.
- * dm Private exponent.
- * pm First prime.
- * qm Second prime.
- * dpm First prime's CRT exponent.
- * dqm Second prime's CRT exponent.
- * qim Inverse of second prime mod p.
- * mm Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 256 bytes long.
- * outLen Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
- int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit ad[64 * 2];
- sp_digit pd[32], qd[32], dpd[32];
- sp_digit tmpad[64], tmpbd[64];
- #else
- sp_digit* t = NULL;
- #endif
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmp;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
- sp_digit c;
- int err = MP_OKAY;
- (void)dm;
- (void)mm;
- if (*outLen < 256)
- err = MP_TO_E;
- if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
- err = MP_READ_E;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL,
- DYNAMIC_TYPE_RSA);
- if (t == NULL)
- err = MEMORY_E;
- }
- if (err == MP_OKAY) {
- a = t;
- p = a + 64 * 2;
- q = p + 32;
- qi = dq = dp = q + 32;
- tmpa = qi + 32;
- tmpb = tmpa + 64;
- tmp = t;
- r = tmp + 64;
- }
- #else
- r = a = ad;
- p = pd;
- q = qd;
- qi = dq = dp = dpd;
- tmpa = tmpad;
- tmpb = tmpbd;
- tmp = a + 64;
- #endif
- if (err == MP_OKAY) {
- sp_2048_from_bin(a, 64, in, inLen);
- sp_2048_from_mp(p, 32, pm);
- sp_2048_from_mp(q, 32, qm);
- sp_2048_from_mp(dp, 32, dpm);
- err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1);
- }
- if (err == MP_OKAY) {
- sp_2048_from_mp(dq, 32, dqm);
- err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1);
- }
- if (err == MP_OKAY) {
- c = sp_2048_sub_in_place_32(tmpa, tmpb);
- sp_2048_mask_32(tmp, p, c);
- sp_2048_add_32(tmpa, tmpa, tmp);
- sp_2048_from_mp(qi, 32, qim);
- sp_2048_mul_32(tmpa, tmpa, qi);
- err = sp_2048_mod_32(tmpa, tmpa, p);
- }
- if (err == MP_OKAY) {
- sp_2048_mul_32(tmpa, q, tmpa);
- XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32);
- sp_2048_add_64(r, tmpb, tmpa);
- sp_2048_to_bin(r, out);
- *outLen = 256;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (t != NULL) {
- XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11);
- XFREE(t, NULL, DYNAMIC_TYPE_RSA);
- }
- #else
- XMEMSET(tmpad, 0, sizeof(tmpad));
- XMEMSET(tmpbd, 0, sizeof(tmpbd));
- XMEMSET(pd, 0, sizeof(pd));
- XMEMSET(qd, 0, sizeof(qd));
- XMEMSET(dpd, 0, sizeof(dpd));
- #endif
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_RSA */
- #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
- !defined(WOLFSSL_RSA_PUBLIC_ONLY))
- /* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
- static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
- {
- int err;
- err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
- #if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 64);
- r->used = 64;
- mp_clamp(r);
- #elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 64; i++) {
- r->dp[j] |= a[i] << s;
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = a[i] >> s;
- }
- }
- s = 32 - s;
- }
- r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #else
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 64; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #endif
- }
- return err;
- }
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base. MP integer.
- * exp Exponent. MP integer.
- * mod Modulus. MP integer.
- * res Result. MP integer.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
- {
- int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
- sp_digit* r = b;
- int expBits = mp_count_bits(exp);
- if (mp_count_bits(base) > 2048) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expBits > 2048) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 2048) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_2048_from_mp(b, 64, base);
- sp_2048_from_mp(e, 64, exp);
- sp_2048_from_mp(m, 64, mod);
- err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0);
- }
- if (err == MP_OKAY) {
- err = sp_2048_to_mp(r, res);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #ifdef WOLFSSL_HAVE_SP_DH
- #ifdef HAVE_FFDHE_2048
- static void sp_2048_lshift_64(sp_digit* r, sp_digit* a, byte n)
- {
- __asm__ __volatile__ (
- "mov r6, #31\n\t"
- "sub r6, r6, %[n]\n\t"
- "add %[a], %[a], #192\n\t"
- "add %[r], %[r], #192\n\t"
- "ldr r3, [%[a], #60]\n\t"
- "lsr r4, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r4, r4, r6\n\t"
- "ldr r2, [%[a], #56]\n\t"
- "str r4, [%[r], #64]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "str r3, [%[r], #60]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "str r2, [%[r], #56]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #44]\n\t"
- "str r4, [%[r], #52]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "str r3, [%[r], #48]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #36]\n\t"
- "str r2, [%[r], #44]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #32]\n\t"
- "str r4, [%[r], #40]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "str r3, [%[r], #36]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "str r2, [%[r], #32]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #20]\n\t"
- "str r4, [%[r], #28]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "str r3, [%[r], #24]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #12]\n\t"
- "str r2, [%[r], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #8]\n\t"
- "str r4, [%[r], #16]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "str r3, [%[r], #12]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "str r2, [%[r], #8]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r2, [%[a], #60]\n\t"
- "str r4, [%[r], #68]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "str r3, [%[r], #64]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #52]\n\t"
- "str r2, [%[r], #60]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #48]\n\t"
- "str r4, [%[r], #56]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "str r3, [%[r], #52]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "str r2, [%[r], #48]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #36]\n\t"
- "str r4, [%[r], #44]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "str r3, [%[r], #40]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #28]\n\t"
- "str r2, [%[r], #36]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #24]\n\t"
- "str r4, [%[r], #32]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "str r3, [%[r], #28]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "str r2, [%[r], #24]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #12]\n\t"
- "str r4, [%[r], #20]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "str r3, [%[r], #16]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #4]\n\t"
- "str r2, [%[r], #12]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #0]\n\t"
- "str r4, [%[r], #8]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "str r3, [%[r], #68]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "str r2, [%[r], #64]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #52]\n\t"
- "str r4, [%[r], #60]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "str r3, [%[r], #56]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #44]\n\t"
- "str r2, [%[r], #52]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #40]\n\t"
- "str r4, [%[r], #48]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "str r3, [%[r], #44]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "str r2, [%[r], #40]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #28]\n\t"
- "str r4, [%[r], #36]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "str r3, [%[r], #32]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #20]\n\t"
- "str r2, [%[r], #28]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #16]\n\t"
- "str r4, [%[r], #24]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "str r3, [%[r], #20]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "str r2, [%[r], #16]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #4]\n\t"
- "str r4, [%[r], #12]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "str r3, [%[r], #8]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r3, [%[a], #60]\n\t"
- "str r2, [%[r], #68]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #56]\n\t"
- "str r4, [%[r], #64]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "str r3, [%[r], #60]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "str r2, [%[r], #56]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #44]\n\t"
- "str r4, [%[r], #52]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "str r3, [%[r], #48]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #36]\n\t"
- "str r2, [%[r], #44]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #32]\n\t"
- "str r4, [%[r], #40]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "str r3, [%[r], #36]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "str r2, [%[r], #32]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #20]\n\t"
- "str r4, [%[r], #28]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "str r3, [%[r], #24]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #12]\n\t"
- "str r2, [%[r], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #8]\n\t"
- "str r4, [%[r], #16]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "str r3, [%[r], #12]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "str r2, [%[r], #8]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "str r3, [%[r]]\n\t"
- "str r4, [%[r], #4]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [n] "r" (n)
- : "memory", "r2", "r3", "r4", "r5", "r6"
- );
- }
- /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
- const sp_digit* m)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit nd[128];
- sp_digit td[65];
- #else
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit* tmp;
- sp_digit mp = 1;
- sp_digit n, o;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- norm = td;
- tmp = td + 128;
- #else
- norm = nd;
- tmp = td;
- #endif
- sp_2048_mont_setup(m, &mp);
- sp_2048_mont_norm_64(norm, m);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- sp_2048_lshift_64(r, norm, y);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_mont_sqr_64(r, r, m, mp);
- sp_2048_lshift_64(r, r, y);
- sp_2048_mul_d_64(tmp, norm, r[64]);
- r[64] = 0;
- o = sp_2048_add_64(r, r, tmp);
- sp_2048_cond_sub_64(r, r, m, (sp_digit)0 - o);
- }
- XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U);
- sp_2048_mont_reduce_64(r, m, mp);
- mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
- sp_2048_cond_sub_64(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* HAVE_FFDHE_2048 */
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base.
- * exp Array of bytes that is the exponent.
- * expLen Length of data, in bytes, in exponent.
- * mod Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 256 bytes long.
- * outLen Length, in bytes, of exponentiation result.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
- {
- int err = MP_OKAY;
- sp_digit b[128], e[64], m[64];
- sp_digit* r = b;
- word32 i;
- if (mp_count_bits(base) > 2048) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expLen > 256) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 2048) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_2048_from_mp(b, 64, base);
- sp_2048_from_bin(e, 64, exp, expLen);
- sp_2048_from_mp(m, 64, mod);
- #ifdef HAVE_FFDHE_2048
- if (base->used == 1 && base->dp[0] == 2 && m[63] == (sp_digit)-1)
- err = sp_2048_mod_exp_2_64(r, e, expLen * 8, m);
- else
- #endif
- err = sp_2048_mod_exp_64(r, b, e, expLen * 8, m, 0);
- }
- if (err == MP_OKAY) {
- sp_2048_to_bin(r, out);
- *outLen = 256;
- for (i=0; i<256 && out[i] == 0; i++) {
- }
- *outLen -= i;
- XMEMMOVE(out, out + i, *outLen);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_DH */
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base. MP integer.
- * exp Exponent. MP integer.
- * mod Modulus. MP integer.
- * res Result. MP integer.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
- {
- int err = MP_OKAY;
- sp_digit b[64], e[32], m[32];
- sp_digit* r = b;
- int expBits = mp_count_bits(exp);
- if (mp_count_bits(base) > 1024) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expBits > 1024) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 1024) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_2048_from_mp(b, 32, base);
- sp_2048_from_mp(e, 32, exp);
- sp_2048_from_mp(m, 32, mod);
- err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0);
- }
- if (err == MP_OKAY) {
- XMEMSET(r + 32, 0, sizeof(*r) * 32U);
- err = sp_2048_to_mp(r, res);
- res->used = mod->used;
- mp_clamp(res);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
- #endif /* !WOLFSSL_SP_NO_2048 */
- #ifndef WOLFSSL_SP_NO_3072
- /* Read big endian unsigned byte array into r.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a Byte array.
- * n Number of bytes in array to read.
- */
- static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
- {
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = n-1; i >= 0; i--) {
- r[j] |= (((sp_digit)a[i]) << s);
- if (s >= 24U) {
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- r[++j] = (sp_digit)a[i] >> s;
- s = 8U - s;
- }
- else {
- s += 8U;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- }
- /* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
- static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
- {
- #if DIGIT_BIT == 32
- int j;
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
- #elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #else
- int i, j = 0, s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #endif
- }
- /* Write r as big endian to byte array.
- * Fixed length number of bytes written: 384
- *
- * r A single precision integer.
- * a Byte array.
- */
- static void sp_3072_to_bin(sp_digit* r, byte* a)
- {
- int i, j, s = 0, b;
- j = 3072 / 8 - 1;
- a[j] = 0;
- for (i=0; i<96 && j>=0; i++) {
- b = 0;
- /* lint allow cast of mismatch sp_digit and int */
- a[j--] |= (byte)(r[i] << s); b += 8 - s; /*lint !e9033*/
- if (j < 0) {
- break;
- }
- while (b < 32) {
- a[j--] = r[i] >> b; b += 8;
- if (j < 0) {
- break;
- }
- }
- s = 8 - (b - 32);
- if (j >= 0) {
- a[j] = 0;
- }
- if (s != 0) {
- j++;
- }
- }
- }
- #ifndef WOLFSSL_SP_SMALL
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_3072_mul_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[12 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #48\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #44\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #88\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #96\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #44\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #48\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #88\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #92\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #96\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_add_12(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
- return c;
- }
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_sub_in_place_24(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
- return c;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_3072_mask_12(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<12; i++) {
- r[i] = a[i] & m;
- }
- #else
- r[0] = a[0] & m;
- r[1] = a[1] & m;
- r[2] = a[2] & m;
- r[3] = a[3] & m;
- r[4] = a[4] & m;
- r[5] = a[5] & m;
- r[6] = a[6] & m;
- r[7] = a[7] & m;
- r[8] = a[8] & m;
- r[9] = a[9] & m;
- r[10] = a[10] & m;
- r[11] = a[11] & m;
- #endif
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit* z0 = r;
- sp_digit z1[24];
- sp_digit a1[12];
- sp_digit b1[12];
- sp_digit z2[24];
- sp_digit u, ca, cb;
- ca = sp_3072_add_12(a1, a, &a[12]);
- cb = sp_3072_add_12(b1, b, &b[12]);
- u = ca & cb;
- sp_3072_mul_12(z1, a1, b1);
- sp_3072_mul_12(z2, &a[12], &b[12]);
- sp_3072_mul_12(z0, a, b);
- sp_3072_mask_12(r + 24, a1, 0 - cb);
- sp_3072_mask_12(b1, b1, 0 - ca);
- u += sp_3072_add_12(r + 24, r + 24, b1);
- u += sp_3072_sub_in_place_24(z1, z2);
- u += sp_3072_sub_in_place_24(z1, z0);
- u += sp_3072_add_24(r + 12, r + 12, z1);
- r[36] = u;
- XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1));
- (void)sp_3072_add_24(r + 24, r + 24, z2);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
- {
- sp_digit* z0 = r;
- sp_digit z2[24];
- sp_digit z1[24];
- sp_digit a1[12];
- sp_digit u;
- u = sp_3072_add_12(a1, a, &a[12]);
- sp_3072_sqr_12(z1, a1);
- sp_3072_sqr_12(z2, &a[12]);
- sp_3072_sqr_12(z0, a);
- sp_3072_mask_12(r + 24, a1, 0 - u);
- u += sp_3072_add_12(r + 24, r + 24, r + 24);
- u += sp_3072_sub_in_place_24(z1, z2);
- u += sp_3072_sub_in_place_24(z1, z0);
- u += sp_3072_add_24(r + 12, r + 12, z1);
- r[36] = u;
- XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1));
- (void)sp_3072_add_24(r + 24, r + 24, z2);
- }
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, #0\n\t"
- "mvn r7, r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r7"
- );
- return c;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_3072_mask_24(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<24; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 24; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit* z0 = r;
- sp_digit z1[48];
- sp_digit a1[24];
- sp_digit b1[24];
- sp_digit z2[48];
- sp_digit u, ca, cb;
- ca = sp_3072_add_24(a1, a, &a[24]);
- cb = sp_3072_add_24(b1, b, &b[24]);
- u = ca & cb;
- sp_3072_mul_24(z1, a1, b1);
- sp_3072_mul_24(z2, &a[24], &b[24]);
- sp_3072_mul_24(z0, a, b);
- sp_3072_mask_24(r + 48, a1, 0 - cb);
- sp_3072_mask_24(b1, b1, 0 - ca);
- u += sp_3072_add_24(r + 48, r + 48, b1);
- u += sp_3072_sub_in_place_48(z1, z2);
- u += sp_3072_sub_in_place_48(z1, z0);
- u += sp_3072_add_48(r + 24, r + 24, z1);
- r[72] = u;
- XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
- (void)sp_3072_add_48(r + 48, r + 48, z2);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
- {
- sp_digit* z0 = r;
- sp_digit z2[48];
- sp_digit z1[48];
- sp_digit a1[24];
- sp_digit u;
- u = sp_3072_add_24(a1, a, &a[24]);
- sp_3072_sqr_24(z1, a1);
- sp_3072_sqr_24(z2, &a[24]);
- sp_3072_sqr_24(z0, a);
- sp_3072_mask_24(r + 48, a1, 0 - u);
- u += sp_3072_add_24(r + 48, r + 48, r + 48);
- u += sp_3072_sub_in_place_48(z1, z2);
- u += sp_3072_sub_in_place_48(z1, z0);
- u += sp_3072_add_48(r + 24, r + 24, z1);
- r[72] = u;
- XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
- (void)sp_3072_add_48(r + 48, r + 48, z2);
- }
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, #0\n\t"
- "mvn r7, r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r7"
- );
- return c;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_3072_mask_48(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<48; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 48; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit* z0 = r;
- sp_digit z1[96];
- sp_digit a1[48];
- sp_digit b1[48];
- sp_digit z2[96];
- sp_digit u, ca, cb;
- ca = sp_3072_add_48(a1, a, &a[48]);
- cb = sp_3072_add_48(b1, b, &b[48]);
- u = ca & cb;
- sp_3072_mul_48(z1, a1, b1);
- sp_3072_mul_48(z2, &a[48], &b[48]);
- sp_3072_mul_48(z0, a, b);
- sp_3072_mask_48(r + 96, a1, 0 - cb);
- sp_3072_mask_48(b1, b1, 0 - ca);
- u += sp_3072_add_48(r + 96, r + 96, b1);
- u += sp_3072_sub_in_place_96(z1, z2);
- u += sp_3072_sub_in_place_96(z1, z0);
- u += sp_3072_add_96(r + 48, r + 48, z1);
- r[144] = u;
- XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1));
- (void)sp_3072_add_96(r + 96, r + 96, z2);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a)
- {
- sp_digit* z0 = r;
- sp_digit z2[96];
- sp_digit z1[96];
- sp_digit a1[48];
- sp_digit u;
- u = sp_3072_add_48(a1, a, &a[48]);
- sp_3072_sqr_48(z1, a1);
- sp_3072_sqr_48(z2, &a[48]);
- sp_3072_sqr_48(z0, a);
- sp_3072_mask_48(r + 96, a1, 0 - u);
- u += sp_3072_add_48(r + 96, r + 96, r + 96);
- u += sp_3072_sub_in_place_96(z1, z2);
- u += sp_3072_sub_in_place_96(z1, z0);
- u += sp_3072_add_96(r + 48, r + 48, z1);
- r[144] = u;
- XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1));
- (void)sp_3072_add_96(r + 96, r + 96, z2);
- }
- #endif /* !WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "mov r4, #1\n\t"
- "lsl r4, #8\n\t"
- "add r4, #128\n\t"
- "sub r7, #1\n\t"
- "add r6, r4\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Sub b from a into a. (a -= b)
- *
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, %[a]\n\t"
- "mov r5, #1\n\t"
- "lsl r5, #8\n\t"
- "add r5, #128\n\t"
- "add r7, r5\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a]]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b]]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a]]\n\t"
- "str r4, [%[a], #4]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #8\n\t"
- "add %[b], #8\n\t"
- "cmp %[a], r7\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[96 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #128\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #124\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #3\n\t"
- "lsl r6, r6, #8\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #124\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #128\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #2\n\t"
- "lsl r3, r3, #8\n\t"
- "add r3, #252\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #3\n\t"
- "lsl r6, r6, #8\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- #endif /* WOLFSSL_SP_SMALL */
- #if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
- #ifdef WOLFSSL_SP_SMALL
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_3072_mask_48(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- int i;
- for (i=0; i<48; i++) {
- r[i] = a[i] & m;
- }
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "add r6, #192\n\t"
- "sub r7, #1\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Sub b from a into a. (a -= b)
- *
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, %[a]\n\t"
- "add r7, #192\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a]]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b]]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a]]\n\t"
- "str r4, [%[a], #4]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #8\n\t"
- "add %[b], #8\n\t"
- "cmp %[a], r7\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[48 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #192\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #188\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #120\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #128\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #188\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #192\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #120\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #1\n\t"
- "lsl r3, r3, #8\n\t"
- "add r3, #124\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #128\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- #endif /* WOLFSSL_SP_SMALL */
- #endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
- /* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a A single precision number.
- * rho Bottom word of inverse.
- */
- static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
- {
- sp_digit x, b;
- b = a[0];
- x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
- x *= 2 - b * x; /* here x*a==1 mod 2**8 */
- x *= 2 - b * x; /* here x*a==1 mod 2**16 */
- x *= 2 - b * x; /* here x*a==1 mod 2**32 */
- /* rho = -1/m mod b */
- *rho = -x;
- }
- /* Mul a by digit b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision digit.
- */
- SP_NOINLINE static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a,
- sp_digit b)
- {
- __asm__ __volatile__ (
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #128\n\t"
- "add r6, %[a]\n\t"
- "mov r8, %[r]\n\t"
- "mov r9, r6\n\t"
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "# A[] * B\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# A[] * B - Done\n\t"
- "mov %[r], r8\n\t"
- "str r3, [%[r]]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add %[r], #4\n\t"
- "add %[a], #4\n\t"
- "mov r8, %[r]\n\t"
- "cmp %[a], r9\n\t"
- "blt 1b\n\t"
- "str r3, [%[r]]\n\t"
- : [r] "+r" (r), [a] "+r" (a)
- : [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
- );
- }
- #if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
- /* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r A single precision number.
- * m A single precision number.
- */
- static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m)
- {
- XMEMSET(r, 0, sizeof(sp_digit) * 48);
- /* r = 2^n mod m */
- sp_3072_sub_in_place_48(r, m);
- }
- /* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
- SP_NOINLINE static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a,
- const sp_digit* b, sp_digit m)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r5, #192\n\t"
- "mov r8, r5\n\t"
- "mov r7, #0\n\t"
- "1:\n\t"
- "ldr r6, [%[b], r7]\n\t"
- "and r6, %[m]\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r5, [%[a], r7]\n\t"
- "sbc r5, r6\n\t"
- "sbc %[c], %[c]\n\t"
- "str r5, [%[r], r7]\n\t"
- "add r7, #4\n\t"
- "cmp r7, r8\n\t"
- "blt 1b\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
- : "memory", "r5", "r6", "r7", "r8"
- );
- return c;
- }
- /* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
- SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_digit ca = 0;
- __asm__ __volatile__ (
- "mov r8, %[mp]\n\t"
- "mov r12, %[ca]\n\t"
- "mov r14, %[m]\n\t"
- "mov r9, %[a]\n\t"
- "mov r4, #0\n\t"
- "# i = 0\n\t"
- "mov r11, r4\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "mov %[ca], #0\n\t"
- "# mu = a[i] * mp\n\t"
- "mov %[mp], r8\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mul %[mp], %[a]\n\t"
- "mov %[m], r14\n\t"
- "mov r10, r9\n\t"
- "\n2:\n\t"
- "# a[i+j] += m[j] * mu\n\t"
- "mov %[a], r10\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "# Multiply m[j] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add %[a], r7\n\t"
- "adc r5, %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "# Multiply m[j] and mu - Done\n\t"
- "add r4, %[a]\n\t"
- "adc r5, %[ca]\n\t"
- "mov %[a], r10\n\t"
- "str r4, [%[a]]\n\t"
- "mov r6, #4\n\t"
- "add %[m], #4\n\t"
- "add r10, r6\n\t"
- "mov r4, #188\n\t"
- "add r4, r9\n\t"
- "cmp r10, r4\n\t"
- "blt 2b\n\t"
- "# a[i+47] += m[47] * mu\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r12\n\t"
- "mov %[a], #0\n\t"
- "# Multiply m[47] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "adc r4, %[ca]\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "# Multiply m[47] and mu - Done\n\t"
- "mov %[ca], %[a]\n\t"
- "mov %[a], r10\n\t"
- "ldr r7, [%[a], #4]\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov r6, #0\n\t"
- "add r5, %[a]\n\t"
- "adc r7, r4\n\t"
- "adc %[ca], r6\n\t"
- "mov %[a], r10\n\t"
- "str r5, [%[a]]\n\t"
- "str r7, [%[a], #4]\n\t"
- "# i += 1\n\t"
- "mov r6, #4\n\t"
- "add r9, r6\n\t"
- "add r11, r6\n\t"
- "mov r12, %[ca]\n\t"
- "mov %[a], r9\n\t"
- "mov r4, #192\n\t"
- "cmp r11, r4\n\t"
- "blt 1b\n\t"
- "mov %[m], r14\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
- : [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
- );
- sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca);
- }
- /* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r Result of multiplication.
- * a First number to multiply in Montogmery form.
- * b Second number to multiply in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
- {
- sp_3072_mul_48(r, a, b);
- sp_3072_mont_reduce_48(r, m, mp);
- }
- /* Square the Montgomery form number. (r = a * a mod m)
- *
- * r Result of squaring.
- * a Number to square in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_3072_sqr_48(r, a);
- sp_3072_mont_reduce_48(r, m, mp);
- }
- /* Mul a by digit b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision digit.
- */
- SP_NOINLINE static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a,
- sp_digit b)
- {
- __asm__ __volatile__ (
- "mov r6, #192\n\t"
- "add r6, %[a]\n\t"
- "mov r8, %[r]\n\t"
- "mov r9, r6\n\t"
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "# A[] * B\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# A[] * B - Done\n\t"
- "mov %[r], r8\n\t"
- "str r3, [%[r]]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add %[r], #4\n\t"
- "add %[a], #4\n\t"
- "mov r8, %[r]\n\t"
- "cmp %[a], r9\n\t"
- "blt 1b\n\t"
- "str r3, [%[r]]\n\t"
- : [r] "+r" (r), [a] "+r" (a)
- : [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
- );
- }
- /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1 The high order half of the number to divide.
- * d0 The low order half of the number to divide.
- * div The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
- SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0,
- sp_digit div)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "lsr r5, %[div], #1\n\t"
- "add r5, #1\n\t"
- "mov r8, %[d0]\n\t"
- "mov r9, %[d1]\n\t"
- "# Do top 32\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "# Next 30 bits\n\t"
- "mov r4, #29\n\t"
- "1:\n\t"
- "lsl %[d0], %[d0], #1\n\t"
- "adc %[d1], %[d1]\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "sub r4, #1\n\t"
- "bpl 1b\n\t"
- "mov r7, #0\n\t"
- "add %[r], %[r]\n\t"
- "add %[r], #1\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "sub %[d1], r4\n\t"
- "mov r4, %[d1]\n\t"
- "mov %[d1], r9\n\t"
- "sbc %[d1], r5\n\t"
- "mov r5, %[d1]\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "mov r6, %[div]\n\t"
- "sub r6, r4\n\t"
- "sbc r6, r6\n\t"
- "sub %[r], r6\n\t"
- : [r] "+r" (r)
- : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
- : "r4", "r5", "r7", "r6", "r8", "r9"
- );
- return r;
- }
- /* Compare a with b in constant time.
- *
- * a A single precision integer.
- * b A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
- SP_NOINLINE static int32_t sp_3072_cmp_48(const sp_digit* a, const sp_digit* b)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mvn r3, r3\n\t"
- "mov r6, #188\n\t"
- "1:\n\t"
- "ldr r7, [%[a], r6]\n\t"
- "ldr r5, [%[b], r6]\n\t"
- "and r7, r3\n\t"
- "and r5, r3\n\t"
- "mov r4, r7\n\t"
- "sub r7, r5\n\t"
- "sbc r7, r7\n\t"
- "add %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r5, r4\n\t"
- "sbc r7, r7\n\t"
- "sub %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r6, #4\n\t"
- "cmp r6, #0\n\t"
- "bge 1b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "r3", "r4", "r5", "r6", "r7"
- );
- return r;
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[96], t2[49];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[47];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 48);
- for (i=47; i>=0; i--) {
- r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div);
- sp_3072_mul_d_48(t2, d, r1);
- t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2);
- t1[48 + i] -= t2[48];
- sp_3072_mask_48(t2, d, t1[48 + i]);
- t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
- sp_3072_mask_48(t2, d, t1[48 + i]);
- t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
- }
- r1 = sp_3072_cmp_48(t1, d) >= 0;
- sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_3072_div_48(a, m, NULL, r);
- }
- #ifdef WOLFSSL_SP_SMALL
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[16][96];
- #else
- sp_digit* t[16];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 96, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<16; i++) {
- t[i] = td + i * 96;
- }
- #endif
- norm = t[0];
- sp_3072_mont_setup(m, &mp);
- sp_3072_mont_norm_48(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 48U);
- if (reduceA != 0) {
- err = sp_3072_mod_48(t[1] + 48, a, m);
- if (err == MP_OKAY) {
- err = sp_3072_mod_48(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
- err = sp_3072_mod_48(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
- sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
- sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
- sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
- sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
- sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
- sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
- sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
- sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
- sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
- sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
- sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
- sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
- sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 4;
- if (c == 32) {
- c = 28;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
- for (; i>=0 || c>=4; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 28;
- n <<= 4;
- c = 28;
- }
- else if (c < 4) {
- y = n >> 28;
- n = e[i--];
- c = 4 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 28) & 0xf;
- n <<= 4;
- c -= 4;
- }
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_mul_48(r, r, t[y], m, mp);
- }
- XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U);
- sp_3072_mont_reduce_48(r, m, mp);
- mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
- sp_3072_cond_sub_48(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #else
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[32][96];
- #else
- sp_digit* t[32];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<32; i++) {
- t[i] = td + i * 96;
- }
- #endif
- norm = t[0];
- sp_3072_mont_setup(m, &mp);
- sp_3072_mont_norm_48(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 48U);
- if (reduceA != 0) {
- err = sp_3072_mod_48(t[1] + 48, a, m);
- if (err == MP_OKAY) {
- err = sp_3072_mod_48(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
- err = sp_3072_mod_48(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
- sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
- sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
- sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
- sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
- sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
- sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
- sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
- sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
- sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
- sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
- sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
- sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
- sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
- sp_3072_mont_sqr_48(t[16], t[ 8], m, mp);
- sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp);
- sp_3072_mont_sqr_48(t[18], t[ 9], m, mp);
- sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp);
- sp_3072_mont_sqr_48(t[20], t[10], m, mp);
- sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp);
- sp_3072_mont_sqr_48(t[22], t[11], m, mp);
- sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp);
- sp_3072_mont_sqr_48(t[24], t[12], m, mp);
- sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp);
- sp_3072_mont_sqr_48(t[26], t[13], m, mp);
- sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp);
- sp_3072_mont_sqr_48(t[28], t[14], m, mp);
- sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp);
- sp_3072_mont_sqr_48(t[30], t[15], m, mp);
- sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_sqr_48(r, r, m, mp);
- sp_3072_mont_mul_48(r, r, t[y], m, mp);
- }
- XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U);
- sp_3072_mont_reduce_48(r, m, mp);
- mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
- sp_3072_cond_sub_48(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */
- #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
- /* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r A single precision number.
- * m A single precision number.
- */
- static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m)
- {
- XMEMSET(r, 0, sizeof(sp_digit) * 96);
- /* r = 2^n mod m */
- sp_3072_sub_in_place_96(r, m);
- }
- #endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
- /* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
- SP_NOINLINE static sp_digit sp_3072_cond_sub_96(sp_digit* r, const sp_digit* a,
- const sp_digit* b, sp_digit m)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r5, #1\n\t"
- "lsl r5, r5, #8\n\t"
- "add r5, #128\n\t"
- "mov r8, r5\n\t"
- "mov r7, #0\n\t"
- "1:\n\t"
- "ldr r6, [%[b], r7]\n\t"
- "and r6, %[m]\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r5, [%[a], r7]\n\t"
- "sbc r5, r6\n\t"
- "sbc %[c], %[c]\n\t"
- "str r5, [%[r], r7]\n\t"
- "add r7, #4\n\t"
- "cmp r7, r8\n\t"
- "blt 1b\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
- : "memory", "r5", "r6", "r7", "r8"
- );
- return c;
- }
- /* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
- SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_digit ca = 0;
- __asm__ __volatile__ (
- "mov r8, %[mp]\n\t"
- "mov r12, %[ca]\n\t"
- "mov r14, %[m]\n\t"
- "mov r9, %[a]\n\t"
- "mov r4, #0\n\t"
- "# i = 0\n\t"
- "mov r11, r4\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "mov %[ca], #0\n\t"
- "# mu = a[i] * mp\n\t"
- "mov %[mp], r8\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mul %[mp], %[a]\n\t"
- "mov %[m], r14\n\t"
- "mov r10, r9\n\t"
- "\n2:\n\t"
- "# a[i+j] += m[j] * mu\n\t"
- "mov %[a], r10\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "# Multiply m[j] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add %[a], r7\n\t"
- "adc r5, %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "# Multiply m[j] and mu - Done\n\t"
- "add r4, %[a]\n\t"
- "adc r5, %[ca]\n\t"
- "mov %[a], r10\n\t"
- "str r4, [%[a]]\n\t"
- "mov r6, #4\n\t"
- "add %[m], #4\n\t"
- "add r10, r6\n\t"
- "mov r4, #1\n\t"
- "lsl r4, r4, #8\n\t"
- "add r4, #124\n\t"
- "add r4, r9\n\t"
- "cmp r10, r4\n\t"
- "blt 2b\n\t"
- "# a[i+95] += m[95] * mu\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r12\n\t"
- "mov %[a], #0\n\t"
- "# Multiply m[95] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "adc r4, %[ca]\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "# Multiply m[95] and mu - Done\n\t"
- "mov %[ca], %[a]\n\t"
- "mov %[a], r10\n\t"
- "ldr r7, [%[a], #4]\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov r6, #0\n\t"
- "add r5, %[a]\n\t"
- "adc r7, r4\n\t"
- "adc %[ca], r6\n\t"
- "mov %[a], r10\n\t"
- "str r5, [%[a]]\n\t"
- "str r7, [%[a], #4]\n\t"
- "# i += 1\n\t"
- "mov r6, #4\n\t"
- "add r9, r6\n\t"
- "add r11, r6\n\t"
- "mov r12, %[ca]\n\t"
- "mov %[a], r9\n\t"
- "mov r4, #1\n\t"
- "lsl r4, r4, #8\n\t"
- "add r4, #128\n\t"
- "cmp r11, r4\n\t"
- "blt 1b\n\t"
- "mov %[m], r14\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
- : [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
- );
- sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - ca);
- }
- /* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r Result of multiplication.
- * a First number to multiply in Montogmery form.
- * b Second number to multiply in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
- {
- sp_3072_mul_96(r, a, b);
- sp_3072_mont_reduce_96(r, m, mp);
- }
- /* Square the Montgomery form number. (r = a * a mod m)
- *
- * r Result of squaring.
- * a Number to square in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_3072_sqr_96(r, a);
- sp_3072_mont_reduce_96(r, m, mp);
- }
- /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1 The high order half of the number to divide.
- * d0 The low order half of the number to divide.
- * div The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
- SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0,
- sp_digit div)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "lsr r5, %[div], #1\n\t"
- "add r5, #1\n\t"
- "mov r8, %[d0]\n\t"
- "mov r9, %[d1]\n\t"
- "# Do top 32\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "# Next 30 bits\n\t"
- "mov r4, #29\n\t"
- "1:\n\t"
- "lsl %[d0], %[d0], #1\n\t"
- "adc %[d1], %[d1]\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "sub r4, #1\n\t"
- "bpl 1b\n\t"
- "mov r7, #0\n\t"
- "add %[r], %[r]\n\t"
- "add %[r], #1\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "sub %[d1], r4\n\t"
- "mov r4, %[d1]\n\t"
- "mov %[d1], r9\n\t"
- "sbc %[d1], r5\n\t"
- "mov r5, %[d1]\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "mov r6, %[div]\n\t"
- "sub r6, r4\n\t"
- "sbc r6, r6\n\t"
- "sub %[r], r6\n\t"
- : [r] "+r" (r)
- : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
- : "r4", "r5", "r7", "r6", "r8", "r9"
- );
- return r;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_3072_mask_96(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<96; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 96; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Compare a with b in constant time.
- *
- * a A single precision integer.
- * b A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
- SP_NOINLINE static int32_t sp_3072_cmp_96(const sp_digit* a, const sp_digit* b)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mvn r3, r3\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #124\n\t"
- "1:\n\t"
- "ldr r7, [%[a], r6]\n\t"
- "ldr r5, [%[b], r6]\n\t"
- "and r7, r3\n\t"
- "and r5, r3\n\t"
- "mov r4, r7\n\t"
- "sub r7, r5\n\t"
- "sbc r7, r7\n\t"
- "add %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r5, r4\n\t"
- "sbc r7, r7\n\t"
- "sub %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r6, #4\n\t"
- "cmp r6, #0\n\t"
- "bge 1b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "r3", "r4", "r5", "r6", "r7"
- );
- return r;
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_3072_div_96(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[192], t2[97];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[95];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 96);
- for (i=95; i>=0; i--) {
- r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div);
- sp_3072_mul_d_96(t2, d, r1);
- t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2);
- t1[96 + i] -= t2[96];
- sp_3072_mask_96(t2, d, t1[96 + i]);
- t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2);
- sp_3072_mask_96(t2, d, t1[96 + i]);
- t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2);
- }
- r1 = sp_3072_cmp_96(t1, d) >= 0;
- sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_3072_mod_96(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_3072_div_96(a, m, NULL, r);
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_3072_div_96_cond(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[192], t2[97];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[95];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 96);
- for (i=95; i>=0; i--) {
- r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div);
- sp_3072_mul_d_96(t2, d, r1);
- t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2);
- t1[96 + i] -= t2[96];
- if (t1[96 + i] != 0) {
- t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d);
- if (t1[96 + i] != 0)
- t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d);
- }
- }
- r1 = sp_3072_cmp_96(t1, d) >= 0;
- sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_3072_div_96_cond(a, m, NULL, r);
- }
- #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
- defined(WOLFSSL_HAVE_SP_DH)
- #ifdef WOLFSSL_SP_SMALL
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[16][192];
- #else
- sp_digit* t[16];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 192, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<16; i++) {
- t[i] = td + i * 192;
- }
- #endif
- norm = t[0];
- sp_3072_mont_setup(m, &mp);
- sp_3072_mont_norm_96(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 96U);
- if (reduceA != 0) {
- err = sp_3072_mod_96(t[1] + 96, a, m);
- if (err == MP_OKAY) {
- err = sp_3072_mod_96(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96);
- err = sp_3072_mod_96(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp);
- sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp);
- sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp);
- sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp);
- sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp);
- sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp);
- sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp);
- sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp);
- sp_3072_mont_sqr_96(t[10], t[ 5], m, mp);
- sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp);
- sp_3072_mont_sqr_96(t[12], t[ 6], m, mp);
- sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp);
- sp_3072_mont_sqr_96(t[14], t[ 7], m, mp);
- sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 4;
- if (c == 32) {
- c = 28;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
- for (; i>=0 || c>=4; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 28;
- n <<= 4;
- c = 28;
- }
- else if (c < 4) {
- y = n >> 28;
- n = e[i--];
- c = 4 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 28) & 0xf;
- n <<= 4;
- c -= 4;
- }
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_mul_96(r, r, t[y], m, mp);
- }
- XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U);
- sp_3072_mont_reduce_96(r, m, mp);
- mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
- sp_3072_cond_sub_96(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #else
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[32][192];
- #else
- sp_digit* t[32];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 192, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<32; i++) {
- t[i] = td + i * 192;
- }
- #endif
- norm = t[0];
- sp_3072_mont_setup(m, &mp);
- sp_3072_mont_norm_96(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 96U);
- if (reduceA != 0) {
- err = sp_3072_mod_96(t[1] + 96, a, m);
- if (err == MP_OKAY) {
- err = sp_3072_mod_96(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96);
- err = sp_3072_mod_96(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp);
- sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp);
- sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp);
- sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp);
- sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp);
- sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp);
- sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp);
- sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp);
- sp_3072_mont_sqr_96(t[10], t[ 5], m, mp);
- sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp);
- sp_3072_mont_sqr_96(t[12], t[ 6], m, mp);
- sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp);
- sp_3072_mont_sqr_96(t[14], t[ 7], m, mp);
- sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp);
- sp_3072_mont_sqr_96(t[16], t[ 8], m, mp);
- sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp);
- sp_3072_mont_sqr_96(t[18], t[ 9], m, mp);
- sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp);
- sp_3072_mont_sqr_96(t[20], t[10], m, mp);
- sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp);
- sp_3072_mont_sqr_96(t[22], t[11], m, mp);
- sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp);
- sp_3072_mont_sqr_96(t[24], t[12], m, mp);
- sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp);
- sp_3072_mont_sqr_96(t[26], t[13], m, mp);
- sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp);
- sp_3072_mont_sqr_96(t[28], t[14], m, mp);
- sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp);
- sp_3072_mont_sqr_96(t[30], t[15], m, mp);
- sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_mul_96(r, r, t[y], m, mp);
- }
- XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U);
- sp_3072_mont_reduce_96(r, m, mp);
- mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
- sp_3072_cond_sub_96(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
- #ifdef WOLFSSL_HAVE_SP_RSA
- /* RSA public key operation.
- *
- * in Array of bytes representing the number to exponentiate, base.
- * inLen Number of bytes in base.
- * em Public exponent.
- * mm Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 384 bytes long.
- * outLen Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
- int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit ad[192], md[96], rd[192];
- #else
- sp_digit* d = NULL;
- #endif
- sp_digit* a;
- sp_digit *ah;
- sp_digit* m;
- sp_digit* r;
- sp_digit e[1];
- int err = MP_OKAY;
- if (*outLen < 384)
- err = MP_TO_E;
- if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 ||
- mp_count_bits(mm) != 3072))
- err = MP_READ_E;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL,
- DYNAMIC_TYPE_RSA);
- if (d == NULL)
- err = MEMORY_E;
- }
- if (err == MP_OKAY) {
- a = d;
- r = a + 96 * 2;
- m = r + 96 * 2;
- ah = a + 96;
- }
- #else
- a = ad;
- m = md;
- r = rd;
- ah = a + 96;
- #endif
- if (err == MP_OKAY) {
- sp_3072_from_bin(ah, 96, in, inLen);
- #if DIGIT_BIT >= 32
- e[0] = em->dp[0];
- #else
- e[0] = em->dp[0];
- if (em->used > 1)
- e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
- #endif
- if (e[0] == 0)
- err = MP_EXPTMOD_E;
- }
- if (err == MP_OKAY) {
- sp_3072_from_mp(m, 96, mm);
- if (e[0] == 0x3) {
- if (err == MP_OKAY) {
- sp_3072_sqr_96(r, ah);
- err = sp_3072_mod_96_cond(r, r, m);
- }
- if (err == MP_OKAY) {
- sp_3072_mul_96(r, ah, r);
- err = sp_3072_mod_96_cond(r, r, m);
- }
- }
- else {
- int i;
- sp_digit mp;
- sp_3072_mont_setup(m, &mp);
- /* Convert to Montgomery form. */
- XMEMSET(a, 0, sizeof(sp_digit) * 96);
- err = sp_3072_mod_96_cond(a, a, m);
- if (err == MP_OKAY) {
- for (i=31; i>=0; i--)
- if (e[0] >> i)
- break;
- XMEMCPY(r, a, sizeof(sp_digit) * 96);
- for (i--; i>=0; i--) {
- sp_3072_mont_sqr_96(r, r, m, mp);
- if (((e[0] >> i) & 1) == 1)
- sp_3072_mont_mul_96(r, r, a, m, mp);
- }
- XMEMSET(&r[96], 0, sizeof(sp_digit) * 96);
- sp_3072_mont_reduce_96(r, m, mp);
- for (i = 95; i > 0; i--) {
- if (r[i] != m[i])
- break;
- }
- if (r[i] >= m[i])
- sp_3072_sub_in_place_96(r, m);
- }
- }
- }
- if (err == MP_OKAY) {
- sp_3072_to_bin(r, out);
- *outLen = 384;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL)
- XFREE(d, NULL, DYNAMIC_TYPE_RSA);
- #endif
- return err;
- }
- /* RSA private key operation.
- *
- * in Array of bytes representing the number to exponentiate, base.
- * inLen Number of bytes in base.
- * dm Private exponent.
- * pm First prime.
- * qm Second prime.
- * dpm First prime's CRT exponent.
- * dqm Second prime's CRT exponent.
- * qim Inverse of second prime mod p.
- * mm Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 384 bytes long.
- * outLen Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
- int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit ad[96 * 2];
- sp_digit pd[48], qd[48], dpd[48];
- sp_digit tmpad[96], tmpbd[96];
- #else
- sp_digit* t = NULL;
- #endif
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmp;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
- sp_digit c;
- int err = MP_OKAY;
- (void)dm;
- (void)mm;
- if (*outLen < 384)
- err = MP_TO_E;
- if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
- err = MP_READ_E;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL,
- DYNAMIC_TYPE_RSA);
- if (t == NULL)
- err = MEMORY_E;
- }
- if (err == MP_OKAY) {
- a = t;
- p = a + 96 * 2;
- q = p + 48;
- qi = dq = dp = q + 48;
- tmpa = qi + 48;
- tmpb = tmpa + 96;
- tmp = t;
- r = tmp + 96;
- }
- #else
- r = a = ad;
- p = pd;
- q = qd;
- qi = dq = dp = dpd;
- tmpa = tmpad;
- tmpb = tmpbd;
- tmp = a + 96;
- #endif
- if (err == MP_OKAY) {
- sp_3072_from_bin(a, 96, in, inLen);
- sp_3072_from_mp(p, 48, pm);
- sp_3072_from_mp(q, 48, qm);
- sp_3072_from_mp(dp, 48, dpm);
- err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1);
- }
- if (err == MP_OKAY) {
- sp_3072_from_mp(dq, 48, dqm);
- err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1);
- }
- if (err == MP_OKAY) {
- c = sp_3072_sub_in_place_48(tmpa, tmpb);
- sp_3072_mask_48(tmp, p, c);
- sp_3072_add_48(tmpa, tmpa, tmp);
- sp_3072_from_mp(qi, 48, qim);
- sp_3072_mul_48(tmpa, tmpa, qi);
- err = sp_3072_mod_48(tmpa, tmpa, p);
- }
- if (err == MP_OKAY) {
- sp_3072_mul_48(tmpa, q, tmpa);
- XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48);
- sp_3072_add_96(r, tmpb, tmpa);
- sp_3072_to_bin(r, out);
- *outLen = 384;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (t != NULL) {
- XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11);
- XFREE(t, NULL, DYNAMIC_TYPE_RSA);
- }
- #else
- XMEMSET(tmpad, 0, sizeof(tmpad));
- XMEMSET(tmpbd, 0, sizeof(tmpbd));
- XMEMSET(pd, 0, sizeof(pd));
- XMEMSET(qd, 0, sizeof(qd));
- XMEMSET(dpd, 0, sizeof(dpd));
- #endif
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_RSA */
- #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
- !defined(WOLFSSL_RSA_PUBLIC_ONLY))
- /* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
- static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
- {
- int err;
- err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
- #if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 96);
- r->used = 96;
- mp_clamp(r);
- #elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 96; i++) {
- r->dp[j] |= a[i] << s;
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = a[i] >> s;
- }
- }
- s = 32 - s;
- }
- r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #else
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 96; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #endif
- }
- return err;
- }
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base. MP integer.
- * exp Exponent. MP integer.
- * mod Modulus. MP integer.
- * res Result. MP integer.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
- {
- int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
- sp_digit* r = b;
- int expBits = mp_count_bits(exp);
- if (mp_count_bits(base) > 3072) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expBits > 3072) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 3072) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_3072_from_mp(b, 96, base);
- sp_3072_from_mp(e, 96, exp);
- sp_3072_from_mp(m, 96, mod);
- err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0);
- }
- if (err == MP_OKAY) {
- err = sp_3072_to_mp(r, res);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #ifdef WOLFSSL_HAVE_SP_DH
- #ifdef HAVE_FFDHE_3072
- static void sp_3072_lshift_96(sp_digit* r, sp_digit* a, byte n)
- {
- __asm__ __volatile__ (
- "mov r6, #31\n\t"
- "sub r6, r6, %[n]\n\t"
- "add %[a], %[a], #255\n\t"
- "add %[r], %[r], #255\n\t"
- "add %[a], %[a], #65\n\t"
- "add %[r], %[r], #65\n\t"
- "ldr r3, [%[a], #60]\n\t"
- "lsr r4, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r4, r4, r6\n\t"
- "ldr r2, [%[a], #56]\n\t"
- "str r4, [%[r], #64]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "str r3, [%[r], #60]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "str r2, [%[r], #56]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #44]\n\t"
- "str r4, [%[r], #52]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "str r3, [%[r], #48]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #36]\n\t"
- "str r2, [%[r], #44]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #32]\n\t"
- "str r4, [%[r], #40]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "str r3, [%[r], #36]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "str r2, [%[r], #32]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #20]\n\t"
- "str r4, [%[r], #28]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "str r3, [%[r], #24]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #12]\n\t"
- "str r2, [%[r], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #8]\n\t"
- "str r4, [%[r], #16]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "str r3, [%[r], #12]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "str r2, [%[r], #8]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r2, [%[a], #60]\n\t"
- "str r4, [%[r], #68]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "str r3, [%[r], #64]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #52]\n\t"
- "str r2, [%[r], #60]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #48]\n\t"
- "str r4, [%[r], #56]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "str r3, [%[r], #52]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "str r2, [%[r], #48]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #36]\n\t"
- "str r4, [%[r], #44]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "str r3, [%[r], #40]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #28]\n\t"
- "str r2, [%[r], #36]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #24]\n\t"
- "str r4, [%[r], #32]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "str r3, [%[r], #28]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "str r2, [%[r], #24]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #12]\n\t"
- "str r4, [%[r], #20]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "str r3, [%[r], #16]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #4]\n\t"
- "str r2, [%[r], #12]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #0]\n\t"
- "str r4, [%[r], #8]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "str r3, [%[r], #68]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "str r2, [%[r], #64]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #52]\n\t"
- "str r4, [%[r], #60]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "str r3, [%[r], #56]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #44]\n\t"
- "str r2, [%[r], #52]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #40]\n\t"
- "str r4, [%[r], #48]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "str r3, [%[r], #44]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "str r2, [%[r], #40]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #28]\n\t"
- "str r4, [%[r], #36]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "str r3, [%[r], #32]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #20]\n\t"
- "str r2, [%[r], #28]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #16]\n\t"
- "str r4, [%[r], #24]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "str r3, [%[r], #20]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "str r2, [%[r], #16]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #4]\n\t"
- "str r4, [%[r], #12]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "str r3, [%[r], #8]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r3, [%[a], #60]\n\t"
- "str r2, [%[r], #68]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #56]\n\t"
- "str r4, [%[r], #64]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "str r3, [%[r], #60]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "str r2, [%[r], #56]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #44]\n\t"
- "str r4, [%[r], #52]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "str r3, [%[r], #48]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #36]\n\t"
- "str r2, [%[r], #44]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #32]\n\t"
- "str r4, [%[r], #40]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "str r3, [%[r], #36]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "str r2, [%[r], #32]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #20]\n\t"
- "str r4, [%[r], #28]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "str r3, [%[r], #24]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #12]\n\t"
- "str r2, [%[r], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #8]\n\t"
- "str r4, [%[r], #16]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "str r3, [%[r], #12]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "str r2, [%[r], #8]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r2, [%[a], #60]\n\t"
- "str r4, [%[r], #68]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "str r3, [%[r], #64]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #52]\n\t"
- "str r2, [%[r], #60]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #48]\n\t"
- "str r4, [%[r], #56]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "str r3, [%[r], #52]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "str r2, [%[r], #48]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #36]\n\t"
- "str r4, [%[r], #44]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "str r3, [%[r], #40]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #28]\n\t"
- "str r2, [%[r], #36]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #24]\n\t"
- "str r4, [%[r], #32]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "str r3, [%[r], #28]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "str r2, [%[r], #24]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #12]\n\t"
- "str r4, [%[r], #20]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "str r3, [%[r], #16]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #4]\n\t"
- "str r2, [%[r], #12]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #0]\n\t"
- "str r4, [%[r], #8]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "str r3, [%[r], #68]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "str r2, [%[r], #64]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #52]\n\t"
- "str r4, [%[r], #60]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "str r3, [%[r], #56]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #44]\n\t"
- "str r2, [%[r], #52]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #40]\n\t"
- "str r4, [%[r], #48]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "str r3, [%[r], #44]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "str r2, [%[r], #40]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #28]\n\t"
- "str r4, [%[r], #36]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "str r3, [%[r], #32]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #20]\n\t"
- "str r2, [%[r], #28]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #16]\n\t"
- "str r4, [%[r], #24]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "str r3, [%[r], #20]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "str r2, [%[r], #16]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #4]\n\t"
- "str r4, [%[r], #12]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "str r3, [%[r], #8]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "str r4, [%[r]]\n\t"
- "str r2, [%[r], #4]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [n] "r" (n)
- : "memory", "r2", "r3", "r4", "r5", "r6"
- );
- }
- /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
- const sp_digit* m)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit nd[192];
- sp_digit td[97];
- #else
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit* tmp;
- sp_digit mp = 1;
- sp_digit n, o;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- norm = td;
- tmp = td + 192;
- #else
- norm = nd;
- tmp = td;
- #endif
- sp_3072_mont_setup(m, &mp);
- sp_3072_mont_norm_96(norm, m);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- sp_3072_lshift_96(r, norm, y);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_mont_sqr_96(r, r, m, mp);
- sp_3072_lshift_96(r, r, y);
- sp_3072_mul_d_96(tmp, norm, r[96]);
- r[96] = 0;
- o = sp_3072_add_96(r, r, tmp);
- sp_3072_cond_sub_96(r, r, m, (sp_digit)0 - o);
- }
- XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U);
- sp_3072_mont_reduce_96(r, m, mp);
- mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
- sp_3072_cond_sub_96(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* HAVE_FFDHE_3072 */
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base.
- * exp Array of bytes that is the exponent.
- * expLen Length of data, in bytes, in exponent.
- * mod Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 384 bytes long.
- * outLen Length, in bytes, of exponentiation result.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
- {
- int err = MP_OKAY;
- sp_digit b[192], e[96], m[96];
- sp_digit* r = b;
- word32 i;
- if (mp_count_bits(base) > 3072) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expLen > 384) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 3072) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_3072_from_mp(b, 96, base);
- sp_3072_from_bin(e, 96, exp, expLen);
- sp_3072_from_mp(m, 96, mod);
- #ifdef HAVE_FFDHE_3072
- if (base->used == 1 && base->dp[0] == 2 && m[95] == (sp_digit)-1)
- err = sp_3072_mod_exp_2_96(r, e, expLen * 8, m);
- else
- #endif
- err = sp_3072_mod_exp_96(r, b, e, expLen * 8, m, 0);
- }
- if (err == MP_OKAY) {
- sp_3072_to_bin(r, out);
- *outLen = 384;
- for (i=0; i<384 && out[i] == 0; i++) {
- }
- *outLen -= i;
- XMEMMOVE(out, out + i, *outLen);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_DH */
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base. MP integer.
- * exp Exponent. MP integer.
- * mod Modulus. MP integer.
- * res Result. MP integer.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
- {
- int err = MP_OKAY;
- sp_digit b[96], e[48], m[48];
- sp_digit* r = b;
- int expBits = mp_count_bits(exp);
- if (mp_count_bits(base) > 1536) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expBits > 1536) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 1536) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_3072_from_mp(b, 48, base);
- sp_3072_from_mp(e, 48, exp);
- sp_3072_from_mp(m, 48, mod);
- err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0);
- }
- if (err == MP_OKAY) {
- XMEMSET(r + 48, 0, sizeof(*r) * 48U);
- err = sp_3072_to_mp(r, res);
- res->used = mod->used;
- mp_clamp(res);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
- #endif /* !WOLFSSL_SP_NO_3072 */
- #ifdef WOLFSSL_SP_4096
- /* Read big endian unsigned byte array into r.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a Byte array.
- * n Number of bytes in array to read.
- */
- static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
- {
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = n-1; i >= 0; i--) {
- r[j] |= (((sp_digit)a[i]) << s);
- if (s >= 24U) {
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- r[++j] = (sp_digit)a[i] >> s;
- s = 8U - s;
- }
- else {
- s += 8U;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- }
- /* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
- static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
- {
- #if DIGIT_BIT == 32
- int j;
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
- #elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #else
- int i, j = 0, s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #endif
- }
- /* Write r as big endian to byte array.
- * Fixed length number of bytes written: 512
- *
- * r A single precision integer.
- * a Byte array.
- */
- static void sp_4096_to_bin(sp_digit* r, byte* a)
- {
- int i, j, s = 0, b;
- j = 4096 / 8 - 1;
- a[j] = 0;
- for (i=0; i<128 && j>=0; i++) {
- b = 0;
- /* lint allow cast of mismatch sp_digit and int */
- a[j--] |= (byte)(r[i] << s); b += 8 - s; /*lint !e9033*/
- if (j < 0) {
- break;
- }
- while (b < 32) {
- a[j--] = r[i] >> b; b += 8;
- if (j < 0) {
- break;
- }
- }
- s = 8 - (b - 32);
- if (j >= 0) {
- a[j] = 0;
- }
- if (s != 0) {
- j++;
- }
- }
- }
- #ifndef WOLFSSL_SP_SMALL
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_4096_add_64(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, #0\n\t"
- "mvn r7, r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r7"
- );
- return c;
- }
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_4096_sub_in_place_128(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "ldr r6, [%[b], #36]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #32]\n\t"
- "str r4, [%[a], #36]\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "ldr r6, [%[b], #44]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #40]\n\t"
- "str r4, [%[a], #44]\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "ldr r6, [%[b], #52]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #48]\n\t"
- "str r4, [%[a], #52]\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "ldr r6, [%[b], #60]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #56]\n\t"
- "str r4, [%[a], #60]\n\t"
- "ldr r3, [%[a], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "ldr r6, [%[b], #68]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #64]\n\t"
- "str r4, [%[a], #68]\n\t"
- "ldr r3, [%[a], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "ldr r6, [%[b], #76]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #72]\n\t"
- "str r4, [%[a], #76]\n\t"
- "ldr r3, [%[a], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "ldr r6, [%[b], #84]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #80]\n\t"
- "str r4, [%[a], #84]\n\t"
- "ldr r3, [%[a], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "ldr r6, [%[b], #92]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #88]\n\t"
- "str r4, [%[a], #92]\n\t"
- "ldr r3, [%[a], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "ldr r6, [%[b], #100]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #96]\n\t"
- "str r4, [%[a], #100]\n\t"
- "ldr r3, [%[a], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "ldr r6, [%[b], #108]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #104]\n\t"
- "str r4, [%[a], #108]\n\t"
- "ldr r3, [%[a], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "ldr r6, [%[b], #116]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #112]\n\t"
- "str r4, [%[a], #116]\n\t"
- "ldr r3, [%[a], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "ldr r6, [%[b], #124]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #120]\n\t"
- "str r4, [%[a], #124]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, #0\n\t"
- "mvn r7, r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #0x80\n\t"
- "add %[b], #0x80\n\t"
- "add %[r], #0x80\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "ldr r5, [%[b], #32]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #32]\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "ldr r5, [%[b], #36]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #36]\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "ldr r5, [%[b], #40]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #40]\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "ldr r5, [%[b], #44]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #44]\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "ldr r5, [%[b], #48]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #48]\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "ldr r5, [%[b], #52]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #52]\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "ldr r5, [%[b], #56]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #56]\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "ldr r5, [%[b], #60]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #60]\n\t"
- "ldr r4, [%[a], #64]\n\t"
- "ldr r5, [%[b], #64]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #64]\n\t"
- "ldr r4, [%[a], #68]\n\t"
- "ldr r5, [%[b], #68]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #68]\n\t"
- "ldr r4, [%[a], #72]\n\t"
- "ldr r5, [%[b], #72]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #72]\n\t"
- "ldr r4, [%[a], #76]\n\t"
- "ldr r5, [%[b], #76]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #76]\n\t"
- "ldr r4, [%[a], #80]\n\t"
- "ldr r5, [%[b], #80]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #80]\n\t"
- "ldr r4, [%[a], #84]\n\t"
- "ldr r5, [%[b], #84]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #84]\n\t"
- "ldr r4, [%[a], #88]\n\t"
- "ldr r5, [%[b], #88]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #88]\n\t"
- "ldr r4, [%[a], #92]\n\t"
- "ldr r5, [%[b], #92]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #92]\n\t"
- "ldr r4, [%[a], #96]\n\t"
- "ldr r5, [%[b], #96]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #96]\n\t"
- "ldr r4, [%[a], #100]\n\t"
- "ldr r5, [%[b], #100]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #100]\n\t"
- "ldr r4, [%[a], #104]\n\t"
- "ldr r5, [%[b], #104]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #104]\n\t"
- "ldr r4, [%[a], #108]\n\t"
- "ldr r5, [%[b], #108]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #108]\n\t"
- "ldr r4, [%[a], #112]\n\t"
- "ldr r5, [%[b], #112]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #112]\n\t"
- "ldr r4, [%[a], #116]\n\t"
- "ldr r5, [%[b], #116]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #116]\n\t"
- "ldr r4, [%[a], #120]\n\t"
- "ldr r5, [%[b], #120]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #120]\n\t"
- "ldr r4, [%[a], #124]\n\t"
- "ldr r5, [%[b], #124]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #124]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r7"
- );
- return c;
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_4096_mul_64(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[64 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #252\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_4096_mask_64(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<64; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 64; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit* z0 = r;
- sp_digit z1[128];
- sp_digit a1[64];
- sp_digit b1[64];
- sp_digit z2[128];
- sp_digit u, ca, cb;
- ca = sp_2048_add_64(a1, a, &a[64]);
- cb = sp_2048_add_64(b1, b, &b[64]);
- u = ca & cb;
- sp_2048_mul_64(z1, a1, b1);
- sp_2048_mul_64(z2, &a[64], &b[64]);
- sp_2048_mul_64(z0, a, b);
- sp_2048_mask_64(r + 128, a1, 0 - cb);
- sp_2048_mask_64(b1, b1, 0 - ca);
- u += sp_2048_add_64(r + 128, r + 128, b1);
- u += sp_4096_sub_in_place_128(z1, z2);
- u += sp_4096_sub_in_place_128(z1, z0);
- u += sp_4096_add_128(r + 64, r + 64, z1);
- r[192] = u;
- XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1));
- (void)sp_4096_add_128(r + 128, r + 128, z2);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #252\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #1\n\t"
- "lsl r3, r3, #8\n\t"
- "add r3, #252\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a)
- {
- sp_digit* z0 = r;
- sp_digit z2[128];
- sp_digit z1[128];
- sp_digit a1[64];
- sp_digit u;
- u = sp_2048_add_64(a1, a, &a[64]);
- sp_2048_sqr_64(z1, a1);
- sp_2048_sqr_64(z2, &a[64]);
- sp_2048_sqr_64(z0, a);
- sp_2048_mask_64(r + 128, a1, 0 - u);
- u += sp_2048_add_64(r + 128, r + 128, r + 128);
- u += sp_4096_sub_in_place_128(z1, z2);
- u += sp_4096_sub_in_place_128(z1, z0);
- u += sp_4096_add_128(r + 64, r + 64, z1);
- r[192] = u;
- XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1));
- (void)sp_4096_add_128(r + 128, r + 128, z2);
- }
- #endif /* !WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "mov r4, #2\n\t"
- "lsl r4, #8\n\t"
- "sub r7, #1\n\t"
- "add r6, r4\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Sub b from a into a. (a -= b)
- *
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_4096_sub_in_place_128(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, %[a]\n\t"
- "mov r5, #2\n\t"
- "lsl r5, #8\n\t"
- "add r7, r5\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a]]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b]]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a]]\n\t"
- "str r4, [%[a], #4]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #8\n\t"
- "add %[b], #8\n\t"
- "cmp %[a], r7\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #ifdef WOLFSSL_SP_SMALL
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[128 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #252\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #3\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #4\n\t"
- "lsl r6, r6, #8\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #252\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #3\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #248\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #3\n\t"
- "lsl r3, r3, #8\n\t"
- "add r3, #252\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #4\n\t"
- "lsl r6, r6, #8\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- #endif /* WOLFSSL_SP_SMALL */
- /* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a A single precision number.
- * rho Bottom word of inverse.
- */
- static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
- {
- sp_digit x, b;
- b = a[0];
- x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
- x *= 2 - b * x; /* here x*a==1 mod 2**8 */
- x *= 2 - b * x; /* here x*a==1 mod 2**16 */
- x *= 2 - b * x; /* here x*a==1 mod 2**32 */
- /* rho = -1/m mod b */
- *rho = -x;
- }
- /* Mul a by digit b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision digit.
- */
- SP_NOINLINE static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a,
- sp_digit b)
- {
- __asm__ __volatile__ (
- "mov r6, #2\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, %[a]\n\t"
- "mov r8, %[r]\n\t"
- "mov r9, r6\n\t"
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "# A[] * B\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# A[] * B - Done\n\t"
- "mov %[r], r8\n\t"
- "str r3, [%[r]]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add %[r], #4\n\t"
- "add %[a], #4\n\t"
- "mov r8, %[r]\n\t"
- "cmp %[a], r9\n\t"
- "blt 1b\n\t"
- "str r3, [%[r]]\n\t"
- : [r] "+r" (r), [a] "+r" (a)
- : [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
- );
- }
- #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
- /* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 4096 bits, just need to subtract.
- *
- * r A single precision number.
- * m A single precision number.
- */
- static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m)
- {
- XMEMSET(r, 0, sizeof(sp_digit) * 128);
- /* r = 2^n mod m */
- sp_4096_sub_in_place_128(r, m);
- }
- #endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
- /* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
- SP_NOINLINE static sp_digit sp_4096_cond_sub_128(sp_digit* r, const sp_digit* a,
- const sp_digit* b, sp_digit m)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r5, #2\n\t"
- "lsl r5, r5, #8\n\t"
- "mov r8, r5\n\t"
- "mov r7, #0\n\t"
- "1:\n\t"
- "ldr r6, [%[b], r7]\n\t"
- "and r6, %[m]\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r5, [%[a], r7]\n\t"
- "sbc r5, r6\n\t"
- "sbc %[c], %[c]\n\t"
- "str r5, [%[r], r7]\n\t"
- "add r7, #4\n\t"
- "cmp r7, r8\n\t"
- "blt 1b\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
- : "memory", "r5", "r6", "r7", "r8"
- );
- return c;
- }
- /* Reduce the number back to 4096 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
- SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_digit ca = 0;
- __asm__ __volatile__ (
- "mov r8, %[mp]\n\t"
- "mov r12, %[ca]\n\t"
- "mov r14, %[m]\n\t"
- "mov r9, %[a]\n\t"
- "mov r4, #0\n\t"
- "# i = 0\n\t"
- "mov r11, r4\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "mov %[ca], #0\n\t"
- "# mu = a[i] * mp\n\t"
- "mov %[mp], r8\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mul %[mp], %[a]\n\t"
- "mov %[m], r14\n\t"
- "mov r10, r9\n\t"
- "\n2:\n\t"
- "# a[i+j] += m[j] * mu\n\t"
- "mov %[a], r10\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "# Multiply m[j] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add %[a], r7\n\t"
- "adc r5, %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "# Multiply m[j] and mu - Done\n\t"
- "add r4, %[a]\n\t"
- "adc r5, %[ca]\n\t"
- "mov %[a], r10\n\t"
- "str r4, [%[a]]\n\t"
- "mov r6, #4\n\t"
- "add %[m], #4\n\t"
- "add r10, r6\n\t"
- "mov r4, #1\n\t"
- "lsl r4, r4, #8\n\t"
- "add r4, #252\n\t"
- "add r4, r9\n\t"
- "cmp r10, r4\n\t"
- "blt 2b\n\t"
- "# a[i+127] += m[127] * mu\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r12\n\t"
- "mov %[a], #0\n\t"
- "# Multiply m[127] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "adc r4, %[ca]\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "# Multiply m[127] and mu - Done\n\t"
- "mov %[ca], %[a]\n\t"
- "mov %[a], r10\n\t"
- "ldr r7, [%[a], #4]\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov r6, #0\n\t"
- "add r5, %[a]\n\t"
- "adc r7, r4\n\t"
- "adc %[ca], r6\n\t"
- "mov %[a], r10\n\t"
- "str r5, [%[a]]\n\t"
- "str r7, [%[a], #4]\n\t"
- "# i += 1\n\t"
- "mov r6, #4\n\t"
- "add r9, r6\n\t"
- "add r11, r6\n\t"
- "mov r12, %[ca]\n\t"
- "mov %[a], r9\n\t"
- "mov r4, #2\n\t"
- "lsl r4, r4, #8\n\t"
- "cmp r11, r4\n\t"
- "blt 1b\n\t"
- "mov %[m], r14\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
- : [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
- );
- sp_4096_cond_sub_128(a - 128, a, m, (sp_digit)0 - ca);
- }
- /* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r Result of multiplication.
- * a First number to multiply in Montogmery form.
- * b Second number to multiply in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
- {
- sp_4096_mul_128(r, a, b);
- sp_4096_mont_reduce_128(r, m, mp);
- }
- /* Square the Montgomery form number. (r = a * a mod m)
- *
- * r Result of squaring.
- * a Number to square in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_4096_sqr_128(r, a);
- sp_4096_mont_reduce_128(r, m, mp);
- }
- /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1 The high order half of the number to divide.
- * d0 The low order half of the number to divide.
- * div The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
- SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0,
- sp_digit div)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "lsr r5, %[div], #1\n\t"
- "add r5, #1\n\t"
- "mov r8, %[d0]\n\t"
- "mov r9, %[d1]\n\t"
- "# Do top 32\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "# Next 30 bits\n\t"
- "mov r4, #29\n\t"
- "1:\n\t"
- "lsl %[d0], %[d0], #1\n\t"
- "adc %[d1], %[d1]\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "sub r4, #1\n\t"
- "bpl 1b\n\t"
- "mov r7, #0\n\t"
- "add %[r], %[r]\n\t"
- "add %[r], #1\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "sub %[d1], r4\n\t"
- "mov r4, %[d1]\n\t"
- "mov %[d1], r9\n\t"
- "sbc %[d1], r5\n\t"
- "mov r5, %[d1]\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "mov r6, %[div]\n\t"
- "sub r6, r4\n\t"
- "sbc r6, r6\n\t"
- "sub %[r], r6\n\t"
- : [r] "+r" (r)
- : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
- : "r4", "r5", "r7", "r6", "r8", "r9"
- );
- return r;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_4096_mask_128(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<128; i++) {
- r[i] = a[i] & m;
- }
- #else
- int i;
- for (i = 0; i < 128; i += 8) {
- r[i+0] = a[i+0] & m;
- r[i+1] = a[i+1] & m;
- r[i+2] = a[i+2] & m;
- r[i+3] = a[i+3] & m;
- r[i+4] = a[i+4] & m;
- r[i+5] = a[i+5] & m;
- r[i+6] = a[i+6] & m;
- r[i+7] = a[i+7] & m;
- }
- #endif
- }
- /* Compare a with b in constant time.
- *
- * a A single precision integer.
- * b A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
- SP_NOINLINE static int32_t sp_4096_cmp_128(const sp_digit* a, const sp_digit* b)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mvn r3, r3\n\t"
- "mov r6, #1\n\t"
- "lsl r6, r6, #8\n\t"
- "add r6, #252\n\t"
- "1:\n\t"
- "ldr r7, [%[a], r6]\n\t"
- "ldr r5, [%[b], r6]\n\t"
- "and r7, r3\n\t"
- "and r5, r3\n\t"
- "mov r4, r7\n\t"
- "sub r7, r5\n\t"
- "sbc r7, r7\n\t"
- "add %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r5, r4\n\t"
- "sbc r7, r7\n\t"
- "sub %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r6, #4\n\t"
- "cmp r6, #0\n\t"
- "bge 1b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "r3", "r4", "r5", "r6", "r7"
- );
- return r;
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_4096_div_128(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[256], t2[129];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[127];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 128);
- for (i=127; i>=0; i--) {
- r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div);
- sp_4096_mul_d_128(t2, d, r1);
- t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2);
- t1[128 + i] -= t2[128];
- sp_4096_mask_128(t2, d, t1[128 + i]);
- t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2);
- sp_4096_mask_128(t2, d, t1[128 + i]);
- t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2);
- }
- r1 = sp_4096_cmp_128(t1, d) >= 0;
- sp_4096_cond_sub_128(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_4096_mod_128(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_4096_div_128(a, m, NULL, r);
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_4096_div_128_cond(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[256], t2[129];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[127];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 128);
- for (i=127; i>=0; i--) {
- r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div);
- sp_4096_mul_d_128(t2, d, r1);
- t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2);
- t1[128 + i] -= t2[128];
- if (t1[128 + i] != 0) {
- t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d);
- if (t1[128 + i] != 0)
- t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d);
- }
- }
- r1 = sp_4096_cmp_128(t1, d) >= 0;
- sp_4096_cond_sub_128(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_4096_mod_128_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_4096_div_128_cond(a, m, NULL, r);
- }
- #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
- defined(WOLFSSL_HAVE_SP_DH)
- #ifdef WOLFSSL_SP_SMALL
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[16][256];
- #else
- sp_digit* t[16];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 256, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<16; i++) {
- t[i] = td + i * 256;
- }
- #endif
- norm = t[0];
- sp_4096_mont_setup(m, &mp);
- sp_4096_mont_norm_128(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 128U);
- if (reduceA != 0) {
- err = sp_4096_mod_128(t[1] + 128, a, m);
- if (err == MP_OKAY) {
- err = sp_4096_mod_128(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128);
- err = sp_4096_mod_128(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp);
- sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp);
- sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp);
- sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp);
- sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp);
- sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp);
- sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp);
- sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp);
- sp_4096_mont_sqr_128(t[10], t[ 5], m, mp);
- sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp);
- sp_4096_mont_sqr_128(t[12], t[ 6], m, mp);
- sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp);
- sp_4096_mont_sqr_128(t[14], t[ 7], m, mp);
- sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 4;
- if (c == 32) {
- c = 28;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
- for (; i>=0 || c>=4; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 28;
- n <<= 4;
- c = 28;
- }
- else if (c < 4) {
- y = n >> 28;
- n = e[i--];
- c = 4 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 28) & 0xf;
- n <<= 4;
- c -= 4;
- }
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_mul_128(r, r, t[y], m, mp);
- }
- XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U);
- sp_4096_mont_reduce_128(r, m, mp);
- mask = 0 - (sp_4096_cmp_128(r, m) >= 0);
- sp_4096_cond_sub_128(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #else
- /* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * a A single precision number being exponentiated.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e,
- int bits, const sp_digit* m, int reduceA)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit t[32][256];
- #else
- sp_digit* t[32];
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit mp = 1;
- sp_digit n;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 256, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- for (i=0; i<32; i++) {
- t[i] = td + i * 256;
- }
- #endif
- norm = t[0];
- sp_4096_mont_setup(m, &mp);
- sp_4096_mont_norm_128(norm, m);
- XMEMSET(t[1], 0, sizeof(sp_digit) * 128U);
- if (reduceA != 0) {
- err = sp_4096_mod_128(t[1] + 128, a, m);
- if (err == MP_OKAY) {
- err = sp_4096_mod_128(t[1], t[1], m);
- }
- }
- else {
- XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128);
- err = sp_4096_mod_128(t[1], t[1], m);
- }
- }
- if (err == MP_OKAY) {
- sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp);
- sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp);
- sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp);
- sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp);
- sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp);
- sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp);
- sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp);
- sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp);
- sp_4096_mont_sqr_128(t[10], t[ 5], m, mp);
- sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp);
- sp_4096_mont_sqr_128(t[12], t[ 6], m, mp);
- sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp);
- sp_4096_mont_sqr_128(t[14], t[ 7], m, mp);
- sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp);
- sp_4096_mont_sqr_128(t[16], t[ 8], m, mp);
- sp_4096_mont_mul_128(t[17], t[ 9], t[ 8], m, mp);
- sp_4096_mont_sqr_128(t[18], t[ 9], m, mp);
- sp_4096_mont_mul_128(t[19], t[10], t[ 9], m, mp);
- sp_4096_mont_sqr_128(t[20], t[10], m, mp);
- sp_4096_mont_mul_128(t[21], t[11], t[10], m, mp);
- sp_4096_mont_sqr_128(t[22], t[11], m, mp);
- sp_4096_mont_mul_128(t[23], t[12], t[11], m, mp);
- sp_4096_mont_sqr_128(t[24], t[12], m, mp);
- sp_4096_mont_mul_128(t[25], t[13], t[12], m, mp);
- sp_4096_mont_sqr_128(t[26], t[13], m, mp);
- sp_4096_mont_mul_128(t[27], t[14], t[13], m, mp);
- sp_4096_mont_sqr_128(t[28], t[14], m, mp);
- sp_4096_mont_mul_128(t[29], t[15], t[14], m, mp);
- sp_4096_mont_sqr_128(t[30], t[15], m, mp);
- sp_4096_mont_mul_128(t[31], t[16], t[15], m, mp);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_mul_128(r, r, t[y], m, mp);
- }
- XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U);
- sp_4096_mont_reduce_128(r, m, mp);
- mask = 0 - (sp_4096_cmp_128(r, m) >= 0);
- sp_4096_cond_sub_128(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* WOLFSSL_SP_SMALL */
- #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
- #ifdef WOLFSSL_HAVE_SP_RSA
- /* RSA public key operation.
- *
- * in Array of bytes representing the number to exponentiate, base.
- * inLen Number of bytes in base.
- * em Public exponent.
- * mm Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 512 bytes long.
- * outLen Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
- int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
- byte* out, word32* outLen)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit ad[256], md[128], rd[256];
- #else
- sp_digit* d = NULL;
- #endif
- sp_digit* a;
- sp_digit *ah;
- sp_digit* m;
- sp_digit* r;
- sp_digit e[1];
- int err = MP_OKAY;
- if (*outLen < 512)
- err = MP_TO_E;
- if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 512 ||
- mp_count_bits(mm) != 4096))
- err = MP_READ_E;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL,
- DYNAMIC_TYPE_RSA);
- if (d == NULL)
- err = MEMORY_E;
- }
- if (err == MP_OKAY) {
- a = d;
- r = a + 128 * 2;
- m = r + 128 * 2;
- ah = a + 128;
- }
- #else
- a = ad;
- m = md;
- r = rd;
- ah = a + 128;
- #endif
- if (err == MP_OKAY) {
- sp_4096_from_bin(ah, 128, in, inLen);
- #if DIGIT_BIT >= 32
- e[0] = em->dp[0];
- #else
- e[0] = em->dp[0];
- if (em->used > 1)
- e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
- #endif
- if (e[0] == 0)
- err = MP_EXPTMOD_E;
- }
- if (err == MP_OKAY) {
- sp_4096_from_mp(m, 128, mm);
- if (e[0] == 0x3) {
- if (err == MP_OKAY) {
- sp_4096_sqr_128(r, ah);
- err = sp_4096_mod_128_cond(r, r, m);
- }
- if (err == MP_OKAY) {
- sp_4096_mul_128(r, ah, r);
- err = sp_4096_mod_128_cond(r, r, m);
- }
- }
- else {
- int i;
- sp_digit mp;
- sp_4096_mont_setup(m, &mp);
- /* Convert to Montgomery form. */
- XMEMSET(a, 0, sizeof(sp_digit) * 128);
- err = sp_4096_mod_128_cond(a, a, m);
- if (err == MP_OKAY) {
- for (i=31; i>=0; i--)
- if (e[0] >> i)
- break;
- XMEMCPY(r, a, sizeof(sp_digit) * 128);
- for (i--; i>=0; i--) {
- sp_4096_mont_sqr_128(r, r, m, mp);
- if (((e[0] >> i) & 1) == 1)
- sp_4096_mont_mul_128(r, r, a, m, mp);
- }
- XMEMSET(&r[128], 0, sizeof(sp_digit) * 128);
- sp_4096_mont_reduce_128(r, m, mp);
- for (i = 127; i > 0; i--) {
- if (r[i] != m[i])
- break;
- }
- if (r[i] >= m[i])
- sp_4096_sub_in_place_128(r, m);
- }
- }
- }
- if (err == MP_OKAY) {
- sp_4096_to_bin(r, out);
- *outLen = 512;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL)
- XFREE(d, NULL, DYNAMIC_TYPE_RSA);
- #endif
- return err;
- }
- /* RSA private key operation.
- *
- * in Array of bytes representing the number to exponentiate, base.
- * inLen Number of bytes in base.
- * dm Private exponent.
- * pm First prime.
- * qm Second prime.
- * dpm First prime's CRT exponent.
- * dqm Second prime's CRT exponent.
- * qim Inverse of second prime mod p.
- * mm Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 512 bytes long.
- * outLen Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
- int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm,
- mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
- byte* out, word32* outLen)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit ad[128 * 2];
- sp_digit pd[64], qd[64], dpd[64];
- sp_digit tmpad[128], tmpbd[128];
- #else
- sp_digit* t = NULL;
- #endif
- sp_digit* a;
- sp_digit* p;
- sp_digit* q;
- sp_digit* dp;
- sp_digit* dq;
- sp_digit* qi;
- sp_digit* tmp;
- sp_digit* tmpa;
- sp_digit* tmpb;
- sp_digit* r;
- sp_digit c;
- int err = MP_OKAY;
- (void)dm;
- (void)mm;
- if (*outLen < 512)
- err = MP_TO_E;
- if (err == MP_OKAY && (inLen > 512 || mp_count_bits(mm) != 4096))
- err = MP_READ_E;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL,
- DYNAMIC_TYPE_RSA);
- if (t == NULL)
- err = MEMORY_E;
- }
- if (err == MP_OKAY) {
- a = t;
- p = a + 128 * 2;
- q = p + 64;
- qi = dq = dp = q + 64;
- tmpa = qi + 64;
- tmpb = tmpa + 128;
- tmp = t;
- r = tmp + 128;
- }
- #else
- r = a = ad;
- p = pd;
- q = qd;
- qi = dq = dp = dpd;
- tmpa = tmpad;
- tmpb = tmpbd;
- tmp = a + 128;
- #endif
- if (err == MP_OKAY) {
- sp_4096_from_bin(a, 128, in, inLen);
- sp_4096_from_mp(p, 64, pm);
- sp_4096_from_mp(q, 64, qm);
- sp_4096_from_mp(dp, 64, dpm);
- err = sp_4096_mod_exp_64(tmpa, a, dp, 2048, p, 1);
- }
- if (err == MP_OKAY) {
- sp_4096_from_mp(dq, 64, dqm);
- err = sp_4096_mod_exp_64(tmpb, a, dq, 2048, q, 1);
- }
- if (err == MP_OKAY) {
- c = sp_4096_sub_in_place_64(tmpa, tmpb);
- sp_4096_mask_64(tmp, p, c);
- sp_4096_add_64(tmpa, tmpa, tmp);
- sp_4096_from_mp(qi, 64, qim);
- sp_4096_mul_64(tmpa, tmpa, qi);
- err = sp_4096_mod_64(tmpa, tmpa, p);
- }
- if (err == MP_OKAY) {
- sp_4096_mul_64(tmpa, q, tmpa);
- XMEMSET(&tmpb[64], 0, sizeof(sp_digit) * 64);
- sp_4096_add_128(r, tmpb, tmpa);
- sp_4096_to_bin(r, out);
- *outLen = 512;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (t != NULL) {
- XMEMSET(t, 0, sizeof(sp_digit) * 64 * 11);
- XFREE(t, NULL, DYNAMIC_TYPE_RSA);
- }
- #else
- XMEMSET(tmpad, 0, sizeof(tmpad));
- XMEMSET(tmpbd, 0, sizeof(tmpbd));
- XMEMSET(pd, 0, sizeof(pd));
- XMEMSET(qd, 0, sizeof(qd));
- XMEMSET(dpd, 0, sizeof(dpd));
- #endif
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_RSA */
- #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
- !defined(WOLFSSL_RSA_PUBLIC_ONLY))
- /* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
- static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
- {
- int err;
- err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
- #if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 128);
- r->used = 128;
- mp_clamp(r);
- #elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 128; i++) {
- r->dp[j] |= a[i] << s;
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = a[i] >> s;
- }
- }
- s = 32 - s;
- }
- r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #else
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 128; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #endif
- }
- return err;
- }
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base. MP integer.
- * exp Exponent. MP integer.
- * mod Modulus. MP integer.
- * res Result. MP integer.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
- {
- int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
- sp_digit* r = b;
- int expBits = mp_count_bits(exp);
- if (mp_count_bits(base) > 4096) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expBits > 4096) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 4096) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_4096_from_mp(b, 128, base);
- sp_4096_from_mp(e, 128, exp);
- sp_4096_from_mp(m, 128, mod);
- err = sp_4096_mod_exp_128(r, b, e, expBits, m, 0);
- }
- if (err == MP_OKAY) {
- err = sp_4096_to_mp(r, res);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #ifdef WOLFSSL_HAVE_SP_DH
- #ifdef HAVE_FFDHE_4096
- static void sp_4096_lshift_128(sp_digit* r, sp_digit* a, byte n)
- {
- __asm__ __volatile__ (
- "mov r6, #31\n\t"
- "sub r6, r6, %[n]\n\t"
- "add %[a], %[a], #255\n\t"
- "add %[r], %[r], #255\n\t"
- "add %[a], %[a], #193\n\t"
- "add %[r], %[r], #193\n\t"
- "ldr r3, [%[a], #60]\n\t"
- "lsr r4, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r4, r4, r6\n\t"
- "ldr r2, [%[a], #56]\n\t"
- "str r4, [%[r], #64]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "str r3, [%[r], #60]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "str r2, [%[r], #56]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #44]\n\t"
- "str r4, [%[r], #52]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "str r3, [%[r], #48]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #36]\n\t"
- "str r2, [%[r], #44]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #32]\n\t"
- "str r4, [%[r], #40]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "str r3, [%[r], #36]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "str r2, [%[r], #32]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #20]\n\t"
- "str r4, [%[r], #28]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "str r3, [%[r], #24]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #12]\n\t"
- "str r2, [%[r], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #8]\n\t"
- "str r4, [%[r], #16]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "str r3, [%[r], #12]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "str r2, [%[r], #8]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r2, [%[a], #60]\n\t"
- "str r4, [%[r], #68]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "str r3, [%[r], #64]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #52]\n\t"
- "str r2, [%[r], #60]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #48]\n\t"
- "str r4, [%[r], #56]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "str r3, [%[r], #52]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "str r2, [%[r], #48]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #36]\n\t"
- "str r4, [%[r], #44]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "str r3, [%[r], #40]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #28]\n\t"
- "str r2, [%[r], #36]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #24]\n\t"
- "str r4, [%[r], #32]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "str r3, [%[r], #28]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "str r2, [%[r], #24]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #12]\n\t"
- "str r4, [%[r], #20]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "str r3, [%[r], #16]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #4]\n\t"
- "str r2, [%[r], #12]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #0]\n\t"
- "str r4, [%[r], #8]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "str r3, [%[r], #68]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "str r2, [%[r], #64]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #52]\n\t"
- "str r4, [%[r], #60]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "str r3, [%[r], #56]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #44]\n\t"
- "str r2, [%[r], #52]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #40]\n\t"
- "str r4, [%[r], #48]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "str r3, [%[r], #44]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "str r2, [%[r], #40]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #28]\n\t"
- "str r4, [%[r], #36]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "str r3, [%[r], #32]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #20]\n\t"
- "str r2, [%[r], #28]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #16]\n\t"
- "str r4, [%[r], #24]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "str r3, [%[r], #20]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "str r2, [%[r], #16]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #4]\n\t"
- "str r4, [%[r], #12]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "str r3, [%[r], #8]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r3, [%[a], #60]\n\t"
- "str r2, [%[r], #68]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #56]\n\t"
- "str r4, [%[r], #64]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "str r3, [%[r], #60]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "str r2, [%[r], #56]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #44]\n\t"
- "str r4, [%[r], #52]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "str r3, [%[r], #48]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #36]\n\t"
- "str r2, [%[r], #44]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #32]\n\t"
- "str r4, [%[r], #40]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "str r3, [%[r], #36]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "str r2, [%[r], #32]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #20]\n\t"
- "str r4, [%[r], #28]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "str r3, [%[r], #24]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #12]\n\t"
- "str r2, [%[r], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #8]\n\t"
- "str r4, [%[r], #16]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "str r3, [%[r], #12]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "str r2, [%[r], #8]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r2, [%[a], #60]\n\t"
- "str r4, [%[r], #68]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "str r3, [%[r], #64]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #52]\n\t"
- "str r2, [%[r], #60]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #48]\n\t"
- "str r4, [%[r], #56]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "str r3, [%[r], #52]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "str r2, [%[r], #48]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #36]\n\t"
- "str r4, [%[r], #44]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "str r3, [%[r], #40]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #28]\n\t"
- "str r2, [%[r], #36]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #24]\n\t"
- "str r4, [%[r], #32]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "str r3, [%[r], #28]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "str r2, [%[r], #24]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #12]\n\t"
- "str r4, [%[r], #20]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "str r3, [%[r], #16]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #4]\n\t"
- "str r2, [%[r], #12]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #0]\n\t"
- "str r4, [%[r], #8]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r4, [%[a], #60]\n\t"
- "str r3, [%[r], #68]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #56]\n\t"
- "str r2, [%[r], #64]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #52]\n\t"
- "str r4, [%[r], #60]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #48]\n\t"
- "str r3, [%[r], #56]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #44]\n\t"
- "str r2, [%[r], #52]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #40]\n\t"
- "str r4, [%[r], #48]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #36]\n\t"
- "str r3, [%[r], #44]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #32]\n\t"
- "str r2, [%[r], #40]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #28]\n\t"
- "str r4, [%[r], #36]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "str r3, [%[r], #32]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #20]\n\t"
- "str r2, [%[r], #28]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #16]\n\t"
- "str r4, [%[r], #24]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "str r3, [%[r], #20]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "str r2, [%[r], #16]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #4]\n\t"
- "str r4, [%[r], #12]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #0]\n\t"
- "str r3, [%[r], #8]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r3, [%[a], #60]\n\t"
- "str r2, [%[r], #68]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #56]\n\t"
- "str r4, [%[r], #64]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #52]\n\t"
- "str r3, [%[r], #60]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #48]\n\t"
- "str r2, [%[r], #56]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #44]\n\t"
- "str r4, [%[r], #52]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #40]\n\t"
- "str r3, [%[r], #48]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #36]\n\t"
- "str r2, [%[r], #44]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #32]\n\t"
- "str r4, [%[r], #40]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "str r3, [%[r], #36]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "str r2, [%[r], #32]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #20]\n\t"
- "str r4, [%[r], #28]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "str r3, [%[r], #24]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #12]\n\t"
- "str r2, [%[r], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #8]\n\t"
- "str r4, [%[r], #16]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "str r3, [%[r], #12]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "str r2, [%[r], #8]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "sub %[a], %[a], #64\n\t"
- "sub %[r], %[r], #64\n\t"
- "ldr r2, [%[a], #60]\n\t"
- "str r4, [%[r], #68]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #56]\n\t"
- "str r3, [%[r], #64]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #52]\n\t"
- "str r2, [%[r], #60]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #48]\n\t"
- "str r4, [%[r], #56]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #44]\n\t"
- "str r3, [%[r], #52]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #40]\n\t"
- "str r2, [%[r], #48]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #36]\n\t"
- "str r4, [%[r], #44]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #32]\n\t"
- "str r3, [%[r], #40]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #28]\n\t"
- "str r2, [%[r], #36]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #24]\n\t"
- "str r4, [%[r], #32]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "str r3, [%[r], #28]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "str r2, [%[r], #24]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #12]\n\t"
- "str r4, [%[r], #20]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "str r3, [%[r], #16]\n\t"
- "lsr r5, r4, #1\n\t"
- "lsl r4, r4, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r2, r2, r5\n\t"
- "ldr r3, [%[a], #4]\n\t"
- "str r2, [%[r], #12]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r4, r4, r5\n\t"
- "ldr r2, [%[a], #0]\n\t"
- "str r4, [%[r], #8]\n\t"
- "lsr r5, r2, #1\n\t"
- "lsl r2, r2, %[n]\n\t"
- "lsr r5, r5, r6\n\t"
- "orr r3, r3, r5\n\t"
- "str r2, [%[r]]\n\t"
- "str r3, [%[r], #4]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [n] "r" (n)
- : "memory", "r2", "r3", "r4", "r5", "r6"
- );
- }
- /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
- *
- * r A single precision number that is the result of the operation.
- * e A single precision number that is the exponent.
- * bits The number of bits in the exponent.
- * m A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
- static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
- const sp_digit* m)
- {
- #ifndef WOLFSSL_SMALL_STACK
- sp_digit nd[256];
- sp_digit td[129];
- #else
- sp_digit* td;
- #endif
- sp_digit* norm;
- sp_digit* tmp;
- sp_digit mp = 1;
- sp_digit n, o;
- sp_digit mask;
- int i;
- int c, y;
- int err = MP_OKAY;
- #ifdef WOLFSSL_SMALL_STACK
- td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (td == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #ifdef WOLFSSL_SMALL_STACK
- norm = td;
- tmp = td + 256;
- #else
- norm = nd;
- tmp = td;
- #endif
- sp_4096_mont_setup(m, &mp);
- sp_4096_mont_norm_128(norm, m);
- i = (bits - 1) / 32;
- n = e[i--];
- c = bits & 31;
- if (c == 0) {
- c = 32;
- }
- c -= bits % 5;
- if (c == 32) {
- c = 27;
- }
- y = (int)(n >> c);
- n <<= 32 - c;
- sp_4096_lshift_128(r, norm, y);
- for (; i>=0 || c>=5; ) {
- if (c == 0) {
- n = e[i--];
- y = n >> 27;
- n <<= 5;
- c = 27;
- }
- else if (c < 5) {
- y = n >> 27;
- n = e[i--];
- c = 5 - c;
- y |= n >> (32 - c);
- n <<= c;
- c = 32 - c;
- }
- else {
- y = (n >> 27) & 0x1f;
- n <<= 5;
- c -= 5;
- }
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_mont_sqr_128(r, r, m, mp);
- sp_4096_lshift_128(r, r, y);
- sp_4096_mul_d_128(tmp, norm, r[128]);
- r[128] = 0;
- o = sp_4096_add_128(r, r, tmp);
- sp_4096_cond_sub_128(r, r, m, (sp_digit)0 - o);
- }
- XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U);
- sp_4096_mont_reduce_128(r, m, mp);
- mask = 0 - (sp_4096_cmp_128(r, m) >= 0);
- sp_4096_cond_sub_128(r, r, m, mask);
- }
- #ifdef WOLFSSL_SMALL_STACK
- if (td != NULL) {
- XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
- #endif
- return err;
- }
- #endif /* HAVE_FFDHE_4096 */
- /* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base Base.
- * exp Array of bytes that is the exponent.
- * expLen Length of data, in bytes, in exponent.
- * mod Modulus.
- * out Buffer to hold big-endian bytes of exponentiation result.
- * Must be at least 512 bytes long.
- * outLen Length, in bytes, of exponentiation result.
- * returns 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
- int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen,
- mp_int* mod, byte* out, word32* outLen)
- {
- int err = MP_OKAY;
- sp_digit b[256], e[128], m[128];
- sp_digit* r = b;
- word32 i;
- if (mp_count_bits(base) > 4096) {
- err = MP_READ_E;
- }
- if (err == MP_OKAY) {
- if (expLen > 512) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- if (mp_count_bits(mod) != 4096) {
- err = MP_READ_E;
- }
- }
- if (err == MP_OKAY) {
- sp_4096_from_mp(b, 128, base);
- sp_4096_from_bin(e, 128, exp, expLen);
- sp_4096_from_mp(m, 128, mod);
- #ifdef HAVE_FFDHE_4096
- if (base->used == 1 && base->dp[0] == 2 && m[127] == (sp_digit)-1)
- err = sp_4096_mod_exp_2_128(r, e, expLen * 8, m);
- else
- #endif
- err = sp_4096_mod_exp_128(r, b, e, expLen * 8, m, 0);
- }
- if (err == MP_OKAY) {
- sp_4096_to_bin(r, out);
- *outLen = 512;
- for (i=0; i<512 && out[i] == 0; i++) {
- }
- *outLen -= i;
- XMEMMOVE(out, out + i, *outLen);
- }
- XMEMSET(e, 0, sizeof(e));
- return err;
- }
- #endif /* WOLFSSL_HAVE_SP_DH */
- #endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */
- #endif /* WOLFSSL_SP_4096 */
- #endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
- #ifdef WOLFSSL_HAVE_SP_ECC
- #ifndef WOLFSSL_SP_NO_256
- /* Point structure to use. */
- typedef struct sp_point {
- sp_digit x[2 * 8];
- sp_digit y[2 * 8];
- sp_digit z[2 * 8];
- int infinity;
- } sp_point;
- /* The modulus (prime) of the curve P256. */
- static const sp_digit p256_mod[8] = {
- 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000,
- 0x00000001,0xffffffff
- };
- /* The Montogmery normalizer for modulus of the curve P256. */
- static const sp_digit p256_norm_mod[8] = {
- 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff,
- 0xfffffffe,0x00000000
- };
- /* The Montogmery multiplier for modulus of the curve P256. */
- static const sp_digit p256_mp_mod = 0x00000001;
- #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
- defined(HAVE_ECC_VERIFY)
- /* The order of the curve P256. */
- static const sp_digit p256_order[8] = {
- 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
- 0x00000000,0xffffffff
- };
- #endif
- /* The order of the curve P256 minus 2. */
- static const sp_digit p256_order2[8] = {
- 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
- 0x00000000,0xffffffff
- };
- #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
- /* The Montogmery normalizer for order of the curve P256. */
- static const sp_digit p256_norm_order[8] = {
- 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000,
- 0xffffffff,0x00000000
- };
- #endif
- #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
- /* The Montogmery multiplier for order of the curve P256. */
- static const sp_digit p256_mp_order = 0xee00bc4f;
- #endif
- /* The base point of curve P256. */
- static const sp_point p256_base = {
- /* X ordinate */
- {
- 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5,
- 0xe12c4247,0x6b17d1f2, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
- },
- /* Y ordinate */
- {
- 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a,
- 0xfe1a7f9b,0x4fe342e2, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
- },
- /* Z ordinate */
- {
- 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
- },
- /* infinity */
- 0
- };
- #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
- static const sp_digit p256_b[8] = {
- 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55,
- 0xaa3a93e7,0x5ac635d8
- };
- #endif
- static int sp_ecc_point_new_ex(void* heap, sp_point* sp, sp_point** p)
- {
- int ret = MP_OKAY;
- if (p == NULL) {
- ret = MEMORY_E;
- }
- else {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- *p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC);
- (void)sp;
- #else
- *p = sp;
- (void)heap;
- #endif
- }
- return ret;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- /* Allocate memory for point and return error. */
- #define sp_ecc_point_new(heap, sp, p) sp_ecc_point_new_ex((heap), NULL, &(p))
- #else
- /* Set pointer to data and return no error. */
- #define sp_ecc_point_new(heap, sp, p) sp_ecc_point_new_ex((heap), &(sp), &(p))
- #endif
- static void sp_ecc_point_free(sp_point* p, int clear, void* heap)
- {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- /* If valid pointer then clear point data if requested and free data. */
- if (p != NULL) {
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- XFREE(p, heap, DYNAMIC_TYPE_ECC);
- }
- #else
- /* Clear point data if requested. */
- if (clear != 0) {
- XMEMSET(p, 0, sizeof(*p));
- }
- #endif
- (void)heap;
- }
- /* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r The resulting Montgomery form number.
- * a The number to convert.
- * m The modulus (prime).
- */
- static int sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- int64_t t[8];
- int64_t a64[8];
- int64_t o;
- (void)m;
- a64[0] = a[0];
- a64[1] = a[1];
- a64[2] = a[2];
- a64[3] = a[3];
- a64[4] = a[4];
- a64[5] = a[5];
- a64[6] = a[6];
- a64[7] = a[7];
- /* 1 1 0 -1 -1 -1 -1 0 */
- t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6];
- /* 0 1 1 0 -1 -1 -1 -1 */
- t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7];
- /* 0 0 1 1 0 -1 -1 -1 */
- t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7];
- /* -1 -1 0 2 2 1 0 -1 */
- t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7];
- /* 0 -1 -1 0 2 2 1 0 */
- t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6];
- /* 0 0 -1 -1 0 2 2 1 */
- t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7];
- /* -1 -1 0 0 0 1 3 2 */
- t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7];
- /* 1 0 -1 -1 -1 -1 0 3 */
- t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7];
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- o = t[7] >> 32; t[7] &= 0xffffffff;
- t[0] += o;
- t[3] -= o;
- t[6] -= o;
- t[7] += o;
- t[1] += t[0] >> 32; t[0] &= 0xffffffff;
- t[2] += t[1] >> 32; t[1] &= 0xffffffff;
- t[3] += t[2] >> 32; t[2] &= 0xffffffff;
- t[4] += t[3] >> 32; t[3] &= 0xffffffff;
- t[5] += t[4] >> 32; t[4] &= 0xffffffff;
- t[6] += t[5] >> 32; t[5] &= 0xffffffff;
- t[7] += t[6] >> 32; t[6] &= 0xffffffff;
- r[0] = t[0];
- r[1] = t[1];
- r[2] = t[2];
- r[3] = t[3];
- r[4] = t[4];
- r[5] = t[5];
- r[6] = t[6];
- r[7] = t[7];
- return MP_OKAY;
- }
- /* Convert an mp_int to an array of sp_digit.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a A multi-precision integer.
- */
- static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
- {
- #if DIGIT_BIT == 32
- int j;
- XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
- for (j = a->used; j < size; j++) {
- r[j] = 0;
- }
- #elif DIGIT_BIT > 32
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i] << s);
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- while ((s + 32U) <= (word32)DIGIT_BIT) {
- s += 32U;
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- if (s < (word32)DIGIT_BIT) {
- /* lint allow cast of mismatch word32 and mp_digit */
- r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
- }
- else {
- r[++j] = 0L;
- }
- }
- s = (word32)DIGIT_BIT - s;
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #else
- int i, j = 0, s = 0;
- r[0] = 0;
- for (i = 0; i < a->used && j < size; i++) {
- r[j] |= ((sp_digit)a->dp[i]) << s;
- if (s + DIGIT_BIT >= 32) {
- r[j] &= 0xffffffff;
- if (j + 1 >= size) {
- break;
- }
- s = 32 - s;
- if (s == DIGIT_BIT) {
- r[++j] = 0;
- s = 0;
- }
- else {
- r[++j] = a->dp[i] >> s;
- s = DIGIT_BIT - s;
- }
- }
- else {
- s += DIGIT_BIT;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- #endif
- }
- /* Convert a point of type ecc_point to type sp_point.
- *
- * p Point of type sp_point (result).
- * pm Point of type ecc_point.
- */
- static void sp_256_point_from_ecc_point_8(sp_point* p, const ecc_point* pm)
- {
- XMEMSET(p->x, 0, sizeof(p->x));
- XMEMSET(p->y, 0, sizeof(p->y));
- XMEMSET(p->z, 0, sizeof(p->z));
- sp_256_from_mp(p->x, 8, pm->x);
- sp_256_from_mp(p->y, 8, pm->y);
- sp_256_from_mp(p->z, 8, pm->z);
- p->infinity = 0;
- }
- /* Convert an array of sp_digit to an mp_int.
- *
- * a A single precision integer.
- * r A multi-precision integer.
- */
- static int sp_256_to_mp(const sp_digit* a, mp_int* r)
- {
- int err;
- err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
- if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
- #if DIGIT_BIT == 32
- XMEMCPY(r->dp, a, sizeof(sp_digit) * 8);
- r->used = 8;
- mp_clamp(r);
- #elif DIGIT_BIT < 32
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 8; i++) {
- r->dp[j] |= a[i] << s;
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- while (s + DIGIT_BIT <= 32) {
- s += DIGIT_BIT;
- r->dp[j++] &= (1L << DIGIT_BIT) - 1;
- if (s == SP_WORD_SIZE) {
- r->dp[j] = 0;
- }
- else {
- r->dp[j] = a[i] >> s;
- }
- }
- s = 32 - s;
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #else
- int i, j = 0, s = 0;
- r->dp[0] = 0;
- for (i = 0; i < 8; i++) {
- r->dp[j] |= ((mp_digit)a[i]) << s;
- if (s + 32 >= DIGIT_BIT) {
- #if DIGIT_BIT != 32 && DIGIT_BIT != 64
- r->dp[j] &= (1L << DIGIT_BIT) - 1;
- #endif
- s = DIGIT_BIT - s;
- r->dp[++j] = a[i] >> s;
- s = 32 - s;
- }
- else {
- s += 32;
- }
- }
- r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
- mp_clamp(r);
- #endif
- }
- return err;
- }
- /* Convert a point of type sp_point to type ecc_point.
- *
- * p Point of type sp_point.
- * pm Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
- static int sp_256_point_to_ecc_point_8(const sp_point* p, ecc_point* pm)
- {
- int err;
- err = sp_256_to_mp(p->x, pm->x);
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->y, pm->y);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->z, pm->z);
- }
- return err;
- }
- /* Compare a with b in constant time.
- *
- * a A single precision integer.
- * b A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
- SP_NOINLINE static int32_t sp_256_cmp_8(const sp_digit* a, const sp_digit* b)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mvn r3, r3\n\t"
- "mov r6, #28\n\t"
- "1:\n\t"
- "ldr r7, [%[a], r6]\n\t"
- "ldr r5, [%[b], r6]\n\t"
- "and r7, r3\n\t"
- "and r5, r3\n\t"
- "mov r4, r7\n\t"
- "sub r7, r5\n\t"
- "sbc r7, r7\n\t"
- "add %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r5, r4\n\t"
- "sbc r7, r7\n\t"
- "sub %[r], r7\n\t"
- "mvn r7, r7\n\t"
- "and r3, r7\n\t"
- "sub r6, #4\n\t"
- "cmp r6, #0\n\t"
- "bge 1b\n\t"
- : [r] "+r" (r)
- : [a] "r" (a), [b] "r" (b)
- : "r3", "r4", "r5", "r6", "r7"
- );
- return r;
- }
- /* Normalize the values in each word to 32.
- *
- * a Array of sp_digit to normalize.
- */
- #define sp_256_norm_8(a)
- /* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r A single precision number representing condition subtract result.
- * a A single precision number to subtract from.
- * b A single precision number to subtract.
- * m Mask value to apply.
- */
- SP_NOINLINE static sp_digit sp_256_cond_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b, sp_digit m)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r5, #32\n\t"
- "mov r8, r5\n\t"
- "mov r7, #0\n\t"
- "1:\n\t"
- "ldr r6, [%[b], r7]\n\t"
- "and r6, %[m]\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r5, [%[a], r7]\n\t"
- "sbc r5, r6\n\t"
- "sbc %[c], %[c]\n\t"
- "str r5, [%[r], r7]\n\t"
- "add r7, #4\n\t"
- "cmp r7, r8\n\t"
- "blt 1b\n\t"
- : [c] "+r" (c)
- : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
- : "memory", "r5", "r6", "r7", "r8"
- );
- return c;
- }
- /* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
- SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- (void)mp;
- (void)m;
- __asm__ __volatile__ (
- "mov r2, #0\n\t"
- "mov r1, #0\n\t"
- "# i = 0\n\t"
- "mov r8, r2\n\t"
- "\n1:\n\t"
- "mov r4, #0\n\t"
- "# mu = a[i] * 1 (mp) = a[i]\n\t"
- "ldr r3, [%[a]]\n\t"
- "# a[i+0] += -1 * mu\n\t"
- "mov r5, r3\n\t"
- "str r4, [%[a], #0]\n\t"
- "# a[i+1] += -1 * mu\n\t"
- "ldr r6, [%[a], #4]\n\t"
- "mov r4, r3\n\t"
- "sub r5, r3\n\t"
- "sbc r4, r2\n\t"
- "add r5, r6\n\t"
- "adc r4, r2\n\t"
- "str r5, [%[a], #4]\n\t"
- "# a[i+2] += -1 * mu\n\t"
- "ldr r6, [%[a], #8]\n\t"
- "mov r5, r3\n\t"
- "sub r4, r3\n\t"
- "sbc r5, r2\n\t"
- "add r4, r6\n\t"
- "adc r5, r2\n\t"
- "str r4, [%[a], #8]\n\t"
- "# a[i+3] += 0 * mu\n\t"
- "ldr r6, [%[a], #12]\n\t"
- "mov r4, #0\n\t"
- "add r5, r6\n\t"
- "adc r4, r2\n\t"
- "str r5, [%[a], #12]\n\t"
- "# a[i+4] += 0 * mu\n\t"
- "ldr r6, [%[a], #16]\n\t"
- "mov r5, #0\n\t"
- "add r4, r6\n\t"
- "adc r5, r2\n\t"
- "str r4, [%[a], #16]\n\t"
- "# a[i+5] += 0 * mu\n\t"
- "ldr r6, [%[a], #20]\n\t"
- "mov r4, #0\n\t"
- "add r5, r6\n\t"
- "adc r4, r2\n\t"
- "str r5, [%[a], #20]\n\t"
- "# a[i+6] += 1 * mu\n\t"
- "ldr r6, [%[a], #24]\n\t"
- "mov r5, #0\n\t"
- "add r4, r3\n\t"
- "adc r5, r2\n\t"
- "add r4, r6\n\t"
- "adc r5, r2\n\t"
- "str r4, [%[a], #24]\n\t"
- "# a[i+7] += -1 * mu\n\t"
- "ldr r6, [%[a], #28]\n\t"
- "ldr r7, [%[a], #32]\n\t"
- "add r4, r1, r3\n\t"
- "mov r1, #0\n\t"
- "adc r1, r2\n\t"
- "sub r5, r3\n\t"
- "sbc r4, r2\n\t"
- "sbc r1, r2\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc r1, r2\n\t"
- "str r5, [%[a], #28]\n\t"
- "str r4, [%[a], #32]\n\t"
- "# i += 1\n\t"
- "mov r6, #4\n\t"
- "add r8, r6\n\t"
- "add %[a], #4\n\t"
- "mov r6, #32\n\t"
- "cmp r8, r6\n\t"
- "blt 1b\n\t"
- "sub %[a], #32\n\t"
- "mov r3, r1\n\t"
- "sub r1, #1\n\t"
- "mvn r1, r1\n\t"
- "ldr r5, [%[a],#32]\n\t"
- "ldr r4, [%[a],#36]\n\t"
- "ldr r6, [%[a],#40]\n\t"
- "ldr r7, [%[a],#44]\n\t"
- "sub r5, r1\n\t"
- "sbc r4, r1\n\t"
- "sbc r6, r1\n\t"
- "sbc r7, r2\n\t"
- "str r5, [%[a],#0]\n\t"
- "str r4, [%[a],#4]\n\t"
- "str r6, [%[a],#8]\n\t"
- "str r7, [%[a],#12]\n\t"
- "ldr r5, [%[a],#48]\n\t"
- "ldr r4, [%[a],#52]\n\t"
- "ldr r6, [%[a],#56]\n\t"
- "ldr r7, [%[a],#60]\n\t"
- "sbc r5, r2\n\t"
- "sbc r4, r2\n\t"
- "sbc r6, r3\n\t"
- "sbc r7, r1\n\t"
- "str r5, [%[a],#16]\n\t"
- "str r4, [%[a],#20]\n\t"
- "str r6, [%[a],#24]\n\t"
- "str r7, [%[a],#28]\n\t"
- : [a] "+r" (a)
- :
- : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"
- );
- (void)m;
- (void)mp;
- }
- /* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a A single precision number to reduce in place.
- * m The single precision number representing the modulus.
- * mp The digit representing the negative inverse of m mod 2^n.
- */
- SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_digit ca = 0;
- __asm__ __volatile__ (
- "mov r8, %[mp]\n\t"
- "mov r12, %[ca]\n\t"
- "mov r14, %[m]\n\t"
- "mov r9, %[a]\n\t"
- "mov r4, #0\n\t"
- "# i = 0\n\t"
- "mov r11, r4\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "mov %[ca], #0\n\t"
- "# mu = a[i] * mp\n\t"
- "mov %[mp], r8\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mul %[mp], %[a]\n\t"
- "mov %[m], r14\n\t"
- "mov r10, r9\n\t"
- "\n2:\n\t"
- "# a[i+j] += m[j] * mu\n\t"
- "mov %[a], r10\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "# Multiply m[j] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add %[a], r7\n\t"
- "adc r5, %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add %[a], r6\n\t"
- "adc r5, r7\n\t"
- "# Multiply m[j] and mu - Done\n\t"
- "add r4, %[a]\n\t"
- "adc r5, %[ca]\n\t"
- "mov %[a], r10\n\t"
- "str r4, [%[a]]\n\t"
- "mov r6, #4\n\t"
- "add %[m], #4\n\t"
- "add r10, r6\n\t"
- "mov r4, #28\n\t"
- "add r4, r9\n\t"
- "cmp r10, r4\n\t"
- "blt 2b\n\t"
- "# a[i+7] += m[7] * mu\n\t"
- "mov %[ca], #0\n\t"
- "mov r4, r12\n\t"
- "mov %[a], #0\n\t"
- "# Multiply m[7] and mu - Start\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r6, %[mp], #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r5, r7\n\t"
- "adc r4, %[ca]\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsr r6, %[mp], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "ldr r7, [%[m]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r5, r6\n\t"
- "adc r4, r7\n\t"
- "adc %[a], %[ca]\n\t"
- "# Multiply m[7] and mu - Done\n\t"
- "mov %[ca], %[a]\n\t"
- "mov %[a], r10\n\t"
- "ldr r7, [%[a], #4]\n\t"
- "ldr %[a], [%[a]]\n\t"
- "mov r6, #0\n\t"
- "add r5, %[a]\n\t"
- "adc r7, r4\n\t"
- "adc %[ca], r6\n\t"
- "mov %[a], r10\n\t"
- "str r5, [%[a]]\n\t"
- "str r7, [%[a], #4]\n\t"
- "# i += 1\n\t"
- "mov r6, #4\n\t"
- "add r9, r6\n\t"
- "add r11, r6\n\t"
- "mov r12, %[ca]\n\t"
- "mov %[a], r9\n\t"
- "mov r4, #32\n\t"
- "cmp r11, r4\n\t"
- "blt 1b\n\t"
- "mov %[m], r14\n\t"
- : [ca] "+r" (ca), [a] "+r" (a)
- : [m] "r" (m), [mp] "r" (mp)
- : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
- );
- sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca);
- }
- /* Multiply a and b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit tmp[8 * 2];
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r9, %[a]\n\t"
- "mov r10, %[b]\n\t"
- "mov r6, #32\n\t"
- "add r6, r9\n\t"
- "mov r12, r6\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "mov r6, #28\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov %[b], r8\n\t"
- "sub %[b], %[a]\n\t"
- "add %[a], r9\n\t"
- "add %[b], r10\n\t"
- "\n2:\n\t"
- "# Multiply Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [%[b]]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply Done\n\t"
- "add %[a], #4\n\t"
- "sub %[b], #4\n\t"
- "cmp %[a], r12\n\t"
- "beq 3f\n\t"
- "mov r6, r8\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r11\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #56\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[a], r9\n\t"
- "mov %[b], r10\n\t"
- :
- : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
- );
- XMEMCPY(r, tmp, sizeof(tmp));
- }
- /* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r Result of multiplication.
- * a First number to multiply in Montogmery form.
- * b Second number to multiply in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_256_mont_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m, sp_digit mp)
- {
- sp_256_mul_8(r, a, b);
- sp_256_mont_reduce_8(r, m, mp);
- }
- /* Square a and put result in r. (r = a * a)
- *
- * r A single precision integer.
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "mov r5, #0\n\t"
- "mov r8, r3\n\t"
- "mov r11, %[r]\n\t"
- "mov r6, #64\n\t"
- "neg r6, r6\n\t"
- "add sp, r6\n\t"
- "mov r10, sp\n\t"
- "mov r9, %[a]\n\t"
- "\n1:\n\t"
- "mov %[r], #0\n\t"
- "mov r6, #28\n\t"
- "mov %[a], r8\n\t"
- "sub %[a], r6\n\t"
- "sbc r6, r6\n\t"
- "mvn r6, r6\n\t"
- "and %[a], r6\n\t"
- "mov r2, r8\n\t"
- "sub r2, %[a]\n\t"
- "add %[a], r9\n\t"
- "add r2, r9\n\t"
- "\n2:\n\t"
- "cmp r2, %[a]\n\t"
- "beq 4f\n\t"
- "# Multiply * 2: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "ldr r7, [r2]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r7, [r2]\n\t"
- "lsl r7, r7, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Multiply * 2: Done\n\t"
- "bal 5f\n\t"
- "\n4:\n\t"
- "# Square: Start\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r6\n\t"
- "add r3, r6\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "mul r7, r7\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #15\n\t"
- "lsl r6, r6, #17\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# Square: Done\n\t"
- "\n5:\n\t"
- "add %[a], #4\n\t"
- "sub r2, #4\n\t"
- "mov r6, #32\n\t"
- "add r6, r9\n\t"
- "cmp %[a], r6\n\t"
- "beq 3f\n\t"
- "cmp %[a], r2\n\t"
- "bgt 3f\n\t"
- "mov r7, r8\n\t"
- "add r7, r9\n\t"
- "cmp %[a], r7\n\t"
- "ble 2b\n\t"
- "\n3:\n\t"
- "mov %[r], r10\n\t"
- "mov r7, r8\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "mov r5, #0\n\t"
- "add r7, #4\n\t"
- "mov r8, r7\n\t"
- "mov r6, #56\n\t"
- "cmp r7, r6\n\t"
- "ble 1b\n\t"
- "mov %[a], r9\n\t"
- "str r3, [%[r], r7]\n\t"
- "mov %[r], r11\n\t"
- "mov %[a], r10\n\t"
- "mov r3, #60\n\t"
- "\n4:\n\t"
- "ldr r6, [%[a], r3]\n\t"
- "str r6, [%[r], r3]\n\t"
- "sub r3, #4\n\t"
- "bge 4b\n\t"
- "mov r6, #64\n\t"
- "add sp, r6\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- /* Square the Montgomery form number. (r = a * a mod m)
- *
- * r Result of squaring.
- * a Number to square in Montogmery form.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a, const sp_digit* m,
- sp_digit mp)
- {
- sp_256_sqr_8(r, a);
- sp_256_mont_reduce_8(r, m, mp);
- }
- #if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
- /* Square the Montgomery form number a number of times. (r = a ^ n mod m)
- *
- * r Result of squaring.
- * a Number to square in Montogmery form.
- * n Number of times to square.
- * m Modulus (prime).
- * mp Montogmery mulitplier.
- */
- static void sp_256_mont_sqr_n_8(sp_digit* r, const sp_digit* a, int n,
- const sp_digit* m, sp_digit mp)
- {
- sp_256_mont_sqr_8(r, a, m, mp);
- for (; n > 1; n--) {
- sp_256_mont_sqr_8(r, r, m, mp);
- }
- }
- #endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
- #ifdef WOLFSSL_SP_SMALL
- /* Mod-2 for the P256 curve. */
- static const uint32_t p256_mod_2[8] = {
- 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U,
- 0x00000001U,0xffffffffU
- };
- #endif /* !WOLFSSL_SP_SMALL */
- /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
- * P256 curve. (r = 1 / a mod m)
- *
- * r Inverse result.
- * a Number to invert.
- * td Temporary data.
- */
- static void sp_256_mont_inv_8(sp_digit* r, const sp_digit* a, sp_digit* td)
- {
- #ifdef WOLFSSL_SP_SMALL
- sp_digit* t = td;
- int i;
- XMEMCPY(t, a, sizeof(sp_digit) * 8);
- for (i=254; i>=0; i--) {
- sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod);
- if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))
- sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod);
- }
- XMEMCPY(r, t, sizeof(sp_digit) * 8);
- #else
- sp_digit* t = td;
- sp_digit* t2 = td + 2 * 8;
- sp_digit* t3 = td + 4 * 8;
- /* t = a^2 */
- sp_256_mont_sqr_8(t, a, p256_mod, p256_mp_mod);
- /* t = a^3 = t * a */
- sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod);
- /* t2= a^c = t ^ 2 ^ 2 */
- sp_256_mont_sqr_n_8(t2, t, 2, p256_mod, p256_mp_mod);
- /* t3= a^d = t2 * a */
- sp_256_mont_mul_8(t3, t2, a, p256_mod, p256_mp_mod);
- /* t = a^f = t2 * t */
- sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
- /* t2= a^f0 = t ^ 2 ^ 4 */
- sp_256_mont_sqr_n_8(t2, t, 4, p256_mod, p256_mp_mod);
- /* t3= a^fd = t2 * t3 */
- sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod);
- /* t = a^ff = t2 * t */
- sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
- /* t2= a^ff00 = t ^ 2 ^ 8 */
- sp_256_mont_sqr_n_8(t2, t, 8, p256_mod, p256_mp_mod);
- /* t3= a^fffd = t2 * t3 */
- sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod);
- /* t = a^ffff = t2 * t */
- sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
- /* t2= a^ffff0000 = t ^ 2 ^ 16 */
- sp_256_mont_sqr_n_8(t2, t, 16, p256_mod, p256_mp_mod);
- /* t3= a^fffffffd = t2 * t3 */
- sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod);
- /* t = a^ffffffff = t2 * t */
- sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
- /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */
- sp_256_mont_sqr_n_8(t2, t, 32, p256_mod, p256_mp_mod);
- /* t2= a^ffffffffffffffff = t2 * t */
- sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
- /* t2= a^ffffffff00000001 = t2 * a */
- sp_256_mont_mul_8(t2, t2, a, p256_mod, p256_mp_mod);
- /* t2= a^ffffffff000000010000000000000000000000000000000000000000
- * = t2 ^ 2 ^ 160 */
- sp_256_mont_sqr_n_8(t2, t2, 160, p256_mod, p256_mp_mod);
- /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff
- * = t2 * t */
- sp_256_mont_mul_8(t2, t2, t, p256_mod, p256_mp_mod);
- /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000
- * = t2 ^ 2 ^ 32 */
- sp_256_mont_sqr_n_8(t2, t2, 32, p256_mod, p256_mp_mod);
- /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd
- * = t2 * t3 */
- sp_256_mont_mul_8(r, t2, t3, p256_mod, p256_mp_mod);
- #endif /* WOLFSSL_SP_SMALL */
- }
- /* Map the Montgomery form projective coordinate point to an affine point.
- *
- * r Resulting affine coordinate point.
- * p Montgomery form projective coordinate point.
- * t Temporary ordinate data.
- */
- static void sp_256_map_8(sp_point* r, const sp_point* p, sp_digit* t)
- {
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2*8;
- int32_t n;
- sp_256_mont_inv_8(t1, p->z, t + 2*8);
- sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
- /* x /= z^2 */
- sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod);
- XMEMSET(r->x + 8, 0, sizeof(r->x) / 2U);
- sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod);
- /* Reduce x to less than modulus */
- n = sp_256_cmp_8(r->x, p256_mod);
- sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - ((n >= 0) ?
- (sp_digit)1 : (sp_digit)0));
- sp_256_norm_8(r->x);
- /* y /= z^3 */
- sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod);
- XMEMSET(r->y + 8, 0, sizeof(r->y) / 2U);
- sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod);
- /* Reduce y to less than modulus */
- n = sp_256_cmp_8(r->y, p256_mod);
- sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - ((n >= 0) ?
- (sp_digit)1 : (sp_digit)0));
- sp_256_norm_8(r->y);
- XMEMSET(r->z, 0, sizeof(r->z));
- r->z[0] = 1;
- }
- #ifdef WOLFSSL_SP_SMALL
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "mov r7, #0\n\t"
- "add r6, #32\n\t"
- "sub r7, #1\n\t"
- "\n1:\n\t"
- "add %[c], r7\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #else
- /* Add b to a into r. (r = a + b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "add r4, r5\n\t"
- "str r4, [%[r], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #4]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #12]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #20]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #28]\n\t"
- "adc r4, r5\n\t"
- "str r4, [%[r], #28]\n\t"
- "mov %[c], #0\n\t"
- "adc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- /* Add two Montgomery form numbers (r = a + b % m).
- *
- * r Result of addition.
- * a First number to add in Montogmery form.
- * b Second number to add in Montogmery form.
- * m Modulus (prime).
- */
- SP_NOINLINE static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m)
- {
- (void)m;
- __asm__ __volatile__ (
- "mov r3, #0\n\t"
- "ldr r4, [%[a],#0]\n\t"
- "ldr r5, [%[a],#4]\n\t"
- "ldr r6, [%[b],#0]\n\t"
- "ldr r7, [%[b],#4]\n\t"
- "add r4, r6\n\t"
- "adc r5, r7\n\t"
- "str r4, [%[r],#0]\n\t"
- "str r5, [%[r],#4]\n\t"
- "ldr r4, [%[a],#8]\n\t"
- "ldr r5, [%[a],#12]\n\t"
- "ldr r6, [%[b],#8]\n\t"
- "ldr r7, [%[b],#12]\n\t"
- "adc r4, r6\n\t"
- "adc r5, r7\n\t"
- "str r4, [%[r],#8]\n\t"
- "str r5, [%[r],#12]\n\t"
- "ldr r4, [%[a],#16]\n\t"
- "ldr r5, [%[a],#20]\n\t"
- "ldr r6, [%[b],#16]\n\t"
- "ldr r7, [%[b],#20]\n\t"
- "adc r4, r6\n\t"
- "adc r5, r7\n\t"
- "mov r8, r4\n\t"
- "mov r9, r5\n\t"
- "ldr r4, [%[a],#24]\n\t"
- "ldr r5, [%[a],#28]\n\t"
- "ldr r6, [%[b],#24]\n\t"
- "ldr r7, [%[b],#28]\n\t"
- "adc r4, r6\n\t"
- "adc r5, r7\n\t"
- "mov r10, r4\n\t"
- "mov r11, r5\n\t"
- "adc r3, r3\n\t"
- "mov r6, r3\n\t"
- "sub r3, #1\n\t"
- "mvn r3, r3\n\t"
- "mov r7, #0\n\t"
- "ldr r4, [%[r],#0]\n\t"
- "ldr r5, [%[r],#4]\n\t"
- "sub r4, r3\n\t"
- "sbc r5, r3\n\t"
- "str r4, [%[r],#0]\n\t"
- "str r5, [%[r],#4]\n\t"
- "ldr r4, [%[r],#8]\n\t"
- "ldr r5, [%[r],#12]\n\t"
- "sbc r4, r3\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r],#8]\n\t"
- "str r5, [%[r],#12]\n\t"
- "mov r4, r8\n\t"
- "mov r5, r9\n\t"
- "sbc r4, r7\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r],#16]\n\t"
- "str r5, [%[r],#20]\n\t"
- "mov r4, r10\n\t"
- "mov r5, r11\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r3\n\t"
- "str r4, [%[r],#24]\n\t"
- "str r5, [%[r],#28]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- /* Double a Montgomery form number (r = a + a % m).
- *
- * r Result of doubling.
- * a Number to double in Montogmery form.
- * m Modulus (prime).
- */
- SP_NOINLINE static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- (void)m;
- __asm__ __volatile__ (
- "ldr r4, [%[a],#0]\n\t"
- "ldr r5, [%[a],#4]\n\t"
- "ldr r6, [%[a],#8]\n\t"
- "ldr r7, [%[a],#12]\n\t"
- "add r4, r4\n\t"
- "adc r5, r5\n\t"
- "adc r6, r6\n\t"
- "adc r7, r7\n\t"
- "str r4, [%[r],#0]\n\t"
- "str r5, [%[r],#4]\n\t"
- "str r6, [%[r],#8]\n\t"
- "str r7, [%[r],#12]\n\t"
- "ldr r4, [%[a],#16]\n\t"
- "ldr r5, [%[a],#20]\n\t"
- "ldr r6, [%[a],#24]\n\t"
- "ldr r7, [%[a],#28]\n\t"
- "adc r4, r4\n\t"
- "adc r5, r5\n\t"
- "adc r6, r6\n\t"
- "adc r7, r7\n\t"
- "mov r8, r4\n\t"
- "mov r9, r5\n\t"
- "mov r10, r6\n\t"
- "mov r11, r7\n\t"
- "mov r3, #0\n\t"
- "mov r7, #0\n\t"
- "adc r3, r3\n\t"
- "mov r2, r3\n\t"
- "sub r3, #1\n\t"
- "mvn r3, r3\n\t"
- "ldr r4, [%[r],#0]\n\t"
- "ldr r5, [%[r],#4]\n\t"
- "ldr r6, [%[r],#8]\n\t"
- "sub r4, r3\n\t"
- "sbc r5, r3\n\t"
- "sbc r6, r3\n\t"
- "str r4, [%[r],#0]\n\t"
- "str r5, [%[r],#4]\n\t"
- "str r6, [%[r],#8]\n\t"
- "ldr r4, [%[r],#12]\n\t"
- "mov r5, r8\n\t"
- "mov r6, r9\n\t"
- "sbc r4, r7\n\t"
- "sbc r5, r7\n\t"
- "sbc r6, r7\n\t"
- "str r4, [%[r],#12]\n\t"
- "str r5, [%[r],#16]\n\t"
- "str r6, [%[r],#20]\n\t"
- "mov r4, r10\n\t"
- "mov r5, r11\n\t"
- "sbc r4, r2\n\t"
- "sbc r5, r3\n\t"
- "str r4, [%[r],#24]\n\t"
- "str r5, [%[r],#28]\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r3", "r2", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- /* Triple a Montgomery form number (r = a + a + a % m).
- *
- * r Result of Tripling.
- * a Number to triple in Montogmery form.
- * m Modulus (prime).
- */
- SP_NOINLINE static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- (void)m;
- __asm__ __volatile__ (
- "ldr r6, [%[a],#0]\n\t"
- "ldr r7, [%[a],#4]\n\t"
- "ldr r4, [%[a],#8]\n\t"
- "ldr r5, [%[a],#12]\n\t"
- "add r6, r6\n\t"
- "adc r7, r7\n\t"
- "adc r4, r4\n\t"
- "adc r5, r5\n\t"
- "mov r8, r4\n\t"
- "mov r9, r5\n\t"
- "ldr r2, [%[a],#16]\n\t"
- "ldr r3, [%[a],#20]\n\t"
- "ldr r4, [%[a],#24]\n\t"
- "ldr r5, [%[a],#28]\n\t"
- "adc r2, r2\n\t"
- "adc r3, r3\n\t"
- "adc r4, r4\n\t"
- "adc r5, r5\n\t"
- "mov r10, r2\n\t"
- "mov r11, r3\n\t"
- "mov r12, r4\n\t"
- "mov r14, r5\n\t"
- "mov r3, #0\n\t"
- "mov r5, #0\n\t"
- "adc r3, r3\n\t"
- "mov r4, r3\n\t"
- "sub r3, #1\n\t"
- "mvn r3, r3\n\t"
- "sub r6, r3\n\t"
- "sbc r7, r3\n\t"
- "mov r2, r8\n\t"
- "sbc r2, r3\n\t"
- "mov r8, r2\n\t"
- "mov r2, r9\n\t"
- "sbc r2, r5\n\t"
- "mov r9, r2\n\t"
- "mov r2, r10\n\t"
- "sbc r2, r5\n\t"
- "mov r10, r2\n\t"
- "mov r2, r11\n\t"
- "sbc r2, r5\n\t"
- "mov r11, r2\n\t"
- "mov r2, r12\n\t"
- "sbc r2, r4\n\t"
- "mov r12, r2\n\t"
- "mov r2, r14\n\t"
- "sbc r2, r3\n\t"
- "mov r14, r2\n\t"
- "ldr r2, [%[a],#0]\n\t"
- "ldr r3, [%[a],#4]\n\t"
- "add r6, r2\n\t"
- "adc r7, r3\n\t"
- "ldr r2, [%[a],#8]\n\t"
- "ldr r3, [%[a],#12]\n\t"
- "mov r4, r8\n\t"
- "mov r5, r9\n\t"
- "adc r2, r4\n\t"
- "adc r3, r5\n\t"
- "mov r8, r2\n\t"
- "mov r9, r3\n\t"
- "ldr r2, [%[a],#16]\n\t"
- "ldr r3, [%[a],#20]\n\t"
- "mov r4, r10\n\t"
- "mov r5, r11\n\t"
- "adc r2, r4\n\t"
- "adc r3, r5\n\t"
- "mov r10, r2\n\t"
- "mov r11, r3\n\t"
- "ldr r2, [%[a],#24]\n\t"
- "ldr r3, [%[a],#28]\n\t"
- "mov r4, r12\n\t"
- "mov r5, r14\n\t"
- "adc r2, r4\n\t"
- "adc r3, r5\n\t"
- "mov r12, r2\n\t"
- "mov r14, r3\n\t"
- "mov r3, #0\n\t"
- "mov r5, #0\n\t"
- "adc r3, r3\n\t"
- "mov r4, r3\n\t"
- "sub r3, #1\n\t"
- "mvn r3, r3\n\t"
- "sub r6, r3\n\t"
- "str r6, [%[r],#0]\n\t"
- "sbc r7, r3\n\t"
- "str r7, [%[r],#4]\n\t"
- "mov r2, r8\n\t"
- "sbc r2, r3\n\t"
- "str r2, [%[r],#8]\n\t"
- "mov r2, r9\n\t"
- "sbc r2, r5\n\t"
- "str r2, [%[r],#12]\n\t"
- "mov r2, r10\n\t"
- "sbc r2, r5\n\t"
- "str r2, [%[r],#16]\n\t"
- "mov r2, r11\n\t"
- "sbc r2, r5\n\t"
- "str r2, [%[r],#20]\n\t"
- "mov r2, r12\n\t"
- "sbc r2, r4\n\t"
- "str r2, [%[r],#24]\n\t"
- "mov r2, r14\n\t"
- "sbc r2, r3\n\t"
- "str r2, [%[r],#28]\n\t"
- :
- : [r] "r" (r), [a] "r" (a)
- : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
- );
- }
- /* Subtract two Montgomery form numbers (r = a - b % m).
- *
- * r Result of subtration.
- * a Number to subtract from in Montogmery form.
- * b Number to subtract with in Montogmery form.
- * m Modulus (prime).
- */
- SP_NOINLINE static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b,
- const sp_digit* m)
- {
- (void)m;
- __asm__ __volatile__ (
- "ldr r4, [%[a],#0]\n\t"
- "ldr r5, [%[a],#4]\n\t"
- "ldr r6, [%[b],#0]\n\t"
- "ldr r7, [%[b],#4]\n\t"
- "sub r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r],#0]\n\t"
- "str r5, [%[r],#4]\n\t"
- "ldr r4, [%[a],#8]\n\t"
- "ldr r5, [%[a],#12]\n\t"
- "ldr r6, [%[b],#8]\n\t"
- "ldr r7, [%[b],#12]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r],#8]\n\t"
- "str r5, [%[r],#12]\n\t"
- "ldr r4, [%[a],#16]\n\t"
- "ldr r5, [%[a],#20]\n\t"
- "ldr r6, [%[b],#16]\n\t"
- "ldr r7, [%[b],#20]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "mov r8, r4\n\t"
- "mov r9, r5\n\t"
- "ldr r4, [%[a],#24]\n\t"
- "ldr r5, [%[a],#28]\n\t"
- "ldr r6, [%[b],#24]\n\t"
- "ldr r7, [%[b],#28]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "mov r10, r4\n\t"
- "mov r11, r5\n\t"
- "sbc r3, r3\n\t"
- "lsr r7, r3, #31\n\t"
- "mov r6, #0\n\t"
- "ldr r4, [%[r],#0]\n\t"
- "ldr r5, [%[r],#4]\n\t"
- "add r4, r3\n\t"
- "adc r5, r3\n\t"
- "str r4, [%[r],#0]\n\t"
- "str r5, [%[r],#4]\n\t"
- "ldr r4, [%[r],#8]\n\t"
- "ldr r5, [%[r],#12]\n\t"
- "adc r4, r3\n\t"
- "adc r5, r6\n\t"
- "str r4, [%[r],#8]\n\t"
- "str r5, [%[r],#12]\n\t"
- "mov r4, r8\n\t"
- "mov r5, r9\n\t"
- "adc r4, r6\n\t"
- "adc r5, r6\n\t"
- "str r4, [%[r],#16]\n\t"
- "str r5, [%[r],#20]\n\t"
- "mov r4, r10\n\t"
- "mov r5, r11\n\t"
- "adc r4, r7\n\t"
- "adc r5, r3\n\t"
- "str r4, [%[r],#24]\n\t"
- "str r5, [%[r],#28]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
- );
- }
- /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
- *
- * r Result of division by 2.
- * a Number to divide.
- * m Modulus (prime).
- */
- SP_NOINLINE static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- __asm__ __volatile__ (
- "ldr r7, [%[a], #0]\n\t"
- "lsl r7, r7, #31\n\t"
- "lsr r7, r7, #31\n\t"
- "mov r5, #0\n\t"
- "sub r5, r7\n\t"
- "mov r7, #0\n\t"
- "lsl r6, r5, #31\n\t"
- "lsr r6, r6, #31\n\t"
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "add r3, r5\n\t"
- "adc r4, r5\n\t"
- "str r3, [%[r], #0]\n\t"
- "str r4, [%[r], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "adc r3, r5\n\t"
- "adc r4, r7\n\t"
- "str r3, [%[r], #8]\n\t"
- "str r4, [%[r], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "adc r3, r7\n\t"
- "adc r4, r7\n\t"
- "str r3, [%[r], #16]\n\t"
- "str r4, [%[r], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "adc r3, r6\n\t"
- "adc r4, r5\n\t"
- "adc r7, r7\n\t"
- "lsl r7, r7, #31\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, #31\n\t"
- "lsr r6, r4, #1\n\t"
- "lsl r4, r4, #31\n\t"
- "orr r5, r4\n\t"
- "orr r6, r7\n\t"
- "mov r7, r3\n\t"
- "str r5, [%[r], #24]\n\t"
- "str r6, [%[r], #28]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, #31\n\t"
- "lsr r6, r4, #1\n\t"
- "lsl r4, r4, #31\n\t"
- "orr r5, r4\n\t"
- "orr r6, r7\n\t"
- "mov r7, r3\n\t"
- "str r5, [%[r], #16]\n\t"
- "str r6, [%[r], #20]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsl r3, r3, #31\n\t"
- "lsr r6, r4, #1\n\t"
- "lsl r4, r4, #31\n\t"
- "orr r5, r4\n\t"
- "orr r6, r7\n\t"
- "mov r7, r3\n\t"
- "str r5, [%[r], #8]\n\t"
- "str r6, [%[r], #12]\n\t"
- "ldr r3, [%[r], #0]\n\t"
- "ldr r4, [%[r], #4]\n\t"
- "lsr r5, r3, #1\n\t"
- "lsr r6, r4, #1\n\t"
- "lsl r4, r4, #31\n\t"
- "orr r5, r4\n\t"
- "orr r6, r7\n\t"
- "str r5, [%[r], #0]\n\t"
- "str r6, [%[r], #4]\n\t"
- :
- : [r] "r" (r), [a] "r" (a), [m] "r" (m)
- : "memory", "r3", "r4", "r5", "r6", "r7"
- );
- }
- /* Double the Montgomery form projective point p.
- *
- * r Result of doubling point.
- * p Point to double.
- * t Temporary ordinate data.
- */
- static void sp_256_proj_point_dbl_8(sp_point* r, const sp_point* p, sp_digit* t)
- {
- sp_point* rp[2];
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2*8;
- sp_digit* x;
- sp_digit* y;
- sp_digit* z;
- int i;
- /* When infinity don't double point passed in - constant time. */
- rp[0] = r;
- /*lint allow cast to different type of pointer*/
- rp[1] = (sp_point*)t; /*lint !e9087 !e740*/
- XMEMSET(rp[1], 0, sizeof(sp_point));
- x = rp[p->infinity]->x;
- y = rp[p->infinity]->y;
- z = rp[p->infinity]->z;
- /* Put point to double into result - good for infinity. */
- if (r != p) {
- for (i=0; i<8; i++) {
- r->x[i] = p->x[i];
- }
- for (i=0; i<8; i++) {
- r->y[i] = p->y[i];
- }
- for (i=0; i<8; i++) {
- r->z[i] = p->z[i];
- }
- r->infinity = p->infinity;
- }
- /* T1 = Z * Z */
- sp_256_mont_sqr_8(t1, z, p256_mod, p256_mp_mod);
- /* Z = Y * Z */
- sp_256_mont_mul_8(z, y, z, p256_mod, p256_mp_mod);
- /* Z = 2Z */
- sp_256_mont_dbl_8(z, z, p256_mod);
- /* T2 = X - T1 */
- sp_256_mont_sub_8(t2, x, t1, p256_mod);
- /* T1 = X + T1 */
- sp_256_mont_add_8(t1, x, t1, p256_mod);
- /* T2 = T1 * T2 */
- sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod);
- /* T1 = 3T2 */
- sp_256_mont_tpl_8(t1, t2, p256_mod);
- /* Y = 2Y */
- sp_256_mont_dbl_8(y, y, p256_mod);
- /* Y = Y * Y */
- sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod);
- /* T2 = Y * Y */
- sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
- /* T2 = T2/2 */
- sp_256_div2_8(t2, t2, p256_mod);
- /* Y = Y * X */
- sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod);
- /* X = T1 * T1 */
- sp_256_mont_mul_8(x, t1, t1, p256_mod, p256_mp_mod);
- /* X = X - Y */
- sp_256_mont_sub_8(x, x, y, p256_mod);
- /* X = X - Y */
- sp_256_mont_sub_8(x, x, y, p256_mod);
- /* Y = Y - X */
- sp_256_mont_sub_8(y, y, x, p256_mod);
- /* Y = Y * T1 */
- sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod);
- /* Y = Y - T2 */
- sp_256_mont_sub_8(y, y, t2, p256_mod);
- }
- #ifdef WOLFSSL_SP_SMALL
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r6, %[a]\n\t"
- "add r6, #32\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r4, [%[a]]\n\t"
- "ldr r5, [%[b]]\n\t"
- "sbc r4, r5\n\t"
- "str r4, [%[r]]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #4\n\t"
- "add %[b], #4\n\t"
- "add %[r], #4\n\t"
- "cmp %[a], r6\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6"
- );
- return c;
- }
- #else
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r4, [%[a], #0]\n\t"
- "ldr r5, [%[a], #4]\n\t"
- "ldr r6, [%[b], #0]\n\t"
- "ldr r7, [%[b], #4]\n\t"
- "sub r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #0]\n\t"
- "str r5, [%[r], #4]\n\t"
- "ldr r4, [%[a], #8]\n\t"
- "ldr r5, [%[a], #12]\n\t"
- "ldr r6, [%[b], #8]\n\t"
- "ldr r7, [%[b], #12]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #8]\n\t"
- "str r5, [%[r], #12]\n\t"
- "ldr r4, [%[a], #16]\n\t"
- "ldr r5, [%[a], #20]\n\t"
- "ldr r6, [%[b], #16]\n\t"
- "ldr r7, [%[b], #20]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #16]\n\t"
- "str r5, [%[r], #20]\n\t"
- "ldr r4, [%[a], #24]\n\t"
- "ldr r5, [%[a], #28]\n\t"
- "ldr r6, [%[b], #24]\n\t"
- "ldr r7, [%[b], #28]\n\t"
- "sbc r4, r6\n\t"
- "sbc r5, r7\n\t"
- "str r4, [%[r], #24]\n\t"
- "str r5, [%[r], #28]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- /* Compare two numbers to determine if they are equal.
- * Constant time implementation.
- *
- * a First number to compare.
- * b Second number to compare.
- * returns 1 when equal and 0 otherwise.
- */
- static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b)
- {
- return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) |
- (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7])) == 0;
- }
- /* Add two Montgomery form projective points.
- *
- * r Result of addition.
- * p First point to add.
- * q Second point to add.
- * t Temporary ordinate data.
- */
- static void sp_256_proj_point_add_8(sp_point* r, const sp_point* p, const sp_point* q,
- sp_digit* t)
- {
- const sp_point* ap[2];
- sp_point* rp[2];
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2*8;
- sp_digit* t3 = t + 4*8;
- sp_digit* t4 = t + 6*8;
- sp_digit* t5 = t + 8*8;
- sp_digit* x;
- sp_digit* y;
- sp_digit* z;
- int i;
- /* Ensure only the first point is the same as the result. */
- if (q == r) {
- const sp_point* a = p;
- p = q;
- q = a;
- }
- /* Check double */
- (void)sp_256_sub_8(t1, p256_mod, q->y);
- sp_256_norm_8(t1);
- if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) &
- (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) {
- sp_256_proj_point_dbl_8(r, p, t);
- }
- else {
- rp[0] = r;
- /*lint allow cast to different type of pointer*/
- rp[1] = (sp_point*)t; /*lint !e9087 !e740*/
- XMEMSET(rp[1], 0, sizeof(sp_point));
- x = rp[p->infinity | q->infinity]->x;
- y = rp[p->infinity | q->infinity]->y;
- z = rp[p->infinity | q->infinity]->z;
- ap[0] = p;
- ap[1] = q;
- for (i=0; i<8; i++) {
- r->x[i] = ap[p->infinity]->x[i];
- }
- for (i=0; i<8; i++) {
- r->y[i] = ap[p->infinity]->y[i];
- }
- for (i=0; i<8; i++) {
- r->z[i] = ap[p->infinity]->z[i];
- }
- r->infinity = ap[p->infinity]->infinity;
- /* U1 = X1*Z2^2 */
- sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod);
- /* U2 = X2*Z1^2 */
- sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod);
- /* S1 = Y1*Z2^3 */
- sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod);
- /* S2 = Y2*Z1^3 */
- sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod);
- /* H = U2 - U1 */
- sp_256_mont_sub_8(t2, t2, t1, p256_mod);
- /* R = S2 - S1 */
- sp_256_mont_sub_8(t4, t4, t3, p256_mod);
- /* Z3 = H*Z1*Z2 */
- sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod);
- /* X3 = R^2 - H^3 - 2*U1*H^2 */
- sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod);
- sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod);
- sp_256_mont_sub_8(x, x, t5, p256_mod);
- sp_256_mont_dbl_8(t1, y, p256_mod);
- sp_256_mont_sub_8(x, x, t1, p256_mod);
- /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
- sp_256_mont_sub_8(y, y, x, p256_mod);
- sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod);
- sp_256_mont_sub_8(y, y, t5, p256_mod);
- }
- }
- /* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * r Resulting point.
- * g Point to multiply.
- * k Scalar to multiply by.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- static int sp_256_ecc_mulmod_fast_8(sp_point* r, const sp_point* g, const sp_digit* k,
- int map, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point td[16];
- sp_point rtd;
- sp_digit tmpd[2 * 8 * 5];
- #endif
- sp_point* t;
- sp_point* rt;
- sp_digit* tmp;
- sp_digit n;
- int i;
- int c, y;
- int err;
- (void)heap;
- err = sp_ecc_point_new(heap, rtd, rt);
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC);
- if (t == NULL)
- err = MEMORY_E;
- tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap,
- DYNAMIC_TYPE_ECC);
- if (tmp == NULL)
- err = MEMORY_E;
- #else
- t = td;
- tmp = tmpd;
- #endif
- if (err == MP_OKAY) {
- /* t[0] = {0, 0, 1} * norm */
- XMEMSET(&t[0], 0, sizeof(t[0]));
- t[0].infinity = 1;
- /* t[1] = {g->x, g->y, g->z} * norm */
- (void)sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod);
- (void)sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod);
- (void)sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod);
- t[1].infinity = 0;
- sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp);
- t[ 2].infinity = 0;
- sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp);
- t[ 3].infinity = 0;
- sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp);
- t[ 4].infinity = 0;
- sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp);
- t[ 5].infinity = 0;
- sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp);
- t[ 6].infinity = 0;
- sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp);
- t[ 7].infinity = 0;
- sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp);
- t[ 8].infinity = 0;
- sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp);
- t[ 9].infinity = 0;
- sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp);
- t[10].infinity = 0;
- sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp);
- t[11].infinity = 0;
- sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp);
- t[12].infinity = 0;
- sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp);
- t[13].infinity = 0;
- sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp);
- t[14].infinity = 0;
- sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp);
- t[15].infinity = 0;
- i = 6;
- n = k[i+1] << 0;
- c = 28;
- y = n >> 28;
- XMEMCPY(rt, &t[y], sizeof(sp_point));
- n <<= 4;
- for (; i>=0 || c>=4; ) {
- if (c < 4) {
- n |= k[i--] << (0 - c);
- c += 32;
- }
- y = (n >> 28) & 0xf;
- n <<= 4;
- c -= 4;
- sp_256_proj_point_dbl_8(rt, rt, tmp);
- sp_256_proj_point_dbl_8(rt, rt, tmp);
- sp_256_proj_point_dbl_8(rt, rt, tmp);
- sp_256_proj_point_dbl_8(rt, rt, tmp);
- sp_256_proj_point_add_8(rt, rt, &t[y], tmp);
- }
- if (map != 0) {
- sp_256_map_8(r, rt, tmp);
- }
- else {
- XMEMCPY(r, rt, sizeof(sp_point));
- }
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (tmp != NULL) {
- XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5);
- XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
- }
- if (t != NULL) {
- XMEMSET(t, 0, sizeof(sp_point) * 16);
- XFREE(t, heap, DYNAMIC_TYPE_ECC);
- }
- #else
- ForceZero(tmpd, sizeof(tmpd));
- ForceZero(td, sizeof(td));
- #endif
- sp_ecc_point_free(rt, 1, heap);
- return err;
- }
- /* A table entry for pre-computed points. */
- typedef struct sp_table_entry {
- sp_digit x[8];
- sp_digit y[8];
- } sp_table_entry;
- #ifdef FP_ECC
- /* Double the Montgomery form projective point p a number of times.
- *
- * r Result of repeated doubling of point.
- * p Point to double.
- * n Number of times to double
- * t Temporary ordinate data.
- */
- static void sp_256_proj_point_dbl_n_8(sp_point* r, const sp_point* p, int n,
- sp_digit* t)
- {
- sp_point* rp[2];
- sp_digit* w = t;
- sp_digit* a = t + 2*8;
- sp_digit* b = t + 4*8;
- sp_digit* t1 = t + 6*8;
- sp_digit* t2 = t + 8*8;
- sp_digit* x;
- sp_digit* y;
- sp_digit* z;
- int i;
- rp[0] = r;
- /*lint allow cast to different type of pointer*/
- rp[1] = (sp_point*)t; /*lint !e9087 !e740*/
- XMEMSET(rp[1], 0, sizeof(sp_point));
- x = rp[p->infinity]->x;
- y = rp[p->infinity]->y;
- z = rp[p->infinity]->z;
- if (r != p) {
- for (i=0; i<8; i++) {
- r->x[i] = p->x[i];
- }
- for (i=0; i<8; i++) {
- r->y[i] = p->y[i];
- }
- for (i=0; i<8; i++) {
- r->z[i] = p->z[i];
- }
- r->infinity = p->infinity;
- }
- /* Y = 2*Y */
- sp_256_mont_dbl_8(y, y, p256_mod);
- /* W = Z^4 */
- sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod);
- sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod);
- while (n-- > 0) {
- /* A = 3*(X^2 - W) */
- sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod);
- sp_256_mont_sub_8(t1, t1, w, p256_mod);
- sp_256_mont_tpl_8(a, t1, p256_mod);
- /* B = X*Y^2 */
- sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(b, t2, x, p256_mod, p256_mp_mod);
- /* X = A^2 - 2B */
- sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod);
- sp_256_mont_dbl_8(t1, b, p256_mod);
- sp_256_mont_sub_8(x, x, t1, p256_mod);
- /* Z = Z*Y */
- sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod);
- /* t2 = Y^4 */
- sp_256_mont_sqr_8(t2, t2, p256_mod, p256_mp_mod);
- if (n != 0) {
- /* W = W*Y^4 */
- sp_256_mont_mul_8(w, w, t2, p256_mod, p256_mp_mod);
- }
- /* y = 2*A*(B - X) - Y^4 */
- sp_256_mont_sub_8(y, b, x, p256_mod);
- sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod);
- sp_256_mont_dbl_8(y, y, p256_mod);
- sp_256_mont_sub_8(y, y, t2, p256_mod);
- }
- /* Y = Y/2 */
- sp_256_div2_8(y, y, p256_mod);
- }
- #endif /* FP_ECC */
- /* Add two Montgomery form projective points. The second point has a q value of
- * one.
- * Only the first point can be the same pointer as the result point.
- *
- * r Result of addition.
- * p First point to add.
- * q Second point to add.
- * t Temporary ordinate data.
- */
- static void sp_256_proj_point_add_qz1_8(sp_point* r, const sp_point* p,
- const sp_point* q, sp_digit* t)
- {
- const sp_point* ap[2];
- sp_point* rp[2];
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2*8;
- sp_digit* t3 = t + 4*8;
- sp_digit* t4 = t + 6*8;
- sp_digit* t5 = t + 8*8;
- sp_digit* x;
- sp_digit* y;
- sp_digit* z;
- int i;
- /* Check double */
- (void)sp_256_sub_8(t1, p256_mod, q->y);
- sp_256_norm_8(t1);
- if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) &
- (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) {
- sp_256_proj_point_dbl_8(r, p, t);
- }
- else {
- rp[0] = r;
- /*lint allow cast to different type of pointer*/
- rp[1] = (sp_point*)t; /*lint !e9087 !e740*/
- XMEMSET(rp[1], 0, sizeof(sp_point));
- x = rp[p->infinity | q->infinity]->x;
- y = rp[p->infinity | q->infinity]->y;
- z = rp[p->infinity | q->infinity]->z;
- ap[0] = p;
- ap[1] = q;
- for (i=0; i<8; i++) {
- r->x[i] = ap[p->infinity]->x[i];
- }
- for (i=0; i<8; i++) {
- r->y[i] = ap[p->infinity]->y[i];
- }
- for (i=0; i<8; i++) {
- r->z[i] = ap[p->infinity]->z[i];
- }
- r->infinity = ap[p->infinity]->infinity;
- /* U2 = X2*Z1^2 */
- sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod);
- /* S2 = Y2*Z1^3 */
- sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod);
- /* H = U2 - X1 */
- sp_256_mont_sub_8(t2, t2, x, p256_mod);
- /* R = S2 - Y1 */
- sp_256_mont_sub_8(t4, t4, y, p256_mod);
- /* Z3 = H*Z1 */
- sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod);
- /* X3 = R^2 - H^3 - 2*X1*H^2 */
- sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod);
- sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod);
- sp_256_mont_sub_8(x, t1, t5, p256_mod);
- sp_256_mont_dbl_8(t1, t3, p256_mod);
- sp_256_mont_sub_8(x, x, t1, p256_mod);
- /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
- sp_256_mont_sub_8(t3, t3, x, p256_mod);
- sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod);
- sp_256_mont_sub_8(y, t3, t5, p256_mod);
- }
- }
- #ifdef WOLFSSL_SP_SMALL
- #ifdef FP_ECC
- /* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a Point to convert.
- * t Temporary data.
- */
- static void sp_256_proj_to_affine_8(sp_point* a, sp_digit* t)
- {
- sp_digit* t1 = t;
- sp_digit* t2 = t + 2 * 8;
- sp_digit* tmp = t + 4 * 8;
- sp_256_mont_inv_8(t1, a->z, tmp);
- sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod);
- XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
- }
- /* Generate the pre-computed table of points for the base point.
- *
- * a The base point.
- * table Place to store generated point data.
- * tmp Temporary data.
- * heap Heap to use for allocation.
- */
- static int sp_256_gen_stripe_table_8(const sp_point* a,
- sp_table_entry* table, sp_digit* tmp, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point td, s1d, s2d;
- #endif
- sp_point* t;
- sp_point* s1 = NULL;
- sp_point* s2 = NULL;
- int i, j;
- int err;
- (void)heap;
- err = sp_ecc_point_new(heap, td, t);
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, s1d, s1);
- }
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, s2d, s2);
- }
- if (err == MP_OKAY) {
- err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod);
- }
- if (err == MP_OKAY) {
- err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod);
- }
- if (err == MP_OKAY) {
- err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod);
- }
- if (err == MP_OKAY) {
- t->infinity = 0;
- sp_256_proj_to_affine_8(t, tmp);
- XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
- s1->infinity = 0;
- XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
- s2->infinity = 0;
- /* table[0] = {0, 0, infinity} */
- XMEMSET(&table[0], 0, sizeof(sp_table_entry));
- /* table[1] = Affine version of 'a' in Montgomery form */
- XMEMCPY(table[1].x, t->x, sizeof(table->x));
- XMEMCPY(table[1].y, t->y, sizeof(table->y));
- for (i=1; i<4; i++) {
- sp_256_proj_point_dbl_n_8(t, t, 64, tmp);
- sp_256_proj_to_affine_8(t, tmp);
- XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
- XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
- }
- for (i=1; i<4; i++) {
- XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
- XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
- for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
- XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
- XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
- sp_256_proj_point_add_qz1_8(t, s1, s2, tmp);
- sp_256_proj_to_affine_8(t, tmp);
- XMEMCPY(table[j].x, t->x, sizeof(table->x));
- XMEMCPY(table[j].y, t->y, sizeof(table->y));
- }
- }
- }
- sp_ecc_point_free(s2, 0, heap);
- sp_ecc_point_free(s1, 0, heap);
- sp_ecc_point_free( t, 0, heap);
- return err;
- }
- #endif /* FP_ECC */
- /* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * r Resulting point.
- * k Scalar to multiply by.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- static int sp_256_ecc_mulmod_stripe_8(sp_point* r, const sp_point* g,
- const sp_table_entry* table, const sp_digit* k, int map, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point rtd;
- sp_point pd;
- sp_digit td[2 * 8 * 5];
- #endif
- sp_point* rt;
- sp_point* p = NULL;
- sp_digit* t;
- int i, j;
- int y, x;
- int err;
- (void)g;
- (void)heap;
- err = sp_ecc_point_new(heap, rtd, rt);
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, pd, p);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap,
- DYNAMIC_TYPE_ECC);
- if (t == NULL) {
- err = MEMORY_E;
- }
- #else
- t = td;
- #endif
- if (err == MP_OKAY) {
- XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
- XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
- y = 0;
- for (j=0,x=63; j<4; j++,x+=64) {
- y |= ((k[x / 32] >> (x % 32)) & 1) << j;
- }
- XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
- XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
- rt->infinity = !y;
- for (i=62; i>=0; i--) {
- y = 0;
- for (j=0,x=i; j<4; j++,x+=64) {
- y |= ((k[x / 32] >> (x % 32)) & 1) << j;
- }
- sp_256_proj_point_dbl_8(rt, rt, t);
- XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
- XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
- p->infinity = !y;
- sp_256_proj_point_add_qz1_8(rt, rt, p, t);
- }
- if (map != 0) {
- sp_256_map_8(r, rt, t);
- }
- else {
- XMEMCPY(r, rt, sizeof(sp_point));
- }
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (t != NULL) {
- XFREE(t, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(p, 0, heap);
- sp_ecc_point_free(rt, 0, heap);
- return err;
- }
- #ifdef FP_ECC
- #ifndef FP_ENTRIES
- #define FP_ENTRIES 16
- #endif
- typedef struct sp_cache_t {
- sp_digit x[8];
- sp_digit y[8];
- sp_table_entry table[16];
- uint32_t cnt;
- int set;
- } sp_cache_t;
- static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
- static THREAD_LS_T int sp_cache_last = -1;
- static THREAD_LS_T int sp_cache_inited = 0;
- #ifndef HAVE_THREAD_LS
- static volatile int initCacheMutex = 0;
- static wolfSSL_Mutex sp_cache_lock;
- #endif
- static void sp_ecc_get_cache(const sp_point* g, sp_cache_t** cache)
- {
- int i, j;
- uint32_t least;
- if (sp_cache_inited == 0) {
- for (i=0; i<FP_ENTRIES; i++) {
- sp_cache[i].set = 0;
- }
- sp_cache_inited = 1;
- }
- /* Compare point with those in cache. */
- for (i=0; i<FP_ENTRIES; i++) {
- if (!sp_cache[i].set)
- continue;
- if (sp_256_cmp_equal_8(g->x, sp_cache[i].x) &
- sp_256_cmp_equal_8(g->y, sp_cache[i].y)) {
- sp_cache[i].cnt++;
- break;
- }
- }
- /* No match. */
- if (i == FP_ENTRIES) {
- /* Find empty entry. */
- i = (sp_cache_last + 1) % FP_ENTRIES;
- for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
- if (!sp_cache[i].set) {
- break;
- }
- }
- /* Evict least used. */
- if (i == sp_cache_last) {
- least = sp_cache[0].cnt;
- for (j=1; j<FP_ENTRIES; j++) {
- if (sp_cache[j].cnt < least) {
- i = j;
- least = sp_cache[i].cnt;
- }
- }
- }
- XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
- XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
- sp_cache[i].set = 1;
- sp_cache[i].cnt = 1;
- }
- *cache = &sp_cache[i];
- sp_cache_last = i;
- }
- #endif /* FP_ECC */
- /* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * r Resulting point.
- * g Point to multiply.
- * k Scalar to multiply by.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- static int sp_256_ecc_mulmod_8(sp_point* r, const sp_point* g, const sp_digit* k,
- int map, void* heap)
- {
- #ifndef FP_ECC
- return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
- #else
- sp_digit tmp[2 * 8 * 5];
- sp_cache_t* cache;
- int err = MP_OKAY;
- #ifndef HAVE_THREAD_LS
- if (initCacheMutex == 0) {
- wc_InitMutex(&sp_cache_lock);
- initCacheMutex = 1;
- }
- if (wc_LockMutex(&sp_cache_lock) != 0)
- err = BAD_MUTEX_E;
- #endif /* HAVE_THREAD_LS */
- if (err == MP_OKAY) {
- sp_ecc_get_cache(g, &cache);
- if (cache->cnt == 2)
- sp_256_gen_stripe_table_8(g, cache->table, tmp, heap);
- #ifndef HAVE_THREAD_LS
- wc_UnLockMutex(&sp_cache_lock);
- #endif /* HAVE_THREAD_LS */
- if (cache->cnt < 2) {
- err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
- }
- else {
- err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k,
- map, heap);
- }
- }
- return err;
- #endif
- }
- #else
- #ifdef FP_ECC
- /* Generate the pre-computed table of points for the base point.
- *
- * a The base point.
- * table Place to store generated point data.
- * tmp Temporary data.
- * heap Heap to use for allocation.
- */
- static int sp_256_gen_stripe_table_8(const sp_point* a,
- sp_table_entry* table, sp_digit* tmp, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point td, s1d, s2d;
- #endif
- sp_point* t;
- sp_point* s1 = NULL;
- sp_point* s2 = NULL;
- int i, j;
- int err;
- (void)heap;
- err = sp_ecc_point_new(heap, td, t);
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, s1d, s1);
- }
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, s2d, s2);
- }
- if (err == MP_OKAY) {
- err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod);
- }
- if (err == MP_OKAY) {
- err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod);
- }
- if (err == MP_OKAY) {
- err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod);
- }
- if (err == MP_OKAY) {
- t->infinity = 0;
- sp_256_proj_to_affine_8(t, tmp);
- XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
- s1->infinity = 0;
- XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
- s2->infinity = 0;
- /* table[0] = {0, 0, infinity} */
- XMEMSET(&table[0], 0, sizeof(sp_table_entry));
- /* table[1] = Affine version of 'a' in Montgomery form */
- XMEMCPY(table[1].x, t->x, sizeof(table->x));
- XMEMCPY(table[1].y, t->y, sizeof(table->y));
- for (i=1; i<8; i++) {
- sp_256_proj_point_dbl_n_8(t, t, 32, tmp);
- sp_256_proj_to_affine_8(t, tmp);
- XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
- XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
- }
- for (i=1; i<8; i++) {
- XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
- XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
- for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
- XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
- XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
- sp_256_proj_point_add_qz1_8(t, s1, s2, tmp);
- sp_256_proj_to_affine_8(t, tmp);
- XMEMCPY(table[j].x, t->x, sizeof(table->x));
- XMEMCPY(table[j].y, t->y, sizeof(table->y));
- }
- }
- }
- sp_ecc_point_free(s2, 0, heap);
- sp_ecc_point_free(s1, 0, heap);
- sp_ecc_point_free( t, 0, heap);
- return err;
- }
- #endif /* FP_ECC */
- /* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * r Resulting point.
- * k Scalar to multiply by.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- static int sp_256_ecc_mulmod_stripe_8(sp_point* r, const sp_point* g,
- const sp_table_entry* table, const sp_digit* k, int map, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point rtd;
- sp_point pd;
- sp_digit td[2 * 8 * 5];
- #endif
- sp_point* rt;
- sp_point* p = NULL;
- sp_digit* t;
- int i, j;
- int y, x;
- int err;
- (void)g;
- (void)heap;
- err = sp_ecc_point_new(heap, rtd, rt);
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, pd, p);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap,
- DYNAMIC_TYPE_ECC);
- if (t == NULL) {
- err = MEMORY_E;
- }
- #else
- t = td;
- #endif
- if (err == MP_OKAY) {
- XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
- XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
- y = 0;
- for (j=0,x=31; j<8; j++,x+=32) {
- y |= ((k[x / 32] >> (x % 32)) & 1) << j;
- }
- XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
- XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
- rt->infinity = !y;
- for (i=30; i>=0; i--) {
- y = 0;
- for (j=0,x=i; j<8; j++,x+=32) {
- y |= ((k[x / 32] >> (x % 32)) & 1) << j;
- }
- sp_256_proj_point_dbl_8(rt, rt, t);
- XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
- XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
- p->infinity = !y;
- sp_256_proj_point_add_qz1_8(rt, rt, p, t);
- }
- if (map != 0) {
- sp_256_map_8(r, rt, t);
- }
- else {
- XMEMCPY(r, rt, sizeof(sp_point));
- }
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (t != NULL) {
- XFREE(t, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(p, 0, heap);
- sp_ecc_point_free(rt, 0, heap);
- return err;
- }
- #ifdef FP_ECC
- #ifndef FP_ENTRIES
- #define FP_ENTRIES 16
- #endif
- typedef struct sp_cache_t {
- sp_digit x[8];
- sp_digit y[8];
- sp_table_entry table[256];
- uint32_t cnt;
- int set;
- } sp_cache_t;
- static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
- static THREAD_LS_T int sp_cache_last = -1;
- static THREAD_LS_T int sp_cache_inited = 0;
- #ifndef HAVE_THREAD_LS
- static volatile int initCacheMutex = 0;
- static wolfSSL_Mutex sp_cache_lock;
- #endif
- static void sp_ecc_get_cache(const sp_point* g, sp_cache_t** cache)
- {
- int i, j;
- uint32_t least;
- if (sp_cache_inited == 0) {
- for (i=0; i<FP_ENTRIES; i++) {
- sp_cache[i].set = 0;
- }
- sp_cache_inited = 1;
- }
- /* Compare point with those in cache. */
- for (i=0; i<FP_ENTRIES; i++) {
- if (!sp_cache[i].set)
- continue;
- if (sp_256_cmp_equal_8(g->x, sp_cache[i].x) &
- sp_256_cmp_equal_8(g->y, sp_cache[i].y)) {
- sp_cache[i].cnt++;
- break;
- }
- }
- /* No match. */
- if (i == FP_ENTRIES) {
- /* Find empty entry. */
- i = (sp_cache_last + 1) % FP_ENTRIES;
- for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
- if (!sp_cache[i].set) {
- break;
- }
- }
- /* Evict least used. */
- if (i == sp_cache_last) {
- least = sp_cache[0].cnt;
- for (j=1; j<FP_ENTRIES; j++) {
- if (sp_cache[j].cnt < least) {
- i = j;
- least = sp_cache[i].cnt;
- }
- }
- }
- XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
- XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
- sp_cache[i].set = 1;
- sp_cache[i].cnt = 1;
- }
- *cache = &sp_cache[i];
- sp_cache_last = i;
- }
- #endif /* FP_ECC */
- /* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * r Resulting point.
- * g Point to multiply.
- * k Scalar to multiply by.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- static int sp_256_ecc_mulmod_8(sp_point* r, const sp_point* g, const sp_digit* k,
- int map, void* heap)
- {
- #ifndef FP_ECC
- return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
- #else
- sp_digit tmp[2 * 8 * 5];
- sp_cache_t* cache;
- int err = MP_OKAY;
- #ifndef HAVE_THREAD_LS
- if (initCacheMutex == 0) {
- wc_InitMutex(&sp_cache_lock);
- initCacheMutex = 1;
- }
- if (wc_LockMutex(&sp_cache_lock) != 0)
- err = BAD_MUTEX_E;
- #endif /* HAVE_THREAD_LS */
- if (err == MP_OKAY) {
- sp_ecc_get_cache(g, &cache);
- if (cache->cnt == 2)
- sp_256_gen_stripe_table_8(g, cache->table, tmp, heap);
- #ifndef HAVE_THREAD_LS
- wc_UnLockMutex(&sp_cache_lock);
- #endif /* HAVE_THREAD_LS */
- if (cache->cnt < 2) {
- err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
- }
- else {
- err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k,
- map, heap);
- }
- }
- return err;
- #endif
- }
- #endif /* WOLFSSL_SP_SMALL */
- /* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * km Scalar to multiply by.
- * p Point to multiply.
- * r Resulting point.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
- void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point p;
- sp_digit k[8];
- #else
- sp_digit* k = NULL;
- #endif
- sp_point* point;
- int err;
- err = sp_ecc_point_new(heap, p, point);
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
- DYNAMIC_TYPE_ECC);
- if (k == NULL)
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- sp_256_from_mp(k, 8, km);
- sp_256_point_from_ecc_point_8(point, gm);
- err = sp_256_ecc_mulmod_8(point, point, k, map, heap);
- }
- if (err == MP_OKAY) {
- err = sp_256_point_to_ecc_point_8(point, r);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (k != NULL) {
- XFREE(k, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(point, 0, heap);
- return err;
- }
- #ifdef WOLFSSL_SP_SMALL
- static const sp_table_entry p256_table[16] = {
- /* 0 */
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
- /* 1 */
- { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b,
- 0xa53755c6,0x18905f76 },
- { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688,
- 0x25885d85,0x8571ff18 } },
- /* 2 */
- { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a,
- 0xfd1b667f,0x2f5e6961 },
- { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37,
- 0x8d6f0f7b,0xf648f916 } },
- /* 3 */
- { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761,
- 0x133d0015,0x5abe0285 },
- { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562,
- 0x6b6f7383,0x94bb725b } },
- /* 4 */
- { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5,
- 0x21d324f6,0x61d587d4 },
- { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e,
- 0x4621efbe,0xfa11fe12 } },
- /* 5 */
- { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67,
- 0x1f13bedc,0x586eb04c },
- { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0,
- 0x70864f11,0x19d5ac08 } },
- /* 6 */
- { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a,
- 0xc3b266b1,0xbb6de651 },
- { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1,
- 0x5d18b99b,0x60b4619a } },
- /* 7 */
- { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014,
- 0xaeebffcd,0x9d0f27b2 },
- { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0,
- 0x356ec48d,0x244a566d } },
- /* 8 */
- { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e,
- 0xcd42ab1b,0x803f3e02 },
- { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273,
- 0x5067adc1,0xc097440e } },
- /* 9 */
- { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459,
- 0x915f1f30,0xf1af32d5 },
- { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418,
- 0xe2d41c8b,0x23d0f130 } },
- /* 10 */
- { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926,
- 0x7990216a,0x50bbb4d9 },
- { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b,
- 0x01fe49c3,0x2b100118 } },
- /* 11 */
- { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa,
- 0x83fbae0c,0xdd558999 },
- { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf,
- 0x149d6041,0xe6e4c551 } },
- /* 12 */
- { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07,
- 0xdb7e63af,0xfad27148 },
- { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875,
- 0x9f0e1a84,0x77387de3 } },
- /* 13 */
- { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408,
- 0xbef0c47e,0xb37b85c0 },
- { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa,
- 0xf9f628d5,0x9c135ac8 } },
- /* 14 */
- { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403,
- 0x91ece900,0xc109f9cb },
- { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d,
- 0x2eee1ee1,0x9bc3344f } },
- /* 15 */
- { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665,
- 0x5f1a4cc1,0x29591d52 },
- { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496,
- 0x18ef332c,0x6376551f } },
- };
- /* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * r Resulting point.
- * k Scalar to multiply by.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- static int sp_256_ecc_mulmod_base_8(sp_point* r, const sp_digit* k,
- int map, void* heap)
- {
- return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table,
- k, map, heap);
- }
- #else
- static const sp_table_entry p256_table[256] = {
- /* 0 */
- { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
- /* 1 */
- { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b,
- 0xa53755c6,0x18905f76 },
- { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688,
- 0x25885d85,0x8571ff18 } },
- /* 2 */
- { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca,
- 0xdbdf58e9,0xd953c50d },
- { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110,
- 0x9eb288f3,0x863ebb7e } },
- /* 3 */
- { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954,
- 0xb5ff80a0,0x00076055 },
- { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39,
- 0x34373ee0,0x83087761 } },
- /* 4 */
- { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a,
- 0xfd1b667f,0x2f5e6961 },
- { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37,
- 0x8d6f0f7b,0xf648f916 } },
- /* 5 */
- { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761,
- 0x133d0015,0x5abe0285 },
- { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562,
- 0x6b6f7383,0x94bb725b } },
- /* 6 */
- { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129,
- 0x2f7dc4ef,0xcdd6bbcb },
- { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792,
- 0x4bdae5f6,0xa361bebd } },
- /* 7 */
- { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec,
- 0xc4b5292c,0xba12ca09 },
- { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089,
- 0x701fef4b,0x53ebb99d } },
- /* 8 */
- { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334,
- 0x06d54831,0x8589fb92 },
- { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507,
- 0x02541c4f,0xebb0696d } },
- /* 9 */
- { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3,
- 0xd1b27da3,0xeb2820cb },
- { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42,
- 0x55a7da1d,0x1f28289b } },
- /* 10 */
- { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862,
- 0x05e54d63,0x337a4b59 },
- { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781,
- 0xf4c2fbd6,0x0d65e0d5 } },
- /* 11 */
- { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4,
- 0x52f4a232,0xc23da242 },
- { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86,
- 0xc790cff1,0x19de3b8c } },
- /* 12 */
- { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586,
- 0x91fccbfd,0xe34dcbd4 },
- { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127,
- 0x7b4e0f7f,0xe7641f44 } },
- /* 13 */
- { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6,
- 0x052a57bf,0x4a12df57 },
- { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa,
- 0xbb5bea46,0x6af5aa93 } },
- /* 14 */
- { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4,
- 0x66a44013,0x5fe3475a },
- { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae,
- 0xecfea916,0xb544e308 } },
- /* 15 */
- { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76,
- 0xa6b0c20b,0xe0b6b2bd },
- { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad,
- 0x25a63774,0x71c023de } },
- /* 16 */
- { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5,
- 0x21d324f6,0x61d587d4 },
- { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e,
- 0x4621efbe,0xfa11fe12 } },
- /* 17 */
- { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67,
- 0x1f13bedc,0x586eb04c },
- { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0,
- 0x70864f11,0x19d5ac08 } },
- /* 18 */
- { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b,
- 0x7f9c563f,0xe7c0073f },
- { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a,
- 0xc65b3c0a,0xe08504fe } },
- /* 19 */
- { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa,
- 0x5b0996b4,0x78f01882 },
- { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877,
- 0x7e94747a,0x43a773b8 } },
- /* 20 */
- { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a,
- 0xc3b266b1,0xbb6de651 },
- { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1,
- 0x5d18b99b,0x60b4619a } },
- /* 21 */
- { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014,
- 0xaeebffcd,0x9d0f27b2 },
- { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0,
- 0x356ec48d,0x244a566d } },
- /* 22 */
- { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b,
- 0x3581ef69,0x45e58c87 },
- { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2,
- 0xc1e4b7a4,0xc040e21c } },
- /* 23 */
- { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576,
- 0x682c6ec7,0x1cdf5c97 },
- { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1,
- 0xa92dff3d,0x046755f8 } },
- /* 24 */
- { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172,
- 0x3b83a5f3,0x046e5e11 },
- { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6,
- 0x303d005b,0x6e0106c3 } },
- /* 25 */
- { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8,
- 0xe901cf1f,0x442594ed },
- { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1,
- 0x4c2ee68e,0xa796fa51 } },
- /* 26 */
- { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e,
- 0xc69766e9,0xe4ad2da9 },
- { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4,
- 0xc37b5143,0xc5e94046 } },
- /* 27 */
- { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0,
- 0xdb464747,0x63283daf },
- { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad,
- 0x1981a938,0x68bd19ab } },
- /* 28 */
- { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981,
- 0x3c6fdfd6,0x495292f5 },
- { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2,
- 0x26036837,0x0ec7530d } },
- /* 29 */
- { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5,
- 0x64863f0b,0x0f6207a6 },
- { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407,
- 0x08ed6dcf,0xff0db072 } },
- /* 30 */
- { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317,
- 0x88740ea3,0x313b513c },
- { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd,
- 0x86f19f81,0x2d3abcf9 } },
- /* 31 */
- { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f,
- 0xded98cdf,0xc036fa10 },
- { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277,
- 0xb6d40194,0xa6b2a2c4 } },
- /* 32 */
- { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac,
- 0xaf7c9860,0x810ee252 },
- { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74,
- 0x92731745,0xd485717a } },
- /* 33 */
- { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb,
- 0x2f9a604e,0x6a6045a7 },
- { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73,
- 0xf9e15790,0xd3e45cfa } },
- /* 34 */
- { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54,
- 0xe3c2c19c,0x207755de },
- { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6,
- 0x7154b00d,0x48dc5ee5 } },
- /* 35 */
- { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe,
- 0xdff6f445,0xf2fb0aed },
- { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad,
- 0xdb28d525,0xa13e9015 } },
- /* 36 */
- { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241,
- 0x1497526f,0x2bf0d6b0 },
- { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f,
- 0x162fe89f,0x42a94a5a } },
- /* 37 */
- { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050,
- 0xc65ede3d,0x2c2dd969 },
- { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706,
- 0x42c56dbc,0xf437fa1f } },
- /* 38 */
- { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050,
- 0x54707aa8,0xaaf45b33 },
- { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681,
- 0xf4f272bc,0xcdf6310d } },
- /* 39 */
- { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772,
- 0xda9e2ff2,0xf0d008ba },
- { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d,
- 0xca887b8b,0x5bd5c2f5 } },
- /* 40 */
- { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e,
- 0xa09e4719,0xaa12dfc8 },
- { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73,
- 0xe48ca901,0x6c036e73 } },
- /* 41 */
- { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b,
- 0x96afbe24,0x292ff658 },
- { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f,
- 0x311b7276,0x644e0c90 } },
- /* 42 */
- { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87,
- 0xcab79a77,0xf25ae793 },
- { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3,
- 0x13db0a3e,0x39b8e653 } },
- /* 43 */
- { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a,
- 0x0f19db06,0x39122f2f },
- { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2,
- 0xce80ff8d,0x8de80af8 } },
- /* 44 */
- { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b,
- 0x2e368c04,0x87194906 },
- { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a,
- 0x5b74fde1,0xfc315e6a } },
- /* 45 */
- { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b,
- 0xee389088,0xe6d4a7ad },
- { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93,
- 0x9be2ae57,0x35dfaf9a } },
- /* 46 */
- { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41,
- 0x1c830d2b,0x1da5c7d7 },
- { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7,
- 0xdbf4b9d6,0x7077c0fd } },
- /* 47 */
- { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140,
- 0xe50efe44,0x53a8632e },
- { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3,
- 0x34e1fcc1,0x028ca76d } },
- /* 48 */
- { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117,
- 0x6962f046,0x04c17cd8 },
- { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6,
- 0xfed97474,0xf7ba4de9 } },
- /* 49 */
- { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553,
- 0x52131c41,0xe31f9600 },
- { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac,
- 0xce34d47b,0xaa3a6259 } },
- /* 50 */
- { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa,
- 0x7e79daee,0x2398dd62 },
- { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377,
- 0x1c046210,0x5717f5b2 } },
- /* 51 */
- { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239,
- 0x0e3c28de,0x660a2c56 },
- { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481,
- 0x4f522453,0x624ee54c } },
- /* 52 */
- { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423,
- 0x92bdfbc0,0x4f392afb },
- { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803,
- 0xccdb399c,0x8a3e7977 } },
- /* 53 */
- { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de,
- 0x70c24404,0x3888d023 },
- { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8,
- 0x18102336,0xa5e62e47 } },
- /* 54 */
- { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7,
- 0x466a5adc,0x2c4768e6 },
- { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064,
- 0xf9e652a0,0x7b5e6441 } },
- /* 55 */
- { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5,
- 0x0c8d744a,0xb8af73cb },
- { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f,
- 0x7f3f0895,0xa036395f } },
- /* 56 */
- { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682,
- 0x875fb533,0x4be36b01 },
- { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05,
- 0x1bdc00c0,0x8cbc9a87 } },
- /* 57 */
- { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c,
- 0x0c0835f8,0x44e7553e },
- { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276,
- 0x5eb8fc18,0x470a683a } },
- /* 58 */
- { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee,
- 0xc63dc6ef,0x16410690 },
- { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72,
- 0x7abcbb4f,0xd73479fd } },
- /* 59 */
- { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1,
- 0x0771666b,0x816469e3 },
- { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb,
- 0xf0dd3f9c,0x0a36dd23 } },
- /* 60 */
- { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad,
- 0xfdbab118,0xe331dfd6 },
- { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7,
- 0x492e3389,0xd3b4782a } },
- /* 61 */
- { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953,
- 0x4c86a5bd,0x7281275a },
- { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a,
- 0xce145059,0x2c062e7e } },
- /* 62 */
- { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288,
- 0x2c4e7ef1,0x282a35f9 },
- { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38,
- 0x554d2abd,0xc71cd513 } },
- /* 63 */
- { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7,
- 0xcf47f3a3,0xc50f6740 },
- { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222,
- 0x212958dc,0xb9ecb3a7 } },
- /* 64 */
- { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e,
- 0xcd42ab1b,0x803f3e02 },
- { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273,
- 0x5067adc1,0xc097440e } },
- /* 65 */
- { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459,
- 0x915f1f30,0xf1af32d5 },
- { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418,
- 0xe2d41c8b,0x23d0f130 } },
- /* 66 */
- { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648,
- 0xc0a3fadd,0xb0288dd6 },
- { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7,
- 0xf408c8d2,0xffd3724f } },
- /* 67 */
- { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b,
- 0xd78c26df,0xf5590f4a },
- { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f,
- 0xf6f74a20,0x18d6da54 } },
- /* 68 */
- { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926,
- 0x7990216a,0x50bbb4d9 },
- { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b,
- 0x01fe49c3,0x2b100118 } },
- /* 69 */
- { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa,
- 0x83fbae0c,0xdd558999 },
- { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf,
- 0x149d6041,0xe6e4c551 } },
- /* 70 */
- { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b,
- 0x07ed56ff,0x51e00db1 },
- { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5,
- 0x49829177,0xe22f4241 } },
- /* 71 */
- { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f,
- 0x52dc48c9,0xf709373d },
- { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a,
- 0xe7275b11,0xbd52d288 } },
- /* 72 */
- { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e,
- 0xc8aa77a6,0xa0d0f8e4 },
- { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8,
- 0x946d6a00,0xa56c78c7 } },
- /* 73 */
- { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f,
- 0x731a367a,0xd8befdf8 },
- { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40,
- 0xce9f6478,0x854a68a5 } },
- /* 74 */
- { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b,
- 0x98846a95,0x5cacea0b },
- { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8,
- 0x35e4efa9,0xe4982d12 } },
- /* 75 */
- { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa,
- 0x16b20499,0x8046b7f6 },
- { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea,
- 0x9082af55,0xeb17ca7b } },
- /* 76 */
- { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565,
- 0xfab5e131,0x097b00ba },
- { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11,
- 0xafdbcc9e,0xf95c747b } },
- /* 77 */
- { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1,
- 0x566ed837,0x3512601e },
- { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2,
- 0x6068ab6b,0x0ef97123 } },
- /* 78 */
- { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74,
- 0x3b4fbc95,0xfc16d933 },
- { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497,
- 0xb95d7a17,0x14ca4af1 } },
- /* 79 */
- { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7,
- 0xf59c231d,0x4057b063 },
- { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae,
- 0xf1330b13,0x1c3b5d64 } },
- /* 80 */
- { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07,
- 0xdb7e63af,0xfad27148 },
- { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875,
- 0x9f0e1a84,0x77387de3 } },
- /* 81 */
- { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408,
- 0xbef0c47e,0xb37b85c0 },
- { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa,
- 0xf9f628d5,0x9c135ac8 } },
- /* 82 */
- { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176,
- 0xc433851f,0x5721361f },
- { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e,
- 0xe6bb11bd,0xdcbac3c9 } },
- /* 83 */
- { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7,
- 0x2d626862,0xb8c1c89e },
- { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9,
- 0x2f9422d4,0x5d23bbda } },
- /* 84 */
- { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403,
- 0x91ece900,0xc109f9cb },
- { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d,
- 0x2eee1ee1,0x9bc3344f } },
- /* 85 */
- { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665,
- 0x5f1a4cc1,0x29591d52 },
- { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496,
- 0x18ef332c,0x6376551f } },
- /* 86 */
- { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064,
- 0x08e2987a,0xbdb79dc8 },
- { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022,
- 0xadd3c14a,0x8ee86001 } },
- /* 87 */
- { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899,
- 0x6f77aa4b,0x92e51d7a },
- { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3,
- 0x0a56aaaa,0x5182f86f } },
- /* 88 */
- { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb,
- 0x4073a6f2,0x91dcab5d },
- { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c,
- 0x97974f2b,0x17a0cedb } },
- /* 89 */
- { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4,
- 0x7f4cdf41,0x2e8ce36c },
- { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388,
- 0x34f668f3,0xf4ccc6cb } },
- /* 90 */
- { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741,
- 0x9a0df3c9,0xac0db488 },
- { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f,
- 0x94c974a2,0x95a64a61 } },
- /* 91 */
- { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c,
- 0x29210677,0x231e54ba },
- { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b,
- 0xd8a731e1,0xab0be032 } },
- /* 92 */
- { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196,
- 0x2cf6a679,0xf1bcc880 },
- { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc,
- 0x5aebb271,0x85169469 } },
- /* 93 */
- { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2,
- 0xdaad55d8,0x8f67d9d2 },
- { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4,
- 0xc0728b5d,0xf84572b9 } },
- /* 94 */
- { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07,
- 0x616b2c19,0xedee2710 },
- { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3,
- 0x44ebd7f4,0x9fd27e9b } },
- /* 95 */
- { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816,
- 0x958ff387,0xa40c2fb6 },
- { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704,
- 0x7dc6decf,0x99bc9bb8 } },
- /* 96 */
- { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0,
- 0xa16d7e64,0x9abe210b },
- { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987,
- 0x87f344b0,0x7881c257 } },
- /* 97 */
- { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2,
- 0xa30e8940,0x15e6e319 },
- { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1,
- 0x191172ce,0x0e55facf } },
- /* 98 */
- { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca,
- 0x6fe96577,0xd73d0976 },
- { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859,
- 0x8f15a50b,0x9250a374 } },
- /* 99 */
- { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289,
- 0xc1cc8c0b,0x77414082 },
- { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7,
- 0x12eb20b9,0x8cb04f4d } },
- /* 100 */
- { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f,
- 0x47123b51,0xe4e429ef },
- { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07,
- 0x3c6e6552,0x37bca2ff } },
- /* 101 */
- { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9,
- 0x3002b22a,0x59913edc },
- { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375,
- 0xb013e226,0x43786e4a } },
- /* 102 */
- { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845,
- 0xb7e79e7a,0x8638ca98 },
- { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0,
- 0x7b3aa6f0,0x1ecdd36a } },
- /* 103 */
- { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa,
- 0xd459f32d,0xd85d0f85 },
- { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4,
- 0xb4ed3c62,0xa04f19c3 } },
- /* 104 */
- { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a,
- 0x5c0950b0,0x92b2eeea },
- { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3,
- 0x5834276c,0x1ee78221 } },
- /* 105 */
- { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a,
- 0x57a6e150,0xf3f2ced8 },
- { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7,
- 0x3da3e210,0x0f56a454 } },
- /* 106 */
- { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0,
- 0x1969e263,0xbd8f1741 },
- { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7,
- 0x30ccfa09,0x2d1a1c35 } },
- /* 107 */
- { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949,
- 0xb91fba46,0xa107a65e },
- { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584,
- 0xf87a9af2,0x183d760a } },
- /* 108 */
- { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963,
- 0xc269d754,0x1d44179d },
- { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5,
- 0x9606d262,0x771f9cc2 } },
- /* 109 */
- { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2,
- 0x0362718e,0x64427a31 },
- { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d,
- 0x6ae90d6d,0x49d9b749 } },
- /* 110 */
- { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0,
- 0x3f605445,0x9037d81b },
- { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96,
- 0x7cc0639c,0x08c3de6a } },
- /* 111 */
- { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e,
- 0x45796b2f,0xc6909442 },
- { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab,
- 0xcafe3ac0,0x3fa3db02 } },
- /* 112 */
- { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c,
- 0xfdb808ff,0xc5c4bdb0 },
- { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d,
- 0x46c2b6b5,0x2d56db94 } },
- /* 113 */
- { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4,
- 0xe503ba42,0x0f56bd9d },
- { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a,
- 0x1173b5f1,0x4003bb9d } },
- /* 114 */
- { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d,
- 0xa07f2f9e,0x53765522 },
- { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e,
- 0x6c5d4549,0x7a056f58 } },
- /* 115 */
- { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e,
- 0x7a1a2675,0x77d482f1 },
- { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057,
- 0x2b38b0e4,0x4115012b } },
- /* 116 */
- { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e,
- 0xfbea0946,0xcdf04572 },
- { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1,
- 0x97383109,0xee703dda } },
- /* 117 */
- { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff,
- 0xa162ce21,0x2a0ad89d },
- { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c,
- 0xac2b4659,0xd62d0b67 } },
- /* 118 */
- { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3,
- 0x991c2426,0xb39a23f2 },
- { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137,
- 0xc0674cc5,0x04ed0092 } },
- /* 119 */
- { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6,
- 0x0177c387,0xa0a91fc1 },
- { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1,
- 0x9ed20c41,0x084cf988 } },
- /* 120 */
- { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4,
- 0x73abf77e,0xd57955b2 },
- { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089,
- 0x02d141f1,0x8e14ea42 } },
- /* 121 */
- { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194,
- 0x2aa4d158,0x597e1a37 },
- { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a,
- 0x199b4dea,0xca3f0236 } },
- /* 122 */
- { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1,
- 0x309c07e4,0xbde7fd7e },
- { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f,
- 0x0a7dd198,0xb623ad0e } },
- /* 123 */
- { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0,
- 0x58ec137b,0xd6aa2e46 },
- { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b,
- 0x2dcc513a,0x111662e0 } },
- /* 124 */
- { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7,
- 0x94b750f8,0xdb3ee1cb },
- { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93,
- 0x52206a59,0x886a6442 } },
- /* 125 */
- { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d,
- 0x018a17bc,0xa70cf4eb },
- { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e,
- 0xd1747b77,0xaa4772ab } },
- /* 126 */
- { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4,
- 0x30faf974,0x611a6ddc },
- { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf,
- 0x16429c88,0x5cfffaf8 } },
- /* 127 */
- { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f,
- 0x7dc1994c,0x6e5a6b23 },
- { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6,
- 0x242dabcc,0x481a238d } },
- /* 128 */
- { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d,
- 0xe0cdf943,0x2c41114c },
- { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2,
- 0x42ff9297,0x20477abf } },
- /* 129 */
- { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b,
- 0xc77396b6,0xac66409a },
- { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba,
- 0xcc122f85,0xce8e6975 } },
- /* 130 */
- { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d,
- 0x250bb4a8,0x08fde365 },
- { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc,
- 0x565d6cd7,0x2f7e2fd2 } },
- /* 131 */
- { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d,
- 0x907702ae,0xc65be92e },
- { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585,
- 0xd1193b3a,0x4bff8e47 } },
- /* 132 */
- { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef,
- 0x5772967d,0x3e4e4ae6 },
- { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26,
- 0x58ec6028,0x5388aefd } },
- /* 133 */
- { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f,
- 0x4f75be0e,0x5cf908d1 },
- { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f,
- 0x60f00ce2,0xa698ba40 } },
- /* 134 */
- { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544,
- 0x7aebad8d,0xb142ef8a },
- { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b,
- 0x58515075,0xd1896a96 } },
- /* 135 */
- { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73,
- 0x7981da39,0x267b0e0b },
- { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0,
- 0xa1119393,0xb54e287a } },
- /* 136 */
- { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab,
- 0x5f87d4e6,0x84abb28b },
- { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b,
- 0x17655640,0xe5436f67 } },
- /* 137 */
- { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd,
- 0x5b9ce99e,0x0404f68b },
- { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960,
- 0x0ac1c701,0x3a4263df } },
- /* 138 */
- { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6,
- 0x905ea367,0x0ca8fd3f },
- { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be,
- 0x4ddb0c33,0x96dca264 } },
- /* 139 */
- { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770,
- 0x3aad59dc,0x4363e212 },
- { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604,
- 0xd8bb98c4,0x840e115c } },
- /* 140 */
- { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272,
- 0x30ded6d4,0x5e0d6abd },
- { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9,
- 0x2945a25a,0x7dea48f4 } },
- /* 141 */
- { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54,
- 0xebfd16d1,0xabc2a2be },
- { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377,
- 0x6c7eefc1,0x4ea35394 } },
- /* 142 */
- { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a,
- 0x1c94ffc3,0x3a76e689 },
- { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72,
- 0x465e6464,0x8212a10a } },
- /* 143 */
- { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67,
- 0x599cb164,0xaa7cab71 },
- { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292,
- 0xfe0617c3,0x40e38073 } },
- /* 144 */
- { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320,
- 0xb3055526,0xe3604700 },
- { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434,
- 0xa3dee15f,0x6542d677 } },
- /* 145 */
- { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8,
- 0x09bb6f21,0xa6534aee },
- { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1,
- 0xdc9aef22,0xf3cb672f } },
- /* 146 */
- { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9,
- 0xaae870e7,0x7cafaa2e },
- { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108,
- 0xb9bd522e,0x0aab13c1 } },
- /* 147 */
- { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173,
- 0x847012e9,0x4b91a602 },
- { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a,
- 0x72321cab,0x49534c53 } },
- /* 148 */
- { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b,
- 0xd65ac5ee,0xcaf46c4f },
- { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168,
- 0x04c6770f,0x14ce9e57 } },
- /* 149 */
- { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f,
- 0x3e4c9a71,0x1bb708a5 },
- { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71,
- 0xda300102,0xf9d126f2 } },
- /* 150 */
- { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311,
- 0x729ecc69,0x807afcb9 },
- { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59,
- 0x6568cd8c,0x751adcd1 } },
- /* 151 */
- { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14,
- 0x2537743f,0x29ec4468 },
- { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a,
- 0x92a4077d,0xff9370e3 } },
- /* 152 */
- { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e,
- 0xa2a9d01a,0x9776478b },
- { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5,
- 0xac2f82fa,0x74a6313f } },
- /* 153 */
- { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0,
- 0x0ff4863d,0xab75be15 },
- { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03,
- 0x0b4459f6,0x4ebeac2e } },
- /* 154 */
- { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633,
- 0x2c1baffc,0xdf99887b },
- { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511,
- 0x779f4058,0x27b040a7 } },
- /* 155 */
- { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152,
- 0xe4cfa3f5,0xb393dd37 },
- { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be,
- 0xd0463419,0x09588c12 } },
- /* 156 */
- { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280,
- 0xdb9f648b,0x81c879a9 },
- { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41,
- 0x5fc11bc4,0xfa0d48f5 } },
- /* 157 */
- { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1,
- 0xb6a367d6,0x8ea0e156 },
- { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b,
- 0xfa00b5ac,0x3f5ab924 } },
- /* 158 */
- { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6,
- 0x2b74256e,0x8bc76887 },
- { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168,
- 0x60fcf34f,0xb386f190 } },
- /* 159 */
- { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea,
- 0x1b069c4d,0x4cb460f7 },
- { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66,
- 0x95ef5223,0x52c0d508 } },
- /* 160 */
- { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661,
- 0x2bb09c0b,0x4ac3c938 },
- { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765,
- 0xe39705f4,0x380d94c7 } },
- /* 161 */
- { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977,
- 0xde2637af,0x2ce3e171 },
- { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f,
- 0x0b624e4d,0x2e6cd852 } },
- /* 162 */
- { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e,
- 0x42c69d54,0xca177547 },
- { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793,
- 0x9cab2ce6,0xa976a713 } },
- /* 163 */
- { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7,
- 0x0a1f4999,0x8720a717 },
- { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a,
- 0xc769893c,0x9719ef29 } },
- /* 164 */
- { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0,
- 0xe15704c1,0xa5072976 },
- { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18,
- 0xf7b77725,0x99389c9d } },
- /* 165 */
- { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89,
- 0x202c82e4,0xa88806aa },
- { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0,
- 0x4738dcfe,0x0043bffb } },
- /* 166 */
- { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a,
- 0xba6c4866,0x52f3ef01 },
- { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa,
- 0x9ef27e75,0x3296bd89 } },
- /* 167 */
- { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd,
- 0xaee571e9,0x3b90febf },
- { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48,
- 0x9f810b18,0x6e88069d } },
- /* 168 */
- { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221,
- 0xdefaad13,0xa7222bea },
- { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5,
- 0xbc2ac690,0xbe94d523 } },
- /* 169 */
- { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1,
- 0x9be8c766,0x7782defe },
- { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc,
- 0xa2892e4b,0x03838567 } },
- /* 170 */
- { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc,
- 0xadf7b420,0xdbd986c4 },
- { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d,
- 0x6860bbd0,0x8e24d3c4 } },
- /* 171 */
- { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4,
- 0x407bafc8,0x541a99c4 },
- { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4,
- 0xf57d35d1,0xc0092c49 } },
- /* 172 */
- { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1,
- 0x7286944d,0x75e40634 },
- { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16,
- 0xc7848586,0x5b7cb658 } },
- /* 173 */
- { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1,
- 0x8df097a1,0x7ae13eba },
- { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878,
- 0xe2a8e3fd,0x787d8074 } },
- /* 174 */
- { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3,
- 0x9ef28484,0x5c222819 },
- { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1,
- 0xbaf0f2b0,0xe45d37ab } },
- /* 175 */
- { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7,
- 0x84dfb9d3,0xed7bc122 },
- { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140,
- 0x45ca6d27,0xaac97cc9 } },
- /* 176 */
- { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1,
- 0x1163dc4e,0x318f97b3 },
- { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f,
- 0x9a84ff4d,0xfa41faa1 } },
- /* 177 */
- { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4,
- 0x1d26e9e2,0x38bb6b2c },
- { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf,
- 0xce7601a5,0x94dd0905 } },
- /* 178 */
- { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9,
- 0xd25c2ae9,0x92077867 },
- { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3,
- 0xd29beb51,0x81e8428b } },
- /* 179 */
- { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f,
- 0xdbbfa4b1,0x1b94ab62 },
- { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f,
- 0x055590ee,0x06a38e28 } },
- /* 180 */
- { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b,
- 0x83d9d4f8,0xa7b36c20 },
- { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2,
- 0xa2822a20,0xbe54c6b4 } },
- /* 181 */
- { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f,
- 0xeae022bb,0xbf30a5ab },
- { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb,
- 0x2732d13a,0xd1c820de } },
- /* 182 */
- { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe,
- 0x68a18da3,0xb7d17bed },
- { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af,
- 0x6412cc64,0x3997fd5e } },
- /* 183 */
- { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0,
- 0x3c6c13e8,0x0eeb8929 },
- { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6,
- 0xc922b6ef,0x228916f8 } },
- /* 184 */
- { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e,
- 0x6e93097e,0xec05ad1d },
- { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237,
- 0x7ff11b37,0x7d314156 } },
- /* 185 */
- { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97,
- 0x9bc1d7a3,0xe9ce66fc },
- { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34,
- 0x72280651,0xd9650b01 } },
- /* 186 */
- { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208,
- 0x804eb7a2,0x14d6699a },
- { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90,
- 0x0d43598a,0x6f4c6841 } },
- /* 187 */
- { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2,
- 0x61189abb,0x4c4350fd },
- { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413,
- 0x5a3118b5,0xa726d242 } },
- /* 188 */
- { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f,
- 0xcc6cf392,0x13639e82 },
- { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e,
- 0xc1a335a3,0xca9365e1 } },
- /* 189 */
- { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4,
- 0x970b72a5,0x9ce29c34 },
- { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a,
- 0xab42af98,0x48c4abd7 } },
- /* 190 */
- { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698,
- 0xf67b33cb,0x78017c32 },
- { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55,
- 0xde5c1c04,0x53cd0454 } },
- /* 191 */
- { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1,
- 0xd3d7fa8f,0xeea465c1 },
- { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770,
- 0x7ae69193,0x1b6e42a4 } },
- /* 192 */
- { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887,
- 0x187fbd3d,0x0224da14 },
- { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf,
- 0x42bfff33,0x60838ef0 } },
- /* 193 */
- { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a,
- 0x2d331643,0x636eb202 },
- { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2,
- 0x39218bac,0x8844eeb6 } },
- /* 194 */
- { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f,
- 0x51fb789e,0x27ba83dc },
- { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35,
- 0x87f3a4ab,0xadb62d34 } },
- /* 195 */
- { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7,
- 0x75e7c8b2,0xb990fd76 },
- { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a,
- 0x4d10d18d,0x81707ef9 } },
- /* 196 */
- { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4,
- 0xd5a8aa5c,0x3792daea },
- { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527,
- 0x94b001ba,0x5abd635e } },
- /* 197 */
- { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea,
- 0x846ab610,0x5995bf21 },
- { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44,
- 0xd483411e,0x44c32ca2 } },
- /* 198 */
- { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b,
- 0x8082a54c,0x1f2162fb },
- { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e,
- 0xc3e907c9,0x8f1d402b } },
- /* 199 */
- { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37,
- 0x926edbf9,0xb1980f43 },
- { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4,
- 0x37448e45,0x2828ad9b } },
- /* 200 */
- { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2,
- 0x5a14b390,0x4973f127 },
- { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f,
- 0xdb168ac7,0x6dac8ed0 } },
- /* 201 */
- { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0,
- 0x20b9de4c,0x4b23ef59 },
- { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863,
- 0xddf49a4e,0x4dd71534 } },
- /* 202 */
- { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8,
- 0x2f4a4dbb,0xfd317000 },
- { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976,
- 0x9569f365,0x14fac58c } },
- /* 203 */
- { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240,
- 0x36abda50,0xed7c7651 },
- { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075,
- 0x4d2e9f53,0xfefcb7f7 } },
- /* 204 */
- { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de,
- 0x87e0d80b,0x1801a57e },
- { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b,
- 0x1ead1064,0x9f8fc11e } },
- /* 205 */
- { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd,
- 0x3d3a69a9,0xa9d3809d },
- { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e,
- 0xe1178ef7,0x3006b9ae } },
- /* 206 */
- { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd,
- 0x45f8f761,0x0ab85fd7 },
- { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274,
- 0x11e942c2,0xb122d675 } },
- /* 207 */
- { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301,
- 0x097dbaec,0x9f599dc1 },
- { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4,
- 0x8a294b78,0x7d5528e0 } },
- /* 208 */
- { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b,
- 0x303f1730,0x28ccea01 },
- { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc,
- 0xa1d013bf,0xc18baf48 } },
- /* 209 */
- { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171,
- 0xb7a9596b,0x9def809d },
- { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d,
- 0x68808ce5,0x0357f8b0 } },
- /* 210 */
- { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874,
- 0x1b489887,0xe4a01add },
- { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71,
- 0xce10cc30,0x466d7d79 } },
- /* 211 */
- { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28,
- 0x451ead1a,0xc672a522 },
- { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680,
- 0xf2a67513,0x5e3d64fa } },
- /* 212 */
- { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a,
- 0xeb8e42fc,0x6c8a7a95 },
- { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738,
- 0xad82ca91,0x348ae422 } },
- /* 213 */
- { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782,
- 0xd9ef2d2e,0xc1074de0 },
- { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50,
- 0xc9e54ffc,0xfbadfbdb } },
- /* 214 */
- { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd,
- 0x83716fcd,0xb7f976b4 },
- { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760,
- 0xcafcc805,0xf4d41b2e } },
- /* 215 */
- { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974,
- 0xe0160f10,0x180824ea },
- { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34,
- 0x83cf6d25,0x67e5f639 } },
- /* 216 */
- { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276,
- 0x04c11fc6,0x9fef789a },
- { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0,
- 0xa99c4e20,0xbc80c181 } },
- /* 217 */
- { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171,
- 0x9f8cdf10,0x49270e62 },
- { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17,
- 0x61372f7f,0xd2ee52f9 } },
- /* 218 */
- { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5,
- 0xe5abb733,0xdfb478be },
- { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf,
- 0x08df473a,0xd9a140b4 } },
- /* 219 */
- { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391,
- 0x623f4b1a,0x760c058d },
- { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110,
- 0x8f190409,0x7141982d } },
- /* 220 */
- { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6,
- 0x89d54e47,0x3af9d1ce },
- { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc,
- 0x73957dd6,0xb1f815c3 } },
- /* 221 */
- { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d,
- 0x1543f052,0xa41aed14 },
- { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be,
- 0x86fb60ef,0xd6e9c1dd } },
- /* 222 */
- { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7,
- 0xae9bf8c2,0x9c9c6e10 },
- { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23,
- 0x40fa61b6,0x566bd596 } },
- /* 223 */
- { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0,
- 0xf525345e,0xcf2c7390 },
- { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a,
- 0x8aa20979,0x02f51755 } },
- /* 224 */
- { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac,
- 0xe8d4d97d,0x14e9ada5 },
- { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d,
- 0x8e9d9ae8,0xa0ad4fab } },
- /* 225 */
- { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737,
- 0x6e56ed1e,0xbcd530b8 },
- { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761,
- 0x6979341d,0x909283cf } },
- /* 226 */
- { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b,
- 0xace1549a,0x35eeb7c9 },
- { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c,
- 0x448ae864,0x9a8b2cf4 } },
- /* 227 */
- { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168,
- 0xd4491379,0x6bdb60f4 },
- { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741,
- 0x94ba08a9,0x01ec3cfd } },
- /* 228 */
- { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f,
- 0x475464f6,0xd1acb1c0 },
- { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813,
- 0x405626c2,0x7dcd079d } },
- /* 229 */
- { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971,
- 0x377d19b8,0x0bf53589 },
- { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6,
- 0xe16686fc,0xd28be4d9 } },
- /* 230 */
- { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa,
- 0x510f88ce,0xd76007aa },
- { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082,
- 0xb303bb01,0xf2b52f68 } },
- /* 231 */
- { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680,
- 0xcc5aed3a,0xd8dbe98e },
- { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd,
- 0xee559705,0xe01593a3 } },
- /* 232 */
- { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f,
- 0xaeb8ef06,0xafec07b1 },
- { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a,
- 0x6e2dbfdd,0xa71b9354 } },
- /* 233 */
- { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db,
- 0x628523d9,0x53a2005c },
- { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7,
- 0x3d588e3d,0xbf47d19b } },
- /* 234 */
- { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae,
- 0x39c9a1b6,0x001c2c7f },
- { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b,
- 0x86ffb99b,0xfdadf8e7 } },
- /* 235 */
- { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055,
- 0x5aa43c94,0x3a838e4d },
- { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6,
- 0x873e1da3,0x3cdb8257 } },
- /* 236 */
- { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2,
- 0xf1f57fba,0x5a60cc89 },
- { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8,
- 0xdbfd8fc0,0x922ff56f } },
- /* 237 */
- { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46,
- 0xf6c5cd62,0x72919a7d },
- { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77,
- 0x3624089a,0x5e791780 } },
- /* 238 */
- { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea,
- 0xe24c2fab,0x4e0a5371 },
- { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae,
- 0xd56604ee,0xf5ff7818 } },
- /* 239 */
- { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a,
- 0x533f5e64,0xe41df0e9 },
- { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192,
- 0xac4f155f,0x8edd7d6e } },
- /* 240 */
- { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c,
- 0xed8aee96,0x1432c1ca },
- { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5,
- 0x5ac8d2c6,0xcaef480b } },
- /* 241 */
- { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0,
- 0x8efae236,0xd0ba177e },
- { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605,
- 0x1c54ae16,0xf31c957c } },
- /* 242 */
- { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55,
- 0x96e17c3a,0x013404cb },
- { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682,
- 0x91933e6c,0x6f377c4b } },
- /* 243 */
- { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037,
- 0xd2d09506,0x6dba3e4e },
- { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752,
- 0x3becf4a7,0xf13cf342 } },
- /* 244 */
- { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6,
- 0x274bbad3,0xc83fa9a9 },
- { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e,
- 0x5d702683,0xb49d70f4 } },
- /* 245 */
- { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418,
- 0x0c30f1cf,0x59cfadbb },
- { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c,
- 0x354a4b67,0x5babf362 } },
- /* 246 */
- { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1,
- 0x9026c8f0,0x6188c6a7 },
- { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b,
- 0xdf50b9d9,0x993fe475 } },
- /* 247 */
- { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a,
- 0x4c80616b,0x81f76466 },
- { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04,
- 0x5fe9060d,0x564a812a } },
- /* 248 */
- { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f,
- 0x00e51d6c,0x226bf3cf },
- { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49,
- 0xff257836,0x68779f47 } },
- /* 249 */
- { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28,
- 0xeb092e0b,0x97bcb0d1 },
- { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3,
- 0x0a784655,0xa872ffe8 } },
- /* 250 */
- { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91,
- 0xb732a36a,0x02812bfc },
- { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398,
- 0xfe5396af,0x07391cc9 } },
- /* 251 */
- { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8,
- 0x7e6d2a08,0x355d2adc },
- { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd,
- 0x7c2a3a79,0x3dc2b1e3 } },
- /* 252 */
- { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590,
- 0x3ccd846b,0xc4786910 },
- { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5,
- 0xd5bb4d32,0xccc42968 } },
- /* 253 */
- { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640,
- 0xaa4871cf,0xe147eb42 },
- { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47,
- 0x080e96e3,0x239ac047 } },
- /* 254 */
- { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e,
- 0xf5f7e59d,0xc55fa1a3 },
- { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998,
- 0xd4f4b699,0x094cd99c } },
- /* 255 */
- { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9,
- 0x42abad33,0xb90a30b6 },
- { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc,
- 0x1b7924f7,0x019f8b9a } },
- };
- /* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * r Resulting point.
- * k Scalar to multiply by.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- static int sp_256_ecc_mulmod_base_8(sp_point* r, const sp_digit* k,
- int map, void* heap)
- {
- return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table,
- k, map, heap);
- }
- #endif
- /* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine coordinates.
- *
- * km Scalar to multiply by.
- * r Resulting point.
- * map Indicates whether to convert result to affine.
- * heap Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point p;
- sp_digit k[8];
- #else
- sp_digit* k = NULL;
- #endif
- sp_point* point;
- int err;
- err = sp_ecc_point_new(heap, p, point);
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
- DYNAMIC_TYPE_ECC);
- if (k == NULL) {
- err = MEMORY_E;
- }
- }
- #endif
- if (err == MP_OKAY) {
- sp_256_from_mp(k, 8, km);
- err = sp_256_ecc_mulmod_base_8(point, k, map, heap);
- }
- if (err == MP_OKAY) {
- err = sp_256_point_to_ecc_point_8(point, r);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (k != NULL) {
- XFREE(k, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(point, 0, heap);
- return err;
- }
- #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
- defined(HAVE_ECC_VERIFY)
- /* Returns 1 if the number of zero.
- * Implementation is constant time.
- *
- * a Number to check.
- * returns 1 if the number is zero and 0 otherwise.
- */
- static int sp_256_iszero_8(const sp_digit* a)
- {
- return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0;
- }
- #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
- /* Add 1 to a. (a = a + 1)
- *
- * a A single precision integer.
- */
- SP_NOINLINE static void sp_256_add_one_8(sp_digit* a)
- {
- __asm__ __volatile__ (
- "mov r2, #1\n\t"
- "ldr r1, [%[a], #0]\n\t"
- "add r1, r2\n\t"
- "mov r2, #0\n\t"
- "str r1, [%[a], #0]\n\t"
- "ldr r1, [%[a], #4]\n\t"
- "adc r1, r2\n\t"
- "str r1, [%[a], #4]\n\t"
- "ldr r1, [%[a], #8]\n\t"
- "adc r1, r2\n\t"
- "str r1, [%[a], #8]\n\t"
- "ldr r1, [%[a], #12]\n\t"
- "adc r1, r2\n\t"
- "str r1, [%[a], #12]\n\t"
- "ldr r1, [%[a], #16]\n\t"
- "adc r1, r2\n\t"
- "str r1, [%[a], #16]\n\t"
- "ldr r1, [%[a], #20]\n\t"
- "adc r1, r2\n\t"
- "str r1, [%[a], #20]\n\t"
- "ldr r1, [%[a], #24]\n\t"
- "adc r1, r2\n\t"
- "str r1, [%[a], #24]\n\t"
- "ldr r1, [%[a], #28]\n\t"
- "adc r1, r2\n\t"
- "str r1, [%[a], #28]\n\t"
- :
- : [a] "r" (a)
- : "memory", "r1", "r2"
- );
- }
- /* Read big endian unsigned byte array into r.
- *
- * r A single precision integer.
- * size Maximum number of bytes to convert
- * a Byte array.
- * n Number of bytes in array to read.
- */
- static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n)
- {
- int i, j = 0;
- word32 s = 0;
- r[0] = 0;
- for (i = n-1; i >= 0; i--) {
- r[j] |= (((sp_digit)a[i]) << s);
- if (s >= 24U) {
- r[j] &= 0xffffffff;
- s = 32U - s;
- if (j + 1 >= size) {
- break;
- }
- r[++j] = (sp_digit)a[i] >> s;
- s = 8U - s;
- }
- else {
- s += 8U;
- }
- }
- for (j++; j < size; j++) {
- r[j] = 0;
- }
- }
- /* Generates a scalar that is in the range 1..order-1.
- *
- * rng Random number generator.
- * k Scalar value.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
- static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k)
- {
- int err;
- byte buf[32];
- do {
- err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
- if (err == 0) {
- sp_256_from_bin(k, 8, buf, (int)sizeof(buf));
- if (sp_256_cmp_8(k, p256_order2) < 0) {
- sp_256_add_one_8(k);
- break;
- }
- }
- }
- while (err == 0);
- return err;
- }
- /* Makes a random EC key pair.
- *
- * rng Random number generator.
- * priv Generated private value.
- * pub Generated public point.
- * heap Heap to use for allocation.
- * returns ECC_INF_E when the point does not have the correct order, RNG
- * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point p;
- sp_digit k[8];
- #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
- sp_point inf;
- #endif
- #else
- sp_digit* k = NULL;
- #endif
- sp_point* point;
- #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
- sp_point* infinity;
- #endif
- int err;
- (void)heap;
- err = sp_ecc_point_new(heap, p, point);
- #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, inf, infinity);
- }
- #endif
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
- DYNAMIC_TYPE_ECC);
- if (k == NULL) {
- err = MEMORY_E;
- }
- }
- #endif
- if (err == MP_OKAY) {
- err = sp_256_ecc_gen_k_8(rng, k);
- }
- if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL);
- }
- #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
- if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL);
- }
- if (err == MP_OKAY) {
- if ((sp_256_iszero_8(point->x) == 0) || (sp_256_iszero_8(point->y) == 0)) {
- err = ECC_INF_E;
- }
- }
- #endif
- if (err == MP_OKAY) {
- err = sp_256_to_mp(k, priv);
- }
- if (err == MP_OKAY) {
- err = sp_256_point_to_ecc_point_8(point, pub);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (k != NULL) {
- XFREE(k, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
- sp_ecc_point_free(infinity, 1, heap);
- #endif
- sp_ecc_point_free(point, 1, heap);
- return err;
- }
- #ifdef HAVE_ECC_DHE
- /* Write r as big endian to byte array.
- * Fixed length number of bytes written: 32
- *
- * r A single precision integer.
- * a Byte array.
- */
- static void sp_256_to_bin(sp_digit* r, byte* a)
- {
- int i, j, s = 0, b;
- j = 256 / 8 - 1;
- a[j] = 0;
- for (i=0; i<8 && j>=0; i++) {
- b = 0;
- /* lint allow cast of mismatch sp_digit and int */
- a[j--] |= (byte)(r[i] << s); b += 8 - s; /*lint !e9033*/
- if (j < 0) {
- break;
- }
- while (b < 32) {
- a[j--] = r[i] >> b; b += 8;
- if (j < 0) {
- break;
- }
- }
- s = 8 - (b - 32);
- if (j >= 0) {
- a[j] = 0;
- }
- if (s != 0) {
- j++;
- }
- }
- }
- /* Multiply the point by the scalar and serialize the X ordinate.
- * The number is 0 padded to maximum size on output.
- *
- * priv Scalar to multiply the point by.
- * pub Point to multiply.
- * out Buffer to hold X ordinate.
- * outLen On entry, size of the buffer in bytes.
- * On exit, length of data in buffer in bytes.
- * heap Heap to use for allocation.
- * returns BUFFER_E if the buffer is to small for output size,
- * MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
- int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
- word32* outLen, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point p;
- sp_digit k[8];
- #else
- sp_digit* k = NULL;
- #endif
- sp_point* point = NULL;
- int err = MP_OKAY;
- if (*outLen < 32U) {
- err = BUFFER_E;
- }
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, p, point);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
- DYNAMIC_TYPE_ECC);
- if (k == NULL)
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- sp_256_from_mp(k, 8, priv);
- sp_256_point_from_ecc_point_8(point, pub);
- err = sp_256_ecc_mulmod_8(point, point, k, 1, heap);
- }
- if (err == MP_OKAY) {
- sp_256_to_bin(point->x, out);
- *outLen = 32;
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (k != NULL) {
- XFREE(k, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(point, 0, heap);
- return err;
- }
- #endif /* HAVE_ECC_DHE */
- #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
- #endif
- #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
- #ifdef WOLFSSL_SP_SMALL
- /* Sub b from a into a. (a -= b)
- *
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "mov r7, %[a]\n\t"
- "add r7, #32\n\t"
- "\n1:\n\t"
- "mov r5, #0\n\t"
- "sub r5, %[c]\n\t"
- "ldr r3, [%[a]]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b]]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a]]\n\t"
- "str r4, [%[a], #4]\n\t"
- "sbc %[c], %[c]\n\t"
- "add %[a], #8\n\t"
- "add %[b], #8\n\t"
- "cmp %[a], r7\n\t"
- "bne 1b\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6", "r7"
- );
- return c;
- }
- #else
- /* Sub b from a into r. (r = a - b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision integer.
- */
- SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a,
- const sp_digit* b)
- {
- sp_digit c = 0;
- __asm__ __volatile__ (
- "ldr r3, [%[a], #0]\n\t"
- "ldr r4, [%[a], #4]\n\t"
- "ldr r5, [%[b], #0]\n\t"
- "ldr r6, [%[b], #4]\n\t"
- "sub r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #0]\n\t"
- "str r4, [%[a], #4]\n\t"
- "ldr r3, [%[a], #8]\n\t"
- "ldr r4, [%[a], #12]\n\t"
- "ldr r5, [%[b], #8]\n\t"
- "ldr r6, [%[b], #12]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #8]\n\t"
- "str r4, [%[a], #12]\n\t"
- "ldr r3, [%[a], #16]\n\t"
- "ldr r4, [%[a], #20]\n\t"
- "ldr r5, [%[b], #16]\n\t"
- "ldr r6, [%[b], #20]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #16]\n\t"
- "str r4, [%[a], #20]\n\t"
- "ldr r3, [%[a], #24]\n\t"
- "ldr r4, [%[a], #28]\n\t"
- "ldr r5, [%[b], #24]\n\t"
- "ldr r6, [%[b], #28]\n\t"
- "sbc r3, r5\n\t"
- "sbc r4, r6\n\t"
- "str r3, [%[a], #24]\n\t"
- "str r4, [%[a], #28]\n\t"
- "sbc %[c], %[c]\n\t"
- : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
- :
- : "memory", "r3", "r4", "r5", "r6"
- );
- return c;
- }
- #endif /* WOLFSSL_SP_SMALL */
- /* Mul a by digit b into r. (r = a * b)
- *
- * r A single precision integer.
- * a A single precision integer.
- * b A single precision digit.
- */
- SP_NOINLINE static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a,
- sp_digit b)
- {
- __asm__ __volatile__ (
- "mov r6, #32\n\t"
- "add r6, %[a]\n\t"
- "mov r8, %[r]\n\t"
- "mov r9, r6\n\t"
- "mov r3, #0\n\t"
- "mov r4, #0\n\t"
- "1:\n\t"
- "mov %[r], #0\n\t"
- "mov r5, #0\n\t"
- "# A[] * B\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsl r6, r6, #16\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r7, r6\n\t"
- "add r3, r7\n\t"
- "adc r4, %[r]\n\t"
- "adc r5, %[r]\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "ldr r6, [%[a]]\n\t"
- "lsr r6, r6, #16\n\t"
- "lsr r7, %[b], #16\n\t"
- "mul r7, r6\n\t"
- "add r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "lsl r7, %[b], #16\n\t"
- "lsr r7, r7, #16\n\t"
- "mul r6, r7\n\t"
- "lsr r7, r6, #16\n\t"
- "lsl r6, r6, #16\n\t"
- "add r3, r6\n\t"
- "adc r4, r7\n\t"
- "adc r5, %[r]\n\t"
- "# A[] * B - Done\n\t"
- "mov %[r], r8\n\t"
- "str r3, [%[r]]\n\t"
- "mov r3, r4\n\t"
- "mov r4, r5\n\t"
- "add %[r], #4\n\t"
- "add %[a], #4\n\t"
- "mov r8, %[r]\n\t"
- "cmp %[a], r9\n\t"
- "blt 1b\n\t"
- "str r3, [%[r]]\n\t"
- : [r] "+r" (r), [a] "+r" (a)
- : [b] "r" (b)
- : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
- );
- }
- /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1 The high order half of the number to divide.
- * d0 The low order half of the number to divide.
- * div The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
- SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0,
- sp_digit div)
- {
- sp_digit r = 0;
- __asm__ __volatile__ (
- "lsr r5, %[div], #1\n\t"
- "add r5, #1\n\t"
- "mov r8, %[d0]\n\t"
- "mov r9, %[d1]\n\t"
- "# Do top 32\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "# Next 30 bits\n\t"
- "mov r4, #29\n\t"
- "1:\n\t"
- "lsl %[d0], %[d0], #1\n\t"
- "adc %[d1], %[d1]\n\t"
- "mov r6, r5\n\t"
- "sub r6, %[d1]\n\t"
- "sbc r6, r6\n\t"
- "add %[r], %[r]\n\t"
- "sub %[r], r6\n\t"
- "and r6, r5\n\t"
- "sub %[d1], r6\n\t"
- "sub r4, #1\n\t"
- "bpl 1b\n\t"
- "mov r7, #0\n\t"
- "add %[r], %[r]\n\t"
- "add %[r], #1\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "sub %[d1], r4\n\t"
- "mov r4, %[d1]\n\t"
- "mov %[d1], r9\n\t"
- "sbc %[d1], r5\n\t"
- "mov r5, %[d1]\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "# r * div - Start\n\t"
- "lsl %[d1], %[r], #16\n\t"
- "lsl r4, %[div], #16\n\t"
- "lsr %[d1], %[d1], #16\n\t"
- "lsr r4, r4, #16\n\t"
- "mul r4, %[d1]\n\t"
- "lsr r6, %[div], #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r5, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r7\n\t"
- "lsr %[d1], %[r], #16\n\t"
- "mul r6, %[d1]\n\t"
- "add r5, r6\n\t"
- "lsl r6, %[div], #16\n\t"
- "lsr r6, r6, #16\n\t"
- "mul %[d1], r6\n\t"
- "lsr r6, %[d1], #16\n\t"
- "lsl %[d1], %[d1], #16\n\t"
- "add r4, %[d1]\n\t"
- "adc r5, r6\n\t"
- "# r * div - Done\n\t"
- "mov %[d1], r8\n\t"
- "mov r6, r9\n\t"
- "sub r4, %[d1], r4\n\t"
- "sbc r6, r5\n\t"
- "mov r5, r6\n\t"
- "add %[r], r5\n\t"
- "mov r6, %[div]\n\t"
- "sub r6, r4\n\t"
- "sbc r6, r6\n\t"
- "sub %[r], r6\n\t"
- : [r] "+r" (r)
- : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
- : "r4", "r5", "r7", "r6", "r8", "r9"
- );
- return r;
- }
- /* AND m into each word of a and store in r.
- *
- * r A single precision integer.
- * a A single precision integer.
- * m Mask to AND against each digit.
- */
- static void sp_256_mask_8(sp_digit* r, const sp_digit* a, sp_digit m)
- {
- #ifdef WOLFSSL_SP_SMALL
- int i;
- for (i=0; i<8; i++) {
- r[i] = a[i] & m;
- }
- #else
- r[0] = a[0] & m;
- r[1] = a[1] & m;
- r[2] = a[2] & m;
- r[3] = a[3] & m;
- r[4] = a[4] & m;
- r[5] = a[5] & m;
- r[6] = a[6] & m;
- r[7] = a[7] & m;
- #endif
- }
- /* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a Nmber to be divided.
- * d Number to divide with.
- * m Multiplier result.
- * r Remainder from the division.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_256_div_8(const sp_digit* a, const sp_digit* d, sp_digit* m,
- sp_digit* r)
- {
- sp_digit t1[16], t2[9];
- sp_digit div, r1;
- int i;
- (void)m;
- div = d[7];
- XMEMCPY(t1, a, sizeof(*t1) * 2 * 8);
- for (i=7; i>=0; i--) {
- r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div);
- sp_256_mul_d_8(t2, d, r1);
- t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2);
- t1[8 + i] -= t2[8];
- sp_256_mask_8(t2, d, t1[8 + i]);
- t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2);
- sp_256_mask_8(t2, d, t1[8 + i]);
- t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2);
- }
- r1 = sp_256_cmp_8(t1, d) >= 0;
- sp_256_cond_sub_8(r, t1, d, (sp_digit)0 - r1);
- return MP_OKAY;
- }
- /* Reduce a modulo m into r. (r = a mod m)
- *
- * r A single precision number that is the reduced result.
- * a A single precision number that is to be reduced.
- * m A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
- static WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
- {
- return sp_256_div_8(a, m, NULL, r);
- }
- #endif
- #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
- #ifdef WOLFSSL_SP_SMALL
- /* Order-2 for the P256 curve. */
- static const uint32_t p256_order_2[8] = {
- 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU,
- 0x00000000U,0xffffffffU
- };
- #else
- /* The low half of the order-2 of the P256 curve. */
- static const uint32_t p256_order_low[4] = {
- 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU
- };
- #endif /* WOLFSSL_SP_SMALL */
- /* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r Result of the multiplication.
- * a First operand of the multiplication.
- * b Second operand of the multiplication.
- */
- static void sp_256_mont_mul_order_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
- {
- sp_256_mul_8(r, a, b);
- sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order);
- }
- /* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r Result of the squaring.
- * a Number to square.
- */
- static void sp_256_mont_sqr_order_8(sp_digit* r, const sp_digit* a)
- {
- sp_256_sqr_8(r, a);
- sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order);
- }
- #ifndef WOLFSSL_SP_SMALL
- /* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r Result of the squaring.
- * a Number to square.
- */
- static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n)
- {
- int i;
- sp_256_mont_sqr_order_8(r, a);
- for (i=1; i<n; i++) {
- sp_256_mont_sqr_order_8(r, r);
- }
- }
- #endif /* !WOLFSSL_SP_SMALL */
- /* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r Inverse result.
- * a Number to invert.
- * td Temporary data.
- */
- static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
- sp_digit* td)
- {
- #ifdef WOLFSSL_SP_SMALL
- sp_digit* t = td;
- int i;
- XMEMCPY(t, a, sizeof(sp_digit) * 8);
- for (i=254; i>=0; i--) {
- sp_256_mont_sqr_order_8(t, t);
- if ((p256_order_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
- sp_256_mont_mul_order_8(t, t, a);
- }
- }
- XMEMCPY(r, t, sizeof(sp_digit) * 8U);
- #else
- sp_digit* t = td;
- sp_digit* t2 = td + 2 * 8;
- sp_digit* t3 = td + 4 * 8;
- int i;
- /* t = a^2 */
- sp_256_mont_sqr_order_8(t, a);
- /* t = a^3 = t * a */
- sp_256_mont_mul_order_8(t, t, a);
- /* t2= a^c = t ^ 2 ^ 2 */
- sp_256_mont_sqr_n_order_8(t2, t, 2);
- /* t3= a^f = t2 * t */
- sp_256_mont_mul_order_8(t3, t2, t);
- /* t2= a^f0 = t3 ^ 2 ^ 4 */
- sp_256_mont_sqr_n_order_8(t2, t3, 4);
- /* t = a^ff = t2 * t3 */
- sp_256_mont_mul_order_8(t, t2, t3);
- /* t3= a^ff00 = t ^ 2 ^ 8 */
- sp_256_mont_sqr_n_order_8(t2, t, 8);
- /* t = a^ffff = t2 * t */
- sp_256_mont_mul_order_8(t, t2, t);
- /* t2= a^ffff0000 = t ^ 2 ^ 16 */
- sp_256_mont_sqr_n_order_8(t2, t, 16);
- /* t = a^ffffffff = t2 * t */
- sp_256_mont_mul_order_8(t, t2, t);
- /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */
- sp_256_mont_sqr_n_order_8(t2, t, 64);
- /* t2= a^ffffffff00000000ffffffff = t2 * t */
- sp_256_mont_mul_order_8(t2, t2, t);
- /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */
- sp_256_mont_sqr_n_order_8(t2, t2, 32);
- /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
- sp_256_mont_mul_order_8(t2, t2, t);
- /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
- for (i=127; i>=112; i--) {
- sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
- sp_256_mont_mul_order_8(t2, t2, a);
- }
- }
- /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
- sp_256_mont_sqr_n_order_8(t2, t2, 4);
- sp_256_mont_mul_order_8(t2, t2, t3);
- /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
- for (i=107; i>=64; i--) {
- sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
- sp_256_mont_mul_order_8(t2, t2, a);
- }
- }
- /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
- sp_256_mont_sqr_n_order_8(t2, t2, 4);
- sp_256_mont_mul_order_8(t2, t2, t3);
- /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
- for (i=59; i>=32; i--) {
- sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
- sp_256_mont_mul_order_8(t2, t2, a);
- }
- }
- /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
- sp_256_mont_sqr_n_order_8(t2, t2, 4);
- sp_256_mont_mul_order_8(t2, t2, t3);
- /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
- for (i=27; i>=0; i--) {
- sp_256_mont_sqr_order_8(t2, t2);
- if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
- sp_256_mont_mul_order_8(t2, t2, a);
- }
- }
- /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
- sp_256_mont_sqr_n_order_8(t2, t2, 4);
- /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
- sp_256_mont_mul_order_8(r, t2, t3);
- #endif /* WOLFSSL_SP_SMALL */
- }
- #endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
- #ifdef HAVE_ECC_SIGN
- #ifndef SP_ECC_MAX_SIG_GEN
- #define SP_ECC_MAX_SIG_GEN 64
- #endif
- /* Sign the hash using the private key.
- * e = [hash, 256 bits] from binary
- * r = (k.G)->x mod order
- * s = (r * x + e) / k mod order
- * The hash is truncated to the first 256 bits.
- *
- * hash Hash to sign.
- * hashLen Length of the hash data.
- * rng Random number generator.
- * priv Private part of key - scalar.
- * rm First part of result as an mp_int.
- * sm Sirst part of result as an mp_int.
- * heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
- int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
- mp_int* rm, mp_int* sm, mp_int* km, void* heap)
- {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- sp_digit* d = NULL;
- #else
- sp_digit ed[2*8];
- sp_digit xd[2*8];
- sp_digit kd[2*8];
- sp_digit rd[2*8];
- sp_digit td[3 * 2*8];
- sp_point p;
- #endif
- sp_digit* e = NULL;
- sp_digit* x = NULL;
- sp_digit* k = NULL;
- sp_digit* r = NULL;
- sp_digit* tmp = NULL;
- sp_point* point = NULL;
- sp_digit carry;
- sp_digit* s = NULL;
- sp_digit* kInv = NULL;
- int err;
- int32_t c;
- int i;
- (void)heap;
- err = sp_ecc_point_new(heap, p, point);
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap,
- DYNAMIC_TYPE_ECC);
- if (d == NULL) {
- err = MEMORY_E;
- }
- }
- #endif
- if (err == MP_OKAY) {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- e = d + 0 * 8;
- x = d + 2 * 8;
- k = d + 4 * 8;
- r = d + 6 * 8;
- tmp = d + 8 * 8;
- #else
- e = ed;
- x = xd;
- k = kd;
- r = rd;
- tmp = td;
- #endif
- s = e;
- kInv = k;
- if (hashLen > 32U) {
- hashLen = 32U;
- }
- sp_256_from_bin(e, 8, hash, (int)hashLen);
- }
- for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
- sp_256_from_mp(x, 8, priv);
- /* New random point. */
- if (km == NULL || mp_iszero(km)) {
- err = sp_256_ecc_gen_k_8(rng, k);
- }
- else {
- sp_256_from_mp(k, 8, km);
- mp_zero(km);
- }
- if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL);
- }
- if (err == MP_OKAY) {
- /* r = point->x mod order */
- XMEMCPY(r, point->x, sizeof(sp_digit) * 8U);
- sp_256_norm_8(r);
- c = sp_256_cmp_8(r, p256_order);
- sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0));
- sp_256_norm_8(r);
- /* Conv k to Montgomery form (mod order) */
- sp_256_mul_8(k, k, p256_norm_order);
- err = sp_256_mod_8(k, k, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(k);
- /* kInv = 1/k mod order */
- sp_256_mont_inv_order_8(kInv, k, tmp);
- sp_256_norm_8(kInv);
- /* s = r * x + e */
- sp_256_mul_8(x, x, r);
- err = sp_256_mod_8(x, x, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(x);
- carry = sp_256_add_8(s, e, x);
- sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
- sp_256_norm_8(s);
- c = sp_256_cmp_8(s, p256_order);
- sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0));
- sp_256_norm_8(s);
- /* s = s * k^-1 mod order */
- sp_256_mont_mul_order_8(s, s, kInv);
- sp_256_norm_8(s);
- /* Check that signature is usable. */
- if (sp_256_iszero_8(s) == 0) {
- break;
- }
- }
- }
- if (i == 0) {
- err = RNG_FAILURE_E;
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(r, rm);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(s, sm);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL) {
- XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8);
- XFREE(d, heap, DYNAMIC_TYPE_ECC);
- }
- #else
- XMEMSET(e, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U);
- XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U);
- #endif
- sp_ecc_point_free(point, 1, heap);
- return err;
- }
- #endif /* HAVE_ECC_SIGN */
- #ifdef HAVE_ECC_VERIFY
- /* Verify the signature values with the hash and public key.
- * e = Truncate(hash, 256)
- * u1 = e/s mod order
- * u2 = r/s mod order
- * r == (u1.G + u2.Q)->x mod order
- * Optimization: Leave point in projective form.
- * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
- * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
- * The hash is truncated to the first 256 bits.
- *
- * hash Hash to sign.
- * hashLen Length of the hash data.
- * rng Random number generator.
- * priv Private part of key - scalar.
- * rm First part of result as an mp_int.
- * sm Sirst part of result as an mp_int.
- * heap Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
- int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
- mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
- {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- sp_digit* d = NULL;
- #else
- sp_digit u1d[2*8];
- sp_digit u2d[2*8];
- sp_digit sd[2*8];
- sp_digit tmpd[2*8 * 5];
- sp_point p1d;
- sp_point p2d;
- #endif
- sp_digit* u1 = NULL;
- sp_digit* u2 = NULL;
- sp_digit* s = NULL;
- sp_digit* tmp = NULL;
- sp_point* p1;
- sp_point* p2 = NULL;
- sp_digit carry;
- int32_t c;
- int err;
- err = sp_ecc_point_new(heap, p1d, p1);
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, p2d, p2);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap,
- DYNAMIC_TYPE_ECC);
- if (d == NULL) {
- err = MEMORY_E;
- }
- }
- #endif
- if (err == MP_OKAY) {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- u1 = d + 0 * 8;
- u2 = d + 2 * 8;
- s = d + 4 * 8;
- tmp = d + 6 * 8;
- #else
- u1 = u1d;
- u2 = u2d;
- s = sd;
- tmp = tmpd;
- #endif
- if (hashLen > 32U) {
- hashLen = 32U;
- }
- sp_256_from_bin(u1, 8, hash, (int)hashLen);
- sp_256_from_mp(u2, 8, r);
- sp_256_from_mp(s, 8, sm);
- sp_256_from_mp(p2->x, 8, pX);
- sp_256_from_mp(p2->y, 8, pY);
- sp_256_from_mp(p2->z, 8, pZ);
- {
- sp_256_mul_8(s, s, p256_norm_order);
- }
- err = sp_256_mod_8(s, s, p256_order);
- }
- if (err == MP_OKAY) {
- sp_256_norm_8(s);
- {
- sp_256_mont_inv_order_8(s, s, tmp);
- sp_256_mont_mul_order_8(u1, u1, s);
- sp_256_mont_mul_order_8(u2, u2, s);
- }
- err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap);
- }
- if (err == MP_OKAY) {
- err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap);
- }
- if (err == MP_OKAY) {
- {
- sp_256_proj_point_add_8(p1, p1, p2, tmp);
- if (sp_256_iszero_8(p1->z)) {
- if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
- sp_256_proj_point_dbl_8(p1, p2, tmp);
- }
- else {
- /* Y ordinate is not used from here - don't set. */
- p1->x[0] = 0;
- p1->x[1] = 0;
- p1->x[2] = 0;
- p1->x[3] = 0;
- p1->x[4] = 0;
- p1->x[5] = 0;
- p1->x[6] = 0;
- p1->x[7] = 0;
- XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
- }
- }
- }
- /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
- /* Reload r and convert to Montgomery form. */
- sp_256_from_mp(u2, 8, r);
- err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
- }
- if (err == MP_OKAY) {
- /* u1 = r.z'.z' mod prime */
- sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod);
- *res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
- if (*res == 0) {
- /* Reload r and add order. */
- sp_256_from_mp(u2, 8, r);
- carry = sp_256_add_8(u2, u2, p256_order);
- /* Carry means result is greater than mod and is not valid. */
- if (carry == 0) {
- sp_256_norm_8(u2);
- /* Compare with mod and if greater or equal then not valid. */
- c = sp_256_cmp_8(u2, p256_mod);
- if (c < 0) {
- /* Convert to Montogomery form */
- err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
- if (err == MP_OKAY) {
- /* u1 = (r + 1*order).z'.z' mod prime */
- sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
- p256_mp_mod);
- *res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
- }
- }
- }
- }
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL)
- XFREE(d, heap, DYNAMIC_TYPE_ECC);
- #endif
- sp_ecc_point_free(p1, 0, heap);
- sp_ecc_point_free(p2, 0, heap);
- return err;
- }
- #endif /* HAVE_ECC_VERIFY */
- #ifdef HAVE_ECC_CHECK_KEY
- /* Check that the x and y oridinates are a valid point on the curve.
- *
- * point EC point.
- * heap Heap to use if dynamically allocating.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
- static int sp_256_ecc_is_point_8(sp_point* point, void* heap)
- {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- sp_digit* d;
- #else
- sp_digit t1d[2*8];
- sp_digit t2d[2*8];
- #endif
- sp_digit* t1;
- sp_digit* t2;
- int err = MP_OKAY;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC);
- if (d == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- t1 = d + 0 * 8;
- t2 = d + 2 * 8;
- #else
- (void)heap;
- t1 = t1d;
- t2 = t2d;
- #endif
- sp_256_sqr_8(t1, point->y);
- (void)sp_256_mod_8(t1, t1, p256_mod);
- sp_256_sqr_8(t2, point->x);
- (void)sp_256_mod_8(t2, t2, p256_mod);
- sp_256_mul_8(t2, t2, point->x);
- (void)sp_256_mod_8(t2, t2, p256_mod);
- (void)sp_256_sub_8(t2, p256_mod, t2);
- sp_256_mont_add_8(t1, t1, t2, p256_mod);
- sp_256_mont_add_8(t1, t1, point->x, p256_mod);
- sp_256_mont_add_8(t1, t1, point->x, p256_mod);
- sp_256_mont_add_8(t1, t1, point->x, p256_mod);
- if (sp_256_cmp_8(t1, p256_b) != 0) {
- err = MP_VAL;
- }
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL) {
- XFREE(d, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- return err;
- }
- /* Check that the x and y oridinates are a valid point on the curve.
- *
- * pX X ordinate of EC point.
- * pY Y ordinate of EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
- int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_point pubd;
- #endif
- sp_point* pub;
- byte one[1] = { 1 };
- int err;
- err = sp_ecc_point_new(NULL, pubd, pub);
- if (err == MP_OKAY) {
- sp_256_from_mp(pub->x, 8, pX);
- sp_256_from_mp(pub->y, 8, pY);
- sp_256_from_bin(pub->z, 8, one, (int)sizeof(one));
- err = sp_256_ecc_is_point_8(pub, NULL);
- }
- sp_ecc_point_free(pub, 0, NULL);
- return err;
- }
- /* Check that the private scalar generates the EC point (px, py), the point is
- * on the curve and the point has the correct order.
- *
- * pX X ordinate of EC point.
- * pY Y ordinate of EC point.
- * privm Private scalar that generates EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve, ECC_INF_E if the point does not have the correct order,
- * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
- * MP_OKAY otherwise.
- */
- int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit privd[8];
- sp_point pubd;
- sp_point pd;
- #endif
- sp_digit* priv = NULL;
- sp_point* pub;
- sp_point* p = NULL;
- byte one[1] = { 1 };
- int err;
- err = sp_ecc_point_new(heap, pubd, pub);
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(heap, pd, p);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
- DYNAMIC_TYPE_ECC);
- if (priv == NULL) {
- err = MEMORY_E;
- }
- }
- #endif
- if (err == MP_OKAY) {
- #if !(defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK))
- priv = privd;
- #endif
- sp_256_from_mp(pub->x, 8, pX);
- sp_256_from_mp(pub->y, 8, pY);
- sp_256_from_bin(pub->z, 8, one, (int)sizeof(one));
- sp_256_from_mp(priv, 8, privm);
- /* Check point at infinitiy. */
- if ((sp_256_iszero_8(pub->x) != 0) &&
- (sp_256_iszero_8(pub->y) != 0)) {
- err = ECC_INF_E;
- }
- }
- if (err == MP_OKAY) {
- /* Check range of X and Y */
- if (sp_256_cmp_8(pub->x, p256_mod) >= 0 ||
- sp_256_cmp_8(pub->y, p256_mod) >= 0) {
- err = ECC_OUT_OF_RANGE_E;
- }
- }
- if (err == MP_OKAY) {
- /* Check point is on curve */
- err = sp_256_ecc_is_point_8(pub, heap);
- }
- if (err == MP_OKAY) {
- /* Point * order = infinity */
- err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap);
- }
- if (err == MP_OKAY) {
- /* Check result is infinity */
- if ((sp_256_iszero_8(p->x) == 0) ||
- (sp_256_iszero_8(p->y) == 0)) {
- err = ECC_INF_E;
- }
- }
- if (err == MP_OKAY) {
- /* Base * private = point */
- err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap);
- }
- if (err == MP_OKAY) {
- /* Check result is public key */
- if (sp_256_cmp_8(p->x, pub->x) != 0 ||
- sp_256_cmp_8(p->y, pub->y) != 0) {
- err = ECC_PRIV_KEY_E;
- }
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (priv != NULL) {
- XFREE(priv, heap, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(p, 0, heap);
- sp_ecc_point_free(pub, 0, heap);
- return err;
- }
- #endif
- #ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
- /* Add two projective EC points together.
- * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
- *
- * pX First EC point's X ordinate.
- * pY First EC point's Y ordinate.
- * pZ First EC point's Z ordinate.
- * qX Second EC point's X ordinate.
- * qY Second EC point's Y ordinate.
- * qZ Second EC point's Z ordinate.
- * rX Resultant EC point's X ordinate.
- * rY Resultant EC point's Y ordinate.
- * rZ Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
- int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
- mp_int* qX, mp_int* qY, mp_int* qZ,
- mp_int* rX, mp_int* rY, mp_int* rZ)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit tmpd[2 * 8 * 5];
- sp_point pd;
- sp_point qd;
- #endif
- sp_digit* tmp;
- sp_point* p;
- sp_point* q = NULL;
- int err;
- err = sp_ecc_point_new(NULL, pd, p);
- if (err == MP_OKAY) {
- err = sp_ecc_point_new(NULL, qd, q);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL,
- DYNAMIC_TYPE_ECC);
- if (tmp == NULL) {
- err = MEMORY_E;
- }
- }
- #else
- tmp = tmpd;
- #endif
- if (err == MP_OKAY) {
- sp_256_from_mp(p->x, 8, pX);
- sp_256_from_mp(p->y, 8, pY);
- sp_256_from_mp(p->z, 8, pZ);
- sp_256_from_mp(q->x, 8, qX);
- sp_256_from_mp(q->y, 8, qY);
- sp_256_from_mp(q->z, 8, qZ);
- sp_256_proj_point_add_8(p, p, q, tmp);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->x, rX);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->y, rY);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->z, rZ);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (tmp != NULL) {
- XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(q, 0, NULL);
- sp_ecc_point_free(p, 0, NULL);
- return err;
- }
- /* Double a projective EC point.
- * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
- *
- * pX EC point's X ordinate.
- * pY EC point's Y ordinate.
- * pZ EC point's Z ordinate.
- * rX Resultant EC point's X ordinate.
- * rY Resultant EC point's Y ordinate.
- * rZ Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
- int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
- mp_int* rX, mp_int* rY, mp_int* rZ)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit tmpd[2 * 8 * 2];
- sp_point pd;
- #endif
- sp_digit* tmp;
- sp_point* p;
- int err;
- err = sp_ecc_point_new(NULL, pd, p);
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL,
- DYNAMIC_TYPE_ECC);
- if (tmp == NULL) {
- err = MEMORY_E;
- }
- }
- #else
- tmp = tmpd;
- #endif
- if (err == MP_OKAY) {
- sp_256_from_mp(p->x, 8, pX);
- sp_256_from_mp(p->y, 8, pY);
- sp_256_from_mp(p->z, 8, pZ);
- sp_256_proj_point_dbl_8(p, p, tmp);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->x, rX);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->y, rY);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->z, rZ);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (tmp != NULL) {
- XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(p, 0, NULL);
- return err;
- }
- /* Map a projective EC point to affine in place.
- * pZ will be one.
- *
- * pX EC point's X ordinate.
- * pY EC point's Y ordinate.
- * pZ EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
- int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
- {
- #if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
- sp_digit tmpd[2 * 8 * 4];
- sp_point pd;
- #endif
- sp_digit* tmp;
- sp_point* p;
- int err;
- err = sp_ecc_point_new(NULL, pd, p);
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (err == MP_OKAY) {
- tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL,
- DYNAMIC_TYPE_ECC);
- if (tmp == NULL) {
- err = MEMORY_E;
- }
- }
- #else
- tmp = tmpd;
- #endif
- if (err == MP_OKAY) {
- sp_256_from_mp(p->x, 8, pX);
- sp_256_from_mp(p->y, 8, pY);
- sp_256_from_mp(p->z, 8, pZ);
- sp_256_map_8(p, p, tmp);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->x, pX);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->y, pY);
- }
- if (err == MP_OKAY) {
- err = sp_256_to_mp(p->z, pZ);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (tmp != NULL) {
- XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
- }
- #endif
- sp_ecc_point_free(p, 0, NULL);
- return err;
- }
- #endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
- #ifdef HAVE_COMP_KEY
- /* Find the square root of a number mod the prime of the curve.
- *
- * y The number to operate on and the result.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
- static int sp_256_mont_sqrt_8(sp_digit* y)
- {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- sp_digit* d;
- #else
- sp_digit t1d[2 * 8];
- sp_digit t2d[2 * 8];
- #endif
- sp_digit* t1;
- sp_digit* t2;
- int err = MP_OKAY;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC);
- if (d == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- t1 = d + 0 * 8;
- t2 = d + 2 * 8;
- #else
- t1 = t1d;
- t2 = t2d;
- #endif
- {
- /* t2 = y ^ 0x2 */
- sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0x3 */
- sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod);
- /* t2 = y ^ 0xc */
- sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xf */
- sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
- /* t2 = y ^ 0xf0 */
- sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xff */
- sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
- /* t2 = y ^ 0xff00 */
- sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xffff */
- sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
- /* t2 = y ^ 0xffff0000 */
- sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xffffffff */
- sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xffffffff00000000 */
- sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xffffffff00000001 */
- sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
- sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod);
- /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
- sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod);
- sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod);
- }
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL) {
- XFREE(d, NULL, DYNAMIC_TYPE_ECC);
- }
- #endif
- return err;
- }
- /* Uncompress the point given the X ordinate.
- *
- * xm X ordinate.
- * odd Whether the Y ordinate is odd.
- * ym Calculated Y ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
- int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
- {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- sp_digit* d;
- #else
- sp_digit xd[2 * 8];
- sp_digit yd[2 * 8];
- #endif
- sp_digit* x = NULL;
- sp_digit* y = NULL;
- int err = MP_OKAY;
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC);
- if (d == NULL) {
- err = MEMORY_E;
- }
- #endif
- if (err == MP_OKAY) {
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- x = d + 0 * 8;
- y = d + 2 * 8;
- #else
- x = xd;
- y = yd;
- #endif
- sp_256_from_mp(x, 8, xm);
- err = sp_256_mod_mul_norm_8(x, x, p256_mod);
- }
- if (err == MP_OKAY) {
- /* y = x^3 */
- {
- sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod);
- sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod);
- }
- /* y = x^3 - 3x */
- sp_256_mont_sub_8(y, y, x, p256_mod);
- sp_256_mont_sub_8(y, y, x, p256_mod);
- sp_256_mont_sub_8(y, y, x, p256_mod);
- /* y = x^3 - 3x + b */
- err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod);
- }
- if (err == MP_OKAY) {
- sp_256_mont_add_8(y, y, x, p256_mod);
- /* y = sqrt(x^3 - 3x + b) */
- err = sp_256_mont_sqrt_8(y);
- }
- if (err == MP_OKAY) {
- XMEMSET(y + 8, 0, 8U * sizeof(sp_digit));
- sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod);
- if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
- sp_256_mont_sub_8(y, p256_mod, y, p256_mod);
- }
- err = sp_256_to_mp(y, ym);
- }
- #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
- if (d != NULL) {
- XFREE(d, NULL, DYNAMIC_TYPE_ECC);
- }
- #endif
- return err;
- }
- #endif
- #endif /* !WOLFSSL_SP_NO_256 */
- #endif /* WOLFSSL_HAVE_SP_ECC */
- #endif /* WOLFSSL_SP_ARM_THUMB_ASM */
- #endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
|