sp_cortexm.c 2.7 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339543405434154342543435434454345543465434754348543495435054351543525435354354543555435654357543585435954360543615436254363543645436554366543675436854369543705437154372543735437454375543765437754378543795438054381543825438354384543855438654387543885438954390543915439254393543945439554396543975439854399544005440154402544035440454405544065440754408544095441054411544125441354414544155441654417544185441954420544215442254423544245442554426544275442854429544305443154432544335443454435544365443754438544395444054441544425444354444544455444654447544485444954450544515445254453544545445554456544575445854459544605446154462544635446454465544665446754468544695447054471544725447354474544755447654477544785447954480544815448254483544845448554486544875448854489544905449154492544935449454495544965449754498544995450054501545025450354504545055450654507545085450954510545115451254513545145451554516545175451854519545205452154522545235452454525545265452754528545295453054531545325453354534545355453654537545385453954540545415454254543545445454554546545475454854549545505455154552545535455454555545565455754558545595456054561545625456354564545655456654567545685456954570545715457254573545745457554576545775457854579545805458154582545835458454585545865458754588545895459054591545925459354594545955459654597545985459954600546015460254603546045460554606546075460854609546105461154612546135461454615546165461754618546195462054621546225462354624546255462654627546285462954630546315463254633546345463554636546375463854639546405464154642546435464454645546465464754648546495465054651546525465354654546555465654657546585465954660546615466254663546645466554666546675466854669546705467154672546735467454675546765467754678546795468054681546825468354684546855468654687546885468954690546915469254693546945469554696546975469854699547005470154702547035470454705547065470754708547095471054711547125471354714547155471654717547185471954720547215472254723547245472554726547275472854729547305473154732547335473454735547365473754738547395474054741547425474354744547455474654747547485474954750547515475254753547545475554756547575475854759547605476154762547635476454765547665476754768547695477054771547725477354774547755477654777547785477954780547815478254783547845478554786547875478854789547905479154792547935479454795547965479754798547995480054801548025480354804548055480654807548085480954810548115481254813548145481554816548175481854819548205482154822548235482454825548265482754828548295483054831548325483354834548355483654837548385483954840548415484254843548445484554846548475484854849548505485154852548535485454855548565485754858548595486054861548625486354864548655486654867548685486954870548715487254873548745487554876548775487854879548805488154882548835488454885548865488754888548895489054891548925489354894548955489654897548985489954900549015490254903549045490554906549075490854909549105491154912549135491454915549165491754918549195492054921549225492354924549255492654927549285492954930549315493254933549345493554936549375493854939549405494154942549435494454945549465494754948549495495054951549525495354954549555495654957549585495954960549615496254963549645496554966549675496854969549705497154972549735497454975549765497754978549795498054981549825498354984549855498654987549885498954990549915499254993549945499554996549975499854999550005500155002550035500455005550065500755008550095501055011550125501355014550155501655017550185501955020550215502255023550245502555026550275502855029550305503155032550335503455035550365503755038550395504055041550425504355044550455504655047550485504955050550515505255053550545505555056550575505855059550605506155062550635506455065550665506755068550695507055071550725507355074550755507655077550785507955080550815508255083550845508555086550875508855089550905509155092550935509455095550965509755098550995510055101551025510355104551055510655107551085510955110551115511255113551145511555116551175511855119551205512155122551235512455125551265512755128551295513055131551325513355134551355513655137551385513955140551415514255143551445514555146551475514855149551505515155152551535515455155551565515755158551595516055161551625516355164551655516655167551685516955170551715517255173551745517555176551775517855179551805518155182551835518455185551865518755188551895519055191551925519355194551955519655197551985519955200552015520255203552045520555206552075520855209552105521155212552135521455215552165521755218552195522055221552225522355224552255522655227552285522955230552315523255233552345523555236552375523855239552405524155242552435524455245552465524755248552495525055251552525525355254552555525655257552585525955260552615526255263552645526555266552675526855269552705527155272552735527455275552765527755278552795528055281552825528355284552855528655287552885528955290552915529255293552945529555296552975529855299553005530155302553035530455305553065530755308553095531055311553125531355314553155531655317553185531955320553215532255323553245532555326553275532855329553305533155332553335533455335553365533755338553395534055341553425534355344553455534655347553485534955350553515535255353553545535555356553575535855359553605536155362553635536455365553665536755368553695537055371553725537355374553755537655377553785537955380553815538255383553845538555386553875538855389553905539155392553935539455395553965539755398553995540055401554025540355404554055540655407554085540955410554115541255413554145541555416554175541855419554205542155422554235542455425554265542755428554295543055431554325543355434554355543655437554385543955440554415544255443554445544555446554475544855449554505545155452554535545455455554565545755458554595546055461554625546355464554655546655467554685546955470554715547255473554745547555476554775547855479554805548155482554835548455485554865548755488554895549055491554925549355494554955549655497554985549955500555015550255503555045550555506555075550855509555105551155512555135551455515555165551755518555195552055521555225552355524555255552655527555285552955530555315553255533555345553555536555375553855539555405554155542555435554455545555465554755548555495555055551555525555355554555555555655557555585555955560555615556255563555645556555566555675556855569555705557155572555735557455575555765557755578555795558055581555825558355584555855558655587555885558955590555915559255593555945559555596555975559855599556005560155602556035560455605556065560755608556095561055611556125561355614556155561655617556185561955620556215562255623556245562555626556275562855629556305563155632556335563455635556365563755638556395564055641556425564355644556455564655647556485564955650556515565255653556545565555656556575565855659556605566155662556635566455665556665566755668556695567055671556725567355674556755567655677556785567955680556815568255683556845568555686556875568855689556905569155692556935569455695556965569755698556995570055701557025570355704557055570655707557085570955710557115571255713557145571555716557175571855719557205572155722557235572455725557265572755728557295573055731557325573355734557355573655737557385573955740557415574255743557445574555746557475574855749557505575155752557535575455755557565575755758557595576055761557625576355764557655576655767557685576955770557715577255773557745577555776557775577855779557805578155782557835578455785557865578755788557895579055791557925579355794557955579655797557985579955800558015580255803558045580555806558075580855809558105581155812558135581455815558165581755818558195582055821558225582355824558255582655827558285582955830558315583255833558345583555836558375583855839558405584155842558435584455845558465584755848558495585055851558525585355854558555585655857558585585955860558615586255863558645586555866558675586855869558705587155872558735587455875558765587755878558795588055881558825588355884558855588655887558885588955890558915589255893558945589555896558975589855899559005590155902559035590455905559065590755908559095591055911559125591355914559155591655917559185591955920559215592255923559245592555926559275592855929559305593155932559335593455935559365593755938559395594055941559425594355944559455594655947559485594955950559515595255953559545595555956559575595855959559605596155962559635596455965559665596755968559695597055971559725597355974559755597655977559785597955980559815598255983559845598555986559875598855989559905599155992559935599455995559965599755998559995600056001560025600356004560055600656007560085600956010560115601256013560145601556016560175601856019560205602156022560235602456025560265602756028560295603056031560325603356034560355603656037560385603956040560415604256043560445604556046560475604856049560505605156052560535605456055560565605756058560595606056061560625606356064560655606656067560685606956070560715607256073560745607556076560775607856079560805608156082560835608456085560865608756088560895609056091560925609356094560955609656097560985609956100561015610256103561045610556106561075610856109561105611156112561135611456115561165611756118561195612056121561225612356124561255612656127561285612956130561315613256133561345613556136561375613856139561405614156142561435614456145561465614756148561495615056151561525615356154561555615656157561585615956160561615616256163561645616556166561675616856169561705617156172561735617456175561765617756178561795618056181561825618356184561855618656187561885618956190561915619256193561945619556196561975619856199562005620156202562035620456205562065620756208562095621056211562125621356214562155621656217562185621956220562215622256223562245622556226562275622856229562305623156232562335623456235562365623756238562395624056241562425624356244562455624656247562485624956250562515625256253562545625556256562575625856259562605626156262562635626456265562665626756268562695627056271562725627356274562755627656277562785627956280562815628256283562845628556286562875628856289562905629156292562935629456295562965629756298562995630056301563025630356304563055630656307563085630956310563115631256313563145631556316563175631856319563205632156322563235632456325563265632756328563295633056331563325633356334563355633656337563385633956340563415634256343563445634556346563475634856349563505635156352563535635456355563565635756358563595636056361563625636356364563655636656367563685636956370563715637256373563745637556376563775637856379563805638156382563835638456385563865638756388563895639056391563925639356394563955639656397563985639956400564015640256403564045640556406564075640856409564105641156412564135641456415564165641756418564195642056421564225642356424564255642656427564285642956430564315643256433564345643556436564375643856439564405644156442564435644456445564465644756448564495645056451564525645356454564555645656457564585645956460564615646256463564645646556466564675646856469564705647156472564735647456475564765647756478564795648056481564825648356484564855648656487564885648956490564915649256493564945649556496564975649856499565005650156502565035650456505565065650756508565095651056511565125651356514565155651656517565185651956520565215652256523565245652556526565275652856529565305653156532565335653456535565365653756538565395654056541565425654356544565455654656547565485654956550565515655256553565545655556556565575655856559565605656156562565635656456565565665656756568565695657056571565725657356574565755657656577565785657956580565815658256583565845658556586565875658856589565905659156592565935659456595565965659756598565995660056601566025660356604566055660656607566085660956610566115661256613566145661556616566175661856619566205662156622566235662456625566265662756628566295663056631566325663356634566355663656637566385663956640566415664256643566445664556646566475664856649566505665156652566535665456655566565665756658566595666056661566625666356664566655666656667566685666956670566715667256673566745667556676566775667856679566805668156682566835668456685566865668756688566895669056691566925669356694566955669656697566985669956700567015670256703567045670556706567075670856709567105671156712567135671456715567165671756718567195672056721567225672356724567255672656727567285672956730567315673256733567345673556736567375673856739567405674156742567435674456745567465674756748567495675056751567525675356754567555675656757567585675956760567615676256763567645676556766567675676856769567705677156772567735677456775567765677756778567795678056781567825678356784567855678656787567885678956790567915679256793567945679556796567975679856799568005680156802568035680456805568065680756808568095681056811568125681356814568155681656817568185681956820568215682256823568245682556826568275682856829568305683156832568335683456835568365683756838568395684056841568425684356844568455684656847568485684956850568515685256853568545685556856568575685856859568605686156862568635686456865568665686756868568695687056871568725687356874568755687656877568785687956880568815688256883568845688556886568875688856889568905689156892568935689456895568965689756898568995690056901569025690356904569055690656907569085690956910569115691256913569145691556916569175691856919569205692156922569235692456925569265692756928569295693056931569325693356934569355693656937569385693956940569415694256943569445694556946569475694856949569505695156952569535695456955569565695756958569595696056961569625696356964569655696656967569685696956970569715697256973569745697556976569775697856979569805698156982569835698456985569865698756988569895699056991569925699356994569955699656997569985699957000570015700257003570045700557006570075700857009570105701157012570135701457015570165701757018570195702057021570225702357024570255702657027570285702957030570315703257033570345703557036570375703857039570405704157042570435704457045570465704757048570495705057051570525705357054570555705657057570585705957060570615706257063570645706557066570675706857069570705707157072570735707457075570765707757078570795708057081570825708357084570855708657087570885708957090570915709257093570945709557096570975709857099571005710157102571035710457105571065710757108571095711057111571125711357114571155711657117571185711957120571215712257123571245712557126571275712857129571305713157132571335713457135571365713757138571395714057141571425714357144571455714657147571485714957150571515715257153571545715557156571575715857159571605716157162571635716457165571665716757168571695717057171571725717357174571755717657177571785717957180571815718257183571845718557186571875718857189571905719157192571935719457195571965719757198571995720057201572025720357204572055720657207572085720957210572115721257213572145721557216572175721857219572205722157222572235722457225572265722757228572295723057231572325723357234572355723657237572385723957240572415724257243572445724557246572475724857249572505725157252572535725457255572565725757258572595726057261572625726357264572655726657267572685726957270572715727257273572745727557276572775727857279572805728157282572835728457285572865728757288572895729057291572925729357294572955729657297572985729957300573015730257303573045730557306573075730857309573105731157312573135731457315573165731757318573195732057321573225732357324573255732657327573285732957330573315733257333573345733557336573375733857339573405734157342573435734457345573465734757348573495735057351573525735357354573555735657357573585735957360573615736257363573645736557366573675736857369573705737157372573735737457375573765737757378573795738057381573825738357384573855738657387573885738957390573915739257393573945739557396573975739857399574005740157402574035740457405574065740757408574095741057411574125741357414574155741657417574185741957420574215742257423574245742557426574275742857429574305743157432574335743457435574365743757438574395744057441574425744357444574455744657447574485744957450574515745257453574545745557456574575745857459574605746157462574635746457465574665746757468574695747057471574725747357474574755747657477574785747957480574815748257483574845748557486574875748857489574905749157492574935749457495574965749757498574995750057501575025750357504575055750657507575085750957510575115751257513575145751557516575175751857519575205752157522575235752457525575265752757528575295753057531575325753357534575355753657537575385753957540575415754257543575445754557546575475754857549575505755157552575535755457555575565755757558575595756057561575625756357564575655756657567575685756957570575715757257573575745757557576575775757857579575805758157582575835758457585575865758757588575895759057591575925759357594575955759657597575985759957600576015760257603576045760557606576075760857609576105761157612576135761457615576165761757618576195762057621576225762357624576255762657627576285762957630576315763257633576345763557636576375763857639576405764157642576435764457645576465764757648576495765057651576525765357654576555765657657576585765957660576615766257663576645766557666576675766857669576705767157672576735767457675576765767757678576795768057681576825768357684576855768657687576885768957690576915769257693576945769557696576975769857699577005770157702577035770457705577065770757708577095771057711577125771357714577155771657717577185771957720577215772257723577245772557726577275772857729577305773157732577335773457735577365773757738577395774057741577425774357744577455774657747577485774957750577515775257753577545775557756577575775857759577605776157762577635776457765577665776757768577695777057771577725777357774577755777657777577785777957780577815778257783577845778557786577875778857789577905779157792577935779457795577965779757798577995780057801578025780357804578055780657807578085780957810578115781257813578145781557816578175781857819578205782157822578235782457825578265782757828578295783057831578325783357834578355783657837578385783957840578415784257843578445784557846578475784857849578505785157852578535785457855578565785757858578595786057861578625786357864578655786657867578685786957870578715787257873578745787557876578775787857879578805788157882578835788457885578865788757888578895789057891578925789357894578955789657897578985789957900579015790257903579045790557906579075790857909579105791157912579135791457915579165791757918579195792057921579225792357924579255792657927579285792957930579315793257933579345793557936579375793857939579405794157942579435794457945579465794757948579495795057951579525795357954579555795657957579585795957960579615796257963579645796557966579675796857969579705797157972579735797457975579765797757978579795798057981579825798357984579855798657987579885798957990579915799257993579945799557996579975799857999580005800158002580035800458005580065800758008580095801058011580125801358014580155801658017580185801958020580215802258023580245802558026580275802858029580305803158032580335803458035580365803758038580395804058041580425804358044580455804658047580485804958050580515805258053580545805558056580575805858059580605806158062580635806458065580665806758068580695807058071580725807358074580755807658077580785807958080580815808258083580845808558086580875808858089580905809158092580935809458095580965809758098580995810058101581025810358104581055810658107581085810958110581115811258113581145811558116581175811858119581205812158122581235812458125581265812758128581295813058131581325813358134581355813658137581385813958140581415814258143581445814558146581475814858149581505815158152581535815458155581565815758158581595816058161581625816358164581655816658167581685816958170581715817258173581745817558176581775817858179581805818158182581835818458185581865818758188581895819058191581925819358194581955819658197581985819958200582015820258203582045820558206582075820858209582105821158212582135821458215582165821758218582195822058221582225822358224582255822658227582285822958230582315823258233582345823558236582375823858239582405824158242582435824458245582465824758248582495825058251582525825358254582555825658257582585825958260582615826258263582645826558266582675826858269582705827158272582735827458275582765827758278582795828058281582825828358284582855828658287582885828958290582915829258293582945829558296582975829858299583005830158302583035830458305583065830758308583095831058311583125831358314583155831658317583185831958320583215832258323583245832558326583275832858329583305833158332583335833458335583365833758338583395834058341583425834358344583455834658347583485834958350583515835258353583545835558356583575835858359583605836158362583635836458365583665836758368583695837058371583725837358374583755837658377583785837958380583815838258383583845838558386583875838858389583905839158392583935839458395583965839758398583995840058401584025840358404584055840658407584085840958410584115841258413584145841558416584175841858419584205842158422584235842458425584265842758428584295843058431584325843358434584355843658437584385843958440584415844258443584445844558446584475844858449584505845158452584535845458455584565845758458584595846058461584625846358464584655846658467584685846958470584715847258473584745847558476584775847858479584805848158482584835848458485584865848758488584895849058491584925849358494584955849658497584985849958500585015850258503585045850558506585075850858509585105851158512585135851458515585165851758518585195852058521585225852358524585255852658527585285852958530585315853258533585345853558536585375853858539585405854158542585435854458545585465854758548585495855058551585525855358554585555855658557585585855958560585615856258563585645856558566585675856858569585705857158572585735857458575585765857758578585795858058581585825858358584585855858658587585885858958590585915859258593585945859558596585975859858599586005860158602586035860458605586065860758608586095861058611586125861358614586155861658617586185861958620586215862258623586245862558626586275862858629586305863158632586335863458635586365863758638586395864058641586425864358644586455864658647586485864958650586515865258653586545865558656586575865858659586605866158662586635866458665586665866758668586695867058671586725867358674586755867658677586785867958680586815868258683586845868558686586875868858689586905869158692586935869458695586965869758698586995870058701587025870358704587055870658707587085870958710587115871258713587145871558716587175871858719587205872158722587235872458725587265872758728587295873058731587325873358734587355873658737587385873958740587415874258743587445874558746587475874858749587505875158752587535875458755587565875758758587595876058761587625876358764587655876658767587685876958770587715877258773587745877558776587775877858779587805878158782587835878458785587865878758788587895879058791587925879358794587955879658797587985879958800588015880258803588045880558806588075880858809588105881158812588135881458815588165881758818588195882058821588225882358824588255882658827588285882958830588315883258833588345883558836588375883858839588405884158842588435884458845588465884758848588495885058851588525885358854588555885658857588585885958860588615886258863588645886558866588675886858869588705887158872588735887458875588765887758878588795888058881588825888358884588855888658887588885888958890588915889258893588945889558896588975889858899589005890158902589035890458905589065890758908589095891058911589125891358914589155891658917589185891958920589215892258923589245892558926589275892858929589305893158932589335893458935589365893758938589395894058941589425894358944589455894658947589485894958950589515895258953589545895558956589575895858959589605896158962589635896458965589665896758968589695897058971589725897358974589755897658977589785897958980589815898258983589845898558986589875898858989589905899158992589935899458995589965899758998589995900059001590025900359004590055900659007590085900959010590115901259013590145901559016590175901859019590205902159022590235902459025590265902759028590295903059031590325903359034590355903659037590385903959040590415904259043590445904559046590475904859049590505905159052590535905459055590565905759058590595906059061590625906359064590655906659067590685906959070590715907259073590745907559076590775907859079590805908159082590835908459085590865908759088590895909059091590925909359094590955909659097590985909959100591015910259103591045910559106591075910859109591105911159112591135911459115591165911759118591195912059121591225912359124591255912659127591285912959130591315913259133591345913559136591375913859139591405914159142591435914459145591465914759148591495915059151591525915359154591555915659157591585915959160591615916259163591645916559166591675916859169591705917159172591735917459175591765917759178591795918059181591825918359184591855918659187591885918959190591915919259193591945919559196591975919859199592005920159202592035920459205592065920759208592095921059211592125921359214592155921659217592185921959220592215922259223592245922559226592275922859229592305923159232592335923459235592365923759238592395924059241592425924359244592455924659247592485924959250592515925259253592545925559256592575925859259592605926159262592635926459265592665926759268592695927059271592725927359274592755927659277592785927959280592815928259283592845928559286592875928859289592905929159292592935929459295592965929759298592995930059301593025930359304593055930659307593085930959310593115931259313593145931559316593175931859319593205932159322593235932459325593265932759328593295933059331593325933359334593355933659337593385933959340593415934259343593445934559346593475934859349593505935159352593535935459355593565935759358593595936059361593625936359364593655936659367593685936959370593715937259373593745937559376593775937859379593805938159382593835938459385593865938759388593895939059391593925939359394593955939659397593985939959400594015940259403594045940559406594075940859409594105941159412594135941459415594165941759418594195942059421594225942359424594255942659427594285942959430594315943259433594345943559436594375943859439594405944159442594435944459445594465944759448594495945059451594525945359454594555945659457594585945959460594615946259463594645946559466594675946859469594705947159472594735947459475594765947759478594795948059481594825948359484594855948659487594885948959490594915949259493594945949559496594975949859499595005950159502595035950459505595065950759508595095951059511595125951359514595155951659517595185951959520595215952259523595245952559526595275952859529595305953159532595335953459535595365953759538595395954059541595425954359544595455954659547595485954959550595515955259553595545955559556595575955859559595605956159562595635956459565595665956759568595695957059571595725957359574595755957659577595785957959580595815958259583595845958559586595875958859589595905959159592595935959459595595965959759598595995960059601596025960359604596055960659607596085960959610596115961259613596145961559616596175961859619596205962159622596235962459625596265962759628596295963059631596325963359634596355963659637596385963959640596415964259643596445964559646596475964859649596505965159652596535965459655596565965759658596595966059661596625966359664596655966659667596685966959670596715967259673596745967559676596775967859679596805968159682596835968459685596865968759688596895969059691596925969359694596955969659697596985969959700597015970259703597045970559706597075970859709597105971159712597135971459715597165971759718597195972059721597225972359724597255972659727597285972959730597315973259733597345973559736597375973859739597405974159742597435974459745597465974759748597495975059751597525975359754597555975659757597585975959760597615976259763597645976559766597675976859769597705977159772597735977459775597765977759778597795978059781597825978359784597855978659787597885978959790597915979259793597945979559796597975979859799598005980159802598035980459805598065980759808598095981059811598125981359814598155981659817598185981959820598215982259823598245982559826598275982859829598305983159832598335983459835598365983759838598395984059841598425984359844598455984659847598485984959850598515985259853598545985559856598575985859859598605986159862598635986459865598665986759868598695987059871598725987359874598755987659877598785987959880598815988259883598845988559886598875988859889598905989159892598935989459895598965989759898598995990059901599025990359904599055990659907599085990959910599115991259913599145991559916599175991859919599205992159922599235992459925599265992759928599295993059931599325993359934599355993659937599385993959940599415994259943599445994559946599475994859949599505995159952599535995459955599565995759958599595996059961599625996359964599655996659967599685996959970599715997259973599745997559976599775997859979599805998159982599835998459985599865998759988599895999059991599925999359994599955999659997599985999960000600016000260003600046000560006600076000860009600106001160012600136001460015600166001760018600196002060021600226002360024600256002660027600286002960030600316003260033600346003560036600376003860039600406004160042600436004460045600466004760048600496005060051600526005360054600556005660057600586005960060600616006260063600646006560066600676006860069600706007160072600736007460075600766007760078600796008060081600826008360084600856008660087600886008960090600916009260093600946009560096600976009860099601006010160102601036010460105601066010760108601096011060111601126011360114601156011660117601186011960120601216012260123601246012560126601276012860129601306013160132601336013460135601366013760138601396014060141601426014360144601456014660147601486014960150601516015260153601546015560156601576015860159601606016160162601636016460165601666016760168601696017060171601726017360174601756017660177601786017960180601816018260183601846018560186601876018860189601906019160192601936019460195601966019760198601996020060201602026020360204602056020660207602086020960210602116021260213602146021560216602176021860219602206022160222602236022460225602266022760228602296023060231602326023360234602356023660237602386023960240602416024260243602446024560246602476024860249602506025160252602536025460255602566025760258602596026060261602626026360264602656026660267602686026960270602716027260273602746027560276602776027860279602806028160282602836028460285602866028760288602896029060291602926029360294602956029660297602986029960300603016030260303603046030560306603076030860309603106031160312603136031460315603166031760318603196032060321603226032360324603256032660327603286032960330603316033260333603346033560336603376033860339603406034160342603436034460345603466034760348603496035060351603526035360354603556035660357603586035960360603616036260363603646036560366603676036860369603706037160372603736037460375603766037760378603796038060381603826038360384603856038660387603886038960390603916039260393603946039560396603976039860399604006040160402604036040460405604066040760408604096041060411604126041360414604156041660417604186041960420604216042260423604246042560426604276042860429604306043160432604336043460435604366043760438604396044060441604426044360444604456044660447604486044960450604516045260453604546045560456604576045860459604606046160462604636046460465604666046760468604696047060471604726047360474604756047660477604786047960480604816048260483604846048560486604876048860489604906049160492604936049460495604966049760498604996050060501605026050360504605056050660507605086050960510605116051260513605146051560516605176051860519605206052160522605236052460525605266052760528605296053060531605326053360534605356053660537605386053960540605416054260543605446054560546605476054860549605506055160552605536055460555605566055760558605596056060561605626056360564605656056660567605686056960570605716057260573605746057560576605776057860579605806058160582605836058460585605866058760588605896059060591605926059360594605956059660597605986059960600606016060260603606046060560606606076060860609606106061160612606136061460615606166061760618606196062060621606226062360624606256062660627606286062960630606316063260633606346063560636606376063860639606406064160642606436064460645606466064760648606496065060651606526065360654606556065660657606586065960660606616066260663606646066560666606676066860669606706067160672606736067460675606766067760678606796068060681606826068360684606856068660687606886068960690606916069260693606946069560696606976069860699607006070160702607036070460705607066070760708607096071060711607126071360714607156071660717607186071960720607216072260723607246072560726607276072860729607306073160732607336073460735607366073760738607396074060741607426074360744607456074660747607486074960750607516075260753607546075560756607576075860759607606076160762607636076460765607666076760768607696077060771607726077360774607756077660777607786077960780607816078260783607846078560786607876078860789607906079160792607936079460795607966079760798607996080060801608026080360804608056080660807608086080960810608116081260813608146081560816608176081860819608206082160822608236082460825608266082760828608296083060831608326083360834608356083660837608386083960840608416084260843608446084560846608476084860849608506085160852608536085460855608566085760858608596086060861608626086360864608656086660867608686086960870608716087260873608746087560876608776087860879608806088160882608836088460885608866088760888608896089060891608926089360894608956089660897608986089960900609016090260903609046090560906609076090860909609106091160912609136091460915609166091760918609196092060921609226092360924609256092660927609286092960930609316093260933609346093560936609376093860939609406094160942609436094460945609466094760948609496095060951609526095360954609556095660957609586095960960609616096260963609646096560966609676096860969609706097160972609736097460975609766097760978609796098060981609826098360984609856098660987609886098960990609916099260993609946099560996609976099860999610006100161002610036100461005610066100761008610096101061011610126101361014610156101661017610186101961020610216102261023610246102561026610276102861029610306103161032610336103461035610366103761038610396104061041610426104361044610456104661047610486104961050610516105261053610546105561056610576105861059610606106161062610636106461065610666106761068610696107061071610726107361074610756107661077610786107961080610816108261083610846108561086610876108861089610906109161092610936109461095610966109761098610996110061101611026110361104611056110661107611086110961110611116111261113611146111561116611176111861119611206112161122611236112461125611266112761128611296113061131611326113361134611356113661137611386113961140611416114261143611446114561146611476114861149611506115161152611536115461155611566115761158611596116061161611626116361164611656116661167611686116961170611716117261173611746117561176611776117861179611806118161182611836118461185611866118761188611896119061191611926119361194611956119661197611986119961200612016120261203612046120561206612076120861209612106121161212612136121461215612166121761218612196122061221612226122361224612256122661227612286122961230612316123261233612346123561236612376123861239612406124161242612436124461245612466124761248612496125061251612526125361254612556125661257612586125961260612616126261263612646126561266612676126861269612706127161272612736127461275612766127761278612796128061281612826128361284612856128661287612886128961290612916129261293612946129561296612976129861299613006130161302613036130461305613066130761308613096131061311613126131361314613156131661317613186131961320613216132261323613246132561326613276132861329613306133161332613336133461335613366133761338613396134061341613426134361344613456134661347613486134961350613516135261353613546135561356613576135861359613606136161362613636136461365613666136761368613696137061371613726137361374613756137661377613786137961380613816138261383613846138561386613876138861389613906139161392613936139461395613966139761398613996140061401614026140361404614056140661407614086140961410614116141261413614146141561416614176141861419614206142161422614236142461425614266142761428614296143061431614326143361434614356143661437614386143961440614416144261443614446144561446614476144861449614506145161452614536145461455614566145761458614596146061461614626146361464614656146661467614686146961470614716147261473614746147561476614776147861479614806148161482614836148461485614866148761488614896149061491614926149361494614956149661497614986149961500615016150261503615046150561506615076150861509615106151161512615136151461515615166151761518615196152061521615226152361524615256152661527615286152961530615316153261533615346153561536615376153861539615406154161542615436154461545615466154761548615496155061551615526155361554615556155661557615586155961560615616156261563615646156561566615676156861569615706157161572615736157461575615766157761578615796158061581615826158361584615856158661587615886158961590615916159261593615946159561596615976159861599616006160161602616036160461605616066160761608616096161061611616126161361614616156161661617616186161961620616216162261623616246162561626616276162861629616306163161632616336163461635616366163761638616396164061641616426164361644616456164661647616486164961650616516165261653616546165561656616576165861659616606166161662616636166461665616666166761668616696167061671616726167361674616756167661677616786167961680616816168261683616846168561686616876168861689616906169161692616936169461695616966169761698616996170061701617026170361704617056170661707617086170961710617116171261713617146171561716617176171861719617206172161722617236172461725617266172761728617296173061731617326173361734617356173661737617386173961740617416174261743617446174561746617476174861749617506175161752617536175461755617566175761758617596176061761617626176361764617656176661767617686176961770617716177261773617746177561776617776177861779617806178161782617836178461785617866178761788617896179061791617926179361794617956179661797617986179961800618016180261803618046180561806618076180861809618106181161812618136181461815618166181761818618196182061821618226182361824618256182661827618286182961830618316183261833618346183561836618376183861839618406184161842618436184461845618466184761848618496185061851618526185361854618556185661857618586185961860618616186261863618646186561866618676186861869618706187161872618736187461875618766187761878618796188061881618826188361884618856188661887618886188961890618916189261893618946189561896618976189861899619006190161902619036190461905619066190761908619096191061911619126191361914619156191661917619186191961920619216192261923619246192561926619276192861929619306193161932619336193461935619366193761938619396194061941619426194361944619456194661947619486194961950619516195261953619546195561956619576195861959619606196161962619636196461965619666196761968619696197061971619726197361974619756197661977619786197961980619816198261983619846198561986619876198861989619906199161992619936199461995619966199761998619996200062001620026200362004620056200662007620086200962010620116201262013620146201562016620176201862019620206202162022620236202462025620266202762028620296203062031620326203362034620356203662037620386203962040620416204262043620446204562046620476204862049620506205162052620536205462055620566205762058620596206062061620626206362064620656206662067620686206962070620716207262073620746207562076620776207862079620806208162082620836208462085620866208762088620896209062091620926209362094620956209662097620986209962100621016210262103621046210562106621076210862109621106211162112621136211462115621166211762118621196212062121621226212362124621256212662127621286212962130621316213262133621346213562136621376213862139621406214162142621436214462145621466214762148621496215062151621526215362154621556215662157621586215962160621616216262163621646216562166621676216862169621706217162172621736217462175621766217762178621796218062181621826218362184621856218662187621886218962190621916219262193621946219562196621976219862199622006220162202622036220462205622066220762208622096221062211622126221362214622156221662217622186221962220622216222262223622246222562226622276222862229622306223162232622336223462235622366223762238622396224062241622426224362244622456224662247622486224962250622516225262253622546225562256622576225862259622606226162262622636226462265622666226762268622696227062271622726227362274622756227662277622786227962280622816228262283622846228562286622876228862289622906229162292622936229462295622966229762298622996230062301623026230362304623056230662307623086230962310623116231262313623146231562316623176231862319623206232162322623236232462325623266232762328623296233062331623326233362334623356233662337623386233962340623416234262343623446234562346623476234862349623506235162352623536235462355623566235762358623596236062361623626236362364623656236662367623686236962370623716237262373623746237562376623776237862379623806238162382623836238462385623866238762388623896239062391623926239362394623956239662397623986239962400624016240262403624046240562406624076240862409624106241162412624136241462415624166241762418624196242062421624226242362424624256242662427624286242962430624316243262433624346243562436624376243862439624406244162442624436244462445624466244762448624496245062451624526245362454624556245662457624586245962460624616246262463624646246562466624676246862469624706247162472624736247462475624766247762478624796248062481624826248362484624856248662487624886248962490624916249262493624946249562496624976249862499625006250162502625036250462505625066250762508625096251062511625126251362514625156251662517625186251962520625216252262523625246252562526625276252862529625306253162532625336253462535625366253762538625396254062541625426254362544625456254662547625486254962550625516255262553625546255562556625576255862559625606256162562625636256462565625666256762568625696257062571625726257362574625756257662577625786257962580625816258262583625846258562586625876258862589625906259162592625936259462595625966259762598625996260062601626026260362604626056260662607626086260962610626116261262613626146261562616626176261862619626206262162622626236262462625626266262762628626296263062631626326263362634626356263662637626386263962640626416264262643626446264562646626476264862649626506265162652626536265462655626566265762658626596266062661626626266362664626656266662667626686266962670626716267262673626746267562676626776267862679626806268162682626836268462685626866268762688626896269062691626926269362694626956269662697626986269962700627016270262703627046270562706627076270862709627106271162712627136271462715627166271762718627196272062721627226272362724627256272662727627286272962730627316273262733627346273562736627376273862739627406274162742627436274462745627466274762748627496275062751627526275362754627556275662757627586275962760627616276262763627646276562766627676276862769627706277162772627736277462775627766277762778627796278062781627826278362784627856278662787627886278962790627916279262793627946279562796627976279862799628006280162802628036280462805628066280762808628096281062811628126281362814628156281662817628186281962820628216282262823628246282562826628276282862829628306283162832628336283462835628366283762838628396284062841628426284362844628456284662847628486284962850628516285262853628546285562856628576285862859628606286162862628636286462865628666286762868628696287062871628726287362874628756287662877628786287962880628816288262883628846288562886628876288862889628906289162892628936289462895628966289762898628996290062901629026290362904629056290662907629086290962910629116291262913629146291562916629176291862919629206292162922629236292462925629266292762928629296293062931629326293362934629356293662937629386293962940629416294262943629446294562946629476294862949629506295162952629536295462955629566295762958629596296062961629626296362964629656296662967629686296962970629716297262973629746297562976629776297862979629806298162982629836298462985629866298762988629896299062991629926299362994629956299662997629986299963000630016300263003630046300563006630076300863009630106301163012630136301463015630166301763018630196302063021630226302363024630256302663027630286302963030630316303263033630346303563036630376303863039630406304163042630436304463045630466304763048630496305063051630526305363054630556305663057630586305963060630616306263063630646306563066630676306863069630706307163072630736307463075630766307763078630796308063081630826308363084630856308663087630886308963090630916309263093630946309563096630976309863099631006310163102631036310463105631066310763108631096311063111631126311363114631156311663117631186311963120631216312263123631246312563126631276312863129631306313163132631336313463135631366313763138631396314063141631426314363144631456314663147631486314963150631516315263153631546315563156631576315863159631606316163162631636316463165631666316763168631696317063171631726317363174631756317663177631786317963180631816318263183631846318563186631876318863189631906319163192631936319463195631966319763198631996320063201632026320363204632056320663207632086320963210632116321263213632146321563216632176321863219632206322163222632236322463225632266322763228632296323063231632326323363234632356323663237632386323963240632416324263243632446324563246632476324863249632506325163252632536325463255632566325763258632596326063261632626326363264632656326663267632686326963270632716327263273632746327563276632776327863279632806328163282632836328463285632866328763288632896329063291632926329363294632956329663297632986329963300633016330263303633046330563306633076330863309633106331163312633136331463315633166331763318633196332063321633226332363324633256332663327633286332963330633316333263333633346333563336633376333863339633406334163342633436334463345633466334763348633496335063351633526335363354633556335663357633586335963360633616336263363633646336563366633676336863369633706337163372633736337463375633766337763378633796338063381633826338363384633856338663387633886338963390633916339263393633946339563396633976339863399634006340163402634036340463405634066340763408634096341063411634126341363414634156341663417634186341963420634216342263423634246342563426634276342863429634306343163432634336343463435634366343763438634396344063441634426344363444634456344663447634486344963450634516345263453634546345563456634576345863459634606346163462634636346463465634666346763468634696347063471634726347363474634756347663477634786347963480634816348263483634846348563486634876348863489634906349163492634936349463495634966349763498634996350063501635026350363504635056350663507635086350963510635116351263513635146351563516635176351863519635206352163522635236352463525635266352763528635296353063531635326353363534635356353663537635386353963540635416354263543635446354563546635476354863549635506355163552635536355463555635566355763558635596356063561635626356363564635656356663567635686356963570635716357263573635746357563576635776357863579635806358163582635836358463585635866358763588635896359063591635926359363594635956359663597635986359963600636016360263603636046360563606636076360863609636106361163612636136361463615636166361763618636196362063621636226362363624636256362663627636286362963630636316363263633636346363563636636376363863639636406364163642636436364463645636466364763648636496365063651636526365363654636556365663657636586365963660636616366263663636646366563666636676366863669636706367163672636736367463675636766367763678636796368063681636826368363684636856368663687636886368963690636916369263693636946369563696636976369863699637006370163702637036370463705637066370763708637096371063711637126371363714637156371663717637186371963720637216372263723637246372563726637276372863729637306373163732637336373463735637366373763738637396374063741637426374363744637456374663747637486374963750637516375263753637546375563756637576375863759637606376163762637636376463765637666376763768637696377063771637726377363774637756377663777637786377963780637816378263783637846378563786637876378863789637906379163792637936379463795637966379763798637996380063801638026380363804638056380663807638086380963810638116381263813638146381563816638176381863819638206382163822638236382463825638266382763828638296383063831638326383363834638356383663837638386383963840638416384263843638446384563846638476384863849638506385163852638536385463855638566385763858638596386063861638626386363864638656386663867638686386963870638716387263873638746387563876638776387863879638806388163882638836388463885638866388763888638896389063891638926389363894638956389663897638986389963900639016390263903639046390563906639076390863909639106391163912639136391463915639166391763918639196392063921639226392363924639256392663927639286392963930639316393263933639346393563936639376393863939639406394163942639436394463945639466394763948639496395063951639526395363954639556395663957639586395963960639616396263963639646396563966639676396863969639706397163972639736397463975639766397763978639796398063981639826398363984639856398663987639886398963990639916399263993639946399563996639976399863999640006400164002640036400464005640066400764008640096401064011640126401364014640156401664017640186401964020640216402264023640246402564026640276402864029640306403164032640336403464035640366403764038640396404064041640426404364044640456404664047640486404964050640516405264053640546405564056640576405864059640606406164062640636406464065640666406764068640696407064071640726407364074640756407664077640786407964080640816408264083640846408564086640876408864089640906409164092640936409464095640966409764098640996410064101641026410364104641056410664107641086410964110641116411264113641146411564116641176411864119641206412164122641236412464125641266412764128641296413064131641326413364134641356413664137641386413964140641416414264143641446414564146641476414864149641506415164152641536415464155641566415764158641596416064161641626416364164641656416664167641686416964170641716417264173641746417564176641776417864179641806418164182641836418464185641866418764188641896419064191641926419364194641956419664197641986419964200642016420264203642046420564206642076420864209642106421164212642136421464215642166421764218642196422064221642226422364224642256422664227642286422964230642316423264233642346423564236642376423864239642406424164242642436424464245642466424764248642496425064251642526425364254642556425664257642586425964260642616426264263642646426564266642676426864269642706427164272642736427464275642766427764278642796428064281642826428364284642856428664287642886428964290642916429264293642946429564296642976429864299643006430164302643036430464305643066430764308643096431064311643126431364314643156431664317643186431964320643216432264323643246432564326643276432864329643306433164332643336433464335643366433764338643396434064341643426434364344643456434664347643486434964350643516435264353643546435564356643576435864359643606436164362643636436464365643666436764368643696437064371643726437364374643756437664377643786437964380643816438264383643846438564386643876438864389643906439164392643936439464395643966439764398643996440064401644026440364404644056440664407644086440964410644116441264413644146441564416644176441864419644206442164422644236442464425644266442764428644296443064431644326443364434644356443664437644386443964440644416444264443644446444564446644476444864449644506445164452644536445464455644566445764458644596446064461644626446364464644656446664467644686446964470644716447264473644746447564476644776447864479644806448164482644836448464485644866448764488644896449064491644926449364494644956449664497644986449964500645016450264503645046450564506645076450864509645106451164512645136451464515645166451764518645196452064521645226452364524645256452664527645286452964530645316453264533645346453564536645376453864539645406454164542645436454464545645466454764548645496455064551645526455364554645556455664557645586455964560645616456264563645646456564566645676456864569645706457164572645736457464575645766457764578645796458064581645826458364584645856458664587645886458964590645916459264593645946459564596645976459864599646006460164602646036460464605646066460764608646096461064611646126461364614646156461664617646186461964620646216462264623646246462564626646276462864629646306463164632646336463464635646366463764638646396464064641646426464364644646456464664647646486464964650646516465264653646546465564656646576465864659646606466164662646636466464665646666466764668646696467064671646726467364674646756467664677646786467964680646816468264683646846468564686646876468864689646906469164692646936469464695646966469764698646996470064701647026470364704647056470664707647086470964710647116471264713647146471564716647176471864719647206472164722647236472464725647266472764728647296473064731647326473364734647356473664737647386473964740647416474264743647446474564746647476474864749647506475164752647536475464755647566475764758647596476064761647626476364764647656476664767647686476964770647716477264773647746477564776647776477864779647806478164782647836478464785647866478764788647896479064791647926479364794647956479664797647986479964800648016480264803648046480564806648076480864809648106481164812648136481464815648166481764818648196482064821648226482364824648256482664827648286482964830648316483264833648346483564836648376483864839648406484164842648436484464845648466484764848648496485064851648526485364854648556485664857648586485964860648616486264863648646486564866648676486864869648706487164872648736487464875648766487764878648796488064881648826488364884648856488664887648886488964890648916489264893648946489564896648976489864899649006490164902649036490464905649066490764908649096491064911649126491364914649156491664917649186491964920649216492264923649246492564926649276492864929649306493164932649336493464935649366493764938649396494064941649426494364944649456494664947649486494964950649516495264953649546495564956649576495864959649606496164962649636496464965649666496764968649696497064971649726497364974649756497664977649786497964980649816498264983649846498564986649876498864989649906499164992649936499464995649966499764998649996500065001650026500365004650056500665007650086500965010650116501265013650146501565016650176501865019650206502165022650236502465025650266502765028650296503065031650326503365034650356503665037650386503965040650416504265043650446504565046650476504865049650506505165052650536505465055650566505765058650596506065061650626506365064650656506665067650686506965070650716507265073650746507565076650776507865079650806508165082650836508465085650866508765088650896509065091650926509365094650956509665097650986509965100651016510265103651046510565106651076510865109651106511165112651136511465115651166511765118651196512065121651226512365124651256512665127651286512965130651316513265133651346513565136651376513865139651406514165142651436514465145651466514765148651496515065151651526515365154651556515665157651586515965160651616516265163651646516565166651676516865169651706517165172651736517465175651766517765178651796518065181651826518365184651856518665187651886518965190651916519265193651946519565196651976519865199652006520165202652036520465205652066520765208652096521065211652126521365214652156521665217652186521965220652216522265223652246522565226652276522865229652306523165232652336523465235652366523765238652396524065241652426524365244652456524665247652486524965250652516525265253652546525565256652576525865259652606526165262652636526465265652666526765268652696527065271652726527365274652756527665277652786527965280652816528265283652846528565286652876528865289652906529165292652936529465295652966529765298652996530065301653026530365304653056530665307653086530965310653116531265313653146531565316653176531865319653206532165322653236532465325653266532765328653296533065331653326533365334653356533665337653386533965340653416534265343653446534565346653476534865349653506535165352653536535465355653566535765358653596536065361653626536365364653656536665367653686536965370653716537265373653746537565376653776537865379653806538165382653836538465385653866538765388653896539065391653926539365394653956539665397653986539965400654016540265403654046540565406654076540865409654106541165412654136541465415654166541765418654196542065421654226542365424654256542665427654286542965430654316543265433654346543565436654376543865439654406544165442654436544465445654466544765448654496545065451654526545365454654556545665457654586545965460654616546265463654646546565466654676546865469654706547165472654736547465475654766547765478654796548065481654826548365484654856548665487654886548965490654916549265493654946549565496654976549865499655006550165502655036550465505655066550765508655096551065511655126551365514655156551665517655186551965520655216552265523655246552565526655276552865529655306553165532655336553465535655366553765538655396554065541655426554365544655456554665547655486554965550655516555265553655546555565556655576555865559655606556165562655636556465565655666556765568655696557065571655726557365574655756557665577655786557965580655816558265583655846558565586655876558865589655906559165592655936559465595655966559765598655996560065601656026560365604656056560665607656086560965610656116561265613656146561565616656176561865619656206562165622656236562465625656266562765628656296563065631656326563365634656356563665637656386563965640656416564265643656446564565646656476564865649656506565165652656536565465655656566565765658656596566065661656626566365664656656566665667656686566965670656716567265673656746567565676656776567865679656806568165682656836568465685656866568765688656896569065691656926569365694656956569665697656986569965700657016570265703657046570565706657076570865709657106571165712657136571465715657166571765718657196572065721657226572365724657256572665727657286572965730657316573265733657346573565736657376573865739657406574165742657436574465745657466574765748657496575065751657526575365754657556575665757657586575965760657616576265763657646576565766657676576865769657706577165772657736577465775657766577765778657796578065781657826578365784657856578665787657886578965790657916579265793657946579565796657976579865799658006580165802658036580465805658066580765808658096581065811658126581365814658156581665817658186581965820658216582265823658246582565826658276582865829658306583165832658336583465835658366583765838658396584065841658426584365844658456584665847658486584965850658516585265853658546585565856658576585865859658606586165862658636586465865658666586765868658696587065871658726587365874658756587665877658786587965880658816588265883658846588565886658876588865889658906589165892658936589465895658966589765898658996590065901659026590365904659056590665907659086590965910659116591265913659146591565916659176591865919659206592165922659236592465925659266592765928659296593065931659326593365934659356593665937659386593965940659416594265943659446594565946659476594865949659506595165952659536595465955659566595765958659596596065961659626596365964659656596665967659686596965970659716597265973659746597565976659776597865979659806598165982659836598465985659866598765988659896599065991659926599365994659956599665997659986599966000660016600266003660046600566006660076600866009660106601166012660136601466015660166601766018660196602066021660226602366024660256602666027660286602966030660316603266033660346603566036660376603866039660406604166042660436604466045660466604766048660496605066051660526605366054660556605666057660586605966060660616606266063660646606566066660676606866069660706607166072660736607466075660766607766078660796608066081660826608366084660856608666087660886608966090660916609266093660946609566096660976609866099661006610166102661036610466105661066610766108661096611066111661126611366114661156611666117661186611966120661216612266123661246612566126661276612866129661306613166132661336613466135661366613766138661396614066141661426614366144661456614666147661486614966150661516615266153661546615566156661576615866159661606616166162661636616466165661666616766168661696617066171661726617366174661756617666177661786617966180661816618266183661846618566186661876618866189661906619166192661936619466195661966619766198661996620066201662026620366204662056620666207662086620966210662116621266213662146621566216662176621866219662206622166222662236622466225662266622766228662296623066231662326623366234662356623666237662386623966240662416624266243662446624566246662476624866249662506625166252662536625466255662566625766258662596626066261662626626366264662656626666267662686626966270662716627266273662746627566276662776627866279662806628166282662836628466285662866628766288662896629066291662926629366294662956629666297662986629966300663016630266303663046630566306663076630866309663106631166312663136631466315663166631766318663196632066321663226632366324663256632666327663286632966330663316633266333663346633566336663376633866339663406634166342663436634466345663466634766348663496635066351663526635366354663556635666357663586635966360663616636266363663646636566366663676636866369663706637166372663736637466375663766637766378663796638066381663826638366384663856638666387663886638966390663916639266393663946639566396663976639866399664006640166402664036640466405664066640766408664096641066411664126641366414664156641666417664186641966420664216642266423664246642566426664276642866429664306643166432664336643466435664366643766438664396644066441664426644366444664456644666447664486644966450664516645266453664546645566456664576645866459664606646166462664636646466465664666646766468664696647066471664726647366474664756647666477664786647966480664816648266483664846648566486664876648866489664906649166492664936649466495664966649766498664996650066501665026650366504665056650666507665086650966510665116651266513665146651566516665176651866519665206652166522665236652466525665266652766528665296653066531665326653366534665356653666537665386653966540665416654266543665446654566546665476654866549665506655166552665536655466555665566655766558665596656066561665626656366564665656656666567665686656966570665716657266573665746657566576665776657866579665806658166582665836658466585665866658766588665896659066591665926659366594665956659666597665986659966600666016660266603666046660566606666076660866609666106661166612666136661466615666166661766618666196662066621666226662366624666256662666627666286662966630666316663266633666346663566636666376663866639666406664166642666436664466645666466664766648666496665066651666526665366654666556665666657666586665966660666616666266663666646666566666666676666866669666706667166672666736667466675666766667766678666796668066681666826668366684666856668666687666886668966690666916669266693666946669566696666976669866699667006670166702667036670466705667066670766708667096671066711667126671366714667156671666717667186671966720667216672266723667246672566726667276672866729667306673166732667336673466735667366673766738667396674066741667426674366744667456674666747667486674966750667516675266753667546675566756667576675866759667606676166762667636676466765667666676766768667696677066771667726677366774667756677666777667786677966780667816678266783667846678566786667876678866789667906679166792667936679466795667966679766798667996680066801668026680366804668056680666807668086680966810668116681266813668146681566816668176681866819668206682166822668236682466825668266682766828668296683066831668326683366834668356683666837668386683966840668416684266843668446684566846668476684866849668506685166852668536685466855668566685766858668596686066861668626686366864668656686666867668686686966870668716687266873668746687566876668776687866879668806688166882668836688466885668866688766888668896689066891668926689366894668956689666897668986689966900669016690266903669046690566906669076690866909669106691166912669136691466915669166691766918669196692066921669226692366924669256692666927669286692966930669316693266933669346693566936669376693866939669406694166942669436694466945669466694766948669496695066951669526695366954669556695666957669586695966960669616696266963669646696566966669676696866969669706697166972669736697466975669766697766978669796698066981669826698366984669856698666987669886698966990669916699266993669946699566996669976699866999670006700167002670036700467005670066700767008670096701067011670126701367014670156701667017670186701967020670216702267023670246702567026670276702867029670306703167032670336703467035670366703767038670396704067041670426704367044670456704667047670486704967050670516705267053670546705567056670576705867059670606706167062670636706467065670666706767068670696707067071670726707367074670756707667077670786707967080670816708267083670846708567086670876708867089670906709167092670936709467095670966709767098670996710067101671026710367104671056710667107671086710967110671116711267113671146711567116671176711867119671206712167122671236712467125671266712767128671296713067131671326713367134671356713667137671386713967140671416714267143671446714567146671476714867149671506715167152671536715467155671566715767158671596716067161671626716367164671656716667167671686716967170671716717267173671746717567176671776717867179671806718167182671836718467185671866718767188671896719067191671926719367194671956719667197671986719967200672016720267203672046720567206672076720867209672106721167212672136721467215672166721767218672196722067221672226722367224672256722667227672286722967230672316723267233672346723567236672376723867239672406724167242672436724467245672466724767248672496725067251672526725367254672556725667257672586725967260672616726267263672646726567266672676726867269672706727167272672736727467275672766727767278672796728067281672826728367284672856728667287672886728967290672916729267293672946729567296672976729867299673006730167302673036730467305673066730767308673096731067311673126731367314673156731667317673186731967320673216732267323673246732567326673276732867329673306733167332673336733467335673366733767338673396734067341673426734367344673456734667347673486734967350673516735267353673546735567356673576735867359673606736167362673636736467365673666736767368673696737067371673726737367374673756737667377673786737967380673816738267383673846738567386673876738867389673906739167392673936739467395673966739767398673996740067401674026740367404674056740667407674086740967410674116741267413674146741567416674176741867419674206742167422674236742467425674266742767428674296743067431674326743367434674356743667437674386743967440674416744267443674446744567446674476744867449674506745167452674536745467455674566745767458674596746067461674626746367464674656746667467674686746967470674716747267473674746747567476674776747867479674806748167482674836748467485674866748767488674896749067491674926749367494674956749667497674986749967500675016750267503675046750567506675076750867509675106751167512675136751467515675166751767518675196752067521675226752367524675256752667527675286752967530675316753267533675346753567536675376753867539675406754167542675436754467545675466754767548675496755067551675526755367554675556755667557675586755967560675616756267563675646756567566675676756867569675706757167572675736757467575675766757767578675796758067581675826758367584675856758667587675886758967590675916759267593675946759567596675976759867599676006760167602676036760467605676066760767608676096761067611676126761367614676156761667617676186761967620676216762267623676246762567626676276762867629676306763167632676336763467635676366763767638676396764067641676426764367644676456764667647676486764967650676516765267653676546765567656676576765867659676606766167662676636766467665676666766767668676696767067671676726767367674676756767667677676786767967680676816768267683676846768567686676876768867689676906769167692676936769467695676966769767698676996770067701677026770367704677056770667707677086770967710677116771267713677146771567716677176771867719677206772167722677236772467725677266772767728677296773067731677326773367734677356773667737677386773967740677416774267743677446774567746677476774867749677506775167752677536775467755677566775767758677596776067761677626776367764677656776667767677686776967770677716777267773677746777567776677776777867779677806778167782677836778467785677866778767788677896779067791677926779367794677956779667797677986779967800678016780267803678046780567806678076780867809678106781167812678136781467815678166781767818678196782067821678226782367824678256782667827678286782967830678316783267833678346783567836678376783867839678406784167842678436784467845678466784767848678496785067851678526785367854678556785667857678586785967860678616786267863678646786567866678676786867869678706787167872678736787467875678766787767878678796788067881678826788367884678856788667887678886788967890678916789267893678946789567896678976789867899679006790167902679036790467905679066790767908679096791067911679126791367914679156791667917679186791967920679216792267923679246792567926679276792867929679306793167932679336793467935679366793767938679396794067941679426794367944679456794667947679486794967950679516795267953679546795567956679576795867959679606796167962679636796467965679666796767968679696797067971679726797367974679756797667977679786797967980679816798267983679846798567986679876798867989679906799167992679936799467995679966799767998679996800068001680026800368004680056800668007680086800968010680116801268013680146801568016680176801868019680206802168022680236802468025680266802768028680296803068031680326803368034680356803668037680386803968040680416804268043680446804568046680476804868049680506805168052680536805468055680566805768058680596806068061680626806368064680656806668067680686806968070680716807268073680746807568076680776807868079680806808168082680836808468085680866808768088680896809068091680926809368094680956809668097680986809968100681016810268103681046810568106681076810868109681106811168112681136811468115681166811768118681196812068121681226812368124681256812668127681286812968130681316813268133681346813568136681376813868139681406814168142681436814468145681466814768148681496815068151681526815368154681556815668157681586815968160681616816268163681646816568166681676816868169681706817168172681736817468175681766817768178681796818068181681826818368184681856818668187681886818968190681916819268193681946819568196681976819868199682006820168202682036820468205682066820768208682096821068211682126821368214682156821668217682186821968220682216822268223682246822568226682276822868229682306823168232682336823468235682366823768238682396824068241682426824368244682456824668247682486824968250682516825268253682546825568256682576825868259682606826168262682636826468265682666826768268682696827068271682726827368274682756827668277682786827968280682816828268283682846828568286682876828868289682906829168292682936829468295682966829768298682996830068301683026830368304683056830668307683086830968310683116831268313683146831568316683176831868319683206832168322683236832468325683266832768328683296833068331683326833368334683356833668337683386833968340683416834268343683446834568346683476834868349683506835168352683536835468355683566835768358683596836068361683626836368364683656836668367683686836968370683716837268373683746837568376683776837868379683806838168382683836838468385683866838768388683896839068391683926839368394683956839668397683986839968400684016840268403684046840568406684076840868409684106841168412684136841468415684166841768418684196842068421684226842368424684256842668427684286842968430684316843268433684346843568436684376843868439684406844168442684436844468445684466844768448684496845068451684526845368454684556845668457684586845968460684616846268463684646846568466684676846868469684706847168472684736847468475684766847768478684796848068481684826848368484684856848668487684886848968490684916849268493684946849568496684976849868499685006850168502685036850468505685066850768508685096851068511685126851368514685156851668517685186851968520685216852268523685246852568526685276852868529685306853168532685336853468535685366853768538685396854068541685426854368544685456854668547685486854968550685516855268553685546855568556685576855868559685606856168562685636856468565685666856768568685696857068571685726857368574685756857668577685786857968580685816858268583685846858568586685876858868589685906859168592685936859468595685966859768598685996860068601686026860368604686056860668607686086860968610686116861268613686146861568616686176861868619686206862168622686236862468625686266862768628686296863068631686326863368634686356863668637686386863968640686416864268643686446864568646686476864868649686506865168652686536865468655686566865768658686596866068661686626866368664686656866668667686686866968670686716867268673686746867568676686776867868679686806868168682686836868468685686866868768688686896869068691686926869368694686956869668697686986869968700687016870268703687046870568706687076870868709687106871168712687136871468715687166871768718687196872068721687226872368724687256872668727687286872968730687316873268733687346873568736687376873868739687406874168742687436874468745687466874768748687496875068751687526875368754687556875668757687586875968760687616876268763687646876568766687676876868769687706877168772687736877468775687766877768778687796878068781687826878368784687856878668787687886878968790687916879268793687946879568796687976879868799688006880168802688036880468805688066880768808688096881068811688126881368814688156881668817688186881968820688216882268823688246882568826688276882868829688306883168832688336883468835688366883768838688396884068841688426884368844688456884668847688486884968850688516885268853688546885568856688576885868859688606886168862688636886468865688666886768868688696887068871688726887368874688756887668877688786887968880688816888268883688846888568886688876888868889688906889168892688936889468895688966889768898688996890068901689026890368904689056890668907689086890968910689116891268913689146891568916689176891868919689206892168922689236892468925689266892768928689296893068931689326893368934689356893668937689386893968940689416894268943689446894568946689476894868949689506895168952689536895468955689566895768958689596896068961689626896368964689656896668967689686896968970689716897268973689746897568976689776897868979689806898168982689836898468985689866898768988689896899068991689926899368994689956899668997689986899969000690016900269003690046900569006690076900869009690106901169012690136901469015690166901769018690196902069021690226902369024690256902669027690286902969030690316903269033690346903569036690376903869039690406904169042690436904469045690466904769048690496905069051690526905369054690556905669057690586905969060690616906269063690646906569066690676906869069690706907169072690736907469075690766907769078690796908069081690826908369084690856908669087690886908969090690916909269093690946909569096690976909869099691006910169102691036910469105691066910769108691096911069111691126911369114691156911669117691186911969120691216912269123691246912569126691276912869129691306913169132691336913469135691366913769138691396914069141691426914369144691456914669147691486914969150691516915269153691546915569156691576915869159691606916169162691636916469165691666916769168691696917069171691726917369174691756917669177691786917969180691816918269183691846918569186691876918869189691906919169192691936919469195691966919769198691996920069201692026920369204692056920669207692086920969210692116921269213692146921569216692176921869219692206922169222692236922469225692266922769228692296923069231692326923369234692356923669237692386923969240692416924269243692446924569246692476924869249692506925169252692536925469255692566925769258692596926069261692626926369264692656926669267692686926969270692716927269273692746927569276692776927869279692806928169282692836928469285692866928769288692896929069291692926929369294692956929669297692986929969300693016930269303693046930569306693076930869309693106931169312693136931469315693166931769318693196932069321693226932369324693256932669327693286932969330693316933269333693346933569336693376933869339693406934169342693436934469345693466934769348693496935069351693526935369354693556935669357693586935969360693616936269363693646936569366693676936869369693706937169372693736937469375693766937769378693796938069381693826938369384693856938669387693886938969390693916939269393693946939569396693976939869399694006940169402694036940469405694066940769408694096941069411694126941369414694156941669417694186941969420694216942269423694246942569426694276942869429694306943169432694336943469435694366943769438694396944069441694426944369444694456944669447694486944969450694516945269453694546945569456694576945869459694606946169462694636946469465694666946769468694696947069471694726947369474694756947669477694786947969480694816948269483694846948569486694876948869489694906949169492694936949469495694966949769498694996950069501695026950369504695056950669507695086950969510695116951269513695146951569516695176951869519695206952169522695236952469525695266952769528695296953069531695326953369534695356953669537695386953969540695416954269543695446954569546695476954869549695506955169552695536955469555695566955769558695596956069561695626956369564695656956669567695686956969570695716957269573695746957569576695776957869579695806958169582695836958469585695866958769588695896959069591695926959369594695956959669597695986959969600696016960269603696046960569606696076960869609696106961169612696136961469615696166961769618696196962069621696226962369624696256962669627696286962969630696316963269633696346963569636696376963869639696406964169642696436964469645696466964769648696496965069651696526965369654696556965669657696586965969660696616966269663696646966569666696676966869669696706967169672696736967469675696766967769678696796968069681696826968369684696856968669687696886968969690696916969269693696946969569696696976969869699697006970169702697036970469705697066970769708697096971069711697126971369714697156971669717697186971969720697216972269723697246972569726697276972869729697306973169732697336973469735697366973769738697396974069741697426974369744697456974669747697486974969750697516975269753697546975569756697576975869759697606976169762697636976469765697666976769768697696977069771697726977369774697756977669777697786977969780697816978269783697846978569786697876978869789697906979169792697936979469795697966979769798697996980069801698026980369804698056980669807698086980969810698116981269813698146981569816698176981869819698206982169822698236982469825698266982769828698296983069831698326983369834698356983669837698386983969840698416984269843698446984569846698476984869849698506985169852698536985469855698566985769858698596986069861698626986369864698656986669867698686986969870698716987269873698746987569876698776987869879698806988169882698836988469885698866988769888698896989069891698926989369894698956989669897698986989969900699016990269903699046990569906699076990869909699106991169912699136991469915699166991769918699196992069921699226992369924699256992669927699286992969930699316993269933699346993569936699376993869939699406994169942699436994469945699466994769948699496995069951699526995369954699556995669957699586995969960699616996269963699646996569966699676996869969699706997169972699736997469975699766997769978699796998069981699826998369984699856998669987699886998969990699916999269993699946999569996699976999869999700007000170002700037000470005700067000770008700097001070011700127001370014700157001670017700187001970020700217002270023700247002570026700277002870029700307003170032700337003470035700367003770038700397004070041700427004370044700457004670047700487004970050700517005270053700547005570056700577005870059700607006170062700637006470065700667006770068700697007070071700727007370074700757007670077700787007970080700817008270083700847008570086700877008870089700907009170092700937009470095700967009770098700997010070101701027010370104701057010670107701087010970110701117011270113701147011570116701177011870119701207012170122701237012470125701267012770128701297013070131701327013370134701357013670137701387013970140701417014270143701447014570146701477014870149701507015170152701537015470155701567015770158701597016070161701627016370164701657016670167701687016970170701717017270173701747017570176701777017870179701807018170182701837018470185701867018770188701897019070191701927019370194701957019670197701987019970200702017020270203702047020570206702077020870209702107021170212702137021470215702167021770218702197022070221702227022370224702257022670227702287022970230702317023270233702347023570236702377023870239702407024170242702437024470245702467024770248702497025070251702527025370254702557025670257702587025970260702617026270263702647026570266702677026870269702707027170272702737027470275702767027770278702797028070281702827028370284702857028670287702887028970290702917029270293702947029570296702977029870299703007030170302703037030470305703067030770308703097031070311703127031370314703157031670317703187031970320703217032270323703247032570326703277032870329703307033170332703337033470335703367033770338703397034070341703427034370344703457034670347703487034970350703517035270353703547035570356703577035870359703607036170362703637036470365703667036770368703697037070371703727037370374703757037670377703787037970380703817038270383703847038570386703877038870389703907039170392703937039470395703967039770398703997040070401704027040370404704057040670407704087040970410704117041270413704147041570416704177041870419704207042170422704237042470425704267042770428704297043070431704327043370434704357043670437704387043970440704417044270443704447044570446704477044870449704507045170452704537045470455704567045770458704597046070461704627046370464704657046670467704687046970470704717047270473704747047570476704777047870479704807048170482704837048470485704867048770488704897049070491704927049370494704957049670497704987049970500705017050270503705047050570506705077050870509705107051170512705137051470515705167051770518705197052070521705227052370524705257052670527705287052970530705317053270533705347053570536705377053870539705407054170542705437054470545705467054770548705497055070551705527055370554705557055670557705587055970560705617056270563705647056570566705677056870569705707057170572705737057470575705767057770578705797058070581705827058370584705857058670587705887058970590705917059270593705947059570596705977059870599706007060170602706037060470605706067060770608706097061070611706127061370614706157061670617706187061970620706217062270623706247062570626706277062870629706307063170632706337063470635706367063770638706397064070641706427064370644706457064670647706487064970650706517065270653706547065570656706577065870659706607066170662706637066470665706667066770668706697067070671706727067370674706757067670677706787067970680706817068270683706847068570686706877068870689706907069170692706937069470695706967069770698706997070070701707027070370704707057070670707707087070970710707117071270713707147071570716707177071870719707207072170722707237072470725707267072770728707297073070731707327073370734707357073670737707387073970740707417074270743707447074570746707477074870749707507075170752707537075470755707567075770758707597076070761707627076370764707657076670767707687076970770707717077270773707747077570776707777077870779707807078170782707837078470785707867078770788707897079070791707927079370794707957079670797707987079970800708017080270803708047080570806708077080870809708107081170812708137081470815708167081770818708197082070821708227082370824708257082670827708287082970830708317083270833708347083570836708377083870839708407084170842708437084470845708467084770848708497085070851708527085370854708557085670857708587085970860708617086270863708647086570866708677086870869708707087170872708737087470875708767087770878708797088070881708827088370884708857088670887708887088970890708917089270893708947089570896708977089870899709007090170902709037090470905709067090770908709097091070911709127091370914709157091670917709187091970920709217092270923709247092570926709277092870929709307093170932709337093470935709367093770938709397094070941709427094370944709457094670947709487094970950709517095270953709547095570956709577095870959709607096170962709637096470965709667096770968709697097070971709727097370974709757097670977709787097970980709817098270983709847098570986709877098870989709907099170992709937099470995709967099770998709997100071001710027100371004710057100671007710087100971010710117101271013710147101571016710177101871019710207102171022710237102471025710267102771028710297103071031710327103371034710357103671037710387103971040710417104271043710447104571046710477104871049710507105171052710537105471055710567105771058710597106071061710627106371064710657106671067710687106971070710717107271073710747107571076710777107871079710807108171082710837108471085710867108771088710897109071091710927109371094710957109671097710987109971100711017110271103711047110571106711077110871109711107111171112711137111471115711167111771118711197112071121711227112371124711257112671127711287112971130711317113271133711347113571136711377113871139711407114171142711437114471145711467114771148711497115071151711527115371154711557115671157711587115971160711617116271163711647116571166711677116871169711707117171172711737117471175711767117771178711797118071181711827118371184711857118671187711887118971190711917119271193711947119571196711977119871199712007120171202712037120471205712067120771208712097121071211712127121371214712157121671217712187121971220712217122271223712247122571226712277122871229712307123171232712337123471235712367123771238712397124071241712427124371244712457124671247712487124971250712517125271253712547125571256712577125871259712607126171262712637126471265712667126771268712697127071271712727127371274712757127671277712787127971280712817128271283712847128571286712877128871289712907129171292712937129471295712967129771298712997130071301713027130371304713057130671307713087130971310713117131271313713147131571316713177131871319713207132171322713237132471325713267132771328713297133071331713327133371334713357133671337713387133971340713417134271343713447134571346713477134871349713507135171352713537135471355713567135771358713597136071361713627136371364713657136671367713687136971370713717137271373713747137571376713777137871379713807138171382713837138471385713867138771388713897139071391713927139371394713957139671397713987139971400714017140271403714047140571406714077140871409714107141171412714137141471415714167141771418714197142071421714227142371424714257142671427714287142971430714317143271433714347143571436714377143871439714407144171442714437144471445714467144771448714497145071451714527145371454714557145671457714587145971460714617146271463714647146571466714677146871469714707147171472714737147471475714767147771478714797148071481714827148371484714857148671487714887148971490714917149271493714947149571496714977149871499715007150171502715037150471505715067150771508715097151071511715127151371514715157151671517715187151971520715217152271523715247152571526715277152871529715307153171532715337153471535715367153771538715397154071541715427154371544715457154671547715487154971550715517155271553715547155571556715577155871559715607156171562715637156471565715667156771568715697157071571715727157371574715757157671577715787157971580715817158271583715847158571586715877158871589715907159171592715937159471595715967159771598715997160071601716027160371604716057160671607716087160971610716117161271613716147161571616716177161871619716207162171622716237162471625716267162771628716297163071631716327163371634716357163671637716387163971640716417164271643716447164571646716477164871649716507165171652716537165471655716567165771658716597166071661716627166371664716657166671667716687166971670716717167271673716747167571676716777167871679716807168171682716837168471685716867168771688716897169071691716927169371694716957169671697716987169971700717017170271703717047170571706717077170871709717107171171712717137171471715717167171771718717197172071721717227172371724717257172671727717287172971730717317173271733717347173571736717377173871739717407174171742717437174471745717467174771748717497175071751717527175371754717557175671757717587175971760717617176271763717647176571766717677176871769717707177171772717737177471775717767177771778717797178071781717827178371784717857178671787717887178971790717917179271793717947179571796717977179871799718007180171802718037180471805718067180771808718097181071811718127181371814718157181671817718187181971820718217182271823718247182571826718277182871829718307183171832718337183471835718367183771838718397184071841718427184371844718457184671847718487184971850718517185271853718547185571856718577185871859718607186171862718637186471865718667186771868718697187071871718727187371874718757187671877718787187971880718817188271883718847188571886718877188871889718907189171892718937189471895718967189771898718997190071901719027190371904719057190671907719087190971910719117191271913719147191571916719177191871919719207192171922719237192471925719267192771928719297193071931719327193371934719357193671937719387193971940719417194271943719447194571946719477194871949719507195171952719537195471955719567195771958719597196071961719627196371964719657196671967719687196971970719717197271973719747197571976719777197871979719807198171982719837198471985719867198771988719897199071991719927199371994719957199671997719987199972000720017200272003720047200572006720077200872009720107201172012720137201472015720167201772018720197202072021720227202372024720257202672027720287202972030720317203272033720347203572036720377203872039720407204172042720437204472045720467204772048720497205072051720527205372054720557205672057720587205972060720617206272063720647206572066720677206872069720707207172072720737207472075720767207772078720797208072081720827208372084720857208672087720887208972090720917209272093720947209572096720977209872099721007210172102721037210472105721067210772108721097211072111721127211372114721157211672117721187211972120721217212272123721247212572126721277212872129721307213172132721337213472135721367213772138721397214072141721427214372144721457214672147721487214972150721517215272153721547215572156721577215872159721607216172162721637216472165721667216772168721697217072171721727217372174721757217672177721787217972180721817218272183721847218572186721877218872189721907219172192721937219472195721967219772198721997220072201722027220372204722057220672207722087220972210722117221272213722147221572216722177221872219722207222172222722237222472225722267222772228722297223072231722327223372234722357223672237722387223972240722417224272243722447224572246722477224872249722507225172252722537225472255722567225772258722597226072261722627226372264722657226672267722687226972270722717227272273722747227572276722777227872279722807228172282722837228472285722867228772288722897229072291722927229372294722957229672297722987229972300723017230272303723047230572306723077230872309723107231172312723137231472315723167231772318723197232072321723227232372324723257232672327723287232972330723317233272333723347233572336723377233872339723407234172342723437234472345723467234772348723497235072351723527235372354723557235672357723587235972360723617236272363723647236572366723677236872369723707237172372723737237472375723767237772378723797238072381723827238372384723857238672387723887238972390723917239272393723947239572396723977239872399724007240172402724037240472405724067240772408724097241072411724127241372414724157241672417724187241972420724217242272423724247242572426724277242872429724307243172432724337243472435724367243772438724397244072441724427244372444724457244672447724487244972450724517245272453724547245572456724577245872459724607246172462724637246472465724667246772468724697247072471724727247372474724757247672477724787247972480724817248272483724847248572486724877248872489724907249172492724937249472495724967249772498724997250072501725027250372504725057250672507725087250972510725117251272513725147251572516725177251872519725207252172522725237252472525725267252772528725297253072531725327253372534725357253672537725387253972540725417254272543725447254572546725477254872549725507255172552725537255472555725567255772558725597256072561725627256372564725657256672567725687256972570725717257272573725747257572576725777257872579725807258172582725837258472585725867258772588725897259072591725927259372594725957259672597725987259972600726017260272603726047260572606726077260872609726107261172612726137261472615726167261772618726197262072621726227262372624726257262672627726287262972630726317263272633726347263572636726377263872639726407264172642726437264472645726467264772648726497265072651726527265372654726557265672657726587265972660726617266272663726647266572666726677266872669726707267172672726737267472675726767267772678726797268072681726827268372684726857268672687726887268972690726917269272693726947269572696726977269872699727007270172702727037270472705727067270772708727097271072711727127271372714727157271672717727187271972720727217272272723727247272572726727277272872729727307273172732727337273472735727367273772738727397274072741727427274372744727457274672747727487274972750727517275272753727547275572756727577275872759727607276172762727637276472765727667276772768727697277072771727727277372774727757277672777727787277972780727817278272783727847278572786727877278872789727907279172792727937279472795727967279772798727997280072801728027280372804728057280672807728087280972810728117281272813728147281572816728177281872819728207282172822728237282472825728267282772828728297283072831728327283372834728357283672837728387283972840728417284272843728447284572846728477284872849728507285172852728537285472855728567285772858728597286072861728627286372864728657286672867728687286972870728717287272873728747287572876728777287872879728807288172882728837288472885728867288772888728897289072891728927289372894728957289672897728987289972900729017290272903729047290572906729077290872909729107291172912729137291472915729167291772918729197292072921729227292372924729257292672927729287292972930729317293272933729347293572936729377293872939729407294172942729437294472945729467294772948729497295072951729527295372954729557295672957729587295972960729617296272963729647296572966729677296872969729707297172972729737297472975729767297772978729797298072981729827298372984729857298672987729887298972990729917299272993729947299572996729977299872999730007300173002730037300473005730067300773008730097301073011730127301373014730157301673017730187301973020730217302273023730247302573026730277302873029730307303173032730337303473035730367303773038730397304073041730427304373044730457304673047730487304973050730517305273053730547305573056730577305873059730607306173062730637306473065730667306773068730697307073071730727307373074730757307673077730787307973080730817308273083730847308573086730877308873089730907309173092730937309473095730967309773098730997310073101731027310373104731057310673107731087310973110731117311273113731147311573116731177311873119731207312173122731237312473125731267312773128731297313073131731327313373134731357313673137731387313973140731417314273143731447314573146731477314873149731507315173152731537315473155731567315773158731597316073161731627316373164731657316673167731687316973170731717317273173731747317573176731777317873179731807318173182731837318473185731867318773188731897319073191731927319373194731957319673197731987319973200732017320273203732047320573206732077320873209732107321173212732137321473215732167321773218732197322073221732227322373224732257322673227732287322973230732317323273233732347323573236732377323873239732407324173242732437324473245732467324773248732497325073251732527325373254732557325673257732587325973260732617326273263732647326573266732677326873269732707327173272732737327473275732767327773278732797328073281732827328373284732857328673287732887328973290732917329273293732947329573296732977329873299733007330173302733037330473305733067330773308733097331073311733127331373314733157331673317733187331973320733217332273323733247332573326733277332873329733307333173332733337333473335733367333773338733397334073341733427334373344733457334673347733487334973350733517335273353733547335573356733577335873359733607336173362733637336473365733667336773368733697337073371733727337373374733757337673377733787337973380733817338273383733847338573386733877338873389733907339173392733937339473395733967339773398733997340073401734027340373404734057340673407734087340973410734117341273413734147341573416734177341873419734207342173422734237342473425734267342773428734297343073431734327343373434734357343673437734387343973440734417344273443734447344573446734477344873449734507345173452734537345473455734567345773458734597346073461734627346373464734657346673467734687346973470734717347273473734747347573476734777347873479734807348173482734837348473485734867348773488734897349073491734927349373494734957349673497734987349973500735017350273503735047350573506735077350873509735107351173512735137351473515735167351773518735197352073521735227352373524735257352673527735287352973530735317353273533735347353573536735377353873539735407354173542735437354473545735467354773548735497355073551735527355373554735557355673557735587355973560735617356273563735647356573566735677356873569735707357173572735737357473575735767357773578735797358073581735827358373584735857358673587735887358973590735917359273593735947359573596735977359873599736007360173602736037360473605736067360773608736097361073611736127361373614736157361673617736187361973620736217362273623736247362573626736277362873629736307363173632736337363473635736367363773638736397364073641736427364373644736457364673647736487364973650736517365273653736547365573656736577365873659736607366173662736637366473665736667366773668736697367073671736727367373674736757367673677736787367973680736817368273683736847368573686736877368873689736907369173692736937369473695736967369773698736997370073701737027370373704737057370673707737087370973710737117371273713737147371573716737177371873719737207372173722737237372473725737267372773728737297373073731737327373373734737357373673737737387373973740737417374273743737447374573746737477374873749737507375173752737537375473755737567375773758737597376073761737627376373764737657376673767737687376973770737717377273773737747377573776737777377873779737807378173782737837378473785737867378773788737897379073791737927379373794737957379673797737987379973800738017380273803738047380573806738077380873809738107381173812738137381473815738167381773818738197382073821738227382373824738257382673827738287382973830738317383273833738347383573836738377383873839738407384173842738437384473845738467384773848738497385073851738527385373854738557385673857738587385973860738617386273863738647386573866738677386873869738707387173872738737387473875738767387773878738797388073881738827388373884738857388673887738887388973890738917389273893738947389573896738977389873899739007390173902739037390473905739067390773908739097391073911739127391373914739157391673917739187391973920739217392273923739247392573926739277392873929739307393173932739337393473935739367393773938739397394073941739427394373944739457394673947739487394973950739517395273953739547395573956739577395873959739607396173962739637396473965739667396773968739697397073971739727397373974739757397673977739787397973980739817398273983739847398573986739877398873989739907399173992739937399473995739967399773998739997400074001740027400374004740057400674007740087400974010740117401274013740147401574016740177401874019740207402174022740237402474025740267402774028740297403074031740327403374034740357403674037740387403974040740417404274043740447404574046740477404874049740507405174052740537405474055740567405774058740597406074061740627406374064740657406674067740687406974070740717407274073740747407574076740777407874079740807408174082740837408474085740867408774088740897409074091740927409374094740957409674097740987409974100741017410274103741047410574106741077410874109741107411174112741137411474115741167411774118741197412074121741227412374124741257412674127741287412974130741317413274133741347413574136741377413874139741407414174142741437414474145741467414774148741497415074151741527415374154741557415674157741587415974160741617416274163741647416574166741677416874169741707417174172741737417474175741767417774178741797418074181741827418374184741857418674187741887418974190741917419274193741947419574196741977419874199742007420174202742037420474205742067420774208742097421074211742127421374214742157421674217742187421974220742217422274223742247422574226742277422874229742307423174232742337423474235742367423774238742397424074241742427424374244742457424674247742487424974250742517425274253742547425574256742577425874259742607426174262742637426474265742667426774268742697427074271742727427374274742757427674277742787427974280742817428274283742847428574286742877428874289742907429174292742937429474295742967429774298742997430074301743027430374304743057430674307743087430974310743117431274313743147431574316743177431874319743207432174322743237432474325743267432774328743297433074331743327433374334743357433674337743387433974340743417434274343743447434574346743477434874349743507435174352743537435474355743567435774358743597436074361743627436374364743657436674367743687436974370743717437274373743747437574376743777437874379743807438174382743837438474385743867438774388743897439074391743927439374394743957439674397743987439974400744017440274403744047440574406744077440874409744107441174412744137441474415744167441774418744197442074421744227442374424744257442674427744287442974430744317443274433744347443574436744377443874439744407444174442744437444474445744467444774448744497445074451744527445374454744557445674457744587445974460744617446274463744647446574466744677446874469744707447174472744737447474475744767447774478744797448074481744827448374484744857448674487744887448974490744917449274493744947449574496744977449874499745007450174502745037450474505745067450774508745097451074511745127451374514745157451674517745187451974520745217452274523745247452574526745277452874529745307453174532745337453474535745367453774538745397454074541745427454374544745457454674547745487454974550745517455274553745547455574556745577455874559745607456174562745637456474565745667456774568745697457074571745727457374574745757457674577745787457974580745817458274583745847458574586745877458874589745907459174592745937459474595745967459774598745997460074601746027460374604746057460674607746087460974610746117461274613746147461574616746177461874619746207462174622746237462474625746267462774628746297463074631746327463374634746357463674637746387463974640746417464274643746447464574646746477464874649746507465174652746537465474655746567465774658746597466074661746627466374664746657466674667746687466974670746717467274673746747467574676746777467874679746807468174682746837468474685746867468774688746897469074691746927469374694746957469674697746987469974700747017470274703747047470574706747077470874709747107471174712747137471474715747167471774718747197472074721747227472374724747257472674727747287472974730747317473274733747347473574736747377473874739747407474174742747437474474745747467474774748747497475074751747527475374754747557475674757747587475974760747617476274763747647476574766747677476874769747707477174772747737477474775747767477774778747797478074781747827478374784747857478674787747887478974790747917479274793747947479574796747977479874799748007480174802748037480474805748067480774808748097481074811748127481374814748157481674817748187481974820748217482274823748247482574826748277482874829748307483174832748337483474835748367483774838748397484074841748427484374844748457484674847748487484974850748517485274853748547485574856748577485874859748607486174862748637486474865748667486774868748697487074871748727487374874748757487674877748787487974880748817488274883748847488574886748877488874889748907489174892748937489474895748967489774898748997490074901749027490374904749057490674907749087490974910749117491274913749147491574916749177491874919749207492174922749237492474925749267492774928749297493074931749327493374934749357493674937749387493974940749417494274943749447494574946749477494874949749507495174952749537495474955749567495774958749597496074961749627496374964749657496674967749687496974970749717497274973749747497574976749777497874979749807498174982749837498474985749867498774988749897499074991749927499374994749957499674997749987499975000750017500275003750047500575006750077500875009750107501175012750137501475015750167501775018750197502075021750227502375024750257502675027750287502975030750317503275033750347503575036750377503875039750407504175042750437504475045750467504775048750497505075051750527505375054750557505675057750587505975060750617506275063750647506575066750677506875069750707507175072750737507475075750767507775078750797508075081750827508375084750857508675087750887508975090750917509275093750947509575096750977509875099751007510175102751037510475105751067510775108751097511075111751127511375114751157511675117751187511975120751217512275123751247512575126751277512875129751307513175132751337513475135751367513775138751397514075141751427514375144751457514675147751487514975150751517515275153751547515575156751577515875159751607516175162751637516475165751667516775168751697517075171751727517375174751757517675177751787517975180751817518275183751847518575186751877518875189751907519175192751937519475195751967519775198751997520075201752027520375204752057520675207752087520975210752117521275213752147521575216752177521875219752207522175222752237522475225752267522775228752297523075231752327523375234752357523675237752387523975240752417524275243752447524575246752477524875249752507525175252752537525475255752567525775258752597526075261752627526375264752657526675267752687526975270752717527275273752747527575276752777527875279752807528175282752837528475285752867528775288752897529075291752927529375294752957529675297752987529975300753017530275303753047530575306753077530875309753107531175312753137531475315753167531775318753197532075321753227532375324753257532675327753287532975330753317533275333753347533575336753377533875339753407534175342753437534475345753467534775348753497535075351753527535375354753557535675357753587535975360753617536275363753647536575366753677536875369753707537175372753737537475375753767537775378753797538075381753827538375384753857538675387753887538975390753917539275393753947539575396753977539875399754007540175402754037540475405754067540775408754097541075411754127541375414754157541675417754187541975420754217542275423754247542575426754277542875429754307543175432754337543475435754367543775438754397544075441754427544375444754457544675447754487544975450754517545275453754547545575456754577545875459754607546175462754637546475465754667546775468754697547075471754727547375474754757547675477754787547975480754817548275483754847548575486754877548875489754907549175492754937549475495754967549775498754997550075501755027550375504755057550675507755087550975510755117551275513755147551575516755177551875519755207552175522755237552475525755267552775528755297553075531755327553375534755357553675537755387553975540755417554275543755447554575546755477554875549755507555175552755537555475555755567555775558755597556075561755627556375564755657556675567755687556975570755717557275573755747557575576755777557875579755807558175582755837558475585755867558775588755897559075591755927559375594755957559675597755987559975600756017560275603756047560575606756077560875609756107561175612756137561475615756167561775618756197562075621756227562375624756257562675627756287562975630756317563275633756347563575636756377563875639756407564175642756437564475645756467564775648756497565075651756527565375654756557565675657756587565975660756617566275663756647566575666756677566875669756707567175672756737567475675756767567775678756797568075681756827568375684756857568675687756887568975690756917569275693756947569575696756977569875699757007570175702757037570475705757067570775708757097571075711757127571375714757157571675717757187571975720757217572275723757247572575726757277572875729757307573175732757337573475735757367573775738757397574075741757427574375744757457574675747757487574975750757517575275753757547575575756757577575875759757607576175762757637576475765757667576775768757697577075771757727577375774757757577675777757787577975780757817578275783757847578575786757877578875789757907579175792757937579475795757967579775798757997580075801758027580375804758057580675807758087580975810758117581275813758147581575816758177581875819758207582175822758237582475825758267582775828758297583075831758327583375834758357583675837758387583975840758417584275843758447584575846758477584875849758507585175852758537585475855758567585775858758597586075861758627586375864758657586675867758687586975870758717587275873758747587575876758777587875879758807588175882758837588475885758867588775888758897589075891758927589375894758957589675897758987589975900759017590275903759047590575906759077590875909759107591175912759137591475915759167591775918759197592075921759227592375924759257592675927759287592975930759317593275933759347593575936759377593875939759407594175942759437594475945759467594775948759497595075951759527595375954759557595675957759587595975960759617596275963759647596575966759677596875969759707597175972759737597475975759767597775978759797598075981759827598375984759857598675987759887598975990759917599275993759947599575996759977599875999760007600176002760037600476005760067600776008760097601076011760127601376014760157601676017760187601976020760217602276023760247602576026760277602876029760307603176032760337603476035760367603776038760397604076041760427604376044760457604676047760487604976050760517605276053760547605576056760577605876059760607606176062760637606476065760667606776068760697607076071760727607376074760757607676077760787607976080760817608276083760847608576086760877608876089760907609176092760937609476095760967609776098760997610076101761027610376104761057610676107761087610976110761117611276113761147611576116761177611876119761207612176122761237612476125761267612776128761297613076131761327613376134761357613676137761387613976140761417614276143761447614576146761477614876149761507615176152761537615476155761567615776158761597616076161761627616376164761657616676167761687616976170761717617276173761747617576176761777617876179761807618176182761837618476185761867618776188761897619076191761927619376194761957619676197761987619976200762017620276203762047620576206762077620876209762107621176212762137621476215762167621776218762197622076221762227622376224762257622676227762287622976230762317623276233762347623576236762377623876239762407624176242762437624476245762467624776248762497625076251762527625376254762557625676257762587625976260762617626276263762647626576266762677626876269762707627176272762737627476275762767627776278762797628076281762827628376284762857628676287762887628976290762917629276293762947629576296762977629876299763007630176302763037630476305763067630776308763097631076311763127631376314763157631676317763187631976320763217632276323763247632576326763277632876329763307633176332763337633476335763367633776338763397634076341763427634376344763457634676347763487634976350763517635276353763547635576356763577635876359763607636176362763637636476365763667636776368763697637076371763727637376374763757637676377763787637976380763817638276383763847638576386763877638876389763907639176392763937639476395763967639776398763997640076401764027640376404764057640676407764087640976410764117641276413764147641576416764177641876419764207642176422764237642476425764267642776428764297643076431764327643376434764357643676437764387643976440764417644276443764447644576446764477644876449764507645176452764537645476455764567645776458764597646076461764627646376464764657646676467764687646976470764717647276473764747647576476764777647876479764807648176482764837648476485764867648776488764897649076491764927649376494764957649676497764987649976500765017650276503765047650576506765077650876509765107651176512765137651476515765167651776518765197652076521765227652376524765257652676527765287652976530765317653276533765347653576536765377653876539765407654176542765437654476545765467654776548765497655076551765527655376554765557655676557765587655976560765617656276563765647656576566765677656876569765707657176572765737657476575765767657776578765797658076581765827658376584765857658676587765887658976590765917659276593765947659576596765977659876599766007660176602766037660476605766067660776608766097661076611766127661376614766157661676617766187661976620766217662276623766247662576626766277662876629766307663176632766337663476635766367663776638766397664076641766427664376644766457664676647766487664976650766517665276653766547665576656766577665876659766607666176662766637666476665766667666776668766697667076671766727667376674766757667676677766787667976680766817668276683766847668576686766877668876689766907669176692766937669476695766967669776698766997670076701767027670376704767057670676707767087670976710767117671276713767147671576716767177671876719767207672176722767237672476725767267672776728767297673076731767327673376734767357673676737767387673976740767417674276743767447674576746767477674876749767507675176752767537675476755767567675776758767597676076761767627676376764767657676676767767687676976770767717677276773767747677576776767777677876779767807678176782767837678476785767867678776788767897679076791767927679376794767957679676797767987679976800768017680276803768047680576806768077680876809768107681176812768137681476815768167681776818768197682076821768227682376824768257682676827768287682976830768317683276833768347683576836768377683876839768407684176842768437684476845768467684776848768497685076851768527685376854768557685676857768587685976860768617686276863768647686576866768677686876869768707687176872768737687476875768767687776878768797688076881768827688376884768857688676887768887688976890768917689276893768947689576896768977689876899769007690176902769037690476905769067690776908769097691076911769127691376914769157691676917769187691976920769217692276923769247692576926769277692876929769307693176932769337693476935769367693776938769397694076941769427694376944769457694676947769487694976950769517695276953769547695576956769577695876959769607696176962769637696476965769667696776968769697697076971769727697376974769757697676977769787697976980769817698276983769847698576986769877698876989769907699176992769937699476995769967699776998769997700077001770027700377004770057700677007770087700977010770117701277013770147701577016770177701877019770207702177022770237702477025770267702777028770297703077031770327703377034770357703677037770387703977040770417704277043770447704577046770477704877049770507705177052770537705477055770567705777058770597706077061770627706377064770657706677067770687706977070770717707277073770747707577076770777707877079770807708177082770837708477085770867708777088770897709077091770927709377094770957709677097770987709977100771017710277103771047710577106771077710877109771107711177112771137711477115771167711777118771197712077121771227712377124771257712677127771287712977130771317713277133771347713577136771377713877139771407714177142771437714477145771467714777148771497715077151771527715377154771557715677157771587715977160771617716277163771647716577166771677716877169771707717177172771737717477175771767717777178771797718077181771827718377184771857718677187771887718977190771917719277193771947719577196771977719877199772007720177202772037720477205772067720777208772097721077211772127721377214772157721677217772187721977220772217722277223772247722577226772277722877229772307723177232772337723477235772367723777238772397724077241772427724377244772457724677247772487724977250772517725277253772547725577256772577725877259772607726177262772637726477265772667726777268772697727077271772727727377274772757727677277772787727977280772817728277283772847728577286772877728877289772907729177292772937729477295772967729777298772997730077301773027730377304773057730677307773087730977310773117731277313773147731577316773177731877319773207732177322773237732477325773267732777328773297733077331773327733377334773357733677337773387733977340773417734277343773447734577346773477734877349773507735177352773537735477355773567735777358773597736077361773627736377364773657736677367773687736977370773717737277373773747737577376773777737877379773807738177382773837738477385773867738777388773897739077391773927739377394773957739677397773987739977400774017740277403774047740577406774077740877409774107741177412774137741477415774167741777418774197742077421774227742377424774257742677427774287742977430774317743277433774347743577436774377743877439774407744177442774437744477445774467744777448774497745077451774527745377454774557745677457774587745977460774617746277463774647746577466774677746877469774707747177472774737747477475774767747777478774797748077481774827748377484774857748677487774887748977490774917749277493774947749577496774977749877499775007750177502775037750477505775067750777508775097751077511775127751377514775157751677517775187751977520775217752277523775247752577526775277752877529775307753177532775337753477535775367753777538775397754077541775427754377544775457754677547775487754977550775517755277553775547755577556775577755877559775607756177562775637756477565775667756777568775697757077571775727757377574775757757677577775787757977580775817758277583775847758577586775877758877589775907759177592775937759477595775967759777598775997760077601776027760377604776057760677607776087760977610776117761277613776147761577616776177761877619776207762177622776237762477625776267762777628776297763077631776327763377634776357763677637776387763977640776417764277643776447764577646776477764877649776507765177652776537765477655776567765777658776597766077661776627766377664776657766677667776687766977670776717767277673776747767577676776777767877679776807768177682776837768477685776867768777688776897769077691776927769377694776957769677697776987769977700777017770277703777047770577706777077770877709777107771177712777137771477715777167771777718777197772077721777227772377724777257772677727777287772977730777317773277733777347773577736777377773877739777407774177742777437774477745777467774777748777497775077751777527775377754777557775677757777587775977760777617776277763777647776577766777677776877769777707777177772777737777477775777767777777778777797778077781777827778377784777857778677787777887778977790777917779277793777947779577796777977779877799778007780177802778037780477805778067780777808778097781077811778127781377814778157781677817778187781977820778217782277823778247782577826778277782877829778307783177832778337783477835778367783777838778397784077841778427784377844778457784677847778487784977850778517785277853778547785577856778577785877859778607786177862778637786477865778667786777868778697787077871778727787377874778757787677877778787787977880778817788277883778847788577886778877788877889778907789177892778937789477895778967789777898778997790077901779027790377904779057790677907779087790977910779117791277913779147791577916779177791877919779207792177922779237792477925779267792777928779297793077931779327793377934779357793677937779387793977940779417794277943779447794577946779477794877949779507795177952779537795477955779567795777958779597796077961779627796377964779657796677967779687796977970779717797277973779747797577976779777797877979779807798177982779837798477985779867798777988779897799077991779927799377994779957799677997779987799978000780017800278003780047800578006780077800878009780107801178012780137801478015780167801778018780197802078021780227802378024780257802678027780287802978030780317803278033780347803578036780377803878039780407804178042780437804478045780467804778048780497805078051780527805378054780557805678057780587805978060780617806278063780647806578066780677806878069780707807178072780737807478075780767807778078780797808078081780827808378084780857808678087780887808978090780917809278093780947809578096780977809878099781007810178102781037810478105781067810778108781097811078111781127811378114781157811678117781187811978120781217812278123781247812578126781277812878129781307813178132781337813478135781367813778138781397814078141781427814378144781457814678147781487814978150781517815278153781547815578156781577815878159781607816178162781637816478165781667816778168781697817078171781727817378174781757817678177781787817978180781817818278183781847818578186781877818878189781907819178192781937819478195781967819778198781997820078201782027820378204782057820678207782087820978210782117821278213782147821578216782177821878219782207822178222782237822478225782267822778228782297823078231782327823378234782357823678237782387823978240782417824278243782447824578246782477824878249782507825178252782537825478255782567825778258782597826078261782627826378264782657826678267782687826978270782717827278273782747827578276782777827878279782807828178282782837828478285782867828778288782897829078291782927829378294782957829678297782987829978300783017830278303783047830578306783077830878309783107831178312783137831478315783167831778318783197832078321783227832378324783257832678327783287832978330783317833278333783347833578336783377833878339783407834178342783437834478345783467834778348783497835078351783527835378354783557835678357783587835978360783617836278363783647836578366783677836878369783707837178372783737837478375783767837778378783797838078381783827838378384783857838678387783887838978390783917839278393783947839578396783977839878399784007840178402784037840478405784067840778408784097841078411784127841378414784157841678417784187841978420784217842278423784247842578426784277842878429784307843178432784337843478435784367843778438784397844078441784427844378444784457844678447784487844978450784517845278453784547845578456784577845878459784607846178462784637846478465784667846778468784697847078471784727847378474784757847678477784787847978480784817848278483784847848578486784877848878489784907849178492784937849478495784967849778498784997850078501785027850378504785057850678507785087850978510785117851278513785147851578516785177851878519785207852178522785237852478525785267852778528785297853078531785327853378534785357853678537785387853978540785417854278543785447854578546785477854878549785507855178552785537855478555785567855778558785597856078561785627856378564785657856678567785687856978570785717857278573785747857578576785777857878579785807858178582785837858478585785867858778588785897859078591785927859378594785957859678597785987859978600786017860278603786047860578606786077860878609786107861178612786137861478615786167861778618786197862078621786227862378624786257862678627786287862978630786317863278633786347863578636786377863878639786407864178642786437864478645786467864778648786497865078651786527865378654786557865678657786587865978660786617866278663786647866578666786677866878669786707867178672786737867478675786767867778678786797868078681786827868378684786857868678687786887868978690786917869278693786947869578696786977869878699787007870178702787037870478705787067870778708787097871078711787127871378714787157871678717787187871978720787217872278723787247872578726787277872878729787307873178732787337873478735787367873778738787397874078741787427874378744787457874678747787487874978750787517875278753787547875578756787577875878759787607876178762787637876478765787667876778768787697877078771787727877378774787757877678777787787877978780787817878278783787847878578786787877878878789787907879178792787937879478795787967879778798787997880078801788027880378804788057880678807788087880978810788117881278813788147881578816788177881878819788207882178822788237882478825788267882778828788297883078831788327883378834788357883678837788387883978840788417884278843788447884578846788477884878849788507885178852788537885478855788567885778858788597886078861788627886378864788657886678867788687886978870788717887278873788747887578876788777887878879788807888178882788837888478885788867888778888788897889078891788927889378894788957889678897788987889978900789017890278903789047890578906789077890878909789107891178912789137891478915789167891778918789197892078921789227892378924789257892678927789287892978930789317893278933789347893578936789377893878939789407894178942789437894478945789467894778948789497895078951789527895378954789557895678957789587895978960789617896278963789647896578966789677896878969789707897178972789737897478975789767897778978789797898078981789827898378984789857898678987789887898978990789917899278993789947899578996789977899878999790007900179002790037900479005790067900779008790097901079011790127901379014790157901679017790187901979020790217902279023790247902579026790277902879029790307903179032790337903479035790367903779038790397904079041790427904379044790457904679047790487904979050790517905279053790547905579056790577905879059790607906179062790637906479065790667906779068790697907079071790727907379074790757907679077790787907979080790817908279083790847908579086790877908879089790907909179092790937909479095790967909779098790997910079101791027910379104791057910679107791087910979110791117911279113791147911579116791177911879119791207912179122791237912479125791267912779128791297913079131791327913379134791357913679137791387913979140791417914279143791447914579146791477914879149791507915179152791537915479155791567915779158791597916079161791627916379164791657916679167791687916979170791717917279173791747917579176791777917879179791807918179182791837918479185791867918779188791897919079191791927919379194791957919679197791987919979200792017920279203792047920579206792077920879209792107921179212792137921479215792167921779218792197922079221792227922379224792257922679227792287922979230792317923279233792347923579236792377923879239792407924179242792437924479245792467924779248792497925079251792527925379254792557925679257792587925979260792617926279263792647926579266792677926879269792707927179272792737927479275792767927779278792797928079281792827928379284792857928679287792887928979290792917929279293792947929579296792977929879299793007930179302793037930479305793067930779308793097931079311793127931379314793157931679317793187931979320793217932279323793247932579326793277932879329793307933179332793337933479335793367933779338793397934079341793427934379344793457934679347793487934979350793517935279353793547935579356793577935879359793607936179362793637936479365793667936779368793697937079371793727937379374793757937679377793787937979380793817938279383793847938579386793877938879389793907939179392793937939479395793967939779398793997940079401794027940379404794057940679407794087940979410794117941279413794147941579416794177941879419794207942179422794237942479425794267942779428794297943079431794327943379434794357943679437794387943979440794417944279443794447944579446794477944879449794507945179452794537945479455794567945779458794597946079461794627946379464794657946679467794687946979470794717947279473794747947579476794777947879479794807948179482794837948479485794867948779488794897949079491794927949379494794957949679497794987949979500795017950279503795047950579506795077950879509795107951179512795137951479515795167951779518795197952079521795227952379524795257952679527795287952979530795317953279533795347953579536795377953879539795407954179542795437954479545795467954779548795497955079551795527955379554795557955679557795587955979560795617956279563795647956579566795677956879569795707957179572795737957479575795767957779578795797958079581795827958379584795857958679587795887958979590795917959279593795947959579596795977959879599796007960179602796037960479605796067960779608796097961079611796127961379614796157961679617796187961979620796217962279623796247962579626796277962879629796307963179632796337963479635796367963779638796397964079641796427964379644796457964679647796487964979650796517965279653796547965579656796577965879659796607966179662796637966479665796667966779668796697967079671796727967379674796757967679677796787967979680796817968279683796847968579686796877968879689796907969179692796937969479695796967969779698796997970079701797027970379704797057970679707797087970979710797117971279713797147971579716797177971879719797207972179722797237972479725797267972779728797297973079731797327973379734797357973679737797387973979740797417974279743797447974579746797477974879749797507975179752797537975479755797567975779758797597976079761797627976379764797657976679767797687976979770797717977279773797747977579776797777977879779797807978179782797837978479785797867978779788797897979079791797927979379794797957979679797797987979979800798017980279803798047980579806798077980879809798107981179812798137981479815798167981779818798197982079821798227982379824798257982679827798287982979830798317983279833798347983579836798377983879839798407984179842798437984479845798467984779848798497985079851798527985379854798557985679857798587985979860798617986279863798647986579866798677986879869798707987179872798737987479875798767987779878798797988079881798827988379884798857988679887798887988979890798917989279893798947989579896798977989879899799007990179902799037990479905799067990779908799097991079911799127991379914799157991679917799187991979920799217992279923799247992579926799277992879929799307993179932799337993479935799367993779938799397994079941799427994379944799457994679947799487994979950799517995279953799547995579956799577995879959799607996179962799637996479965799667996779968799697997079971799727997379974799757997679977799787997979980799817998279983799847998579986799877998879989799907999179992799937999479995799967999779998799998000080001800028000380004800058000680007800088000980010800118001280013800148001580016800178001880019800208002180022800238002480025800268002780028800298003080031800328003380034800358003680037800388003980040800418004280043800448004580046800478004880049800508005180052800538005480055800568005780058800598006080061800628006380064800658006680067800688006980070800718007280073800748007580076800778007880079800808008180082800838008480085800868008780088800898009080091800928009380094800958009680097800988009980100801018010280103801048010580106801078010880109801108011180112801138011480115801168011780118801198012080121801228012380124801258012680127801288012980130801318013280133801348013580136801378013880139801408014180142801438014480145801468014780148801498015080151801528015380154801558015680157801588015980160801618016280163801648016580166801678016880169801708017180172801738017480175801768017780178801798018080181801828018380184801858018680187801888018980190801918019280193801948019580196801978019880199802008020180202802038020480205802068020780208802098021080211802128021380214802158021680217802188021980220802218022280223802248022580226802278022880229802308023180232802338023480235802368023780238802398024080241802428024380244802458024680247802488024980250802518025280253802548025580256802578025880259802608026180262802638026480265802668026780268802698027080271802728027380274802758027680277802788027980280802818028280283802848028580286802878028880289802908029180292802938029480295802968029780298802998030080301803028030380304803058030680307803088030980310803118031280313803148031580316803178031880319803208032180322803238032480325803268032780328803298033080331803328033380334803358033680337803388033980340803418034280343803448034580346803478034880349803508035180352803538035480355803568035780358803598036080361803628036380364803658036680367803688036980370803718037280373803748037580376803778037880379803808038180382803838038480385803868038780388803898039080391803928039380394803958039680397803988039980400804018040280403804048040580406804078040880409804108041180412804138041480415804168041780418804198042080421804228042380424804258042680427804288042980430804318043280433804348043580436804378043880439804408044180442804438044480445804468044780448804498045080451804528045380454804558045680457804588045980460804618046280463804648046580466804678046880469804708047180472804738047480475804768047780478804798048080481804828048380484804858048680487804888048980490804918049280493804948049580496804978049880499805008050180502805038050480505805068050780508805098051080511805128051380514805158051680517805188051980520805218052280523805248052580526805278052880529805308053180532805338053480535805368053780538805398054080541805428054380544805458054680547805488054980550805518055280553805548055580556805578055880559805608056180562805638056480565805668056780568805698057080571805728057380574805758057680577805788057980580805818058280583805848058580586805878058880589805908059180592805938059480595805968059780598805998060080601806028060380604806058060680607806088060980610806118061280613806148061580616806178061880619806208062180622806238062480625806268062780628806298063080631806328063380634806358063680637806388063980640806418064280643806448064580646806478064880649806508065180652806538065480655806568065780658806598066080661806628066380664806658066680667806688066980670806718067280673806748067580676806778067880679
  1. /* sp.c
  2. *
  3. * Copyright (C) 2006-2023 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. /* Implementation by Sean Parkinson. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #include <wolfssl/wolfcrypt/settings.h>
  26. #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
  27. defined(WOLFSSL_HAVE_SP_ECC)
  28. #include <wolfssl/wolfcrypt/error-crypt.h>
  29. #include <wolfssl/wolfcrypt/cpuid.h>
  30. #ifdef NO_INLINE
  31. #include <wolfssl/wolfcrypt/misc.h>
  32. #else
  33. #define WOLFSSL_MISC_INCLUDED
  34. #include <wolfcrypt/src/misc.c>
  35. #endif
  36. #ifdef RSA_LOW_MEM
  37. #ifndef WOLFSSL_SP_SMALL
  38. #define WOLFSSL_SP_SMALL
  39. #endif
  40. #endif
  41. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42. #undef WOLFSSL_SP_SMALL_STACK
  43. #define WOLFSSL_SP_SMALL_STACK
  44. #endif
  45. #include <wolfssl/wolfcrypt/sp.h>
  46. #ifdef __IAR_SYSTEMS_ICC__
  47. #define __asm__ asm
  48. #define __volatile__ volatile
  49. #define WOLFSSL_NO_VAR_ASSIGN_REG
  50. #endif /* __IAR_SYSTEMS_ICC__ */
  51. #ifdef __KEIL__
  52. #define __asm__ __asm
  53. #define __volatile__ volatile
  54. #endif
  55. #ifdef WOLFSSL_SP_ARM_CORTEX_M_ASM
  56. #define SP_PRINT_NUM(var, name, total, words, bits) \
  57. do { \
  58. int ii; \
  59. fprintf(stderr, name "=0x"); \
  60. for (ii = ((bits + 31) / 32) - 1; ii >= 0; ii--) \
  61. fprintf(stderr, SP_PRINT_FMT, (var)[ii]); \
  62. fprintf(stderr, "\n"); \
  63. } while (0)
  64. #define SP_PRINT_VAL(var, name) \
  65. fprintf(stderr, name "=0x" SP_PRINT_FMT "\n", var)
  66. #define SP_PRINT_INT(var, name) \
  67. fprintf(stderr, name "=%d\n", var)
  68. #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
  69. #ifndef WOLFSSL_SP_NO_2048
  70. /* Read big endian unsigned byte array into r.
  71. *
  72. * r A single precision integer.
  73. * size Maximum number of bytes to convert
  74. * a Byte array.
  75. * n Number of bytes in array to read.
  76. */
  77. static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
  78. {
  79. int i;
  80. int j;
  81. byte* d;
  82. for (i = n - 1,j = 0; i >= 3; i -= 4) {
  83. r[j] = ((sp_digit)a[i - 0] << 0) |
  84. ((sp_digit)a[i - 1] << 8) |
  85. ((sp_digit)a[i - 2] << 16) |
  86. ((sp_digit)a[i - 3] << 24);
  87. j++;
  88. }
  89. if (i >= 0) {
  90. r[j] = 0;
  91. d = (byte*)r;
  92. switch (i) {
  93. case 2: d[n - 1 - 2] = a[2]; //fallthrough
  94. case 1: d[n - 1 - 1] = a[1]; //fallthrough
  95. case 0: d[n - 1 - 0] = a[0]; //fallthrough
  96. }
  97. j++;
  98. }
  99. for (; j < size; j++) {
  100. r[j] = 0;
  101. }
  102. }
  103. /* Convert an mp_int to an array of sp_digit.
  104. *
  105. * r A single precision integer.
  106. * size Maximum number of bytes to convert
  107. * a A multi-precision integer.
  108. */
  109. static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
  110. {
  111. #if DIGIT_BIT == 32
  112. int i;
  113. sp_digit j = (sp_digit)0 - (sp_digit)a->used;
  114. int o = 0;
  115. for (i = 0; i < size; i++) {
  116. sp_digit mask = (sp_digit)0 - (j >> 31);
  117. r[i] = a->dp[o] & mask;
  118. j++;
  119. o += (int)(j >> 31);
  120. }
  121. #elif DIGIT_BIT > 32
  122. unsigned int i;
  123. int j = 0;
  124. word32 s = 0;
  125. r[0] = 0;
  126. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  127. r[j] |= ((sp_digit)a->dp[i] << s);
  128. r[j] &= 0xffffffff;
  129. s = 32U - s;
  130. if (j + 1 >= size) {
  131. break;
  132. }
  133. /* lint allow cast of mismatch word32 and mp_digit */
  134. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  135. while ((s + 32U) <= (word32)DIGIT_BIT) {
  136. s += 32U;
  137. r[j] &= 0xffffffff;
  138. if (j + 1 >= size) {
  139. break;
  140. }
  141. if (s < (word32)DIGIT_BIT) {
  142. /* lint allow cast of mismatch word32 and mp_digit */
  143. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  144. }
  145. else {
  146. r[++j] = (sp_digit)0;
  147. }
  148. }
  149. s = (word32)DIGIT_BIT - s;
  150. }
  151. for (j++; j < size; j++) {
  152. r[j] = 0;
  153. }
  154. #else
  155. unsigned int i;
  156. int j = 0;
  157. int s = 0;
  158. r[0] = 0;
  159. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  160. r[j] |= ((sp_digit)a->dp[i]) << s;
  161. if (s + DIGIT_BIT >= 32) {
  162. r[j] &= 0xffffffff;
  163. if (j + 1 >= size) {
  164. break;
  165. }
  166. s = 32 - s;
  167. if (s == DIGIT_BIT) {
  168. r[++j] = 0;
  169. s = 0;
  170. }
  171. else {
  172. r[++j] = a->dp[i] >> s;
  173. s = DIGIT_BIT - s;
  174. }
  175. }
  176. else {
  177. s += DIGIT_BIT;
  178. }
  179. }
  180. for (j++; j < size; j++) {
  181. r[j] = 0;
  182. }
  183. #endif
  184. }
  185. /* Write r as big endian to byte array.
  186. * Fixed length number of bytes written: 256
  187. *
  188. * r A single precision integer.
  189. * a Byte array.
  190. */
  191. static void sp_2048_to_bin_64(sp_digit* r, byte* a)
  192. {
  193. int i;
  194. int j = 0;
  195. for (i = 63; i >= 0; i--) {
  196. a[j++] = r[i] >> 24;
  197. a[j++] = r[i] >> 16;
  198. a[j++] = r[i] >> 8;
  199. a[j++] = r[i] >> 0;
  200. }
  201. }
  202. #if (defined(WOLFSSL_HAVE_SP_RSA) && (!defined(WOLFSSL_RSA_PUBLIC_ONLY) || !defined(WOLFSSL_SP_SMALL))) || defined(WOLFSSL_HAVE_SP_DH)
  203. /* Normalize the values in each word to 32.
  204. *
  205. * a Array of sp_digit to normalize.
  206. */
  207. #define sp_2048_norm_64(a)
  208. #endif /* (WOLFSSL_HAVE_SP_RSA && (!WOLFSSL_RSA_PUBLIC_ONLY || !WOLFSSL_SP_SMALL)) || WOLFSSL_HAVE_SP_DH */
  209. /* Normalize the values in each word to 32.
  210. *
  211. * a Array of sp_digit to normalize.
  212. */
  213. #define sp_2048_norm_64(a)
  214. #ifndef WOLFSSL_SP_SMALL
  215. #ifdef WOLFSSL_SP_NO_UMAAL
  216. /* Multiply a and b into r. (r = a * b)
  217. *
  218. * r A single precision integer.
  219. * a A single precision integer.
  220. * b A single precision integer.
  221. */
  222. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  223. SP_NOINLINE static void sp_2048_mul_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  224. #else
  225. SP_NOINLINE static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  226. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  227. {
  228. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  229. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  230. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  231. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  232. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  233. __asm__ __volatile__ (
  234. "SUB sp, sp, #0x24\n\t"
  235. "STR %[r], [sp, #32]\n\t"
  236. "MOV %[r], #0x0\n\t"
  237. "LDR r12, [%[a]]\n\t"
  238. /* A[0] * B[0] */
  239. "LDR lr, [%[b]]\n\t"
  240. "UMULL r3, r4, r12, lr\n\t"
  241. /* A[0] * B[2] */
  242. "LDR lr, [%[b], #8]\n\t"
  243. "UMULL r5, r6, r12, lr\n\t"
  244. /* A[0] * B[4] */
  245. "LDR lr, [%[b], #16]\n\t"
  246. "UMULL r7, r8, r12, lr\n\t"
  247. /* A[0] * B[6] */
  248. "LDR lr, [%[b], #24]\n\t"
  249. "UMULL r9, r10, r12, lr\n\t"
  250. "STR r3, [sp]\n\t"
  251. /* A[0] * B[1] */
  252. "LDR lr, [%[b], #4]\n\t"
  253. "MOV r11, %[r]\n\t"
  254. "UMLAL r4, r11, r12, lr\n\t"
  255. "ADDS r5, r5, r11\n\t"
  256. /* A[0] * B[3] */
  257. "LDR lr, [%[b], #12]\n\t"
  258. "ADCS r6, r6, #0x0\n\t"
  259. "ADC r11, %[r], #0x0\n\t"
  260. "UMLAL r6, r11, r12, lr\n\t"
  261. "ADDS r7, r7, r11\n\t"
  262. /* A[0] * B[5] */
  263. "LDR lr, [%[b], #20]\n\t"
  264. "ADCS r8, r8, #0x0\n\t"
  265. "ADC r11, %[r], #0x0\n\t"
  266. "UMLAL r8, r11, r12, lr\n\t"
  267. "ADDS r9, r9, r11\n\t"
  268. /* A[0] * B[7] */
  269. "LDR lr, [%[b], #28]\n\t"
  270. "ADCS r10, r10, #0x0\n\t"
  271. "ADC r3, %[r], #0x0\n\t"
  272. "UMLAL r10, r3, r12, lr\n\t"
  273. /* A[1] * B[0] */
  274. "LDR r12, [%[a], #4]\n\t"
  275. "LDR lr, [%[b]]\n\t"
  276. "MOV r11, #0x0\n\t"
  277. "UMLAL r4, r11, r12, lr\n\t"
  278. "STR r4, [sp, #4]\n\t"
  279. "ADDS r5, r5, r11\n\t"
  280. /* A[1] * B[1] */
  281. "LDR lr, [%[b], #4]\n\t"
  282. "ADC r11, %[r], #0x0\n\t"
  283. "UMLAL r5, r11, r12, lr\n\t"
  284. "ADDS r6, r6, r11\n\t"
  285. /* A[1] * B[2] */
  286. "LDR lr, [%[b], #8]\n\t"
  287. "ADC r11, %[r], #0x0\n\t"
  288. "UMLAL r6, r11, r12, lr\n\t"
  289. "ADDS r7, r7, r11\n\t"
  290. /* A[1] * B[3] */
  291. "LDR lr, [%[b], #12]\n\t"
  292. "ADC r11, %[r], #0x0\n\t"
  293. "UMLAL r7, r11, r12, lr\n\t"
  294. "ADDS r8, r8, r11\n\t"
  295. /* A[1] * B[4] */
  296. "LDR lr, [%[b], #16]\n\t"
  297. "ADC r11, %[r], #0x0\n\t"
  298. "UMLAL r8, r11, r12, lr\n\t"
  299. "ADDS r9, r9, r11\n\t"
  300. /* A[1] * B[5] */
  301. "LDR lr, [%[b], #20]\n\t"
  302. "ADC r11, %[r], #0x0\n\t"
  303. "UMLAL r9, r11, r12, lr\n\t"
  304. "ADDS r10, r10, r11\n\t"
  305. /* A[1] * B[6] */
  306. "LDR lr, [%[b], #24]\n\t"
  307. "ADC r11, %[r], #0x0\n\t"
  308. "UMLAL r10, r11, r12, lr\n\t"
  309. "ADDS r3, r3, r11\n\t"
  310. /* A[1] * B[7] */
  311. "LDR lr, [%[b], #28]\n\t"
  312. "ADC r4, %[r], #0x0\n\t"
  313. "UMLAL r3, r4, r12, lr\n\t"
  314. /* A[2] * B[0] */
  315. "LDR r12, [%[a], #8]\n\t"
  316. "LDR lr, [%[b]]\n\t"
  317. "MOV r11, #0x0\n\t"
  318. "UMLAL r5, r11, r12, lr\n\t"
  319. "STR r5, [sp, #8]\n\t"
  320. "ADDS r6, r6, r11\n\t"
  321. /* A[2] * B[1] */
  322. "LDR lr, [%[b], #4]\n\t"
  323. "ADC r11, %[r], #0x0\n\t"
  324. "UMLAL r6, r11, r12, lr\n\t"
  325. "ADDS r7, r7, r11\n\t"
  326. /* A[2] * B[2] */
  327. "LDR lr, [%[b], #8]\n\t"
  328. "ADC r11, %[r], #0x0\n\t"
  329. "UMLAL r7, r11, r12, lr\n\t"
  330. "ADDS r8, r8, r11\n\t"
  331. /* A[2] * B[3] */
  332. "LDR lr, [%[b], #12]\n\t"
  333. "ADC r11, %[r], #0x0\n\t"
  334. "UMLAL r8, r11, r12, lr\n\t"
  335. "ADDS r9, r9, r11\n\t"
  336. /* A[2] * B[4] */
  337. "LDR lr, [%[b], #16]\n\t"
  338. "ADC r11, %[r], #0x0\n\t"
  339. "UMLAL r9, r11, r12, lr\n\t"
  340. "ADDS r10, r10, r11\n\t"
  341. /* A[2] * B[5] */
  342. "LDR lr, [%[b], #20]\n\t"
  343. "ADC r11, %[r], #0x0\n\t"
  344. "UMLAL r10, r11, r12, lr\n\t"
  345. "ADDS r3, r3, r11\n\t"
  346. /* A[2] * B[6] */
  347. "LDR lr, [%[b], #24]\n\t"
  348. "ADC r11, %[r], #0x0\n\t"
  349. "UMLAL r3, r11, r12, lr\n\t"
  350. "ADDS r4, r4, r11\n\t"
  351. /* A[2] * B[7] */
  352. "LDR lr, [%[b], #28]\n\t"
  353. "ADC r5, %[r], #0x0\n\t"
  354. "UMLAL r4, r5, r12, lr\n\t"
  355. /* A[3] * B[0] */
  356. "LDR r12, [%[a], #12]\n\t"
  357. "LDR lr, [%[b]]\n\t"
  358. "MOV r11, #0x0\n\t"
  359. "UMLAL r6, r11, r12, lr\n\t"
  360. "STR r6, [sp, #12]\n\t"
  361. "ADDS r7, r7, r11\n\t"
  362. /* A[3] * B[1] */
  363. "LDR lr, [%[b], #4]\n\t"
  364. "ADC r11, %[r], #0x0\n\t"
  365. "UMLAL r7, r11, r12, lr\n\t"
  366. "ADDS r8, r8, r11\n\t"
  367. /* A[3] * B[2] */
  368. "LDR lr, [%[b], #8]\n\t"
  369. "ADC r11, %[r], #0x0\n\t"
  370. "UMLAL r8, r11, r12, lr\n\t"
  371. "ADDS r9, r9, r11\n\t"
  372. /* A[3] * B[3] */
  373. "LDR lr, [%[b], #12]\n\t"
  374. "ADC r11, %[r], #0x0\n\t"
  375. "UMLAL r9, r11, r12, lr\n\t"
  376. "ADDS r10, r10, r11\n\t"
  377. /* A[3] * B[4] */
  378. "LDR lr, [%[b], #16]\n\t"
  379. "ADC r11, %[r], #0x0\n\t"
  380. "UMLAL r10, r11, r12, lr\n\t"
  381. "ADDS r3, r3, r11\n\t"
  382. /* A[3] * B[5] */
  383. "LDR lr, [%[b], #20]\n\t"
  384. "ADC r11, %[r], #0x0\n\t"
  385. "UMLAL r3, r11, r12, lr\n\t"
  386. "ADDS r4, r4, r11\n\t"
  387. /* A[3] * B[6] */
  388. "LDR lr, [%[b], #24]\n\t"
  389. "ADC r11, %[r], #0x0\n\t"
  390. "UMLAL r4, r11, r12, lr\n\t"
  391. "ADDS r5, r5, r11\n\t"
  392. /* A[3] * B[7] */
  393. "LDR lr, [%[b], #28]\n\t"
  394. "ADC r6, %[r], #0x0\n\t"
  395. "UMLAL r5, r6, r12, lr\n\t"
  396. /* A[4] * B[0] */
  397. "LDR r12, [%[a], #16]\n\t"
  398. "LDR lr, [%[b]]\n\t"
  399. "MOV r11, #0x0\n\t"
  400. "UMLAL r7, r11, r12, lr\n\t"
  401. "STR r7, [sp, #16]\n\t"
  402. "ADDS r8, r8, r11\n\t"
  403. /* A[4] * B[1] */
  404. "LDR lr, [%[b], #4]\n\t"
  405. "ADC r11, %[r], #0x0\n\t"
  406. "UMLAL r8, r11, r12, lr\n\t"
  407. "ADDS r9, r9, r11\n\t"
  408. /* A[4] * B[2] */
  409. "LDR lr, [%[b], #8]\n\t"
  410. "ADC r11, %[r], #0x0\n\t"
  411. "UMLAL r9, r11, r12, lr\n\t"
  412. "ADDS r10, r10, r11\n\t"
  413. /* A[4] * B[3] */
  414. "LDR lr, [%[b], #12]\n\t"
  415. "ADC r11, %[r], #0x0\n\t"
  416. "UMLAL r10, r11, r12, lr\n\t"
  417. "ADDS r3, r3, r11\n\t"
  418. /* A[4] * B[4] */
  419. "LDR lr, [%[b], #16]\n\t"
  420. "ADC r11, %[r], #0x0\n\t"
  421. "UMLAL r3, r11, r12, lr\n\t"
  422. "ADDS r4, r4, r11\n\t"
  423. /* A[4] * B[5] */
  424. "LDR lr, [%[b], #20]\n\t"
  425. "ADC r11, %[r], #0x0\n\t"
  426. "UMLAL r4, r11, r12, lr\n\t"
  427. "ADDS r5, r5, r11\n\t"
  428. /* A[4] * B[6] */
  429. "LDR lr, [%[b], #24]\n\t"
  430. "ADC r11, %[r], #0x0\n\t"
  431. "UMLAL r5, r11, r12, lr\n\t"
  432. "ADDS r6, r6, r11\n\t"
  433. /* A[4] * B[7] */
  434. "LDR lr, [%[b], #28]\n\t"
  435. "ADC r7, %[r], #0x0\n\t"
  436. "UMLAL r6, r7, r12, lr\n\t"
  437. /* A[5] * B[0] */
  438. "LDR r12, [%[a], #20]\n\t"
  439. "LDR lr, [%[b]]\n\t"
  440. "MOV r11, #0x0\n\t"
  441. "UMLAL r8, r11, r12, lr\n\t"
  442. "STR r8, [sp, #20]\n\t"
  443. "ADDS r9, r9, r11\n\t"
  444. /* A[5] * B[1] */
  445. "LDR lr, [%[b], #4]\n\t"
  446. "ADC r11, %[r], #0x0\n\t"
  447. "UMLAL r9, r11, r12, lr\n\t"
  448. "ADDS r10, r10, r11\n\t"
  449. /* A[5] * B[2] */
  450. "LDR lr, [%[b], #8]\n\t"
  451. "ADC r11, %[r], #0x0\n\t"
  452. "UMLAL r10, r11, r12, lr\n\t"
  453. "ADDS r3, r3, r11\n\t"
  454. /* A[5] * B[3] */
  455. "LDR lr, [%[b], #12]\n\t"
  456. "ADC r11, %[r], #0x0\n\t"
  457. "UMLAL r3, r11, r12, lr\n\t"
  458. "ADDS r4, r4, r11\n\t"
  459. /* A[5] * B[4] */
  460. "LDR lr, [%[b], #16]\n\t"
  461. "ADC r11, %[r], #0x0\n\t"
  462. "UMLAL r4, r11, r12, lr\n\t"
  463. "ADDS r5, r5, r11\n\t"
  464. /* A[5] * B[5] */
  465. "LDR lr, [%[b], #20]\n\t"
  466. "ADC r11, %[r], #0x0\n\t"
  467. "UMLAL r5, r11, r12, lr\n\t"
  468. "ADDS r6, r6, r11\n\t"
  469. /* A[5] * B[6] */
  470. "LDR lr, [%[b], #24]\n\t"
  471. "ADC r11, %[r], #0x0\n\t"
  472. "UMLAL r6, r11, r12, lr\n\t"
  473. "ADDS r7, r7, r11\n\t"
  474. /* A[5] * B[7] */
  475. "LDR lr, [%[b], #28]\n\t"
  476. "ADC r8, %[r], #0x0\n\t"
  477. "UMLAL r7, r8, r12, lr\n\t"
  478. /* A[6] * B[0] */
  479. "LDR r12, [%[a], #24]\n\t"
  480. "LDR lr, [%[b]]\n\t"
  481. "MOV r11, #0x0\n\t"
  482. "UMLAL r9, r11, r12, lr\n\t"
  483. "STR r9, [sp, #24]\n\t"
  484. "ADDS r10, r10, r11\n\t"
  485. /* A[6] * B[1] */
  486. "LDR lr, [%[b], #4]\n\t"
  487. "ADC r11, %[r], #0x0\n\t"
  488. "UMLAL r10, r11, r12, lr\n\t"
  489. "ADDS r3, r3, r11\n\t"
  490. /* A[6] * B[2] */
  491. "LDR lr, [%[b], #8]\n\t"
  492. "ADC r11, %[r], #0x0\n\t"
  493. "UMLAL r3, r11, r12, lr\n\t"
  494. "ADDS r4, r4, r11\n\t"
  495. /* A[6] * B[3] */
  496. "LDR lr, [%[b], #12]\n\t"
  497. "ADC r11, %[r], #0x0\n\t"
  498. "UMLAL r4, r11, r12, lr\n\t"
  499. "ADDS r5, r5, r11\n\t"
  500. /* A[6] * B[4] */
  501. "LDR lr, [%[b], #16]\n\t"
  502. "ADC r11, %[r], #0x0\n\t"
  503. "UMLAL r5, r11, r12, lr\n\t"
  504. "ADDS r6, r6, r11\n\t"
  505. /* A[6] * B[5] */
  506. "LDR lr, [%[b], #20]\n\t"
  507. "ADC r11, %[r], #0x0\n\t"
  508. "UMLAL r6, r11, r12, lr\n\t"
  509. "ADDS r7, r7, r11\n\t"
  510. /* A[6] * B[6] */
  511. "LDR lr, [%[b], #24]\n\t"
  512. "ADC r11, %[r], #0x0\n\t"
  513. "UMLAL r7, r11, r12, lr\n\t"
  514. "ADDS r8, r8, r11\n\t"
  515. /* A[6] * B[7] */
  516. "LDR lr, [%[b], #28]\n\t"
  517. "ADC r9, %[r], #0x0\n\t"
  518. "UMLAL r8, r9, r12, lr\n\t"
  519. /* A[7] * B[0] */
  520. "LDR r12, [%[a], #28]\n\t"
  521. "LDR lr, [%[b]]\n\t"
  522. "MOV r11, #0x0\n\t"
  523. "UMLAL r10, r11, r12, lr\n\t"
  524. "STR r10, [sp, #28]\n\t"
  525. "ADDS r3, r3, r11\n\t"
  526. /* A[7] * B[1] */
  527. "LDR lr, [%[b], #4]\n\t"
  528. "ADC r11, %[r], #0x0\n\t"
  529. "UMLAL r3, r11, r12, lr\n\t"
  530. "ADDS r4, r4, r11\n\t"
  531. /* A[7] * B[2] */
  532. "LDR lr, [%[b], #8]\n\t"
  533. "ADC r11, %[r], #0x0\n\t"
  534. "UMLAL r4, r11, r12, lr\n\t"
  535. "ADDS r5, r5, r11\n\t"
  536. /* A[7] * B[3] */
  537. "LDR lr, [%[b], #12]\n\t"
  538. "ADC r11, %[r], #0x0\n\t"
  539. "UMLAL r5, r11, r12, lr\n\t"
  540. "ADDS r6, r6, r11\n\t"
  541. /* A[7] * B[4] */
  542. "LDR lr, [%[b], #16]\n\t"
  543. "ADC r11, %[r], #0x0\n\t"
  544. "UMLAL r6, r11, r12, lr\n\t"
  545. "ADDS r7, r7, r11\n\t"
  546. /* A[7] * B[5] */
  547. "LDR lr, [%[b], #20]\n\t"
  548. "ADC r11, %[r], #0x0\n\t"
  549. "UMLAL r7, r11, r12, lr\n\t"
  550. "ADDS r8, r8, r11\n\t"
  551. /* A[7] * B[6] */
  552. "LDR lr, [%[b], #24]\n\t"
  553. "ADC r11, %[r], #0x0\n\t"
  554. "UMLAL r8, r11, r12, lr\n\t"
  555. "ADDS r9, r9, r11\n\t"
  556. /* A[7] * B[7] */
  557. "LDR lr, [%[b], #28]\n\t"
  558. "ADC r10, %[r], #0x0\n\t"
  559. "UMLAL r9, r10, r12, lr\n\t"
  560. "LDR %[r], [sp, #32]\n\t"
  561. "ADD %[r], %[r], #0x20\n\t"
  562. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  563. "LDM sp, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  564. "SUB %[r], %[r], #0x20\n\t"
  565. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  566. "ADD sp, sp, #0x24\n\t"
  567. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  568. :
  569. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  570. );
  571. }
  572. #else
  573. /* Multiply a and b into r. (r = a * b)
  574. *
  575. * r A single precision integer.
  576. * a A single precision integer.
  577. * b A single precision integer.
  578. */
  579. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  580. SP_NOINLINE static void sp_2048_mul_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  581. #else
  582. SP_NOINLINE static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  583. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  584. {
  585. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  586. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  587. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  588. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  589. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  590. __asm__ __volatile__ (
  591. "SUB sp, sp, #0x2c\n\t"
  592. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  593. "STRD %[r], %[a], [sp, #36]\n\t"
  594. #else
  595. "STR %[r], [sp, #36]\n\t"
  596. "STR %[a], [sp, #40]\n\t"
  597. #endif /* WOLFSSL_NO_VAR_ASSIGN_REG */
  598. "MOV lr, %[b]\n\t"
  599. "LDM %[a], {r0, r1, r2, r3}\n\t"
  600. "LDM lr!, {r4, r5, r6}\n\t"
  601. "UMULL r10, r11, r0, r4\n\t"
  602. "UMULL r12, r7, r1, r4\n\t"
  603. "UMAAL r11, r12, r0, r5\n\t"
  604. "UMULL r8, r9, r2, r4\n\t"
  605. "UMAAL r12, r8, r1, r5\n\t"
  606. "UMAAL r12, r7, r0, r6\n\t"
  607. "UMAAL r8, r9, r3, r4\n\t"
  608. "STM sp, {r10, r11, r12}\n\t"
  609. "UMAAL r7, r8, r2, r5\n\t"
  610. "LDM lr!, {r4}\n\t"
  611. "UMULL r10, r11, r1, r6\n\t"
  612. "UMAAL r8, r9, r2, r6\n\t"
  613. "UMAAL r7, r10, r0, r4\n\t"
  614. "UMAAL r8, r11, r3, r5\n\t"
  615. "STR r7, [sp, #12]\n\t"
  616. "UMAAL r8, r10, r1, r4\n\t"
  617. "UMAAL r9, r11, r3, r6\n\t"
  618. "UMAAL r9, r10, r2, r4\n\t"
  619. "UMAAL r10, r11, r3, r4\n\t"
  620. "LDM lr, {r4, r5, r6, r7}\n\t"
  621. "MOV r12, #0x0\n\t"
  622. "UMLAL r8, r12, r0, r4\n\t"
  623. "UMAAL r9, r12, r1, r4\n\t"
  624. "UMAAL r10, r12, r2, r4\n\t"
  625. "UMAAL r11, r12, r3, r4\n\t"
  626. "MOV r4, #0x0\n\t"
  627. "UMLAL r9, r4, r0, r5\n\t"
  628. "UMAAL r10, r4, r1, r5\n\t"
  629. "UMAAL r11, r4, r2, r5\n\t"
  630. "UMAAL r12, r4, r3, r5\n\t"
  631. "MOV r5, #0x0\n\t"
  632. "UMLAL r10, r5, r0, r6\n\t"
  633. "UMAAL r11, r5, r1, r6\n\t"
  634. "UMAAL r12, r5, r2, r6\n\t"
  635. "UMAAL r4, r5, r3, r6\n\t"
  636. "MOV r6, #0x0\n\t"
  637. "UMLAL r11, r6, r0, r7\n\t"
  638. "LDR r0, [sp, #40]\n\t"
  639. "UMAAL r12, r6, r1, r7\n\t"
  640. "ADD r0, r0, #0x10\n\t"
  641. "UMAAL r4, r6, r2, r7\n\t"
  642. "SUB lr, lr, #0x10\n\t"
  643. "UMAAL r5, r6, r3, r7\n\t"
  644. "LDM r0, {r0, r1, r2, r3}\n\t"
  645. "STR r6, [sp, #32]\n\t"
  646. "LDM lr!, {r6}\n\t"
  647. "MOV r7, #0x0\n\t"
  648. "UMLAL r8, r7, r0, r6\n\t"
  649. "UMAAL r9, r7, r1, r6\n\t"
  650. "STR r8, [sp, #16]\n\t"
  651. "UMAAL r10, r7, r2, r6\n\t"
  652. "UMAAL r11, r7, r3, r6\n\t"
  653. "LDM lr!, {r6}\n\t"
  654. "MOV r8, #0x0\n\t"
  655. "UMLAL r9, r8, r0, r6\n\t"
  656. "UMAAL r10, r8, r1, r6\n\t"
  657. "STR r9, [sp, #20]\n\t"
  658. "UMAAL r11, r8, r2, r6\n\t"
  659. "UMAAL r12, r8, r3, r6\n\t"
  660. "LDM lr!, {r6}\n\t"
  661. "MOV r9, #0x0\n\t"
  662. "UMLAL r10, r9, r0, r6\n\t"
  663. "UMAAL r11, r9, r1, r6\n\t"
  664. "STR r10, [sp, #24]\n\t"
  665. "UMAAL r12, r9, r2, r6\n\t"
  666. "UMAAL r4, r9, r3, r6\n\t"
  667. "LDM lr!, {r6}\n\t"
  668. "MOV r10, #0x0\n\t"
  669. "UMLAL r11, r10, r0, r6\n\t"
  670. "UMAAL r12, r10, r1, r6\n\t"
  671. "STR r11, [sp, #28]\n\t"
  672. "UMAAL r4, r10, r2, r6\n\t"
  673. "UMAAL r5, r10, r3, r6\n\t"
  674. "LDM lr!, {r11}\n\t"
  675. "UMAAL r12, r7, r0, r11\n\t"
  676. "UMAAL r4, r7, r1, r11\n\t"
  677. "LDR r6, [sp, #32]\n\t"
  678. "UMAAL r5, r7, r2, r11\n\t"
  679. "UMAAL r6, r7, r3, r11\n\t"
  680. "LDM lr!, {r11}\n\t"
  681. "UMAAL r4, r8, r0, r11\n\t"
  682. "UMAAL r5, r8, r1, r11\n\t"
  683. "UMAAL r6, r8, r2, r11\n\t"
  684. "UMAAL r7, r8, r3, r11\n\t"
  685. "LDM lr, {r11, lr}\n\t"
  686. "UMAAL r5, r9, r0, r11\n\t"
  687. "UMAAL r6, r10, r0, lr\n\t"
  688. "UMAAL r6, r9, r1, r11\n\t"
  689. "UMAAL r7, r10, r1, lr\n\t"
  690. "UMAAL r7, r9, r2, r11\n\t"
  691. "UMAAL r8, r10, r2, lr\n\t"
  692. "UMAAL r8, r9, r3, r11\n\t"
  693. "UMAAL r9, r10, r3, lr\n\t"
  694. "MOV r3, r12\n\t"
  695. "LDR lr, [sp, #36]\n\t"
  696. "ADD lr, lr, #0x20\n\t"
  697. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  698. "SUB lr, lr, #0x20\n\t"
  699. "LDM sp, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  700. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  701. "ADD sp, sp, #0x2c\n\t"
  702. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  703. :
  704. : "memory", "r3", "r4", "r5", "r6", "r10", "r11", "r12", "r7", "r8", "r9", "lr", "cc"
  705. );
  706. }
  707. #endif /* WOLFSSL_SP_NO_UMAAL */
  708. /* Add b to a into r. (r = a + b)
  709. *
  710. * r A single precision integer.
  711. * a A single precision integer.
  712. * b A single precision integer.
  713. */
  714. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  715. static sp_digit sp_2048_add_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  716. #else
  717. static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  718. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  719. {
  720. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  721. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  722. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  723. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  724. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  725. __asm__ __volatile__ (
  726. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  727. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  728. "ADDS r3, r3, r7\n\t"
  729. "ADCS r4, r4, r8\n\t"
  730. "ADCS r5, r5, r9\n\t"
  731. "ADCS r6, r6, r10\n\t"
  732. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  733. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  734. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  735. "ADCS r3, r3, r7\n\t"
  736. "ADCS r4, r4, r8\n\t"
  737. "ADCS r5, r5, r9\n\t"
  738. "ADCS r6, r6, r10\n\t"
  739. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  740. "MOV %[r], #0x0\n\t"
  741. "ADC %[r], %[r], #0x0\n\t"
  742. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  743. :
  744. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  745. );
  746. return (uint32_t)(size_t)r;
  747. }
  748. /* Sub b from a into a. (a -= b)
  749. *
  750. * a A single precision integer and result.
  751. * b A single precision integer.
  752. */
  753. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  754. static sp_digit sp_2048_sub_in_place_16(sp_digit* a_p, const sp_digit* b_p)
  755. #else
  756. static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b)
  757. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  758. {
  759. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  760. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  761. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  762. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  763. __asm__ __volatile__ (
  764. "LDM %[a], {r2, r3, r4, r5}\n\t"
  765. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  766. "SUBS r2, r2, r6\n\t"
  767. "SBCS r3, r3, r7\n\t"
  768. "SBCS r4, r4, r8\n\t"
  769. "SBCS r5, r5, r9\n\t"
  770. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  771. "LDM %[a], {r2, r3, r4, r5}\n\t"
  772. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  773. "SBCS r2, r2, r6\n\t"
  774. "SBCS r3, r3, r7\n\t"
  775. "SBCS r4, r4, r8\n\t"
  776. "SBCS r5, r5, r9\n\t"
  777. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  778. "LDM %[a], {r2, r3, r4, r5}\n\t"
  779. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  780. "SBCS r2, r2, r6\n\t"
  781. "SBCS r3, r3, r7\n\t"
  782. "SBCS r4, r4, r8\n\t"
  783. "SBCS r5, r5, r9\n\t"
  784. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  785. "LDM %[a], {r2, r3, r4, r5}\n\t"
  786. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  787. "SBCS r2, r2, r6\n\t"
  788. "SBCS r3, r3, r7\n\t"
  789. "SBCS r4, r4, r8\n\t"
  790. "SBCS r5, r5, r9\n\t"
  791. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  792. "SBC %[a], r9, r9\n\t"
  793. : [a] "+r" (a), [b] "+r" (b)
  794. :
  795. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  796. );
  797. return (uint32_t)(size_t)a;
  798. }
  799. /* Add b to a into r. (r = a + b)
  800. *
  801. * r A single precision integer.
  802. * a A single precision integer.
  803. * b A single precision integer.
  804. */
  805. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  806. static sp_digit sp_2048_add_16(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  807. #else
  808. static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b)
  809. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  810. {
  811. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  812. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  813. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  814. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  815. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  816. __asm__ __volatile__ (
  817. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  818. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  819. "ADDS r3, r3, r7\n\t"
  820. "ADCS r4, r4, r8\n\t"
  821. "ADCS r5, r5, r9\n\t"
  822. "ADCS r6, r6, r10\n\t"
  823. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  824. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  825. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  826. "ADCS r3, r3, r7\n\t"
  827. "ADCS r4, r4, r8\n\t"
  828. "ADCS r5, r5, r9\n\t"
  829. "ADCS r6, r6, r10\n\t"
  830. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  831. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  832. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  833. "ADCS r3, r3, r7\n\t"
  834. "ADCS r4, r4, r8\n\t"
  835. "ADCS r5, r5, r9\n\t"
  836. "ADCS r6, r6, r10\n\t"
  837. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  838. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  839. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  840. "ADCS r3, r3, r7\n\t"
  841. "ADCS r4, r4, r8\n\t"
  842. "ADCS r5, r5, r9\n\t"
  843. "ADCS r6, r6, r10\n\t"
  844. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  845. "MOV %[r], #0x0\n\t"
  846. "ADC %[r], %[r], #0x0\n\t"
  847. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  848. :
  849. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  850. );
  851. return (uint32_t)(size_t)r;
  852. }
  853. /* AND m into each word of a and store in r.
  854. *
  855. * r A single precision integer.
  856. * a A single precision integer.
  857. * m Mask to AND against each digit.
  858. */
  859. static void sp_2048_mask_8(sp_digit* r, const sp_digit* a, sp_digit m)
  860. {
  861. #ifdef WOLFSSL_SP_SMALL
  862. int i;
  863. for (i=0; i<8; i++) {
  864. r[i] = a[i] & m;
  865. }
  866. #else
  867. r[0] = a[0] & m;
  868. r[1] = a[1] & m;
  869. r[2] = a[2] & m;
  870. r[3] = a[3] & m;
  871. r[4] = a[4] & m;
  872. r[5] = a[5] & m;
  873. r[6] = a[6] & m;
  874. r[7] = a[7] & m;
  875. #endif
  876. }
  877. /* Multiply a and b into r. (r = a * b)
  878. *
  879. * r A single precision integer.
  880. * a A single precision integer.
  881. * b A single precision integer.
  882. */
  883. SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
  884. const sp_digit* b)
  885. {
  886. sp_digit* z0 = r;
  887. sp_digit z1[16];
  888. sp_digit a1[8];
  889. sp_digit b1[8];
  890. sp_digit* z2 = r + 16;
  891. sp_digit u;
  892. sp_digit ca;
  893. sp_digit cb;
  894. ca = sp_2048_add_8(a1, a, &a[8]);
  895. cb = sp_2048_add_8(b1, b, &b[8]);
  896. u = ca & cb;
  897. sp_2048_mul_8(z2, &a[8], &b[8]);
  898. sp_2048_mul_8(z0, a, b);
  899. sp_2048_mul_8(z1, a1, b1);
  900. u += sp_2048_sub_in_place_16(z1, z0);
  901. u += sp_2048_sub_in_place_16(z1, z2);
  902. sp_2048_mask_8(a1, a1, 0 - cb);
  903. u += sp_2048_add_8(z1 + 8, z1 + 8, a1);
  904. sp_2048_mask_8(b1, b1, 0 - ca);
  905. u += sp_2048_add_8(z1 + 8, z1 + 8, b1);
  906. u += sp_2048_add_16(r + 8, r + 8, z1);
  907. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (8 - 1));
  908. a1[0] = u;
  909. (void)sp_2048_add_8(r + 24, r + 24, a1);
  910. }
  911. /* Sub b from a into a. (a -= b)
  912. *
  913. * a A single precision integer and result.
  914. * b A single precision integer.
  915. */
  916. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  917. static sp_digit sp_2048_sub_in_place_32(sp_digit* a_p, const sp_digit* b_p)
  918. #else
  919. static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b)
  920. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  921. {
  922. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  923. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  924. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  925. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  926. __asm__ __volatile__ (
  927. "LDM %[a], {r2, r3, r4, r5}\n\t"
  928. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  929. "SUBS r2, r2, r6\n\t"
  930. "SBCS r3, r3, r7\n\t"
  931. "SBCS r4, r4, r8\n\t"
  932. "SBCS r5, r5, r9\n\t"
  933. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  934. "LDM %[a], {r2, r3, r4, r5}\n\t"
  935. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  936. "SBCS r2, r2, r6\n\t"
  937. "SBCS r3, r3, r7\n\t"
  938. "SBCS r4, r4, r8\n\t"
  939. "SBCS r5, r5, r9\n\t"
  940. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  941. "LDM %[a], {r2, r3, r4, r5}\n\t"
  942. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  943. "SBCS r2, r2, r6\n\t"
  944. "SBCS r3, r3, r7\n\t"
  945. "SBCS r4, r4, r8\n\t"
  946. "SBCS r5, r5, r9\n\t"
  947. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  948. "LDM %[a], {r2, r3, r4, r5}\n\t"
  949. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  950. "SBCS r2, r2, r6\n\t"
  951. "SBCS r3, r3, r7\n\t"
  952. "SBCS r4, r4, r8\n\t"
  953. "SBCS r5, r5, r9\n\t"
  954. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  955. "LDM %[a], {r2, r3, r4, r5}\n\t"
  956. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  957. "SBCS r2, r2, r6\n\t"
  958. "SBCS r3, r3, r7\n\t"
  959. "SBCS r4, r4, r8\n\t"
  960. "SBCS r5, r5, r9\n\t"
  961. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  962. "LDM %[a], {r2, r3, r4, r5}\n\t"
  963. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  964. "SBCS r2, r2, r6\n\t"
  965. "SBCS r3, r3, r7\n\t"
  966. "SBCS r4, r4, r8\n\t"
  967. "SBCS r5, r5, r9\n\t"
  968. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  969. "LDM %[a], {r2, r3, r4, r5}\n\t"
  970. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  971. "SBCS r2, r2, r6\n\t"
  972. "SBCS r3, r3, r7\n\t"
  973. "SBCS r4, r4, r8\n\t"
  974. "SBCS r5, r5, r9\n\t"
  975. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  976. "LDM %[a], {r2, r3, r4, r5}\n\t"
  977. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  978. "SBCS r2, r2, r6\n\t"
  979. "SBCS r3, r3, r7\n\t"
  980. "SBCS r4, r4, r8\n\t"
  981. "SBCS r5, r5, r9\n\t"
  982. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  983. "SBC %[a], r9, r9\n\t"
  984. : [a] "+r" (a), [b] "+r" (b)
  985. :
  986. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  987. );
  988. return (uint32_t)(size_t)a;
  989. }
  990. /* Add b to a into r. (r = a + b)
  991. *
  992. * r A single precision integer.
  993. * a A single precision integer.
  994. * b A single precision integer.
  995. */
  996. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  997. static sp_digit sp_2048_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  998. #else
  999. static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
  1000. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1001. {
  1002. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1003. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  1004. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  1005. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  1006. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1007. __asm__ __volatile__ (
  1008. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1009. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1010. "ADDS r3, r3, r7\n\t"
  1011. "ADCS r4, r4, r8\n\t"
  1012. "ADCS r5, r5, r9\n\t"
  1013. "ADCS r6, r6, r10\n\t"
  1014. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1015. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1016. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1017. "ADCS r3, r3, r7\n\t"
  1018. "ADCS r4, r4, r8\n\t"
  1019. "ADCS r5, r5, r9\n\t"
  1020. "ADCS r6, r6, r10\n\t"
  1021. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1022. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1023. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1024. "ADCS r3, r3, r7\n\t"
  1025. "ADCS r4, r4, r8\n\t"
  1026. "ADCS r5, r5, r9\n\t"
  1027. "ADCS r6, r6, r10\n\t"
  1028. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1029. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1030. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1031. "ADCS r3, r3, r7\n\t"
  1032. "ADCS r4, r4, r8\n\t"
  1033. "ADCS r5, r5, r9\n\t"
  1034. "ADCS r6, r6, r10\n\t"
  1035. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1036. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1037. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1038. "ADCS r3, r3, r7\n\t"
  1039. "ADCS r4, r4, r8\n\t"
  1040. "ADCS r5, r5, r9\n\t"
  1041. "ADCS r6, r6, r10\n\t"
  1042. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1043. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1044. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1045. "ADCS r3, r3, r7\n\t"
  1046. "ADCS r4, r4, r8\n\t"
  1047. "ADCS r5, r5, r9\n\t"
  1048. "ADCS r6, r6, r10\n\t"
  1049. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1050. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1051. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1052. "ADCS r3, r3, r7\n\t"
  1053. "ADCS r4, r4, r8\n\t"
  1054. "ADCS r5, r5, r9\n\t"
  1055. "ADCS r6, r6, r10\n\t"
  1056. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1057. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1058. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1059. "ADCS r3, r3, r7\n\t"
  1060. "ADCS r4, r4, r8\n\t"
  1061. "ADCS r5, r5, r9\n\t"
  1062. "ADCS r6, r6, r10\n\t"
  1063. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1064. "MOV %[r], #0x0\n\t"
  1065. "ADC %[r], %[r], #0x0\n\t"
  1066. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  1067. :
  1068. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  1069. );
  1070. return (uint32_t)(size_t)r;
  1071. }
  1072. /* AND m into each word of a and store in r.
  1073. *
  1074. * r A single precision integer.
  1075. * a A single precision integer.
  1076. * m Mask to AND against each digit.
  1077. */
  1078. static void sp_2048_mask_16(sp_digit* r, const sp_digit* a, sp_digit m)
  1079. {
  1080. #ifdef WOLFSSL_SP_SMALL
  1081. int i;
  1082. for (i=0; i<16; i++) {
  1083. r[i] = a[i] & m;
  1084. }
  1085. #else
  1086. int i;
  1087. for (i = 0; i < 16; i += 8) {
  1088. r[i+0] = a[i+0] & m;
  1089. r[i+1] = a[i+1] & m;
  1090. r[i+2] = a[i+2] & m;
  1091. r[i+3] = a[i+3] & m;
  1092. r[i+4] = a[i+4] & m;
  1093. r[i+5] = a[i+5] & m;
  1094. r[i+6] = a[i+6] & m;
  1095. r[i+7] = a[i+7] & m;
  1096. }
  1097. #endif
  1098. }
  1099. /* Multiply a and b into r. (r = a * b)
  1100. *
  1101. * r A single precision integer.
  1102. * a A single precision integer.
  1103. * b A single precision integer.
  1104. */
  1105. SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
  1106. const sp_digit* b)
  1107. {
  1108. sp_digit* z0 = r;
  1109. sp_digit z1[32];
  1110. sp_digit a1[16];
  1111. sp_digit b1[16];
  1112. sp_digit* z2 = r + 32;
  1113. sp_digit u;
  1114. sp_digit ca;
  1115. sp_digit cb;
  1116. ca = sp_2048_add_16(a1, a, &a[16]);
  1117. cb = sp_2048_add_16(b1, b, &b[16]);
  1118. u = ca & cb;
  1119. sp_2048_mul_16(z2, &a[16], &b[16]);
  1120. sp_2048_mul_16(z0, a, b);
  1121. sp_2048_mul_16(z1, a1, b1);
  1122. u += sp_2048_sub_in_place_32(z1, z0);
  1123. u += sp_2048_sub_in_place_32(z1, z2);
  1124. sp_2048_mask_16(a1, a1, 0 - cb);
  1125. u += sp_2048_add_16(z1 + 16, z1 + 16, a1);
  1126. sp_2048_mask_16(b1, b1, 0 - ca);
  1127. u += sp_2048_add_16(z1 + 16, z1 + 16, b1);
  1128. u += sp_2048_add_32(r + 16, r + 16, z1);
  1129. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (16 - 1));
  1130. a1[0] = u;
  1131. (void)sp_2048_add_16(r + 48, r + 48, a1);
  1132. }
  1133. /* Sub b from a into a. (a -= b)
  1134. *
  1135. * a A single precision integer and result.
  1136. * b A single precision integer.
  1137. */
  1138. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1139. static sp_digit sp_2048_sub_in_place_64(sp_digit* a_p, const sp_digit* b_p)
  1140. #else
  1141. static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b)
  1142. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1143. {
  1144. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1145. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  1146. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  1147. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1148. __asm__ __volatile__ (
  1149. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1150. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1151. "SUBS r2, r2, r6\n\t"
  1152. "SBCS r3, r3, r7\n\t"
  1153. "SBCS r4, r4, r8\n\t"
  1154. "SBCS r5, r5, r9\n\t"
  1155. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1156. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1157. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1158. "SBCS r2, r2, r6\n\t"
  1159. "SBCS r3, r3, r7\n\t"
  1160. "SBCS r4, r4, r8\n\t"
  1161. "SBCS r5, r5, r9\n\t"
  1162. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1163. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1164. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1165. "SBCS r2, r2, r6\n\t"
  1166. "SBCS r3, r3, r7\n\t"
  1167. "SBCS r4, r4, r8\n\t"
  1168. "SBCS r5, r5, r9\n\t"
  1169. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1170. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1171. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1172. "SBCS r2, r2, r6\n\t"
  1173. "SBCS r3, r3, r7\n\t"
  1174. "SBCS r4, r4, r8\n\t"
  1175. "SBCS r5, r5, r9\n\t"
  1176. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1177. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1178. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1179. "SBCS r2, r2, r6\n\t"
  1180. "SBCS r3, r3, r7\n\t"
  1181. "SBCS r4, r4, r8\n\t"
  1182. "SBCS r5, r5, r9\n\t"
  1183. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1184. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1185. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1186. "SBCS r2, r2, r6\n\t"
  1187. "SBCS r3, r3, r7\n\t"
  1188. "SBCS r4, r4, r8\n\t"
  1189. "SBCS r5, r5, r9\n\t"
  1190. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1191. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1192. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1193. "SBCS r2, r2, r6\n\t"
  1194. "SBCS r3, r3, r7\n\t"
  1195. "SBCS r4, r4, r8\n\t"
  1196. "SBCS r5, r5, r9\n\t"
  1197. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1198. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1199. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1200. "SBCS r2, r2, r6\n\t"
  1201. "SBCS r3, r3, r7\n\t"
  1202. "SBCS r4, r4, r8\n\t"
  1203. "SBCS r5, r5, r9\n\t"
  1204. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1205. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1206. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1207. "SBCS r2, r2, r6\n\t"
  1208. "SBCS r3, r3, r7\n\t"
  1209. "SBCS r4, r4, r8\n\t"
  1210. "SBCS r5, r5, r9\n\t"
  1211. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1212. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1213. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1214. "SBCS r2, r2, r6\n\t"
  1215. "SBCS r3, r3, r7\n\t"
  1216. "SBCS r4, r4, r8\n\t"
  1217. "SBCS r5, r5, r9\n\t"
  1218. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1219. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1220. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1221. "SBCS r2, r2, r6\n\t"
  1222. "SBCS r3, r3, r7\n\t"
  1223. "SBCS r4, r4, r8\n\t"
  1224. "SBCS r5, r5, r9\n\t"
  1225. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1226. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1227. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1228. "SBCS r2, r2, r6\n\t"
  1229. "SBCS r3, r3, r7\n\t"
  1230. "SBCS r4, r4, r8\n\t"
  1231. "SBCS r5, r5, r9\n\t"
  1232. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1233. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1234. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1235. "SBCS r2, r2, r6\n\t"
  1236. "SBCS r3, r3, r7\n\t"
  1237. "SBCS r4, r4, r8\n\t"
  1238. "SBCS r5, r5, r9\n\t"
  1239. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1240. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1241. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1242. "SBCS r2, r2, r6\n\t"
  1243. "SBCS r3, r3, r7\n\t"
  1244. "SBCS r4, r4, r8\n\t"
  1245. "SBCS r5, r5, r9\n\t"
  1246. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1247. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1248. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1249. "SBCS r2, r2, r6\n\t"
  1250. "SBCS r3, r3, r7\n\t"
  1251. "SBCS r4, r4, r8\n\t"
  1252. "SBCS r5, r5, r9\n\t"
  1253. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1254. "LDM %[a], {r2, r3, r4, r5}\n\t"
  1255. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  1256. "SBCS r2, r2, r6\n\t"
  1257. "SBCS r3, r3, r7\n\t"
  1258. "SBCS r4, r4, r8\n\t"
  1259. "SBCS r5, r5, r9\n\t"
  1260. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  1261. "SBC %[a], r9, r9\n\t"
  1262. : [a] "+r" (a), [b] "+r" (b)
  1263. :
  1264. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  1265. );
  1266. return (uint32_t)(size_t)a;
  1267. }
  1268. /* Add b to a into r. (r = a + b)
  1269. *
  1270. * r A single precision integer.
  1271. * a A single precision integer.
  1272. * b A single precision integer.
  1273. */
  1274. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1275. static sp_digit sp_2048_add_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  1276. #else
  1277. static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b)
  1278. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1279. {
  1280. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1281. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  1282. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  1283. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  1284. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1285. __asm__ __volatile__ (
  1286. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1287. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1288. "ADDS r3, r3, r7\n\t"
  1289. "ADCS r4, r4, r8\n\t"
  1290. "ADCS r5, r5, r9\n\t"
  1291. "ADCS r6, r6, r10\n\t"
  1292. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1293. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1294. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1295. "ADCS r3, r3, r7\n\t"
  1296. "ADCS r4, r4, r8\n\t"
  1297. "ADCS r5, r5, r9\n\t"
  1298. "ADCS r6, r6, r10\n\t"
  1299. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1300. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1301. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1302. "ADCS r3, r3, r7\n\t"
  1303. "ADCS r4, r4, r8\n\t"
  1304. "ADCS r5, r5, r9\n\t"
  1305. "ADCS r6, r6, r10\n\t"
  1306. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1307. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1308. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1309. "ADCS r3, r3, r7\n\t"
  1310. "ADCS r4, r4, r8\n\t"
  1311. "ADCS r5, r5, r9\n\t"
  1312. "ADCS r6, r6, r10\n\t"
  1313. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1314. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1315. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1316. "ADCS r3, r3, r7\n\t"
  1317. "ADCS r4, r4, r8\n\t"
  1318. "ADCS r5, r5, r9\n\t"
  1319. "ADCS r6, r6, r10\n\t"
  1320. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1321. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1322. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1323. "ADCS r3, r3, r7\n\t"
  1324. "ADCS r4, r4, r8\n\t"
  1325. "ADCS r5, r5, r9\n\t"
  1326. "ADCS r6, r6, r10\n\t"
  1327. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1328. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1329. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1330. "ADCS r3, r3, r7\n\t"
  1331. "ADCS r4, r4, r8\n\t"
  1332. "ADCS r5, r5, r9\n\t"
  1333. "ADCS r6, r6, r10\n\t"
  1334. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1335. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1336. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1337. "ADCS r3, r3, r7\n\t"
  1338. "ADCS r4, r4, r8\n\t"
  1339. "ADCS r5, r5, r9\n\t"
  1340. "ADCS r6, r6, r10\n\t"
  1341. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1342. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1343. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1344. "ADCS r3, r3, r7\n\t"
  1345. "ADCS r4, r4, r8\n\t"
  1346. "ADCS r5, r5, r9\n\t"
  1347. "ADCS r6, r6, r10\n\t"
  1348. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1349. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1350. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1351. "ADCS r3, r3, r7\n\t"
  1352. "ADCS r4, r4, r8\n\t"
  1353. "ADCS r5, r5, r9\n\t"
  1354. "ADCS r6, r6, r10\n\t"
  1355. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1356. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1357. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1358. "ADCS r3, r3, r7\n\t"
  1359. "ADCS r4, r4, r8\n\t"
  1360. "ADCS r5, r5, r9\n\t"
  1361. "ADCS r6, r6, r10\n\t"
  1362. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1363. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1364. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1365. "ADCS r3, r3, r7\n\t"
  1366. "ADCS r4, r4, r8\n\t"
  1367. "ADCS r5, r5, r9\n\t"
  1368. "ADCS r6, r6, r10\n\t"
  1369. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1370. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1371. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1372. "ADCS r3, r3, r7\n\t"
  1373. "ADCS r4, r4, r8\n\t"
  1374. "ADCS r5, r5, r9\n\t"
  1375. "ADCS r6, r6, r10\n\t"
  1376. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1377. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1378. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1379. "ADCS r3, r3, r7\n\t"
  1380. "ADCS r4, r4, r8\n\t"
  1381. "ADCS r5, r5, r9\n\t"
  1382. "ADCS r6, r6, r10\n\t"
  1383. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1384. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1385. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1386. "ADCS r3, r3, r7\n\t"
  1387. "ADCS r4, r4, r8\n\t"
  1388. "ADCS r5, r5, r9\n\t"
  1389. "ADCS r6, r6, r10\n\t"
  1390. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1391. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1392. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1393. "ADCS r3, r3, r7\n\t"
  1394. "ADCS r4, r4, r8\n\t"
  1395. "ADCS r5, r5, r9\n\t"
  1396. "ADCS r6, r6, r10\n\t"
  1397. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1398. "MOV %[r], #0x0\n\t"
  1399. "ADC %[r], %[r], #0x0\n\t"
  1400. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  1401. :
  1402. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  1403. );
  1404. return (uint32_t)(size_t)r;
  1405. }
  1406. /* AND m into each word of a and store in r.
  1407. *
  1408. * r A single precision integer.
  1409. * a A single precision integer.
  1410. * m Mask to AND against each digit.
  1411. */
  1412. static void sp_2048_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
  1413. {
  1414. #ifdef WOLFSSL_SP_SMALL
  1415. int i;
  1416. for (i=0; i<32; i++) {
  1417. r[i] = a[i] & m;
  1418. }
  1419. #else
  1420. int i;
  1421. for (i = 0; i < 32; i += 8) {
  1422. r[i+0] = a[i+0] & m;
  1423. r[i+1] = a[i+1] & m;
  1424. r[i+2] = a[i+2] & m;
  1425. r[i+3] = a[i+3] & m;
  1426. r[i+4] = a[i+4] & m;
  1427. r[i+5] = a[i+5] & m;
  1428. r[i+6] = a[i+6] & m;
  1429. r[i+7] = a[i+7] & m;
  1430. }
  1431. #endif
  1432. }
  1433. /* Multiply a and b into r. (r = a * b)
  1434. *
  1435. * r A single precision integer.
  1436. * a A single precision integer.
  1437. * b A single precision integer.
  1438. */
  1439. SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a,
  1440. const sp_digit* b)
  1441. {
  1442. sp_digit* z0 = r;
  1443. sp_digit z1[64];
  1444. sp_digit a1[32];
  1445. sp_digit b1[32];
  1446. sp_digit* z2 = r + 64;
  1447. sp_digit u;
  1448. sp_digit ca;
  1449. sp_digit cb;
  1450. ca = sp_2048_add_32(a1, a, &a[32]);
  1451. cb = sp_2048_add_32(b1, b, &b[32]);
  1452. u = ca & cb;
  1453. sp_2048_mul_32(z2, &a[32], &b[32]);
  1454. sp_2048_mul_32(z0, a, b);
  1455. sp_2048_mul_32(z1, a1, b1);
  1456. u += sp_2048_sub_in_place_64(z1, z0);
  1457. u += sp_2048_sub_in_place_64(z1, z2);
  1458. sp_2048_mask_32(a1, a1, 0 - cb);
  1459. u += sp_2048_add_32(z1 + 32, z1 + 32, a1);
  1460. sp_2048_mask_32(b1, b1, 0 - ca);
  1461. u += sp_2048_add_32(z1 + 32, z1 + 32, b1);
  1462. u += sp_2048_add_64(r + 32, r + 32, z1);
  1463. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (32 - 1));
  1464. a1[0] = u;
  1465. (void)sp_2048_add_32(r + 96, r + 96, a1);
  1466. }
  1467. #ifdef WOLFSSL_SP_NO_UMAAL
  1468. /* Square a and put result in r. (r = a * a)
  1469. *
  1470. * r A single precision integer.
  1471. * a A single precision integer.
  1472. */
  1473. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1474. SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r_p, const sp_digit* a_p)
  1475. #else
  1476. SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
  1477. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1478. {
  1479. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1480. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  1481. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  1482. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1483. __asm__ __volatile__ (
  1484. "SUB sp, sp, #0x44\n\t"
  1485. "STR %[r], [sp, #64]\n\t"
  1486. "MOV %[r], #0x0\n\t"
  1487. "LDR r12, [%[a]]\n\t"
  1488. /* A[0] * A[1] */
  1489. "LDR lr, [%[a], #4]\n\t"
  1490. "UMULL r4, r5, r12, lr\n\t"
  1491. /* A[0] * A[3] */
  1492. "LDR lr, [%[a], #12]\n\t"
  1493. "UMULL r6, r7, r12, lr\n\t"
  1494. /* A[0] * A[5] */
  1495. "LDR lr, [%[a], #20]\n\t"
  1496. "UMULL r8, r9, r12, lr\n\t"
  1497. /* A[0] * A[7] */
  1498. "LDR lr, [%[a], #28]\n\t"
  1499. "UMULL r10, r3, r12, lr\n\t"
  1500. /* A[0] * A[2] */
  1501. "LDR lr, [%[a], #8]\n\t"
  1502. "MOV r11, #0x0\n\t"
  1503. "UMLAL r5, r11, r12, lr\n\t"
  1504. "ADDS r6, r6, r11\n\t"
  1505. /* A[0] * A[4] */
  1506. "LDR lr, [%[a], #16]\n\t"
  1507. "ADCS r7, r7, #0x0\n\t"
  1508. "ADC r11, %[r], #0x0\n\t"
  1509. "UMLAL r7, r11, r12, lr\n\t"
  1510. "ADDS r8, r8, r11\n\t"
  1511. /* A[0] * A[6] */
  1512. "LDR lr, [%[a], #24]\n\t"
  1513. "ADCS r9, r9, #0x0\n\t"
  1514. "ADC r11, %[r], #0x0\n\t"
  1515. "UMLAL r9, r11, r12, lr\n\t"
  1516. "ADDS r10, r10, r11\n\t"
  1517. "ADCS r3, r3, #0x0\n\t"
  1518. "STR r4, [sp, #4]\n\t"
  1519. "STR r5, [sp, #8]\n\t"
  1520. /* A[1] * A[2] */
  1521. "LDR r12, [%[a], #4]\n\t"
  1522. "LDR lr, [%[a], #8]\n\t"
  1523. "MOV r11, #0x0\n\t"
  1524. "UMLAL r6, r11, r12, lr\n\t"
  1525. "STR r6, [sp, #12]\n\t"
  1526. "ADDS r7, r7, r11\n\t"
  1527. /* A[1] * A[3] */
  1528. "LDR lr, [%[a], #12]\n\t"
  1529. "ADC r11, %[r], #0x0\n\t"
  1530. "UMLAL r7, r11, r12, lr\n\t"
  1531. "STR r7, [sp, #16]\n\t"
  1532. "ADDS r8, r8, r11\n\t"
  1533. /* A[1] * A[4] */
  1534. "LDR lr, [%[a], #16]\n\t"
  1535. "ADC r11, %[r], #0x0\n\t"
  1536. "UMLAL r8, r11, r12, lr\n\t"
  1537. "ADDS r9, r9, r11\n\t"
  1538. /* A[1] * A[5] */
  1539. "LDR lr, [%[a], #20]\n\t"
  1540. "ADC r11, %[r], #0x0\n\t"
  1541. "UMLAL r9, r11, r12, lr\n\t"
  1542. "ADDS r10, r10, r11\n\t"
  1543. /* A[1] * A[6] */
  1544. "LDR lr, [%[a], #24]\n\t"
  1545. "ADC r11, %[r], #0x0\n\t"
  1546. "UMLAL r10, r11, r12, lr\n\t"
  1547. "ADDS r3, r3, r11\n\t"
  1548. /* A[1] * A[7] */
  1549. "LDR lr, [%[a], #28]\n\t"
  1550. "ADC r4, %[r], #0x0\n\t"
  1551. "UMLAL r3, r4, r12, lr\n\t"
  1552. /* A[2] * A[3] */
  1553. "LDR r12, [%[a], #8]\n\t"
  1554. "LDR lr, [%[a], #12]\n\t"
  1555. "MOV r11, #0x0\n\t"
  1556. "UMLAL r8, r11, r12, lr\n\t"
  1557. "STR r8, [sp, #20]\n\t"
  1558. "ADDS r9, r9, r11\n\t"
  1559. /* A[2] * A[4] */
  1560. "LDR lr, [%[a], #16]\n\t"
  1561. "ADC r11, %[r], #0x0\n\t"
  1562. "UMLAL r9, r11, r12, lr\n\t"
  1563. "STR r9, [sp, #24]\n\t"
  1564. "ADDS r10, r10, r11\n\t"
  1565. /* A[2] * A[5] */
  1566. "LDR lr, [%[a], #20]\n\t"
  1567. "ADC r11, %[r], #0x0\n\t"
  1568. "UMLAL r10, r11, r12, lr\n\t"
  1569. "ADDS r3, r3, r11\n\t"
  1570. /* A[2] * A[6] */
  1571. "LDR lr, [%[a], #24]\n\t"
  1572. "ADC r11, %[r], #0x0\n\t"
  1573. "UMLAL r3, r11, r12, lr\n\t"
  1574. "ADDS r4, r4, r11\n\t"
  1575. /* A[2] * A[7] */
  1576. "LDR lr, [%[a], #28]\n\t"
  1577. "ADC r5, %[r], #0x0\n\t"
  1578. "UMLAL r4, r5, r12, lr\n\t"
  1579. /* A[3] * A[4] */
  1580. "LDR r12, [%[a], #12]\n\t"
  1581. "LDR lr, [%[a], #16]\n\t"
  1582. "MOV r11, #0x0\n\t"
  1583. "UMLAL r10, r11, r12, lr\n\t"
  1584. "STR r10, [sp, #28]\n\t"
  1585. "ADDS r3, r3, r11\n\t"
  1586. /* A[3] * A[5] */
  1587. "LDR lr, [%[a], #20]\n\t"
  1588. "ADC r11, %[r], #0x0\n\t"
  1589. "UMLAL r3, r11, r12, lr\n\t"
  1590. "ADDS r4, r4, r11\n\t"
  1591. /* A[3] * A[6] */
  1592. "LDR lr, [%[a], #24]\n\t"
  1593. "ADC r11, %[r], #0x0\n\t"
  1594. "UMLAL r4, r11, r12, lr\n\t"
  1595. "ADDS r5, r5, r11\n\t"
  1596. /* A[3] * A[7] */
  1597. "LDR lr, [%[a], #28]\n\t"
  1598. "ADC r6, %[r], #0x0\n\t"
  1599. "UMLAL r5, r6, r12, lr\n\t"
  1600. /* A[4] * A[5] */
  1601. "LDR r12, [%[a], #16]\n\t"
  1602. "LDR lr, [%[a], #20]\n\t"
  1603. "MOV r11, #0x0\n\t"
  1604. "UMLAL r4, r11, r12, lr\n\t"
  1605. "ADDS r5, r5, r11\n\t"
  1606. /* A[4] * A[6] */
  1607. "LDR lr, [%[a], #24]\n\t"
  1608. "ADC r11, %[r], #0x0\n\t"
  1609. "UMLAL r5, r11, r12, lr\n\t"
  1610. "ADDS r6, r6, r11\n\t"
  1611. /* A[4] * A[7] */
  1612. "LDR lr, [%[a], #28]\n\t"
  1613. "ADC r7, %[r], #0x0\n\t"
  1614. "UMLAL r6, r7, r12, lr\n\t"
  1615. /* A[5] * A[6] */
  1616. "LDR r12, [%[a], #20]\n\t"
  1617. "LDR lr, [%[a], #24]\n\t"
  1618. "MOV r11, #0x0\n\t"
  1619. "UMLAL r6, r11, r12, lr\n\t"
  1620. "ADDS r7, r7, r11\n\t"
  1621. /* A[5] * A[7] */
  1622. "LDR lr, [%[a], #28]\n\t"
  1623. "ADC r8, %[r], #0x0\n\t"
  1624. "UMLAL r7, r8, r12, lr\n\t"
  1625. /* A[6] * A[7] */
  1626. "LDR r12, [%[a], #24]\n\t"
  1627. "LDR lr, [%[a], #28]\n\t"
  1628. "MOV r9, #0x0\n\t"
  1629. "UMLAL r8, r9, r12, lr\n\t"
  1630. "ADD lr, sp, #0x20\n\t"
  1631. "STM lr, {r3, r4, r5, r6, r7, r8, r9}\n\t"
  1632. "ADD lr, sp, #0x4\n\t"
  1633. "LDM lr, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  1634. "ADDS r4, r4, r4\n\t"
  1635. "ADCS r5, r5, r5\n\t"
  1636. "ADCS r6, r6, r6\n\t"
  1637. "ADCS r7, r7, r7\n\t"
  1638. "ADCS r8, r8, r8\n\t"
  1639. "ADCS r9, r9, r9\n\t"
  1640. "ADCS r10, r10, r10\n\t"
  1641. "STM lr!, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  1642. "LDM lr, {r3, r4, r5, r6, r7, r8, r9}\n\t"
  1643. "ADCS r3, r3, r3\n\t"
  1644. "ADCS r4, r4, r4\n\t"
  1645. "ADCS r5, r5, r5\n\t"
  1646. "ADCS r6, r6, r6\n\t"
  1647. "ADCS r7, r7, r7\n\t"
  1648. "ADCS r8, r8, r8\n\t"
  1649. "ADCS r9, r9, r9\n\t"
  1650. "ADC r10, %[r], #0x0\n\t"
  1651. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  1652. "ADD lr, sp, #0x4\n\t"
  1653. "LDM lr, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  1654. "MOV lr, sp\n\t"
  1655. /* A[0] * A[0] */
  1656. "LDR r12, [%[a]]\n\t"
  1657. "UMULL r3, r11, r12, r12\n\t"
  1658. "ADDS r4, r4, r11\n\t"
  1659. /* A[1] * A[1] */
  1660. "LDR r12, [%[a], #4]\n\t"
  1661. "ADCS r5, r5, #0x0\n\t"
  1662. "ADC r11, %[r], #0x0\n\t"
  1663. "UMLAL r5, r11, r12, r12\n\t"
  1664. "ADDS r6, r6, r11\n\t"
  1665. /* A[2] * A[2] */
  1666. "LDR r12, [%[a], #8]\n\t"
  1667. "ADCS r7, r7, #0x0\n\t"
  1668. "ADC r11, %[r], #0x0\n\t"
  1669. "UMLAL r7, r11, r12, r12\n\t"
  1670. "ADDS r8, r8, r11\n\t"
  1671. /* A[3] * A[3] */
  1672. "LDR r12, [%[a], #12]\n\t"
  1673. "ADCS r9, r9, #0x0\n\t"
  1674. "ADC r11, %[r], #0x0\n\t"
  1675. "UMLAL r9, r11, r12, r12\n\t"
  1676. "ADDS r10, r10, r11\n\t"
  1677. "STM lr!, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  1678. "LDM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  1679. /* A[4] * A[4] */
  1680. "LDR r12, [%[a], #16]\n\t"
  1681. "ADCS r3, r3, #0x0\n\t"
  1682. "ADC r11, %[r], #0x0\n\t"
  1683. "UMLAL r3, r11, r12, r12\n\t"
  1684. "ADDS r4, r4, r11\n\t"
  1685. /* A[5] * A[5] */
  1686. "LDR r12, [%[a], #20]\n\t"
  1687. "ADCS r5, r5, #0x0\n\t"
  1688. "ADC r11, %[r], #0x0\n\t"
  1689. "UMLAL r5, r11, r12, r12\n\t"
  1690. "ADDS r6, r6, r11\n\t"
  1691. /* A[6] * A[6] */
  1692. "LDR r12, [%[a], #24]\n\t"
  1693. "ADCS r7, r7, #0x0\n\t"
  1694. "ADC r11, %[r], #0x0\n\t"
  1695. "UMLAL r7, r11, r12, r12\n\t"
  1696. "ADDS r8, r8, r11\n\t"
  1697. /* A[7] * A[7] */
  1698. "LDR r12, [%[a], #28]\n\t"
  1699. "ADCS r9, r9, #0x0\n\t"
  1700. "ADC r10, r10, #0x0\n\t"
  1701. "UMLAL r9, r10, r12, r12\n\t"
  1702. "LDR %[r], [sp, #64]\n\t"
  1703. "ADD %[r], %[r], #0x20\n\t"
  1704. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  1705. "LDM sp, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  1706. "SUB %[r], %[r], #0x20\n\t"
  1707. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  1708. "ADD sp, sp, #0x44\n\t"
  1709. : [r] "+r" (r), [a] "+r" (a)
  1710. :
  1711. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  1712. );
  1713. }
  1714. #else
  1715. /* Square a and put result in r. (r = a * a)
  1716. *
  1717. * r A single precision integer.
  1718. * a A single precision integer.
  1719. */
  1720. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1721. SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r_p, const sp_digit* a_p)
  1722. #else
  1723. SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
  1724. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1725. {
  1726. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1727. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  1728. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  1729. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1730. __asm__ __volatile__ (
  1731. "SUB sp, sp, #0x20\n\t"
  1732. "STR %[r], [sp, #28]\n\t"
  1733. "LDM %[a], {r0, r1, r2, r3, r4, r5, r6, r7}\n\t"
  1734. "UMULL r9, r10, r0, r0\n\t"
  1735. "UMULL r11, r12, r0, r1\n\t"
  1736. "ADDS r11, r11, r11\n\t"
  1737. "MOV lr, #0x0\n\t"
  1738. "UMAAL r10, r11, lr, lr\n\t"
  1739. "STM sp, {r9, r10}\n\t"
  1740. "MOV r8, lr\n\t"
  1741. "UMAAL r8, r12, r0, r2\n\t"
  1742. "ADCS r8, r8, r8\n\t"
  1743. "UMAAL r8, r11, r1, r1\n\t"
  1744. "UMULL r9, r10, r0, r3\n\t"
  1745. "UMAAL r9, r12, r1, r2\n\t"
  1746. "ADCS r9, r9, r9\n\t"
  1747. "UMAAL r9, r11, lr, lr\n\t"
  1748. "STRD r8, r9, [sp, #8]\n\t"
  1749. "MOV r9, lr\n\t"
  1750. "UMAAL r9, r10, r0, r4\n\t"
  1751. "UMAAL r9, r12, r1, r3\n\t"
  1752. "ADCS r9, r9, r9\n\t"
  1753. "UMAAL r9, r11, r2, r2\n\t"
  1754. "STR r9, [sp, #16]\n\t"
  1755. "UMULL r9, r8, r0, r5\n\t"
  1756. "UMAAL r9, r12, r1, r4\n\t"
  1757. "UMAAL r9, r10, r2, r3\n\t"
  1758. "ADCS r9, r9, r9\n\t"
  1759. "UMAAL r9, r11, lr, lr\n\t"
  1760. "STR r9, [sp, #20]\n\t"
  1761. "MOV r9, lr\n\t"
  1762. "UMAAL r9, r8, r0, r6\n\t"
  1763. "UMAAL r9, r12, r1, r5\n\t"
  1764. "UMAAL r9, r10, r2, r4\n\t"
  1765. "ADCS r9, r9, r9\n\t"
  1766. "UMAAL r9, r11, r3, r3\n\t"
  1767. "STR r9, [sp, #24]\n\t"
  1768. "UMULL r0, r9, r0, r7\n\t"
  1769. "UMAAL r0, r8, r1, r6\n\t"
  1770. "UMAAL r0, r12, r2, r5\n\t"
  1771. "UMAAL r0, r10, r3, r4\n\t"
  1772. "ADCS r0, r0, r0\n\t"
  1773. "UMAAL r0, r11, lr, lr\n\t"
  1774. /* R[7] = r0 */
  1775. "UMAAL r9, r8, r1, r7\n\t"
  1776. "UMAAL r9, r10, r2, r6\n\t"
  1777. "UMAAL r12, r9, r3, r5\n\t"
  1778. "ADCS r12, r12, r12\n\t"
  1779. "UMAAL r12, r11, r4, r4\n\t"
  1780. /* R[8] = r12 */
  1781. "UMAAL r9, r8, r2, r7\n\t"
  1782. "UMAAL r10, r9, r3, r6\n\t"
  1783. "MOV r2, lr\n\t"
  1784. "UMAAL r10, r2, r4, r5\n\t"
  1785. "ADCS r10, r10, r10\n\t"
  1786. "UMAAL r11, r10, lr, lr\n\t"
  1787. /* R[9] = r11 */
  1788. "UMAAL r2, r8, r3, r7\n\t"
  1789. "UMAAL r2, r9, r4, r6\n\t"
  1790. "ADCS r3, r2, r2\n\t"
  1791. "UMAAL r10, r3, r5, r5\n\t"
  1792. /* R[10] = r10 */
  1793. "MOV r1, lr\n\t"
  1794. "UMAAL r1, r8, r4, r7\n\t"
  1795. "UMAAL r1, r9, r5, r6\n\t"
  1796. "ADCS r4, r1, r1\n\t"
  1797. "UMAAL r3, r4, lr, lr\n\t"
  1798. /* R[11] = r3 */
  1799. "UMAAL r8, r9, r5, r7\n\t"
  1800. "ADCS r8, r8, r8\n\t"
  1801. "UMAAL r4, r8, r6, r6\n\t"
  1802. /* R[12] = r4 */
  1803. "MOV r5, lr\n\t"
  1804. "UMAAL r5, r9, r6, r7\n\t"
  1805. "ADCS r5, r5, r5\n\t"
  1806. "UMAAL r8, r5, lr, lr\n\t"
  1807. /* R[13] = r8 */
  1808. "ADCS r9, r9, r9\n\t"
  1809. "UMAAL r9, r5, r7, r7\n\t"
  1810. "ADCS r7, r5, lr\n\t"
  1811. /* R[14] = r9 */
  1812. /* R[15] = r7 */
  1813. "LDR lr, [sp, #28]\n\t"
  1814. "ADD lr, lr, #0x1c\n\t"
  1815. "STM lr!, {r0, r12}\n\t"
  1816. "STM lr!, {r11}\n\t"
  1817. "STM lr!, {r10}\n\t"
  1818. "STM lr!, {r3, r4, r8, r9}\n\t"
  1819. "STM lr!, {r7}\n\t"
  1820. "SUB lr, lr, #0x40\n\t"
  1821. "LDM sp, {r0, r1, r2, r3, r4, r5, r6}\n\t"
  1822. "STM lr, {r0, r1, r2, r3, r4, r5, r6}\n\t"
  1823. "ADD sp, sp, #0x20\n\t"
  1824. : [r] "+r" (r), [a] "+r" (a)
  1825. :
  1826. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  1827. );
  1828. }
  1829. #endif /* WOLFSSL_SP_NO_UMAAL */
  1830. /* Sub b from a into r. (r = a - b)
  1831. *
  1832. * r A single precision integer.
  1833. * a A single precision integer.
  1834. * b A single precision integer.
  1835. */
  1836. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1837. static sp_digit sp_2048_sub_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  1838. #else
  1839. static sp_digit sp_2048_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  1840. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1841. {
  1842. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1843. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  1844. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  1845. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  1846. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1847. __asm__ __volatile__ (
  1848. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1849. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1850. "SUBS r3, r3, r7\n\t"
  1851. "SBCS r4, r4, r8\n\t"
  1852. "SBCS r5, r5, r9\n\t"
  1853. "SBCS r6, r6, r10\n\t"
  1854. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1855. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1856. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1857. "SBCS r3, r3, r7\n\t"
  1858. "SBCS r4, r4, r8\n\t"
  1859. "SBCS r5, r5, r9\n\t"
  1860. "SBCS r6, r6, r10\n\t"
  1861. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1862. "SBC %[r], r6, r6\n\t"
  1863. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  1864. :
  1865. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  1866. );
  1867. return (uint32_t)(size_t)r;
  1868. }
  1869. /* Square a and put result in r. (r = a * a)
  1870. *
  1871. * r A single precision integer.
  1872. * a A single precision integer.
  1873. */
  1874. SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
  1875. {
  1876. sp_digit* z0 = r;
  1877. sp_digit* z2 = r + 16;
  1878. sp_digit z1[16];
  1879. sp_digit* a1 = z1;
  1880. sp_digit zero[8];
  1881. sp_digit u;
  1882. sp_digit mask;
  1883. sp_digit* p1;
  1884. sp_digit* p2;
  1885. XMEMSET(zero, 0, sizeof(sp_digit) * 8);
  1886. mask = sp_2048_sub_8(a1, a, &a[8]);
  1887. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  1888. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  1889. (void)sp_2048_sub_8(a1, p1, p2);
  1890. sp_2048_sqr_8(z2, &a[8]);
  1891. sp_2048_sqr_8(z0, a);
  1892. sp_2048_sqr_8(z1, a1);
  1893. u = 0;
  1894. u -= sp_2048_sub_in_place_16(z1, z2);
  1895. u -= sp_2048_sub_in_place_16(z1, z0);
  1896. u += sp_2048_sub_in_place_16(r + 8, z1);
  1897. zero[0] = u;
  1898. (void)sp_2048_add_8(r + 24, r + 24, zero);
  1899. }
  1900. /* Sub b from a into r. (r = a - b)
  1901. *
  1902. * r A single precision integer.
  1903. * a A single precision integer.
  1904. * b A single precision integer.
  1905. */
  1906. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1907. static sp_digit sp_2048_sub_16(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  1908. #else
  1909. static sp_digit sp_2048_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b)
  1910. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1911. {
  1912. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1913. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  1914. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  1915. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  1916. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1917. __asm__ __volatile__ (
  1918. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1919. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1920. "SUBS r3, r3, r7\n\t"
  1921. "SBCS r4, r4, r8\n\t"
  1922. "SBCS r5, r5, r9\n\t"
  1923. "SBCS r6, r6, r10\n\t"
  1924. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1925. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1926. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1927. "SBCS r3, r3, r7\n\t"
  1928. "SBCS r4, r4, r8\n\t"
  1929. "SBCS r5, r5, r9\n\t"
  1930. "SBCS r6, r6, r10\n\t"
  1931. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1932. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1933. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1934. "SBCS r3, r3, r7\n\t"
  1935. "SBCS r4, r4, r8\n\t"
  1936. "SBCS r5, r5, r9\n\t"
  1937. "SBCS r6, r6, r10\n\t"
  1938. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1939. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  1940. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  1941. "SBCS r3, r3, r7\n\t"
  1942. "SBCS r4, r4, r8\n\t"
  1943. "SBCS r5, r5, r9\n\t"
  1944. "SBCS r6, r6, r10\n\t"
  1945. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  1946. "SBC %[r], r6, r6\n\t"
  1947. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  1948. :
  1949. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  1950. );
  1951. return (uint32_t)(size_t)r;
  1952. }
  1953. /* Square a and put result in r. (r = a * a)
  1954. *
  1955. * r A single precision integer.
  1956. * a A single precision integer.
  1957. */
  1958. SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
  1959. {
  1960. sp_digit* z0 = r;
  1961. sp_digit* z2 = r + 32;
  1962. sp_digit z1[32];
  1963. sp_digit* a1 = z1;
  1964. sp_digit zero[16];
  1965. sp_digit u;
  1966. sp_digit mask;
  1967. sp_digit* p1;
  1968. sp_digit* p2;
  1969. XMEMSET(zero, 0, sizeof(sp_digit) * 16);
  1970. mask = sp_2048_sub_16(a1, a, &a[16]);
  1971. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  1972. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  1973. (void)sp_2048_sub_16(a1, p1, p2);
  1974. sp_2048_sqr_16(z2, &a[16]);
  1975. sp_2048_sqr_16(z0, a);
  1976. sp_2048_sqr_16(z1, a1);
  1977. u = 0;
  1978. u -= sp_2048_sub_in_place_32(z1, z2);
  1979. u -= sp_2048_sub_in_place_32(z1, z0);
  1980. u += sp_2048_sub_in_place_32(r + 16, z1);
  1981. zero[0] = u;
  1982. (void)sp_2048_add_16(r + 48, r + 48, zero);
  1983. }
  1984. /* Sub b from a into r. (r = a - b)
  1985. *
  1986. * r A single precision integer.
  1987. * a A single precision integer.
  1988. * b A single precision integer.
  1989. */
  1990. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1991. static sp_digit sp_2048_sub_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  1992. #else
  1993. static sp_digit sp_2048_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
  1994. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  1995. {
  1996. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  1997. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  1998. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  1999. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  2000. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2001. __asm__ __volatile__ (
  2002. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2003. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2004. "SUBS r3, r3, r7\n\t"
  2005. "SBCS r4, r4, r8\n\t"
  2006. "SBCS r5, r5, r9\n\t"
  2007. "SBCS r6, r6, r10\n\t"
  2008. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2009. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2010. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2011. "SBCS r3, r3, r7\n\t"
  2012. "SBCS r4, r4, r8\n\t"
  2013. "SBCS r5, r5, r9\n\t"
  2014. "SBCS r6, r6, r10\n\t"
  2015. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2016. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2017. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2018. "SBCS r3, r3, r7\n\t"
  2019. "SBCS r4, r4, r8\n\t"
  2020. "SBCS r5, r5, r9\n\t"
  2021. "SBCS r6, r6, r10\n\t"
  2022. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2023. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2024. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2025. "SBCS r3, r3, r7\n\t"
  2026. "SBCS r4, r4, r8\n\t"
  2027. "SBCS r5, r5, r9\n\t"
  2028. "SBCS r6, r6, r10\n\t"
  2029. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2030. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2031. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2032. "SBCS r3, r3, r7\n\t"
  2033. "SBCS r4, r4, r8\n\t"
  2034. "SBCS r5, r5, r9\n\t"
  2035. "SBCS r6, r6, r10\n\t"
  2036. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2037. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2038. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2039. "SBCS r3, r3, r7\n\t"
  2040. "SBCS r4, r4, r8\n\t"
  2041. "SBCS r5, r5, r9\n\t"
  2042. "SBCS r6, r6, r10\n\t"
  2043. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2044. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2045. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2046. "SBCS r3, r3, r7\n\t"
  2047. "SBCS r4, r4, r8\n\t"
  2048. "SBCS r5, r5, r9\n\t"
  2049. "SBCS r6, r6, r10\n\t"
  2050. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2051. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  2052. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  2053. "SBCS r3, r3, r7\n\t"
  2054. "SBCS r4, r4, r8\n\t"
  2055. "SBCS r5, r5, r9\n\t"
  2056. "SBCS r6, r6, r10\n\t"
  2057. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  2058. "SBC %[r], r6, r6\n\t"
  2059. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  2060. :
  2061. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  2062. );
  2063. return (uint32_t)(size_t)r;
  2064. }
  2065. /* Square a and put result in r. (r = a * a)
  2066. *
  2067. * r A single precision integer.
  2068. * a A single precision integer.
  2069. */
  2070. SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a)
  2071. {
  2072. sp_digit* z0 = r;
  2073. sp_digit* z2 = r + 64;
  2074. sp_digit z1[64];
  2075. sp_digit* a1 = z1;
  2076. sp_digit zero[32];
  2077. sp_digit u;
  2078. sp_digit mask;
  2079. sp_digit* p1;
  2080. sp_digit* p2;
  2081. XMEMSET(zero, 0, sizeof(sp_digit) * 32);
  2082. mask = sp_2048_sub_32(a1, a, &a[32]);
  2083. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  2084. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  2085. (void)sp_2048_sub_32(a1, p1, p2);
  2086. sp_2048_sqr_32(z2, &a[32]);
  2087. sp_2048_sqr_32(z0, a);
  2088. sp_2048_sqr_32(z1, a1);
  2089. u = 0;
  2090. u -= sp_2048_sub_in_place_64(z1, z2);
  2091. u -= sp_2048_sub_in_place_64(z1, z0);
  2092. u += sp_2048_sub_in_place_64(r + 32, z1);
  2093. zero[0] = u;
  2094. (void)sp_2048_add_32(r + 96, r + 96, zero);
  2095. }
  2096. #endif /* !WOLFSSL_SP_SMALL */
  2097. #ifdef WOLFSSL_SP_SMALL
  2098. /* Add b to a into r. (r = a + b)
  2099. *
  2100. * r A single precision integer.
  2101. * a A single precision integer.
  2102. * b A single precision integer.
  2103. */
  2104. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2105. static sp_digit sp_2048_add_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  2106. #else
  2107. static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b)
  2108. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2109. {
  2110. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2111. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2112. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2113. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  2114. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2115. __asm__ __volatile__ (
  2116. "MOV r3, #0x0\n\t"
  2117. "ADD r12, %[a], #0x100\n\t"
  2118. "\n"
  2119. "L_sp_2048_add_64_word:\n\t"
  2120. "ADDS r3, r3, #0xffffffff\n\t"
  2121. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  2122. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  2123. "ADCS r4, r4, r8\n\t"
  2124. "ADCS r5, r5, r9\n\t"
  2125. "ADCS r6, r6, r10\n\t"
  2126. "ADCS r7, r7, r11\n\t"
  2127. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  2128. "MOV r4, #0x0\n\t"
  2129. "ADC r3, r4, #0x0\n\t"
  2130. "CMP %[a], r12\n\t"
  2131. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2132. "BNE L_sp_2048_add_64_word\n\t"
  2133. #else
  2134. "BNE.N L_sp_2048_add_64_word\n\t"
  2135. #endif
  2136. "MOV %[r], r3\n\t"
  2137. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  2138. :
  2139. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  2140. );
  2141. return (uint32_t)(size_t)r;
  2142. }
  2143. #endif /* WOLFSSL_SP_SMALL */
  2144. #ifdef WOLFSSL_SP_SMALL
  2145. /* Sub b from a into a. (a -= b)
  2146. *
  2147. * a A single precision integer.
  2148. * b A single precision integer.
  2149. */
  2150. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2151. static sp_digit sp_2048_sub_in_place_64(sp_digit* a_p, const sp_digit* b_p)
  2152. #else
  2153. static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b)
  2154. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2155. {
  2156. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2157. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  2158. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  2159. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2160. __asm__ __volatile__ (
  2161. "MOV r10, #0x0\n\t"
  2162. "ADD r11, %[a], #0x100\n\t"
  2163. "\n"
  2164. "L_sp_2048_sub_in_pkace_64_word:\n\t"
  2165. "RSBS r10, r10, #0x0\n\t"
  2166. "LDM %[a], {r2, r3, r4, r5}\n\t"
  2167. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  2168. "SBCS r2, r2, r6\n\t"
  2169. "SBCS r3, r3, r7\n\t"
  2170. "SBCS r4, r4, r8\n\t"
  2171. "SBCS r5, r5, r9\n\t"
  2172. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  2173. "SBC r10, r10, r10\n\t"
  2174. "CMP %[a], r11\n\t"
  2175. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2176. "BNE L_sp_2048_sub_in_pkace_64_word\n\t"
  2177. #else
  2178. "BNE.N L_sp_2048_sub_in_pkace_64_word\n\t"
  2179. #endif
  2180. "MOV %[a], r10\n\t"
  2181. : [a] "+r" (a), [b] "+r" (b)
  2182. :
  2183. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  2184. );
  2185. return (uint32_t)(size_t)a;
  2186. }
  2187. #endif /* WOLFSSL_SP_SMALL */
  2188. #ifdef WOLFSSL_SP_SMALL
  2189. /* Multiply a and b into r. (r = a * b)
  2190. *
  2191. * r A single precision integer.
  2192. * a A single precision integer.
  2193. * b A single precision integer.
  2194. */
  2195. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2196. static void sp_2048_mul_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  2197. #else
  2198. static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b)
  2199. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2200. {
  2201. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2202. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2203. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2204. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  2205. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2206. __asm__ __volatile__ (
  2207. "SUB sp, sp, #0x200\n\t"
  2208. "LDR lr, [%[a]]\n\t"
  2209. "LDR r11, [%[b]]\n\t"
  2210. "UMULL r8, r6, lr, r11\n\t"
  2211. "STR r8, [sp]\n\t"
  2212. "MOV r7, #0x0\n\t"
  2213. "MOV r8, #0x0\n\t"
  2214. "MOV r5, #0x4\n\t"
  2215. "\n"
  2216. "L_sp_2048_mul_64_outer:\n\t"
  2217. "SUBS r3, r5, #0xfc\n\t"
  2218. "IT cc\n\t"
  2219. "MOVCC r3, #0x0\n\t"
  2220. "SUB r4, r5, r3\n\t"
  2221. "\n"
  2222. "L_sp_2048_mul_64_inner:\n\t"
  2223. "LDR lr, [%[a], r3]\n\t"
  2224. "LDR r11, [%[b], r4]\n\t"
  2225. "UMULL r9, r10, lr, r11\n\t"
  2226. "ADDS r6, r6, r9\n\t"
  2227. "ADCS r7, r7, r10\n\t"
  2228. "ADC r8, r8, #0x0\n\t"
  2229. "LDR lr, [%[a], r4]\n\t"
  2230. "LDR r11, [%[b], r3]\n\t"
  2231. "UMULL r9, r10, lr, r11\n\t"
  2232. "ADDS r6, r6, r9\n\t"
  2233. "ADCS r7, r7, r10\n\t"
  2234. "ADC r8, r8, #0x0\n\t"
  2235. "ADD r3, r3, #0x4\n\t"
  2236. "SUB r4, r4, #0x4\n\t"
  2237. "CMP r3, r4\n\t"
  2238. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2239. "BGT L_sp_2048_mul_64_inner_done\n\t"
  2240. #else
  2241. "BGT.N L_sp_2048_mul_64_inner_done\n\t"
  2242. #endif
  2243. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2244. "BLT L_sp_2048_mul_64_inner\n\t"
  2245. #else
  2246. "BLT.N L_sp_2048_mul_64_inner\n\t"
  2247. #endif
  2248. "LDR lr, [%[a], r3]\n\t"
  2249. "LDR r11, [%[b], r3]\n\t"
  2250. "UMULL r9, r10, lr, r11\n\t"
  2251. "ADDS r6, r6, r9\n\t"
  2252. "ADCS r7, r7, r10\n\t"
  2253. "ADC r8, r8, #0x0\n\t"
  2254. "\n"
  2255. "L_sp_2048_mul_64_inner_done:\n\t"
  2256. "STR r6, [sp, r5]\n\t"
  2257. "MOV r6, r7\n\t"
  2258. "MOV r7, r8\n\t"
  2259. "MOV r8, #0x0\n\t"
  2260. "ADD r5, r5, #0x4\n\t"
  2261. "CMP r5, #0x1f4\n\t"
  2262. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2263. "BLE L_sp_2048_mul_64_outer\n\t"
  2264. #else
  2265. "BLE.N L_sp_2048_mul_64_outer\n\t"
  2266. #endif
  2267. "LDR lr, [%[a], #252]\n\t"
  2268. "LDR r11, [%[b], #252]\n\t"
  2269. "UMLAL r6, r7, lr, r11\n\t"
  2270. "STR r6, [sp, r5]\n\t"
  2271. "ADD r5, r5, #0x4\n\t"
  2272. "STR r7, [sp, r5]\n\t"
  2273. "\n"
  2274. "L_sp_2048_mul_64_store:\n\t"
  2275. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2276. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2277. "SUBS r5, r5, #0x20\n\t"
  2278. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2279. "BGT L_sp_2048_mul_64_store\n\t"
  2280. #else
  2281. "BGT.N L_sp_2048_mul_64_store\n\t"
  2282. #endif
  2283. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  2284. :
  2285. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  2286. );
  2287. }
  2288. /* Square a and put result in r. (r = a * a)
  2289. *
  2290. * r A single precision integer.
  2291. * a A single precision integer.
  2292. */
  2293. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2294. static void sp_2048_sqr_64(sp_digit* r_p, const sp_digit* a_p)
  2295. #else
  2296. static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a)
  2297. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2298. {
  2299. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2300. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2301. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2302. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2303. __asm__ __volatile__ (
  2304. "SUB sp, sp, #0x200\n\t"
  2305. "LDR lr, [%[a]]\n\t"
  2306. "UMULL r8, r6, lr, lr\n\t"
  2307. "STR r8, [sp]\n\t"
  2308. "MOV r7, #0x0\n\t"
  2309. "MOV r8, #0x0\n\t"
  2310. "MOV r5, #0x4\n\t"
  2311. "\n"
  2312. "L_sp_2048_sqr_64_outer:\n\t"
  2313. "SUBS r3, r5, #0xfc\n\t"
  2314. "IT cc\n\t"
  2315. "MOVCC r3, #0x0\n\t"
  2316. "SUB r4, r5, r3\n\t"
  2317. "\n"
  2318. "L_sp_2048_sqr_64_inner:\n\t"
  2319. "LDR lr, [%[a], r3]\n\t"
  2320. "LDR r11, [%[a], r4]\n\t"
  2321. "UMULL r9, r10, lr, r11\n\t"
  2322. "ADDS r6, r6, r9\n\t"
  2323. "ADCS r7, r7, r10\n\t"
  2324. "ADC r8, r8, #0x0\n\t"
  2325. "ADDS r6, r6, r9\n\t"
  2326. "ADCS r7, r7, r10\n\t"
  2327. "ADC r8, r8, #0x0\n\t"
  2328. "ADD r3, r3, #0x4\n\t"
  2329. "SUB r4, r4, #0x4\n\t"
  2330. "CMP r3, r4\n\t"
  2331. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2332. "BGT L_sp_2048_sqr_64_inner_done\n\t"
  2333. #else
  2334. "BGT.N L_sp_2048_sqr_64_inner_done\n\t"
  2335. #endif
  2336. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2337. "BLT L_sp_2048_sqr_64_inner\n\t"
  2338. #else
  2339. "BLT.N L_sp_2048_sqr_64_inner\n\t"
  2340. #endif
  2341. "LDR lr, [%[a], r3]\n\t"
  2342. "UMULL r9, r10, lr, lr\n\t"
  2343. "ADDS r6, r6, r9\n\t"
  2344. "ADCS r7, r7, r10\n\t"
  2345. "ADC r8, r8, #0x0\n\t"
  2346. "\n"
  2347. "L_sp_2048_sqr_64_inner_done:\n\t"
  2348. "STR r6, [sp, r5]\n\t"
  2349. "MOV r6, r7\n\t"
  2350. "MOV r7, r8\n\t"
  2351. "MOV r8, #0x0\n\t"
  2352. "ADD r5, r5, #0x4\n\t"
  2353. "CMP r5, #0x1f4\n\t"
  2354. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2355. "BLE L_sp_2048_sqr_64_outer\n\t"
  2356. #else
  2357. "BLE.N L_sp_2048_sqr_64_outer\n\t"
  2358. #endif
  2359. "LDR lr, [%[a], #252]\n\t"
  2360. "UMLAL r6, r7, lr, lr\n\t"
  2361. "STR r6, [sp, r5]\n\t"
  2362. "ADD r5, r5, #0x4\n\t"
  2363. "STR r7, [sp, r5]\n\t"
  2364. "\n"
  2365. "L_sp_2048_sqr_64_store:\n\t"
  2366. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2367. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2368. "SUBS r5, r5, #0x20\n\t"
  2369. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2370. "BGT L_sp_2048_sqr_64_store\n\t"
  2371. #else
  2372. "BGT.N L_sp_2048_sqr_64_store\n\t"
  2373. #endif
  2374. : [r] "+r" (r), [a] "+r" (a)
  2375. :
  2376. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  2377. );
  2378. }
  2379. #endif /* WOLFSSL_SP_SMALL */
  2380. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  2381. #ifdef WOLFSSL_SP_SMALL
  2382. /* AND m into each word of a and store in r.
  2383. *
  2384. * r A single precision integer.
  2385. * a A single precision integer.
  2386. * m Mask to AND against each digit.
  2387. */
  2388. static void sp_2048_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
  2389. {
  2390. int i;
  2391. for (i=0; i<32; i++) {
  2392. r[i] = a[i] & m;
  2393. }
  2394. }
  2395. #endif /* WOLFSSL_SP_SMALL */
  2396. #ifdef WOLFSSL_SP_SMALL
  2397. /* Add b to a into r. (r = a + b)
  2398. *
  2399. * r A single precision integer.
  2400. * a A single precision integer.
  2401. * b A single precision integer.
  2402. */
  2403. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2404. static sp_digit sp_2048_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  2405. #else
  2406. static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
  2407. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2408. {
  2409. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2410. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2411. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2412. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  2413. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2414. __asm__ __volatile__ (
  2415. "MOV r3, #0x0\n\t"
  2416. "ADD r12, %[a], #0x80\n\t"
  2417. "\n"
  2418. "L_sp_2048_add_32_word:\n\t"
  2419. "ADDS r3, r3, #0xffffffff\n\t"
  2420. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  2421. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  2422. "ADCS r4, r4, r8\n\t"
  2423. "ADCS r5, r5, r9\n\t"
  2424. "ADCS r6, r6, r10\n\t"
  2425. "ADCS r7, r7, r11\n\t"
  2426. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  2427. "MOV r4, #0x0\n\t"
  2428. "ADC r3, r4, #0x0\n\t"
  2429. "CMP %[a], r12\n\t"
  2430. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2431. "BNE L_sp_2048_add_32_word\n\t"
  2432. #else
  2433. "BNE.N L_sp_2048_add_32_word\n\t"
  2434. #endif
  2435. "MOV %[r], r3\n\t"
  2436. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  2437. :
  2438. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  2439. );
  2440. return (uint32_t)(size_t)r;
  2441. }
  2442. #endif /* WOLFSSL_SP_SMALL */
  2443. #ifdef WOLFSSL_SP_SMALL
  2444. /* Sub b from a into a. (a -= b)
  2445. *
  2446. * a A single precision integer.
  2447. * b A single precision integer.
  2448. */
  2449. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2450. static sp_digit sp_2048_sub_in_place_32(sp_digit* a_p, const sp_digit* b_p)
  2451. #else
  2452. static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b)
  2453. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2454. {
  2455. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2456. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  2457. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  2458. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2459. __asm__ __volatile__ (
  2460. "MOV r10, #0x0\n\t"
  2461. "ADD r11, %[a], #0x80\n\t"
  2462. "\n"
  2463. "L_sp_2048_sub_in_pkace_32_word:\n\t"
  2464. "RSBS r10, r10, #0x0\n\t"
  2465. "LDM %[a], {r2, r3, r4, r5}\n\t"
  2466. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  2467. "SBCS r2, r2, r6\n\t"
  2468. "SBCS r3, r3, r7\n\t"
  2469. "SBCS r4, r4, r8\n\t"
  2470. "SBCS r5, r5, r9\n\t"
  2471. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  2472. "SBC r10, r10, r10\n\t"
  2473. "CMP %[a], r11\n\t"
  2474. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2475. "BNE L_sp_2048_sub_in_pkace_32_word\n\t"
  2476. #else
  2477. "BNE.N L_sp_2048_sub_in_pkace_32_word\n\t"
  2478. #endif
  2479. "MOV %[a], r10\n\t"
  2480. : [a] "+r" (a), [b] "+r" (b)
  2481. :
  2482. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  2483. );
  2484. return (uint32_t)(size_t)a;
  2485. }
  2486. #endif /* WOLFSSL_SP_SMALL */
  2487. #ifdef WOLFSSL_SP_SMALL
  2488. /* Multiply a and b into r. (r = a * b)
  2489. *
  2490. * r A single precision integer.
  2491. * a A single precision integer.
  2492. * b A single precision integer.
  2493. */
  2494. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2495. static void sp_2048_mul_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  2496. #else
  2497. static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
  2498. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2499. {
  2500. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2501. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2502. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2503. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  2504. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2505. __asm__ __volatile__ (
  2506. "SUB sp, sp, #0x100\n\t"
  2507. "LDR lr, [%[a]]\n\t"
  2508. "LDR r11, [%[b]]\n\t"
  2509. "UMULL r8, r6, lr, r11\n\t"
  2510. "STR r8, [sp]\n\t"
  2511. "MOV r7, #0x0\n\t"
  2512. "MOV r8, #0x0\n\t"
  2513. "MOV r5, #0x4\n\t"
  2514. "\n"
  2515. "L_sp_2048_mul_32_outer:\n\t"
  2516. "SUBS r3, r5, #0x7c\n\t"
  2517. "IT cc\n\t"
  2518. "MOVCC r3, #0x0\n\t"
  2519. "SUB r4, r5, r3\n\t"
  2520. "\n"
  2521. "L_sp_2048_mul_32_inner:\n\t"
  2522. "LDR lr, [%[a], r3]\n\t"
  2523. "LDR r11, [%[b], r4]\n\t"
  2524. "UMULL r9, r10, lr, r11\n\t"
  2525. "ADDS r6, r6, r9\n\t"
  2526. "ADCS r7, r7, r10\n\t"
  2527. "ADC r8, r8, #0x0\n\t"
  2528. "LDR lr, [%[a], r4]\n\t"
  2529. "LDR r11, [%[b], r3]\n\t"
  2530. "UMULL r9, r10, lr, r11\n\t"
  2531. "ADDS r6, r6, r9\n\t"
  2532. "ADCS r7, r7, r10\n\t"
  2533. "ADC r8, r8, #0x0\n\t"
  2534. "ADD r3, r3, #0x4\n\t"
  2535. "SUB r4, r4, #0x4\n\t"
  2536. "CMP r3, r4\n\t"
  2537. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2538. "BGT L_sp_2048_mul_32_inner_done\n\t"
  2539. #else
  2540. "BGT.N L_sp_2048_mul_32_inner_done\n\t"
  2541. #endif
  2542. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2543. "BLT L_sp_2048_mul_32_inner\n\t"
  2544. #else
  2545. "BLT.N L_sp_2048_mul_32_inner\n\t"
  2546. #endif
  2547. "LDR lr, [%[a], r3]\n\t"
  2548. "LDR r11, [%[b], r3]\n\t"
  2549. "UMULL r9, r10, lr, r11\n\t"
  2550. "ADDS r6, r6, r9\n\t"
  2551. "ADCS r7, r7, r10\n\t"
  2552. "ADC r8, r8, #0x0\n\t"
  2553. "\n"
  2554. "L_sp_2048_mul_32_inner_done:\n\t"
  2555. "STR r6, [sp, r5]\n\t"
  2556. "MOV r6, r7\n\t"
  2557. "MOV r7, r8\n\t"
  2558. "MOV r8, #0x0\n\t"
  2559. "ADD r5, r5, #0x4\n\t"
  2560. "CMP r5, #0xf4\n\t"
  2561. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2562. "BLE L_sp_2048_mul_32_outer\n\t"
  2563. #else
  2564. "BLE.N L_sp_2048_mul_32_outer\n\t"
  2565. #endif
  2566. "LDR lr, [%[a], #124]\n\t"
  2567. "LDR r11, [%[b], #124]\n\t"
  2568. "UMLAL r6, r7, lr, r11\n\t"
  2569. "STR r6, [sp, r5]\n\t"
  2570. "ADD r5, r5, #0x4\n\t"
  2571. "STR r7, [sp, r5]\n\t"
  2572. "\n"
  2573. "L_sp_2048_mul_32_store:\n\t"
  2574. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2575. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2576. "SUBS r5, r5, #0x20\n\t"
  2577. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2578. "BGT L_sp_2048_mul_32_store\n\t"
  2579. #else
  2580. "BGT.N L_sp_2048_mul_32_store\n\t"
  2581. #endif
  2582. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  2583. :
  2584. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  2585. );
  2586. }
  2587. /* Square a and put result in r. (r = a * a)
  2588. *
  2589. * r A single precision integer.
  2590. * a A single precision integer.
  2591. */
  2592. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2593. static void sp_2048_sqr_32(sp_digit* r_p, const sp_digit* a_p)
  2594. #else
  2595. static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
  2596. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2597. {
  2598. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2599. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2600. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2601. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2602. __asm__ __volatile__ (
  2603. "SUB sp, sp, #0x100\n\t"
  2604. "LDR lr, [%[a]]\n\t"
  2605. "UMULL r8, r6, lr, lr\n\t"
  2606. "STR r8, [sp]\n\t"
  2607. "MOV r7, #0x0\n\t"
  2608. "MOV r8, #0x0\n\t"
  2609. "MOV r5, #0x4\n\t"
  2610. "\n"
  2611. "L_sp_2048_sqr_32_outer:\n\t"
  2612. "SUBS r3, r5, #0x7c\n\t"
  2613. "IT cc\n\t"
  2614. "MOVCC r3, #0x0\n\t"
  2615. "SUB r4, r5, r3\n\t"
  2616. "\n"
  2617. "L_sp_2048_sqr_32_inner:\n\t"
  2618. "LDR lr, [%[a], r3]\n\t"
  2619. "LDR r11, [%[a], r4]\n\t"
  2620. "UMULL r9, r10, lr, r11\n\t"
  2621. "ADDS r6, r6, r9\n\t"
  2622. "ADCS r7, r7, r10\n\t"
  2623. "ADC r8, r8, #0x0\n\t"
  2624. "ADDS r6, r6, r9\n\t"
  2625. "ADCS r7, r7, r10\n\t"
  2626. "ADC r8, r8, #0x0\n\t"
  2627. "ADD r3, r3, #0x4\n\t"
  2628. "SUB r4, r4, #0x4\n\t"
  2629. "CMP r3, r4\n\t"
  2630. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2631. "BGT L_sp_2048_sqr_32_inner_done\n\t"
  2632. #else
  2633. "BGT.N L_sp_2048_sqr_32_inner_done\n\t"
  2634. #endif
  2635. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2636. "BLT L_sp_2048_sqr_32_inner\n\t"
  2637. #else
  2638. "BLT.N L_sp_2048_sqr_32_inner\n\t"
  2639. #endif
  2640. "LDR lr, [%[a], r3]\n\t"
  2641. "UMULL r9, r10, lr, lr\n\t"
  2642. "ADDS r6, r6, r9\n\t"
  2643. "ADCS r7, r7, r10\n\t"
  2644. "ADC r8, r8, #0x0\n\t"
  2645. "\n"
  2646. "L_sp_2048_sqr_32_inner_done:\n\t"
  2647. "STR r6, [sp, r5]\n\t"
  2648. "MOV r6, r7\n\t"
  2649. "MOV r7, r8\n\t"
  2650. "MOV r8, #0x0\n\t"
  2651. "ADD r5, r5, #0x4\n\t"
  2652. "CMP r5, #0xf4\n\t"
  2653. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2654. "BLE L_sp_2048_sqr_32_outer\n\t"
  2655. #else
  2656. "BLE.N L_sp_2048_sqr_32_outer\n\t"
  2657. #endif
  2658. "LDR lr, [%[a], #124]\n\t"
  2659. "UMLAL r6, r7, lr, lr\n\t"
  2660. "STR r6, [sp, r5]\n\t"
  2661. "ADD r5, r5, #0x4\n\t"
  2662. "STR r7, [sp, r5]\n\t"
  2663. "\n"
  2664. "L_sp_2048_sqr_32_store:\n\t"
  2665. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2666. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  2667. "SUBS r5, r5, #0x20\n\t"
  2668. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2669. "BGT L_sp_2048_sqr_32_store\n\t"
  2670. #else
  2671. "BGT.N L_sp_2048_sqr_32_store\n\t"
  2672. #endif
  2673. : [r] "+r" (r), [a] "+r" (a)
  2674. :
  2675. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  2676. );
  2677. }
  2678. #endif /* WOLFSSL_SP_SMALL */
  2679. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  2680. /* Calculate the bottom digit of -1/a mod 2^n.
  2681. *
  2682. * a A single precision number.
  2683. * rho Bottom word of inverse.
  2684. */
  2685. static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
  2686. {
  2687. sp_digit x;
  2688. sp_digit b;
  2689. b = a[0];
  2690. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  2691. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  2692. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  2693. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  2694. /* rho = -1/m mod b */
  2695. *rho = (sp_digit)0 - x;
  2696. }
  2697. #ifdef WOLFSSL_SP_SMALL
  2698. /* Mul a by digit b into r. (r = a * b)
  2699. *
  2700. * r A single precision integer.
  2701. * a A single precision integer.
  2702. * b A single precision digit.
  2703. */
  2704. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2705. static void sp_2048_mul_d_64(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  2706. #else
  2707. static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, sp_digit b)
  2708. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2709. {
  2710. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2711. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2712. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2713. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  2714. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2715. __asm__ __volatile__ (
  2716. /* A[0] * B */
  2717. "LDR r8, [%[a]]\n\t"
  2718. "UMULL r5, r3, %[b], r8\n\t"
  2719. "MOV r4, #0x0\n\t"
  2720. "STR r5, [%[r]]\n\t"
  2721. "MOV r5, #0x0\n\t"
  2722. "MOV r9, #0x4\n\t"
  2723. "\n"
  2724. "L_sp_2048_mul_d_64_word:\n\t"
  2725. /* A[i] * B */
  2726. "LDR r8, [%[a], r9]\n\t"
  2727. "UMULL r6, r7, %[b], r8\n\t"
  2728. "ADDS r3, r3, r6\n\t"
  2729. "ADCS r4, r4, r7\n\t"
  2730. "ADC r5, r5, #0x0\n\t"
  2731. "STR r3, [%[r], r9]\n\t"
  2732. "MOV r3, r4\n\t"
  2733. "MOV r4, r5\n\t"
  2734. "MOV r5, #0x0\n\t"
  2735. "ADD r9, r9, #0x4\n\t"
  2736. "CMP r9, #0x100\n\t"
  2737. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  2738. "BLT L_sp_2048_mul_d_64_word\n\t"
  2739. #else
  2740. "BLT.N L_sp_2048_mul_d_64_word\n\t"
  2741. #endif
  2742. "STR r3, [%[r], #256]\n\t"
  2743. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  2744. :
  2745. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  2746. );
  2747. }
  2748. #else
  2749. /* Mul a by digit b into r. (r = a * b)
  2750. *
  2751. * r A single precision integer.
  2752. * a A single precision integer.
  2753. * b A single precision digit.
  2754. */
  2755. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2756. static void sp_2048_mul_d_64(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  2757. #else
  2758. static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, sp_digit b)
  2759. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2760. {
  2761. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  2762. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  2763. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  2764. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  2765. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  2766. __asm__ __volatile__ (
  2767. /* A[0] * B */
  2768. "LDM %[a]!, {r8}\n\t"
  2769. "UMULL r3, r4, %[b], r8\n\t"
  2770. "STM %[r]!, {r3}\n\t"
  2771. "MOV r5, #0x0\n\t"
  2772. /* A[1] * B */
  2773. "LDM %[a]!, {r8}\n\t"
  2774. "UMLAL r4, r5, %[b], r8\n\t"
  2775. "STM %[r]!, {r4}\n\t"
  2776. "MOV r3, #0x0\n\t"
  2777. /* A[2] * B */
  2778. "LDM %[a]!, {r8}\n\t"
  2779. "UMLAL r5, r3, %[b], r8\n\t"
  2780. "STM %[r]!, {r5}\n\t"
  2781. "MOV r4, #0x0\n\t"
  2782. /* A[3] * B */
  2783. "LDM %[a]!, {r8}\n\t"
  2784. "UMLAL r3, r4, %[b], r8\n\t"
  2785. "STM %[r]!, {r3}\n\t"
  2786. "MOV r5, #0x0\n\t"
  2787. /* A[4] * B */
  2788. "LDM %[a]!, {r8}\n\t"
  2789. "UMLAL r4, r5, %[b], r8\n\t"
  2790. "STM %[r]!, {r4}\n\t"
  2791. "MOV r3, #0x0\n\t"
  2792. /* A[5] * B */
  2793. "LDM %[a]!, {r8}\n\t"
  2794. "UMLAL r5, r3, %[b], r8\n\t"
  2795. "STM %[r]!, {r5}\n\t"
  2796. "MOV r4, #0x0\n\t"
  2797. /* A[6] * B */
  2798. "LDM %[a]!, {r8}\n\t"
  2799. "UMLAL r3, r4, %[b], r8\n\t"
  2800. "STM %[r]!, {r3}\n\t"
  2801. "MOV r5, #0x0\n\t"
  2802. /* A[7] * B */
  2803. "LDM %[a]!, {r8}\n\t"
  2804. "UMLAL r4, r5, %[b], r8\n\t"
  2805. "STM %[r]!, {r4}\n\t"
  2806. "MOV r3, #0x0\n\t"
  2807. /* A[8] * B */
  2808. "LDM %[a]!, {r8}\n\t"
  2809. "UMLAL r5, r3, %[b], r8\n\t"
  2810. "STM %[r]!, {r5}\n\t"
  2811. "MOV r4, #0x0\n\t"
  2812. /* A[9] * B */
  2813. "LDM %[a]!, {r8}\n\t"
  2814. "UMLAL r3, r4, %[b], r8\n\t"
  2815. "STM %[r]!, {r3}\n\t"
  2816. "MOV r5, #0x0\n\t"
  2817. /* A[10] * B */
  2818. "LDM %[a]!, {r8}\n\t"
  2819. "UMLAL r4, r5, %[b], r8\n\t"
  2820. "STM %[r]!, {r4}\n\t"
  2821. "MOV r3, #0x0\n\t"
  2822. /* A[11] * B */
  2823. "LDM %[a]!, {r8}\n\t"
  2824. "UMLAL r5, r3, %[b], r8\n\t"
  2825. "STM %[r]!, {r5}\n\t"
  2826. "MOV r4, #0x0\n\t"
  2827. /* A[12] * B */
  2828. "LDM %[a]!, {r8}\n\t"
  2829. "UMLAL r3, r4, %[b], r8\n\t"
  2830. "STM %[r]!, {r3}\n\t"
  2831. "MOV r5, #0x0\n\t"
  2832. /* A[13] * B */
  2833. "LDM %[a]!, {r8}\n\t"
  2834. "UMLAL r4, r5, %[b], r8\n\t"
  2835. "STM %[r]!, {r4}\n\t"
  2836. "MOV r3, #0x0\n\t"
  2837. /* A[14] * B */
  2838. "LDM %[a]!, {r8}\n\t"
  2839. "UMLAL r5, r3, %[b], r8\n\t"
  2840. "STM %[r]!, {r5}\n\t"
  2841. "MOV r4, #0x0\n\t"
  2842. /* A[15] * B */
  2843. "LDM %[a]!, {r8}\n\t"
  2844. "UMLAL r3, r4, %[b], r8\n\t"
  2845. "STM %[r]!, {r3}\n\t"
  2846. "MOV r5, #0x0\n\t"
  2847. /* A[16] * B */
  2848. "LDM %[a]!, {r8}\n\t"
  2849. "UMLAL r4, r5, %[b], r8\n\t"
  2850. "STM %[r]!, {r4}\n\t"
  2851. "MOV r3, #0x0\n\t"
  2852. /* A[17] * B */
  2853. "LDM %[a]!, {r8}\n\t"
  2854. "UMLAL r5, r3, %[b], r8\n\t"
  2855. "STM %[r]!, {r5}\n\t"
  2856. "MOV r4, #0x0\n\t"
  2857. /* A[18] * B */
  2858. "LDM %[a]!, {r8}\n\t"
  2859. "UMLAL r3, r4, %[b], r8\n\t"
  2860. "STM %[r]!, {r3}\n\t"
  2861. "MOV r5, #0x0\n\t"
  2862. /* A[19] * B */
  2863. "LDM %[a]!, {r8}\n\t"
  2864. "UMLAL r4, r5, %[b], r8\n\t"
  2865. "STM %[r]!, {r4}\n\t"
  2866. "MOV r3, #0x0\n\t"
  2867. /* A[20] * B */
  2868. "LDM %[a]!, {r8}\n\t"
  2869. "UMLAL r5, r3, %[b], r8\n\t"
  2870. "STM %[r]!, {r5}\n\t"
  2871. "MOV r4, #0x0\n\t"
  2872. /* A[21] * B */
  2873. "LDM %[a]!, {r8}\n\t"
  2874. "UMLAL r3, r4, %[b], r8\n\t"
  2875. "STM %[r]!, {r3}\n\t"
  2876. "MOV r5, #0x0\n\t"
  2877. /* A[22] * B */
  2878. "LDM %[a]!, {r8}\n\t"
  2879. "UMLAL r4, r5, %[b], r8\n\t"
  2880. "STM %[r]!, {r4}\n\t"
  2881. "MOV r3, #0x0\n\t"
  2882. /* A[23] * B */
  2883. "LDM %[a]!, {r8}\n\t"
  2884. "UMLAL r5, r3, %[b], r8\n\t"
  2885. "STM %[r]!, {r5}\n\t"
  2886. "MOV r4, #0x0\n\t"
  2887. /* A[24] * B */
  2888. "LDM %[a]!, {r8}\n\t"
  2889. "UMLAL r3, r4, %[b], r8\n\t"
  2890. "STM %[r]!, {r3}\n\t"
  2891. "MOV r5, #0x0\n\t"
  2892. /* A[25] * B */
  2893. "LDM %[a]!, {r8}\n\t"
  2894. "UMLAL r4, r5, %[b], r8\n\t"
  2895. "STM %[r]!, {r4}\n\t"
  2896. "MOV r3, #0x0\n\t"
  2897. /* A[26] * B */
  2898. "LDM %[a]!, {r8}\n\t"
  2899. "UMLAL r5, r3, %[b], r8\n\t"
  2900. "STM %[r]!, {r5}\n\t"
  2901. "MOV r4, #0x0\n\t"
  2902. /* A[27] * B */
  2903. "LDM %[a]!, {r8}\n\t"
  2904. "UMLAL r3, r4, %[b], r8\n\t"
  2905. "STM %[r]!, {r3}\n\t"
  2906. "MOV r5, #0x0\n\t"
  2907. /* A[28] * B */
  2908. "LDM %[a]!, {r8}\n\t"
  2909. "UMLAL r4, r5, %[b], r8\n\t"
  2910. "STM %[r]!, {r4}\n\t"
  2911. "MOV r3, #0x0\n\t"
  2912. /* A[29] * B */
  2913. "LDM %[a]!, {r8}\n\t"
  2914. "UMLAL r5, r3, %[b], r8\n\t"
  2915. "STM %[r]!, {r5}\n\t"
  2916. "MOV r4, #0x0\n\t"
  2917. /* A[30] * B */
  2918. "LDM %[a]!, {r8}\n\t"
  2919. "UMLAL r3, r4, %[b], r8\n\t"
  2920. "STM %[r]!, {r3}\n\t"
  2921. "MOV r5, #0x0\n\t"
  2922. /* A[31] * B */
  2923. "LDM %[a]!, {r8}\n\t"
  2924. "UMLAL r4, r5, %[b], r8\n\t"
  2925. "STM %[r]!, {r4}\n\t"
  2926. "MOV r3, #0x0\n\t"
  2927. /* A[32] * B */
  2928. "LDM %[a]!, {r8}\n\t"
  2929. "UMLAL r5, r3, %[b], r8\n\t"
  2930. "STM %[r]!, {r5}\n\t"
  2931. "MOV r4, #0x0\n\t"
  2932. /* A[33] * B */
  2933. "LDM %[a]!, {r8}\n\t"
  2934. "UMLAL r3, r4, %[b], r8\n\t"
  2935. "STM %[r]!, {r3}\n\t"
  2936. "MOV r5, #0x0\n\t"
  2937. /* A[34] * B */
  2938. "LDM %[a]!, {r8}\n\t"
  2939. "UMLAL r4, r5, %[b], r8\n\t"
  2940. "STM %[r]!, {r4}\n\t"
  2941. "MOV r3, #0x0\n\t"
  2942. /* A[35] * B */
  2943. "LDM %[a]!, {r8}\n\t"
  2944. "UMLAL r5, r3, %[b], r8\n\t"
  2945. "STM %[r]!, {r5}\n\t"
  2946. "MOV r4, #0x0\n\t"
  2947. /* A[36] * B */
  2948. "LDM %[a]!, {r8}\n\t"
  2949. "UMLAL r3, r4, %[b], r8\n\t"
  2950. "STM %[r]!, {r3}\n\t"
  2951. "MOV r5, #0x0\n\t"
  2952. /* A[37] * B */
  2953. "LDM %[a]!, {r8}\n\t"
  2954. "UMLAL r4, r5, %[b], r8\n\t"
  2955. "STM %[r]!, {r4}\n\t"
  2956. "MOV r3, #0x0\n\t"
  2957. /* A[38] * B */
  2958. "LDM %[a]!, {r8}\n\t"
  2959. "UMLAL r5, r3, %[b], r8\n\t"
  2960. "STM %[r]!, {r5}\n\t"
  2961. "MOV r4, #0x0\n\t"
  2962. /* A[39] * B */
  2963. "LDM %[a]!, {r8}\n\t"
  2964. "UMLAL r3, r4, %[b], r8\n\t"
  2965. "STM %[r]!, {r3}\n\t"
  2966. "MOV r5, #0x0\n\t"
  2967. /* A[40] * B */
  2968. "LDM %[a]!, {r8}\n\t"
  2969. "UMLAL r4, r5, %[b], r8\n\t"
  2970. "STM %[r]!, {r4}\n\t"
  2971. "MOV r3, #0x0\n\t"
  2972. /* A[41] * B */
  2973. "LDM %[a]!, {r8}\n\t"
  2974. "UMLAL r5, r3, %[b], r8\n\t"
  2975. "STM %[r]!, {r5}\n\t"
  2976. "MOV r4, #0x0\n\t"
  2977. /* A[42] * B */
  2978. "LDM %[a]!, {r8}\n\t"
  2979. "UMLAL r3, r4, %[b], r8\n\t"
  2980. "STM %[r]!, {r3}\n\t"
  2981. "MOV r5, #0x0\n\t"
  2982. /* A[43] * B */
  2983. "LDM %[a]!, {r8}\n\t"
  2984. "UMLAL r4, r5, %[b], r8\n\t"
  2985. "STM %[r]!, {r4}\n\t"
  2986. "MOV r3, #0x0\n\t"
  2987. /* A[44] * B */
  2988. "LDM %[a]!, {r8}\n\t"
  2989. "UMLAL r5, r3, %[b], r8\n\t"
  2990. "STM %[r]!, {r5}\n\t"
  2991. "MOV r4, #0x0\n\t"
  2992. /* A[45] * B */
  2993. "LDM %[a]!, {r8}\n\t"
  2994. "UMLAL r3, r4, %[b], r8\n\t"
  2995. "STM %[r]!, {r3}\n\t"
  2996. "MOV r5, #0x0\n\t"
  2997. /* A[46] * B */
  2998. "LDM %[a]!, {r8}\n\t"
  2999. "UMLAL r4, r5, %[b], r8\n\t"
  3000. "STM %[r]!, {r4}\n\t"
  3001. "MOV r3, #0x0\n\t"
  3002. /* A[47] * B */
  3003. "LDM %[a]!, {r8}\n\t"
  3004. "UMLAL r5, r3, %[b], r8\n\t"
  3005. "STM %[r]!, {r5}\n\t"
  3006. "MOV r4, #0x0\n\t"
  3007. /* A[48] * B */
  3008. "LDM %[a]!, {r8}\n\t"
  3009. "UMLAL r3, r4, %[b], r8\n\t"
  3010. "STM %[r]!, {r3}\n\t"
  3011. "MOV r5, #0x0\n\t"
  3012. /* A[49] * B */
  3013. "LDM %[a]!, {r8}\n\t"
  3014. "UMLAL r4, r5, %[b], r8\n\t"
  3015. "STM %[r]!, {r4}\n\t"
  3016. "MOV r3, #0x0\n\t"
  3017. /* A[50] * B */
  3018. "LDM %[a]!, {r8}\n\t"
  3019. "UMLAL r5, r3, %[b], r8\n\t"
  3020. "STM %[r]!, {r5}\n\t"
  3021. "MOV r4, #0x0\n\t"
  3022. /* A[51] * B */
  3023. "LDM %[a]!, {r8}\n\t"
  3024. "UMLAL r3, r4, %[b], r8\n\t"
  3025. "STM %[r]!, {r3}\n\t"
  3026. "MOV r5, #0x0\n\t"
  3027. /* A[52] * B */
  3028. "LDM %[a]!, {r8}\n\t"
  3029. "UMLAL r4, r5, %[b], r8\n\t"
  3030. "STM %[r]!, {r4}\n\t"
  3031. "MOV r3, #0x0\n\t"
  3032. /* A[53] * B */
  3033. "LDM %[a]!, {r8}\n\t"
  3034. "UMLAL r5, r3, %[b], r8\n\t"
  3035. "STM %[r]!, {r5}\n\t"
  3036. "MOV r4, #0x0\n\t"
  3037. /* A[54] * B */
  3038. "LDM %[a]!, {r8}\n\t"
  3039. "UMLAL r3, r4, %[b], r8\n\t"
  3040. "STM %[r]!, {r3}\n\t"
  3041. "MOV r5, #0x0\n\t"
  3042. /* A[55] * B */
  3043. "LDM %[a]!, {r8}\n\t"
  3044. "UMLAL r4, r5, %[b], r8\n\t"
  3045. "STM %[r]!, {r4}\n\t"
  3046. "MOV r3, #0x0\n\t"
  3047. /* A[56] * B */
  3048. "LDM %[a]!, {r8}\n\t"
  3049. "UMLAL r5, r3, %[b], r8\n\t"
  3050. "STM %[r]!, {r5}\n\t"
  3051. "MOV r4, #0x0\n\t"
  3052. /* A[57] * B */
  3053. "LDM %[a]!, {r8}\n\t"
  3054. "UMLAL r3, r4, %[b], r8\n\t"
  3055. "STM %[r]!, {r3}\n\t"
  3056. "MOV r5, #0x0\n\t"
  3057. /* A[58] * B */
  3058. "LDM %[a]!, {r8}\n\t"
  3059. "UMLAL r4, r5, %[b], r8\n\t"
  3060. "STM %[r]!, {r4}\n\t"
  3061. "MOV r3, #0x0\n\t"
  3062. /* A[59] * B */
  3063. "LDM %[a]!, {r8}\n\t"
  3064. "UMLAL r5, r3, %[b], r8\n\t"
  3065. "STM %[r]!, {r5}\n\t"
  3066. "MOV r4, #0x0\n\t"
  3067. /* A[60] * B */
  3068. "LDM %[a]!, {r8}\n\t"
  3069. "UMLAL r3, r4, %[b], r8\n\t"
  3070. "STM %[r]!, {r3}\n\t"
  3071. "MOV r5, #0x0\n\t"
  3072. /* A[61] * B */
  3073. "LDM %[a]!, {r8}\n\t"
  3074. "UMLAL r4, r5, %[b], r8\n\t"
  3075. "STM %[r]!, {r4}\n\t"
  3076. "MOV r3, #0x0\n\t"
  3077. /* A[62] * B */
  3078. "LDM %[a]!, {r8}\n\t"
  3079. "UMLAL r5, r3, %[b], r8\n\t"
  3080. "STM %[r]!, {r5}\n\t"
  3081. "MOV r4, #0x0\n\t"
  3082. /* A[63] * B */
  3083. "LDM %[a]!, {r8}\n\t"
  3084. "UMLAL r3, r4, %[b], r8\n\t"
  3085. "STM %[r]!, {r3}\n\t"
  3086. "STR r4, [%[r]]\n\t"
  3087. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  3088. :
  3089. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  3090. );
  3091. }
  3092. #endif /* WOLFSSL_SP_SMALL */
  3093. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  3094. /* r = 2^n mod m where n is the number of bits to reduce by.
  3095. * Given m must be 2048 bits, just need to subtract.
  3096. *
  3097. * r A single precision number.
  3098. * m A single precision number.
  3099. */
  3100. static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m)
  3101. {
  3102. XMEMSET(r, 0, sizeof(sp_digit) * 32);
  3103. /* r = 2^n mod m */
  3104. sp_2048_sub_in_place_32(r, m);
  3105. }
  3106. #ifdef WOLFSSL_SP_SMALL
  3107. /* Conditionally subtract b from a using the mask m.
  3108. * m is -1 to subtract and 0 when not copying.
  3109. *
  3110. * r A single precision number representing condition subtract result.
  3111. * a A single precision number to subtract from.
  3112. * b A single precision number to subtract.
  3113. * m Mask value to apply.
  3114. */
  3115. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3116. static sp_digit sp_2048_cond_sub_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  3117. #else
  3118. static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  3119. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3120. {
  3121. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3122. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  3123. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  3124. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  3125. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  3126. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3127. __asm__ __volatile__ (
  3128. "MOV r8, #0x0\n\t"
  3129. "MOV r4, #0x0\n\t"
  3130. "MOV r5, #0x0\n\t"
  3131. "\n"
  3132. "L_sp_2048_cond_sub_32_words:\n\t"
  3133. "SUBS r4, r8, r4\n\t"
  3134. "LDR r6, [%[a], r5]\n\t"
  3135. "LDR r7, [%[b], r5]\n\t"
  3136. "AND r7, r7, %[m]\n\t"
  3137. "SBCS r6, r6, r7\n\t"
  3138. "SBC r4, r8, r8\n\t"
  3139. "STR r6, [%[r], r5]\n\t"
  3140. "ADD r5, r5, #0x4\n\t"
  3141. "CMP r5, #0x80\n\t"
  3142. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  3143. "BLT L_sp_2048_cond_sub_32_words\n\t"
  3144. #else
  3145. "BLT.N L_sp_2048_cond_sub_32_words\n\t"
  3146. #endif
  3147. "MOV %[r], r4\n\t"
  3148. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  3149. :
  3150. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  3151. );
  3152. return (uint32_t)(size_t)r;
  3153. }
  3154. #else
  3155. /* Conditionally subtract b from a using the mask m.
  3156. * m is -1 to subtract and 0 when not copying.
  3157. *
  3158. * r A single precision number representing condition subtract result.
  3159. * a A single precision number to subtract from.
  3160. * b A single precision number to subtract.
  3161. * m Mask value to apply.
  3162. */
  3163. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3164. static sp_digit sp_2048_cond_sub_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  3165. #else
  3166. static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  3167. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3168. {
  3169. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3170. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  3171. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  3172. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  3173. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  3174. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3175. __asm__ __volatile__ (
  3176. "MOV r5, #0x0\n\t"
  3177. "LDM %[a]!, {r6, r7}\n\t"
  3178. "LDM %[b]!, {r8, r9}\n\t"
  3179. "AND r8, r8, %[m]\n\t"
  3180. "AND r9, r9, %[m]\n\t"
  3181. "SUBS r6, r6, r8\n\t"
  3182. "SBCS r7, r7, r9\n\t"
  3183. "STM %[r]!, {r6, r7}\n\t"
  3184. "LDM %[a]!, {r6, r7}\n\t"
  3185. "LDM %[b]!, {r8, r9}\n\t"
  3186. "AND r8, r8, %[m]\n\t"
  3187. "AND r9, r9, %[m]\n\t"
  3188. "SBCS r6, r6, r8\n\t"
  3189. "SBCS r7, r7, r9\n\t"
  3190. "STM %[r]!, {r6, r7}\n\t"
  3191. "LDM %[a]!, {r6, r7}\n\t"
  3192. "LDM %[b]!, {r8, r9}\n\t"
  3193. "AND r8, r8, %[m]\n\t"
  3194. "AND r9, r9, %[m]\n\t"
  3195. "SBCS r6, r6, r8\n\t"
  3196. "SBCS r7, r7, r9\n\t"
  3197. "STM %[r]!, {r6, r7}\n\t"
  3198. "LDM %[a]!, {r6, r7}\n\t"
  3199. "LDM %[b]!, {r8, r9}\n\t"
  3200. "AND r8, r8, %[m]\n\t"
  3201. "AND r9, r9, %[m]\n\t"
  3202. "SBCS r6, r6, r8\n\t"
  3203. "SBCS r7, r7, r9\n\t"
  3204. "STM %[r]!, {r6, r7}\n\t"
  3205. "LDM %[a]!, {r6, r7}\n\t"
  3206. "LDM %[b]!, {r8, r9}\n\t"
  3207. "AND r8, r8, %[m]\n\t"
  3208. "AND r9, r9, %[m]\n\t"
  3209. "SBCS r6, r6, r8\n\t"
  3210. "SBCS r7, r7, r9\n\t"
  3211. "STM %[r]!, {r6, r7}\n\t"
  3212. "LDM %[a]!, {r6, r7}\n\t"
  3213. "LDM %[b]!, {r8, r9}\n\t"
  3214. "AND r8, r8, %[m]\n\t"
  3215. "AND r9, r9, %[m]\n\t"
  3216. "SBCS r6, r6, r8\n\t"
  3217. "SBCS r7, r7, r9\n\t"
  3218. "STM %[r]!, {r6, r7}\n\t"
  3219. "LDM %[a]!, {r6, r7}\n\t"
  3220. "LDM %[b]!, {r8, r9}\n\t"
  3221. "AND r8, r8, %[m]\n\t"
  3222. "AND r9, r9, %[m]\n\t"
  3223. "SBCS r6, r6, r8\n\t"
  3224. "SBCS r7, r7, r9\n\t"
  3225. "STM %[r]!, {r6, r7}\n\t"
  3226. "LDM %[a]!, {r6, r7}\n\t"
  3227. "LDM %[b]!, {r8, r9}\n\t"
  3228. "AND r8, r8, %[m]\n\t"
  3229. "AND r9, r9, %[m]\n\t"
  3230. "SBCS r6, r6, r8\n\t"
  3231. "SBCS r7, r7, r9\n\t"
  3232. "STM %[r]!, {r6, r7}\n\t"
  3233. "LDM %[a]!, {r6, r7}\n\t"
  3234. "LDM %[b]!, {r8, r9}\n\t"
  3235. "AND r8, r8, %[m]\n\t"
  3236. "AND r9, r9, %[m]\n\t"
  3237. "SBCS r6, r6, r8\n\t"
  3238. "SBCS r7, r7, r9\n\t"
  3239. "STM %[r]!, {r6, r7}\n\t"
  3240. "LDM %[a]!, {r6, r7}\n\t"
  3241. "LDM %[b]!, {r8, r9}\n\t"
  3242. "AND r8, r8, %[m]\n\t"
  3243. "AND r9, r9, %[m]\n\t"
  3244. "SBCS r6, r6, r8\n\t"
  3245. "SBCS r7, r7, r9\n\t"
  3246. "STM %[r]!, {r6, r7}\n\t"
  3247. "LDM %[a]!, {r6, r7}\n\t"
  3248. "LDM %[b]!, {r8, r9}\n\t"
  3249. "AND r8, r8, %[m]\n\t"
  3250. "AND r9, r9, %[m]\n\t"
  3251. "SBCS r6, r6, r8\n\t"
  3252. "SBCS r7, r7, r9\n\t"
  3253. "STM %[r]!, {r6, r7}\n\t"
  3254. "LDM %[a]!, {r6, r7}\n\t"
  3255. "LDM %[b]!, {r8, r9}\n\t"
  3256. "AND r8, r8, %[m]\n\t"
  3257. "AND r9, r9, %[m]\n\t"
  3258. "SBCS r6, r6, r8\n\t"
  3259. "SBCS r7, r7, r9\n\t"
  3260. "STM %[r]!, {r6, r7}\n\t"
  3261. "LDM %[a]!, {r6, r7}\n\t"
  3262. "LDM %[b]!, {r8, r9}\n\t"
  3263. "AND r8, r8, %[m]\n\t"
  3264. "AND r9, r9, %[m]\n\t"
  3265. "SBCS r6, r6, r8\n\t"
  3266. "SBCS r7, r7, r9\n\t"
  3267. "STM %[r]!, {r6, r7}\n\t"
  3268. "LDM %[a]!, {r6, r7}\n\t"
  3269. "LDM %[b]!, {r8, r9}\n\t"
  3270. "AND r8, r8, %[m]\n\t"
  3271. "AND r9, r9, %[m]\n\t"
  3272. "SBCS r6, r6, r8\n\t"
  3273. "SBCS r7, r7, r9\n\t"
  3274. "STM %[r]!, {r6, r7}\n\t"
  3275. "LDM %[a]!, {r6, r7}\n\t"
  3276. "LDM %[b]!, {r8, r9}\n\t"
  3277. "AND r8, r8, %[m]\n\t"
  3278. "AND r9, r9, %[m]\n\t"
  3279. "SBCS r6, r6, r8\n\t"
  3280. "SBCS r7, r7, r9\n\t"
  3281. "STM %[r]!, {r6, r7}\n\t"
  3282. "LDM %[a]!, {r6, r7}\n\t"
  3283. "LDM %[b]!, {r8, r9}\n\t"
  3284. "AND r8, r8, %[m]\n\t"
  3285. "AND r9, r9, %[m]\n\t"
  3286. "SBCS r6, r6, r8\n\t"
  3287. "SBCS r7, r7, r9\n\t"
  3288. "STM %[r]!, {r6, r7}\n\t"
  3289. "SBC %[r], r5, r5\n\t"
  3290. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  3291. :
  3292. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  3293. );
  3294. return (uint32_t)(size_t)r;
  3295. }
  3296. #endif /* WOLFSSL_SP_SMALL */
  3297. #ifdef WOLFSSL_SP_NO_UMAAL
  3298. #ifndef WOLFSSL_SP_SMALL
  3299. /* Reduce the number back to 2048 bits using Montgomery reduction.
  3300. *
  3301. * a A single precision number to reduce in place.
  3302. * m The single precision number representing the modulus.
  3303. * mp The digit representing the negative inverse of m mod 2^n.
  3304. */
  3305. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3306. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  3307. #else
  3308. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp)
  3309. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3310. {
  3311. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3312. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  3313. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  3314. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  3315. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3316. __asm__ __volatile__ (
  3317. "LDR lr, [%[m]]\n\t"
  3318. /* i = 0 */
  3319. "MOV r11, #0x0\n\t"
  3320. "MOV r3, #0x0\n\t"
  3321. "LDR r4, [%[a]]\n\t"
  3322. "LDR r5, [%[a], #4]\n\t"
  3323. "\n"
  3324. "L_sp_2048_mont_reduce_32_word:\n\t"
  3325. /* mu = a[i] * mp */
  3326. "MUL r10, %[mp], r4\n\t"
  3327. /* a[i+0] += m[0] * mu */
  3328. "MOV r7, #0x0\n\t"
  3329. "UMLAL r4, r7, r10, lr\n\t"
  3330. /* a[i+1] += m[1] * mu */
  3331. "LDR r9, [%[m], #4]\n\t"
  3332. "MOV r6, #0x0\n\t"
  3333. "UMLAL r5, r6, r10, r9\n\t"
  3334. "MOV r4, r5\n\t"
  3335. "ADDS r4, r4, r7\n\t"
  3336. "ADC r6, r6, #0x0\n\t"
  3337. /* a[i+2] += m[2] * mu */
  3338. "LDR r9, [%[m], #8]\n\t"
  3339. "LDR r5, [%[a], #8]\n\t"
  3340. "MOV r7, #0x0\n\t"
  3341. "UMLAL r5, r7, r10, r9\n\t"
  3342. "ADDS r5, r5, r6\n\t"
  3343. "ADC r7, r7, #0x0\n\t"
  3344. /* a[i+3] += m[3] * mu */
  3345. "LDR r9, [%[m], #12]\n\t"
  3346. "LDR r12, [%[a], #12]\n\t"
  3347. "MOV r6, #0x0\n\t"
  3348. "UMLAL r12, r6, r10, r9\n\t"
  3349. "ADDS r12, r12, r7\n\t"
  3350. "STR r12, [%[a], #12]\n\t"
  3351. "ADC r6, r6, #0x0\n\t"
  3352. /* a[i+4] += m[4] * mu */
  3353. "LDR r9, [%[m], #16]\n\t"
  3354. "LDR r12, [%[a], #16]\n\t"
  3355. "MOV r7, #0x0\n\t"
  3356. "UMLAL r12, r7, r10, r9\n\t"
  3357. "ADDS r12, r12, r6\n\t"
  3358. "STR r12, [%[a], #16]\n\t"
  3359. "ADC r7, r7, #0x0\n\t"
  3360. /* a[i+5] += m[5] * mu */
  3361. "LDR r9, [%[m], #20]\n\t"
  3362. "LDR r12, [%[a], #20]\n\t"
  3363. "MOV r6, #0x0\n\t"
  3364. "UMLAL r12, r6, r10, r9\n\t"
  3365. "ADDS r12, r12, r7\n\t"
  3366. "STR r12, [%[a], #20]\n\t"
  3367. "ADC r6, r6, #0x0\n\t"
  3368. /* a[i+6] += m[6] * mu */
  3369. "LDR r9, [%[m], #24]\n\t"
  3370. "LDR r12, [%[a], #24]\n\t"
  3371. "MOV r7, #0x0\n\t"
  3372. "UMLAL r12, r7, r10, r9\n\t"
  3373. "ADDS r12, r12, r6\n\t"
  3374. "STR r12, [%[a], #24]\n\t"
  3375. "ADC r7, r7, #0x0\n\t"
  3376. /* a[i+7] += m[7] * mu */
  3377. "LDR r9, [%[m], #28]\n\t"
  3378. "LDR r12, [%[a], #28]\n\t"
  3379. "MOV r6, #0x0\n\t"
  3380. "UMLAL r12, r6, r10, r9\n\t"
  3381. "ADDS r12, r12, r7\n\t"
  3382. "STR r12, [%[a], #28]\n\t"
  3383. "ADC r6, r6, #0x0\n\t"
  3384. /* a[i+8] += m[8] * mu */
  3385. "LDR r9, [%[m], #32]\n\t"
  3386. "LDR r12, [%[a], #32]\n\t"
  3387. "MOV r7, #0x0\n\t"
  3388. "UMLAL r12, r7, r10, r9\n\t"
  3389. "ADDS r12, r12, r6\n\t"
  3390. "STR r12, [%[a], #32]\n\t"
  3391. "ADC r7, r7, #0x0\n\t"
  3392. /* a[i+9] += m[9] * mu */
  3393. "LDR r9, [%[m], #36]\n\t"
  3394. "LDR r12, [%[a], #36]\n\t"
  3395. "MOV r6, #0x0\n\t"
  3396. "UMLAL r12, r6, r10, r9\n\t"
  3397. "ADDS r12, r12, r7\n\t"
  3398. "STR r12, [%[a], #36]\n\t"
  3399. "ADC r6, r6, #0x0\n\t"
  3400. /* a[i+10] += m[10] * mu */
  3401. "LDR r9, [%[m], #40]\n\t"
  3402. "LDR r12, [%[a], #40]\n\t"
  3403. "MOV r7, #0x0\n\t"
  3404. "UMLAL r12, r7, r10, r9\n\t"
  3405. "ADDS r12, r12, r6\n\t"
  3406. "STR r12, [%[a], #40]\n\t"
  3407. "ADC r7, r7, #0x0\n\t"
  3408. /* a[i+11] += m[11] * mu */
  3409. "LDR r9, [%[m], #44]\n\t"
  3410. "LDR r12, [%[a], #44]\n\t"
  3411. "MOV r6, #0x0\n\t"
  3412. "UMLAL r12, r6, r10, r9\n\t"
  3413. "ADDS r12, r12, r7\n\t"
  3414. "STR r12, [%[a], #44]\n\t"
  3415. "ADC r6, r6, #0x0\n\t"
  3416. /* a[i+12] += m[12] * mu */
  3417. "LDR r9, [%[m], #48]\n\t"
  3418. "LDR r12, [%[a], #48]\n\t"
  3419. "MOV r7, #0x0\n\t"
  3420. "UMLAL r12, r7, r10, r9\n\t"
  3421. "ADDS r12, r12, r6\n\t"
  3422. "STR r12, [%[a], #48]\n\t"
  3423. "ADC r7, r7, #0x0\n\t"
  3424. /* a[i+13] += m[13] * mu */
  3425. "LDR r9, [%[m], #52]\n\t"
  3426. "LDR r12, [%[a], #52]\n\t"
  3427. "MOV r6, #0x0\n\t"
  3428. "UMLAL r12, r6, r10, r9\n\t"
  3429. "ADDS r12, r12, r7\n\t"
  3430. "STR r12, [%[a], #52]\n\t"
  3431. "ADC r6, r6, #0x0\n\t"
  3432. /* a[i+14] += m[14] * mu */
  3433. "LDR r9, [%[m], #56]\n\t"
  3434. "LDR r12, [%[a], #56]\n\t"
  3435. "MOV r7, #0x0\n\t"
  3436. "UMLAL r12, r7, r10, r9\n\t"
  3437. "ADDS r12, r12, r6\n\t"
  3438. "STR r12, [%[a], #56]\n\t"
  3439. "ADC r7, r7, #0x0\n\t"
  3440. /* a[i+15] += m[15] * mu */
  3441. "LDR r9, [%[m], #60]\n\t"
  3442. "LDR r12, [%[a], #60]\n\t"
  3443. "MOV r6, #0x0\n\t"
  3444. "UMLAL r12, r6, r10, r9\n\t"
  3445. "ADDS r12, r12, r7\n\t"
  3446. "STR r12, [%[a], #60]\n\t"
  3447. "ADC r6, r6, #0x0\n\t"
  3448. /* a[i+16] += m[16] * mu */
  3449. "LDR r9, [%[m], #64]\n\t"
  3450. "LDR r12, [%[a], #64]\n\t"
  3451. "MOV r7, #0x0\n\t"
  3452. "UMLAL r12, r7, r10, r9\n\t"
  3453. "ADDS r12, r12, r6\n\t"
  3454. "STR r12, [%[a], #64]\n\t"
  3455. "ADC r7, r7, #0x0\n\t"
  3456. /* a[i+17] += m[17] * mu */
  3457. "LDR r9, [%[m], #68]\n\t"
  3458. "LDR r12, [%[a], #68]\n\t"
  3459. "MOV r6, #0x0\n\t"
  3460. "UMLAL r12, r6, r10, r9\n\t"
  3461. "ADDS r12, r12, r7\n\t"
  3462. "STR r12, [%[a], #68]\n\t"
  3463. "ADC r6, r6, #0x0\n\t"
  3464. /* a[i+18] += m[18] * mu */
  3465. "LDR r9, [%[m], #72]\n\t"
  3466. "LDR r12, [%[a], #72]\n\t"
  3467. "MOV r7, #0x0\n\t"
  3468. "UMLAL r12, r7, r10, r9\n\t"
  3469. "ADDS r12, r12, r6\n\t"
  3470. "STR r12, [%[a], #72]\n\t"
  3471. "ADC r7, r7, #0x0\n\t"
  3472. /* a[i+19] += m[19] * mu */
  3473. "LDR r9, [%[m], #76]\n\t"
  3474. "LDR r12, [%[a], #76]\n\t"
  3475. "MOV r6, #0x0\n\t"
  3476. "UMLAL r12, r6, r10, r9\n\t"
  3477. "ADDS r12, r12, r7\n\t"
  3478. "STR r12, [%[a], #76]\n\t"
  3479. "ADC r6, r6, #0x0\n\t"
  3480. /* a[i+20] += m[20] * mu */
  3481. "LDR r9, [%[m], #80]\n\t"
  3482. "LDR r12, [%[a], #80]\n\t"
  3483. "MOV r7, #0x0\n\t"
  3484. "UMLAL r12, r7, r10, r9\n\t"
  3485. "ADDS r12, r12, r6\n\t"
  3486. "STR r12, [%[a], #80]\n\t"
  3487. "ADC r7, r7, #0x0\n\t"
  3488. /* a[i+21] += m[21] * mu */
  3489. "LDR r9, [%[m], #84]\n\t"
  3490. "LDR r12, [%[a], #84]\n\t"
  3491. "MOV r6, #0x0\n\t"
  3492. "UMLAL r12, r6, r10, r9\n\t"
  3493. "ADDS r12, r12, r7\n\t"
  3494. "STR r12, [%[a], #84]\n\t"
  3495. "ADC r6, r6, #0x0\n\t"
  3496. /* a[i+22] += m[22] * mu */
  3497. "LDR r9, [%[m], #88]\n\t"
  3498. "LDR r12, [%[a], #88]\n\t"
  3499. "MOV r7, #0x0\n\t"
  3500. "UMLAL r12, r7, r10, r9\n\t"
  3501. "ADDS r12, r12, r6\n\t"
  3502. "STR r12, [%[a], #88]\n\t"
  3503. "ADC r7, r7, #0x0\n\t"
  3504. /* a[i+23] += m[23] * mu */
  3505. "LDR r9, [%[m], #92]\n\t"
  3506. "LDR r12, [%[a], #92]\n\t"
  3507. "MOV r6, #0x0\n\t"
  3508. "UMLAL r12, r6, r10, r9\n\t"
  3509. "ADDS r12, r12, r7\n\t"
  3510. "STR r12, [%[a], #92]\n\t"
  3511. "ADC r6, r6, #0x0\n\t"
  3512. /* a[i+24] += m[24] * mu */
  3513. "LDR r9, [%[m], #96]\n\t"
  3514. "LDR r12, [%[a], #96]\n\t"
  3515. "MOV r7, #0x0\n\t"
  3516. "UMLAL r12, r7, r10, r9\n\t"
  3517. "ADDS r12, r12, r6\n\t"
  3518. "STR r12, [%[a], #96]\n\t"
  3519. "ADC r7, r7, #0x0\n\t"
  3520. /* a[i+25] += m[25] * mu */
  3521. "LDR r9, [%[m], #100]\n\t"
  3522. "LDR r12, [%[a], #100]\n\t"
  3523. "MOV r6, #0x0\n\t"
  3524. "UMLAL r12, r6, r10, r9\n\t"
  3525. "ADDS r12, r12, r7\n\t"
  3526. "STR r12, [%[a], #100]\n\t"
  3527. "ADC r6, r6, #0x0\n\t"
  3528. /* a[i+26] += m[26] * mu */
  3529. "LDR r9, [%[m], #104]\n\t"
  3530. "LDR r12, [%[a], #104]\n\t"
  3531. "MOV r7, #0x0\n\t"
  3532. "UMLAL r12, r7, r10, r9\n\t"
  3533. "ADDS r12, r12, r6\n\t"
  3534. "STR r12, [%[a], #104]\n\t"
  3535. "ADC r7, r7, #0x0\n\t"
  3536. /* a[i+27] += m[27] * mu */
  3537. "LDR r9, [%[m], #108]\n\t"
  3538. "LDR r12, [%[a], #108]\n\t"
  3539. "MOV r6, #0x0\n\t"
  3540. "UMLAL r12, r6, r10, r9\n\t"
  3541. "ADDS r12, r12, r7\n\t"
  3542. "STR r12, [%[a], #108]\n\t"
  3543. "ADC r6, r6, #0x0\n\t"
  3544. /* a[i+28] += m[28] * mu */
  3545. "LDR r9, [%[m], #112]\n\t"
  3546. "LDR r12, [%[a], #112]\n\t"
  3547. "MOV r7, #0x0\n\t"
  3548. "UMLAL r12, r7, r10, r9\n\t"
  3549. "ADDS r12, r12, r6\n\t"
  3550. "STR r12, [%[a], #112]\n\t"
  3551. "ADC r7, r7, #0x0\n\t"
  3552. /* a[i+29] += m[29] * mu */
  3553. "LDR r9, [%[m], #116]\n\t"
  3554. "LDR r12, [%[a], #116]\n\t"
  3555. "MOV r6, #0x0\n\t"
  3556. "UMLAL r12, r6, r10, r9\n\t"
  3557. "ADDS r12, r12, r7\n\t"
  3558. "STR r12, [%[a], #116]\n\t"
  3559. "ADC r6, r6, #0x0\n\t"
  3560. /* a[i+30] += m[30] * mu */
  3561. "LDR r9, [%[m], #120]\n\t"
  3562. "LDR r12, [%[a], #120]\n\t"
  3563. "MOV r7, #0x0\n\t"
  3564. "UMLAL r12, r7, r10, r9\n\t"
  3565. "ADDS r12, r12, r6\n\t"
  3566. "STR r12, [%[a], #120]\n\t"
  3567. "ADC r7, r7, #0x0\n\t"
  3568. /* a[i+31] += m[31] * mu */
  3569. "LDR r9, [%[m], #124]\n\t"
  3570. "LDR r12, [%[a], #124]\n\t"
  3571. "UMULL r8, r9, r10, r9\n\t"
  3572. "ADDS r7, r7, r8\n\t"
  3573. "ADCS r6, r9, r3\n\t"
  3574. "MOV r3, #0x0\n\t"
  3575. "ADC r3, r3, r3\n\t"
  3576. "ADDS r12, r12, r7\n\t"
  3577. "STR r12, [%[a], #124]\n\t"
  3578. "LDR r12, [%[a], #128]\n\t"
  3579. "ADCS r12, r12, r6\n\t"
  3580. "STR r12, [%[a], #128]\n\t"
  3581. "ADC r3, r3, #0x0\n\t"
  3582. /* i += 1 */
  3583. "ADD r11, r11, #0x4\n\t"
  3584. "ADD %[a], %[a], #0x4\n\t"
  3585. "CMP r11, #0x80\n\t"
  3586. #ifdef __GNUC__
  3587. "BLT L_sp_2048_mont_reduce_32_word\n\t"
  3588. #else
  3589. "BLT.W L_sp_2048_mont_reduce_32_word\n\t"
  3590. #endif
  3591. /* Loop Done */
  3592. "STR r4, [%[a]]\n\t"
  3593. "STR r5, [%[a], #4]\n\t"
  3594. "MOV %[mp], r3\n\t"
  3595. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  3596. :
  3597. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  3598. );
  3599. sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - mp);
  3600. }
  3601. #else
  3602. /* Reduce the number back to 2048 bits using Montgomery reduction.
  3603. *
  3604. * a A single precision number to reduce in place.
  3605. * m The single precision number representing the modulus.
  3606. * mp The digit representing the negative inverse of m mod 2^n.
  3607. */
  3608. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3609. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  3610. #else
  3611. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp)
  3612. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3613. {
  3614. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3615. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  3616. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  3617. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  3618. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3619. __asm__ __volatile__ (
  3620. "LDR r11, [%[m]]\n\t"
  3621. /* i = 0 */
  3622. "MOV r9, #0x0\n\t"
  3623. /* ca = 0 */
  3624. "MOV r3, #0x0\n\t"
  3625. "\n"
  3626. "L_sp_2048_mont_reduce_32_word:\n\t"
  3627. /* mu = a[i] * mp */
  3628. "LDR r10, [%[a]]\n\t"
  3629. "MUL r8, %[mp], r10\n\t"
  3630. /* j = 0 */
  3631. "MOV r12, #0x0\n\t"
  3632. "MOV r4, #0x0\n\t"
  3633. "\n"
  3634. "L_sp_2048_mont_reduce_32_mul:\n\t"
  3635. /* a[i+j+0] += m[j+0] * mu */
  3636. "LDR r7, [%[m], r12]\n\t"
  3637. "LDR r10, [%[a], r12]\n\t"
  3638. "MOV r5, #0x0\n\t"
  3639. "UMLAL r10, r5, r8, r7\n\t"
  3640. "ADDS r10, r10, r4\n\t"
  3641. "STR r10, [%[a], r12]\n\t"
  3642. "ADC r4, r5, #0x0\n\t"
  3643. /* j += 1 */
  3644. "ADD r12, r12, #0x4\n\t"
  3645. /* a[i+j+1] += m[j+1] * mu */
  3646. "LDR r7, [%[m], r12]\n\t"
  3647. "LDR r10, [%[a], r12]\n\t"
  3648. "MOV r5, #0x0\n\t"
  3649. "UMLAL r10, r5, r8, r7\n\t"
  3650. "ADDS r10, r10, r4\n\t"
  3651. "STR r10, [%[a], r12]\n\t"
  3652. "ADC r4, r5, #0x0\n\t"
  3653. /* j += 1 */
  3654. "ADD r12, r12, #0x4\n\t"
  3655. /* a[i+j+2] += m[j+2] * mu */
  3656. "LDR r7, [%[m], r12]\n\t"
  3657. "LDR r10, [%[a], r12]\n\t"
  3658. "MOV r5, #0x0\n\t"
  3659. "UMLAL r10, r5, r8, r7\n\t"
  3660. "ADDS r10, r10, r4\n\t"
  3661. "STR r10, [%[a], r12]\n\t"
  3662. "ADC r4, r5, #0x0\n\t"
  3663. /* j += 1 */
  3664. "ADD r12, r12, #0x4\n\t"
  3665. /* a[i+j+3] += m[j+3] * mu */
  3666. "LDR r7, [%[m], r12]\n\t"
  3667. "LDR r10, [%[a], r12]\n\t"
  3668. "MOV r5, #0x0\n\t"
  3669. "UMLAL r10, r5, r8, r7\n\t"
  3670. "ADDS r10, r10, r4\n\t"
  3671. "STR r10, [%[a], r12]\n\t"
  3672. "ADC r4, r5, #0x0\n\t"
  3673. /* j += 1 */
  3674. "ADD r12, r12, #0x4\n\t"
  3675. "CMP r12, #0x80\n\t"
  3676. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  3677. "BLT L_sp_2048_mont_reduce_32_mul\n\t"
  3678. #else
  3679. "BLT.N L_sp_2048_mont_reduce_32_mul\n\t"
  3680. #endif
  3681. "LDR r10, [%[a], #128]\n\t"
  3682. "ADDS r4, r4, r3\n\t"
  3683. "MOV r3, #0x0\n\t"
  3684. "ADC r3, r3, #0x0\n\t"
  3685. "ADDS r10, r10, r4\n\t"
  3686. "ADC r3, r3, r3\n\t"
  3687. "STR r10, [%[a], #128]\n\t"
  3688. /* i += 1 */
  3689. "ADD r9, r9, #0x4\n\t"
  3690. "ADD %[a], %[a], #0x4\n\t"
  3691. "CMP r9, #0x80\n\t"
  3692. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  3693. "BLT L_sp_2048_mont_reduce_32_word\n\t"
  3694. #else
  3695. "BLT.N L_sp_2048_mont_reduce_32_word\n\t"
  3696. #endif
  3697. /* Loop Done */
  3698. "MOV %[mp], r3\n\t"
  3699. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  3700. :
  3701. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  3702. );
  3703. sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - mp);
  3704. }
  3705. #endif /* !WOLFSSL_SP_SMALL */
  3706. #else
  3707. #ifndef WOLFSSL_SP_SMALL
  3708. /* Reduce the number back to 2048 bits using Montgomery reduction.
  3709. *
  3710. * a A single precision number to reduce in place.
  3711. * m The single precision number representing the modulus.
  3712. * mp The digit representing the negative inverse of m mod 2^n.
  3713. */
  3714. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3715. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  3716. #else
  3717. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp)
  3718. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3719. {
  3720. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3721. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  3722. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  3723. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  3724. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3725. __asm__ __volatile__ (
  3726. /* i = 0 */
  3727. "MOV r4, #0x0\n\t"
  3728. "MOV r5, #0x0\n\t"
  3729. "LDR r6, [%[a]]\n\t"
  3730. "LDR r7, [%[a], #4]\n\t"
  3731. "LDR r8, [%[a], #8]\n\t"
  3732. "LDR r9, [%[a], #12]\n\t"
  3733. "LDR r10, [%[a], #16]\n\t"
  3734. "\n"
  3735. "L_sp_2048_mont_reduce_32_word:\n\t"
  3736. /* mu = a[i] * mp */
  3737. "MUL lr, %[mp], r6\n\t"
  3738. /* a[i+0] += m[0] * mu */
  3739. "LDR r12, [%[m]]\n\t"
  3740. "MOV r3, #0x0\n\t"
  3741. "UMAAL r6, r3, lr, r12\n\t"
  3742. /* a[i+1] += m[1] * mu */
  3743. "LDR r12, [%[m], #4]\n\t"
  3744. "MOV r6, r7\n\t"
  3745. "UMAAL r6, r3, lr, r12\n\t"
  3746. /* a[i+2] += m[2] * mu */
  3747. "LDR r12, [%[m], #8]\n\t"
  3748. "MOV r7, r8\n\t"
  3749. "UMAAL r7, r3, lr, r12\n\t"
  3750. /* a[i+3] += m[3] * mu */
  3751. "LDR r12, [%[m], #12]\n\t"
  3752. "MOV r8, r9\n\t"
  3753. "UMAAL r8, r3, lr, r12\n\t"
  3754. /* a[i+4] += m[4] * mu */
  3755. "LDR r12, [%[m], #16]\n\t"
  3756. "MOV r9, r10\n\t"
  3757. "UMAAL r9, r3, lr, r12\n\t"
  3758. /* a[i+5] += m[5] * mu */
  3759. "LDR r12, [%[m], #20]\n\t"
  3760. "LDR r10, [%[a], #20]\n\t"
  3761. "UMAAL r10, r3, lr, r12\n\t"
  3762. /* a[i+6] += m[6] * mu */
  3763. "LDR r12, [%[m], #24]\n\t"
  3764. "LDR r11, [%[a], #24]\n\t"
  3765. "UMAAL r11, r3, lr, r12\n\t"
  3766. "STR r11, [%[a], #24]\n\t"
  3767. /* a[i+7] += m[7] * mu */
  3768. "LDR r12, [%[m], #28]\n\t"
  3769. "LDR r11, [%[a], #28]\n\t"
  3770. "UMAAL r11, r3, lr, r12\n\t"
  3771. "STR r11, [%[a], #28]\n\t"
  3772. /* a[i+8] += m[8] * mu */
  3773. "LDR r12, [%[m], #32]\n\t"
  3774. "LDR r11, [%[a], #32]\n\t"
  3775. "UMAAL r11, r3, lr, r12\n\t"
  3776. "STR r11, [%[a], #32]\n\t"
  3777. /* a[i+9] += m[9] * mu */
  3778. "LDR r12, [%[m], #36]\n\t"
  3779. "LDR r11, [%[a], #36]\n\t"
  3780. "UMAAL r11, r3, lr, r12\n\t"
  3781. "STR r11, [%[a], #36]\n\t"
  3782. /* a[i+10] += m[10] * mu */
  3783. "LDR r12, [%[m], #40]\n\t"
  3784. "LDR r11, [%[a], #40]\n\t"
  3785. "UMAAL r11, r3, lr, r12\n\t"
  3786. "STR r11, [%[a], #40]\n\t"
  3787. /* a[i+11] += m[11] * mu */
  3788. "LDR r12, [%[m], #44]\n\t"
  3789. "LDR r11, [%[a], #44]\n\t"
  3790. "UMAAL r11, r3, lr, r12\n\t"
  3791. "STR r11, [%[a], #44]\n\t"
  3792. /* a[i+12] += m[12] * mu */
  3793. "LDR r12, [%[m], #48]\n\t"
  3794. "LDR r11, [%[a], #48]\n\t"
  3795. "UMAAL r11, r3, lr, r12\n\t"
  3796. "STR r11, [%[a], #48]\n\t"
  3797. /* a[i+13] += m[13] * mu */
  3798. "LDR r12, [%[m], #52]\n\t"
  3799. "LDR r11, [%[a], #52]\n\t"
  3800. "UMAAL r11, r3, lr, r12\n\t"
  3801. "STR r11, [%[a], #52]\n\t"
  3802. /* a[i+14] += m[14] * mu */
  3803. "LDR r12, [%[m], #56]\n\t"
  3804. "LDR r11, [%[a], #56]\n\t"
  3805. "UMAAL r11, r3, lr, r12\n\t"
  3806. "STR r11, [%[a], #56]\n\t"
  3807. /* a[i+15] += m[15] * mu */
  3808. "LDR r12, [%[m], #60]\n\t"
  3809. "LDR r11, [%[a], #60]\n\t"
  3810. "UMAAL r11, r3, lr, r12\n\t"
  3811. "STR r11, [%[a], #60]\n\t"
  3812. /* a[i+16] += m[16] * mu */
  3813. "LDR r12, [%[m], #64]\n\t"
  3814. "LDR r11, [%[a], #64]\n\t"
  3815. "UMAAL r11, r3, lr, r12\n\t"
  3816. "STR r11, [%[a], #64]\n\t"
  3817. /* a[i+17] += m[17] * mu */
  3818. "LDR r12, [%[m], #68]\n\t"
  3819. "LDR r11, [%[a], #68]\n\t"
  3820. "UMAAL r11, r3, lr, r12\n\t"
  3821. "STR r11, [%[a], #68]\n\t"
  3822. /* a[i+18] += m[18] * mu */
  3823. "LDR r12, [%[m], #72]\n\t"
  3824. "LDR r11, [%[a], #72]\n\t"
  3825. "UMAAL r11, r3, lr, r12\n\t"
  3826. "STR r11, [%[a], #72]\n\t"
  3827. /* a[i+19] += m[19] * mu */
  3828. "LDR r12, [%[m], #76]\n\t"
  3829. "LDR r11, [%[a], #76]\n\t"
  3830. "UMAAL r11, r3, lr, r12\n\t"
  3831. "STR r11, [%[a], #76]\n\t"
  3832. /* a[i+20] += m[20] * mu */
  3833. "LDR r12, [%[m], #80]\n\t"
  3834. "LDR r11, [%[a], #80]\n\t"
  3835. "UMAAL r11, r3, lr, r12\n\t"
  3836. "STR r11, [%[a], #80]\n\t"
  3837. /* a[i+21] += m[21] * mu */
  3838. "LDR r12, [%[m], #84]\n\t"
  3839. "LDR r11, [%[a], #84]\n\t"
  3840. "UMAAL r11, r3, lr, r12\n\t"
  3841. "STR r11, [%[a], #84]\n\t"
  3842. /* a[i+22] += m[22] * mu */
  3843. "LDR r12, [%[m], #88]\n\t"
  3844. "LDR r11, [%[a], #88]\n\t"
  3845. "UMAAL r11, r3, lr, r12\n\t"
  3846. "STR r11, [%[a], #88]\n\t"
  3847. /* a[i+23] += m[23] * mu */
  3848. "LDR r12, [%[m], #92]\n\t"
  3849. "LDR r11, [%[a], #92]\n\t"
  3850. "UMAAL r11, r3, lr, r12\n\t"
  3851. "STR r11, [%[a], #92]\n\t"
  3852. /* a[i+24] += m[24] * mu */
  3853. "LDR r12, [%[m], #96]\n\t"
  3854. "LDR r11, [%[a], #96]\n\t"
  3855. "UMAAL r11, r3, lr, r12\n\t"
  3856. "STR r11, [%[a], #96]\n\t"
  3857. /* a[i+25] += m[25] * mu */
  3858. "LDR r12, [%[m], #100]\n\t"
  3859. "LDR r11, [%[a], #100]\n\t"
  3860. "UMAAL r11, r3, lr, r12\n\t"
  3861. "STR r11, [%[a], #100]\n\t"
  3862. /* a[i+26] += m[26] * mu */
  3863. "LDR r12, [%[m], #104]\n\t"
  3864. "LDR r11, [%[a], #104]\n\t"
  3865. "UMAAL r11, r3, lr, r12\n\t"
  3866. "STR r11, [%[a], #104]\n\t"
  3867. /* a[i+27] += m[27] * mu */
  3868. "LDR r12, [%[m], #108]\n\t"
  3869. "LDR r11, [%[a], #108]\n\t"
  3870. "UMAAL r11, r3, lr, r12\n\t"
  3871. "STR r11, [%[a], #108]\n\t"
  3872. /* a[i+28] += m[28] * mu */
  3873. "LDR r12, [%[m], #112]\n\t"
  3874. "LDR r11, [%[a], #112]\n\t"
  3875. "UMAAL r11, r3, lr, r12\n\t"
  3876. "STR r11, [%[a], #112]\n\t"
  3877. /* a[i+29] += m[29] * mu */
  3878. "LDR r12, [%[m], #116]\n\t"
  3879. "LDR r11, [%[a], #116]\n\t"
  3880. "UMAAL r11, r3, lr, r12\n\t"
  3881. "STR r11, [%[a], #116]\n\t"
  3882. /* a[i+30] += m[30] * mu */
  3883. "LDR r12, [%[m], #120]\n\t"
  3884. "LDR r11, [%[a], #120]\n\t"
  3885. "UMAAL r11, r3, lr, r12\n\t"
  3886. "STR r11, [%[a], #120]\n\t"
  3887. /* a[i+31] += m[31] * mu */
  3888. "LDR r12, [%[m], #124]\n\t"
  3889. "LDR r11, [%[a], #124]\n\t"
  3890. "UMAAL r11, r3, lr, r12\n\t"
  3891. "LDR lr, [%[a], #128]\n\t"
  3892. "MOV r12, #0x0\n\t"
  3893. "UMAAL r3, lr, r12, r12\n\t"
  3894. "STR r11, [%[a], #124]\n\t"
  3895. "ADDS r3, r3, r5\n\t"
  3896. "ADC r5, lr, #0x0\n\t"
  3897. "STR r3, [%[a], #128]\n\t"
  3898. /* i += 1 */
  3899. "ADD r4, r4, #0x4\n\t"
  3900. "ADD %[a], %[a], #0x4\n\t"
  3901. "CMP r4, #0x80\n\t"
  3902. #ifdef __GNUC__
  3903. "BLT L_sp_2048_mont_reduce_32_word\n\t"
  3904. #else
  3905. "BLT.W L_sp_2048_mont_reduce_32_word\n\t"
  3906. #endif
  3907. /* Loop Done */
  3908. "STR r6, [%[a]]\n\t"
  3909. "STR r7, [%[a], #4]\n\t"
  3910. "STR r8, [%[a], #8]\n\t"
  3911. "STR r9, [%[a], #12]\n\t"
  3912. "STR r10, [%[a], #16]\n\t"
  3913. "MOV %[mp], r5\n\t"
  3914. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  3915. :
  3916. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  3917. );
  3918. sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - mp);
  3919. }
  3920. #else
  3921. /* Reduce the number back to 2048 bits using Montgomery reduction.
  3922. *
  3923. * a A single precision number to reduce in place.
  3924. * m The single precision number representing the modulus.
  3925. * mp The digit representing the negative inverse of m mod 2^n.
  3926. */
  3927. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3928. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  3929. #else
  3930. SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp)
  3931. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3932. {
  3933. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  3934. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  3935. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  3936. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  3937. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  3938. __asm__ __volatile__ (
  3939. "LDR r11, [%[m]]\n\t"
  3940. /* i = 0 */
  3941. "MOV r9, #0x0\n\t"
  3942. /* ca = 0 */
  3943. "MOV r3, #0x0\n\t"
  3944. "\n"
  3945. "L_sp_2048_mont_reduce_32_word:\n\t"
  3946. /* mu = a[i] * mp */
  3947. "LDR r10, [%[a]]\n\t"
  3948. "MUL r8, %[mp], r10\n\t"
  3949. /* j = 0 */
  3950. "MOV r12, #0x0\n\t"
  3951. "MOV r4, #0x0\n\t"
  3952. "\n"
  3953. "L_sp_2048_mont_reduce_32_mul:\n\t"
  3954. /* a[i+j+0] += m[j+0] * mu */
  3955. "LDR r7, [%[m], r12]\n\t"
  3956. "LDR r10, [%[a], r12]\n\t"
  3957. "UMAAL r10, r4, r8, r7\n\t"
  3958. "STR r10, [%[a], r12]\n\t"
  3959. /* j += 1 */
  3960. "ADD r12, r12, #0x4\n\t"
  3961. /* a[i+j+1] += m[j+1] * mu */
  3962. "LDR r7, [%[m], r12]\n\t"
  3963. "LDR r10, [%[a], r12]\n\t"
  3964. "UMAAL r10, r4, r8, r7\n\t"
  3965. "STR r10, [%[a], r12]\n\t"
  3966. /* j += 1 */
  3967. "ADD r12, r12, #0x4\n\t"
  3968. /* a[i+j+2] += m[j+2] * mu */
  3969. "LDR r7, [%[m], r12]\n\t"
  3970. "LDR r10, [%[a], r12]\n\t"
  3971. "UMAAL r10, r4, r8, r7\n\t"
  3972. "STR r10, [%[a], r12]\n\t"
  3973. /* j += 1 */
  3974. "ADD r12, r12, #0x4\n\t"
  3975. /* a[i+j+3] += m[j+3] * mu */
  3976. "LDR r7, [%[m], r12]\n\t"
  3977. "LDR r10, [%[a], r12]\n\t"
  3978. "UMAAL r10, r4, r8, r7\n\t"
  3979. "STR r10, [%[a], r12]\n\t"
  3980. /* j += 1 */
  3981. "ADD r12, r12, #0x4\n\t"
  3982. "CMP r12, #0x80\n\t"
  3983. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  3984. "BLT L_sp_2048_mont_reduce_32_mul\n\t"
  3985. #else
  3986. "BLT.N L_sp_2048_mont_reduce_32_mul\n\t"
  3987. #endif
  3988. "LDR r10, [%[a], #128]\n\t"
  3989. "ADDS r4, r4, r3\n\t"
  3990. "MOV r3, #0x0\n\t"
  3991. "ADC r3, r3, #0x0\n\t"
  3992. "ADDS r10, r10, r4\n\t"
  3993. "ADC r3, r3, r3\n\t"
  3994. "STR r10, [%[a], #128]\n\t"
  3995. /* i += 1 */
  3996. "ADD r9, r9, #0x4\n\t"
  3997. "ADD %[a], %[a], #0x4\n\t"
  3998. "CMP r9, #0x80\n\t"
  3999. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  4000. "BLT L_sp_2048_mont_reduce_32_word\n\t"
  4001. #else
  4002. "BLT.N L_sp_2048_mont_reduce_32_word\n\t"
  4003. #endif
  4004. /* Loop Done */
  4005. "MOV %[mp], r3\n\t"
  4006. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  4007. :
  4008. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  4009. );
  4010. sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - mp);
  4011. }
  4012. #endif /* !WOLFSSL_SP_SMALL */
  4013. #endif
  4014. /* Multiply two Montgomery form numbers mod the modulus (prime).
  4015. * (r = a * b mod m)
  4016. *
  4017. * r Result of multiplication.
  4018. * a First number to multiply in Montgomery form.
  4019. * b Second number to multiply in Montgomery form.
  4020. * m Modulus (prime).
  4021. * mp Montgomery multiplier.
  4022. */
  4023. SP_NOINLINE static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a,
  4024. const sp_digit* b, const sp_digit* m, sp_digit mp)
  4025. {
  4026. sp_2048_mul_32(r, a, b);
  4027. sp_2048_mont_reduce_32(r, m, mp);
  4028. }
  4029. /* Square the Montgomery form number. (r = a * a mod m)
  4030. *
  4031. * r Result of squaring.
  4032. * a Number to square in Montgomery form.
  4033. * m Modulus (prime).
  4034. * mp Montgomery multiplier.
  4035. */
  4036. SP_NOINLINE static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a,
  4037. const sp_digit* m, sp_digit mp)
  4038. {
  4039. sp_2048_sqr_32(r, a);
  4040. sp_2048_mont_reduce_32(r, m, mp);
  4041. }
  4042. #ifdef WOLFSSL_SP_SMALL
  4043. /* Mul a by digit b into r. (r = a * b)
  4044. *
  4045. * r A single precision integer.
  4046. * a A single precision integer.
  4047. * b A single precision digit.
  4048. */
  4049. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4050. static void sp_2048_mul_d_32(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  4051. #else
  4052. static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b)
  4053. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4054. {
  4055. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4056. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  4057. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  4058. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  4059. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4060. __asm__ __volatile__ (
  4061. /* A[0] * B */
  4062. "LDR r8, [%[a]]\n\t"
  4063. "UMULL r5, r3, %[b], r8\n\t"
  4064. "MOV r4, #0x0\n\t"
  4065. "STR r5, [%[r]]\n\t"
  4066. "MOV r5, #0x0\n\t"
  4067. "MOV r9, #0x4\n\t"
  4068. "\n"
  4069. "L_sp_2048_mul_d_32_word:\n\t"
  4070. /* A[i] * B */
  4071. "LDR r8, [%[a], r9]\n\t"
  4072. "UMULL r6, r7, %[b], r8\n\t"
  4073. "ADDS r3, r3, r6\n\t"
  4074. "ADCS r4, r4, r7\n\t"
  4075. "ADC r5, r5, #0x0\n\t"
  4076. "STR r3, [%[r], r9]\n\t"
  4077. "MOV r3, r4\n\t"
  4078. "MOV r4, r5\n\t"
  4079. "MOV r5, #0x0\n\t"
  4080. "ADD r9, r9, #0x4\n\t"
  4081. "CMP r9, #0x80\n\t"
  4082. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  4083. "BLT L_sp_2048_mul_d_32_word\n\t"
  4084. #else
  4085. "BLT.N L_sp_2048_mul_d_32_word\n\t"
  4086. #endif
  4087. "STR r3, [%[r], #128]\n\t"
  4088. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  4089. :
  4090. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  4091. );
  4092. }
  4093. #else
  4094. /* Mul a by digit b into r. (r = a * b)
  4095. *
  4096. * r A single precision integer.
  4097. * a A single precision integer.
  4098. * b A single precision digit.
  4099. */
  4100. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4101. static void sp_2048_mul_d_32(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  4102. #else
  4103. static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b)
  4104. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4105. {
  4106. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4107. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  4108. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  4109. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  4110. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4111. __asm__ __volatile__ (
  4112. /* A[0] * B */
  4113. "LDM %[a]!, {r8}\n\t"
  4114. "UMULL r3, r4, %[b], r8\n\t"
  4115. "STM %[r]!, {r3}\n\t"
  4116. "MOV r5, #0x0\n\t"
  4117. /* A[1] * B */
  4118. "LDM %[a]!, {r8}\n\t"
  4119. "UMLAL r4, r5, %[b], r8\n\t"
  4120. "STM %[r]!, {r4}\n\t"
  4121. "MOV r3, #0x0\n\t"
  4122. /* A[2] * B */
  4123. "LDM %[a]!, {r8}\n\t"
  4124. "UMLAL r5, r3, %[b], r8\n\t"
  4125. "STM %[r]!, {r5}\n\t"
  4126. "MOV r4, #0x0\n\t"
  4127. /* A[3] * B */
  4128. "LDM %[a]!, {r8}\n\t"
  4129. "UMLAL r3, r4, %[b], r8\n\t"
  4130. "STM %[r]!, {r3}\n\t"
  4131. "MOV r5, #0x0\n\t"
  4132. /* A[4] * B */
  4133. "LDM %[a]!, {r8}\n\t"
  4134. "UMLAL r4, r5, %[b], r8\n\t"
  4135. "STM %[r]!, {r4}\n\t"
  4136. "MOV r3, #0x0\n\t"
  4137. /* A[5] * B */
  4138. "LDM %[a]!, {r8}\n\t"
  4139. "UMLAL r5, r3, %[b], r8\n\t"
  4140. "STM %[r]!, {r5}\n\t"
  4141. "MOV r4, #0x0\n\t"
  4142. /* A[6] * B */
  4143. "LDM %[a]!, {r8}\n\t"
  4144. "UMLAL r3, r4, %[b], r8\n\t"
  4145. "STM %[r]!, {r3}\n\t"
  4146. "MOV r5, #0x0\n\t"
  4147. /* A[7] * B */
  4148. "LDM %[a]!, {r8}\n\t"
  4149. "UMLAL r4, r5, %[b], r8\n\t"
  4150. "STM %[r]!, {r4}\n\t"
  4151. "MOV r3, #0x0\n\t"
  4152. /* A[8] * B */
  4153. "LDM %[a]!, {r8}\n\t"
  4154. "UMLAL r5, r3, %[b], r8\n\t"
  4155. "STM %[r]!, {r5}\n\t"
  4156. "MOV r4, #0x0\n\t"
  4157. /* A[9] * B */
  4158. "LDM %[a]!, {r8}\n\t"
  4159. "UMLAL r3, r4, %[b], r8\n\t"
  4160. "STM %[r]!, {r3}\n\t"
  4161. "MOV r5, #0x0\n\t"
  4162. /* A[10] * B */
  4163. "LDM %[a]!, {r8}\n\t"
  4164. "UMLAL r4, r5, %[b], r8\n\t"
  4165. "STM %[r]!, {r4}\n\t"
  4166. "MOV r3, #0x0\n\t"
  4167. /* A[11] * B */
  4168. "LDM %[a]!, {r8}\n\t"
  4169. "UMLAL r5, r3, %[b], r8\n\t"
  4170. "STM %[r]!, {r5}\n\t"
  4171. "MOV r4, #0x0\n\t"
  4172. /* A[12] * B */
  4173. "LDM %[a]!, {r8}\n\t"
  4174. "UMLAL r3, r4, %[b], r8\n\t"
  4175. "STM %[r]!, {r3}\n\t"
  4176. "MOV r5, #0x0\n\t"
  4177. /* A[13] * B */
  4178. "LDM %[a]!, {r8}\n\t"
  4179. "UMLAL r4, r5, %[b], r8\n\t"
  4180. "STM %[r]!, {r4}\n\t"
  4181. "MOV r3, #0x0\n\t"
  4182. /* A[14] * B */
  4183. "LDM %[a]!, {r8}\n\t"
  4184. "UMLAL r5, r3, %[b], r8\n\t"
  4185. "STM %[r]!, {r5}\n\t"
  4186. "MOV r4, #0x0\n\t"
  4187. /* A[15] * B */
  4188. "LDM %[a]!, {r8}\n\t"
  4189. "UMLAL r3, r4, %[b], r8\n\t"
  4190. "STM %[r]!, {r3}\n\t"
  4191. "MOV r5, #0x0\n\t"
  4192. /* A[16] * B */
  4193. "LDM %[a]!, {r8}\n\t"
  4194. "UMLAL r4, r5, %[b], r8\n\t"
  4195. "STM %[r]!, {r4}\n\t"
  4196. "MOV r3, #0x0\n\t"
  4197. /* A[17] * B */
  4198. "LDM %[a]!, {r8}\n\t"
  4199. "UMLAL r5, r3, %[b], r8\n\t"
  4200. "STM %[r]!, {r5}\n\t"
  4201. "MOV r4, #0x0\n\t"
  4202. /* A[18] * B */
  4203. "LDM %[a]!, {r8}\n\t"
  4204. "UMLAL r3, r4, %[b], r8\n\t"
  4205. "STM %[r]!, {r3}\n\t"
  4206. "MOV r5, #0x0\n\t"
  4207. /* A[19] * B */
  4208. "LDM %[a]!, {r8}\n\t"
  4209. "UMLAL r4, r5, %[b], r8\n\t"
  4210. "STM %[r]!, {r4}\n\t"
  4211. "MOV r3, #0x0\n\t"
  4212. /* A[20] * B */
  4213. "LDM %[a]!, {r8}\n\t"
  4214. "UMLAL r5, r3, %[b], r8\n\t"
  4215. "STM %[r]!, {r5}\n\t"
  4216. "MOV r4, #0x0\n\t"
  4217. /* A[21] * B */
  4218. "LDM %[a]!, {r8}\n\t"
  4219. "UMLAL r3, r4, %[b], r8\n\t"
  4220. "STM %[r]!, {r3}\n\t"
  4221. "MOV r5, #0x0\n\t"
  4222. /* A[22] * B */
  4223. "LDM %[a]!, {r8}\n\t"
  4224. "UMLAL r4, r5, %[b], r8\n\t"
  4225. "STM %[r]!, {r4}\n\t"
  4226. "MOV r3, #0x0\n\t"
  4227. /* A[23] * B */
  4228. "LDM %[a]!, {r8}\n\t"
  4229. "UMLAL r5, r3, %[b], r8\n\t"
  4230. "STM %[r]!, {r5}\n\t"
  4231. "MOV r4, #0x0\n\t"
  4232. /* A[24] * B */
  4233. "LDM %[a]!, {r8}\n\t"
  4234. "UMLAL r3, r4, %[b], r8\n\t"
  4235. "STM %[r]!, {r3}\n\t"
  4236. "MOV r5, #0x0\n\t"
  4237. /* A[25] * B */
  4238. "LDM %[a]!, {r8}\n\t"
  4239. "UMLAL r4, r5, %[b], r8\n\t"
  4240. "STM %[r]!, {r4}\n\t"
  4241. "MOV r3, #0x0\n\t"
  4242. /* A[26] * B */
  4243. "LDM %[a]!, {r8}\n\t"
  4244. "UMLAL r5, r3, %[b], r8\n\t"
  4245. "STM %[r]!, {r5}\n\t"
  4246. "MOV r4, #0x0\n\t"
  4247. /* A[27] * B */
  4248. "LDM %[a]!, {r8}\n\t"
  4249. "UMLAL r3, r4, %[b], r8\n\t"
  4250. "STM %[r]!, {r3}\n\t"
  4251. "MOV r5, #0x0\n\t"
  4252. /* A[28] * B */
  4253. "LDM %[a]!, {r8}\n\t"
  4254. "UMLAL r4, r5, %[b], r8\n\t"
  4255. "STM %[r]!, {r4}\n\t"
  4256. "MOV r3, #0x0\n\t"
  4257. /* A[29] * B */
  4258. "LDM %[a]!, {r8}\n\t"
  4259. "UMLAL r5, r3, %[b], r8\n\t"
  4260. "STM %[r]!, {r5}\n\t"
  4261. "MOV r4, #0x0\n\t"
  4262. /* A[30] * B */
  4263. "LDM %[a]!, {r8}\n\t"
  4264. "UMLAL r3, r4, %[b], r8\n\t"
  4265. "STM %[r]!, {r3}\n\t"
  4266. "MOV r5, #0x0\n\t"
  4267. /* A[31] * B */
  4268. "LDM %[a]!, {r8}\n\t"
  4269. "UMLAL r4, r5, %[b], r8\n\t"
  4270. "STM %[r]!, {r4}\n\t"
  4271. "STR r5, [%[r]]\n\t"
  4272. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  4273. :
  4274. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  4275. );
  4276. }
  4277. #endif /* WOLFSSL_SP_SMALL */
  4278. #ifdef WOLFSSL_SP_USE_UDIV
  4279. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  4280. *
  4281. * d1 The high order half of the number to divide.
  4282. * d0 The low order half of the number to divide.
  4283. * div The divisor.
  4284. * returns the result of the division.
  4285. *
  4286. * Note that this is an approximate div. It may give an answer 1 larger.
  4287. */
  4288. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4289. SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  4290. #else
  4291. SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div)
  4292. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4293. {
  4294. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4295. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  4296. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  4297. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  4298. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4299. __asm__ __volatile__ (
  4300. "LSR r8, %[div], #16\n\t"
  4301. "ADD r5, r8, #0x1\n\t"
  4302. "UDIV r6, %[d1], r5\n\t"
  4303. "LSL r7, %[div], #16\n\t"
  4304. "LSL r6, r6, #16\n\t"
  4305. "UMULL r3, r4, %[div], r6\n\t"
  4306. "SUBS %[d0], %[d0], r3\n\t"
  4307. "SBC %[d1], %[d1], r4\n\t"
  4308. "SUBS r3, %[d1], r5\n\t"
  4309. "SBC r9, r9, r9\n\t"
  4310. "ADD r9, r9, #0x1\n\t"
  4311. "RSB r10, r9, #0x0\n\t"
  4312. "LSL r9, r9, #16\n\t"
  4313. "AND r7, r7, r10\n\t"
  4314. "AND r8, r8, r10\n\t"
  4315. "SUBS %[d0], %[d0], r7\n\t"
  4316. "ADD r6, r6, r9\n\t"
  4317. "SBC %[d1], %[d1], r8\n\t"
  4318. "LSL r4, %[d1], #16\n\t"
  4319. "LSR r3, %[d0], #16\n\t"
  4320. "ORR r3, r3, r4\n\t"
  4321. "UDIV r3, r3, r5\n\t"
  4322. "ADD r6, r6, r3\n\t"
  4323. "UMULL r3, r4, %[div], r3\n\t"
  4324. "SUBS %[d0], %[d0], r3\n\t"
  4325. "SBC %[d1], %[d1], r4\n\t"
  4326. "LSL r4, %[d1], #16\n\t"
  4327. "LSR r3, %[d0], #16\n\t"
  4328. "ORR r3, r3, r4\n\t"
  4329. "UDIV r3, r3, r5\n\t"
  4330. "ADD r6, r6, r3\n\t"
  4331. "MUL r3, %[div], r3\n\t"
  4332. "SUB %[d0], %[d0], r3\n\t"
  4333. "UDIV r3, %[d0], %[div]\n\t"
  4334. "ADD %[d1], r6, r3\n\t"
  4335. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  4336. :
  4337. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  4338. );
  4339. return (uint32_t)(size_t)d1;
  4340. }
  4341. #else
  4342. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  4343. *
  4344. * d1 The high order half of the number to divide.
  4345. * d0 The low order half of the number to divide.
  4346. * div The divisor.
  4347. * returns the result of the division.
  4348. *
  4349. * Note that this is an approximate div. It may give an answer 1 larger.
  4350. */
  4351. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4352. SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  4353. #else
  4354. SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div)
  4355. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4356. {
  4357. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4358. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  4359. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  4360. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  4361. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4362. __asm__ __volatile__ (
  4363. "LSR r5, %[div], #1\n\t"
  4364. "ADD r5, r5, #0x1\n\t"
  4365. "MOV r6, %[d0]\n\t"
  4366. "MOV r7, %[d1]\n\t"
  4367. /* Do top 32 */
  4368. "SUBS r8, r5, r7\n\t"
  4369. "SBC r8, r8, r8\n\t"
  4370. "MOV r3, #0x0\n\t"
  4371. "SUB r3, r3, r8\n\t"
  4372. "AND r8, r8, r5\n\t"
  4373. "SUBS r7, r7, r8\n\t"
  4374. /* Next 30 bits */
  4375. "MOV r4, #0x1d\n\t"
  4376. "\n"
  4377. "L_div_2048_word_32_bit:\n\t"
  4378. "LSLS r6, r6, #1\n\t"
  4379. "ADC r7, r7, r7\n\t"
  4380. "SUBS r8, r5, r7\n\t"
  4381. "SBC r8, r8, r8\n\t"
  4382. "ADD r3, r3, r3\n\t"
  4383. "SUB r3, r3, r8\n\t"
  4384. "AND r8, r8, r5\n\t"
  4385. "SUBS r7, r7, r8\n\t"
  4386. "SUBS r4, r4, #0x1\n\t"
  4387. "bpl L_div_2048_word_32_bit\n\t"
  4388. "ADD r3, r3, r3\n\t"
  4389. "ADD r3, r3, #0x1\n\t"
  4390. "UMULL r6, r7, r3, %[div]\n\t"
  4391. "SUBS r9, %[d0], r6\n\t"
  4392. "SBC r10, %[d1], r7\n\t"
  4393. "ADD r3, r3, r10\n\t"
  4394. "UMULL r6, r7, r3, %[div]\n\t"
  4395. "SUBS r9, %[d0], r6\n\t"
  4396. "SBC r10, %[d1], r7\n\t"
  4397. "ADD r3, r3, r10\n\t"
  4398. "UMULL r6, r7, r3, %[div]\n\t"
  4399. "SUBS r9, %[d0], r6\n\t"
  4400. "SBC r10, %[d1], r7\n\t"
  4401. "ADD r3, r3, r10\n\t"
  4402. "SUBS r8, %[div], r9\n\t"
  4403. "SBC r8, r8, r8\n\t"
  4404. "SUB %[d1], r3, r8\n\t"
  4405. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  4406. :
  4407. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  4408. );
  4409. return (uint32_t)(size_t)d1;
  4410. }
  4411. #endif
  4412. /* Compare a with b in constant time.
  4413. *
  4414. * a A single precision integer.
  4415. * b A single precision integer.
  4416. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  4417. * respectively.
  4418. */
  4419. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4420. static sp_int32 sp_2048_cmp_32(const sp_digit* a_p, const sp_digit* b_p)
  4421. #else
  4422. static sp_int32 sp_2048_cmp_32(const sp_digit* a, const sp_digit* b)
  4423. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4424. {
  4425. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  4426. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  4427. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  4428. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  4429. __asm__ __volatile__ (
  4430. "MOV r2, #0xffffffff\n\t"
  4431. "MOV r8, #0x1\n\t"
  4432. "MOV r7, #0x0\n\t"
  4433. "MOV r3, #0xffffffff\n\t"
  4434. #ifdef WOLFSSL_SP_SMALL
  4435. "MOV r6, #0x7c\n\t"
  4436. "\n"
  4437. "L_sp_2048_cmp_32_words:\n\t"
  4438. "LDR r4, [%[a], r6]\n\t"
  4439. "LDR r5, [%[b], r6]\n\t"
  4440. "AND r4, r4, r3\n\t"
  4441. "AND r5, r5, r3\n\t"
  4442. "SUBS r4, r4, r5\n\t"
  4443. "IT hi\n\t"
  4444. "movhi r2, r8\n\t"
  4445. "IT lo\n\t"
  4446. "movlo r2, r3\n\t"
  4447. "IT ne\n\t"
  4448. "movne r3, r7\n\t"
  4449. "SUBS r6, r6, #0x4\n\t"
  4450. "bcs L_sp_2048_cmp_32_words\n\t"
  4451. "EOR r2, r2, r3\n\t"
  4452. #else
  4453. "LDR r4, [%[a], #124]\n\t"
  4454. "LDR r5, [%[b], #124]\n\t"
  4455. "AND r4, r4, r3\n\t"
  4456. "AND r5, r5, r3\n\t"
  4457. "SUBS r4, r4, r5\n\t"
  4458. "IT hi\n\t"
  4459. "movhi r2, r8\n\t"
  4460. "IT lo\n\t"
  4461. "movlo r2, r3\n\t"
  4462. "IT ne\n\t"
  4463. "movne r3, r7\n\t"
  4464. "LDR r4, [%[a], #120]\n\t"
  4465. "LDR r5, [%[b], #120]\n\t"
  4466. "AND r4, r4, r3\n\t"
  4467. "AND r5, r5, r3\n\t"
  4468. "SUBS r4, r4, r5\n\t"
  4469. "IT hi\n\t"
  4470. "movhi r2, r8\n\t"
  4471. "IT lo\n\t"
  4472. "movlo r2, r3\n\t"
  4473. "IT ne\n\t"
  4474. "movne r3, r7\n\t"
  4475. "LDR r4, [%[a], #116]\n\t"
  4476. "LDR r5, [%[b], #116]\n\t"
  4477. "AND r4, r4, r3\n\t"
  4478. "AND r5, r5, r3\n\t"
  4479. "SUBS r4, r4, r5\n\t"
  4480. "IT hi\n\t"
  4481. "movhi r2, r8\n\t"
  4482. "IT lo\n\t"
  4483. "movlo r2, r3\n\t"
  4484. "IT ne\n\t"
  4485. "movne r3, r7\n\t"
  4486. "LDR r4, [%[a], #112]\n\t"
  4487. "LDR r5, [%[b], #112]\n\t"
  4488. "AND r4, r4, r3\n\t"
  4489. "AND r5, r5, r3\n\t"
  4490. "SUBS r4, r4, r5\n\t"
  4491. "IT hi\n\t"
  4492. "movhi r2, r8\n\t"
  4493. "IT lo\n\t"
  4494. "movlo r2, r3\n\t"
  4495. "IT ne\n\t"
  4496. "movne r3, r7\n\t"
  4497. "LDR r4, [%[a], #108]\n\t"
  4498. "LDR r5, [%[b], #108]\n\t"
  4499. "AND r4, r4, r3\n\t"
  4500. "AND r5, r5, r3\n\t"
  4501. "SUBS r4, r4, r5\n\t"
  4502. "IT hi\n\t"
  4503. "movhi r2, r8\n\t"
  4504. "IT lo\n\t"
  4505. "movlo r2, r3\n\t"
  4506. "IT ne\n\t"
  4507. "movne r3, r7\n\t"
  4508. "LDR r4, [%[a], #104]\n\t"
  4509. "LDR r5, [%[b], #104]\n\t"
  4510. "AND r4, r4, r3\n\t"
  4511. "AND r5, r5, r3\n\t"
  4512. "SUBS r4, r4, r5\n\t"
  4513. "IT hi\n\t"
  4514. "movhi r2, r8\n\t"
  4515. "IT lo\n\t"
  4516. "movlo r2, r3\n\t"
  4517. "IT ne\n\t"
  4518. "movne r3, r7\n\t"
  4519. "LDR r4, [%[a], #100]\n\t"
  4520. "LDR r5, [%[b], #100]\n\t"
  4521. "AND r4, r4, r3\n\t"
  4522. "AND r5, r5, r3\n\t"
  4523. "SUBS r4, r4, r5\n\t"
  4524. "IT hi\n\t"
  4525. "movhi r2, r8\n\t"
  4526. "IT lo\n\t"
  4527. "movlo r2, r3\n\t"
  4528. "IT ne\n\t"
  4529. "movne r3, r7\n\t"
  4530. "LDR r4, [%[a], #96]\n\t"
  4531. "LDR r5, [%[b], #96]\n\t"
  4532. "AND r4, r4, r3\n\t"
  4533. "AND r5, r5, r3\n\t"
  4534. "SUBS r4, r4, r5\n\t"
  4535. "IT hi\n\t"
  4536. "movhi r2, r8\n\t"
  4537. "IT lo\n\t"
  4538. "movlo r2, r3\n\t"
  4539. "IT ne\n\t"
  4540. "movne r3, r7\n\t"
  4541. "LDR r4, [%[a], #92]\n\t"
  4542. "LDR r5, [%[b], #92]\n\t"
  4543. "AND r4, r4, r3\n\t"
  4544. "AND r5, r5, r3\n\t"
  4545. "SUBS r4, r4, r5\n\t"
  4546. "IT hi\n\t"
  4547. "movhi r2, r8\n\t"
  4548. "IT lo\n\t"
  4549. "movlo r2, r3\n\t"
  4550. "IT ne\n\t"
  4551. "movne r3, r7\n\t"
  4552. "LDR r4, [%[a], #88]\n\t"
  4553. "LDR r5, [%[b], #88]\n\t"
  4554. "AND r4, r4, r3\n\t"
  4555. "AND r5, r5, r3\n\t"
  4556. "SUBS r4, r4, r5\n\t"
  4557. "IT hi\n\t"
  4558. "movhi r2, r8\n\t"
  4559. "IT lo\n\t"
  4560. "movlo r2, r3\n\t"
  4561. "IT ne\n\t"
  4562. "movne r3, r7\n\t"
  4563. "LDR r4, [%[a], #84]\n\t"
  4564. "LDR r5, [%[b], #84]\n\t"
  4565. "AND r4, r4, r3\n\t"
  4566. "AND r5, r5, r3\n\t"
  4567. "SUBS r4, r4, r5\n\t"
  4568. "IT hi\n\t"
  4569. "movhi r2, r8\n\t"
  4570. "IT lo\n\t"
  4571. "movlo r2, r3\n\t"
  4572. "IT ne\n\t"
  4573. "movne r3, r7\n\t"
  4574. "LDR r4, [%[a], #80]\n\t"
  4575. "LDR r5, [%[b], #80]\n\t"
  4576. "AND r4, r4, r3\n\t"
  4577. "AND r5, r5, r3\n\t"
  4578. "SUBS r4, r4, r5\n\t"
  4579. "IT hi\n\t"
  4580. "movhi r2, r8\n\t"
  4581. "IT lo\n\t"
  4582. "movlo r2, r3\n\t"
  4583. "IT ne\n\t"
  4584. "movne r3, r7\n\t"
  4585. "LDR r4, [%[a], #76]\n\t"
  4586. "LDR r5, [%[b], #76]\n\t"
  4587. "AND r4, r4, r3\n\t"
  4588. "AND r5, r5, r3\n\t"
  4589. "SUBS r4, r4, r5\n\t"
  4590. "IT hi\n\t"
  4591. "movhi r2, r8\n\t"
  4592. "IT lo\n\t"
  4593. "movlo r2, r3\n\t"
  4594. "IT ne\n\t"
  4595. "movne r3, r7\n\t"
  4596. "LDR r4, [%[a], #72]\n\t"
  4597. "LDR r5, [%[b], #72]\n\t"
  4598. "AND r4, r4, r3\n\t"
  4599. "AND r5, r5, r3\n\t"
  4600. "SUBS r4, r4, r5\n\t"
  4601. "IT hi\n\t"
  4602. "movhi r2, r8\n\t"
  4603. "IT lo\n\t"
  4604. "movlo r2, r3\n\t"
  4605. "IT ne\n\t"
  4606. "movne r3, r7\n\t"
  4607. "LDR r4, [%[a], #68]\n\t"
  4608. "LDR r5, [%[b], #68]\n\t"
  4609. "AND r4, r4, r3\n\t"
  4610. "AND r5, r5, r3\n\t"
  4611. "SUBS r4, r4, r5\n\t"
  4612. "IT hi\n\t"
  4613. "movhi r2, r8\n\t"
  4614. "IT lo\n\t"
  4615. "movlo r2, r3\n\t"
  4616. "IT ne\n\t"
  4617. "movne r3, r7\n\t"
  4618. "LDR r4, [%[a], #64]\n\t"
  4619. "LDR r5, [%[b], #64]\n\t"
  4620. "AND r4, r4, r3\n\t"
  4621. "AND r5, r5, r3\n\t"
  4622. "SUBS r4, r4, r5\n\t"
  4623. "IT hi\n\t"
  4624. "movhi r2, r8\n\t"
  4625. "IT lo\n\t"
  4626. "movlo r2, r3\n\t"
  4627. "IT ne\n\t"
  4628. "movne r3, r7\n\t"
  4629. "LDR r4, [%[a], #60]\n\t"
  4630. "LDR r5, [%[b], #60]\n\t"
  4631. "AND r4, r4, r3\n\t"
  4632. "AND r5, r5, r3\n\t"
  4633. "SUBS r4, r4, r5\n\t"
  4634. "IT hi\n\t"
  4635. "movhi r2, r8\n\t"
  4636. "IT lo\n\t"
  4637. "movlo r2, r3\n\t"
  4638. "IT ne\n\t"
  4639. "movne r3, r7\n\t"
  4640. "LDR r4, [%[a], #56]\n\t"
  4641. "LDR r5, [%[b], #56]\n\t"
  4642. "AND r4, r4, r3\n\t"
  4643. "AND r5, r5, r3\n\t"
  4644. "SUBS r4, r4, r5\n\t"
  4645. "IT hi\n\t"
  4646. "movhi r2, r8\n\t"
  4647. "IT lo\n\t"
  4648. "movlo r2, r3\n\t"
  4649. "IT ne\n\t"
  4650. "movne r3, r7\n\t"
  4651. "LDR r4, [%[a], #52]\n\t"
  4652. "LDR r5, [%[b], #52]\n\t"
  4653. "AND r4, r4, r3\n\t"
  4654. "AND r5, r5, r3\n\t"
  4655. "SUBS r4, r4, r5\n\t"
  4656. "IT hi\n\t"
  4657. "movhi r2, r8\n\t"
  4658. "IT lo\n\t"
  4659. "movlo r2, r3\n\t"
  4660. "IT ne\n\t"
  4661. "movne r3, r7\n\t"
  4662. "LDR r4, [%[a], #48]\n\t"
  4663. "LDR r5, [%[b], #48]\n\t"
  4664. "AND r4, r4, r3\n\t"
  4665. "AND r5, r5, r3\n\t"
  4666. "SUBS r4, r4, r5\n\t"
  4667. "IT hi\n\t"
  4668. "movhi r2, r8\n\t"
  4669. "IT lo\n\t"
  4670. "movlo r2, r3\n\t"
  4671. "IT ne\n\t"
  4672. "movne r3, r7\n\t"
  4673. "LDR r4, [%[a], #44]\n\t"
  4674. "LDR r5, [%[b], #44]\n\t"
  4675. "AND r4, r4, r3\n\t"
  4676. "AND r5, r5, r3\n\t"
  4677. "SUBS r4, r4, r5\n\t"
  4678. "IT hi\n\t"
  4679. "movhi r2, r8\n\t"
  4680. "IT lo\n\t"
  4681. "movlo r2, r3\n\t"
  4682. "IT ne\n\t"
  4683. "movne r3, r7\n\t"
  4684. "LDR r4, [%[a], #40]\n\t"
  4685. "LDR r5, [%[b], #40]\n\t"
  4686. "AND r4, r4, r3\n\t"
  4687. "AND r5, r5, r3\n\t"
  4688. "SUBS r4, r4, r5\n\t"
  4689. "IT hi\n\t"
  4690. "movhi r2, r8\n\t"
  4691. "IT lo\n\t"
  4692. "movlo r2, r3\n\t"
  4693. "IT ne\n\t"
  4694. "movne r3, r7\n\t"
  4695. "LDR r4, [%[a], #36]\n\t"
  4696. "LDR r5, [%[b], #36]\n\t"
  4697. "AND r4, r4, r3\n\t"
  4698. "AND r5, r5, r3\n\t"
  4699. "SUBS r4, r4, r5\n\t"
  4700. "IT hi\n\t"
  4701. "movhi r2, r8\n\t"
  4702. "IT lo\n\t"
  4703. "movlo r2, r3\n\t"
  4704. "IT ne\n\t"
  4705. "movne r3, r7\n\t"
  4706. "LDR r4, [%[a], #32]\n\t"
  4707. "LDR r5, [%[b], #32]\n\t"
  4708. "AND r4, r4, r3\n\t"
  4709. "AND r5, r5, r3\n\t"
  4710. "SUBS r4, r4, r5\n\t"
  4711. "IT hi\n\t"
  4712. "movhi r2, r8\n\t"
  4713. "IT lo\n\t"
  4714. "movlo r2, r3\n\t"
  4715. "IT ne\n\t"
  4716. "movne r3, r7\n\t"
  4717. "LDR r4, [%[a], #28]\n\t"
  4718. "LDR r5, [%[b], #28]\n\t"
  4719. "AND r4, r4, r3\n\t"
  4720. "AND r5, r5, r3\n\t"
  4721. "SUBS r4, r4, r5\n\t"
  4722. "IT hi\n\t"
  4723. "movhi r2, r8\n\t"
  4724. "IT lo\n\t"
  4725. "movlo r2, r3\n\t"
  4726. "IT ne\n\t"
  4727. "movne r3, r7\n\t"
  4728. "LDR r4, [%[a], #24]\n\t"
  4729. "LDR r5, [%[b], #24]\n\t"
  4730. "AND r4, r4, r3\n\t"
  4731. "AND r5, r5, r3\n\t"
  4732. "SUBS r4, r4, r5\n\t"
  4733. "IT hi\n\t"
  4734. "movhi r2, r8\n\t"
  4735. "IT lo\n\t"
  4736. "movlo r2, r3\n\t"
  4737. "IT ne\n\t"
  4738. "movne r3, r7\n\t"
  4739. "LDR r4, [%[a], #20]\n\t"
  4740. "LDR r5, [%[b], #20]\n\t"
  4741. "AND r4, r4, r3\n\t"
  4742. "AND r5, r5, r3\n\t"
  4743. "SUBS r4, r4, r5\n\t"
  4744. "IT hi\n\t"
  4745. "movhi r2, r8\n\t"
  4746. "IT lo\n\t"
  4747. "movlo r2, r3\n\t"
  4748. "IT ne\n\t"
  4749. "movne r3, r7\n\t"
  4750. "LDR r4, [%[a], #16]\n\t"
  4751. "LDR r5, [%[b], #16]\n\t"
  4752. "AND r4, r4, r3\n\t"
  4753. "AND r5, r5, r3\n\t"
  4754. "SUBS r4, r4, r5\n\t"
  4755. "IT hi\n\t"
  4756. "movhi r2, r8\n\t"
  4757. "IT lo\n\t"
  4758. "movlo r2, r3\n\t"
  4759. "IT ne\n\t"
  4760. "movne r3, r7\n\t"
  4761. "LDR r4, [%[a], #12]\n\t"
  4762. "LDR r5, [%[b], #12]\n\t"
  4763. "AND r4, r4, r3\n\t"
  4764. "AND r5, r5, r3\n\t"
  4765. "SUBS r4, r4, r5\n\t"
  4766. "IT hi\n\t"
  4767. "movhi r2, r8\n\t"
  4768. "IT lo\n\t"
  4769. "movlo r2, r3\n\t"
  4770. "IT ne\n\t"
  4771. "movne r3, r7\n\t"
  4772. "LDR r4, [%[a], #8]\n\t"
  4773. "LDR r5, [%[b], #8]\n\t"
  4774. "AND r4, r4, r3\n\t"
  4775. "AND r5, r5, r3\n\t"
  4776. "SUBS r4, r4, r5\n\t"
  4777. "IT hi\n\t"
  4778. "movhi r2, r8\n\t"
  4779. "IT lo\n\t"
  4780. "movlo r2, r3\n\t"
  4781. "IT ne\n\t"
  4782. "movne r3, r7\n\t"
  4783. "LDR r4, [%[a], #4]\n\t"
  4784. "LDR r5, [%[b], #4]\n\t"
  4785. "AND r4, r4, r3\n\t"
  4786. "AND r5, r5, r3\n\t"
  4787. "SUBS r4, r4, r5\n\t"
  4788. "IT hi\n\t"
  4789. "movhi r2, r8\n\t"
  4790. "IT lo\n\t"
  4791. "movlo r2, r3\n\t"
  4792. "IT ne\n\t"
  4793. "movne r3, r7\n\t"
  4794. "LDR r4, [%[a]]\n\t"
  4795. "LDR r5, [%[b]]\n\t"
  4796. "AND r4, r4, r3\n\t"
  4797. "AND r5, r5, r3\n\t"
  4798. "SUBS r4, r4, r5\n\t"
  4799. "IT hi\n\t"
  4800. "movhi r2, r8\n\t"
  4801. "IT lo\n\t"
  4802. "movlo r2, r3\n\t"
  4803. "IT ne\n\t"
  4804. "movne r3, r7\n\t"
  4805. "EOR r2, r2, r3\n\t"
  4806. #endif /*WOLFSSL_SP_SMALL */
  4807. "MOV %[a], r2\n\t"
  4808. : [a] "+r" (a), [b] "+r" (b)
  4809. :
  4810. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  4811. );
  4812. return (uint32_t)(size_t)a;
  4813. }
  4814. /* Divide d in a and put remainder into r (m*d + r = a)
  4815. * m is not calculated as it is not needed at this time.
  4816. *
  4817. * a Number to be divided.
  4818. * d Number to divide with.
  4819. * m Multiplier result.
  4820. * r Remainder from the division.
  4821. * returns MP_OKAY indicating success.
  4822. */
  4823. static WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d,
  4824. sp_digit* m, sp_digit* r)
  4825. {
  4826. sp_digit t1[64], t2[33];
  4827. sp_digit div, r1;
  4828. int i;
  4829. (void)m;
  4830. div = d[31];
  4831. XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
  4832. r1 = sp_2048_cmp_32(&t1[32], d) >= 0;
  4833. sp_2048_cond_sub_32(&t1[32], &t1[32], d, (sp_digit)0 - r1);
  4834. for (i = 31; i >= 0; i--) {
  4835. volatile sp_digit mask = (sp_digit)0 - (t1[32 + i] == div);
  4836. sp_digit hi = t1[32 + i] + mask;
  4837. r1 = div_2048_word_32(hi, t1[32 + i - 1], div);
  4838. r1 |= mask;
  4839. sp_2048_mul_d_32(t2, d, r1);
  4840. t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2);
  4841. t1[32 + i] -= t2[32];
  4842. sp_2048_mask_32(t2, d, t1[32 + i]);
  4843. t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
  4844. sp_2048_mask_32(t2, d, t1[32 + i]);
  4845. t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
  4846. }
  4847. r1 = sp_2048_cmp_32(t1, d) >= 0;
  4848. sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1);
  4849. return MP_OKAY;
  4850. }
  4851. /* Reduce a modulo m into r. (r = a mod m)
  4852. *
  4853. * r A single precision number that is the reduced result.
  4854. * a A single precision number that is to be reduced.
  4855. * m A single precision number that is the modulus to reduce with.
  4856. * returns MP_OKAY indicating success.
  4857. */
  4858. static WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
  4859. {
  4860. return sp_2048_div_32(a, m, NULL, r);
  4861. }
  4862. #ifdef WOLFSSL_SP_SMALL
  4863. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  4864. *
  4865. * r A single precision number that is the result of the operation.
  4866. * a A single precision number being exponentiated.
  4867. * e A single precision number that is the exponent.
  4868. * bits The number of bits in the exponent.
  4869. * m A single precision number that is the modulus.
  4870. * returns 0 on success.
  4871. * returns MEMORY_E on dynamic memory allocation failure.
  4872. * returns MP_VAL when base is even or exponent is 0.
  4873. */
  4874. static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
  4875. int bits, const sp_digit* m, int reduceA)
  4876. {
  4877. #ifdef WOLFSSL_SP_SMALL_STACK
  4878. sp_digit* td = NULL;
  4879. #else
  4880. sp_digit td[16 * 64];
  4881. #endif
  4882. sp_digit* t[16];
  4883. sp_digit* norm = NULL;
  4884. sp_digit mp = 1;
  4885. sp_digit n;
  4886. sp_digit mask;
  4887. int i;
  4888. int c;
  4889. byte y;
  4890. int err = MP_OKAY;
  4891. if (bits == 0) {
  4892. err = MP_VAL;
  4893. }
  4894. #ifdef WOLFSSL_SP_SMALL_STACK
  4895. if (err == MP_OKAY) {
  4896. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 64), NULL,
  4897. DYNAMIC_TYPE_TMP_BUFFER);
  4898. if (td == NULL)
  4899. err = MEMORY_E;
  4900. }
  4901. #endif
  4902. if (err == MP_OKAY) {
  4903. norm = td;
  4904. for (i=0; i<16; i++) {
  4905. t[i] = td + i * 64;
  4906. }
  4907. sp_2048_mont_setup(m, &mp);
  4908. sp_2048_mont_norm_32(norm, m);
  4909. XMEMSET(t[1], 0, sizeof(sp_digit) * 32U);
  4910. if (reduceA != 0) {
  4911. err = sp_2048_mod_32(t[1] + 32, a, m);
  4912. if (err == MP_OKAY) {
  4913. err = sp_2048_mod_32(t[1], t[1], m);
  4914. }
  4915. }
  4916. else {
  4917. XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
  4918. err = sp_2048_mod_32(t[1], t[1], m);
  4919. }
  4920. }
  4921. if (err == MP_OKAY) {
  4922. sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
  4923. sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
  4924. sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
  4925. sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
  4926. sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
  4927. sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
  4928. sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
  4929. sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
  4930. sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
  4931. sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
  4932. sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
  4933. sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
  4934. sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
  4935. sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
  4936. i = (bits - 1) / 32;
  4937. n = e[i--];
  4938. c = bits & 31;
  4939. if (c == 0) {
  4940. c = 32;
  4941. }
  4942. c -= bits % 4;
  4943. if (c == 32) {
  4944. c = 28;
  4945. }
  4946. if (c < 0) {
  4947. /* Number of bits in top word is less than number needed. */
  4948. c = -c;
  4949. y = (byte)(n << c);
  4950. n = e[i--];
  4951. y |= (byte)(n >> (64 - c));
  4952. n <<= c;
  4953. c = 64 - c;
  4954. }
  4955. else if (c == 0) {
  4956. /* All bits in top word used. */
  4957. y = (byte)n;
  4958. }
  4959. else {
  4960. y = (byte)(n >> c);
  4961. n <<= 32 - c;
  4962. }
  4963. XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
  4964. for (; i>=0 || c>=4; ) {
  4965. if (c == 0) {
  4966. n = e[i--];
  4967. y = (byte)(n >> 28);
  4968. n <<= 4;
  4969. c = 28;
  4970. }
  4971. else if (c < 4) {
  4972. y = (byte)(n >> 28);
  4973. n = e[i--];
  4974. c = 4 - c;
  4975. y |= (byte)(n >> (32 - c));
  4976. n <<= c;
  4977. c = 32 - c;
  4978. }
  4979. else {
  4980. y = (byte)((n >> 28) & 0xf);
  4981. n <<= 4;
  4982. c -= 4;
  4983. }
  4984. sp_2048_mont_sqr_32(r, r, m, mp);
  4985. sp_2048_mont_sqr_32(r, r, m, mp);
  4986. sp_2048_mont_sqr_32(r, r, m, mp);
  4987. sp_2048_mont_sqr_32(r, r, m, mp);
  4988. sp_2048_mont_mul_32(r, r, t[y], m, mp);
  4989. }
  4990. XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U);
  4991. sp_2048_mont_reduce_32(r, m, mp);
  4992. mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
  4993. sp_2048_cond_sub_32(r, r, m, mask);
  4994. }
  4995. #ifdef WOLFSSL_SP_SMALL_STACK
  4996. if (td != NULL)
  4997. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  4998. #endif
  4999. return err;
  5000. }
  5001. #else
  5002. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  5003. *
  5004. * r A single precision number that is the result of the operation.
  5005. * a A single precision number being exponentiated.
  5006. * e A single precision number that is the exponent.
  5007. * bits The number of bits in the exponent.
  5008. * m A single precision number that is the modulus.
  5009. * returns 0 on success.
  5010. * returns MEMORY_E on dynamic memory allocation failure.
  5011. * returns MP_VAL when base is even or exponent is 0.
  5012. */
  5013. static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e,
  5014. int bits, const sp_digit* m, int reduceA)
  5015. {
  5016. #ifdef WOLFSSL_SP_SMALL_STACK
  5017. sp_digit* td = NULL;
  5018. #else
  5019. sp_digit td[32 * 64];
  5020. #endif
  5021. sp_digit* t[32];
  5022. sp_digit* norm = NULL;
  5023. sp_digit mp = 1;
  5024. sp_digit n;
  5025. sp_digit mask;
  5026. int i;
  5027. int c;
  5028. byte y;
  5029. int err = MP_OKAY;
  5030. if (bits == 0) {
  5031. err = MP_VAL;
  5032. }
  5033. #ifdef WOLFSSL_SP_SMALL_STACK
  5034. if (err == MP_OKAY) {
  5035. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 64), NULL,
  5036. DYNAMIC_TYPE_TMP_BUFFER);
  5037. if (td == NULL)
  5038. err = MEMORY_E;
  5039. }
  5040. #endif
  5041. if (err == MP_OKAY) {
  5042. norm = td;
  5043. for (i=0; i<32; i++) {
  5044. t[i] = td + i * 64;
  5045. }
  5046. sp_2048_mont_setup(m, &mp);
  5047. sp_2048_mont_norm_32(norm, m);
  5048. XMEMSET(t[1], 0, sizeof(sp_digit) * 32U);
  5049. if (reduceA != 0) {
  5050. err = sp_2048_mod_32(t[1] + 32, a, m);
  5051. if (err == MP_OKAY) {
  5052. err = sp_2048_mod_32(t[1], t[1], m);
  5053. }
  5054. }
  5055. else {
  5056. XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
  5057. err = sp_2048_mod_32(t[1], t[1], m);
  5058. }
  5059. }
  5060. if (err == MP_OKAY) {
  5061. sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
  5062. sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
  5063. sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
  5064. sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
  5065. sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
  5066. sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
  5067. sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
  5068. sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
  5069. sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
  5070. sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
  5071. sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
  5072. sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
  5073. sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
  5074. sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
  5075. sp_2048_mont_sqr_32(t[16], t[ 8], m, mp);
  5076. sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp);
  5077. sp_2048_mont_sqr_32(t[18], t[ 9], m, mp);
  5078. sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp);
  5079. sp_2048_mont_sqr_32(t[20], t[10], m, mp);
  5080. sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp);
  5081. sp_2048_mont_sqr_32(t[22], t[11], m, mp);
  5082. sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp);
  5083. sp_2048_mont_sqr_32(t[24], t[12], m, mp);
  5084. sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp);
  5085. sp_2048_mont_sqr_32(t[26], t[13], m, mp);
  5086. sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp);
  5087. sp_2048_mont_sqr_32(t[28], t[14], m, mp);
  5088. sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp);
  5089. sp_2048_mont_sqr_32(t[30], t[15], m, mp);
  5090. sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp);
  5091. i = (bits - 1) / 32;
  5092. n = e[i--];
  5093. c = bits & 31;
  5094. if (c == 0) {
  5095. c = 32;
  5096. }
  5097. c -= bits % 5;
  5098. if (c == 32) {
  5099. c = 27;
  5100. }
  5101. if (c < 0) {
  5102. /* Number of bits in top word is less than number needed. */
  5103. c = -c;
  5104. y = (byte)(n << c);
  5105. n = e[i--];
  5106. y |= (byte)(n >> (64 - c));
  5107. n <<= c;
  5108. c = 64 - c;
  5109. }
  5110. else if (c == 0) {
  5111. /* All bits in top word used. */
  5112. y = (byte)n;
  5113. }
  5114. else {
  5115. y = (byte)(n >> c);
  5116. n <<= 32 - c;
  5117. }
  5118. XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
  5119. for (; i>=0 || c>=5; ) {
  5120. if (c == 0) {
  5121. n = e[i--];
  5122. y = (byte)(n >> 27);
  5123. n <<= 5;
  5124. c = 27;
  5125. }
  5126. else if (c < 5) {
  5127. y = (byte)(n >> 27);
  5128. n = e[i--];
  5129. c = 5 - c;
  5130. y |= (byte)(n >> (32 - c));
  5131. n <<= c;
  5132. c = 32 - c;
  5133. }
  5134. else {
  5135. y = (byte)((n >> 27) & 0x1f);
  5136. n <<= 5;
  5137. c -= 5;
  5138. }
  5139. sp_2048_mont_sqr_32(r, r, m, mp);
  5140. sp_2048_mont_sqr_32(r, r, m, mp);
  5141. sp_2048_mont_sqr_32(r, r, m, mp);
  5142. sp_2048_mont_sqr_32(r, r, m, mp);
  5143. sp_2048_mont_sqr_32(r, r, m, mp);
  5144. sp_2048_mont_mul_32(r, r, t[y], m, mp);
  5145. }
  5146. XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U);
  5147. sp_2048_mont_reduce_32(r, m, mp);
  5148. mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
  5149. sp_2048_cond_sub_32(r, r, m, mask);
  5150. }
  5151. #ifdef WOLFSSL_SP_SMALL_STACK
  5152. if (td != NULL)
  5153. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  5154. #endif
  5155. return err;
  5156. }
  5157. #endif /* WOLFSSL_SP_SMALL */
  5158. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  5159. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  5160. /* r = 2^n mod m where n is the number of bits to reduce by.
  5161. * Given m must be 2048 bits, just need to subtract.
  5162. *
  5163. * r A single precision number.
  5164. * m A single precision number.
  5165. */
  5166. static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m)
  5167. {
  5168. XMEMSET(r, 0, sizeof(sp_digit) * 64);
  5169. /* r = 2^n mod m */
  5170. sp_2048_sub_in_place_64(r, m);
  5171. }
  5172. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  5173. #ifdef WOLFSSL_SP_SMALL
  5174. /* Conditionally subtract b from a using the mask m.
  5175. * m is -1 to subtract and 0 when not copying.
  5176. *
  5177. * r A single precision number representing condition subtract result.
  5178. * a A single precision number to subtract from.
  5179. * b A single precision number to subtract.
  5180. * m Mask value to apply.
  5181. */
  5182. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  5183. static sp_digit sp_2048_cond_sub_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  5184. #else
  5185. static sp_digit sp_2048_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  5186. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  5187. {
  5188. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  5189. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  5190. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  5191. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  5192. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  5193. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  5194. __asm__ __volatile__ (
  5195. "MOV r8, #0x0\n\t"
  5196. "MOV r4, #0x0\n\t"
  5197. "MOV r5, #0x0\n\t"
  5198. "\n"
  5199. "L_sp_2048_cond_sub_64_words:\n\t"
  5200. "SUBS r4, r8, r4\n\t"
  5201. "LDR r6, [%[a], r5]\n\t"
  5202. "LDR r7, [%[b], r5]\n\t"
  5203. "AND r7, r7, %[m]\n\t"
  5204. "SBCS r6, r6, r7\n\t"
  5205. "SBC r4, r8, r8\n\t"
  5206. "STR r6, [%[r], r5]\n\t"
  5207. "ADD r5, r5, #0x4\n\t"
  5208. "CMP r5, #0x100\n\t"
  5209. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  5210. "BLT L_sp_2048_cond_sub_64_words\n\t"
  5211. #else
  5212. "BLT.N L_sp_2048_cond_sub_64_words\n\t"
  5213. #endif
  5214. "MOV %[r], r4\n\t"
  5215. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  5216. :
  5217. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  5218. );
  5219. return (uint32_t)(size_t)r;
  5220. }
  5221. #else
  5222. /* Conditionally subtract b from a using the mask m.
  5223. * m is -1 to subtract and 0 when not copying.
  5224. *
  5225. * r A single precision number representing condition subtract result.
  5226. * a A single precision number to subtract from.
  5227. * b A single precision number to subtract.
  5228. * m Mask value to apply.
  5229. */
  5230. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  5231. static sp_digit sp_2048_cond_sub_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  5232. #else
  5233. static sp_digit sp_2048_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  5234. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  5235. {
  5236. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  5237. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  5238. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  5239. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  5240. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  5241. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  5242. __asm__ __volatile__ (
  5243. "MOV r5, #0x0\n\t"
  5244. "LDM %[a]!, {r6, r7}\n\t"
  5245. "LDM %[b]!, {r8, r9}\n\t"
  5246. "AND r8, r8, %[m]\n\t"
  5247. "AND r9, r9, %[m]\n\t"
  5248. "SUBS r6, r6, r8\n\t"
  5249. "SBCS r7, r7, r9\n\t"
  5250. "STM %[r]!, {r6, r7}\n\t"
  5251. "LDM %[a]!, {r6, r7}\n\t"
  5252. "LDM %[b]!, {r8, r9}\n\t"
  5253. "AND r8, r8, %[m]\n\t"
  5254. "AND r9, r9, %[m]\n\t"
  5255. "SBCS r6, r6, r8\n\t"
  5256. "SBCS r7, r7, r9\n\t"
  5257. "STM %[r]!, {r6, r7}\n\t"
  5258. "LDM %[a]!, {r6, r7}\n\t"
  5259. "LDM %[b]!, {r8, r9}\n\t"
  5260. "AND r8, r8, %[m]\n\t"
  5261. "AND r9, r9, %[m]\n\t"
  5262. "SBCS r6, r6, r8\n\t"
  5263. "SBCS r7, r7, r9\n\t"
  5264. "STM %[r]!, {r6, r7}\n\t"
  5265. "LDM %[a]!, {r6, r7}\n\t"
  5266. "LDM %[b]!, {r8, r9}\n\t"
  5267. "AND r8, r8, %[m]\n\t"
  5268. "AND r9, r9, %[m]\n\t"
  5269. "SBCS r6, r6, r8\n\t"
  5270. "SBCS r7, r7, r9\n\t"
  5271. "STM %[r]!, {r6, r7}\n\t"
  5272. "LDM %[a]!, {r6, r7}\n\t"
  5273. "LDM %[b]!, {r8, r9}\n\t"
  5274. "AND r8, r8, %[m]\n\t"
  5275. "AND r9, r9, %[m]\n\t"
  5276. "SBCS r6, r6, r8\n\t"
  5277. "SBCS r7, r7, r9\n\t"
  5278. "STM %[r]!, {r6, r7}\n\t"
  5279. "LDM %[a]!, {r6, r7}\n\t"
  5280. "LDM %[b]!, {r8, r9}\n\t"
  5281. "AND r8, r8, %[m]\n\t"
  5282. "AND r9, r9, %[m]\n\t"
  5283. "SBCS r6, r6, r8\n\t"
  5284. "SBCS r7, r7, r9\n\t"
  5285. "STM %[r]!, {r6, r7}\n\t"
  5286. "LDM %[a]!, {r6, r7}\n\t"
  5287. "LDM %[b]!, {r8, r9}\n\t"
  5288. "AND r8, r8, %[m]\n\t"
  5289. "AND r9, r9, %[m]\n\t"
  5290. "SBCS r6, r6, r8\n\t"
  5291. "SBCS r7, r7, r9\n\t"
  5292. "STM %[r]!, {r6, r7}\n\t"
  5293. "LDM %[a]!, {r6, r7}\n\t"
  5294. "LDM %[b]!, {r8, r9}\n\t"
  5295. "AND r8, r8, %[m]\n\t"
  5296. "AND r9, r9, %[m]\n\t"
  5297. "SBCS r6, r6, r8\n\t"
  5298. "SBCS r7, r7, r9\n\t"
  5299. "STM %[r]!, {r6, r7}\n\t"
  5300. "LDM %[a]!, {r6, r7}\n\t"
  5301. "LDM %[b]!, {r8, r9}\n\t"
  5302. "AND r8, r8, %[m]\n\t"
  5303. "AND r9, r9, %[m]\n\t"
  5304. "SBCS r6, r6, r8\n\t"
  5305. "SBCS r7, r7, r9\n\t"
  5306. "STM %[r]!, {r6, r7}\n\t"
  5307. "LDM %[a]!, {r6, r7}\n\t"
  5308. "LDM %[b]!, {r8, r9}\n\t"
  5309. "AND r8, r8, %[m]\n\t"
  5310. "AND r9, r9, %[m]\n\t"
  5311. "SBCS r6, r6, r8\n\t"
  5312. "SBCS r7, r7, r9\n\t"
  5313. "STM %[r]!, {r6, r7}\n\t"
  5314. "LDM %[a]!, {r6, r7}\n\t"
  5315. "LDM %[b]!, {r8, r9}\n\t"
  5316. "AND r8, r8, %[m]\n\t"
  5317. "AND r9, r9, %[m]\n\t"
  5318. "SBCS r6, r6, r8\n\t"
  5319. "SBCS r7, r7, r9\n\t"
  5320. "STM %[r]!, {r6, r7}\n\t"
  5321. "LDM %[a]!, {r6, r7}\n\t"
  5322. "LDM %[b]!, {r8, r9}\n\t"
  5323. "AND r8, r8, %[m]\n\t"
  5324. "AND r9, r9, %[m]\n\t"
  5325. "SBCS r6, r6, r8\n\t"
  5326. "SBCS r7, r7, r9\n\t"
  5327. "STM %[r]!, {r6, r7}\n\t"
  5328. "LDM %[a]!, {r6, r7}\n\t"
  5329. "LDM %[b]!, {r8, r9}\n\t"
  5330. "AND r8, r8, %[m]\n\t"
  5331. "AND r9, r9, %[m]\n\t"
  5332. "SBCS r6, r6, r8\n\t"
  5333. "SBCS r7, r7, r9\n\t"
  5334. "STM %[r]!, {r6, r7}\n\t"
  5335. "LDM %[a]!, {r6, r7}\n\t"
  5336. "LDM %[b]!, {r8, r9}\n\t"
  5337. "AND r8, r8, %[m]\n\t"
  5338. "AND r9, r9, %[m]\n\t"
  5339. "SBCS r6, r6, r8\n\t"
  5340. "SBCS r7, r7, r9\n\t"
  5341. "STM %[r]!, {r6, r7}\n\t"
  5342. "LDM %[a]!, {r6, r7}\n\t"
  5343. "LDM %[b]!, {r8, r9}\n\t"
  5344. "AND r8, r8, %[m]\n\t"
  5345. "AND r9, r9, %[m]\n\t"
  5346. "SBCS r6, r6, r8\n\t"
  5347. "SBCS r7, r7, r9\n\t"
  5348. "STM %[r]!, {r6, r7}\n\t"
  5349. "LDM %[a]!, {r6, r7}\n\t"
  5350. "LDM %[b]!, {r8, r9}\n\t"
  5351. "AND r8, r8, %[m]\n\t"
  5352. "AND r9, r9, %[m]\n\t"
  5353. "SBCS r6, r6, r8\n\t"
  5354. "SBCS r7, r7, r9\n\t"
  5355. "STM %[r]!, {r6, r7}\n\t"
  5356. "LDM %[a]!, {r6, r7}\n\t"
  5357. "LDM %[b]!, {r8, r9}\n\t"
  5358. "AND r8, r8, %[m]\n\t"
  5359. "AND r9, r9, %[m]\n\t"
  5360. "SBCS r6, r6, r8\n\t"
  5361. "SBCS r7, r7, r9\n\t"
  5362. "STM %[r]!, {r6, r7}\n\t"
  5363. "LDM %[a]!, {r6, r7}\n\t"
  5364. "LDM %[b]!, {r8, r9}\n\t"
  5365. "AND r8, r8, %[m]\n\t"
  5366. "AND r9, r9, %[m]\n\t"
  5367. "SBCS r6, r6, r8\n\t"
  5368. "SBCS r7, r7, r9\n\t"
  5369. "STM %[r]!, {r6, r7}\n\t"
  5370. "LDM %[a]!, {r6, r7}\n\t"
  5371. "LDM %[b]!, {r8, r9}\n\t"
  5372. "AND r8, r8, %[m]\n\t"
  5373. "AND r9, r9, %[m]\n\t"
  5374. "SBCS r6, r6, r8\n\t"
  5375. "SBCS r7, r7, r9\n\t"
  5376. "STM %[r]!, {r6, r7}\n\t"
  5377. "LDM %[a]!, {r6, r7}\n\t"
  5378. "LDM %[b]!, {r8, r9}\n\t"
  5379. "AND r8, r8, %[m]\n\t"
  5380. "AND r9, r9, %[m]\n\t"
  5381. "SBCS r6, r6, r8\n\t"
  5382. "SBCS r7, r7, r9\n\t"
  5383. "STM %[r]!, {r6, r7}\n\t"
  5384. "LDM %[a]!, {r6, r7}\n\t"
  5385. "LDM %[b]!, {r8, r9}\n\t"
  5386. "AND r8, r8, %[m]\n\t"
  5387. "AND r9, r9, %[m]\n\t"
  5388. "SBCS r6, r6, r8\n\t"
  5389. "SBCS r7, r7, r9\n\t"
  5390. "STM %[r]!, {r6, r7}\n\t"
  5391. "LDM %[a]!, {r6, r7}\n\t"
  5392. "LDM %[b]!, {r8, r9}\n\t"
  5393. "AND r8, r8, %[m]\n\t"
  5394. "AND r9, r9, %[m]\n\t"
  5395. "SBCS r6, r6, r8\n\t"
  5396. "SBCS r7, r7, r9\n\t"
  5397. "STM %[r]!, {r6, r7}\n\t"
  5398. "LDM %[a]!, {r6, r7}\n\t"
  5399. "LDM %[b]!, {r8, r9}\n\t"
  5400. "AND r8, r8, %[m]\n\t"
  5401. "AND r9, r9, %[m]\n\t"
  5402. "SBCS r6, r6, r8\n\t"
  5403. "SBCS r7, r7, r9\n\t"
  5404. "STM %[r]!, {r6, r7}\n\t"
  5405. "LDM %[a]!, {r6, r7}\n\t"
  5406. "LDM %[b]!, {r8, r9}\n\t"
  5407. "AND r8, r8, %[m]\n\t"
  5408. "AND r9, r9, %[m]\n\t"
  5409. "SBCS r6, r6, r8\n\t"
  5410. "SBCS r7, r7, r9\n\t"
  5411. "STM %[r]!, {r6, r7}\n\t"
  5412. "LDM %[a]!, {r6, r7}\n\t"
  5413. "LDM %[b]!, {r8, r9}\n\t"
  5414. "AND r8, r8, %[m]\n\t"
  5415. "AND r9, r9, %[m]\n\t"
  5416. "SBCS r6, r6, r8\n\t"
  5417. "SBCS r7, r7, r9\n\t"
  5418. "STM %[r]!, {r6, r7}\n\t"
  5419. "LDM %[a]!, {r6, r7}\n\t"
  5420. "LDM %[b]!, {r8, r9}\n\t"
  5421. "AND r8, r8, %[m]\n\t"
  5422. "AND r9, r9, %[m]\n\t"
  5423. "SBCS r6, r6, r8\n\t"
  5424. "SBCS r7, r7, r9\n\t"
  5425. "STM %[r]!, {r6, r7}\n\t"
  5426. "LDM %[a]!, {r6, r7}\n\t"
  5427. "LDM %[b]!, {r8, r9}\n\t"
  5428. "AND r8, r8, %[m]\n\t"
  5429. "AND r9, r9, %[m]\n\t"
  5430. "SBCS r6, r6, r8\n\t"
  5431. "SBCS r7, r7, r9\n\t"
  5432. "STM %[r]!, {r6, r7}\n\t"
  5433. "LDM %[a]!, {r6, r7}\n\t"
  5434. "LDM %[b]!, {r8, r9}\n\t"
  5435. "AND r8, r8, %[m]\n\t"
  5436. "AND r9, r9, %[m]\n\t"
  5437. "SBCS r6, r6, r8\n\t"
  5438. "SBCS r7, r7, r9\n\t"
  5439. "STM %[r]!, {r6, r7}\n\t"
  5440. "LDM %[a]!, {r6, r7}\n\t"
  5441. "LDM %[b]!, {r8, r9}\n\t"
  5442. "AND r8, r8, %[m]\n\t"
  5443. "AND r9, r9, %[m]\n\t"
  5444. "SBCS r6, r6, r8\n\t"
  5445. "SBCS r7, r7, r9\n\t"
  5446. "STM %[r]!, {r6, r7}\n\t"
  5447. "LDM %[a]!, {r6, r7}\n\t"
  5448. "LDM %[b]!, {r8, r9}\n\t"
  5449. "AND r8, r8, %[m]\n\t"
  5450. "AND r9, r9, %[m]\n\t"
  5451. "SBCS r6, r6, r8\n\t"
  5452. "SBCS r7, r7, r9\n\t"
  5453. "STM %[r]!, {r6, r7}\n\t"
  5454. "LDM %[a]!, {r6, r7}\n\t"
  5455. "LDM %[b]!, {r8, r9}\n\t"
  5456. "AND r8, r8, %[m]\n\t"
  5457. "AND r9, r9, %[m]\n\t"
  5458. "SBCS r6, r6, r8\n\t"
  5459. "SBCS r7, r7, r9\n\t"
  5460. "STM %[r]!, {r6, r7}\n\t"
  5461. "LDM %[a]!, {r6, r7}\n\t"
  5462. "LDM %[b]!, {r8, r9}\n\t"
  5463. "AND r8, r8, %[m]\n\t"
  5464. "AND r9, r9, %[m]\n\t"
  5465. "SBCS r6, r6, r8\n\t"
  5466. "SBCS r7, r7, r9\n\t"
  5467. "STM %[r]!, {r6, r7}\n\t"
  5468. "SBC %[r], r5, r5\n\t"
  5469. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  5470. :
  5471. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  5472. );
  5473. return (uint32_t)(size_t)r;
  5474. }
  5475. #endif /* WOLFSSL_SP_SMALL */
  5476. #ifdef WOLFSSL_SP_NO_UMAAL
  5477. #ifndef WOLFSSL_SP_SMALL
  5478. /* Reduce the number back to 2048 bits using Montgomery reduction.
  5479. *
  5480. * a A single precision number to reduce in place.
  5481. * m The single precision number representing the modulus.
  5482. * mp The digit representing the negative inverse of m mod 2^n.
  5483. */
  5484. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  5485. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  5486. #else
  5487. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp)
  5488. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  5489. {
  5490. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  5491. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  5492. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  5493. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  5494. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  5495. __asm__ __volatile__ (
  5496. "LDR lr, [%[m]]\n\t"
  5497. /* i = 0 */
  5498. "MOV r11, #0x0\n\t"
  5499. "MOV r3, #0x0\n\t"
  5500. "LDR r4, [%[a]]\n\t"
  5501. "LDR r5, [%[a], #4]\n\t"
  5502. "\n"
  5503. "L_sp_2048_mont_reduce_64_word:\n\t"
  5504. /* mu = a[i] * mp */
  5505. "MUL r10, %[mp], r4\n\t"
  5506. /* a[i+0] += m[0] * mu */
  5507. "MOV r7, #0x0\n\t"
  5508. "UMLAL r4, r7, r10, lr\n\t"
  5509. /* a[i+1] += m[1] * mu */
  5510. "LDR r9, [%[m], #4]\n\t"
  5511. "MOV r6, #0x0\n\t"
  5512. "UMLAL r5, r6, r10, r9\n\t"
  5513. "MOV r4, r5\n\t"
  5514. "ADDS r4, r4, r7\n\t"
  5515. "ADC r6, r6, #0x0\n\t"
  5516. /* a[i+2] += m[2] * mu */
  5517. "LDR r9, [%[m], #8]\n\t"
  5518. "LDR r5, [%[a], #8]\n\t"
  5519. "MOV r7, #0x0\n\t"
  5520. "UMLAL r5, r7, r10, r9\n\t"
  5521. "ADDS r5, r5, r6\n\t"
  5522. "ADC r7, r7, #0x0\n\t"
  5523. /* a[i+3] += m[3] * mu */
  5524. "LDR r9, [%[m], #12]\n\t"
  5525. "LDR r12, [%[a], #12]\n\t"
  5526. "MOV r6, #0x0\n\t"
  5527. "UMLAL r12, r6, r10, r9\n\t"
  5528. "ADDS r12, r12, r7\n\t"
  5529. "STR r12, [%[a], #12]\n\t"
  5530. "ADC r6, r6, #0x0\n\t"
  5531. /* a[i+4] += m[4] * mu */
  5532. "LDR r9, [%[m], #16]\n\t"
  5533. "LDR r12, [%[a], #16]\n\t"
  5534. "MOV r7, #0x0\n\t"
  5535. "UMLAL r12, r7, r10, r9\n\t"
  5536. "ADDS r12, r12, r6\n\t"
  5537. "STR r12, [%[a], #16]\n\t"
  5538. "ADC r7, r7, #0x0\n\t"
  5539. /* a[i+5] += m[5] * mu */
  5540. "LDR r9, [%[m], #20]\n\t"
  5541. "LDR r12, [%[a], #20]\n\t"
  5542. "MOV r6, #0x0\n\t"
  5543. "UMLAL r12, r6, r10, r9\n\t"
  5544. "ADDS r12, r12, r7\n\t"
  5545. "STR r12, [%[a], #20]\n\t"
  5546. "ADC r6, r6, #0x0\n\t"
  5547. /* a[i+6] += m[6] * mu */
  5548. "LDR r9, [%[m], #24]\n\t"
  5549. "LDR r12, [%[a], #24]\n\t"
  5550. "MOV r7, #0x0\n\t"
  5551. "UMLAL r12, r7, r10, r9\n\t"
  5552. "ADDS r12, r12, r6\n\t"
  5553. "STR r12, [%[a], #24]\n\t"
  5554. "ADC r7, r7, #0x0\n\t"
  5555. /* a[i+7] += m[7] * mu */
  5556. "LDR r9, [%[m], #28]\n\t"
  5557. "LDR r12, [%[a], #28]\n\t"
  5558. "MOV r6, #0x0\n\t"
  5559. "UMLAL r12, r6, r10, r9\n\t"
  5560. "ADDS r12, r12, r7\n\t"
  5561. "STR r12, [%[a], #28]\n\t"
  5562. "ADC r6, r6, #0x0\n\t"
  5563. /* a[i+8] += m[8] * mu */
  5564. "LDR r9, [%[m], #32]\n\t"
  5565. "LDR r12, [%[a], #32]\n\t"
  5566. "MOV r7, #0x0\n\t"
  5567. "UMLAL r12, r7, r10, r9\n\t"
  5568. "ADDS r12, r12, r6\n\t"
  5569. "STR r12, [%[a], #32]\n\t"
  5570. "ADC r7, r7, #0x0\n\t"
  5571. /* a[i+9] += m[9] * mu */
  5572. "LDR r9, [%[m], #36]\n\t"
  5573. "LDR r12, [%[a], #36]\n\t"
  5574. "MOV r6, #0x0\n\t"
  5575. "UMLAL r12, r6, r10, r9\n\t"
  5576. "ADDS r12, r12, r7\n\t"
  5577. "STR r12, [%[a], #36]\n\t"
  5578. "ADC r6, r6, #0x0\n\t"
  5579. /* a[i+10] += m[10] * mu */
  5580. "LDR r9, [%[m], #40]\n\t"
  5581. "LDR r12, [%[a], #40]\n\t"
  5582. "MOV r7, #0x0\n\t"
  5583. "UMLAL r12, r7, r10, r9\n\t"
  5584. "ADDS r12, r12, r6\n\t"
  5585. "STR r12, [%[a], #40]\n\t"
  5586. "ADC r7, r7, #0x0\n\t"
  5587. /* a[i+11] += m[11] * mu */
  5588. "LDR r9, [%[m], #44]\n\t"
  5589. "LDR r12, [%[a], #44]\n\t"
  5590. "MOV r6, #0x0\n\t"
  5591. "UMLAL r12, r6, r10, r9\n\t"
  5592. "ADDS r12, r12, r7\n\t"
  5593. "STR r12, [%[a], #44]\n\t"
  5594. "ADC r6, r6, #0x0\n\t"
  5595. /* a[i+12] += m[12] * mu */
  5596. "LDR r9, [%[m], #48]\n\t"
  5597. "LDR r12, [%[a], #48]\n\t"
  5598. "MOV r7, #0x0\n\t"
  5599. "UMLAL r12, r7, r10, r9\n\t"
  5600. "ADDS r12, r12, r6\n\t"
  5601. "STR r12, [%[a], #48]\n\t"
  5602. "ADC r7, r7, #0x0\n\t"
  5603. /* a[i+13] += m[13] * mu */
  5604. "LDR r9, [%[m], #52]\n\t"
  5605. "LDR r12, [%[a], #52]\n\t"
  5606. "MOV r6, #0x0\n\t"
  5607. "UMLAL r12, r6, r10, r9\n\t"
  5608. "ADDS r12, r12, r7\n\t"
  5609. "STR r12, [%[a], #52]\n\t"
  5610. "ADC r6, r6, #0x0\n\t"
  5611. /* a[i+14] += m[14] * mu */
  5612. "LDR r9, [%[m], #56]\n\t"
  5613. "LDR r12, [%[a], #56]\n\t"
  5614. "MOV r7, #0x0\n\t"
  5615. "UMLAL r12, r7, r10, r9\n\t"
  5616. "ADDS r12, r12, r6\n\t"
  5617. "STR r12, [%[a], #56]\n\t"
  5618. "ADC r7, r7, #0x0\n\t"
  5619. /* a[i+15] += m[15] * mu */
  5620. "LDR r9, [%[m], #60]\n\t"
  5621. "LDR r12, [%[a], #60]\n\t"
  5622. "MOV r6, #0x0\n\t"
  5623. "UMLAL r12, r6, r10, r9\n\t"
  5624. "ADDS r12, r12, r7\n\t"
  5625. "STR r12, [%[a], #60]\n\t"
  5626. "ADC r6, r6, #0x0\n\t"
  5627. /* a[i+16] += m[16] * mu */
  5628. "LDR r9, [%[m], #64]\n\t"
  5629. "LDR r12, [%[a], #64]\n\t"
  5630. "MOV r7, #0x0\n\t"
  5631. "UMLAL r12, r7, r10, r9\n\t"
  5632. "ADDS r12, r12, r6\n\t"
  5633. "STR r12, [%[a], #64]\n\t"
  5634. "ADC r7, r7, #0x0\n\t"
  5635. /* a[i+17] += m[17] * mu */
  5636. "LDR r9, [%[m], #68]\n\t"
  5637. "LDR r12, [%[a], #68]\n\t"
  5638. "MOV r6, #0x0\n\t"
  5639. "UMLAL r12, r6, r10, r9\n\t"
  5640. "ADDS r12, r12, r7\n\t"
  5641. "STR r12, [%[a], #68]\n\t"
  5642. "ADC r6, r6, #0x0\n\t"
  5643. /* a[i+18] += m[18] * mu */
  5644. "LDR r9, [%[m], #72]\n\t"
  5645. "LDR r12, [%[a], #72]\n\t"
  5646. "MOV r7, #0x0\n\t"
  5647. "UMLAL r12, r7, r10, r9\n\t"
  5648. "ADDS r12, r12, r6\n\t"
  5649. "STR r12, [%[a], #72]\n\t"
  5650. "ADC r7, r7, #0x0\n\t"
  5651. /* a[i+19] += m[19] * mu */
  5652. "LDR r9, [%[m], #76]\n\t"
  5653. "LDR r12, [%[a], #76]\n\t"
  5654. "MOV r6, #0x0\n\t"
  5655. "UMLAL r12, r6, r10, r9\n\t"
  5656. "ADDS r12, r12, r7\n\t"
  5657. "STR r12, [%[a], #76]\n\t"
  5658. "ADC r6, r6, #0x0\n\t"
  5659. /* a[i+20] += m[20] * mu */
  5660. "LDR r9, [%[m], #80]\n\t"
  5661. "LDR r12, [%[a], #80]\n\t"
  5662. "MOV r7, #0x0\n\t"
  5663. "UMLAL r12, r7, r10, r9\n\t"
  5664. "ADDS r12, r12, r6\n\t"
  5665. "STR r12, [%[a], #80]\n\t"
  5666. "ADC r7, r7, #0x0\n\t"
  5667. /* a[i+21] += m[21] * mu */
  5668. "LDR r9, [%[m], #84]\n\t"
  5669. "LDR r12, [%[a], #84]\n\t"
  5670. "MOV r6, #0x0\n\t"
  5671. "UMLAL r12, r6, r10, r9\n\t"
  5672. "ADDS r12, r12, r7\n\t"
  5673. "STR r12, [%[a], #84]\n\t"
  5674. "ADC r6, r6, #0x0\n\t"
  5675. /* a[i+22] += m[22] * mu */
  5676. "LDR r9, [%[m], #88]\n\t"
  5677. "LDR r12, [%[a], #88]\n\t"
  5678. "MOV r7, #0x0\n\t"
  5679. "UMLAL r12, r7, r10, r9\n\t"
  5680. "ADDS r12, r12, r6\n\t"
  5681. "STR r12, [%[a], #88]\n\t"
  5682. "ADC r7, r7, #0x0\n\t"
  5683. /* a[i+23] += m[23] * mu */
  5684. "LDR r9, [%[m], #92]\n\t"
  5685. "LDR r12, [%[a], #92]\n\t"
  5686. "MOV r6, #0x0\n\t"
  5687. "UMLAL r12, r6, r10, r9\n\t"
  5688. "ADDS r12, r12, r7\n\t"
  5689. "STR r12, [%[a], #92]\n\t"
  5690. "ADC r6, r6, #0x0\n\t"
  5691. /* a[i+24] += m[24] * mu */
  5692. "LDR r9, [%[m], #96]\n\t"
  5693. "LDR r12, [%[a], #96]\n\t"
  5694. "MOV r7, #0x0\n\t"
  5695. "UMLAL r12, r7, r10, r9\n\t"
  5696. "ADDS r12, r12, r6\n\t"
  5697. "STR r12, [%[a], #96]\n\t"
  5698. "ADC r7, r7, #0x0\n\t"
  5699. /* a[i+25] += m[25] * mu */
  5700. "LDR r9, [%[m], #100]\n\t"
  5701. "LDR r12, [%[a], #100]\n\t"
  5702. "MOV r6, #0x0\n\t"
  5703. "UMLAL r12, r6, r10, r9\n\t"
  5704. "ADDS r12, r12, r7\n\t"
  5705. "STR r12, [%[a], #100]\n\t"
  5706. "ADC r6, r6, #0x0\n\t"
  5707. /* a[i+26] += m[26] * mu */
  5708. "LDR r9, [%[m], #104]\n\t"
  5709. "LDR r12, [%[a], #104]\n\t"
  5710. "MOV r7, #0x0\n\t"
  5711. "UMLAL r12, r7, r10, r9\n\t"
  5712. "ADDS r12, r12, r6\n\t"
  5713. "STR r12, [%[a], #104]\n\t"
  5714. "ADC r7, r7, #0x0\n\t"
  5715. /* a[i+27] += m[27] * mu */
  5716. "LDR r9, [%[m], #108]\n\t"
  5717. "LDR r12, [%[a], #108]\n\t"
  5718. "MOV r6, #0x0\n\t"
  5719. "UMLAL r12, r6, r10, r9\n\t"
  5720. "ADDS r12, r12, r7\n\t"
  5721. "STR r12, [%[a], #108]\n\t"
  5722. "ADC r6, r6, #0x0\n\t"
  5723. /* a[i+28] += m[28] * mu */
  5724. "LDR r9, [%[m], #112]\n\t"
  5725. "LDR r12, [%[a], #112]\n\t"
  5726. "MOV r7, #0x0\n\t"
  5727. "UMLAL r12, r7, r10, r9\n\t"
  5728. "ADDS r12, r12, r6\n\t"
  5729. "STR r12, [%[a], #112]\n\t"
  5730. "ADC r7, r7, #0x0\n\t"
  5731. /* a[i+29] += m[29] * mu */
  5732. "LDR r9, [%[m], #116]\n\t"
  5733. "LDR r12, [%[a], #116]\n\t"
  5734. "MOV r6, #0x0\n\t"
  5735. "UMLAL r12, r6, r10, r9\n\t"
  5736. "ADDS r12, r12, r7\n\t"
  5737. "STR r12, [%[a], #116]\n\t"
  5738. "ADC r6, r6, #0x0\n\t"
  5739. /* a[i+30] += m[30] * mu */
  5740. "LDR r9, [%[m], #120]\n\t"
  5741. "LDR r12, [%[a], #120]\n\t"
  5742. "MOV r7, #0x0\n\t"
  5743. "UMLAL r12, r7, r10, r9\n\t"
  5744. "ADDS r12, r12, r6\n\t"
  5745. "STR r12, [%[a], #120]\n\t"
  5746. "ADC r7, r7, #0x0\n\t"
  5747. /* a[i+31] += m[31] * mu */
  5748. "LDR r9, [%[m], #124]\n\t"
  5749. "LDR r12, [%[a], #124]\n\t"
  5750. "MOV r6, #0x0\n\t"
  5751. "UMLAL r12, r6, r10, r9\n\t"
  5752. "ADDS r12, r12, r7\n\t"
  5753. "STR r12, [%[a], #124]\n\t"
  5754. "ADC r6, r6, #0x0\n\t"
  5755. /* a[i+32] += m[32] * mu */
  5756. "LDR r9, [%[m], #128]\n\t"
  5757. "LDR r12, [%[a], #128]\n\t"
  5758. "MOV r7, #0x0\n\t"
  5759. "UMLAL r12, r7, r10, r9\n\t"
  5760. "ADDS r12, r12, r6\n\t"
  5761. "STR r12, [%[a], #128]\n\t"
  5762. "ADC r7, r7, #0x0\n\t"
  5763. /* a[i+33] += m[33] * mu */
  5764. "LDR r9, [%[m], #132]\n\t"
  5765. "LDR r12, [%[a], #132]\n\t"
  5766. "MOV r6, #0x0\n\t"
  5767. "UMLAL r12, r6, r10, r9\n\t"
  5768. "ADDS r12, r12, r7\n\t"
  5769. "STR r12, [%[a], #132]\n\t"
  5770. "ADC r6, r6, #0x0\n\t"
  5771. /* a[i+34] += m[34] * mu */
  5772. "LDR r9, [%[m], #136]\n\t"
  5773. "LDR r12, [%[a], #136]\n\t"
  5774. "MOV r7, #0x0\n\t"
  5775. "UMLAL r12, r7, r10, r9\n\t"
  5776. "ADDS r12, r12, r6\n\t"
  5777. "STR r12, [%[a], #136]\n\t"
  5778. "ADC r7, r7, #0x0\n\t"
  5779. /* a[i+35] += m[35] * mu */
  5780. "LDR r9, [%[m], #140]\n\t"
  5781. "LDR r12, [%[a], #140]\n\t"
  5782. "MOV r6, #0x0\n\t"
  5783. "UMLAL r12, r6, r10, r9\n\t"
  5784. "ADDS r12, r12, r7\n\t"
  5785. "STR r12, [%[a], #140]\n\t"
  5786. "ADC r6, r6, #0x0\n\t"
  5787. /* a[i+36] += m[36] * mu */
  5788. "LDR r9, [%[m], #144]\n\t"
  5789. "LDR r12, [%[a], #144]\n\t"
  5790. "MOV r7, #0x0\n\t"
  5791. "UMLAL r12, r7, r10, r9\n\t"
  5792. "ADDS r12, r12, r6\n\t"
  5793. "STR r12, [%[a], #144]\n\t"
  5794. "ADC r7, r7, #0x0\n\t"
  5795. /* a[i+37] += m[37] * mu */
  5796. "LDR r9, [%[m], #148]\n\t"
  5797. "LDR r12, [%[a], #148]\n\t"
  5798. "MOV r6, #0x0\n\t"
  5799. "UMLAL r12, r6, r10, r9\n\t"
  5800. "ADDS r12, r12, r7\n\t"
  5801. "STR r12, [%[a], #148]\n\t"
  5802. "ADC r6, r6, #0x0\n\t"
  5803. /* a[i+38] += m[38] * mu */
  5804. "LDR r9, [%[m], #152]\n\t"
  5805. "LDR r12, [%[a], #152]\n\t"
  5806. "MOV r7, #0x0\n\t"
  5807. "UMLAL r12, r7, r10, r9\n\t"
  5808. "ADDS r12, r12, r6\n\t"
  5809. "STR r12, [%[a], #152]\n\t"
  5810. "ADC r7, r7, #0x0\n\t"
  5811. /* a[i+39] += m[39] * mu */
  5812. "LDR r9, [%[m], #156]\n\t"
  5813. "LDR r12, [%[a], #156]\n\t"
  5814. "MOV r6, #0x0\n\t"
  5815. "UMLAL r12, r6, r10, r9\n\t"
  5816. "ADDS r12, r12, r7\n\t"
  5817. "STR r12, [%[a], #156]\n\t"
  5818. "ADC r6, r6, #0x0\n\t"
  5819. /* a[i+40] += m[40] * mu */
  5820. "LDR r9, [%[m], #160]\n\t"
  5821. "LDR r12, [%[a], #160]\n\t"
  5822. "MOV r7, #0x0\n\t"
  5823. "UMLAL r12, r7, r10, r9\n\t"
  5824. "ADDS r12, r12, r6\n\t"
  5825. "STR r12, [%[a], #160]\n\t"
  5826. "ADC r7, r7, #0x0\n\t"
  5827. /* a[i+41] += m[41] * mu */
  5828. "LDR r9, [%[m], #164]\n\t"
  5829. "LDR r12, [%[a], #164]\n\t"
  5830. "MOV r6, #0x0\n\t"
  5831. "UMLAL r12, r6, r10, r9\n\t"
  5832. "ADDS r12, r12, r7\n\t"
  5833. "STR r12, [%[a], #164]\n\t"
  5834. "ADC r6, r6, #0x0\n\t"
  5835. /* a[i+42] += m[42] * mu */
  5836. "LDR r9, [%[m], #168]\n\t"
  5837. "LDR r12, [%[a], #168]\n\t"
  5838. "MOV r7, #0x0\n\t"
  5839. "UMLAL r12, r7, r10, r9\n\t"
  5840. "ADDS r12, r12, r6\n\t"
  5841. "STR r12, [%[a], #168]\n\t"
  5842. "ADC r7, r7, #0x0\n\t"
  5843. /* a[i+43] += m[43] * mu */
  5844. "LDR r9, [%[m], #172]\n\t"
  5845. "LDR r12, [%[a], #172]\n\t"
  5846. "MOV r6, #0x0\n\t"
  5847. "UMLAL r12, r6, r10, r9\n\t"
  5848. "ADDS r12, r12, r7\n\t"
  5849. "STR r12, [%[a], #172]\n\t"
  5850. "ADC r6, r6, #0x0\n\t"
  5851. /* a[i+44] += m[44] * mu */
  5852. "LDR r9, [%[m], #176]\n\t"
  5853. "LDR r12, [%[a], #176]\n\t"
  5854. "MOV r7, #0x0\n\t"
  5855. "UMLAL r12, r7, r10, r9\n\t"
  5856. "ADDS r12, r12, r6\n\t"
  5857. "STR r12, [%[a], #176]\n\t"
  5858. "ADC r7, r7, #0x0\n\t"
  5859. /* a[i+45] += m[45] * mu */
  5860. "LDR r9, [%[m], #180]\n\t"
  5861. "LDR r12, [%[a], #180]\n\t"
  5862. "MOV r6, #0x0\n\t"
  5863. "UMLAL r12, r6, r10, r9\n\t"
  5864. "ADDS r12, r12, r7\n\t"
  5865. "STR r12, [%[a], #180]\n\t"
  5866. "ADC r6, r6, #0x0\n\t"
  5867. /* a[i+46] += m[46] * mu */
  5868. "LDR r9, [%[m], #184]\n\t"
  5869. "LDR r12, [%[a], #184]\n\t"
  5870. "MOV r7, #0x0\n\t"
  5871. "UMLAL r12, r7, r10, r9\n\t"
  5872. "ADDS r12, r12, r6\n\t"
  5873. "STR r12, [%[a], #184]\n\t"
  5874. "ADC r7, r7, #0x0\n\t"
  5875. /* a[i+47] += m[47] * mu */
  5876. "LDR r9, [%[m], #188]\n\t"
  5877. "LDR r12, [%[a], #188]\n\t"
  5878. "MOV r6, #0x0\n\t"
  5879. "UMLAL r12, r6, r10, r9\n\t"
  5880. "ADDS r12, r12, r7\n\t"
  5881. "STR r12, [%[a], #188]\n\t"
  5882. "ADC r6, r6, #0x0\n\t"
  5883. /* a[i+48] += m[48] * mu */
  5884. "LDR r9, [%[m], #192]\n\t"
  5885. "LDR r12, [%[a], #192]\n\t"
  5886. "MOV r7, #0x0\n\t"
  5887. "UMLAL r12, r7, r10, r9\n\t"
  5888. "ADDS r12, r12, r6\n\t"
  5889. "STR r12, [%[a], #192]\n\t"
  5890. "ADC r7, r7, #0x0\n\t"
  5891. /* a[i+49] += m[49] * mu */
  5892. "LDR r9, [%[m], #196]\n\t"
  5893. "LDR r12, [%[a], #196]\n\t"
  5894. "MOV r6, #0x0\n\t"
  5895. "UMLAL r12, r6, r10, r9\n\t"
  5896. "ADDS r12, r12, r7\n\t"
  5897. "STR r12, [%[a], #196]\n\t"
  5898. "ADC r6, r6, #0x0\n\t"
  5899. /* a[i+50] += m[50] * mu */
  5900. "LDR r9, [%[m], #200]\n\t"
  5901. "LDR r12, [%[a], #200]\n\t"
  5902. "MOV r7, #0x0\n\t"
  5903. "UMLAL r12, r7, r10, r9\n\t"
  5904. "ADDS r12, r12, r6\n\t"
  5905. "STR r12, [%[a], #200]\n\t"
  5906. "ADC r7, r7, #0x0\n\t"
  5907. /* a[i+51] += m[51] * mu */
  5908. "LDR r9, [%[m], #204]\n\t"
  5909. "LDR r12, [%[a], #204]\n\t"
  5910. "MOV r6, #0x0\n\t"
  5911. "UMLAL r12, r6, r10, r9\n\t"
  5912. "ADDS r12, r12, r7\n\t"
  5913. "STR r12, [%[a], #204]\n\t"
  5914. "ADC r6, r6, #0x0\n\t"
  5915. /* a[i+52] += m[52] * mu */
  5916. "LDR r9, [%[m], #208]\n\t"
  5917. "LDR r12, [%[a], #208]\n\t"
  5918. "MOV r7, #0x0\n\t"
  5919. "UMLAL r12, r7, r10, r9\n\t"
  5920. "ADDS r12, r12, r6\n\t"
  5921. "STR r12, [%[a], #208]\n\t"
  5922. "ADC r7, r7, #0x0\n\t"
  5923. /* a[i+53] += m[53] * mu */
  5924. "LDR r9, [%[m], #212]\n\t"
  5925. "LDR r12, [%[a], #212]\n\t"
  5926. "MOV r6, #0x0\n\t"
  5927. "UMLAL r12, r6, r10, r9\n\t"
  5928. "ADDS r12, r12, r7\n\t"
  5929. "STR r12, [%[a], #212]\n\t"
  5930. "ADC r6, r6, #0x0\n\t"
  5931. /* a[i+54] += m[54] * mu */
  5932. "LDR r9, [%[m], #216]\n\t"
  5933. "LDR r12, [%[a], #216]\n\t"
  5934. "MOV r7, #0x0\n\t"
  5935. "UMLAL r12, r7, r10, r9\n\t"
  5936. "ADDS r12, r12, r6\n\t"
  5937. "STR r12, [%[a], #216]\n\t"
  5938. "ADC r7, r7, #0x0\n\t"
  5939. /* a[i+55] += m[55] * mu */
  5940. "LDR r9, [%[m], #220]\n\t"
  5941. "LDR r12, [%[a], #220]\n\t"
  5942. "MOV r6, #0x0\n\t"
  5943. "UMLAL r12, r6, r10, r9\n\t"
  5944. "ADDS r12, r12, r7\n\t"
  5945. "STR r12, [%[a], #220]\n\t"
  5946. "ADC r6, r6, #0x0\n\t"
  5947. /* a[i+56] += m[56] * mu */
  5948. "LDR r9, [%[m], #224]\n\t"
  5949. "LDR r12, [%[a], #224]\n\t"
  5950. "MOV r7, #0x0\n\t"
  5951. "UMLAL r12, r7, r10, r9\n\t"
  5952. "ADDS r12, r12, r6\n\t"
  5953. "STR r12, [%[a], #224]\n\t"
  5954. "ADC r7, r7, #0x0\n\t"
  5955. /* a[i+57] += m[57] * mu */
  5956. "LDR r9, [%[m], #228]\n\t"
  5957. "LDR r12, [%[a], #228]\n\t"
  5958. "MOV r6, #0x0\n\t"
  5959. "UMLAL r12, r6, r10, r9\n\t"
  5960. "ADDS r12, r12, r7\n\t"
  5961. "STR r12, [%[a], #228]\n\t"
  5962. "ADC r6, r6, #0x0\n\t"
  5963. /* a[i+58] += m[58] * mu */
  5964. "LDR r9, [%[m], #232]\n\t"
  5965. "LDR r12, [%[a], #232]\n\t"
  5966. "MOV r7, #0x0\n\t"
  5967. "UMLAL r12, r7, r10, r9\n\t"
  5968. "ADDS r12, r12, r6\n\t"
  5969. "STR r12, [%[a], #232]\n\t"
  5970. "ADC r7, r7, #0x0\n\t"
  5971. /* a[i+59] += m[59] * mu */
  5972. "LDR r9, [%[m], #236]\n\t"
  5973. "LDR r12, [%[a], #236]\n\t"
  5974. "MOV r6, #0x0\n\t"
  5975. "UMLAL r12, r6, r10, r9\n\t"
  5976. "ADDS r12, r12, r7\n\t"
  5977. "STR r12, [%[a], #236]\n\t"
  5978. "ADC r6, r6, #0x0\n\t"
  5979. /* a[i+60] += m[60] * mu */
  5980. "LDR r9, [%[m], #240]\n\t"
  5981. "LDR r12, [%[a], #240]\n\t"
  5982. "MOV r7, #0x0\n\t"
  5983. "UMLAL r12, r7, r10, r9\n\t"
  5984. "ADDS r12, r12, r6\n\t"
  5985. "STR r12, [%[a], #240]\n\t"
  5986. "ADC r7, r7, #0x0\n\t"
  5987. /* a[i+61] += m[61] * mu */
  5988. "LDR r9, [%[m], #244]\n\t"
  5989. "LDR r12, [%[a], #244]\n\t"
  5990. "MOV r6, #0x0\n\t"
  5991. "UMLAL r12, r6, r10, r9\n\t"
  5992. "ADDS r12, r12, r7\n\t"
  5993. "STR r12, [%[a], #244]\n\t"
  5994. "ADC r6, r6, #0x0\n\t"
  5995. /* a[i+62] += m[62] * mu */
  5996. "LDR r9, [%[m], #248]\n\t"
  5997. "LDR r12, [%[a], #248]\n\t"
  5998. "MOV r7, #0x0\n\t"
  5999. "UMLAL r12, r7, r10, r9\n\t"
  6000. "ADDS r12, r12, r6\n\t"
  6001. "STR r12, [%[a], #248]\n\t"
  6002. "ADC r7, r7, #0x0\n\t"
  6003. /* a[i+63] += m[63] * mu */
  6004. "LDR r9, [%[m], #252]\n\t"
  6005. "LDR r12, [%[a], #252]\n\t"
  6006. "UMULL r8, r9, r10, r9\n\t"
  6007. "ADDS r7, r7, r8\n\t"
  6008. "ADCS r6, r9, r3\n\t"
  6009. "MOV r3, #0x0\n\t"
  6010. "ADC r3, r3, r3\n\t"
  6011. "ADDS r12, r12, r7\n\t"
  6012. "STR r12, [%[a], #252]\n\t"
  6013. "LDR r12, [%[a], #256]\n\t"
  6014. "ADCS r12, r12, r6\n\t"
  6015. "STR r12, [%[a], #256]\n\t"
  6016. "ADC r3, r3, #0x0\n\t"
  6017. /* i += 1 */
  6018. "ADD r11, r11, #0x4\n\t"
  6019. "ADD %[a], %[a], #0x4\n\t"
  6020. "CMP r11, #0x100\n\t"
  6021. #ifdef __GNUC__
  6022. "BLT L_sp_2048_mont_reduce_64_word\n\t"
  6023. #else
  6024. "BLT.W L_sp_2048_mont_reduce_64_word\n\t"
  6025. #endif
  6026. /* Loop Done */
  6027. "STR r4, [%[a]]\n\t"
  6028. "STR r5, [%[a], #4]\n\t"
  6029. "MOV %[mp], r3\n\t"
  6030. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  6031. :
  6032. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  6033. );
  6034. sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - mp);
  6035. }
  6036. #else
  6037. /* Reduce the number back to 2048 bits using Montgomery reduction.
  6038. *
  6039. * a A single precision number to reduce in place.
  6040. * m The single precision number representing the modulus.
  6041. * mp The digit representing the negative inverse of m mod 2^n.
  6042. */
  6043. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6044. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  6045. #else
  6046. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp)
  6047. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6048. {
  6049. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6050. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  6051. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  6052. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  6053. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6054. __asm__ __volatile__ (
  6055. "LDR r11, [%[m]]\n\t"
  6056. /* i = 0 */
  6057. "MOV r9, #0x0\n\t"
  6058. /* ca = 0 */
  6059. "MOV r3, #0x0\n\t"
  6060. "\n"
  6061. "L_sp_2048_mont_reduce_64_word:\n\t"
  6062. /* mu = a[i] * mp */
  6063. "LDR r10, [%[a]]\n\t"
  6064. "MUL r8, %[mp], r10\n\t"
  6065. /* j = 0 */
  6066. "MOV r12, #0x0\n\t"
  6067. "MOV r4, #0x0\n\t"
  6068. "\n"
  6069. "L_sp_2048_mont_reduce_64_mul:\n\t"
  6070. /* a[i+j+0] += m[j+0] * mu */
  6071. "LDR r7, [%[m], r12]\n\t"
  6072. "LDR r10, [%[a], r12]\n\t"
  6073. "MOV r5, #0x0\n\t"
  6074. "UMLAL r10, r5, r8, r7\n\t"
  6075. "ADDS r10, r10, r4\n\t"
  6076. "STR r10, [%[a], r12]\n\t"
  6077. "ADC r4, r5, #0x0\n\t"
  6078. /* j += 1 */
  6079. "ADD r12, r12, #0x4\n\t"
  6080. /* a[i+j+1] += m[j+1] * mu */
  6081. "LDR r7, [%[m], r12]\n\t"
  6082. "LDR r10, [%[a], r12]\n\t"
  6083. "MOV r5, #0x0\n\t"
  6084. "UMLAL r10, r5, r8, r7\n\t"
  6085. "ADDS r10, r10, r4\n\t"
  6086. "STR r10, [%[a], r12]\n\t"
  6087. "ADC r4, r5, #0x0\n\t"
  6088. /* j += 1 */
  6089. "ADD r12, r12, #0x4\n\t"
  6090. /* a[i+j+2] += m[j+2] * mu */
  6091. "LDR r7, [%[m], r12]\n\t"
  6092. "LDR r10, [%[a], r12]\n\t"
  6093. "MOV r5, #0x0\n\t"
  6094. "UMLAL r10, r5, r8, r7\n\t"
  6095. "ADDS r10, r10, r4\n\t"
  6096. "STR r10, [%[a], r12]\n\t"
  6097. "ADC r4, r5, #0x0\n\t"
  6098. /* j += 1 */
  6099. "ADD r12, r12, #0x4\n\t"
  6100. /* a[i+j+3] += m[j+3] * mu */
  6101. "LDR r7, [%[m], r12]\n\t"
  6102. "LDR r10, [%[a], r12]\n\t"
  6103. "MOV r5, #0x0\n\t"
  6104. "UMLAL r10, r5, r8, r7\n\t"
  6105. "ADDS r10, r10, r4\n\t"
  6106. "STR r10, [%[a], r12]\n\t"
  6107. "ADC r4, r5, #0x0\n\t"
  6108. /* j += 1 */
  6109. "ADD r12, r12, #0x4\n\t"
  6110. "CMP r12, #0x100\n\t"
  6111. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  6112. "BLT L_sp_2048_mont_reduce_64_mul\n\t"
  6113. #else
  6114. "BLT.N L_sp_2048_mont_reduce_64_mul\n\t"
  6115. #endif
  6116. "LDR r10, [%[a], #256]\n\t"
  6117. "ADDS r4, r4, r3\n\t"
  6118. "MOV r3, #0x0\n\t"
  6119. "ADC r3, r3, #0x0\n\t"
  6120. "ADDS r10, r10, r4\n\t"
  6121. "ADC r3, r3, r3\n\t"
  6122. "STR r10, [%[a], #256]\n\t"
  6123. /* i += 1 */
  6124. "ADD r9, r9, #0x4\n\t"
  6125. "ADD %[a], %[a], #0x4\n\t"
  6126. "CMP r9, #0x100\n\t"
  6127. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  6128. "BLT L_sp_2048_mont_reduce_64_word\n\t"
  6129. #else
  6130. "BLT.N L_sp_2048_mont_reduce_64_word\n\t"
  6131. #endif
  6132. /* Loop Done */
  6133. "MOV %[mp], r3\n\t"
  6134. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  6135. :
  6136. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  6137. );
  6138. sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - mp);
  6139. }
  6140. #endif /* !WOLFSSL_SP_SMALL */
  6141. #else
  6142. #ifndef WOLFSSL_SP_SMALL
  6143. /* Reduce the number back to 2048 bits using Montgomery reduction.
  6144. *
  6145. * a A single precision number to reduce in place.
  6146. * m The single precision number representing the modulus.
  6147. * mp The digit representing the negative inverse of m mod 2^n.
  6148. */
  6149. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6150. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  6151. #else
  6152. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp)
  6153. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6154. {
  6155. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6156. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  6157. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  6158. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  6159. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6160. __asm__ __volatile__ (
  6161. /* i = 0 */
  6162. "MOV r4, #0x0\n\t"
  6163. "MOV r5, #0x0\n\t"
  6164. "LDR r6, [%[a]]\n\t"
  6165. "LDR r7, [%[a], #4]\n\t"
  6166. "LDR r8, [%[a], #8]\n\t"
  6167. "LDR r9, [%[a], #12]\n\t"
  6168. "LDR r10, [%[a], #16]\n\t"
  6169. "\n"
  6170. "L_sp_2048_mont_reduce_64_word:\n\t"
  6171. /* mu = a[i] * mp */
  6172. "MUL lr, %[mp], r6\n\t"
  6173. /* a[i+0] += m[0] * mu */
  6174. "LDR r12, [%[m]]\n\t"
  6175. "MOV r3, #0x0\n\t"
  6176. "UMAAL r6, r3, lr, r12\n\t"
  6177. /* a[i+1] += m[1] * mu */
  6178. "LDR r12, [%[m], #4]\n\t"
  6179. "MOV r6, r7\n\t"
  6180. "UMAAL r6, r3, lr, r12\n\t"
  6181. /* a[i+2] += m[2] * mu */
  6182. "LDR r12, [%[m], #8]\n\t"
  6183. "MOV r7, r8\n\t"
  6184. "UMAAL r7, r3, lr, r12\n\t"
  6185. /* a[i+3] += m[3] * mu */
  6186. "LDR r12, [%[m], #12]\n\t"
  6187. "MOV r8, r9\n\t"
  6188. "UMAAL r8, r3, lr, r12\n\t"
  6189. /* a[i+4] += m[4] * mu */
  6190. "LDR r12, [%[m], #16]\n\t"
  6191. "MOV r9, r10\n\t"
  6192. "UMAAL r9, r3, lr, r12\n\t"
  6193. /* a[i+5] += m[5] * mu */
  6194. "LDR r12, [%[m], #20]\n\t"
  6195. "LDR r10, [%[a], #20]\n\t"
  6196. "UMAAL r10, r3, lr, r12\n\t"
  6197. /* a[i+6] += m[6] * mu */
  6198. "LDR r12, [%[m], #24]\n\t"
  6199. "LDR r11, [%[a], #24]\n\t"
  6200. "UMAAL r11, r3, lr, r12\n\t"
  6201. "STR r11, [%[a], #24]\n\t"
  6202. /* a[i+7] += m[7] * mu */
  6203. "LDR r12, [%[m], #28]\n\t"
  6204. "LDR r11, [%[a], #28]\n\t"
  6205. "UMAAL r11, r3, lr, r12\n\t"
  6206. "STR r11, [%[a], #28]\n\t"
  6207. /* a[i+8] += m[8] * mu */
  6208. "LDR r12, [%[m], #32]\n\t"
  6209. "LDR r11, [%[a], #32]\n\t"
  6210. "UMAAL r11, r3, lr, r12\n\t"
  6211. "STR r11, [%[a], #32]\n\t"
  6212. /* a[i+9] += m[9] * mu */
  6213. "LDR r12, [%[m], #36]\n\t"
  6214. "LDR r11, [%[a], #36]\n\t"
  6215. "UMAAL r11, r3, lr, r12\n\t"
  6216. "STR r11, [%[a], #36]\n\t"
  6217. /* a[i+10] += m[10] * mu */
  6218. "LDR r12, [%[m], #40]\n\t"
  6219. "LDR r11, [%[a], #40]\n\t"
  6220. "UMAAL r11, r3, lr, r12\n\t"
  6221. "STR r11, [%[a], #40]\n\t"
  6222. /* a[i+11] += m[11] * mu */
  6223. "LDR r12, [%[m], #44]\n\t"
  6224. "LDR r11, [%[a], #44]\n\t"
  6225. "UMAAL r11, r3, lr, r12\n\t"
  6226. "STR r11, [%[a], #44]\n\t"
  6227. /* a[i+12] += m[12] * mu */
  6228. "LDR r12, [%[m], #48]\n\t"
  6229. "LDR r11, [%[a], #48]\n\t"
  6230. "UMAAL r11, r3, lr, r12\n\t"
  6231. "STR r11, [%[a], #48]\n\t"
  6232. /* a[i+13] += m[13] * mu */
  6233. "LDR r12, [%[m], #52]\n\t"
  6234. "LDR r11, [%[a], #52]\n\t"
  6235. "UMAAL r11, r3, lr, r12\n\t"
  6236. "STR r11, [%[a], #52]\n\t"
  6237. /* a[i+14] += m[14] * mu */
  6238. "LDR r12, [%[m], #56]\n\t"
  6239. "LDR r11, [%[a], #56]\n\t"
  6240. "UMAAL r11, r3, lr, r12\n\t"
  6241. "STR r11, [%[a], #56]\n\t"
  6242. /* a[i+15] += m[15] * mu */
  6243. "LDR r12, [%[m], #60]\n\t"
  6244. "LDR r11, [%[a], #60]\n\t"
  6245. "UMAAL r11, r3, lr, r12\n\t"
  6246. "STR r11, [%[a], #60]\n\t"
  6247. /* a[i+16] += m[16] * mu */
  6248. "LDR r12, [%[m], #64]\n\t"
  6249. "LDR r11, [%[a], #64]\n\t"
  6250. "UMAAL r11, r3, lr, r12\n\t"
  6251. "STR r11, [%[a], #64]\n\t"
  6252. /* a[i+17] += m[17] * mu */
  6253. "LDR r12, [%[m], #68]\n\t"
  6254. "LDR r11, [%[a], #68]\n\t"
  6255. "UMAAL r11, r3, lr, r12\n\t"
  6256. "STR r11, [%[a], #68]\n\t"
  6257. /* a[i+18] += m[18] * mu */
  6258. "LDR r12, [%[m], #72]\n\t"
  6259. "LDR r11, [%[a], #72]\n\t"
  6260. "UMAAL r11, r3, lr, r12\n\t"
  6261. "STR r11, [%[a], #72]\n\t"
  6262. /* a[i+19] += m[19] * mu */
  6263. "LDR r12, [%[m], #76]\n\t"
  6264. "LDR r11, [%[a], #76]\n\t"
  6265. "UMAAL r11, r3, lr, r12\n\t"
  6266. "STR r11, [%[a], #76]\n\t"
  6267. /* a[i+20] += m[20] * mu */
  6268. "LDR r12, [%[m], #80]\n\t"
  6269. "LDR r11, [%[a], #80]\n\t"
  6270. "UMAAL r11, r3, lr, r12\n\t"
  6271. "STR r11, [%[a], #80]\n\t"
  6272. /* a[i+21] += m[21] * mu */
  6273. "LDR r12, [%[m], #84]\n\t"
  6274. "LDR r11, [%[a], #84]\n\t"
  6275. "UMAAL r11, r3, lr, r12\n\t"
  6276. "STR r11, [%[a], #84]\n\t"
  6277. /* a[i+22] += m[22] * mu */
  6278. "LDR r12, [%[m], #88]\n\t"
  6279. "LDR r11, [%[a], #88]\n\t"
  6280. "UMAAL r11, r3, lr, r12\n\t"
  6281. "STR r11, [%[a], #88]\n\t"
  6282. /* a[i+23] += m[23] * mu */
  6283. "LDR r12, [%[m], #92]\n\t"
  6284. "LDR r11, [%[a], #92]\n\t"
  6285. "UMAAL r11, r3, lr, r12\n\t"
  6286. "STR r11, [%[a], #92]\n\t"
  6287. /* a[i+24] += m[24] * mu */
  6288. "LDR r12, [%[m], #96]\n\t"
  6289. "LDR r11, [%[a], #96]\n\t"
  6290. "UMAAL r11, r3, lr, r12\n\t"
  6291. "STR r11, [%[a], #96]\n\t"
  6292. /* a[i+25] += m[25] * mu */
  6293. "LDR r12, [%[m], #100]\n\t"
  6294. "LDR r11, [%[a], #100]\n\t"
  6295. "UMAAL r11, r3, lr, r12\n\t"
  6296. "STR r11, [%[a], #100]\n\t"
  6297. /* a[i+26] += m[26] * mu */
  6298. "LDR r12, [%[m], #104]\n\t"
  6299. "LDR r11, [%[a], #104]\n\t"
  6300. "UMAAL r11, r3, lr, r12\n\t"
  6301. "STR r11, [%[a], #104]\n\t"
  6302. /* a[i+27] += m[27] * mu */
  6303. "LDR r12, [%[m], #108]\n\t"
  6304. "LDR r11, [%[a], #108]\n\t"
  6305. "UMAAL r11, r3, lr, r12\n\t"
  6306. "STR r11, [%[a], #108]\n\t"
  6307. /* a[i+28] += m[28] * mu */
  6308. "LDR r12, [%[m], #112]\n\t"
  6309. "LDR r11, [%[a], #112]\n\t"
  6310. "UMAAL r11, r3, lr, r12\n\t"
  6311. "STR r11, [%[a], #112]\n\t"
  6312. /* a[i+29] += m[29] * mu */
  6313. "LDR r12, [%[m], #116]\n\t"
  6314. "LDR r11, [%[a], #116]\n\t"
  6315. "UMAAL r11, r3, lr, r12\n\t"
  6316. "STR r11, [%[a], #116]\n\t"
  6317. /* a[i+30] += m[30] * mu */
  6318. "LDR r12, [%[m], #120]\n\t"
  6319. "LDR r11, [%[a], #120]\n\t"
  6320. "UMAAL r11, r3, lr, r12\n\t"
  6321. "STR r11, [%[a], #120]\n\t"
  6322. /* a[i+31] += m[31] * mu */
  6323. "LDR r12, [%[m], #124]\n\t"
  6324. "LDR r11, [%[a], #124]\n\t"
  6325. "UMAAL r11, r3, lr, r12\n\t"
  6326. "STR r11, [%[a], #124]\n\t"
  6327. /* a[i+32] += m[32] * mu */
  6328. "LDR r12, [%[m], #128]\n\t"
  6329. "LDR r11, [%[a], #128]\n\t"
  6330. "UMAAL r11, r3, lr, r12\n\t"
  6331. "STR r11, [%[a], #128]\n\t"
  6332. /* a[i+33] += m[33] * mu */
  6333. "LDR r12, [%[m], #132]\n\t"
  6334. "LDR r11, [%[a], #132]\n\t"
  6335. "UMAAL r11, r3, lr, r12\n\t"
  6336. "STR r11, [%[a], #132]\n\t"
  6337. /* a[i+34] += m[34] * mu */
  6338. "LDR r12, [%[m], #136]\n\t"
  6339. "LDR r11, [%[a], #136]\n\t"
  6340. "UMAAL r11, r3, lr, r12\n\t"
  6341. "STR r11, [%[a], #136]\n\t"
  6342. /* a[i+35] += m[35] * mu */
  6343. "LDR r12, [%[m], #140]\n\t"
  6344. "LDR r11, [%[a], #140]\n\t"
  6345. "UMAAL r11, r3, lr, r12\n\t"
  6346. "STR r11, [%[a], #140]\n\t"
  6347. /* a[i+36] += m[36] * mu */
  6348. "LDR r12, [%[m], #144]\n\t"
  6349. "LDR r11, [%[a], #144]\n\t"
  6350. "UMAAL r11, r3, lr, r12\n\t"
  6351. "STR r11, [%[a], #144]\n\t"
  6352. /* a[i+37] += m[37] * mu */
  6353. "LDR r12, [%[m], #148]\n\t"
  6354. "LDR r11, [%[a], #148]\n\t"
  6355. "UMAAL r11, r3, lr, r12\n\t"
  6356. "STR r11, [%[a], #148]\n\t"
  6357. /* a[i+38] += m[38] * mu */
  6358. "LDR r12, [%[m], #152]\n\t"
  6359. "LDR r11, [%[a], #152]\n\t"
  6360. "UMAAL r11, r3, lr, r12\n\t"
  6361. "STR r11, [%[a], #152]\n\t"
  6362. /* a[i+39] += m[39] * mu */
  6363. "LDR r12, [%[m], #156]\n\t"
  6364. "LDR r11, [%[a], #156]\n\t"
  6365. "UMAAL r11, r3, lr, r12\n\t"
  6366. "STR r11, [%[a], #156]\n\t"
  6367. /* a[i+40] += m[40] * mu */
  6368. "LDR r12, [%[m], #160]\n\t"
  6369. "LDR r11, [%[a], #160]\n\t"
  6370. "UMAAL r11, r3, lr, r12\n\t"
  6371. "STR r11, [%[a], #160]\n\t"
  6372. /* a[i+41] += m[41] * mu */
  6373. "LDR r12, [%[m], #164]\n\t"
  6374. "LDR r11, [%[a], #164]\n\t"
  6375. "UMAAL r11, r3, lr, r12\n\t"
  6376. "STR r11, [%[a], #164]\n\t"
  6377. /* a[i+42] += m[42] * mu */
  6378. "LDR r12, [%[m], #168]\n\t"
  6379. "LDR r11, [%[a], #168]\n\t"
  6380. "UMAAL r11, r3, lr, r12\n\t"
  6381. "STR r11, [%[a], #168]\n\t"
  6382. /* a[i+43] += m[43] * mu */
  6383. "LDR r12, [%[m], #172]\n\t"
  6384. "LDR r11, [%[a], #172]\n\t"
  6385. "UMAAL r11, r3, lr, r12\n\t"
  6386. "STR r11, [%[a], #172]\n\t"
  6387. /* a[i+44] += m[44] * mu */
  6388. "LDR r12, [%[m], #176]\n\t"
  6389. "LDR r11, [%[a], #176]\n\t"
  6390. "UMAAL r11, r3, lr, r12\n\t"
  6391. "STR r11, [%[a], #176]\n\t"
  6392. /* a[i+45] += m[45] * mu */
  6393. "LDR r12, [%[m], #180]\n\t"
  6394. "LDR r11, [%[a], #180]\n\t"
  6395. "UMAAL r11, r3, lr, r12\n\t"
  6396. "STR r11, [%[a], #180]\n\t"
  6397. /* a[i+46] += m[46] * mu */
  6398. "LDR r12, [%[m], #184]\n\t"
  6399. "LDR r11, [%[a], #184]\n\t"
  6400. "UMAAL r11, r3, lr, r12\n\t"
  6401. "STR r11, [%[a], #184]\n\t"
  6402. /* a[i+47] += m[47] * mu */
  6403. "LDR r12, [%[m], #188]\n\t"
  6404. "LDR r11, [%[a], #188]\n\t"
  6405. "UMAAL r11, r3, lr, r12\n\t"
  6406. "STR r11, [%[a], #188]\n\t"
  6407. /* a[i+48] += m[48] * mu */
  6408. "LDR r12, [%[m], #192]\n\t"
  6409. "LDR r11, [%[a], #192]\n\t"
  6410. "UMAAL r11, r3, lr, r12\n\t"
  6411. "STR r11, [%[a], #192]\n\t"
  6412. /* a[i+49] += m[49] * mu */
  6413. "LDR r12, [%[m], #196]\n\t"
  6414. "LDR r11, [%[a], #196]\n\t"
  6415. "UMAAL r11, r3, lr, r12\n\t"
  6416. "STR r11, [%[a], #196]\n\t"
  6417. /* a[i+50] += m[50] * mu */
  6418. "LDR r12, [%[m], #200]\n\t"
  6419. "LDR r11, [%[a], #200]\n\t"
  6420. "UMAAL r11, r3, lr, r12\n\t"
  6421. "STR r11, [%[a], #200]\n\t"
  6422. /* a[i+51] += m[51] * mu */
  6423. "LDR r12, [%[m], #204]\n\t"
  6424. "LDR r11, [%[a], #204]\n\t"
  6425. "UMAAL r11, r3, lr, r12\n\t"
  6426. "STR r11, [%[a], #204]\n\t"
  6427. /* a[i+52] += m[52] * mu */
  6428. "LDR r12, [%[m], #208]\n\t"
  6429. "LDR r11, [%[a], #208]\n\t"
  6430. "UMAAL r11, r3, lr, r12\n\t"
  6431. "STR r11, [%[a], #208]\n\t"
  6432. /* a[i+53] += m[53] * mu */
  6433. "LDR r12, [%[m], #212]\n\t"
  6434. "LDR r11, [%[a], #212]\n\t"
  6435. "UMAAL r11, r3, lr, r12\n\t"
  6436. "STR r11, [%[a], #212]\n\t"
  6437. /* a[i+54] += m[54] * mu */
  6438. "LDR r12, [%[m], #216]\n\t"
  6439. "LDR r11, [%[a], #216]\n\t"
  6440. "UMAAL r11, r3, lr, r12\n\t"
  6441. "STR r11, [%[a], #216]\n\t"
  6442. /* a[i+55] += m[55] * mu */
  6443. "LDR r12, [%[m], #220]\n\t"
  6444. "LDR r11, [%[a], #220]\n\t"
  6445. "UMAAL r11, r3, lr, r12\n\t"
  6446. "STR r11, [%[a], #220]\n\t"
  6447. /* a[i+56] += m[56] * mu */
  6448. "LDR r12, [%[m], #224]\n\t"
  6449. "LDR r11, [%[a], #224]\n\t"
  6450. "UMAAL r11, r3, lr, r12\n\t"
  6451. "STR r11, [%[a], #224]\n\t"
  6452. /* a[i+57] += m[57] * mu */
  6453. "LDR r12, [%[m], #228]\n\t"
  6454. "LDR r11, [%[a], #228]\n\t"
  6455. "UMAAL r11, r3, lr, r12\n\t"
  6456. "STR r11, [%[a], #228]\n\t"
  6457. /* a[i+58] += m[58] * mu */
  6458. "LDR r12, [%[m], #232]\n\t"
  6459. "LDR r11, [%[a], #232]\n\t"
  6460. "UMAAL r11, r3, lr, r12\n\t"
  6461. "STR r11, [%[a], #232]\n\t"
  6462. /* a[i+59] += m[59] * mu */
  6463. "LDR r12, [%[m], #236]\n\t"
  6464. "LDR r11, [%[a], #236]\n\t"
  6465. "UMAAL r11, r3, lr, r12\n\t"
  6466. "STR r11, [%[a], #236]\n\t"
  6467. /* a[i+60] += m[60] * mu */
  6468. "LDR r12, [%[m], #240]\n\t"
  6469. "LDR r11, [%[a], #240]\n\t"
  6470. "UMAAL r11, r3, lr, r12\n\t"
  6471. "STR r11, [%[a], #240]\n\t"
  6472. /* a[i+61] += m[61] * mu */
  6473. "LDR r12, [%[m], #244]\n\t"
  6474. "LDR r11, [%[a], #244]\n\t"
  6475. "UMAAL r11, r3, lr, r12\n\t"
  6476. "STR r11, [%[a], #244]\n\t"
  6477. /* a[i+62] += m[62] * mu */
  6478. "LDR r12, [%[m], #248]\n\t"
  6479. "LDR r11, [%[a], #248]\n\t"
  6480. "UMAAL r11, r3, lr, r12\n\t"
  6481. "STR r11, [%[a], #248]\n\t"
  6482. /* a[i+63] += m[63] * mu */
  6483. "LDR r12, [%[m], #252]\n\t"
  6484. "LDR r11, [%[a], #252]\n\t"
  6485. "UMAAL r11, r3, lr, r12\n\t"
  6486. "LDR lr, [%[a], #256]\n\t"
  6487. "MOV r12, #0x0\n\t"
  6488. "UMAAL r3, lr, r12, r12\n\t"
  6489. "STR r11, [%[a], #252]\n\t"
  6490. "ADDS r3, r3, r5\n\t"
  6491. "ADC r5, lr, #0x0\n\t"
  6492. "STR r3, [%[a], #256]\n\t"
  6493. /* i += 1 */
  6494. "ADD r4, r4, #0x4\n\t"
  6495. "ADD %[a], %[a], #0x4\n\t"
  6496. "CMP r4, #0x100\n\t"
  6497. #ifdef __GNUC__
  6498. "BLT L_sp_2048_mont_reduce_64_word\n\t"
  6499. #else
  6500. "BLT.W L_sp_2048_mont_reduce_64_word\n\t"
  6501. #endif
  6502. /* Loop Done */
  6503. "STR r6, [%[a]]\n\t"
  6504. "STR r7, [%[a], #4]\n\t"
  6505. "STR r8, [%[a], #8]\n\t"
  6506. "STR r9, [%[a], #12]\n\t"
  6507. "STR r10, [%[a], #16]\n\t"
  6508. "MOV %[mp], r5\n\t"
  6509. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  6510. :
  6511. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  6512. );
  6513. sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - mp);
  6514. }
  6515. #else
  6516. /* Reduce the number back to 2048 bits using Montgomery reduction.
  6517. *
  6518. * a A single precision number to reduce in place.
  6519. * m The single precision number representing the modulus.
  6520. * mp The digit representing the negative inverse of m mod 2^n.
  6521. */
  6522. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6523. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  6524. #else
  6525. SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp)
  6526. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6527. {
  6528. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6529. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  6530. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  6531. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  6532. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6533. __asm__ __volatile__ (
  6534. "LDR r11, [%[m]]\n\t"
  6535. /* i = 0 */
  6536. "MOV r9, #0x0\n\t"
  6537. /* ca = 0 */
  6538. "MOV r3, #0x0\n\t"
  6539. "\n"
  6540. "L_sp_2048_mont_reduce_64_word:\n\t"
  6541. /* mu = a[i] * mp */
  6542. "LDR r10, [%[a]]\n\t"
  6543. "MUL r8, %[mp], r10\n\t"
  6544. /* j = 0 */
  6545. "MOV r12, #0x0\n\t"
  6546. "MOV r4, #0x0\n\t"
  6547. "\n"
  6548. "L_sp_2048_mont_reduce_64_mul:\n\t"
  6549. /* a[i+j+0] += m[j+0] * mu */
  6550. "LDR r7, [%[m], r12]\n\t"
  6551. "LDR r10, [%[a], r12]\n\t"
  6552. "UMAAL r10, r4, r8, r7\n\t"
  6553. "STR r10, [%[a], r12]\n\t"
  6554. /* j += 1 */
  6555. "ADD r12, r12, #0x4\n\t"
  6556. /* a[i+j+1] += m[j+1] * mu */
  6557. "LDR r7, [%[m], r12]\n\t"
  6558. "LDR r10, [%[a], r12]\n\t"
  6559. "UMAAL r10, r4, r8, r7\n\t"
  6560. "STR r10, [%[a], r12]\n\t"
  6561. /* j += 1 */
  6562. "ADD r12, r12, #0x4\n\t"
  6563. /* a[i+j+2] += m[j+2] * mu */
  6564. "LDR r7, [%[m], r12]\n\t"
  6565. "LDR r10, [%[a], r12]\n\t"
  6566. "UMAAL r10, r4, r8, r7\n\t"
  6567. "STR r10, [%[a], r12]\n\t"
  6568. /* j += 1 */
  6569. "ADD r12, r12, #0x4\n\t"
  6570. /* a[i+j+3] += m[j+3] * mu */
  6571. "LDR r7, [%[m], r12]\n\t"
  6572. "LDR r10, [%[a], r12]\n\t"
  6573. "UMAAL r10, r4, r8, r7\n\t"
  6574. "STR r10, [%[a], r12]\n\t"
  6575. /* j += 1 */
  6576. "ADD r12, r12, #0x4\n\t"
  6577. "CMP r12, #0x100\n\t"
  6578. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  6579. "BLT L_sp_2048_mont_reduce_64_mul\n\t"
  6580. #else
  6581. "BLT.N L_sp_2048_mont_reduce_64_mul\n\t"
  6582. #endif
  6583. "LDR r10, [%[a], #256]\n\t"
  6584. "ADDS r4, r4, r3\n\t"
  6585. "MOV r3, #0x0\n\t"
  6586. "ADC r3, r3, #0x0\n\t"
  6587. "ADDS r10, r10, r4\n\t"
  6588. "ADC r3, r3, r3\n\t"
  6589. "STR r10, [%[a], #256]\n\t"
  6590. /* i += 1 */
  6591. "ADD r9, r9, #0x4\n\t"
  6592. "ADD %[a], %[a], #0x4\n\t"
  6593. "CMP r9, #0x100\n\t"
  6594. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  6595. "BLT L_sp_2048_mont_reduce_64_word\n\t"
  6596. #else
  6597. "BLT.N L_sp_2048_mont_reduce_64_word\n\t"
  6598. #endif
  6599. /* Loop Done */
  6600. "MOV %[mp], r3\n\t"
  6601. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  6602. :
  6603. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  6604. );
  6605. sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - mp);
  6606. }
  6607. #endif /* !WOLFSSL_SP_SMALL */
  6608. #endif
  6609. /* Multiply two Montgomery form numbers mod the modulus (prime).
  6610. * (r = a * b mod m)
  6611. *
  6612. * r Result of multiplication.
  6613. * a First number to multiply in Montgomery form.
  6614. * b Second number to multiply in Montgomery form.
  6615. * m Modulus (prime).
  6616. * mp Montgomery multiplier.
  6617. */
  6618. SP_NOINLINE static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a,
  6619. const sp_digit* b, const sp_digit* m, sp_digit mp)
  6620. {
  6621. sp_2048_mul_64(r, a, b);
  6622. sp_2048_mont_reduce_64(r, m, mp);
  6623. }
  6624. /* Square the Montgomery form number. (r = a * a mod m)
  6625. *
  6626. * r Result of squaring.
  6627. * a Number to square in Montgomery form.
  6628. * m Modulus (prime).
  6629. * mp Montgomery multiplier.
  6630. */
  6631. SP_NOINLINE static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a,
  6632. const sp_digit* m, sp_digit mp)
  6633. {
  6634. sp_2048_sqr_64(r, a);
  6635. sp_2048_mont_reduce_64(r, m, mp);
  6636. }
  6637. #ifdef WOLFSSL_SP_SMALL
  6638. /* Sub b from a into r. (r = a - b)
  6639. *
  6640. * r A single precision integer.
  6641. * a A single precision integer.
  6642. * b A single precision integer.
  6643. */
  6644. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6645. static sp_digit sp_2048_sub_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  6646. #else
  6647. static sp_digit sp_2048_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b)
  6648. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6649. {
  6650. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6651. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  6652. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  6653. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  6654. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6655. __asm__ __volatile__ (
  6656. "MOV r11, #0x0\n\t"
  6657. "ADD r12, %[a], #0x100\n\t"
  6658. "\n"
  6659. "L_sp_2048_sub_64_word:\n\t"
  6660. "RSBS r11, r11, #0x0\n\t"
  6661. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6662. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6663. "SBCS r3, r3, r7\n\t"
  6664. "SBCS r4, r4, r8\n\t"
  6665. "SBCS r5, r5, r9\n\t"
  6666. "SBCS r6, r6, r10\n\t"
  6667. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6668. "SBC r11, r3, r3\n\t"
  6669. "CMP %[a], r12\n\t"
  6670. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  6671. "BNE L_sp_2048_sub_64_word\n\t"
  6672. #else
  6673. "BNE.N L_sp_2048_sub_64_word\n\t"
  6674. #endif
  6675. "MOV %[r], r11\n\t"
  6676. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  6677. :
  6678. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  6679. );
  6680. return (uint32_t)(size_t)r;
  6681. }
  6682. #else
  6683. /* Sub b from a into r. (r = a - b)
  6684. *
  6685. * r A single precision integer.
  6686. * a A single precision integer.
  6687. * b A single precision integer.
  6688. */
  6689. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6690. static sp_digit sp_2048_sub_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  6691. #else
  6692. static sp_digit sp_2048_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b)
  6693. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6694. {
  6695. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6696. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  6697. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  6698. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  6699. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6700. __asm__ __volatile__ (
  6701. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6702. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6703. "SUBS r3, r3, r7\n\t"
  6704. "SBCS r4, r4, r8\n\t"
  6705. "SBCS r5, r5, r9\n\t"
  6706. "SBCS r6, r6, r10\n\t"
  6707. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6708. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6709. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6710. "SBCS r3, r3, r7\n\t"
  6711. "SBCS r4, r4, r8\n\t"
  6712. "SBCS r5, r5, r9\n\t"
  6713. "SBCS r6, r6, r10\n\t"
  6714. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6715. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6716. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6717. "SBCS r3, r3, r7\n\t"
  6718. "SBCS r4, r4, r8\n\t"
  6719. "SBCS r5, r5, r9\n\t"
  6720. "SBCS r6, r6, r10\n\t"
  6721. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6722. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6723. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6724. "SBCS r3, r3, r7\n\t"
  6725. "SBCS r4, r4, r8\n\t"
  6726. "SBCS r5, r5, r9\n\t"
  6727. "SBCS r6, r6, r10\n\t"
  6728. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6729. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6730. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6731. "SBCS r3, r3, r7\n\t"
  6732. "SBCS r4, r4, r8\n\t"
  6733. "SBCS r5, r5, r9\n\t"
  6734. "SBCS r6, r6, r10\n\t"
  6735. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6736. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6737. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6738. "SBCS r3, r3, r7\n\t"
  6739. "SBCS r4, r4, r8\n\t"
  6740. "SBCS r5, r5, r9\n\t"
  6741. "SBCS r6, r6, r10\n\t"
  6742. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6743. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6744. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6745. "SBCS r3, r3, r7\n\t"
  6746. "SBCS r4, r4, r8\n\t"
  6747. "SBCS r5, r5, r9\n\t"
  6748. "SBCS r6, r6, r10\n\t"
  6749. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6750. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6751. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6752. "SBCS r3, r3, r7\n\t"
  6753. "SBCS r4, r4, r8\n\t"
  6754. "SBCS r5, r5, r9\n\t"
  6755. "SBCS r6, r6, r10\n\t"
  6756. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6757. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6758. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6759. "SBCS r3, r3, r7\n\t"
  6760. "SBCS r4, r4, r8\n\t"
  6761. "SBCS r5, r5, r9\n\t"
  6762. "SBCS r6, r6, r10\n\t"
  6763. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6764. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6765. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6766. "SBCS r3, r3, r7\n\t"
  6767. "SBCS r4, r4, r8\n\t"
  6768. "SBCS r5, r5, r9\n\t"
  6769. "SBCS r6, r6, r10\n\t"
  6770. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6771. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6772. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6773. "SBCS r3, r3, r7\n\t"
  6774. "SBCS r4, r4, r8\n\t"
  6775. "SBCS r5, r5, r9\n\t"
  6776. "SBCS r6, r6, r10\n\t"
  6777. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6778. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6779. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6780. "SBCS r3, r3, r7\n\t"
  6781. "SBCS r4, r4, r8\n\t"
  6782. "SBCS r5, r5, r9\n\t"
  6783. "SBCS r6, r6, r10\n\t"
  6784. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6785. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6786. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6787. "SBCS r3, r3, r7\n\t"
  6788. "SBCS r4, r4, r8\n\t"
  6789. "SBCS r5, r5, r9\n\t"
  6790. "SBCS r6, r6, r10\n\t"
  6791. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6792. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6793. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6794. "SBCS r3, r3, r7\n\t"
  6795. "SBCS r4, r4, r8\n\t"
  6796. "SBCS r5, r5, r9\n\t"
  6797. "SBCS r6, r6, r10\n\t"
  6798. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6799. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6800. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6801. "SBCS r3, r3, r7\n\t"
  6802. "SBCS r4, r4, r8\n\t"
  6803. "SBCS r5, r5, r9\n\t"
  6804. "SBCS r6, r6, r10\n\t"
  6805. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6806. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  6807. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  6808. "SBCS r3, r3, r7\n\t"
  6809. "SBCS r4, r4, r8\n\t"
  6810. "SBCS r5, r5, r9\n\t"
  6811. "SBCS r6, r6, r10\n\t"
  6812. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  6813. "SBC %[r], r6, r6\n\t"
  6814. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  6815. :
  6816. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  6817. );
  6818. return (uint32_t)(size_t)r;
  6819. }
  6820. #endif /* WOLFSSL_SP_SMALL */
  6821. #ifdef WOLFSSL_SP_USE_UDIV
  6822. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  6823. *
  6824. * d1 The high order half of the number to divide.
  6825. * d0 The low order half of the number to divide.
  6826. * div The divisor.
  6827. * returns the result of the division.
  6828. *
  6829. * Note that this is an approximate div. It may give an answer 1 larger.
  6830. */
  6831. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6832. SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  6833. #else
  6834. SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, sp_digit div)
  6835. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6836. {
  6837. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6838. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  6839. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  6840. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  6841. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6842. __asm__ __volatile__ (
  6843. "LSR r8, %[div], #16\n\t"
  6844. "ADD r5, r8, #0x1\n\t"
  6845. "UDIV r6, %[d1], r5\n\t"
  6846. "LSL r7, %[div], #16\n\t"
  6847. "LSL r6, r6, #16\n\t"
  6848. "UMULL r3, r4, %[div], r6\n\t"
  6849. "SUBS %[d0], %[d0], r3\n\t"
  6850. "SBC %[d1], %[d1], r4\n\t"
  6851. "SUBS r3, %[d1], r5\n\t"
  6852. "SBC r9, r9, r9\n\t"
  6853. "ADD r9, r9, #0x1\n\t"
  6854. "RSB r10, r9, #0x0\n\t"
  6855. "LSL r9, r9, #16\n\t"
  6856. "AND r7, r7, r10\n\t"
  6857. "AND r8, r8, r10\n\t"
  6858. "SUBS %[d0], %[d0], r7\n\t"
  6859. "ADD r6, r6, r9\n\t"
  6860. "SBC %[d1], %[d1], r8\n\t"
  6861. "LSL r4, %[d1], #16\n\t"
  6862. "LSR r3, %[d0], #16\n\t"
  6863. "ORR r3, r3, r4\n\t"
  6864. "UDIV r3, r3, r5\n\t"
  6865. "ADD r6, r6, r3\n\t"
  6866. "UMULL r3, r4, %[div], r3\n\t"
  6867. "SUBS %[d0], %[d0], r3\n\t"
  6868. "SBC %[d1], %[d1], r4\n\t"
  6869. "LSL r4, %[d1], #16\n\t"
  6870. "LSR r3, %[d0], #16\n\t"
  6871. "ORR r3, r3, r4\n\t"
  6872. "UDIV r3, r3, r5\n\t"
  6873. "ADD r6, r6, r3\n\t"
  6874. "MUL r3, %[div], r3\n\t"
  6875. "SUB %[d0], %[d0], r3\n\t"
  6876. "UDIV r3, %[d0], %[div]\n\t"
  6877. "ADD %[d1], r6, r3\n\t"
  6878. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  6879. :
  6880. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  6881. );
  6882. return (uint32_t)(size_t)d1;
  6883. }
  6884. #else
  6885. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  6886. *
  6887. * d1 The high order half of the number to divide.
  6888. * d0 The low order half of the number to divide.
  6889. * div The divisor.
  6890. * returns the result of the division.
  6891. *
  6892. * Note that this is an approximate div. It may give an answer 1 larger.
  6893. */
  6894. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6895. SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  6896. #else
  6897. SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, sp_digit div)
  6898. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6899. {
  6900. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  6901. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  6902. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  6903. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  6904. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  6905. __asm__ __volatile__ (
  6906. "LSR r5, %[div], #1\n\t"
  6907. "ADD r5, r5, #0x1\n\t"
  6908. "MOV r6, %[d0]\n\t"
  6909. "MOV r7, %[d1]\n\t"
  6910. /* Do top 32 */
  6911. "SUBS r8, r5, r7\n\t"
  6912. "SBC r8, r8, r8\n\t"
  6913. "MOV r3, #0x0\n\t"
  6914. "SUB r3, r3, r8\n\t"
  6915. "AND r8, r8, r5\n\t"
  6916. "SUBS r7, r7, r8\n\t"
  6917. /* Next 30 bits */
  6918. "MOV r4, #0x1d\n\t"
  6919. "\n"
  6920. "L_div_2048_word_64_bit:\n\t"
  6921. "LSLS r6, r6, #1\n\t"
  6922. "ADC r7, r7, r7\n\t"
  6923. "SUBS r8, r5, r7\n\t"
  6924. "SBC r8, r8, r8\n\t"
  6925. "ADD r3, r3, r3\n\t"
  6926. "SUB r3, r3, r8\n\t"
  6927. "AND r8, r8, r5\n\t"
  6928. "SUBS r7, r7, r8\n\t"
  6929. "SUBS r4, r4, #0x1\n\t"
  6930. "bpl L_div_2048_word_64_bit\n\t"
  6931. "ADD r3, r3, r3\n\t"
  6932. "ADD r3, r3, #0x1\n\t"
  6933. "UMULL r6, r7, r3, %[div]\n\t"
  6934. "SUBS r9, %[d0], r6\n\t"
  6935. "SBC r10, %[d1], r7\n\t"
  6936. "ADD r3, r3, r10\n\t"
  6937. "UMULL r6, r7, r3, %[div]\n\t"
  6938. "SUBS r9, %[d0], r6\n\t"
  6939. "SBC r10, %[d1], r7\n\t"
  6940. "ADD r3, r3, r10\n\t"
  6941. "UMULL r6, r7, r3, %[div]\n\t"
  6942. "SUBS r9, %[d0], r6\n\t"
  6943. "SBC r10, %[d1], r7\n\t"
  6944. "ADD r3, r3, r10\n\t"
  6945. "SUBS r8, %[div], r9\n\t"
  6946. "SBC r8, r8, r8\n\t"
  6947. "SUB %[d1], r3, r8\n\t"
  6948. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  6949. :
  6950. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  6951. );
  6952. return (uint32_t)(size_t)d1;
  6953. }
  6954. #endif
  6955. /* Divide d in a and put remainder into r (m*d + r = a)
  6956. * m is not calculated as it is not needed at this time.
  6957. *
  6958. * a Number to be divided.
  6959. * d Number to divide with.
  6960. * m Multiplier result.
  6961. * r Remainder from the division.
  6962. * returns MP_OKAY indicating success.
  6963. */
  6964. static WC_INLINE int sp_2048_div_64_cond(const sp_digit* a, const sp_digit* d,
  6965. sp_digit* m, sp_digit* r)
  6966. {
  6967. sp_digit t1[128], t2[65];
  6968. sp_digit div, r1;
  6969. int i;
  6970. (void)m;
  6971. div = d[63];
  6972. XMEMCPY(t1, a, sizeof(*t1) * 2 * 64);
  6973. for (i = 63; i > 0; i--) {
  6974. if (t1[i + 64] != d[i])
  6975. break;
  6976. }
  6977. if (t1[i + 64] >= d[i]) {
  6978. sp_2048_sub_in_place_64(&t1[64], d);
  6979. }
  6980. for (i = 63; i >= 0; i--) {
  6981. if (t1[64 + i] == div) {
  6982. r1 = SP_DIGIT_MAX;
  6983. }
  6984. else {
  6985. r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div);
  6986. }
  6987. sp_2048_mul_d_64(t2, d, r1);
  6988. t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2);
  6989. t1[64 + i] -= t2[64];
  6990. if (t1[64 + i] != 0) {
  6991. t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d);
  6992. if (t1[64 + i] != 0)
  6993. t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d);
  6994. }
  6995. }
  6996. for (i = 63; i > 0; i--) {
  6997. if (t1[i] != d[i])
  6998. break;
  6999. }
  7000. if (t1[i] >= d[i]) {
  7001. sp_2048_sub_64(r, t1, d);
  7002. }
  7003. else {
  7004. XMEMCPY(r, t1, sizeof(*t1) * 64);
  7005. }
  7006. return MP_OKAY;
  7007. }
  7008. /* Reduce a modulo m into r. (r = a mod m)
  7009. *
  7010. * r A single precision number that is the reduced result.
  7011. * a A single precision number that is to be reduced.
  7012. * m A single precision number that is the modulus to reduce with.
  7013. * returns MP_OKAY indicating success.
  7014. */
  7015. static WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
  7016. {
  7017. return sp_2048_div_64_cond(a, m, NULL, r);
  7018. }
  7019. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  7020. #if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)
  7021. /* AND m into each word of a and store in r.
  7022. *
  7023. * r A single precision integer.
  7024. * a A single precision integer.
  7025. * m Mask to AND against each digit.
  7026. */
  7027. static void sp_2048_mask_64(sp_digit* r, const sp_digit* a, sp_digit m)
  7028. {
  7029. #ifdef WOLFSSL_SP_SMALL
  7030. int i;
  7031. for (i=0; i<64; i++) {
  7032. r[i] = a[i] & m;
  7033. }
  7034. #else
  7035. int i;
  7036. for (i = 0; i < 64; i += 8) {
  7037. r[i+0] = a[i+0] & m;
  7038. r[i+1] = a[i+1] & m;
  7039. r[i+2] = a[i+2] & m;
  7040. r[i+3] = a[i+3] & m;
  7041. r[i+4] = a[i+4] & m;
  7042. r[i+5] = a[i+5] & m;
  7043. r[i+6] = a[i+6] & m;
  7044. r[i+7] = a[i+7] & m;
  7045. }
  7046. #endif
  7047. }
  7048. /* Compare a with b in constant time.
  7049. *
  7050. * a A single precision integer.
  7051. * b A single precision integer.
  7052. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  7053. * respectively.
  7054. */
  7055. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  7056. static sp_int32 sp_2048_cmp_64(const sp_digit* a_p, const sp_digit* b_p)
  7057. #else
  7058. static sp_int32 sp_2048_cmp_64(const sp_digit* a, const sp_digit* b)
  7059. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  7060. {
  7061. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  7062. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  7063. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  7064. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  7065. __asm__ __volatile__ (
  7066. "MOV r2, #0xffffffff\n\t"
  7067. "MOV r8, #0x1\n\t"
  7068. "MOV r7, #0x0\n\t"
  7069. "MOV r3, #0xffffffff\n\t"
  7070. #ifdef WOLFSSL_SP_SMALL
  7071. "MOV r6, #0xfc\n\t"
  7072. "\n"
  7073. "L_sp_2048_cmp_64_words:\n\t"
  7074. "LDR r4, [%[a], r6]\n\t"
  7075. "LDR r5, [%[b], r6]\n\t"
  7076. "AND r4, r4, r3\n\t"
  7077. "AND r5, r5, r3\n\t"
  7078. "SUBS r4, r4, r5\n\t"
  7079. "IT hi\n\t"
  7080. "movhi r2, r8\n\t"
  7081. "IT lo\n\t"
  7082. "movlo r2, r3\n\t"
  7083. "IT ne\n\t"
  7084. "movne r3, r7\n\t"
  7085. "SUBS r6, r6, #0x4\n\t"
  7086. "bcs L_sp_2048_cmp_64_words\n\t"
  7087. "EOR r2, r2, r3\n\t"
  7088. #else
  7089. "LDR r4, [%[a], #252]\n\t"
  7090. "LDR r5, [%[b], #252]\n\t"
  7091. "AND r4, r4, r3\n\t"
  7092. "AND r5, r5, r3\n\t"
  7093. "SUBS r4, r4, r5\n\t"
  7094. "IT hi\n\t"
  7095. "movhi r2, r8\n\t"
  7096. "IT lo\n\t"
  7097. "movlo r2, r3\n\t"
  7098. "IT ne\n\t"
  7099. "movne r3, r7\n\t"
  7100. "LDR r4, [%[a], #248]\n\t"
  7101. "LDR r5, [%[b], #248]\n\t"
  7102. "AND r4, r4, r3\n\t"
  7103. "AND r5, r5, r3\n\t"
  7104. "SUBS r4, r4, r5\n\t"
  7105. "IT hi\n\t"
  7106. "movhi r2, r8\n\t"
  7107. "IT lo\n\t"
  7108. "movlo r2, r3\n\t"
  7109. "IT ne\n\t"
  7110. "movne r3, r7\n\t"
  7111. "LDR r4, [%[a], #244]\n\t"
  7112. "LDR r5, [%[b], #244]\n\t"
  7113. "AND r4, r4, r3\n\t"
  7114. "AND r5, r5, r3\n\t"
  7115. "SUBS r4, r4, r5\n\t"
  7116. "IT hi\n\t"
  7117. "movhi r2, r8\n\t"
  7118. "IT lo\n\t"
  7119. "movlo r2, r3\n\t"
  7120. "IT ne\n\t"
  7121. "movne r3, r7\n\t"
  7122. "LDR r4, [%[a], #240]\n\t"
  7123. "LDR r5, [%[b], #240]\n\t"
  7124. "AND r4, r4, r3\n\t"
  7125. "AND r5, r5, r3\n\t"
  7126. "SUBS r4, r4, r5\n\t"
  7127. "IT hi\n\t"
  7128. "movhi r2, r8\n\t"
  7129. "IT lo\n\t"
  7130. "movlo r2, r3\n\t"
  7131. "IT ne\n\t"
  7132. "movne r3, r7\n\t"
  7133. "LDR r4, [%[a], #236]\n\t"
  7134. "LDR r5, [%[b], #236]\n\t"
  7135. "AND r4, r4, r3\n\t"
  7136. "AND r5, r5, r3\n\t"
  7137. "SUBS r4, r4, r5\n\t"
  7138. "IT hi\n\t"
  7139. "movhi r2, r8\n\t"
  7140. "IT lo\n\t"
  7141. "movlo r2, r3\n\t"
  7142. "IT ne\n\t"
  7143. "movne r3, r7\n\t"
  7144. "LDR r4, [%[a], #232]\n\t"
  7145. "LDR r5, [%[b], #232]\n\t"
  7146. "AND r4, r4, r3\n\t"
  7147. "AND r5, r5, r3\n\t"
  7148. "SUBS r4, r4, r5\n\t"
  7149. "IT hi\n\t"
  7150. "movhi r2, r8\n\t"
  7151. "IT lo\n\t"
  7152. "movlo r2, r3\n\t"
  7153. "IT ne\n\t"
  7154. "movne r3, r7\n\t"
  7155. "LDR r4, [%[a], #228]\n\t"
  7156. "LDR r5, [%[b], #228]\n\t"
  7157. "AND r4, r4, r3\n\t"
  7158. "AND r5, r5, r3\n\t"
  7159. "SUBS r4, r4, r5\n\t"
  7160. "IT hi\n\t"
  7161. "movhi r2, r8\n\t"
  7162. "IT lo\n\t"
  7163. "movlo r2, r3\n\t"
  7164. "IT ne\n\t"
  7165. "movne r3, r7\n\t"
  7166. "LDR r4, [%[a], #224]\n\t"
  7167. "LDR r5, [%[b], #224]\n\t"
  7168. "AND r4, r4, r3\n\t"
  7169. "AND r5, r5, r3\n\t"
  7170. "SUBS r4, r4, r5\n\t"
  7171. "IT hi\n\t"
  7172. "movhi r2, r8\n\t"
  7173. "IT lo\n\t"
  7174. "movlo r2, r3\n\t"
  7175. "IT ne\n\t"
  7176. "movne r3, r7\n\t"
  7177. "LDR r4, [%[a], #220]\n\t"
  7178. "LDR r5, [%[b], #220]\n\t"
  7179. "AND r4, r4, r3\n\t"
  7180. "AND r5, r5, r3\n\t"
  7181. "SUBS r4, r4, r5\n\t"
  7182. "IT hi\n\t"
  7183. "movhi r2, r8\n\t"
  7184. "IT lo\n\t"
  7185. "movlo r2, r3\n\t"
  7186. "IT ne\n\t"
  7187. "movne r3, r7\n\t"
  7188. "LDR r4, [%[a], #216]\n\t"
  7189. "LDR r5, [%[b], #216]\n\t"
  7190. "AND r4, r4, r3\n\t"
  7191. "AND r5, r5, r3\n\t"
  7192. "SUBS r4, r4, r5\n\t"
  7193. "IT hi\n\t"
  7194. "movhi r2, r8\n\t"
  7195. "IT lo\n\t"
  7196. "movlo r2, r3\n\t"
  7197. "IT ne\n\t"
  7198. "movne r3, r7\n\t"
  7199. "LDR r4, [%[a], #212]\n\t"
  7200. "LDR r5, [%[b], #212]\n\t"
  7201. "AND r4, r4, r3\n\t"
  7202. "AND r5, r5, r3\n\t"
  7203. "SUBS r4, r4, r5\n\t"
  7204. "IT hi\n\t"
  7205. "movhi r2, r8\n\t"
  7206. "IT lo\n\t"
  7207. "movlo r2, r3\n\t"
  7208. "IT ne\n\t"
  7209. "movne r3, r7\n\t"
  7210. "LDR r4, [%[a], #208]\n\t"
  7211. "LDR r5, [%[b], #208]\n\t"
  7212. "AND r4, r4, r3\n\t"
  7213. "AND r5, r5, r3\n\t"
  7214. "SUBS r4, r4, r5\n\t"
  7215. "IT hi\n\t"
  7216. "movhi r2, r8\n\t"
  7217. "IT lo\n\t"
  7218. "movlo r2, r3\n\t"
  7219. "IT ne\n\t"
  7220. "movne r3, r7\n\t"
  7221. "LDR r4, [%[a], #204]\n\t"
  7222. "LDR r5, [%[b], #204]\n\t"
  7223. "AND r4, r4, r3\n\t"
  7224. "AND r5, r5, r3\n\t"
  7225. "SUBS r4, r4, r5\n\t"
  7226. "IT hi\n\t"
  7227. "movhi r2, r8\n\t"
  7228. "IT lo\n\t"
  7229. "movlo r2, r3\n\t"
  7230. "IT ne\n\t"
  7231. "movne r3, r7\n\t"
  7232. "LDR r4, [%[a], #200]\n\t"
  7233. "LDR r5, [%[b], #200]\n\t"
  7234. "AND r4, r4, r3\n\t"
  7235. "AND r5, r5, r3\n\t"
  7236. "SUBS r4, r4, r5\n\t"
  7237. "IT hi\n\t"
  7238. "movhi r2, r8\n\t"
  7239. "IT lo\n\t"
  7240. "movlo r2, r3\n\t"
  7241. "IT ne\n\t"
  7242. "movne r3, r7\n\t"
  7243. "LDR r4, [%[a], #196]\n\t"
  7244. "LDR r5, [%[b], #196]\n\t"
  7245. "AND r4, r4, r3\n\t"
  7246. "AND r5, r5, r3\n\t"
  7247. "SUBS r4, r4, r5\n\t"
  7248. "IT hi\n\t"
  7249. "movhi r2, r8\n\t"
  7250. "IT lo\n\t"
  7251. "movlo r2, r3\n\t"
  7252. "IT ne\n\t"
  7253. "movne r3, r7\n\t"
  7254. "LDR r4, [%[a], #192]\n\t"
  7255. "LDR r5, [%[b], #192]\n\t"
  7256. "AND r4, r4, r3\n\t"
  7257. "AND r5, r5, r3\n\t"
  7258. "SUBS r4, r4, r5\n\t"
  7259. "IT hi\n\t"
  7260. "movhi r2, r8\n\t"
  7261. "IT lo\n\t"
  7262. "movlo r2, r3\n\t"
  7263. "IT ne\n\t"
  7264. "movne r3, r7\n\t"
  7265. "LDR r4, [%[a], #188]\n\t"
  7266. "LDR r5, [%[b], #188]\n\t"
  7267. "AND r4, r4, r3\n\t"
  7268. "AND r5, r5, r3\n\t"
  7269. "SUBS r4, r4, r5\n\t"
  7270. "IT hi\n\t"
  7271. "movhi r2, r8\n\t"
  7272. "IT lo\n\t"
  7273. "movlo r2, r3\n\t"
  7274. "IT ne\n\t"
  7275. "movne r3, r7\n\t"
  7276. "LDR r4, [%[a], #184]\n\t"
  7277. "LDR r5, [%[b], #184]\n\t"
  7278. "AND r4, r4, r3\n\t"
  7279. "AND r5, r5, r3\n\t"
  7280. "SUBS r4, r4, r5\n\t"
  7281. "IT hi\n\t"
  7282. "movhi r2, r8\n\t"
  7283. "IT lo\n\t"
  7284. "movlo r2, r3\n\t"
  7285. "IT ne\n\t"
  7286. "movne r3, r7\n\t"
  7287. "LDR r4, [%[a], #180]\n\t"
  7288. "LDR r5, [%[b], #180]\n\t"
  7289. "AND r4, r4, r3\n\t"
  7290. "AND r5, r5, r3\n\t"
  7291. "SUBS r4, r4, r5\n\t"
  7292. "IT hi\n\t"
  7293. "movhi r2, r8\n\t"
  7294. "IT lo\n\t"
  7295. "movlo r2, r3\n\t"
  7296. "IT ne\n\t"
  7297. "movne r3, r7\n\t"
  7298. "LDR r4, [%[a], #176]\n\t"
  7299. "LDR r5, [%[b], #176]\n\t"
  7300. "AND r4, r4, r3\n\t"
  7301. "AND r5, r5, r3\n\t"
  7302. "SUBS r4, r4, r5\n\t"
  7303. "IT hi\n\t"
  7304. "movhi r2, r8\n\t"
  7305. "IT lo\n\t"
  7306. "movlo r2, r3\n\t"
  7307. "IT ne\n\t"
  7308. "movne r3, r7\n\t"
  7309. "LDR r4, [%[a], #172]\n\t"
  7310. "LDR r5, [%[b], #172]\n\t"
  7311. "AND r4, r4, r3\n\t"
  7312. "AND r5, r5, r3\n\t"
  7313. "SUBS r4, r4, r5\n\t"
  7314. "IT hi\n\t"
  7315. "movhi r2, r8\n\t"
  7316. "IT lo\n\t"
  7317. "movlo r2, r3\n\t"
  7318. "IT ne\n\t"
  7319. "movne r3, r7\n\t"
  7320. "LDR r4, [%[a], #168]\n\t"
  7321. "LDR r5, [%[b], #168]\n\t"
  7322. "AND r4, r4, r3\n\t"
  7323. "AND r5, r5, r3\n\t"
  7324. "SUBS r4, r4, r5\n\t"
  7325. "IT hi\n\t"
  7326. "movhi r2, r8\n\t"
  7327. "IT lo\n\t"
  7328. "movlo r2, r3\n\t"
  7329. "IT ne\n\t"
  7330. "movne r3, r7\n\t"
  7331. "LDR r4, [%[a], #164]\n\t"
  7332. "LDR r5, [%[b], #164]\n\t"
  7333. "AND r4, r4, r3\n\t"
  7334. "AND r5, r5, r3\n\t"
  7335. "SUBS r4, r4, r5\n\t"
  7336. "IT hi\n\t"
  7337. "movhi r2, r8\n\t"
  7338. "IT lo\n\t"
  7339. "movlo r2, r3\n\t"
  7340. "IT ne\n\t"
  7341. "movne r3, r7\n\t"
  7342. "LDR r4, [%[a], #160]\n\t"
  7343. "LDR r5, [%[b], #160]\n\t"
  7344. "AND r4, r4, r3\n\t"
  7345. "AND r5, r5, r3\n\t"
  7346. "SUBS r4, r4, r5\n\t"
  7347. "IT hi\n\t"
  7348. "movhi r2, r8\n\t"
  7349. "IT lo\n\t"
  7350. "movlo r2, r3\n\t"
  7351. "IT ne\n\t"
  7352. "movne r3, r7\n\t"
  7353. "LDR r4, [%[a], #156]\n\t"
  7354. "LDR r5, [%[b], #156]\n\t"
  7355. "AND r4, r4, r3\n\t"
  7356. "AND r5, r5, r3\n\t"
  7357. "SUBS r4, r4, r5\n\t"
  7358. "IT hi\n\t"
  7359. "movhi r2, r8\n\t"
  7360. "IT lo\n\t"
  7361. "movlo r2, r3\n\t"
  7362. "IT ne\n\t"
  7363. "movne r3, r7\n\t"
  7364. "LDR r4, [%[a], #152]\n\t"
  7365. "LDR r5, [%[b], #152]\n\t"
  7366. "AND r4, r4, r3\n\t"
  7367. "AND r5, r5, r3\n\t"
  7368. "SUBS r4, r4, r5\n\t"
  7369. "IT hi\n\t"
  7370. "movhi r2, r8\n\t"
  7371. "IT lo\n\t"
  7372. "movlo r2, r3\n\t"
  7373. "IT ne\n\t"
  7374. "movne r3, r7\n\t"
  7375. "LDR r4, [%[a], #148]\n\t"
  7376. "LDR r5, [%[b], #148]\n\t"
  7377. "AND r4, r4, r3\n\t"
  7378. "AND r5, r5, r3\n\t"
  7379. "SUBS r4, r4, r5\n\t"
  7380. "IT hi\n\t"
  7381. "movhi r2, r8\n\t"
  7382. "IT lo\n\t"
  7383. "movlo r2, r3\n\t"
  7384. "IT ne\n\t"
  7385. "movne r3, r7\n\t"
  7386. "LDR r4, [%[a], #144]\n\t"
  7387. "LDR r5, [%[b], #144]\n\t"
  7388. "AND r4, r4, r3\n\t"
  7389. "AND r5, r5, r3\n\t"
  7390. "SUBS r4, r4, r5\n\t"
  7391. "IT hi\n\t"
  7392. "movhi r2, r8\n\t"
  7393. "IT lo\n\t"
  7394. "movlo r2, r3\n\t"
  7395. "IT ne\n\t"
  7396. "movne r3, r7\n\t"
  7397. "LDR r4, [%[a], #140]\n\t"
  7398. "LDR r5, [%[b], #140]\n\t"
  7399. "AND r4, r4, r3\n\t"
  7400. "AND r5, r5, r3\n\t"
  7401. "SUBS r4, r4, r5\n\t"
  7402. "IT hi\n\t"
  7403. "movhi r2, r8\n\t"
  7404. "IT lo\n\t"
  7405. "movlo r2, r3\n\t"
  7406. "IT ne\n\t"
  7407. "movne r3, r7\n\t"
  7408. "LDR r4, [%[a], #136]\n\t"
  7409. "LDR r5, [%[b], #136]\n\t"
  7410. "AND r4, r4, r3\n\t"
  7411. "AND r5, r5, r3\n\t"
  7412. "SUBS r4, r4, r5\n\t"
  7413. "IT hi\n\t"
  7414. "movhi r2, r8\n\t"
  7415. "IT lo\n\t"
  7416. "movlo r2, r3\n\t"
  7417. "IT ne\n\t"
  7418. "movne r3, r7\n\t"
  7419. "LDR r4, [%[a], #132]\n\t"
  7420. "LDR r5, [%[b], #132]\n\t"
  7421. "AND r4, r4, r3\n\t"
  7422. "AND r5, r5, r3\n\t"
  7423. "SUBS r4, r4, r5\n\t"
  7424. "IT hi\n\t"
  7425. "movhi r2, r8\n\t"
  7426. "IT lo\n\t"
  7427. "movlo r2, r3\n\t"
  7428. "IT ne\n\t"
  7429. "movne r3, r7\n\t"
  7430. "LDR r4, [%[a], #128]\n\t"
  7431. "LDR r5, [%[b], #128]\n\t"
  7432. "AND r4, r4, r3\n\t"
  7433. "AND r5, r5, r3\n\t"
  7434. "SUBS r4, r4, r5\n\t"
  7435. "IT hi\n\t"
  7436. "movhi r2, r8\n\t"
  7437. "IT lo\n\t"
  7438. "movlo r2, r3\n\t"
  7439. "IT ne\n\t"
  7440. "movne r3, r7\n\t"
  7441. "LDR r4, [%[a], #124]\n\t"
  7442. "LDR r5, [%[b], #124]\n\t"
  7443. "AND r4, r4, r3\n\t"
  7444. "AND r5, r5, r3\n\t"
  7445. "SUBS r4, r4, r5\n\t"
  7446. "IT hi\n\t"
  7447. "movhi r2, r8\n\t"
  7448. "IT lo\n\t"
  7449. "movlo r2, r3\n\t"
  7450. "IT ne\n\t"
  7451. "movne r3, r7\n\t"
  7452. "LDR r4, [%[a], #120]\n\t"
  7453. "LDR r5, [%[b], #120]\n\t"
  7454. "AND r4, r4, r3\n\t"
  7455. "AND r5, r5, r3\n\t"
  7456. "SUBS r4, r4, r5\n\t"
  7457. "IT hi\n\t"
  7458. "movhi r2, r8\n\t"
  7459. "IT lo\n\t"
  7460. "movlo r2, r3\n\t"
  7461. "IT ne\n\t"
  7462. "movne r3, r7\n\t"
  7463. "LDR r4, [%[a], #116]\n\t"
  7464. "LDR r5, [%[b], #116]\n\t"
  7465. "AND r4, r4, r3\n\t"
  7466. "AND r5, r5, r3\n\t"
  7467. "SUBS r4, r4, r5\n\t"
  7468. "IT hi\n\t"
  7469. "movhi r2, r8\n\t"
  7470. "IT lo\n\t"
  7471. "movlo r2, r3\n\t"
  7472. "IT ne\n\t"
  7473. "movne r3, r7\n\t"
  7474. "LDR r4, [%[a], #112]\n\t"
  7475. "LDR r5, [%[b], #112]\n\t"
  7476. "AND r4, r4, r3\n\t"
  7477. "AND r5, r5, r3\n\t"
  7478. "SUBS r4, r4, r5\n\t"
  7479. "IT hi\n\t"
  7480. "movhi r2, r8\n\t"
  7481. "IT lo\n\t"
  7482. "movlo r2, r3\n\t"
  7483. "IT ne\n\t"
  7484. "movne r3, r7\n\t"
  7485. "LDR r4, [%[a], #108]\n\t"
  7486. "LDR r5, [%[b], #108]\n\t"
  7487. "AND r4, r4, r3\n\t"
  7488. "AND r5, r5, r3\n\t"
  7489. "SUBS r4, r4, r5\n\t"
  7490. "IT hi\n\t"
  7491. "movhi r2, r8\n\t"
  7492. "IT lo\n\t"
  7493. "movlo r2, r3\n\t"
  7494. "IT ne\n\t"
  7495. "movne r3, r7\n\t"
  7496. "LDR r4, [%[a], #104]\n\t"
  7497. "LDR r5, [%[b], #104]\n\t"
  7498. "AND r4, r4, r3\n\t"
  7499. "AND r5, r5, r3\n\t"
  7500. "SUBS r4, r4, r5\n\t"
  7501. "IT hi\n\t"
  7502. "movhi r2, r8\n\t"
  7503. "IT lo\n\t"
  7504. "movlo r2, r3\n\t"
  7505. "IT ne\n\t"
  7506. "movne r3, r7\n\t"
  7507. "LDR r4, [%[a], #100]\n\t"
  7508. "LDR r5, [%[b], #100]\n\t"
  7509. "AND r4, r4, r3\n\t"
  7510. "AND r5, r5, r3\n\t"
  7511. "SUBS r4, r4, r5\n\t"
  7512. "IT hi\n\t"
  7513. "movhi r2, r8\n\t"
  7514. "IT lo\n\t"
  7515. "movlo r2, r3\n\t"
  7516. "IT ne\n\t"
  7517. "movne r3, r7\n\t"
  7518. "LDR r4, [%[a], #96]\n\t"
  7519. "LDR r5, [%[b], #96]\n\t"
  7520. "AND r4, r4, r3\n\t"
  7521. "AND r5, r5, r3\n\t"
  7522. "SUBS r4, r4, r5\n\t"
  7523. "IT hi\n\t"
  7524. "movhi r2, r8\n\t"
  7525. "IT lo\n\t"
  7526. "movlo r2, r3\n\t"
  7527. "IT ne\n\t"
  7528. "movne r3, r7\n\t"
  7529. "LDR r4, [%[a], #92]\n\t"
  7530. "LDR r5, [%[b], #92]\n\t"
  7531. "AND r4, r4, r3\n\t"
  7532. "AND r5, r5, r3\n\t"
  7533. "SUBS r4, r4, r5\n\t"
  7534. "IT hi\n\t"
  7535. "movhi r2, r8\n\t"
  7536. "IT lo\n\t"
  7537. "movlo r2, r3\n\t"
  7538. "IT ne\n\t"
  7539. "movne r3, r7\n\t"
  7540. "LDR r4, [%[a], #88]\n\t"
  7541. "LDR r5, [%[b], #88]\n\t"
  7542. "AND r4, r4, r3\n\t"
  7543. "AND r5, r5, r3\n\t"
  7544. "SUBS r4, r4, r5\n\t"
  7545. "IT hi\n\t"
  7546. "movhi r2, r8\n\t"
  7547. "IT lo\n\t"
  7548. "movlo r2, r3\n\t"
  7549. "IT ne\n\t"
  7550. "movne r3, r7\n\t"
  7551. "LDR r4, [%[a], #84]\n\t"
  7552. "LDR r5, [%[b], #84]\n\t"
  7553. "AND r4, r4, r3\n\t"
  7554. "AND r5, r5, r3\n\t"
  7555. "SUBS r4, r4, r5\n\t"
  7556. "IT hi\n\t"
  7557. "movhi r2, r8\n\t"
  7558. "IT lo\n\t"
  7559. "movlo r2, r3\n\t"
  7560. "IT ne\n\t"
  7561. "movne r3, r7\n\t"
  7562. "LDR r4, [%[a], #80]\n\t"
  7563. "LDR r5, [%[b], #80]\n\t"
  7564. "AND r4, r4, r3\n\t"
  7565. "AND r5, r5, r3\n\t"
  7566. "SUBS r4, r4, r5\n\t"
  7567. "IT hi\n\t"
  7568. "movhi r2, r8\n\t"
  7569. "IT lo\n\t"
  7570. "movlo r2, r3\n\t"
  7571. "IT ne\n\t"
  7572. "movne r3, r7\n\t"
  7573. "LDR r4, [%[a], #76]\n\t"
  7574. "LDR r5, [%[b], #76]\n\t"
  7575. "AND r4, r4, r3\n\t"
  7576. "AND r5, r5, r3\n\t"
  7577. "SUBS r4, r4, r5\n\t"
  7578. "IT hi\n\t"
  7579. "movhi r2, r8\n\t"
  7580. "IT lo\n\t"
  7581. "movlo r2, r3\n\t"
  7582. "IT ne\n\t"
  7583. "movne r3, r7\n\t"
  7584. "LDR r4, [%[a], #72]\n\t"
  7585. "LDR r5, [%[b], #72]\n\t"
  7586. "AND r4, r4, r3\n\t"
  7587. "AND r5, r5, r3\n\t"
  7588. "SUBS r4, r4, r5\n\t"
  7589. "IT hi\n\t"
  7590. "movhi r2, r8\n\t"
  7591. "IT lo\n\t"
  7592. "movlo r2, r3\n\t"
  7593. "IT ne\n\t"
  7594. "movne r3, r7\n\t"
  7595. "LDR r4, [%[a], #68]\n\t"
  7596. "LDR r5, [%[b], #68]\n\t"
  7597. "AND r4, r4, r3\n\t"
  7598. "AND r5, r5, r3\n\t"
  7599. "SUBS r4, r4, r5\n\t"
  7600. "IT hi\n\t"
  7601. "movhi r2, r8\n\t"
  7602. "IT lo\n\t"
  7603. "movlo r2, r3\n\t"
  7604. "IT ne\n\t"
  7605. "movne r3, r7\n\t"
  7606. "LDR r4, [%[a], #64]\n\t"
  7607. "LDR r5, [%[b], #64]\n\t"
  7608. "AND r4, r4, r3\n\t"
  7609. "AND r5, r5, r3\n\t"
  7610. "SUBS r4, r4, r5\n\t"
  7611. "IT hi\n\t"
  7612. "movhi r2, r8\n\t"
  7613. "IT lo\n\t"
  7614. "movlo r2, r3\n\t"
  7615. "IT ne\n\t"
  7616. "movne r3, r7\n\t"
  7617. "LDR r4, [%[a], #60]\n\t"
  7618. "LDR r5, [%[b], #60]\n\t"
  7619. "AND r4, r4, r3\n\t"
  7620. "AND r5, r5, r3\n\t"
  7621. "SUBS r4, r4, r5\n\t"
  7622. "IT hi\n\t"
  7623. "movhi r2, r8\n\t"
  7624. "IT lo\n\t"
  7625. "movlo r2, r3\n\t"
  7626. "IT ne\n\t"
  7627. "movne r3, r7\n\t"
  7628. "LDR r4, [%[a], #56]\n\t"
  7629. "LDR r5, [%[b], #56]\n\t"
  7630. "AND r4, r4, r3\n\t"
  7631. "AND r5, r5, r3\n\t"
  7632. "SUBS r4, r4, r5\n\t"
  7633. "IT hi\n\t"
  7634. "movhi r2, r8\n\t"
  7635. "IT lo\n\t"
  7636. "movlo r2, r3\n\t"
  7637. "IT ne\n\t"
  7638. "movne r3, r7\n\t"
  7639. "LDR r4, [%[a], #52]\n\t"
  7640. "LDR r5, [%[b], #52]\n\t"
  7641. "AND r4, r4, r3\n\t"
  7642. "AND r5, r5, r3\n\t"
  7643. "SUBS r4, r4, r5\n\t"
  7644. "IT hi\n\t"
  7645. "movhi r2, r8\n\t"
  7646. "IT lo\n\t"
  7647. "movlo r2, r3\n\t"
  7648. "IT ne\n\t"
  7649. "movne r3, r7\n\t"
  7650. "LDR r4, [%[a], #48]\n\t"
  7651. "LDR r5, [%[b], #48]\n\t"
  7652. "AND r4, r4, r3\n\t"
  7653. "AND r5, r5, r3\n\t"
  7654. "SUBS r4, r4, r5\n\t"
  7655. "IT hi\n\t"
  7656. "movhi r2, r8\n\t"
  7657. "IT lo\n\t"
  7658. "movlo r2, r3\n\t"
  7659. "IT ne\n\t"
  7660. "movne r3, r7\n\t"
  7661. "LDR r4, [%[a], #44]\n\t"
  7662. "LDR r5, [%[b], #44]\n\t"
  7663. "AND r4, r4, r3\n\t"
  7664. "AND r5, r5, r3\n\t"
  7665. "SUBS r4, r4, r5\n\t"
  7666. "IT hi\n\t"
  7667. "movhi r2, r8\n\t"
  7668. "IT lo\n\t"
  7669. "movlo r2, r3\n\t"
  7670. "IT ne\n\t"
  7671. "movne r3, r7\n\t"
  7672. "LDR r4, [%[a], #40]\n\t"
  7673. "LDR r5, [%[b], #40]\n\t"
  7674. "AND r4, r4, r3\n\t"
  7675. "AND r5, r5, r3\n\t"
  7676. "SUBS r4, r4, r5\n\t"
  7677. "IT hi\n\t"
  7678. "movhi r2, r8\n\t"
  7679. "IT lo\n\t"
  7680. "movlo r2, r3\n\t"
  7681. "IT ne\n\t"
  7682. "movne r3, r7\n\t"
  7683. "LDR r4, [%[a], #36]\n\t"
  7684. "LDR r5, [%[b], #36]\n\t"
  7685. "AND r4, r4, r3\n\t"
  7686. "AND r5, r5, r3\n\t"
  7687. "SUBS r4, r4, r5\n\t"
  7688. "IT hi\n\t"
  7689. "movhi r2, r8\n\t"
  7690. "IT lo\n\t"
  7691. "movlo r2, r3\n\t"
  7692. "IT ne\n\t"
  7693. "movne r3, r7\n\t"
  7694. "LDR r4, [%[a], #32]\n\t"
  7695. "LDR r5, [%[b], #32]\n\t"
  7696. "AND r4, r4, r3\n\t"
  7697. "AND r5, r5, r3\n\t"
  7698. "SUBS r4, r4, r5\n\t"
  7699. "IT hi\n\t"
  7700. "movhi r2, r8\n\t"
  7701. "IT lo\n\t"
  7702. "movlo r2, r3\n\t"
  7703. "IT ne\n\t"
  7704. "movne r3, r7\n\t"
  7705. "LDR r4, [%[a], #28]\n\t"
  7706. "LDR r5, [%[b], #28]\n\t"
  7707. "AND r4, r4, r3\n\t"
  7708. "AND r5, r5, r3\n\t"
  7709. "SUBS r4, r4, r5\n\t"
  7710. "IT hi\n\t"
  7711. "movhi r2, r8\n\t"
  7712. "IT lo\n\t"
  7713. "movlo r2, r3\n\t"
  7714. "IT ne\n\t"
  7715. "movne r3, r7\n\t"
  7716. "LDR r4, [%[a], #24]\n\t"
  7717. "LDR r5, [%[b], #24]\n\t"
  7718. "AND r4, r4, r3\n\t"
  7719. "AND r5, r5, r3\n\t"
  7720. "SUBS r4, r4, r5\n\t"
  7721. "IT hi\n\t"
  7722. "movhi r2, r8\n\t"
  7723. "IT lo\n\t"
  7724. "movlo r2, r3\n\t"
  7725. "IT ne\n\t"
  7726. "movne r3, r7\n\t"
  7727. "LDR r4, [%[a], #20]\n\t"
  7728. "LDR r5, [%[b], #20]\n\t"
  7729. "AND r4, r4, r3\n\t"
  7730. "AND r5, r5, r3\n\t"
  7731. "SUBS r4, r4, r5\n\t"
  7732. "IT hi\n\t"
  7733. "movhi r2, r8\n\t"
  7734. "IT lo\n\t"
  7735. "movlo r2, r3\n\t"
  7736. "IT ne\n\t"
  7737. "movne r3, r7\n\t"
  7738. "LDR r4, [%[a], #16]\n\t"
  7739. "LDR r5, [%[b], #16]\n\t"
  7740. "AND r4, r4, r3\n\t"
  7741. "AND r5, r5, r3\n\t"
  7742. "SUBS r4, r4, r5\n\t"
  7743. "IT hi\n\t"
  7744. "movhi r2, r8\n\t"
  7745. "IT lo\n\t"
  7746. "movlo r2, r3\n\t"
  7747. "IT ne\n\t"
  7748. "movne r3, r7\n\t"
  7749. "LDR r4, [%[a], #12]\n\t"
  7750. "LDR r5, [%[b], #12]\n\t"
  7751. "AND r4, r4, r3\n\t"
  7752. "AND r5, r5, r3\n\t"
  7753. "SUBS r4, r4, r5\n\t"
  7754. "IT hi\n\t"
  7755. "movhi r2, r8\n\t"
  7756. "IT lo\n\t"
  7757. "movlo r2, r3\n\t"
  7758. "IT ne\n\t"
  7759. "movne r3, r7\n\t"
  7760. "LDR r4, [%[a], #8]\n\t"
  7761. "LDR r5, [%[b], #8]\n\t"
  7762. "AND r4, r4, r3\n\t"
  7763. "AND r5, r5, r3\n\t"
  7764. "SUBS r4, r4, r5\n\t"
  7765. "IT hi\n\t"
  7766. "movhi r2, r8\n\t"
  7767. "IT lo\n\t"
  7768. "movlo r2, r3\n\t"
  7769. "IT ne\n\t"
  7770. "movne r3, r7\n\t"
  7771. "LDR r4, [%[a], #4]\n\t"
  7772. "LDR r5, [%[b], #4]\n\t"
  7773. "AND r4, r4, r3\n\t"
  7774. "AND r5, r5, r3\n\t"
  7775. "SUBS r4, r4, r5\n\t"
  7776. "IT hi\n\t"
  7777. "movhi r2, r8\n\t"
  7778. "IT lo\n\t"
  7779. "movlo r2, r3\n\t"
  7780. "IT ne\n\t"
  7781. "movne r3, r7\n\t"
  7782. "LDR r4, [%[a]]\n\t"
  7783. "LDR r5, [%[b]]\n\t"
  7784. "AND r4, r4, r3\n\t"
  7785. "AND r5, r5, r3\n\t"
  7786. "SUBS r4, r4, r5\n\t"
  7787. "IT hi\n\t"
  7788. "movhi r2, r8\n\t"
  7789. "IT lo\n\t"
  7790. "movlo r2, r3\n\t"
  7791. "IT ne\n\t"
  7792. "movne r3, r7\n\t"
  7793. "EOR r2, r2, r3\n\t"
  7794. #endif /*WOLFSSL_SP_SMALL */
  7795. "MOV %[a], r2\n\t"
  7796. : [a] "+r" (a), [b] "+r" (b)
  7797. :
  7798. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  7799. );
  7800. return (uint32_t)(size_t)a;
  7801. }
  7802. /* Divide d in a and put remainder into r (m*d + r = a)
  7803. * m is not calculated as it is not needed at this time.
  7804. *
  7805. * a Number to be divided.
  7806. * d Number to divide with.
  7807. * m Multiplier result.
  7808. * r Remainder from the division.
  7809. * returns MP_OKAY indicating success.
  7810. */
  7811. static WC_INLINE int sp_2048_div_64(const sp_digit* a, const sp_digit* d,
  7812. sp_digit* m, sp_digit* r)
  7813. {
  7814. sp_digit t1[128], t2[65];
  7815. sp_digit div, r1;
  7816. int i;
  7817. (void)m;
  7818. div = d[63];
  7819. XMEMCPY(t1, a, sizeof(*t1) * 2 * 64);
  7820. r1 = sp_2048_cmp_64(&t1[64], d) >= 0;
  7821. sp_2048_cond_sub_64(&t1[64], &t1[64], d, (sp_digit)0 - r1);
  7822. for (i = 63; i >= 0; i--) {
  7823. volatile sp_digit mask = (sp_digit)0 - (t1[64 + i] == div);
  7824. sp_digit hi = t1[64 + i] + mask;
  7825. r1 = div_2048_word_64(hi, t1[64 + i - 1], div);
  7826. r1 |= mask;
  7827. sp_2048_mul_d_64(t2, d, r1);
  7828. t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2);
  7829. t1[64 + i] -= t2[64];
  7830. sp_2048_mask_64(t2, d, t1[64 + i]);
  7831. t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2);
  7832. sp_2048_mask_64(t2, d, t1[64 + i]);
  7833. t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2);
  7834. }
  7835. r1 = sp_2048_cmp_64(t1, d) >= 0;
  7836. sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1);
  7837. return MP_OKAY;
  7838. }
  7839. /* Reduce a modulo m into r. (r = a mod m)
  7840. *
  7841. * r A single precision number that is the reduced result.
  7842. * a A single precision number that is to be reduced.
  7843. * m A single precision number that is the modulus to reduce with.
  7844. * returns MP_OKAY indicating success.
  7845. */
  7846. static WC_INLINE int sp_2048_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m)
  7847. {
  7848. return sp_2048_div_64(a, m, NULL, r);
  7849. }
  7850. #endif /* WOLFSSL_HAVE_SP_DH || !WOLFSSL_RSA_PUBLIC_ONLY */
  7851. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
  7852. defined(WOLFSSL_HAVE_SP_DH)
  7853. #ifdef WOLFSSL_SP_SMALL
  7854. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  7855. *
  7856. * r A single precision number that is the result of the operation.
  7857. * a A single precision number being exponentiated.
  7858. * e A single precision number that is the exponent.
  7859. * bits The number of bits in the exponent.
  7860. * m A single precision number that is the modulus.
  7861. * returns 0 on success.
  7862. * returns MEMORY_E on dynamic memory allocation failure.
  7863. * returns MP_VAL when base is even or exponent is 0.
  7864. */
  7865. static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
  7866. int bits, const sp_digit* m, int reduceA)
  7867. {
  7868. #ifdef WOLFSSL_SP_SMALL_STACK
  7869. sp_digit* td = NULL;
  7870. #else
  7871. sp_digit td[8 * 128];
  7872. #endif
  7873. sp_digit* t[8];
  7874. sp_digit* norm = NULL;
  7875. sp_digit mp = 1;
  7876. sp_digit n;
  7877. sp_digit mask;
  7878. int i;
  7879. int c;
  7880. byte y;
  7881. int err = MP_OKAY;
  7882. if (bits == 0) {
  7883. err = MP_VAL;
  7884. }
  7885. #ifdef WOLFSSL_SP_SMALL_STACK
  7886. if (err == MP_OKAY) {
  7887. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 * 128), NULL,
  7888. DYNAMIC_TYPE_TMP_BUFFER);
  7889. if (td == NULL)
  7890. err = MEMORY_E;
  7891. }
  7892. #endif
  7893. if (err == MP_OKAY) {
  7894. norm = td;
  7895. for (i=0; i<8; i++) {
  7896. t[i] = td + i * 128;
  7897. }
  7898. sp_2048_mont_setup(m, &mp);
  7899. sp_2048_mont_norm_64(norm, m);
  7900. XMEMSET(t[1], 0, sizeof(sp_digit) * 64U);
  7901. if (reduceA != 0) {
  7902. err = sp_2048_mod_64(t[1] + 64, a, m);
  7903. if (err == MP_OKAY) {
  7904. err = sp_2048_mod_64(t[1], t[1], m);
  7905. }
  7906. }
  7907. else {
  7908. XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64);
  7909. err = sp_2048_mod_64(t[1], t[1], m);
  7910. }
  7911. }
  7912. if (err == MP_OKAY) {
  7913. sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp);
  7914. sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp);
  7915. sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp);
  7916. sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp);
  7917. sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp);
  7918. sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp);
  7919. i = (bits - 1) / 32;
  7920. n = e[i--];
  7921. c = bits & 31;
  7922. if (c == 0) {
  7923. c = 32;
  7924. }
  7925. c -= bits % 3;
  7926. if (c == 32) {
  7927. c = 29;
  7928. }
  7929. if (c < 0) {
  7930. /* Number of bits in top word is less than number needed. */
  7931. c = -c;
  7932. y = (byte)(n << c);
  7933. n = e[i--];
  7934. y |= (byte)(n >> (64 - c));
  7935. n <<= c;
  7936. c = 64 - c;
  7937. }
  7938. else if (c == 0) {
  7939. /* All bits in top word used. */
  7940. y = (byte)n;
  7941. }
  7942. else {
  7943. y = (byte)(n >> c);
  7944. n <<= 32 - c;
  7945. }
  7946. XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
  7947. for (; i>=0 || c>=3; ) {
  7948. if (c == 0) {
  7949. n = e[i--];
  7950. y = (byte)(n >> 29);
  7951. n <<= 3;
  7952. c = 29;
  7953. }
  7954. else if (c < 3) {
  7955. y = (byte)(n >> 29);
  7956. n = e[i--];
  7957. c = 3 - c;
  7958. y |= (byte)(n >> (32 - c));
  7959. n <<= c;
  7960. c = 32 - c;
  7961. }
  7962. else {
  7963. y = (byte)((n >> 29) & 0x7);
  7964. n <<= 3;
  7965. c -= 3;
  7966. }
  7967. sp_2048_mont_sqr_64(r, r, m, mp);
  7968. sp_2048_mont_sqr_64(r, r, m, mp);
  7969. sp_2048_mont_sqr_64(r, r, m, mp);
  7970. sp_2048_mont_mul_64(r, r, t[y], m, mp);
  7971. }
  7972. XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U);
  7973. sp_2048_mont_reduce_64(r, m, mp);
  7974. mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
  7975. sp_2048_cond_sub_64(r, r, m, mask);
  7976. }
  7977. #ifdef WOLFSSL_SP_SMALL_STACK
  7978. if (td != NULL)
  7979. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  7980. #endif
  7981. return err;
  7982. }
  7983. #else
  7984. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  7985. *
  7986. * r A single precision number that is the result of the operation.
  7987. * a A single precision number being exponentiated.
  7988. * e A single precision number that is the exponent.
  7989. * bits The number of bits in the exponent.
  7990. * m A single precision number that is the modulus.
  7991. * returns 0 on success.
  7992. * returns MEMORY_E on dynamic memory allocation failure.
  7993. * returns MP_VAL when base is even or exponent is 0.
  7994. */
  7995. static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e,
  7996. int bits, const sp_digit* m, int reduceA)
  7997. {
  7998. #ifdef WOLFSSL_SP_SMALL_STACK
  7999. sp_digit* td = NULL;
  8000. #else
  8001. sp_digit td[16 * 128];
  8002. #endif
  8003. sp_digit* t[16];
  8004. sp_digit* norm = NULL;
  8005. sp_digit mp = 1;
  8006. sp_digit n;
  8007. sp_digit mask;
  8008. int i;
  8009. int c;
  8010. byte y;
  8011. int err = MP_OKAY;
  8012. if (bits == 0) {
  8013. err = MP_VAL;
  8014. }
  8015. #ifdef WOLFSSL_SP_SMALL_STACK
  8016. if (err == MP_OKAY) {
  8017. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 128), NULL,
  8018. DYNAMIC_TYPE_TMP_BUFFER);
  8019. if (td == NULL)
  8020. err = MEMORY_E;
  8021. }
  8022. #endif
  8023. if (err == MP_OKAY) {
  8024. norm = td;
  8025. for (i=0; i<16; i++) {
  8026. t[i] = td + i * 128;
  8027. }
  8028. sp_2048_mont_setup(m, &mp);
  8029. sp_2048_mont_norm_64(norm, m);
  8030. XMEMSET(t[1], 0, sizeof(sp_digit) * 64U);
  8031. if (reduceA != 0) {
  8032. err = sp_2048_mod_64(t[1] + 64, a, m);
  8033. if (err == MP_OKAY) {
  8034. err = sp_2048_mod_64(t[1], t[1], m);
  8035. }
  8036. }
  8037. else {
  8038. XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64);
  8039. err = sp_2048_mod_64(t[1], t[1], m);
  8040. }
  8041. }
  8042. if (err == MP_OKAY) {
  8043. sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp);
  8044. sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp);
  8045. sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp);
  8046. sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp);
  8047. sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp);
  8048. sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp);
  8049. sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp);
  8050. sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp);
  8051. sp_2048_mont_sqr_64(t[10], t[ 5], m, mp);
  8052. sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp);
  8053. sp_2048_mont_sqr_64(t[12], t[ 6], m, mp);
  8054. sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp);
  8055. sp_2048_mont_sqr_64(t[14], t[ 7], m, mp);
  8056. sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp);
  8057. i = (bits - 1) / 32;
  8058. n = e[i--];
  8059. c = bits & 31;
  8060. if (c == 0) {
  8061. c = 32;
  8062. }
  8063. c -= bits % 4;
  8064. if (c == 32) {
  8065. c = 28;
  8066. }
  8067. if (c < 0) {
  8068. /* Number of bits in top word is less than number needed. */
  8069. c = -c;
  8070. y = (byte)(n << c);
  8071. n = e[i--];
  8072. y |= (byte)(n >> (64 - c));
  8073. n <<= c;
  8074. c = 64 - c;
  8075. }
  8076. else if (c == 0) {
  8077. /* All bits in top word used. */
  8078. y = (byte)n;
  8079. }
  8080. else {
  8081. y = (byte)(n >> c);
  8082. n <<= 32 - c;
  8083. }
  8084. XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
  8085. for (; i>=0 || c>=4; ) {
  8086. if (c == 0) {
  8087. n = e[i--];
  8088. y = (byte)(n >> 28);
  8089. n <<= 4;
  8090. c = 28;
  8091. }
  8092. else if (c < 4) {
  8093. y = (byte)(n >> 28);
  8094. n = e[i--];
  8095. c = 4 - c;
  8096. y |= (byte)(n >> (32 - c));
  8097. n <<= c;
  8098. c = 32 - c;
  8099. }
  8100. else {
  8101. y = (byte)((n >> 28) & 0xf);
  8102. n <<= 4;
  8103. c -= 4;
  8104. }
  8105. sp_2048_mont_sqr_64(r, r, m, mp);
  8106. sp_2048_mont_sqr_64(r, r, m, mp);
  8107. sp_2048_mont_sqr_64(r, r, m, mp);
  8108. sp_2048_mont_sqr_64(r, r, m, mp);
  8109. sp_2048_mont_mul_64(r, r, t[y], m, mp);
  8110. }
  8111. XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U);
  8112. sp_2048_mont_reduce_64(r, m, mp);
  8113. mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
  8114. sp_2048_cond_sub_64(r, r, m, mask);
  8115. }
  8116. #ifdef WOLFSSL_SP_SMALL_STACK
  8117. if (td != NULL)
  8118. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  8119. #endif
  8120. return err;
  8121. }
  8122. #endif /* WOLFSSL_SP_SMALL */
  8123. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  8124. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  8125. #ifdef WOLFSSL_HAVE_SP_RSA
  8126. /* RSA public key operation.
  8127. *
  8128. * in Array of bytes representing the number to exponentiate, base.
  8129. * inLen Number of bytes in base.
  8130. * em Public exponent.
  8131. * mm Modulus.
  8132. * out Buffer to hold big-endian bytes of exponentiation result.
  8133. * Must be at least 256 bytes long.
  8134. * outLen Number of bytes in result.
  8135. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  8136. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  8137. */
  8138. int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
  8139. const mp_int* mm, byte* out, word32* outLen)
  8140. {
  8141. #ifdef WOLFSSL_SP_SMALL_STACK
  8142. sp_digit* a = NULL;
  8143. #else
  8144. sp_digit a[64 * 5];
  8145. #endif
  8146. sp_digit* m = NULL;
  8147. sp_digit* r = NULL;
  8148. sp_digit *ah = NULL;
  8149. sp_digit e[1] = {0};
  8150. int err = MP_OKAY;
  8151. if (*outLen < 256) {
  8152. err = MP_TO_E;
  8153. }
  8154. else if (mp_count_bits(em) > 32 || inLen > 256 ||
  8155. mp_count_bits(mm) != 2048) {
  8156. err = MP_READ_E;
  8157. }
  8158. else if (mp_iseven(mm)) {
  8159. err = MP_VAL;
  8160. }
  8161. #ifdef WOLFSSL_SP_SMALL_STACK
  8162. if (err == MP_OKAY) {
  8163. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL,
  8164. DYNAMIC_TYPE_RSA);
  8165. if (a == NULL)
  8166. err = MEMORY_E;
  8167. }
  8168. #endif
  8169. if (err == MP_OKAY) {
  8170. ah = a + 64;
  8171. r = a + 64 * 2;
  8172. m = r + 64 * 2;
  8173. sp_2048_from_bin(ah, 64, in, inLen);
  8174. #if DIGIT_BIT >= 32
  8175. e[0] = em->dp[0];
  8176. #else
  8177. e[0] = em->dp[0];
  8178. if (em->used > 1) {
  8179. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  8180. }
  8181. #endif
  8182. if (e[0] == 0) {
  8183. err = MP_EXPTMOD_E;
  8184. }
  8185. }
  8186. if (err == MP_OKAY) {
  8187. sp_2048_from_mp(m, 64, mm);
  8188. if (e[0] == 0x10001) {
  8189. int i;
  8190. sp_digit mp;
  8191. sp_2048_mont_setup(m, &mp);
  8192. /* Convert to Montgomery form. */
  8193. XMEMSET(a, 0, sizeof(sp_digit) * 64);
  8194. err = sp_2048_mod_64_cond(r, a, m);
  8195. /* Montgomery form: r = a.R mod m */
  8196. if (err == MP_OKAY) {
  8197. /* r = a ^ 0x10000 => r = a squared 16 times */
  8198. for (i = 15; i >= 0; i--) {
  8199. sp_2048_mont_sqr_64(r, r, m, mp);
  8200. }
  8201. /* mont_red(r.R.R) = (r.R.R / R) mod m = r.R mod m
  8202. * mont_red(r.R * a) = (r.R.a / R) mod m = r.a mod m
  8203. */
  8204. sp_2048_mont_mul_64(r, r, ah, m, mp);
  8205. for (i = 63; i > 0; i--) {
  8206. if (r[i] != m[i]) {
  8207. break;
  8208. }
  8209. }
  8210. if (r[i] >= m[i]) {
  8211. sp_2048_sub_in_place_64(r, m);
  8212. }
  8213. }
  8214. }
  8215. else if (e[0] == 0x3) {
  8216. if (err == MP_OKAY) {
  8217. sp_2048_sqr_64(r, ah);
  8218. err = sp_2048_mod_64_cond(r, r, m);
  8219. }
  8220. if (err == MP_OKAY) {
  8221. sp_2048_mul_64(r, ah, r);
  8222. err = sp_2048_mod_64_cond(r, r, m);
  8223. }
  8224. }
  8225. else {
  8226. int i;
  8227. sp_digit mp;
  8228. sp_2048_mont_setup(m, &mp);
  8229. /* Convert to Montgomery form. */
  8230. XMEMSET(a, 0, sizeof(sp_digit) * 64);
  8231. err = sp_2048_mod_64_cond(a, a, m);
  8232. if (err == MP_OKAY) {
  8233. for (i = 31; i >= 0; i--) {
  8234. if (e[0] >> i) {
  8235. break;
  8236. }
  8237. }
  8238. XMEMCPY(r, a, sizeof(sp_digit) * 64);
  8239. for (i--; i >= 0; i--) {
  8240. sp_2048_mont_sqr_64(r, r, m, mp);
  8241. if (((e[0] >> i) & 1) == 1) {
  8242. sp_2048_mont_mul_64(r, r, a, m, mp);
  8243. }
  8244. }
  8245. XMEMSET(&r[64], 0, sizeof(sp_digit) * 64);
  8246. sp_2048_mont_reduce_64(r, m, mp);
  8247. for (i = 63; i > 0; i--) {
  8248. if (r[i] != m[i]) {
  8249. break;
  8250. }
  8251. }
  8252. if (r[i] >= m[i]) {
  8253. sp_2048_sub_in_place_64(r, m);
  8254. }
  8255. }
  8256. }
  8257. }
  8258. if (err == MP_OKAY) {
  8259. sp_2048_to_bin_64(r, out);
  8260. *outLen = 256;
  8261. }
  8262. #ifdef WOLFSSL_SP_SMALL_STACK
  8263. if (a != NULL)
  8264. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  8265. #endif
  8266. return err;
  8267. }
  8268. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  8269. #ifdef WOLFSSL_SP_SMALL
  8270. /* Conditionally add a and b using the mask m.
  8271. * m is -1 to add and 0 when not.
  8272. *
  8273. * r A single precision number representing conditional add result.
  8274. * a A single precision number to add with.
  8275. * b A single precision number to add.
  8276. * m Mask value to apply.
  8277. */
  8278. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  8279. static sp_digit sp_2048_cond_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  8280. #else
  8281. static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  8282. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  8283. {
  8284. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  8285. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  8286. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  8287. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  8288. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  8289. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  8290. __asm__ __volatile__ (
  8291. "MOV r5, #0x0\n\t"
  8292. "MOV r8, #0x0\n\t"
  8293. "MOV r4, #0x0\n\t"
  8294. "\n"
  8295. "L_sp_2048_cond_add_32_words:\n\t"
  8296. "ADDS r5, r5, #0xffffffff\n\t"
  8297. "LDR r6, [%[a], r4]\n\t"
  8298. "LDR r7, [%[b], r4]\n\t"
  8299. "AND r7, r7, %[m]\n\t"
  8300. "ADCS r6, r6, r7\n\t"
  8301. "ADC r5, r8, r8\n\t"
  8302. "STR r6, [%[r], r4]\n\t"
  8303. "ADD r4, r4, #0x4\n\t"
  8304. "CMP r4, #0x80\n\t"
  8305. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  8306. "BLT L_sp_2048_cond_add_32_words\n\t"
  8307. #else
  8308. "BLT.N L_sp_2048_cond_add_32_words\n\t"
  8309. #endif
  8310. "MOV %[r], r5\n\t"
  8311. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  8312. :
  8313. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  8314. );
  8315. return (uint32_t)(size_t)r;
  8316. }
  8317. #else
  8318. /* Conditionally add a and b using the mask m.
  8319. * m is -1 to add and 0 when not.
  8320. *
  8321. * r A single precision number representing conditional add result.
  8322. * a A single precision number to add with.
  8323. * b A single precision number to add.
  8324. * m Mask value to apply.
  8325. */
  8326. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  8327. static sp_digit sp_2048_cond_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  8328. #else
  8329. static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  8330. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  8331. {
  8332. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  8333. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  8334. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  8335. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  8336. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  8337. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  8338. __asm__ __volatile__ (
  8339. "MOV r10, #0x0\n\t"
  8340. "LDM %[a]!, {r6, r7}\n\t"
  8341. "LDM %[b]!, {r8, r9}\n\t"
  8342. "AND r8, r8, %[m]\n\t"
  8343. "AND r9, r9, %[m]\n\t"
  8344. "ADDS r6, r6, r8\n\t"
  8345. "ADCS r7, r7, r9\n\t"
  8346. "STM %[r]!, {r6, r7}\n\t"
  8347. "LDM %[a]!, {r6, r7}\n\t"
  8348. "LDM %[b]!, {r8, r9}\n\t"
  8349. "AND r8, r8, %[m]\n\t"
  8350. "AND r9, r9, %[m]\n\t"
  8351. "ADCS r6, r6, r8\n\t"
  8352. "ADCS r7, r7, r9\n\t"
  8353. "STM %[r]!, {r6, r7}\n\t"
  8354. "LDM %[a]!, {r6, r7}\n\t"
  8355. "LDM %[b]!, {r8, r9}\n\t"
  8356. "AND r8, r8, %[m]\n\t"
  8357. "AND r9, r9, %[m]\n\t"
  8358. "ADCS r6, r6, r8\n\t"
  8359. "ADCS r7, r7, r9\n\t"
  8360. "STM %[r]!, {r6, r7}\n\t"
  8361. "LDM %[a]!, {r6, r7}\n\t"
  8362. "LDM %[b]!, {r8, r9}\n\t"
  8363. "AND r8, r8, %[m]\n\t"
  8364. "AND r9, r9, %[m]\n\t"
  8365. "ADCS r6, r6, r8\n\t"
  8366. "ADCS r7, r7, r9\n\t"
  8367. "STM %[r]!, {r6, r7}\n\t"
  8368. "LDM %[a]!, {r6, r7}\n\t"
  8369. "LDM %[b]!, {r8, r9}\n\t"
  8370. "AND r8, r8, %[m]\n\t"
  8371. "AND r9, r9, %[m]\n\t"
  8372. "ADCS r6, r6, r8\n\t"
  8373. "ADCS r7, r7, r9\n\t"
  8374. "STM %[r]!, {r6, r7}\n\t"
  8375. "LDM %[a]!, {r6, r7}\n\t"
  8376. "LDM %[b]!, {r8, r9}\n\t"
  8377. "AND r8, r8, %[m]\n\t"
  8378. "AND r9, r9, %[m]\n\t"
  8379. "ADCS r6, r6, r8\n\t"
  8380. "ADCS r7, r7, r9\n\t"
  8381. "STM %[r]!, {r6, r7}\n\t"
  8382. "LDM %[a]!, {r6, r7}\n\t"
  8383. "LDM %[b]!, {r8, r9}\n\t"
  8384. "AND r8, r8, %[m]\n\t"
  8385. "AND r9, r9, %[m]\n\t"
  8386. "ADCS r6, r6, r8\n\t"
  8387. "ADCS r7, r7, r9\n\t"
  8388. "STM %[r]!, {r6, r7}\n\t"
  8389. "LDM %[a]!, {r6, r7}\n\t"
  8390. "LDM %[b]!, {r8, r9}\n\t"
  8391. "AND r8, r8, %[m]\n\t"
  8392. "AND r9, r9, %[m]\n\t"
  8393. "ADCS r6, r6, r8\n\t"
  8394. "ADCS r7, r7, r9\n\t"
  8395. "STM %[r]!, {r6, r7}\n\t"
  8396. "LDM %[a]!, {r6, r7}\n\t"
  8397. "LDM %[b]!, {r8, r9}\n\t"
  8398. "AND r8, r8, %[m]\n\t"
  8399. "AND r9, r9, %[m]\n\t"
  8400. "ADCS r6, r6, r8\n\t"
  8401. "ADCS r7, r7, r9\n\t"
  8402. "STM %[r]!, {r6, r7}\n\t"
  8403. "LDM %[a]!, {r6, r7}\n\t"
  8404. "LDM %[b]!, {r8, r9}\n\t"
  8405. "AND r8, r8, %[m]\n\t"
  8406. "AND r9, r9, %[m]\n\t"
  8407. "ADCS r6, r6, r8\n\t"
  8408. "ADCS r7, r7, r9\n\t"
  8409. "STM %[r]!, {r6, r7}\n\t"
  8410. "LDM %[a]!, {r6, r7}\n\t"
  8411. "LDM %[b]!, {r8, r9}\n\t"
  8412. "AND r8, r8, %[m]\n\t"
  8413. "AND r9, r9, %[m]\n\t"
  8414. "ADCS r6, r6, r8\n\t"
  8415. "ADCS r7, r7, r9\n\t"
  8416. "STM %[r]!, {r6, r7}\n\t"
  8417. "LDM %[a]!, {r6, r7}\n\t"
  8418. "LDM %[b]!, {r8, r9}\n\t"
  8419. "AND r8, r8, %[m]\n\t"
  8420. "AND r9, r9, %[m]\n\t"
  8421. "ADCS r6, r6, r8\n\t"
  8422. "ADCS r7, r7, r9\n\t"
  8423. "STM %[r]!, {r6, r7}\n\t"
  8424. "LDM %[a]!, {r6, r7}\n\t"
  8425. "LDM %[b]!, {r8, r9}\n\t"
  8426. "AND r8, r8, %[m]\n\t"
  8427. "AND r9, r9, %[m]\n\t"
  8428. "ADCS r6, r6, r8\n\t"
  8429. "ADCS r7, r7, r9\n\t"
  8430. "STM %[r]!, {r6, r7}\n\t"
  8431. "LDM %[a]!, {r6, r7}\n\t"
  8432. "LDM %[b]!, {r8, r9}\n\t"
  8433. "AND r8, r8, %[m]\n\t"
  8434. "AND r9, r9, %[m]\n\t"
  8435. "ADCS r6, r6, r8\n\t"
  8436. "ADCS r7, r7, r9\n\t"
  8437. "STM %[r]!, {r6, r7}\n\t"
  8438. "LDM %[a]!, {r6, r7}\n\t"
  8439. "LDM %[b]!, {r8, r9}\n\t"
  8440. "AND r8, r8, %[m]\n\t"
  8441. "AND r9, r9, %[m]\n\t"
  8442. "ADCS r6, r6, r8\n\t"
  8443. "ADCS r7, r7, r9\n\t"
  8444. "STM %[r]!, {r6, r7}\n\t"
  8445. "LDM %[a]!, {r6, r7}\n\t"
  8446. "LDM %[b]!, {r8, r9}\n\t"
  8447. "AND r8, r8, %[m]\n\t"
  8448. "AND r9, r9, %[m]\n\t"
  8449. "ADCS r6, r6, r8\n\t"
  8450. "ADCS r7, r7, r9\n\t"
  8451. "STM %[r]!, {r6, r7}\n\t"
  8452. "ADC %[r], r10, r10\n\t"
  8453. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  8454. :
  8455. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  8456. );
  8457. return (uint32_t)(size_t)r;
  8458. }
  8459. #endif /* WOLFSSL_SP_SMALL */
  8460. /* RSA private key operation.
  8461. *
  8462. * in Array of bytes representing the number to exponentiate, base.
  8463. * inLen Number of bytes in base.
  8464. * dm Private exponent.
  8465. * pm First prime.
  8466. * qm Second prime.
  8467. * dpm First prime's CRT exponent.
  8468. * dqm Second prime's CRT exponent.
  8469. * qim Inverse of second prime mod p.
  8470. * mm Modulus.
  8471. * out Buffer to hold big-endian bytes of exponentiation result.
  8472. * Must be at least 256 bytes long.
  8473. * outLen Number of bytes in result.
  8474. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  8475. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  8476. */
  8477. int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
  8478. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  8479. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  8480. {
  8481. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  8482. #ifdef WOLFSSL_SP_SMALL_STACK
  8483. sp_digit* d = NULL;
  8484. #else
  8485. sp_digit d[64 * 4];
  8486. #endif
  8487. sp_digit* a = NULL;
  8488. sp_digit* m = NULL;
  8489. sp_digit* r = NULL;
  8490. int err = MP_OKAY;
  8491. (void)pm;
  8492. (void)qm;
  8493. (void)dpm;
  8494. (void)dqm;
  8495. (void)qim;
  8496. if (*outLen < 256U) {
  8497. err = MP_TO_E;
  8498. }
  8499. if (err == MP_OKAY) {
  8500. if (mp_count_bits(dm) > 2048) {
  8501. err = MP_READ_E;
  8502. }
  8503. else if (inLen > 256) {
  8504. err = MP_READ_E;
  8505. }
  8506. else if (mp_count_bits(mm) != 2048) {
  8507. err = MP_READ_E;
  8508. }
  8509. else if (mp_iseven(mm)) {
  8510. err = MP_VAL;
  8511. }
  8512. }
  8513. #ifdef WOLFSSL_SP_SMALL_STACK
  8514. if (err == MP_OKAY) {
  8515. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL,
  8516. DYNAMIC_TYPE_RSA);
  8517. if (d == NULL)
  8518. err = MEMORY_E;
  8519. }
  8520. #endif
  8521. if (err == MP_OKAY) {
  8522. a = d + 64;
  8523. m = a + 128;
  8524. r = a;
  8525. sp_2048_from_bin(a, 64, in, inLen);
  8526. sp_2048_from_mp(d, 64, dm);
  8527. sp_2048_from_mp(m, 64, mm);
  8528. err = sp_2048_mod_exp_64(r, a, d, 2048, m, 0);
  8529. }
  8530. if (err == MP_OKAY) {
  8531. sp_2048_to_bin_64(r, out);
  8532. *outLen = 256;
  8533. }
  8534. #ifdef WOLFSSL_SP_SMALL_STACK
  8535. if (d != NULL)
  8536. #endif
  8537. {
  8538. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  8539. if (a != NULL)
  8540. ForceZero(a, sizeof(sp_digit) * 64);
  8541. #ifdef WOLFSSL_SP_SMALL_STACK
  8542. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  8543. #endif
  8544. }
  8545. return err;
  8546. #else
  8547. #ifdef WOLFSSL_SP_SMALL_STACK
  8548. sp_digit* a = NULL;
  8549. #else
  8550. sp_digit a[32 * 11];
  8551. #endif
  8552. sp_digit* p = NULL;
  8553. sp_digit* q = NULL;
  8554. sp_digit* dp = NULL;
  8555. sp_digit* tmpa = NULL;
  8556. sp_digit* tmpb = NULL;
  8557. sp_digit* r = NULL;
  8558. sp_digit* qi = NULL;
  8559. sp_digit* dq = NULL;
  8560. sp_digit c;
  8561. int err = MP_OKAY;
  8562. (void)dm;
  8563. (void)mm;
  8564. if (*outLen < 256) {
  8565. err = MP_TO_E;
  8566. }
  8567. else if (inLen > 256 || mp_count_bits(mm) != 2048) {
  8568. err = MP_READ_E;
  8569. }
  8570. else if (mp_iseven(mm)) {
  8571. err = MP_VAL;
  8572. }
  8573. else if (mp_iseven(pm)) {
  8574. err = MP_VAL;
  8575. }
  8576. else if (mp_iseven(qm)) {
  8577. err = MP_VAL;
  8578. }
  8579. #ifdef WOLFSSL_SP_SMALL_STACK
  8580. if (err == MP_OKAY) {
  8581. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL,
  8582. DYNAMIC_TYPE_RSA);
  8583. if (a == NULL)
  8584. err = MEMORY_E;
  8585. }
  8586. #endif
  8587. if (err == MP_OKAY) {
  8588. p = a + 64 * 2;
  8589. q = p + 32;
  8590. qi = dq = dp = q + 32;
  8591. tmpa = qi + 32;
  8592. tmpb = tmpa + 64;
  8593. r = a;
  8594. sp_2048_from_bin(a, 64, in, inLen);
  8595. sp_2048_from_mp(p, 32, pm);
  8596. sp_2048_from_mp(q, 32, qm);
  8597. sp_2048_from_mp(dp, 32, dpm);
  8598. err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1);
  8599. }
  8600. if (err == MP_OKAY) {
  8601. sp_2048_from_mp(dq, 32, dqm);
  8602. err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1);
  8603. }
  8604. if (err == MP_OKAY) {
  8605. c = sp_2048_sub_in_place_32(tmpa, tmpb);
  8606. c += sp_2048_cond_add_32(tmpa, tmpa, p, c);
  8607. sp_2048_cond_add_32(tmpa, tmpa, p, c);
  8608. sp_2048_from_mp(qi, 32, qim);
  8609. sp_2048_mul_32(tmpa, tmpa, qi);
  8610. err = sp_2048_mod_32(tmpa, tmpa, p);
  8611. }
  8612. if (err == MP_OKAY) {
  8613. sp_2048_mul_32(tmpa, q, tmpa);
  8614. XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32);
  8615. sp_2048_add_64(r, tmpb, tmpa);
  8616. sp_2048_to_bin_64(r, out);
  8617. *outLen = 256;
  8618. }
  8619. #ifdef WOLFSSL_SP_SMALL_STACK
  8620. if (a != NULL)
  8621. #endif
  8622. {
  8623. ForceZero(a, sizeof(sp_digit) * 32 * 11);
  8624. #ifdef WOLFSSL_SP_SMALL_STACK
  8625. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  8626. #endif
  8627. }
  8628. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  8629. return err;
  8630. }
  8631. #endif /* WOLFSSL_RSA_PUBLIC_ONLY */
  8632. #endif /* WOLFSSL_HAVE_SP_RSA */
  8633. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  8634. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  8635. /* Convert an array of sp_digit to an mp_int.
  8636. *
  8637. * a A single precision integer.
  8638. * r A multi-precision integer.
  8639. */
  8640. static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
  8641. {
  8642. int err;
  8643. err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
  8644. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  8645. #if DIGIT_BIT == 32
  8646. XMEMCPY(r->dp, a, sizeof(sp_digit) * 64);
  8647. r->used = 64;
  8648. mp_clamp(r);
  8649. #elif DIGIT_BIT < 32
  8650. int i;
  8651. int j = 0;
  8652. int s = 0;
  8653. r->dp[0] = 0;
  8654. for (i = 0; i < 64; i++) {
  8655. r->dp[j] |= (mp_digit)(a[i] << s);
  8656. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  8657. s = DIGIT_BIT - s;
  8658. r->dp[++j] = (mp_digit)(a[i] >> s);
  8659. while (s + DIGIT_BIT <= 32) {
  8660. s += DIGIT_BIT;
  8661. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  8662. if (s == SP_WORD_SIZE) {
  8663. r->dp[j] = 0;
  8664. }
  8665. else {
  8666. r->dp[j] = (mp_digit)(a[i] >> s);
  8667. }
  8668. }
  8669. s = 32 - s;
  8670. }
  8671. r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
  8672. mp_clamp(r);
  8673. #else
  8674. int i;
  8675. int j = 0;
  8676. int s = 0;
  8677. r->dp[0] = 0;
  8678. for (i = 0; i < 64; i++) {
  8679. r->dp[j] |= ((mp_digit)a[i]) << s;
  8680. if (s + 32 >= DIGIT_BIT) {
  8681. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  8682. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  8683. #endif
  8684. s = DIGIT_BIT - s;
  8685. r->dp[++j] = a[i] >> s;
  8686. s = 32 - s;
  8687. }
  8688. else {
  8689. s += 32;
  8690. }
  8691. }
  8692. r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
  8693. mp_clamp(r);
  8694. #endif
  8695. }
  8696. return err;
  8697. }
  8698. /* Perform the modular exponentiation for Diffie-Hellman.
  8699. *
  8700. * base Base. MP integer.
  8701. * exp Exponent. MP integer.
  8702. * mod Modulus. MP integer.
  8703. * res Result. MP integer.
  8704. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  8705. * and MEMORY_E if memory allocation fails.
  8706. */
  8707. int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
  8708. mp_int* res)
  8709. {
  8710. int err = MP_OKAY;
  8711. sp_digit b[128];
  8712. sp_digit e[64];
  8713. sp_digit m[64];
  8714. sp_digit* r = b;
  8715. int expBits = mp_count_bits(exp);
  8716. if (mp_count_bits(base) > 2048) {
  8717. err = MP_READ_E;
  8718. }
  8719. else if (expBits > 2048) {
  8720. err = MP_READ_E;
  8721. }
  8722. else if (mp_count_bits(mod) != 2048) {
  8723. err = MP_READ_E;
  8724. }
  8725. else if (mp_iseven(mod)) {
  8726. err = MP_VAL;
  8727. }
  8728. if (err == MP_OKAY) {
  8729. sp_2048_from_mp(b, 64, base);
  8730. sp_2048_from_mp(e, 64, exp);
  8731. sp_2048_from_mp(m, 64, mod);
  8732. err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0);
  8733. }
  8734. if (err == MP_OKAY) {
  8735. err = sp_2048_to_mp(r, res);
  8736. }
  8737. XMEMSET(e, 0, sizeof(e));
  8738. return err;
  8739. }
  8740. #ifdef WOLFSSL_HAVE_SP_DH
  8741. #ifdef HAVE_FFDHE_2048
  8742. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  8743. static void sp_2048_lshift_64(sp_digit* r_p, const sp_digit* a_p, byte n_p)
  8744. #else
  8745. static void sp_2048_lshift_64(sp_digit* r, const sp_digit* a, byte n)
  8746. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  8747. {
  8748. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  8749. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  8750. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  8751. register byte n __asm__ ("r2") = (byte)n_p;
  8752. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  8753. __asm__ __volatile__ (
  8754. "RSB r7, %[n], #0x1f\n\t"
  8755. "LDR r5, [%[a], #252]\n\t"
  8756. "LSR r6, r5, #1\n\t"
  8757. "LSL r5, r5, %[n]\n\t"
  8758. "LSR r6, r6, r7\n\t"
  8759. "LDR r4, [%[a], #248]\n\t"
  8760. "STR r6, [%[r], #256]\n\t"
  8761. "LSR r3, r4, #1\n\t"
  8762. "LSL r4, r4, %[n]\n\t"
  8763. "LSR r3, r3, r7\n\t"
  8764. "ORR r5, r5, r3\n\t"
  8765. "LDR r6, [%[a], #244]\n\t"
  8766. "STR r5, [%[r], #252]\n\t"
  8767. "LSR r3, r6, #1\n\t"
  8768. "LSL r6, r6, %[n]\n\t"
  8769. "LSR r3, r3, r7\n\t"
  8770. "ORR r4, r4, r3\n\t"
  8771. "LDR r5, [%[a], #240]\n\t"
  8772. "STR r4, [%[r], #248]\n\t"
  8773. "LSR r3, r5, #1\n\t"
  8774. "LSL r5, r5, %[n]\n\t"
  8775. "LSR r3, r3, r7\n\t"
  8776. "ORR r6, r6, r3\n\t"
  8777. "LDR r4, [%[a], #236]\n\t"
  8778. "STR r6, [%[r], #244]\n\t"
  8779. "LSR r3, r4, #1\n\t"
  8780. "LSL r4, r4, %[n]\n\t"
  8781. "LSR r3, r3, r7\n\t"
  8782. "ORR r5, r5, r3\n\t"
  8783. "LDR r6, [%[a], #232]\n\t"
  8784. "STR r5, [%[r], #240]\n\t"
  8785. "LSR r3, r6, #1\n\t"
  8786. "LSL r6, r6, %[n]\n\t"
  8787. "LSR r3, r3, r7\n\t"
  8788. "ORR r4, r4, r3\n\t"
  8789. "LDR r5, [%[a], #228]\n\t"
  8790. "STR r4, [%[r], #236]\n\t"
  8791. "LSR r3, r5, #1\n\t"
  8792. "LSL r5, r5, %[n]\n\t"
  8793. "LSR r3, r3, r7\n\t"
  8794. "ORR r6, r6, r3\n\t"
  8795. "LDR r4, [%[a], #224]\n\t"
  8796. "STR r6, [%[r], #232]\n\t"
  8797. "LSR r3, r4, #1\n\t"
  8798. "LSL r4, r4, %[n]\n\t"
  8799. "LSR r3, r3, r7\n\t"
  8800. "ORR r5, r5, r3\n\t"
  8801. "LDR r6, [%[a], #220]\n\t"
  8802. "STR r5, [%[r], #228]\n\t"
  8803. "LSR r3, r6, #1\n\t"
  8804. "LSL r6, r6, %[n]\n\t"
  8805. "LSR r3, r3, r7\n\t"
  8806. "ORR r4, r4, r3\n\t"
  8807. "LDR r5, [%[a], #216]\n\t"
  8808. "STR r4, [%[r], #224]\n\t"
  8809. "LSR r3, r5, #1\n\t"
  8810. "LSL r5, r5, %[n]\n\t"
  8811. "LSR r3, r3, r7\n\t"
  8812. "ORR r6, r6, r3\n\t"
  8813. "LDR r4, [%[a], #212]\n\t"
  8814. "STR r6, [%[r], #220]\n\t"
  8815. "LSR r3, r4, #1\n\t"
  8816. "LSL r4, r4, %[n]\n\t"
  8817. "LSR r3, r3, r7\n\t"
  8818. "ORR r5, r5, r3\n\t"
  8819. "LDR r6, [%[a], #208]\n\t"
  8820. "STR r5, [%[r], #216]\n\t"
  8821. "LSR r3, r6, #1\n\t"
  8822. "LSL r6, r6, %[n]\n\t"
  8823. "LSR r3, r3, r7\n\t"
  8824. "ORR r4, r4, r3\n\t"
  8825. "LDR r5, [%[a], #204]\n\t"
  8826. "STR r4, [%[r], #212]\n\t"
  8827. "LSR r3, r5, #1\n\t"
  8828. "LSL r5, r5, %[n]\n\t"
  8829. "LSR r3, r3, r7\n\t"
  8830. "ORR r6, r6, r3\n\t"
  8831. "LDR r4, [%[a], #200]\n\t"
  8832. "STR r6, [%[r], #208]\n\t"
  8833. "LSR r3, r4, #1\n\t"
  8834. "LSL r4, r4, %[n]\n\t"
  8835. "LSR r3, r3, r7\n\t"
  8836. "ORR r5, r5, r3\n\t"
  8837. "LDR r6, [%[a], #196]\n\t"
  8838. "STR r5, [%[r], #204]\n\t"
  8839. "LSR r3, r6, #1\n\t"
  8840. "LSL r6, r6, %[n]\n\t"
  8841. "LSR r3, r3, r7\n\t"
  8842. "ORR r4, r4, r3\n\t"
  8843. "LDR r5, [%[a], #192]\n\t"
  8844. "STR r4, [%[r], #200]\n\t"
  8845. "LSR r3, r5, #1\n\t"
  8846. "LSL r5, r5, %[n]\n\t"
  8847. "LSR r3, r3, r7\n\t"
  8848. "ORR r6, r6, r3\n\t"
  8849. "LDR r4, [%[a], #188]\n\t"
  8850. "STR r6, [%[r], #196]\n\t"
  8851. "LSR r3, r4, #1\n\t"
  8852. "LSL r4, r4, %[n]\n\t"
  8853. "LSR r3, r3, r7\n\t"
  8854. "ORR r5, r5, r3\n\t"
  8855. "LDR r6, [%[a], #184]\n\t"
  8856. "STR r5, [%[r], #192]\n\t"
  8857. "LSR r3, r6, #1\n\t"
  8858. "LSL r6, r6, %[n]\n\t"
  8859. "LSR r3, r3, r7\n\t"
  8860. "ORR r4, r4, r3\n\t"
  8861. "LDR r5, [%[a], #180]\n\t"
  8862. "STR r4, [%[r], #188]\n\t"
  8863. "LSR r3, r5, #1\n\t"
  8864. "LSL r5, r5, %[n]\n\t"
  8865. "LSR r3, r3, r7\n\t"
  8866. "ORR r6, r6, r3\n\t"
  8867. "LDR r4, [%[a], #176]\n\t"
  8868. "STR r6, [%[r], #184]\n\t"
  8869. "LSR r3, r4, #1\n\t"
  8870. "LSL r4, r4, %[n]\n\t"
  8871. "LSR r3, r3, r7\n\t"
  8872. "ORR r5, r5, r3\n\t"
  8873. "LDR r6, [%[a], #172]\n\t"
  8874. "STR r5, [%[r], #180]\n\t"
  8875. "LSR r3, r6, #1\n\t"
  8876. "LSL r6, r6, %[n]\n\t"
  8877. "LSR r3, r3, r7\n\t"
  8878. "ORR r4, r4, r3\n\t"
  8879. "LDR r5, [%[a], #168]\n\t"
  8880. "STR r4, [%[r], #176]\n\t"
  8881. "LSR r3, r5, #1\n\t"
  8882. "LSL r5, r5, %[n]\n\t"
  8883. "LSR r3, r3, r7\n\t"
  8884. "ORR r6, r6, r3\n\t"
  8885. "LDR r4, [%[a], #164]\n\t"
  8886. "STR r6, [%[r], #172]\n\t"
  8887. "LSR r3, r4, #1\n\t"
  8888. "LSL r4, r4, %[n]\n\t"
  8889. "LSR r3, r3, r7\n\t"
  8890. "ORR r5, r5, r3\n\t"
  8891. "LDR r6, [%[a], #160]\n\t"
  8892. "STR r5, [%[r], #168]\n\t"
  8893. "LSR r3, r6, #1\n\t"
  8894. "LSL r6, r6, %[n]\n\t"
  8895. "LSR r3, r3, r7\n\t"
  8896. "ORR r4, r4, r3\n\t"
  8897. "LDR r5, [%[a], #156]\n\t"
  8898. "STR r4, [%[r], #164]\n\t"
  8899. "LSR r3, r5, #1\n\t"
  8900. "LSL r5, r5, %[n]\n\t"
  8901. "LSR r3, r3, r7\n\t"
  8902. "ORR r6, r6, r3\n\t"
  8903. "LDR r4, [%[a], #152]\n\t"
  8904. "STR r6, [%[r], #160]\n\t"
  8905. "LSR r3, r4, #1\n\t"
  8906. "LSL r4, r4, %[n]\n\t"
  8907. "LSR r3, r3, r7\n\t"
  8908. "ORR r5, r5, r3\n\t"
  8909. "LDR r6, [%[a], #148]\n\t"
  8910. "STR r5, [%[r], #156]\n\t"
  8911. "LSR r3, r6, #1\n\t"
  8912. "LSL r6, r6, %[n]\n\t"
  8913. "LSR r3, r3, r7\n\t"
  8914. "ORR r4, r4, r3\n\t"
  8915. "LDR r5, [%[a], #144]\n\t"
  8916. "STR r4, [%[r], #152]\n\t"
  8917. "LSR r3, r5, #1\n\t"
  8918. "LSL r5, r5, %[n]\n\t"
  8919. "LSR r3, r3, r7\n\t"
  8920. "ORR r6, r6, r3\n\t"
  8921. "LDR r4, [%[a], #140]\n\t"
  8922. "STR r6, [%[r], #148]\n\t"
  8923. "LSR r3, r4, #1\n\t"
  8924. "LSL r4, r4, %[n]\n\t"
  8925. "LSR r3, r3, r7\n\t"
  8926. "ORR r5, r5, r3\n\t"
  8927. "LDR r6, [%[a], #136]\n\t"
  8928. "STR r5, [%[r], #144]\n\t"
  8929. "LSR r3, r6, #1\n\t"
  8930. "LSL r6, r6, %[n]\n\t"
  8931. "LSR r3, r3, r7\n\t"
  8932. "ORR r4, r4, r3\n\t"
  8933. "LDR r5, [%[a], #132]\n\t"
  8934. "STR r4, [%[r], #140]\n\t"
  8935. "LSR r3, r5, #1\n\t"
  8936. "LSL r5, r5, %[n]\n\t"
  8937. "LSR r3, r3, r7\n\t"
  8938. "ORR r6, r6, r3\n\t"
  8939. "LDR r4, [%[a], #128]\n\t"
  8940. "STR r6, [%[r], #136]\n\t"
  8941. "LSR r3, r4, #1\n\t"
  8942. "LSL r4, r4, %[n]\n\t"
  8943. "LSR r3, r3, r7\n\t"
  8944. "ORR r5, r5, r3\n\t"
  8945. "LDR r6, [%[a], #124]\n\t"
  8946. "STR r5, [%[r], #132]\n\t"
  8947. "LSR r3, r6, #1\n\t"
  8948. "LSL r6, r6, %[n]\n\t"
  8949. "LSR r3, r3, r7\n\t"
  8950. "ORR r4, r4, r3\n\t"
  8951. "LDR r5, [%[a], #120]\n\t"
  8952. "STR r4, [%[r], #128]\n\t"
  8953. "LSR r3, r5, #1\n\t"
  8954. "LSL r5, r5, %[n]\n\t"
  8955. "LSR r3, r3, r7\n\t"
  8956. "ORR r6, r6, r3\n\t"
  8957. "LDR r4, [%[a], #116]\n\t"
  8958. "STR r6, [%[r], #124]\n\t"
  8959. "LSR r3, r4, #1\n\t"
  8960. "LSL r4, r4, %[n]\n\t"
  8961. "LSR r3, r3, r7\n\t"
  8962. "ORR r5, r5, r3\n\t"
  8963. "LDR r6, [%[a], #112]\n\t"
  8964. "STR r5, [%[r], #120]\n\t"
  8965. "LSR r3, r6, #1\n\t"
  8966. "LSL r6, r6, %[n]\n\t"
  8967. "LSR r3, r3, r7\n\t"
  8968. "ORR r4, r4, r3\n\t"
  8969. "LDR r5, [%[a], #108]\n\t"
  8970. "STR r4, [%[r], #116]\n\t"
  8971. "LSR r3, r5, #1\n\t"
  8972. "LSL r5, r5, %[n]\n\t"
  8973. "LSR r3, r3, r7\n\t"
  8974. "ORR r6, r6, r3\n\t"
  8975. "LDR r4, [%[a], #104]\n\t"
  8976. "STR r6, [%[r], #112]\n\t"
  8977. "LSR r3, r4, #1\n\t"
  8978. "LSL r4, r4, %[n]\n\t"
  8979. "LSR r3, r3, r7\n\t"
  8980. "ORR r5, r5, r3\n\t"
  8981. "LDR r6, [%[a], #100]\n\t"
  8982. "STR r5, [%[r], #108]\n\t"
  8983. "LSR r3, r6, #1\n\t"
  8984. "LSL r6, r6, %[n]\n\t"
  8985. "LSR r3, r3, r7\n\t"
  8986. "ORR r4, r4, r3\n\t"
  8987. "LDR r5, [%[a], #96]\n\t"
  8988. "STR r4, [%[r], #104]\n\t"
  8989. "LSR r3, r5, #1\n\t"
  8990. "LSL r5, r5, %[n]\n\t"
  8991. "LSR r3, r3, r7\n\t"
  8992. "ORR r6, r6, r3\n\t"
  8993. "LDR r4, [%[a], #92]\n\t"
  8994. "STR r6, [%[r], #100]\n\t"
  8995. "LSR r3, r4, #1\n\t"
  8996. "LSL r4, r4, %[n]\n\t"
  8997. "LSR r3, r3, r7\n\t"
  8998. "ORR r5, r5, r3\n\t"
  8999. "LDR r6, [%[a], #88]\n\t"
  9000. "STR r5, [%[r], #96]\n\t"
  9001. "LSR r3, r6, #1\n\t"
  9002. "LSL r6, r6, %[n]\n\t"
  9003. "LSR r3, r3, r7\n\t"
  9004. "ORR r4, r4, r3\n\t"
  9005. "LDR r5, [%[a], #84]\n\t"
  9006. "STR r4, [%[r], #92]\n\t"
  9007. "LSR r3, r5, #1\n\t"
  9008. "LSL r5, r5, %[n]\n\t"
  9009. "LSR r3, r3, r7\n\t"
  9010. "ORR r6, r6, r3\n\t"
  9011. "LDR r4, [%[a], #80]\n\t"
  9012. "STR r6, [%[r], #88]\n\t"
  9013. "LSR r3, r4, #1\n\t"
  9014. "LSL r4, r4, %[n]\n\t"
  9015. "LSR r3, r3, r7\n\t"
  9016. "ORR r5, r5, r3\n\t"
  9017. "LDR r6, [%[a], #76]\n\t"
  9018. "STR r5, [%[r], #84]\n\t"
  9019. "LSR r3, r6, #1\n\t"
  9020. "LSL r6, r6, %[n]\n\t"
  9021. "LSR r3, r3, r7\n\t"
  9022. "ORR r4, r4, r3\n\t"
  9023. "LDR r5, [%[a], #72]\n\t"
  9024. "STR r4, [%[r], #80]\n\t"
  9025. "LSR r3, r5, #1\n\t"
  9026. "LSL r5, r5, %[n]\n\t"
  9027. "LSR r3, r3, r7\n\t"
  9028. "ORR r6, r6, r3\n\t"
  9029. "LDR r4, [%[a], #68]\n\t"
  9030. "STR r6, [%[r], #76]\n\t"
  9031. "LSR r3, r4, #1\n\t"
  9032. "LSL r4, r4, %[n]\n\t"
  9033. "LSR r3, r3, r7\n\t"
  9034. "ORR r5, r5, r3\n\t"
  9035. "LDR r6, [%[a], #64]\n\t"
  9036. "STR r5, [%[r], #72]\n\t"
  9037. "LSR r3, r6, #1\n\t"
  9038. "LSL r6, r6, %[n]\n\t"
  9039. "LSR r3, r3, r7\n\t"
  9040. "ORR r4, r4, r3\n\t"
  9041. "LDR r5, [%[a], #60]\n\t"
  9042. "STR r4, [%[r], #68]\n\t"
  9043. "LSR r3, r5, #1\n\t"
  9044. "LSL r5, r5, %[n]\n\t"
  9045. "LSR r3, r3, r7\n\t"
  9046. "ORR r6, r6, r3\n\t"
  9047. "LDR r4, [%[a], #56]\n\t"
  9048. "STR r6, [%[r], #64]\n\t"
  9049. "LSR r3, r4, #1\n\t"
  9050. "LSL r4, r4, %[n]\n\t"
  9051. "LSR r3, r3, r7\n\t"
  9052. "ORR r5, r5, r3\n\t"
  9053. "LDR r6, [%[a], #52]\n\t"
  9054. "STR r5, [%[r], #60]\n\t"
  9055. "LSR r3, r6, #1\n\t"
  9056. "LSL r6, r6, %[n]\n\t"
  9057. "LSR r3, r3, r7\n\t"
  9058. "ORR r4, r4, r3\n\t"
  9059. "LDR r5, [%[a], #48]\n\t"
  9060. "STR r4, [%[r], #56]\n\t"
  9061. "LSR r3, r5, #1\n\t"
  9062. "LSL r5, r5, %[n]\n\t"
  9063. "LSR r3, r3, r7\n\t"
  9064. "ORR r6, r6, r3\n\t"
  9065. "LDR r4, [%[a], #44]\n\t"
  9066. "STR r6, [%[r], #52]\n\t"
  9067. "LSR r3, r4, #1\n\t"
  9068. "LSL r4, r4, %[n]\n\t"
  9069. "LSR r3, r3, r7\n\t"
  9070. "ORR r5, r5, r3\n\t"
  9071. "LDR r6, [%[a], #40]\n\t"
  9072. "STR r5, [%[r], #48]\n\t"
  9073. "LSR r3, r6, #1\n\t"
  9074. "LSL r6, r6, %[n]\n\t"
  9075. "LSR r3, r3, r7\n\t"
  9076. "ORR r4, r4, r3\n\t"
  9077. "LDR r5, [%[a], #36]\n\t"
  9078. "STR r4, [%[r], #44]\n\t"
  9079. "LSR r3, r5, #1\n\t"
  9080. "LSL r5, r5, %[n]\n\t"
  9081. "LSR r3, r3, r7\n\t"
  9082. "ORR r6, r6, r3\n\t"
  9083. "LDR r4, [%[a], #32]\n\t"
  9084. "STR r6, [%[r], #40]\n\t"
  9085. "LSR r3, r4, #1\n\t"
  9086. "LSL r4, r4, %[n]\n\t"
  9087. "LSR r3, r3, r7\n\t"
  9088. "ORR r5, r5, r3\n\t"
  9089. "LDR r6, [%[a], #28]\n\t"
  9090. "STR r5, [%[r], #36]\n\t"
  9091. "LSR r3, r6, #1\n\t"
  9092. "LSL r6, r6, %[n]\n\t"
  9093. "LSR r3, r3, r7\n\t"
  9094. "ORR r4, r4, r3\n\t"
  9095. "LDR r5, [%[a], #24]\n\t"
  9096. "STR r4, [%[r], #32]\n\t"
  9097. "LSR r3, r5, #1\n\t"
  9098. "LSL r5, r5, %[n]\n\t"
  9099. "LSR r3, r3, r7\n\t"
  9100. "ORR r6, r6, r3\n\t"
  9101. "LDR r4, [%[a], #20]\n\t"
  9102. "STR r6, [%[r], #28]\n\t"
  9103. "LSR r3, r4, #1\n\t"
  9104. "LSL r4, r4, %[n]\n\t"
  9105. "LSR r3, r3, r7\n\t"
  9106. "ORR r5, r5, r3\n\t"
  9107. "LDR r6, [%[a], #16]\n\t"
  9108. "STR r5, [%[r], #24]\n\t"
  9109. "LSR r3, r6, #1\n\t"
  9110. "LSL r6, r6, %[n]\n\t"
  9111. "LSR r3, r3, r7\n\t"
  9112. "ORR r4, r4, r3\n\t"
  9113. "LDR r5, [%[a], #12]\n\t"
  9114. "STR r4, [%[r], #20]\n\t"
  9115. "LSR r3, r5, #1\n\t"
  9116. "LSL r5, r5, %[n]\n\t"
  9117. "LSR r3, r3, r7\n\t"
  9118. "ORR r6, r6, r3\n\t"
  9119. "LDR r4, [%[a], #8]\n\t"
  9120. "STR r6, [%[r], #16]\n\t"
  9121. "LSR r3, r4, #1\n\t"
  9122. "LSL r4, r4, %[n]\n\t"
  9123. "LSR r3, r3, r7\n\t"
  9124. "ORR r5, r5, r3\n\t"
  9125. "LDR r6, [%[a], #4]\n\t"
  9126. "STR r5, [%[r], #12]\n\t"
  9127. "LSR r3, r6, #1\n\t"
  9128. "LSL r6, r6, %[n]\n\t"
  9129. "LSR r3, r3, r7\n\t"
  9130. "ORR r4, r4, r3\n\t"
  9131. "LDR r5, [%[a]]\n\t"
  9132. "STR r4, [%[r], #8]\n\t"
  9133. "LSR r3, r5, #1\n\t"
  9134. "LSL r5, r5, %[n]\n\t"
  9135. "LSR r3, r3, r7\n\t"
  9136. "ORR r6, r6, r3\n\t"
  9137. "STR r5, [%[r]]\n\t"
  9138. "STR r6, [%[r], #4]\n\t"
  9139. : [r] "+r" (r), [a] "+r" (a), [n] "+r" (n)
  9140. :
  9141. : "memory", "r4", "r5", "r6", "r3", "r7", "cc"
  9142. );
  9143. }
  9144. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  9145. *
  9146. * r A single precision number that is the result of the operation.
  9147. * e A single precision number that is the exponent.
  9148. * bits The number of bits in the exponent.
  9149. * m A single precision number that is the modulus.
  9150. * returns 0 on success.
  9151. * returns MEMORY_E on dynamic memory allocation failure.
  9152. * returns MP_VAL when base is even.
  9153. */
  9154. static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits,
  9155. const sp_digit* m)
  9156. {
  9157. #ifdef WOLFSSL_SP_SMALL_STACK
  9158. sp_digit* td = NULL;
  9159. #else
  9160. sp_digit td[193];
  9161. #endif
  9162. sp_digit* norm = NULL;
  9163. sp_digit* tmp = NULL;
  9164. sp_digit mp = 1;
  9165. sp_digit n;
  9166. sp_digit o;
  9167. sp_digit mask;
  9168. int i;
  9169. int c;
  9170. byte y;
  9171. int err = MP_OKAY;
  9172. if (bits == 0) {
  9173. err = MP_VAL;
  9174. }
  9175. #ifdef WOLFSSL_SP_SMALL_STACK
  9176. if (err == MP_OKAY) {
  9177. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL,
  9178. DYNAMIC_TYPE_TMP_BUFFER);
  9179. if (td == NULL)
  9180. err = MEMORY_E;
  9181. }
  9182. #endif
  9183. if (err == MP_OKAY) {
  9184. norm = td;
  9185. tmp = td + 128;
  9186. sp_2048_mont_setup(m, &mp);
  9187. sp_2048_mont_norm_64(norm, m);
  9188. i = (bits - 1) / 32;
  9189. n = e[i--];
  9190. c = bits & 31;
  9191. if (c == 0) {
  9192. c = 32;
  9193. }
  9194. c -= bits % 5;
  9195. if (c == 32) {
  9196. c = 27;
  9197. }
  9198. if (c < 0) {
  9199. /* Number of bits in top word is less than number needed. */
  9200. c = -c;
  9201. y = (byte)(n << c);
  9202. n = e[i--];
  9203. y |= (byte)(n >> (64 - c));
  9204. n <<= c;
  9205. c = 64 - c;
  9206. }
  9207. else if (c == 0) {
  9208. /* All bits in top word used. */
  9209. y = (byte)n;
  9210. }
  9211. else {
  9212. y = (byte)(n >> c);
  9213. n <<= 32 - c;
  9214. }
  9215. sp_2048_lshift_64(r, norm, y);
  9216. for (; i>=0 || c>=5; ) {
  9217. if (c == 0) {
  9218. n = e[i--];
  9219. y = (byte)(n >> 27);
  9220. n <<= 5;
  9221. c = 27;
  9222. }
  9223. else if (c < 5) {
  9224. y = (byte)(n >> 27);
  9225. n = e[i--];
  9226. c = 5 - c;
  9227. y |= (byte)(n >> (32 - c));
  9228. n <<= c;
  9229. c = 32 - c;
  9230. }
  9231. else {
  9232. y = (byte)((n >> 27) & 0x1f);
  9233. n <<= 5;
  9234. c -= 5;
  9235. }
  9236. sp_2048_mont_sqr_64(r, r, m, mp);
  9237. sp_2048_mont_sqr_64(r, r, m, mp);
  9238. sp_2048_mont_sqr_64(r, r, m, mp);
  9239. sp_2048_mont_sqr_64(r, r, m, mp);
  9240. sp_2048_mont_sqr_64(r, r, m, mp);
  9241. sp_2048_lshift_64(r, r, y);
  9242. sp_2048_mul_d_64(tmp, norm, r[64]);
  9243. r[64] = 0;
  9244. o = sp_2048_add_64(r, r, tmp);
  9245. sp_2048_cond_sub_64(r, r, m, (sp_digit)0 - o);
  9246. }
  9247. XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U);
  9248. sp_2048_mont_reduce_64(r, m, mp);
  9249. mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
  9250. sp_2048_cond_sub_64(r, r, m, mask);
  9251. }
  9252. #ifdef WOLFSSL_SP_SMALL_STACK
  9253. if (td != NULL)
  9254. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  9255. #endif
  9256. return err;
  9257. }
  9258. #endif /* HAVE_FFDHE_2048 */
  9259. /* Perform the modular exponentiation for Diffie-Hellman.
  9260. *
  9261. * base Base.
  9262. * exp Array of bytes that is the exponent.
  9263. * expLen Length of data, in bytes, in exponent.
  9264. * mod Modulus.
  9265. * out Buffer to hold big-endian bytes of exponentiation result.
  9266. * Must be at least 256 bytes long.
  9267. * outLen Length, in bytes, of exponentiation result.
  9268. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  9269. * and MEMORY_E if memory allocation fails.
  9270. */
  9271. int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
  9272. const mp_int* mod, byte* out, word32* outLen)
  9273. {
  9274. int err = MP_OKAY;
  9275. sp_digit b[128];
  9276. sp_digit e[64];
  9277. sp_digit m[64];
  9278. sp_digit* r = b;
  9279. word32 i;
  9280. if (mp_count_bits(base) > 2048) {
  9281. err = MP_READ_E;
  9282. }
  9283. else if (expLen > 256) {
  9284. err = MP_READ_E;
  9285. }
  9286. else if (mp_count_bits(mod) != 2048) {
  9287. err = MP_READ_E;
  9288. }
  9289. else if (mp_iseven(mod)) {
  9290. err = MP_VAL;
  9291. }
  9292. if (err == MP_OKAY) {
  9293. sp_2048_from_mp(b, 64, base);
  9294. sp_2048_from_bin(e, 64, exp, expLen);
  9295. sp_2048_from_mp(m, 64, mod);
  9296. #ifdef HAVE_FFDHE_2048
  9297. if (base->used == 1 && base->dp[0] == 2 && m[63] == (sp_digit)-1)
  9298. err = sp_2048_mod_exp_2_64(r, e, expLen * 8, m);
  9299. else
  9300. #endif
  9301. err = sp_2048_mod_exp_64(r, b, e, expLen * 8, m, 0);
  9302. }
  9303. if (err == MP_OKAY) {
  9304. sp_2048_to_bin_64(r, out);
  9305. *outLen = 256;
  9306. for (i=0; i<256 && out[i] == 0; i++) {
  9307. /* Search for first non-zero. */
  9308. }
  9309. *outLen -= i;
  9310. XMEMMOVE(out, out + i, *outLen);
  9311. }
  9312. XMEMSET(e, 0, sizeof(e));
  9313. return err;
  9314. }
  9315. #endif /* WOLFSSL_HAVE_SP_DH */
  9316. /* Perform the modular exponentiation for Diffie-Hellman.
  9317. *
  9318. * base Base. MP integer.
  9319. * exp Exponent. MP integer.
  9320. * mod Modulus. MP integer.
  9321. * res Result. MP integer.
  9322. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  9323. * and MEMORY_E if memory allocation fails.
  9324. */
  9325. int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
  9326. mp_int* res)
  9327. {
  9328. int err = MP_OKAY;
  9329. sp_digit b[64];
  9330. sp_digit e[32];
  9331. sp_digit m[32];
  9332. sp_digit* r = b;
  9333. int expBits = mp_count_bits(exp);
  9334. if (mp_count_bits(base) > 1024) {
  9335. err = MP_READ_E;
  9336. }
  9337. else if (expBits > 1024) {
  9338. err = MP_READ_E;
  9339. }
  9340. else if (mp_count_bits(mod) != 1024) {
  9341. err = MP_READ_E;
  9342. }
  9343. else if (mp_iseven(mod)) {
  9344. err = MP_VAL;
  9345. }
  9346. if (err == MP_OKAY) {
  9347. sp_2048_from_mp(b, 32, base);
  9348. sp_2048_from_mp(e, 32, exp);
  9349. sp_2048_from_mp(m, 32, mod);
  9350. err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0);
  9351. }
  9352. if (err == MP_OKAY) {
  9353. XMEMSET(r + 32, 0, sizeof(*r) * 32U);
  9354. err = sp_2048_to_mp(r, res);
  9355. res->used = mod->used;
  9356. mp_clamp(res);
  9357. }
  9358. XMEMSET(e, 0, sizeof(e));
  9359. return err;
  9360. }
  9361. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  9362. #endif /* !WOLFSSL_SP_NO_2048 */
  9363. #ifndef WOLFSSL_SP_NO_3072
  9364. /* Read big endian unsigned byte array into r.
  9365. *
  9366. * r A single precision integer.
  9367. * size Maximum number of bytes to convert
  9368. * a Byte array.
  9369. * n Number of bytes in array to read.
  9370. */
  9371. static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
  9372. {
  9373. int i;
  9374. int j;
  9375. byte* d;
  9376. for (i = n - 1,j = 0; i >= 3; i -= 4) {
  9377. r[j] = ((sp_digit)a[i - 0] << 0) |
  9378. ((sp_digit)a[i - 1] << 8) |
  9379. ((sp_digit)a[i - 2] << 16) |
  9380. ((sp_digit)a[i - 3] << 24);
  9381. j++;
  9382. }
  9383. if (i >= 0) {
  9384. r[j] = 0;
  9385. d = (byte*)r;
  9386. switch (i) {
  9387. case 2: d[n - 1 - 2] = a[2]; //fallthrough
  9388. case 1: d[n - 1 - 1] = a[1]; //fallthrough
  9389. case 0: d[n - 1 - 0] = a[0]; //fallthrough
  9390. }
  9391. j++;
  9392. }
  9393. for (; j < size; j++) {
  9394. r[j] = 0;
  9395. }
  9396. }
  9397. /* Convert an mp_int to an array of sp_digit.
  9398. *
  9399. * r A single precision integer.
  9400. * size Maximum number of bytes to convert
  9401. * a A multi-precision integer.
  9402. */
  9403. static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
  9404. {
  9405. #if DIGIT_BIT == 32
  9406. int i;
  9407. sp_digit j = (sp_digit)0 - (sp_digit)a->used;
  9408. int o = 0;
  9409. for (i = 0; i < size; i++) {
  9410. sp_digit mask = (sp_digit)0 - (j >> 31);
  9411. r[i] = a->dp[o] & mask;
  9412. j++;
  9413. o += (int)(j >> 31);
  9414. }
  9415. #elif DIGIT_BIT > 32
  9416. unsigned int i;
  9417. int j = 0;
  9418. word32 s = 0;
  9419. r[0] = 0;
  9420. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  9421. r[j] |= ((sp_digit)a->dp[i] << s);
  9422. r[j] &= 0xffffffff;
  9423. s = 32U - s;
  9424. if (j + 1 >= size) {
  9425. break;
  9426. }
  9427. /* lint allow cast of mismatch word32 and mp_digit */
  9428. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  9429. while ((s + 32U) <= (word32)DIGIT_BIT) {
  9430. s += 32U;
  9431. r[j] &= 0xffffffff;
  9432. if (j + 1 >= size) {
  9433. break;
  9434. }
  9435. if (s < (word32)DIGIT_BIT) {
  9436. /* lint allow cast of mismatch word32 and mp_digit */
  9437. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  9438. }
  9439. else {
  9440. r[++j] = (sp_digit)0;
  9441. }
  9442. }
  9443. s = (word32)DIGIT_BIT - s;
  9444. }
  9445. for (j++; j < size; j++) {
  9446. r[j] = 0;
  9447. }
  9448. #else
  9449. unsigned int i;
  9450. int j = 0;
  9451. int s = 0;
  9452. r[0] = 0;
  9453. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  9454. r[j] |= ((sp_digit)a->dp[i]) << s;
  9455. if (s + DIGIT_BIT >= 32) {
  9456. r[j] &= 0xffffffff;
  9457. if (j + 1 >= size) {
  9458. break;
  9459. }
  9460. s = 32 - s;
  9461. if (s == DIGIT_BIT) {
  9462. r[++j] = 0;
  9463. s = 0;
  9464. }
  9465. else {
  9466. r[++j] = a->dp[i] >> s;
  9467. s = DIGIT_BIT - s;
  9468. }
  9469. }
  9470. else {
  9471. s += DIGIT_BIT;
  9472. }
  9473. }
  9474. for (j++; j < size; j++) {
  9475. r[j] = 0;
  9476. }
  9477. #endif
  9478. }
  9479. /* Write r as big endian to byte array.
  9480. * Fixed length number of bytes written: 384
  9481. *
  9482. * r A single precision integer.
  9483. * a Byte array.
  9484. */
  9485. static void sp_3072_to_bin_96(sp_digit* r, byte* a)
  9486. {
  9487. int i;
  9488. int j = 0;
  9489. for (i = 95; i >= 0; i--) {
  9490. a[j++] = r[i] >> 24;
  9491. a[j++] = r[i] >> 16;
  9492. a[j++] = r[i] >> 8;
  9493. a[j++] = r[i] >> 0;
  9494. }
  9495. }
  9496. #if (defined(WOLFSSL_HAVE_SP_RSA) && (!defined(WOLFSSL_RSA_PUBLIC_ONLY) || !defined(WOLFSSL_SP_SMALL))) || defined(WOLFSSL_HAVE_SP_DH)
  9497. /* Normalize the values in each word to 32.
  9498. *
  9499. * a Array of sp_digit to normalize.
  9500. */
  9501. #define sp_3072_norm_96(a)
  9502. #endif /* (WOLFSSL_HAVE_SP_RSA && (!WOLFSSL_RSA_PUBLIC_ONLY || !WOLFSSL_SP_SMALL)) || WOLFSSL_HAVE_SP_DH */
  9503. /* Normalize the values in each word to 32.
  9504. *
  9505. * a Array of sp_digit to normalize.
  9506. */
  9507. #define sp_3072_norm_96(a)
  9508. #ifndef WOLFSSL_SP_SMALL
  9509. /* Multiply a and b into r. (r = a * b)
  9510. *
  9511. * r A single precision integer.
  9512. * a A single precision integer.
  9513. * b A single precision integer.
  9514. */
  9515. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  9516. static void sp_3072_mul_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  9517. #else
  9518. static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  9519. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  9520. {
  9521. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  9522. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  9523. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  9524. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  9525. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  9526. __asm__ __volatile__ (
  9527. "SUB sp, sp, #0x30\n\t"
  9528. /* A[0] * B[0] */
  9529. "LDR r11, [%[a]]\n\t"
  9530. "LDR r12, [%[b]]\n\t"
  9531. "UMULL r3, r4, r11, r12\n\t"
  9532. "MOV r5, #0x0\n\t"
  9533. "STR r3, [sp]\n\t"
  9534. /* A[0] * B[1] */
  9535. "LDR r9, [%[b], #4]\n\t"
  9536. "UMULL r6, r7, r11, r9\n\t"
  9537. "ADDS r4, r4, r6\n\t"
  9538. "ADCS r5, r5, r7\n\t"
  9539. "MOV r3, #0x0\n\t"
  9540. "ADC r3, r3, #0x0\n\t"
  9541. /* A[1] * B[0] */
  9542. "LDR r8, [%[a], #4]\n\t"
  9543. "UMULL r6, r7, r8, r12\n\t"
  9544. "ADDS r4, r4, r6\n\t"
  9545. "ADCS r5, r5, r7\n\t"
  9546. "ADC r3, r3, #0x0\n\t"
  9547. "STR r4, [sp, #4]\n\t"
  9548. /* A[2] * B[0] */
  9549. "LDR r8, [%[a], #8]\n\t"
  9550. "UMULL r6, r7, r8, r12\n\t"
  9551. "ADDS r5, r5, r6\n\t"
  9552. "ADCS r3, r3, r7\n\t"
  9553. "MOV r4, #0x0\n\t"
  9554. "ADC r4, r4, #0x0\n\t"
  9555. /* A[1] * B[1] */
  9556. "LDR r11, [%[a], #4]\n\t"
  9557. "LDR r12, [%[b], #4]\n\t"
  9558. "UMULL r6, r7, r11, r12\n\t"
  9559. "ADDS r5, r5, r6\n\t"
  9560. "ADCS r3, r3, r7\n\t"
  9561. "ADC r4, r4, #0x0\n\t"
  9562. /* A[0] * B[2] */
  9563. "LDR r8, [%[a]]\n\t"
  9564. "LDR r9, [%[b], #8]\n\t"
  9565. "UMULL r6, r7, r8, r9\n\t"
  9566. "ADDS r5, r5, r6\n\t"
  9567. "ADCS r3, r3, r7\n\t"
  9568. "ADC r4, r4, #0x0\n\t"
  9569. "STR r5, [sp, #8]\n\t"
  9570. /* A[0] * B[3] */
  9571. "LDR r9, [%[b], #12]\n\t"
  9572. "UMULL r6, r7, r8, r9\n\t"
  9573. "ADDS r3, r3, r6\n\t"
  9574. "ADCS r4, r4, r7\n\t"
  9575. "MOV r5, #0x0\n\t"
  9576. "ADC r5, r5, #0x0\n\t"
  9577. /* A[1] * B[2] */
  9578. "LDR r9, [%[b], #8]\n\t"
  9579. "UMULL r6, r7, r11, r9\n\t"
  9580. "ADDS r3, r3, r6\n\t"
  9581. "ADCS r4, r4, r7\n\t"
  9582. "ADC r5, r5, #0x0\n\t"
  9583. /* A[2] * B[1] */
  9584. "LDR r8, [%[a], #8]\n\t"
  9585. "UMULL r6, r7, r8, r12\n\t"
  9586. "ADDS r3, r3, r6\n\t"
  9587. "ADCS r4, r4, r7\n\t"
  9588. "ADC r5, r5, #0x0\n\t"
  9589. /* A[3] * B[0] */
  9590. "LDR r8, [%[a], #12]\n\t"
  9591. "LDR r9, [%[b]]\n\t"
  9592. "UMULL r6, r7, r8, r9\n\t"
  9593. "ADDS r3, r3, r6\n\t"
  9594. "ADCS r4, r4, r7\n\t"
  9595. "ADC r5, r5, #0x0\n\t"
  9596. "STR r3, [sp, #12]\n\t"
  9597. /* A[4] * B[0] */
  9598. "LDR r8, [%[a], #16]\n\t"
  9599. "UMULL r6, r7, r8, r9\n\t"
  9600. "ADDS r4, r4, r6\n\t"
  9601. "ADCS r5, r5, r7\n\t"
  9602. "MOV r3, #0x0\n\t"
  9603. "ADC r3, r3, #0x0\n\t"
  9604. /* A[3] * B[1] */
  9605. "LDR r8, [%[a], #12]\n\t"
  9606. "UMULL r6, r7, r8, r12\n\t"
  9607. "ADDS r4, r4, r6\n\t"
  9608. "ADCS r5, r5, r7\n\t"
  9609. "ADC r3, r3, #0x0\n\t"
  9610. /* A[2] * B[2] */
  9611. "LDR r11, [%[a], #8]\n\t"
  9612. "LDR r12, [%[b], #8]\n\t"
  9613. "UMULL r6, r7, r11, r12\n\t"
  9614. "ADDS r4, r4, r6\n\t"
  9615. "ADCS r5, r5, r7\n\t"
  9616. "ADC r3, r3, #0x0\n\t"
  9617. /* A[1] * B[3] */
  9618. "LDR r8, [%[a], #4]\n\t"
  9619. "LDR r9, [%[b], #12]\n\t"
  9620. "UMULL r6, r7, r8, r9\n\t"
  9621. "ADDS r4, r4, r6\n\t"
  9622. "ADCS r5, r5, r7\n\t"
  9623. "ADC r3, r3, #0x0\n\t"
  9624. /* A[0] * B[4] */
  9625. "LDR r8, [%[a]]\n\t"
  9626. "LDR r9, [%[b], #16]\n\t"
  9627. "UMULL r6, r7, r8, r9\n\t"
  9628. "ADDS r4, r4, r6\n\t"
  9629. "ADCS r5, r5, r7\n\t"
  9630. "ADC r3, r3, #0x0\n\t"
  9631. "STR r4, [sp, #16]\n\t"
  9632. /* A[0] * B[5] */
  9633. "LDR r9, [%[b], #20]\n\t"
  9634. "UMULL r6, r7, r8, r9\n\t"
  9635. "ADDS r5, r5, r6\n\t"
  9636. "ADCS r3, r3, r7\n\t"
  9637. "MOV r4, #0x0\n\t"
  9638. "ADC r4, r4, #0x0\n\t"
  9639. /* A[1] * B[4] */
  9640. "LDR r8, [%[a], #4]\n\t"
  9641. "LDR r9, [%[b], #16]\n\t"
  9642. "UMULL r6, r7, r8, r9\n\t"
  9643. "ADDS r5, r5, r6\n\t"
  9644. "ADCS r3, r3, r7\n\t"
  9645. "ADC r4, r4, #0x0\n\t"
  9646. /* A[2] * B[3] */
  9647. "LDR r9, [%[b], #12]\n\t"
  9648. "UMULL r6, r7, r11, r9\n\t"
  9649. "ADDS r5, r5, r6\n\t"
  9650. "ADCS r3, r3, r7\n\t"
  9651. "ADC r4, r4, #0x0\n\t"
  9652. /* A[3] * B[2] */
  9653. "LDR r8, [%[a], #12]\n\t"
  9654. "UMULL r6, r7, r8, r12\n\t"
  9655. "ADDS r5, r5, r6\n\t"
  9656. "ADCS r3, r3, r7\n\t"
  9657. "ADC r4, r4, #0x0\n\t"
  9658. /* A[4] * B[1] */
  9659. "LDR r8, [%[a], #16]\n\t"
  9660. "LDR r9, [%[b], #4]\n\t"
  9661. "UMULL r6, r7, r8, r9\n\t"
  9662. "ADDS r5, r5, r6\n\t"
  9663. "ADCS r3, r3, r7\n\t"
  9664. "ADC r4, r4, #0x0\n\t"
  9665. /* A[5] * B[0] */
  9666. "LDR r8, [%[a], #20]\n\t"
  9667. "LDR r9, [%[b]]\n\t"
  9668. "UMULL r6, r7, r8, r9\n\t"
  9669. "ADDS r5, r5, r6\n\t"
  9670. "ADCS r3, r3, r7\n\t"
  9671. "ADC r4, r4, #0x0\n\t"
  9672. "STR r5, [sp, #20]\n\t"
  9673. /* A[6] * B[0] */
  9674. "LDR r8, [%[a], #24]\n\t"
  9675. "UMULL r6, r7, r8, r9\n\t"
  9676. "ADDS r3, r3, r6\n\t"
  9677. "ADCS r4, r4, r7\n\t"
  9678. "MOV r5, #0x0\n\t"
  9679. "ADC r5, r5, #0x0\n\t"
  9680. /* A[5] * B[1] */
  9681. "LDR r8, [%[a], #20]\n\t"
  9682. "LDR r9, [%[b], #4]\n\t"
  9683. "UMULL r6, r7, r8, r9\n\t"
  9684. "ADDS r3, r3, r6\n\t"
  9685. "ADCS r4, r4, r7\n\t"
  9686. "ADC r5, r5, #0x0\n\t"
  9687. /* A[4] * B[2] */
  9688. "LDR r8, [%[a], #16]\n\t"
  9689. "UMULL r6, r7, r8, r12\n\t"
  9690. "ADDS r3, r3, r6\n\t"
  9691. "ADCS r4, r4, r7\n\t"
  9692. "ADC r5, r5, #0x0\n\t"
  9693. /* A[3] * B[3] */
  9694. "LDR r11, [%[a], #12]\n\t"
  9695. "LDR r12, [%[b], #12]\n\t"
  9696. "UMULL r6, r7, r11, r12\n\t"
  9697. "ADDS r3, r3, r6\n\t"
  9698. "ADCS r4, r4, r7\n\t"
  9699. "ADC r5, r5, #0x0\n\t"
  9700. /* A[2] * B[4] */
  9701. "LDR r8, [%[a], #8]\n\t"
  9702. "LDR r9, [%[b], #16]\n\t"
  9703. "UMULL r6, r7, r8, r9\n\t"
  9704. "ADDS r3, r3, r6\n\t"
  9705. "ADCS r4, r4, r7\n\t"
  9706. "ADC r5, r5, #0x0\n\t"
  9707. /* A[1] * B[5] */
  9708. "LDR r8, [%[a], #4]\n\t"
  9709. "LDR r9, [%[b], #20]\n\t"
  9710. "UMULL r6, r7, r8, r9\n\t"
  9711. "ADDS r3, r3, r6\n\t"
  9712. "ADCS r4, r4, r7\n\t"
  9713. "ADC r5, r5, #0x0\n\t"
  9714. /* A[0] * B[6] */
  9715. "LDR r8, [%[a]]\n\t"
  9716. "LDR r9, [%[b], #24]\n\t"
  9717. "UMULL r6, r7, r8, r9\n\t"
  9718. "ADDS r3, r3, r6\n\t"
  9719. "ADCS r4, r4, r7\n\t"
  9720. "ADC r5, r5, #0x0\n\t"
  9721. "STR r3, [sp, #24]\n\t"
  9722. /* A[0] * B[7] */
  9723. "LDR r9, [%[b], #28]\n\t"
  9724. "UMULL r6, r7, r8, r9\n\t"
  9725. "ADDS r4, r4, r6\n\t"
  9726. "ADCS r5, r5, r7\n\t"
  9727. "MOV r3, #0x0\n\t"
  9728. "ADC r3, r3, #0x0\n\t"
  9729. /* A[1] * B[6] */
  9730. "LDR r8, [%[a], #4]\n\t"
  9731. "LDR r9, [%[b], #24]\n\t"
  9732. "UMULL r6, r7, r8, r9\n\t"
  9733. "ADDS r4, r4, r6\n\t"
  9734. "ADCS r5, r5, r7\n\t"
  9735. "ADC r3, r3, #0x0\n\t"
  9736. /* A[2] * B[5] */
  9737. "LDR r8, [%[a], #8]\n\t"
  9738. "LDR r9, [%[b], #20]\n\t"
  9739. "UMULL r6, r7, r8, r9\n\t"
  9740. "ADDS r4, r4, r6\n\t"
  9741. "ADCS r5, r5, r7\n\t"
  9742. "ADC r3, r3, #0x0\n\t"
  9743. /* A[3] * B[4] */
  9744. "LDR r9, [%[b], #16]\n\t"
  9745. "UMULL r6, r7, r11, r9\n\t"
  9746. "ADDS r4, r4, r6\n\t"
  9747. "ADCS r5, r5, r7\n\t"
  9748. "ADC r3, r3, #0x0\n\t"
  9749. /* A[4] * B[3] */
  9750. "LDR r8, [%[a], #16]\n\t"
  9751. "UMULL r6, r7, r8, r12\n\t"
  9752. "ADDS r4, r4, r6\n\t"
  9753. "ADCS r5, r5, r7\n\t"
  9754. "ADC r3, r3, #0x0\n\t"
  9755. /* A[5] * B[2] */
  9756. "LDR r8, [%[a], #20]\n\t"
  9757. "LDR r9, [%[b], #8]\n\t"
  9758. "UMULL r6, r7, r8, r9\n\t"
  9759. "ADDS r4, r4, r6\n\t"
  9760. "ADCS r5, r5, r7\n\t"
  9761. "ADC r3, r3, #0x0\n\t"
  9762. /* A[6] * B[1] */
  9763. "LDR r8, [%[a], #24]\n\t"
  9764. "LDR r9, [%[b], #4]\n\t"
  9765. "UMULL r6, r7, r8, r9\n\t"
  9766. "ADDS r4, r4, r6\n\t"
  9767. "ADCS r5, r5, r7\n\t"
  9768. "ADC r3, r3, #0x0\n\t"
  9769. /* A[7] * B[0] */
  9770. "LDR r8, [%[a], #28]\n\t"
  9771. "LDR r9, [%[b]]\n\t"
  9772. "UMULL r6, r7, r8, r9\n\t"
  9773. "ADDS r4, r4, r6\n\t"
  9774. "ADCS r5, r5, r7\n\t"
  9775. "ADC r3, r3, #0x0\n\t"
  9776. "STR r4, [sp, #28]\n\t"
  9777. /* A[8] * B[0] */
  9778. "LDR r8, [%[a], #32]\n\t"
  9779. "UMULL r6, r7, r8, r9\n\t"
  9780. "ADDS r5, r5, r6\n\t"
  9781. "ADCS r3, r3, r7\n\t"
  9782. "MOV r4, #0x0\n\t"
  9783. "ADC r4, r4, #0x0\n\t"
  9784. /* A[7] * B[1] */
  9785. "LDR r8, [%[a], #28]\n\t"
  9786. "LDR r9, [%[b], #4]\n\t"
  9787. "UMULL r6, r7, r8, r9\n\t"
  9788. "ADDS r5, r5, r6\n\t"
  9789. "ADCS r3, r3, r7\n\t"
  9790. "ADC r4, r4, #0x0\n\t"
  9791. /* A[6] * B[2] */
  9792. "LDR r8, [%[a], #24]\n\t"
  9793. "LDR r9, [%[b], #8]\n\t"
  9794. "UMULL r6, r7, r8, r9\n\t"
  9795. "ADDS r5, r5, r6\n\t"
  9796. "ADCS r3, r3, r7\n\t"
  9797. "ADC r4, r4, #0x0\n\t"
  9798. /* A[5] * B[3] */
  9799. "LDR r8, [%[a], #20]\n\t"
  9800. "UMULL r6, r7, r8, r12\n\t"
  9801. "ADDS r5, r5, r6\n\t"
  9802. "ADCS r3, r3, r7\n\t"
  9803. "ADC r4, r4, #0x0\n\t"
  9804. /* A[4] * B[4] */
  9805. "LDR r11, [%[a], #16]\n\t"
  9806. "LDR r12, [%[b], #16]\n\t"
  9807. "UMULL r6, r7, r11, r12\n\t"
  9808. "ADDS r5, r5, r6\n\t"
  9809. "ADCS r3, r3, r7\n\t"
  9810. "ADC r4, r4, #0x0\n\t"
  9811. /* A[3] * B[5] */
  9812. "LDR r8, [%[a], #12]\n\t"
  9813. "LDR r9, [%[b], #20]\n\t"
  9814. "UMULL r6, r7, r8, r9\n\t"
  9815. "ADDS r5, r5, r6\n\t"
  9816. "ADCS r3, r3, r7\n\t"
  9817. "ADC r4, r4, #0x0\n\t"
  9818. /* A[2] * B[6] */
  9819. "LDR r8, [%[a], #8]\n\t"
  9820. "LDR r9, [%[b], #24]\n\t"
  9821. "UMULL r6, r7, r8, r9\n\t"
  9822. "ADDS r5, r5, r6\n\t"
  9823. "ADCS r3, r3, r7\n\t"
  9824. "ADC r4, r4, #0x0\n\t"
  9825. /* A[1] * B[7] */
  9826. "LDR r8, [%[a], #4]\n\t"
  9827. "LDR r9, [%[b], #28]\n\t"
  9828. "UMULL r6, r7, r8, r9\n\t"
  9829. "ADDS r5, r5, r6\n\t"
  9830. "ADCS r3, r3, r7\n\t"
  9831. "ADC r4, r4, #0x0\n\t"
  9832. /* A[0] * B[8] */
  9833. "LDR r8, [%[a]]\n\t"
  9834. "LDR r9, [%[b], #32]\n\t"
  9835. "UMULL r6, r7, r8, r9\n\t"
  9836. "ADDS r5, r5, r6\n\t"
  9837. "ADCS r3, r3, r7\n\t"
  9838. "ADC r4, r4, #0x0\n\t"
  9839. "STR r5, [sp, #32]\n\t"
  9840. /* A[0] * B[9] */
  9841. "LDR r9, [%[b], #36]\n\t"
  9842. "UMULL r6, r7, r8, r9\n\t"
  9843. "ADDS r3, r3, r6\n\t"
  9844. "ADCS r4, r4, r7\n\t"
  9845. "MOV r5, #0x0\n\t"
  9846. "ADC r5, r5, #0x0\n\t"
  9847. /* A[1] * B[8] */
  9848. "LDR r8, [%[a], #4]\n\t"
  9849. "LDR r9, [%[b], #32]\n\t"
  9850. "UMULL r6, r7, r8, r9\n\t"
  9851. "ADDS r3, r3, r6\n\t"
  9852. "ADCS r4, r4, r7\n\t"
  9853. "ADC r5, r5, #0x0\n\t"
  9854. /* A[2] * B[7] */
  9855. "LDR r8, [%[a], #8]\n\t"
  9856. "LDR r9, [%[b], #28]\n\t"
  9857. "UMULL r6, r7, r8, r9\n\t"
  9858. "ADDS r3, r3, r6\n\t"
  9859. "ADCS r4, r4, r7\n\t"
  9860. "ADC r5, r5, #0x0\n\t"
  9861. /* A[3] * B[6] */
  9862. "LDR r8, [%[a], #12]\n\t"
  9863. "LDR r9, [%[b], #24]\n\t"
  9864. "UMULL r6, r7, r8, r9\n\t"
  9865. "ADDS r3, r3, r6\n\t"
  9866. "ADCS r4, r4, r7\n\t"
  9867. "ADC r5, r5, #0x0\n\t"
  9868. /* A[4] * B[5] */
  9869. "LDR r9, [%[b], #20]\n\t"
  9870. "UMULL r6, r7, r11, r9\n\t"
  9871. "ADDS r3, r3, r6\n\t"
  9872. "ADCS r4, r4, r7\n\t"
  9873. "ADC r5, r5, #0x0\n\t"
  9874. /* A[5] * B[4] */
  9875. "LDR r8, [%[a], #20]\n\t"
  9876. "UMULL r6, r7, r8, r12\n\t"
  9877. "ADDS r3, r3, r6\n\t"
  9878. "ADCS r4, r4, r7\n\t"
  9879. "ADC r5, r5, #0x0\n\t"
  9880. /* A[6] * B[3] */
  9881. "LDR r8, [%[a], #24]\n\t"
  9882. "LDR r9, [%[b], #12]\n\t"
  9883. "UMULL r6, r7, r8, r9\n\t"
  9884. "ADDS r3, r3, r6\n\t"
  9885. "ADCS r4, r4, r7\n\t"
  9886. "ADC r5, r5, #0x0\n\t"
  9887. /* A[7] * B[2] */
  9888. "LDR r8, [%[a], #28]\n\t"
  9889. "LDR r9, [%[b], #8]\n\t"
  9890. "UMULL r6, r7, r8, r9\n\t"
  9891. "ADDS r3, r3, r6\n\t"
  9892. "ADCS r4, r4, r7\n\t"
  9893. "ADC r5, r5, #0x0\n\t"
  9894. /* A[8] * B[1] */
  9895. "LDR r8, [%[a], #32]\n\t"
  9896. "LDR r9, [%[b], #4]\n\t"
  9897. "UMULL r6, r7, r8, r9\n\t"
  9898. "ADDS r3, r3, r6\n\t"
  9899. "ADCS r4, r4, r7\n\t"
  9900. "ADC r5, r5, #0x0\n\t"
  9901. /* A[9] * B[0] */
  9902. "LDR r8, [%[a], #36]\n\t"
  9903. "LDR r9, [%[b]]\n\t"
  9904. "UMULL r6, r7, r8, r9\n\t"
  9905. "ADDS r3, r3, r6\n\t"
  9906. "ADCS r4, r4, r7\n\t"
  9907. "ADC r5, r5, #0x0\n\t"
  9908. "STR r3, [sp, #36]\n\t"
  9909. /* A[10] * B[0] */
  9910. "LDR r8, [%[a], #40]\n\t"
  9911. "UMULL r6, r7, r8, r9\n\t"
  9912. "ADDS r4, r4, r6\n\t"
  9913. "ADCS r5, r5, r7\n\t"
  9914. "MOV r3, #0x0\n\t"
  9915. "ADC r3, r3, #0x0\n\t"
  9916. /* A[9] * B[1] */
  9917. "LDR r8, [%[a], #36]\n\t"
  9918. "LDR r9, [%[b], #4]\n\t"
  9919. "UMULL r6, r7, r8, r9\n\t"
  9920. "ADDS r4, r4, r6\n\t"
  9921. "ADCS r5, r5, r7\n\t"
  9922. "ADC r3, r3, #0x0\n\t"
  9923. /* A[8] * B[2] */
  9924. "LDR r8, [%[a], #32]\n\t"
  9925. "LDR r9, [%[b], #8]\n\t"
  9926. "UMULL r6, r7, r8, r9\n\t"
  9927. "ADDS r4, r4, r6\n\t"
  9928. "ADCS r5, r5, r7\n\t"
  9929. "ADC r3, r3, #0x0\n\t"
  9930. /* A[7] * B[3] */
  9931. "LDR r8, [%[a], #28]\n\t"
  9932. "LDR r9, [%[b], #12]\n\t"
  9933. "UMULL r6, r7, r8, r9\n\t"
  9934. "ADDS r4, r4, r6\n\t"
  9935. "ADCS r5, r5, r7\n\t"
  9936. "ADC r3, r3, #0x0\n\t"
  9937. /* A[6] * B[4] */
  9938. "LDR r8, [%[a], #24]\n\t"
  9939. "UMULL r6, r7, r8, r12\n\t"
  9940. "ADDS r4, r4, r6\n\t"
  9941. "ADCS r5, r5, r7\n\t"
  9942. "ADC r3, r3, #0x0\n\t"
  9943. /* A[5] * B[5] */
  9944. "LDR r11, [%[a], #20]\n\t"
  9945. "LDR r12, [%[b], #20]\n\t"
  9946. "UMULL r6, r7, r11, r12\n\t"
  9947. "ADDS r4, r4, r6\n\t"
  9948. "ADCS r5, r5, r7\n\t"
  9949. "ADC r3, r3, #0x0\n\t"
  9950. /* A[4] * B[6] */
  9951. "LDR r8, [%[a], #16]\n\t"
  9952. "LDR r9, [%[b], #24]\n\t"
  9953. "UMULL r6, r7, r8, r9\n\t"
  9954. "ADDS r4, r4, r6\n\t"
  9955. "ADCS r5, r5, r7\n\t"
  9956. "ADC r3, r3, #0x0\n\t"
  9957. /* A[3] * B[7] */
  9958. "LDR r8, [%[a], #12]\n\t"
  9959. "LDR r9, [%[b], #28]\n\t"
  9960. "UMULL r6, r7, r8, r9\n\t"
  9961. "ADDS r4, r4, r6\n\t"
  9962. "ADCS r5, r5, r7\n\t"
  9963. "ADC r3, r3, #0x0\n\t"
  9964. /* A[2] * B[8] */
  9965. "LDR r8, [%[a], #8]\n\t"
  9966. "LDR r9, [%[b], #32]\n\t"
  9967. "UMULL r6, r7, r8, r9\n\t"
  9968. "ADDS r4, r4, r6\n\t"
  9969. "ADCS r5, r5, r7\n\t"
  9970. "ADC r3, r3, #0x0\n\t"
  9971. /* A[1] * B[9] */
  9972. "LDR r8, [%[a], #4]\n\t"
  9973. "LDR r9, [%[b], #36]\n\t"
  9974. "UMULL r6, r7, r8, r9\n\t"
  9975. "ADDS r4, r4, r6\n\t"
  9976. "ADCS r5, r5, r7\n\t"
  9977. "ADC r3, r3, #0x0\n\t"
  9978. /* A[0] * B[10] */
  9979. "LDR r8, [%[a]]\n\t"
  9980. "LDR r9, [%[b], #40]\n\t"
  9981. "UMULL r6, r7, r8, r9\n\t"
  9982. "ADDS r4, r4, r6\n\t"
  9983. "ADCS r5, r5, r7\n\t"
  9984. "ADC r3, r3, #0x0\n\t"
  9985. "STR r4, [sp, #40]\n\t"
  9986. /* A[0] * B[11] */
  9987. "LDR r9, [%[b], #44]\n\t"
  9988. "UMULL r6, r7, r8, r9\n\t"
  9989. "ADDS r5, r5, r6\n\t"
  9990. "ADCS r3, r3, r7\n\t"
  9991. "MOV r4, #0x0\n\t"
  9992. "ADC r4, r4, #0x0\n\t"
  9993. /* A[1] * B[10] */
  9994. "LDR r8, [%[a], #4]\n\t"
  9995. "LDR r9, [%[b], #40]\n\t"
  9996. "UMULL r6, r7, r8, r9\n\t"
  9997. "ADDS r5, r5, r6\n\t"
  9998. "ADCS r3, r3, r7\n\t"
  9999. "ADC r4, r4, #0x0\n\t"
  10000. /* A[2] * B[9] */
  10001. "LDR r8, [%[a], #8]\n\t"
  10002. "LDR r9, [%[b], #36]\n\t"
  10003. "UMULL r6, r7, r8, r9\n\t"
  10004. "ADDS r5, r5, r6\n\t"
  10005. "ADCS r3, r3, r7\n\t"
  10006. "ADC r4, r4, #0x0\n\t"
  10007. /* A[3] * B[8] */
  10008. "LDR r8, [%[a], #12]\n\t"
  10009. "LDR r9, [%[b], #32]\n\t"
  10010. "UMULL r6, r7, r8, r9\n\t"
  10011. "ADDS r5, r5, r6\n\t"
  10012. "ADCS r3, r3, r7\n\t"
  10013. "ADC r4, r4, #0x0\n\t"
  10014. /* A[4] * B[7] */
  10015. "LDR r8, [%[a], #16]\n\t"
  10016. "LDR r9, [%[b], #28]\n\t"
  10017. "UMULL r6, r7, r8, r9\n\t"
  10018. "ADDS r5, r5, r6\n\t"
  10019. "ADCS r3, r3, r7\n\t"
  10020. "ADC r4, r4, #0x0\n\t"
  10021. /* A[5] * B[6] */
  10022. "LDR r9, [%[b], #24]\n\t"
  10023. "UMULL r6, r7, r11, r9\n\t"
  10024. "ADDS r5, r5, r6\n\t"
  10025. "ADCS r3, r3, r7\n\t"
  10026. "ADC r4, r4, #0x0\n\t"
  10027. /* A[6] * B[5] */
  10028. "LDR r8, [%[a], #24]\n\t"
  10029. "UMULL r6, r7, r8, r12\n\t"
  10030. "ADDS r5, r5, r6\n\t"
  10031. "ADCS r3, r3, r7\n\t"
  10032. "ADC r4, r4, #0x0\n\t"
  10033. /* A[7] * B[4] */
  10034. "LDR r8, [%[a], #28]\n\t"
  10035. "LDR r9, [%[b], #16]\n\t"
  10036. "UMULL r6, r7, r8, r9\n\t"
  10037. "ADDS r5, r5, r6\n\t"
  10038. "ADCS r3, r3, r7\n\t"
  10039. "ADC r4, r4, #0x0\n\t"
  10040. /* A[8] * B[3] */
  10041. "LDR r8, [%[a], #32]\n\t"
  10042. "LDR r9, [%[b], #12]\n\t"
  10043. "UMULL r6, r7, r8, r9\n\t"
  10044. "ADDS r5, r5, r6\n\t"
  10045. "ADCS r3, r3, r7\n\t"
  10046. "ADC r4, r4, #0x0\n\t"
  10047. /* A[9] * B[2] */
  10048. "LDR r8, [%[a], #36]\n\t"
  10049. "LDR r9, [%[b], #8]\n\t"
  10050. "UMULL r6, r7, r8, r9\n\t"
  10051. "ADDS r5, r5, r6\n\t"
  10052. "ADCS r3, r3, r7\n\t"
  10053. "ADC r4, r4, #0x0\n\t"
  10054. /* A[10] * B[1] */
  10055. "LDR r8, [%[a], #40]\n\t"
  10056. "LDR r9, [%[b], #4]\n\t"
  10057. "UMULL r6, r7, r8, r9\n\t"
  10058. "ADDS r5, r5, r6\n\t"
  10059. "ADCS r3, r3, r7\n\t"
  10060. "ADC r4, r4, #0x0\n\t"
  10061. /* A[11] * B[0] */
  10062. "LDR r8, [%[a], #44]\n\t"
  10063. "LDR r9, [%[b]]\n\t"
  10064. "UMULL r6, r7, r8, r9\n\t"
  10065. "ADDS r5, r5, r6\n\t"
  10066. "ADCS r3, r3, r7\n\t"
  10067. "ADC r4, r4, #0x0\n\t"
  10068. "STR r5, [sp, #44]\n\t"
  10069. /* A[11] * B[1] */
  10070. "LDR r9, [%[b], #4]\n\t"
  10071. "UMULL r6, r7, r8, r9\n\t"
  10072. "ADDS r3, r3, r6\n\t"
  10073. "ADCS r4, r4, r7\n\t"
  10074. "MOV r5, #0x0\n\t"
  10075. "ADC r5, r5, #0x0\n\t"
  10076. /* A[10] * B[2] */
  10077. "LDR r8, [%[a], #40]\n\t"
  10078. "LDR r9, [%[b], #8]\n\t"
  10079. "UMULL r6, r7, r8, r9\n\t"
  10080. "ADDS r3, r3, r6\n\t"
  10081. "ADCS r4, r4, r7\n\t"
  10082. "ADC r5, r5, #0x0\n\t"
  10083. /* A[9] * B[3] */
  10084. "LDR r8, [%[a], #36]\n\t"
  10085. "LDR r9, [%[b], #12]\n\t"
  10086. "UMULL r6, r7, r8, r9\n\t"
  10087. "ADDS r3, r3, r6\n\t"
  10088. "ADCS r4, r4, r7\n\t"
  10089. "ADC r5, r5, #0x0\n\t"
  10090. /* A[8] * B[4] */
  10091. "LDR r8, [%[a], #32]\n\t"
  10092. "LDR r9, [%[b], #16]\n\t"
  10093. "UMULL r6, r7, r8, r9\n\t"
  10094. "ADDS r3, r3, r6\n\t"
  10095. "ADCS r4, r4, r7\n\t"
  10096. "ADC r5, r5, #0x0\n\t"
  10097. /* A[7] * B[5] */
  10098. "LDR r8, [%[a], #28]\n\t"
  10099. "UMULL r6, r7, r8, r12\n\t"
  10100. "ADDS r3, r3, r6\n\t"
  10101. "ADCS r4, r4, r7\n\t"
  10102. "ADC r5, r5, #0x0\n\t"
  10103. /* A[6] * B[6] */
  10104. "LDR r11, [%[a], #24]\n\t"
  10105. "LDR r12, [%[b], #24]\n\t"
  10106. "UMULL r6, r7, r11, r12\n\t"
  10107. "ADDS r3, r3, r6\n\t"
  10108. "ADCS r4, r4, r7\n\t"
  10109. "ADC r5, r5, #0x0\n\t"
  10110. /* A[5] * B[7] */
  10111. "LDR r8, [%[a], #20]\n\t"
  10112. "LDR r9, [%[b], #28]\n\t"
  10113. "UMULL r6, r7, r8, r9\n\t"
  10114. "ADDS r3, r3, r6\n\t"
  10115. "ADCS r4, r4, r7\n\t"
  10116. "ADC r5, r5, #0x0\n\t"
  10117. /* A[4] * B[8] */
  10118. "LDR r8, [%[a], #16]\n\t"
  10119. "LDR r9, [%[b], #32]\n\t"
  10120. "UMULL r6, r7, r8, r9\n\t"
  10121. "ADDS r3, r3, r6\n\t"
  10122. "ADCS r4, r4, r7\n\t"
  10123. "ADC r5, r5, #0x0\n\t"
  10124. /* A[3] * B[9] */
  10125. "LDR r8, [%[a], #12]\n\t"
  10126. "LDR r9, [%[b], #36]\n\t"
  10127. "UMULL r6, r7, r8, r9\n\t"
  10128. "ADDS r3, r3, r6\n\t"
  10129. "ADCS r4, r4, r7\n\t"
  10130. "ADC r5, r5, #0x0\n\t"
  10131. /* A[2] * B[10] */
  10132. "LDR r8, [%[a], #8]\n\t"
  10133. "LDR r9, [%[b], #40]\n\t"
  10134. "UMULL r6, r7, r8, r9\n\t"
  10135. "ADDS r3, r3, r6\n\t"
  10136. "ADCS r4, r4, r7\n\t"
  10137. "ADC r5, r5, #0x0\n\t"
  10138. /* A[1] * B[11] */
  10139. "LDR r8, [%[a], #4]\n\t"
  10140. "LDR r9, [%[b], #44]\n\t"
  10141. "UMULL r6, r7, r8, r9\n\t"
  10142. "ADDS r3, r3, r6\n\t"
  10143. "ADCS r4, r4, r7\n\t"
  10144. "ADC r5, r5, #0x0\n\t"
  10145. "STR r3, [%[r], #48]\n\t"
  10146. /* A[2] * B[11] */
  10147. "LDR r8, [%[a], #8]\n\t"
  10148. "UMULL r6, r7, r8, r9\n\t"
  10149. "ADDS r4, r4, r6\n\t"
  10150. "ADCS r5, r5, r7\n\t"
  10151. "MOV r3, #0x0\n\t"
  10152. "ADC r3, r3, #0x0\n\t"
  10153. /* A[3] * B[10] */
  10154. "LDR r8, [%[a], #12]\n\t"
  10155. "LDR r9, [%[b], #40]\n\t"
  10156. "UMULL r6, r7, r8, r9\n\t"
  10157. "ADDS r4, r4, r6\n\t"
  10158. "ADCS r5, r5, r7\n\t"
  10159. "ADC r3, r3, #0x0\n\t"
  10160. /* A[4] * B[9] */
  10161. "LDR r8, [%[a], #16]\n\t"
  10162. "LDR r9, [%[b], #36]\n\t"
  10163. "UMULL r6, r7, r8, r9\n\t"
  10164. "ADDS r4, r4, r6\n\t"
  10165. "ADCS r5, r5, r7\n\t"
  10166. "ADC r3, r3, #0x0\n\t"
  10167. /* A[5] * B[8] */
  10168. "LDR r8, [%[a], #20]\n\t"
  10169. "LDR r9, [%[b], #32]\n\t"
  10170. "UMULL r6, r7, r8, r9\n\t"
  10171. "ADDS r4, r4, r6\n\t"
  10172. "ADCS r5, r5, r7\n\t"
  10173. "ADC r3, r3, #0x0\n\t"
  10174. /* A[6] * B[7] */
  10175. "LDR r9, [%[b], #28]\n\t"
  10176. "UMULL r6, r7, r11, r9\n\t"
  10177. "ADDS r4, r4, r6\n\t"
  10178. "ADCS r5, r5, r7\n\t"
  10179. "ADC r3, r3, #0x0\n\t"
  10180. /* A[7] * B[6] */
  10181. "LDR r8, [%[a], #28]\n\t"
  10182. "UMULL r6, r7, r8, r12\n\t"
  10183. "ADDS r4, r4, r6\n\t"
  10184. "ADCS r5, r5, r7\n\t"
  10185. "ADC r3, r3, #0x0\n\t"
  10186. /* A[8] * B[5] */
  10187. "LDR r8, [%[a], #32]\n\t"
  10188. "LDR r9, [%[b], #20]\n\t"
  10189. "UMULL r6, r7, r8, r9\n\t"
  10190. "ADDS r4, r4, r6\n\t"
  10191. "ADCS r5, r5, r7\n\t"
  10192. "ADC r3, r3, #0x0\n\t"
  10193. /* A[9] * B[4] */
  10194. "LDR r8, [%[a], #36]\n\t"
  10195. "LDR r9, [%[b], #16]\n\t"
  10196. "UMULL r6, r7, r8, r9\n\t"
  10197. "ADDS r4, r4, r6\n\t"
  10198. "ADCS r5, r5, r7\n\t"
  10199. "ADC r3, r3, #0x0\n\t"
  10200. /* A[10] * B[3] */
  10201. "LDR r8, [%[a], #40]\n\t"
  10202. "LDR r9, [%[b], #12]\n\t"
  10203. "UMULL r6, r7, r8, r9\n\t"
  10204. "ADDS r4, r4, r6\n\t"
  10205. "ADCS r5, r5, r7\n\t"
  10206. "ADC r3, r3, #0x0\n\t"
  10207. /* A[11] * B[2] */
  10208. "LDR r8, [%[a], #44]\n\t"
  10209. "LDR r9, [%[b], #8]\n\t"
  10210. "UMULL r6, r7, r8, r9\n\t"
  10211. "ADDS r4, r4, r6\n\t"
  10212. "ADCS r5, r5, r7\n\t"
  10213. "ADC r3, r3, #0x0\n\t"
  10214. "STR r4, [%[r], #52]\n\t"
  10215. /* A[11] * B[3] */
  10216. "LDR r9, [%[b], #12]\n\t"
  10217. "UMULL r6, r7, r8, r9\n\t"
  10218. "ADDS r5, r5, r6\n\t"
  10219. "ADCS r3, r3, r7\n\t"
  10220. "MOV r4, #0x0\n\t"
  10221. "ADC r4, r4, #0x0\n\t"
  10222. /* A[10] * B[4] */
  10223. "LDR r8, [%[a], #40]\n\t"
  10224. "LDR r9, [%[b], #16]\n\t"
  10225. "UMULL r6, r7, r8, r9\n\t"
  10226. "ADDS r5, r5, r6\n\t"
  10227. "ADCS r3, r3, r7\n\t"
  10228. "ADC r4, r4, #0x0\n\t"
  10229. /* A[9] * B[5] */
  10230. "LDR r8, [%[a], #36]\n\t"
  10231. "LDR r9, [%[b], #20]\n\t"
  10232. "UMULL r6, r7, r8, r9\n\t"
  10233. "ADDS r5, r5, r6\n\t"
  10234. "ADCS r3, r3, r7\n\t"
  10235. "ADC r4, r4, #0x0\n\t"
  10236. /* A[8] * B[6] */
  10237. "LDR r8, [%[a], #32]\n\t"
  10238. "UMULL r6, r7, r8, r12\n\t"
  10239. "ADDS r5, r5, r6\n\t"
  10240. "ADCS r3, r3, r7\n\t"
  10241. "ADC r4, r4, #0x0\n\t"
  10242. /* A[7] * B[7] */
  10243. "LDR r11, [%[a], #28]\n\t"
  10244. "LDR r12, [%[b], #28]\n\t"
  10245. "UMULL r6, r7, r11, r12\n\t"
  10246. "ADDS r5, r5, r6\n\t"
  10247. "ADCS r3, r3, r7\n\t"
  10248. "ADC r4, r4, #0x0\n\t"
  10249. /* A[6] * B[8] */
  10250. "LDR r8, [%[a], #24]\n\t"
  10251. "LDR r9, [%[b], #32]\n\t"
  10252. "UMULL r6, r7, r8, r9\n\t"
  10253. "ADDS r5, r5, r6\n\t"
  10254. "ADCS r3, r3, r7\n\t"
  10255. "ADC r4, r4, #0x0\n\t"
  10256. /* A[5] * B[9] */
  10257. "LDR r8, [%[a], #20]\n\t"
  10258. "LDR r9, [%[b], #36]\n\t"
  10259. "UMULL r6, r7, r8, r9\n\t"
  10260. "ADDS r5, r5, r6\n\t"
  10261. "ADCS r3, r3, r7\n\t"
  10262. "ADC r4, r4, #0x0\n\t"
  10263. /* A[4] * B[10] */
  10264. "LDR r8, [%[a], #16]\n\t"
  10265. "LDR r9, [%[b], #40]\n\t"
  10266. "UMULL r6, r7, r8, r9\n\t"
  10267. "ADDS r5, r5, r6\n\t"
  10268. "ADCS r3, r3, r7\n\t"
  10269. "ADC r4, r4, #0x0\n\t"
  10270. /* A[3] * B[11] */
  10271. "LDR r8, [%[a], #12]\n\t"
  10272. "LDR r9, [%[b], #44]\n\t"
  10273. "UMULL r6, r7, r8, r9\n\t"
  10274. "ADDS r5, r5, r6\n\t"
  10275. "ADCS r3, r3, r7\n\t"
  10276. "ADC r4, r4, #0x0\n\t"
  10277. "STR r5, [%[r], #56]\n\t"
  10278. /* A[4] * B[11] */
  10279. "LDR r8, [%[a], #16]\n\t"
  10280. "UMULL r6, r7, r8, r9\n\t"
  10281. "ADDS r3, r3, r6\n\t"
  10282. "ADCS r4, r4, r7\n\t"
  10283. "MOV r5, #0x0\n\t"
  10284. "ADC r5, r5, #0x0\n\t"
  10285. /* A[5] * B[10] */
  10286. "LDR r8, [%[a], #20]\n\t"
  10287. "LDR r9, [%[b], #40]\n\t"
  10288. "UMULL r6, r7, r8, r9\n\t"
  10289. "ADDS r3, r3, r6\n\t"
  10290. "ADCS r4, r4, r7\n\t"
  10291. "ADC r5, r5, #0x0\n\t"
  10292. /* A[6] * B[9] */
  10293. "LDR r8, [%[a], #24]\n\t"
  10294. "LDR r9, [%[b], #36]\n\t"
  10295. "UMULL r6, r7, r8, r9\n\t"
  10296. "ADDS r3, r3, r6\n\t"
  10297. "ADCS r4, r4, r7\n\t"
  10298. "ADC r5, r5, #0x0\n\t"
  10299. /* A[7] * B[8] */
  10300. "LDR r9, [%[b], #32]\n\t"
  10301. "UMULL r6, r7, r11, r9\n\t"
  10302. "ADDS r3, r3, r6\n\t"
  10303. "ADCS r4, r4, r7\n\t"
  10304. "ADC r5, r5, #0x0\n\t"
  10305. /* A[8] * B[7] */
  10306. "LDR r8, [%[a], #32]\n\t"
  10307. "UMULL r6, r7, r8, r12\n\t"
  10308. "ADDS r3, r3, r6\n\t"
  10309. "ADCS r4, r4, r7\n\t"
  10310. "ADC r5, r5, #0x0\n\t"
  10311. /* A[9] * B[6] */
  10312. "LDR r8, [%[a], #36]\n\t"
  10313. "LDR r9, [%[b], #24]\n\t"
  10314. "UMULL r6, r7, r8, r9\n\t"
  10315. "ADDS r3, r3, r6\n\t"
  10316. "ADCS r4, r4, r7\n\t"
  10317. "ADC r5, r5, #0x0\n\t"
  10318. /* A[10] * B[5] */
  10319. "LDR r8, [%[a], #40]\n\t"
  10320. "LDR r9, [%[b], #20]\n\t"
  10321. "UMULL r6, r7, r8, r9\n\t"
  10322. "ADDS r3, r3, r6\n\t"
  10323. "ADCS r4, r4, r7\n\t"
  10324. "ADC r5, r5, #0x0\n\t"
  10325. /* A[11] * B[4] */
  10326. "LDR r8, [%[a], #44]\n\t"
  10327. "LDR r9, [%[b], #16]\n\t"
  10328. "UMULL r6, r7, r8, r9\n\t"
  10329. "ADDS r3, r3, r6\n\t"
  10330. "ADCS r4, r4, r7\n\t"
  10331. "ADC r5, r5, #0x0\n\t"
  10332. "STR r3, [%[r], #60]\n\t"
  10333. /* A[11] * B[5] */
  10334. "LDR r9, [%[b], #20]\n\t"
  10335. "UMULL r6, r7, r8, r9\n\t"
  10336. "ADDS r4, r4, r6\n\t"
  10337. "ADCS r5, r5, r7\n\t"
  10338. "MOV r3, #0x0\n\t"
  10339. "ADC r3, r3, #0x0\n\t"
  10340. /* A[10] * B[6] */
  10341. "LDR r8, [%[a], #40]\n\t"
  10342. "LDR r9, [%[b], #24]\n\t"
  10343. "UMULL r6, r7, r8, r9\n\t"
  10344. "ADDS r4, r4, r6\n\t"
  10345. "ADCS r5, r5, r7\n\t"
  10346. "ADC r3, r3, #0x0\n\t"
  10347. /* A[9] * B[7] */
  10348. "LDR r8, [%[a], #36]\n\t"
  10349. "UMULL r6, r7, r8, r12\n\t"
  10350. "ADDS r4, r4, r6\n\t"
  10351. "ADCS r5, r5, r7\n\t"
  10352. "ADC r3, r3, #0x0\n\t"
  10353. /* A[8] * B[8] */
  10354. "LDR r11, [%[a], #32]\n\t"
  10355. "LDR r12, [%[b], #32]\n\t"
  10356. "UMULL r6, r7, r11, r12\n\t"
  10357. "ADDS r4, r4, r6\n\t"
  10358. "ADCS r5, r5, r7\n\t"
  10359. "ADC r3, r3, #0x0\n\t"
  10360. /* A[7] * B[9] */
  10361. "LDR r8, [%[a], #28]\n\t"
  10362. "LDR r9, [%[b], #36]\n\t"
  10363. "UMULL r6, r7, r8, r9\n\t"
  10364. "ADDS r4, r4, r6\n\t"
  10365. "ADCS r5, r5, r7\n\t"
  10366. "ADC r3, r3, #0x0\n\t"
  10367. /* A[6] * B[10] */
  10368. "LDR r8, [%[a], #24]\n\t"
  10369. "LDR r9, [%[b], #40]\n\t"
  10370. "UMULL r6, r7, r8, r9\n\t"
  10371. "ADDS r4, r4, r6\n\t"
  10372. "ADCS r5, r5, r7\n\t"
  10373. "ADC r3, r3, #0x0\n\t"
  10374. /* A[5] * B[11] */
  10375. "LDR r8, [%[a], #20]\n\t"
  10376. "LDR r9, [%[b], #44]\n\t"
  10377. "UMULL r6, r7, r8, r9\n\t"
  10378. "ADDS r4, r4, r6\n\t"
  10379. "ADCS r5, r5, r7\n\t"
  10380. "ADC r3, r3, #0x0\n\t"
  10381. "STR r4, [%[r], #64]\n\t"
  10382. /* A[6] * B[11] */
  10383. "LDR r8, [%[a], #24]\n\t"
  10384. "UMULL r6, r7, r8, r9\n\t"
  10385. "ADDS r5, r5, r6\n\t"
  10386. "ADCS r3, r3, r7\n\t"
  10387. "MOV r4, #0x0\n\t"
  10388. "ADC r4, r4, #0x0\n\t"
  10389. /* A[7] * B[10] */
  10390. "LDR r8, [%[a], #28]\n\t"
  10391. "LDR r9, [%[b], #40]\n\t"
  10392. "UMULL r6, r7, r8, r9\n\t"
  10393. "ADDS r5, r5, r6\n\t"
  10394. "ADCS r3, r3, r7\n\t"
  10395. "ADC r4, r4, #0x0\n\t"
  10396. /* A[8] * B[9] */
  10397. "LDR r9, [%[b], #36]\n\t"
  10398. "UMULL r6, r7, r11, r9\n\t"
  10399. "ADDS r5, r5, r6\n\t"
  10400. "ADCS r3, r3, r7\n\t"
  10401. "ADC r4, r4, #0x0\n\t"
  10402. /* A[9] * B[8] */
  10403. "LDR r8, [%[a], #36]\n\t"
  10404. "UMULL r6, r7, r8, r12\n\t"
  10405. "ADDS r5, r5, r6\n\t"
  10406. "ADCS r3, r3, r7\n\t"
  10407. "ADC r4, r4, #0x0\n\t"
  10408. /* A[10] * B[7] */
  10409. "LDR r8, [%[a], #40]\n\t"
  10410. "LDR r9, [%[b], #28]\n\t"
  10411. "UMULL r6, r7, r8, r9\n\t"
  10412. "ADDS r5, r5, r6\n\t"
  10413. "ADCS r3, r3, r7\n\t"
  10414. "ADC r4, r4, #0x0\n\t"
  10415. /* A[11] * B[6] */
  10416. "LDR r8, [%[a], #44]\n\t"
  10417. "LDR r9, [%[b], #24]\n\t"
  10418. "UMULL r6, r7, r8, r9\n\t"
  10419. "ADDS r5, r5, r6\n\t"
  10420. "ADCS r3, r3, r7\n\t"
  10421. "ADC r4, r4, #0x0\n\t"
  10422. "STR r5, [%[r], #68]\n\t"
  10423. /* A[11] * B[7] */
  10424. "LDR r9, [%[b], #28]\n\t"
  10425. "UMULL r6, r7, r8, r9\n\t"
  10426. "ADDS r3, r3, r6\n\t"
  10427. "ADCS r4, r4, r7\n\t"
  10428. "MOV r5, #0x0\n\t"
  10429. "ADC r5, r5, #0x0\n\t"
  10430. /* A[10] * B[8] */
  10431. "LDR r8, [%[a], #40]\n\t"
  10432. "UMULL r6, r7, r8, r12\n\t"
  10433. "ADDS r3, r3, r6\n\t"
  10434. "ADCS r4, r4, r7\n\t"
  10435. "ADC r5, r5, #0x0\n\t"
  10436. /* A[9] * B[9] */
  10437. "LDR r11, [%[a], #36]\n\t"
  10438. "LDR r12, [%[b], #36]\n\t"
  10439. "UMULL r6, r7, r11, r12\n\t"
  10440. "ADDS r3, r3, r6\n\t"
  10441. "ADCS r4, r4, r7\n\t"
  10442. "ADC r5, r5, #0x0\n\t"
  10443. /* A[8] * B[10] */
  10444. "LDR r8, [%[a], #32]\n\t"
  10445. "LDR r9, [%[b], #40]\n\t"
  10446. "UMULL r6, r7, r8, r9\n\t"
  10447. "ADDS r3, r3, r6\n\t"
  10448. "ADCS r4, r4, r7\n\t"
  10449. "ADC r5, r5, #0x0\n\t"
  10450. /* A[7] * B[11] */
  10451. "LDR r8, [%[a], #28]\n\t"
  10452. "LDR r9, [%[b], #44]\n\t"
  10453. "UMULL r6, r7, r8, r9\n\t"
  10454. "ADDS r3, r3, r6\n\t"
  10455. "ADCS r4, r4, r7\n\t"
  10456. "ADC r5, r5, #0x0\n\t"
  10457. "STR r3, [%[r], #72]\n\t"
  10458. /* A[8] * B[11] */
  10459. "LDR r8, [%[a], #32]\n\t"
  10460. "UMULL r6, r7, r8, r9\n\t"
  10461. "ADDS r4, r4, r6\n\t"
  10462. "ADCS r5, r5, r7\n\t"
  10463. "MOV r3, #0x0\n\t"
  10464. "ADC r3, r3, #0x0\n\t"
  10465. /* A[9] * B[10] */
  10466. "LDR r9, [%[b], #40]\n\t"
  10467. "UMULL r6, r7, r11, r9\n\t"
  10468. "ADDS r4, r4, r6\n\t"
  10469. "ADCS r5, r5, r7\n\t"
  10470. "ADC r3, r3, #0x0\n\t"
  10471. /* A[10] * B[9] */
  10472. "LDR r8, [%[a], #40]\n\t"
  10473. "UMULL r6, r7, r8, r12\n\t"
  10474. "ADDS r4, r4, r6\n\t"
  10475. "ADCS r5, r5, r7\n\t"
  10476. "ADC r3, r3, #0x0\n\t"
  10477. /* A[11] * B[8] */
  10478. "LDR r8, [%[a], #44]\n\t"
  10479. "LDR r9, [%[b], #32]\n\t"
  10480. "UMULL r6, r7, r8, r9\n\t"
  10481. "ADDS r4, r4, r6\n\t"
  10482. "ADCS r5, r5, r7\n\t"
  10483. "ADC r3, r3, #0x0\n\t"
  10484. "STR r4, [%[r], #76]\n\t"
  10485. /* A[11] * B[9] */
  10486. "UMULL r6, r7, r8, r12\n\t"
  10487. "ADDS r5, r5, r6\n\t"
  10488. "ADCS r3, r3, r7\n\t"
  10489. "MOV r4, #0x0\n\t"
  10490. "ADC r4, r4, #0x0\n\t"
  10491. /* A[10] * B[10] */
  10492. "LDR r11, [%[a], #40]\n\t"
  10493. "LDR r12, [%[b], #40]\n\t"
  10494. "UMULL r6, r7, r11, r12\n\t"
  10495. "ADDS r5, r5, r6\n\t"
  10496. "ADCS r3, r3, r7\n\t"
  10497. "ADC r4, r4, #0x0\n\t"
  10498. /* A[9] * B[11] */
  10499. "LDR r8, [%[a], #36]\n\t"
  10500. "LDR r9, [%[b], #44]\n\t"
  10501. "UMULL r6, r7, r8, r9\n\t"
  10502. "ADDS r5, r5, r6\n\t"
  10503. "ADCS r3, r3, r7\n\t"
  10504. "ADC r4, r4, #0x0\n\t"
  10505. "STR r5, [%[r], #80]\n\t"
  10506. /* A[10] * B[11] */
  10507. "UMULL r6, r7, r11, r9\n\t"
  10508. "ADDS r3, r3, r6\n\t"
  10509. "ADCS r4, r4, r7\n\t"
  10510. "MOV r5, #0x0\n\t"
  10511. "ADC r5, r5, #0x0\n\t"
  10512. /* A[11] * B[10] */
  10513. "LDR r8, [%[a], #44]\n\t"
  10514. "UMULL r6, r7, r8, r12\n\t"
  10515. "ADDS r3, r3, r6\n\t"
  10516. "ADCS r4, r4, r7\n\t"
  10517. "ADC r5, r5, #0x0\n\t"
  10518. "STR r3, [%[r], #84]\n\t"
  10519. /* A[11] * B[11] */
  10520. "UMLAL r4, r5, r8, r9\n\t"
  10521. "STR r4, [%[r], #88]\n\t"
  10522. "STR r5, [%[r], #92]\n\t"
  10523. "LDM sp!, {r3, r4, r5, r6}\n\t"
  10524. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10525. "LDM sp!, {r3, r4, r5, r6}\n\t"
  10526. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10527. "LDM sp!, {r3, r4, r5, r6}\n\t"
  10528. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10529. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  10530. :
  10531. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r11", "r12", "cc"
  10532. );
  10533. }
  10534. /* Add b to a into r. (r = a + b)
  10535. *
  10536. * r A single precision integer.
  10537. * a A single precision integer.
  10538. * b A single precision integer.
  10539. */
  10540. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10541. static sp_digit sp_3072_add_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  10542. #else
  10543. static sp_digit sp_3072_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  10544. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10545. {
  10546. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10547. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  10548. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  10549. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  10550. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10551. __asm__ __volatile__ (
  10552. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10553. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10554. "ADDS r3, r3, r7\n\t"
  10555. "ADCS r4, r4, r8\n\t"
  10556. "ADCS r5, r5, r9\n\t"
  10557. "ADCS r6, r6, r10\n\t"
  10558. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10559. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10560. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10561. "ADCS r3, r3, r7\n\t"
  10562. "ADCS r4, r4, r8\n\t"
  10563. "ADCS r5, r5, r9\n\t"
  10564. "ADCS r6, r6, r10\n\t"
  10565. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10566. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10567. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10568. "ADCS r3, r3, r7\n\t"
  10569. "ADCS r4, r4, r8\n\t"
  10570. "ADCS r5, r5, r9\n\t"
  10571. "ADCS r6, r6, r10\n\t"
  10572. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10573. "MOV %[r], #0x0\n\t"
  10574. "ADC %[r], %[r], #0x0\n\t"
  10575. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  10576. :
  10577. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  10578. );
  10579. return (uint32_t)(size_t)r;
  10580. }
  10581. /* Sub b from a into a. (a -= b)
  10582. *
  10583. * a A single precision integer and result.
  10584. * b A single precision integer.
  10585. */
  10586. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10587. static sp_digit sp_3072_sub_in_place_24(sp_digit* a_p, const sp_digit* b_p)
  10588. #else
  10589. static sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b)
  10590. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10591. {
  10592. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10593. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  10594. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  10595. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10596. __asm__ __volatile__ (
  10597. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10598. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10599. "SUBS r2, r2, r6\n\t"
  10600. "SBCS r3, r3, r7\n\t"
  10601. "SBCS r4, r4, r8\n\t"
  10602. "SBCS r5, r5, r9\n\t"
  10603. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10604. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10605. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10606. "SBCS r2, r2, r6\n\t"
  10607. "SBCS r3, r3, r7\n\t"
  10608. "SBCS r4, r4, r8\n\t"
  10609. "SBCS r5, r5, r9\n\t"
  10610. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10611. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10612. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10613. "SBCS r2, r2, r6\n\t"
  10614. "SBCS r3, r3, r7\n\t"
  10615. "SBCS r4, r4, r8\n\t"
  10616. "SBCS r5, r5, r9\n\t"
  10617. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10618. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10619. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10620. "SBCS r2, r2, r6\n\t"
  10621. "SBCS r3, r3, r7\n\t"
  10622. "SBCS r4, r4, r8\n\t"
  10623. "SBCS r5, r5, r9\n\t"
  10624. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10625. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10626. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10627. "SBCS r2, r2, r6\n\t"
  10628. "SBCS r3, r3, r7\n\t"
  10629. "SBCS r4, r4, r8\n\t"
  10630. "SBCS r5, r5, r9\n\t"
  10631. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10632. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10633. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10634. "SBCS r2, r2, r6\n\t"
  10635. "SBCS r3, r3, r7\n\t"
  10636. "SBCS r4, r4, r8\n\t"
  10637. "SBCS r5, r5, r9\n\t"
  10638. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10639. "SBC %[a], r9, r9\n\t"
  10640. : [a] "+r" (a), [b] "+r" (b)
  10641. :
  10642. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  10643. );
  10644. return (uint32_t)(size_t)a;
  10645. }
  10646. /* Add b to a into r. (r = a + b)
  10647. *
  10648. * r A single precision integer.
  10649. * a A single precision integer.
  10650. * b A single precision integer.
  10651. */
  10652. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10653. static sp_digit sp_3072_add_24(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  10654. #else
  10655. static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, const sp_digit* b)
  10656. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10657. {
  10658. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10659. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  10660. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  10661. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  10662. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10663. __asm__ __volatile__ (
  10664. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10665. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10666. "ADDS r3, r3, r7\n\t"
  10667. "ADCS r4, r4, r8\n\t"
  10668. "ADCS r5, r5, r9\n\t"
  10669. "ADCS r6, r6, r10\n\t"
  10670. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10671. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10672. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10673. "ADCS r3, r3, r7\n\t"
  10674. "ADCS r4, r4, r8\n\t"
  10675. "ADCS r5, r5, r9\n\t"
  10676. "ADCS r6, r6, r10\n\t"
  10677. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10678. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10679. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10680. "ADCS r3, r3, r7\n\t"
  10681. "ADCS r4, r4, r8\n\t"
  10682. "ADCS r5, r5, r9\n\t"
  10683. "ADCS r6, r6, r10\n\t"
  10684. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10685. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10686. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10687. "ADCS r3, r3, r7\n\t"
  10688. "ADCS r4, r4, r8\n\t"
  10689. "ADCS r5, r5, r9\n\t"
  10690. "ADCS r6, r6, r10\n\t"
  10691. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10692. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10693. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10694. "ADCS r3, r3, r7\n\t"
  10695. "ADCS r4, r4, r8\n\t"
  10696. "ADCS r5, r5, r9\n\t"
  10697. "ADCS r6, r6, r10\n\t"
  10698. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10699. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10700. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10701. "ADCS r3, r3, r7\n\t"
  10702. "ADCS r4, r4, r8\n\t"
  10703. "ADCS r5, r5, r9\n\t"
  10704. "ADCS r6, r6, r10\n\t"
  10705. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10706. "MOV %[r], #0x0\n\t"
  10707. "ADC %[r], %[r], #0x0\n\t"
  10708. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  10709. :
  10710. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  10711. );
  10712. return (uint32_t)(size_t)r;
  10713. }
  10714. /* AND m into each word of a and store in r.
  10715. *
  10716. * r A single precision integer.
  10717. * a A single precision integer.
  10718. * m Mask to AND against each digit.
  10719. */
  10720. static void sp_3072_mask_12(sp_digit* r, const sp_digit* a, sp_digit m)
  10721. {
  10722. #ifdef WOLFSSL_SP_SMALL
  10723. int i;
  10724. for (i=0; i<12; i++) {
  10725. r[i] = a[i] & m;
  10726. }
  10727. #else
  10728. r[0] = a[0] & m;
  10729. r[1] = a[1] & m;
  10730. r[2] = a[2] & m;
  10731. r[3] = a[3] & m;
  10732. r[4] = a[4] & m;
  10733. r[5] = a[5] & m;
  10734. r[6] = a[6] & m;
  10735. r[7] = a[7] & m;
  10736. r[8] = a[8] & m;
  10737. r[9] = a[9] & m;
  10738. r[10] = a[10] & m;
  10739. r[11] = a[11] & m;
  10740. #endif
  10741. }
  10742. /* Multiply a and b into r. (r = a * b)
  10743. *
  10744. * r A single precision integer.
  10745. * a A single precision integer.
  10746. * b A single precision integer.
  10747. */
  10748. SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a,
  10749. const sp_digit* b)
  10750. {
  10751. sp_digit* z0 = r;
  10752. sp_digit z1[24];
  10753. sp_digit a1[12];
  10754. sp_digit b1[12];
  10755. sp_digit* z2 = r + 24;
  10756. sp_digit u;
  10757. sp_digit ca;
  10758. sp_digit cb;
  10759. ca = sp_3072_add_12(a1, a, &a[12]);
  10760. cb = sp_3072_add_12(b1, b, &b[12]);
  10761. u = ca & cb;
  10762. sp_3072_mul_12(z2, &a[12], &b[12]);
  10763. sp_3072_mul_12(z0, a, b);
  10764. sp_3072_mul_12(z1, a1, b1);
  10765. u += sp_3072_sub_in_place_24(z1, z0);
  10766. u += sp_3072_sub_in_place_24(z1, z2);
  10767. sp_3072_mask_12(a1, a1, 0 - cb);
  10768. u += sp_3072_add_12(z1 + 12, z1 + 12, a1);
  10769. sp_3072_mask_12(b1, b1, 0 - ca);
  10770. u += sp_3072_add_12(z1 + 12, z1 + 12, b1);
  10771. u += sp_3072_add_24(r + 12, r + 12, z1);
  10772. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (12 - 1));
  10773. a1[0] = u;
  10774. (void)sp_3072_add_12(r + 36, r + 36, a1);
  10775. }
  10776. /* Sub b from a into a. (a -= b)
  10777. *
  10778. * a A single precision integer and result.
  10779. * b A single precision integer.
  10780. */
  10781. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10782. static sp_digit sp_3072_sub_in_place_48(sp_digit* a_p, const sp_digit* b_p)
  10783. #else
  10784. static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b)
  10785. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10786. {
  10787. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10788. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  10789. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  10790. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10791. __asm__ __volatile__ (
  10792. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10793. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10794. "SUBS r2, r2, r6\n\t"
  10795. "SBCS r3, r3, r7\n\t"
  10796. "SBCS r4, r4, r8\n\t"
  10797. "SBCS r5, r5, r9\n\t"
  10798. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10799. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10800. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10801. "SBCS r2, r2, r6\n\t"
  10802. "SBCS r3, r3, r7\n\t"
  10803. "SBCS r4, r4, r8\n\t"
  10804. "SBCS r5, r5, r9\n\t"
  10805. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10806. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10807. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10808. "SBCS r2, r2, r6\n\t"
  10809. "SBCS r3, r3, r7\n\t"
  10810. "SBCS r4, r4, r8\n\t"
  10811. "SBCS r5, r5, r9\n\t"
  10812. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10813. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10814. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10815. "SBCS r2, r2, r6\n\t"
  10816. "SBCS r3, r3, r7\n\t"
  10817. "SBCS r4, r4, r8\n\t"
  10818. "SBCS r5, r5, r9\n\t"
  10819. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10820. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10821. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10822. "SBCS r2, r2, r6\n\t"
  10823. "SBCS r3, r3, r7\n\t"
  10824. "SBCS r4, r4, r8\n\t"
  10825. "SBCS r5, r5, r9\n\t"
  10826. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10827. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10828. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10829. "SBCS r2, r2, r6\n\t"
  10830. "SBCS r3, r3, r7\n\t"
  10831. "SBCS r4, r4, r8\n\t"
  10832. "SBCS r5, r5, r9\n\t"
  10833. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10834. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10835. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10836. "SBCS r2, r2, r6\n\t"
  10837. "SBCS r3, r3, r7\n\t"
  10838. "SBCS r4, r4, r8\n\t"
  10839. "SBCS r5, r5, r9\n\t"
  10840. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10841. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10842. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10843. "SBCS r2, r2, r6\n\t"
  10844. "SBCS r3, r3, r7\n\t"
  10845. "SBCS r4, r4, r8\n\t"
  10846. "SBCS r5, r5, r9\n\t"
  10847. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10848. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10849. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10850. "SBCS r2, r2, r6\n\t"
  10851. "SBCS r3, r3, r7\n\t"
  10852. "SBCS r4, r4, r8\n\t"
  10853. "SBCS r5, r5, r9\n\t"
  10854. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10855. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10856. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10857. "SBCS r2, r2, r6\n\t"
  10858. "SBCS r3, r3, r7\n\t"
  10859. "SBCS r4, r4, r8\n\t"
  10860. "SBCS r5, r5, r9\n\t"
  10861. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10862. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10863. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10864. "SBCS r2, r2, r6\n\t"
  10865. "SBCS r3, r3, r7\n\t"
  10866. "SBCS r4, r4, r8\n\t"
  10867. "SBCS r5, r5, r9\n\t"
  10868. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10869. "LDM %[a], {r2, r3, r4, r5}\n\t"
  10870. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  10871. "SBCS r2, r2, r6\n\t"
  10872. "SBCS r3, r3, r7\n\t"
  10873. "SBCS r4, r4, r8\n\t"
  10874. "SBCS r5, r5, r9\n\t"
  10875. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  10876. "SBC %[a], r9, r9\n\t"
  10877. : [a] "+r" (a), [b] "+r" (b)
  10878. :
  10879. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  10880. );
  10881. return (uint32_t)(size_t)a;
  10882. }
  10883. /* Add b to a into r. (r = a + b)
  10884. *
  10885. * r A single precision integer.
  10886. * a A single precision integer.
  10887. * b A single precision integer.
  10888. */
  10889. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10890. static sp_digit sp_3072_add_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  10891. #else
  10892. static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b)
  10893. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10894. {
  10895. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  10896. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  10897. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  10898. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  10899. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  10900. __asm__ __volatile__ (
  10901. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10902. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10903. "ADDS r3, r3, r7\n\t"
  10904. "ADCS r4, r4, r8\n\t"
  10905. "ADCS r5, r5, r9\n\t"
  10906. "ADCS r6, r6, r10\n\t"
  10907. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10908. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10909. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10910. "ADCS r3, r3, r7\n\t"
  10911. "ADCS r4, r4, r8\n\t"
  10912. "ADCS r5, r5, r9\n\t"
  10913. "ADCS r6, r6, r10\n\t"
  10914. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10915. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10916. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10917. "ADCS r3, r3, r7\n\t"
  10918. "ADCS r4, r4, r8\n\t"
  10919. "ADCS r5, r5, r9\n\t"
  10920. "ADCS r6, r6, r10\n\t"
  10921. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10922. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10923. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10924. "ADCS r3, r3, r7\n\t"
  10925. "ADCS r4, r4, r8\n\t"
  10926. "ADCS r5, r5, r9\n\t"
  10927. "ADCS r6, r6, r10\n\t"
  10928. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10929. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10930. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10931. "ADCS r3, r3, r7\n\t"
  10932. "ADCS r4, r4, r8\n\t"
  10933. "ADCS r5, r5, r9\n\t"
  10934. "ADCS r6, r6, r10\n\t"
  10935. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10936. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10937. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10938. "ADCS r3, r3, r7\n\t"
  10939. "ADCS r4, r4, r8\n\t"
  10940. "ADCS r5, r5, r9\n\t"
  10941. "ADCS r6, r6, r10\n\t"
  10942. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10943. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10944. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10945. "ADCS r3, r3, r7\n\t"
  10946. "ADCS r4, r4, r8\n\t"
  10947. "ADCS r5, r5, r9\n\t"
  10948. "ADCS r6, r6, r10\n\t"
  10949. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10950. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10951. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10952. "ADCS r3, r3, r7\n\t"
  10953. "ADCS r4, r4, r8\n\t"
  10954. "ADCS r5, r5, r9\n\t"
  10955. "ADCS r6, r6, r10\n\t"
  10956. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10957. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10958. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10959. "ADCS r3, r3, r7\n\t"
  10960. "ADCS r4, r4, r8\n\t"
  10961. "ADCS r5, r5, r9\n\t"
  10962. "ADCS r6, r6, r10\n\t"
  10963. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10964. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10965. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10966. "ADCS r3, r3, r7\n\t"
  10967. "ADCS r4, r4, r8\n\t"
  10968. "ADCS r5, r5, r9\n\t"
  10969. "ADCS r6, r6, r10\n\t"
  10970. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10971. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10972. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10973. "ADCS r3, r3, r7\n\t"
  10974. "ADCS r4, r4, r8\n\t"
  10975. "ADCS r5, r5, r9\n\t"
  10976. "ADCS r6, r6, r10\n\t"
  10977. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10978. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  10979. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  10980. "ADCS r3, r3, r7\n\t"
  10981. "ADCS r4, r4, r8\n\t"
  10982. "ADCS r5, r5, r9\n\t"
  10983. "ADCS r6, r6, r10\n\t"
  10984. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  10985. "MOV %[r], #0x0\n\t"
  10986. "ADC %[r], %[r], #0x0\n\t"
  10987. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  10988. :
  10989. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  10990. );
  10991. return (uint32_t)(size_t)r;
  10992. }
  10993. /* AND m into each word of a and store in r.
  10994. *
  10995. * r A single precision integer.
  10996. * a A single precision integer.
  10997. * m Mask to AND against each digit.
  10998. */
  10999. static void sp_3072_mask_24(sp_digit* r, const sp_digit* a, sp_digit m)
  11000. {
  11001. #ifdef WOLFSSL_SP_SMALL
  11002. int i;
  11003. for (i=0; i<24; i++) {
  11004. r[i] = a[i] & m;
  11005. }
  11006. #else
  11007. int i;
  11008. for (i = 0; i < 24; i += 8) {
  11009. r[i+0] = a[i+0] & m;
  11010. r[i+1] = a[i+1] & m;
  11011. r[i+2] = a[i+2] & m;
  11012. r[i+3] = a[i+3] & m;
  11013. r[i+4] = a[i+4] & m;
  11014. r[i+5] = a[i+5] & m;
  11015. r[i+6] = a[i+6] & m;
  11016. r[i+7] = a[i+7] & m;
  11017. }
  11018. #endif
  11019. }
  11020. /* Multiply a and b into r. (r = a * b)
  11021. *
  11022. * r A single precision integer.
  11023. * a A single precision integer.
  11024. * b A single precision integer.
  11025. */
  11026. SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
  11027. const sp_digit* b)
  11028. {
  11029. sp_digit* z0 = r;
  11030. sp_digit z1[48];
  11031. sp_digit a1[24];
  11032. sp_digit b1[24];
  11033. sp_digit* z2 = r + 48;
  11034. sp_digit u;
  11035. sp_digit ca;
  11036. sp_digit cb;
  11037. ca = sp_3072_add_24(a1, a, &a[24]);
  11038. cb = sp_3072_add_24(b1, b, &b[24]);
  11039. u = ca & cb;
  11040. sp_3072_mul_24(z2, &a[24], &b[24]);
  11041. sp_3072_mul_24(z0, a, b);
  11042. sp_3072_mul_24(z1, a1, b1);
  11043. u += sp_3072_sub_in_place_48(z1, z0);
  11044. u += sp_3072_sub_in_place_48(z1, z2);
  11045. sp_3072_mask_24(a1, a1, 0 - cb);
  11046. u += sp_3072_add_24(z1 + 24, z1 + 24, a1);
  11047. sp_3072_mask_24(b1, b1, 0 - ca);
  11048. u += sp_3072_add_24(z1 + 24, z1 + 24, b1);
  11049. u += sp_3072_add_48(r + 24, r + 24, z1);
  11050. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (24 - 1));
  11051. a1[0] = u;
  11052. (void)sp_3072_add_24(r + 72, r + 72, a1);
  11053. }
  11054. /* Sub b from a into a. (a -= b)
  11055. *
  11056. * a A single precision integer and result.
  11057. * b A single precision integer.
  11058. */
  11059. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  11060. static sp_digit sp_3072_sub_in_place_96(sp_digit* a_p, const sp_digit* b_p)
  11061. #else
  11062. static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b)
  11063. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  11064. {
  11065. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  11066. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  11067. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  11068. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  11069. __asm__ __volatile__ (
  11070. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11071. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11072. "SUBS r2, r2, r6\n\t"
  11073. "SBCS r3, r3, r7\n\t"
  11074. "SBCS r4, r4, r8\n\t"
  11075. "SBCS r5, r5, r9\n\t"
  11076. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11077. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11078. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11079. "SBCS r2, r2, r6\n\t"
  11080. "SBCS r3, r3, r7\n\t"
  11081. "SBCS r4, r4, r8\n\t"
  11082. "SBCS r5, r5, r9\n\t"
  11083. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11084. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11085. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11086. "SBCS r2, r2, r6\n\t"
  11087. "SBCS r3, r3, r7\n\t"
  11088. "SBCS r4, r4, r8\n\t"
  11089. "SBCS r5, r5, r9\n\t"
  11090. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11091. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11092. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11093. "SBCS r2, r2, r6\n\t"
  11094. "SBCS r3, r3, r7\n\t"
  11095. "SBCS r4, r4, r8\n\t"
  11096. "SBCS r5, r5, r9\n\t"
  11097. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11098. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11099. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11100. "SBCS r2, r2, r6\n\t"
  11101. "SBCS r3, r3, r7\n\t"
  11102. "SBCS r4, r4, r8\n\t"
  11103. "SBCS r5, r5, r9\n\t"
  11104. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11105. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11106. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11107. "SBCS r2, r2, r6\n\t"
  11108. "SBCS r3, r3, r7\n\t"
  11109. "SBCS r4, r4, r8\n\t"
  11110. "SBCS r5, r5, r9\n\t"
  11111. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11112. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11113. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11114. "SBCS r2, r2, r6\n\t"
  11115. "SBCS r3, r3, r7\n\t"
  11116. "SBCS r4, r4, r8\n\t"
  11117. "SBCS r5, r5, r9\n\t"
  11118. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11119. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11120. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11121. "SBCS r2, r2, r6\n\t"
  11122. "SBCS r3, r3, r7\n\t"
  11123. "SBCS r4, r4, r8\n\t"
  11124. "SBCS r5, r5, r9\n\t"
  11125. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11126. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11127. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11128. "SBCS r2, r2, r6\n\t"
  11129. "SBCS r3, r3, r7\n\t"
  11130. "SBCS r4, r4, r8\n\t"
  11131. "SBCS r5, r5, r9\n\t"
  11132. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11133. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11134. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11135. "SBCS r2, r2, r6\n\t"
  11136. "SBCS r3, r3, r7\n\t"
  11137. "SBCS r4, r4, r8\n\t"
  11138. "SBCS r5, r5, r9\n\t"
  11139. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11140. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11141. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11142. "SBCS r2, r2, r6\n\t"
  11143. "SBCS r3, r3, r7\n\t"
  11144. "SBCS r4, r4, r8\n\t"
  11145. "SBCS r5, r5, r9\n\t"
  11146. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11147. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11148. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11149. "SBCS r2, r2, r6\n\t"
  11150. "SBCS r3, r3, r7\n\t"
  11151. "SBCS r4, r4, r8\n\t"
  11152. "SBCS r5, r5, r9\n\t"
  11153. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11154. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11155. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11156. "SBCS r2, r2, r6\n\t"
  11157. "SBCS r3, r3, r7\n\t"
  11158. "SBCS r4, r4, r8\n\t"
  11159. "SBCS r5, r5, r9\n\t"
  11160. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11161. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11162. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11163. "SBCS r2, r2, r6\n\t"
  11164. "SBCS r3, r3, r7\n\t"
  11165. "SBCS r4, r4, r8\n\t"
  11166. "SBCS r5, r5, r9\n\t"
  11167. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11168. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11169. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11170. "SBCS r2, r2, r6\n\t"
  11171. "SBCS r3, r3, r7\n\t"
  11172. "SBCS r4, r4, r8\n\t"
  11173. "SBCS r5, r5, r9\n\t"
  11174. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11175. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11176. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11177. "SBCS r2, r2, r6\n\t"
  11178. "SBCS r3, r3, r7\n\t"
  11179. "SBCS r4, r4, r8\n\t"
  11180. "SBCS r5, r5, r9\n\t"
  11181. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11182. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11183. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11184. "SBCS r2, r2, r6\n\t"
  11185. "SBCS r3, r3, r7\n\t"
  11186. "SBCS r4, r4, r8\n\t"
  11187. "SBCS r5, r5, r9\n\t"
  11188. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11189. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11190. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11191. "SBCS r2, r2, r6\n\t"
  11192. "SBCS r3, r3, r7\n\t"
  11193. "SBCS r4, r4, r8\n\t"
  11194. "SBCS r5, r5, r9\n\t"
  11195. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11196. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11197. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11198. "SBCS r2, r2, r6\n\t"
  11199. "SBCS r3, r3, r7\n\t"
  11200. "SBCS r4, r4, r8\n\t"
  11201. "SBCS r5, r5, r9\n\t"
  11202. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11203. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11204. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11205. "SBCS r2, r2, r6\n\t"
  11206. "SBCS r3, r3, r7\n\t"
  11207. "SBCS r4, r4, r8\n\t"
  11208. "SBCS r5, r5, r9\n\t"
  11209. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11210. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11211. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11212. "SBCS r2, r2, r6\n\t"
  11213. "SBCS r3, r3, r7\n\t"
  11214. "SBCS r4, r4, r8\n\t"
  11215. "SBCS r5, r5, r9\n\t"
  11216. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11217. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11218. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11219. "SBCS r2, r2, r6\n\t"
  11220. "SBCS r3, r3, r7\n\t"
  11221. "SBCS r4, r4, r8\n\t"
  11222. "SBCS r5, r5, r9\n\t"
  11223. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11224. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11225. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11226. "SBCS r2, r2, r6\n\t"
  11227. "SBCS r3, r3, r7\n\t"
  11228. "SBCS r4, r4, r8\n\t"
  11229. "SBCS r5, r5, r9\n\t"
  11230. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11231. "LDM %[a], {r2, r3, r4, r5}\n\t"
  11232. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  11233. "SBCS r2, r2, r6\n\t"
  11234. "SBCS r3, r3, r7\n\t"
  11235. "SBCS r4, r4, r8\n\t"
  11236. "SBCS r5, r5, r9\n\t"
  11237. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  11238. "SBC %[a], r9, r9\n\t"
  11239. : [a] "+r" (a), [b] "+r" (b)
  11240. :
  11241. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  11242. );
  11243. return (uint32_t)(size_t)a;
  11244. }
  11245. /* Add b to a into r. (r = a + b)
  11246. *
  11247. * r A single precision integer.
  11248. * a A single precision integer.
  11249. * b A single precision integer.
  11250. */
  11251. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  11252. static sp_digit sp_3072_add_96(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  11253. #else
  11254. static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, const sp_digit* b)
  11255. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  11256. {
  11257. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  11258. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  11259. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  11260. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  11261. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  11262. __asm__ __volatile__ (
  11263. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11264. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11265. "ADDS r3, r3, r7\n\t"
  11266. "ADCS r4, r4, r8\n\t"
  11267. "ADCS r5, r5, r9\n\t"
  11268. "ADCS r6, r6, r10\n\t"
  11269. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11270. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11271. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11272. "ADCS r3, r3, r7\n\t"
  11273. "ADCS r4, r4, r8\n\t"
  11274. "ADCS r5, r5, r9\n\t"
  11275. "ADCS r6, r6, r10\n\t"
  11276. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11277. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11278. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11279. "ADCS r3, r3, r7\n\t"
  11280. "ADCS r4, r4, r8\n\t"
  11281. "ADCS r5, r5, r9\n\t"
  11282. "ADCS r6, r6, r10\n\t"
  11283. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11284. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11285. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11286. "ADCS r3, r3, r7\n\t"
  11287. "ADCS r4, r4, r8\n\t"
  11288. "ADCS r5, r5, r9\n\t"
  11289. "ADCS r6, r6, r10\n\t"
  11290. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11291. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11292. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11293. "ADCS r3, r3, r7\n\t"
  11294. "ADCS r4, r4, r8\n\t"
  11295. "ADCS r5, r5, r9\n\t"
  11296. "ADCS r6, r6, r10\n\t"
  11297. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11298. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11299. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11300. "ADCS r3, r3, r7\n\t"
  11301. "ADCS r4, r4, r8\n\t"
  11302. "ADCS r5, r5, r9\n\t"
  11303. "ADCS r6, r6, r10\n\t"
  11304. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11305. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11306. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11307. "ADCS r3, r3, r7\n\t"
  11308. "ADCS r4, r4, r8\n\t"
  11309. "ADCS r5, r5, r9\n\t"
  11310. "ADCS r6, r6, r10\n\t"
  11311. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11312. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11313. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11314. "ADCS r3, r3, r7\n\t"
  11315. "ADCS r4, r4, r8\n\t"
  11316. "ADCS r5, r5, r9\n\t"
  11317. "ADCS r6, r6, r10\n\t"
  11318. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11319. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11320. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11321. "ADCS r3, r3, r7\n\t"
  11322. "ADCS r4, r4, r8\n\t"
  11323. "ADCS r5, r5, r9\n\t"
  11324. "ADCS r6, r6, r10\n\t"
  11325. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11326. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11327. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11328. "ADCS r3, r3, r7\n\t"
  11329. "ADCS r4, r4, r8\n\t"
  11330. "ADCS r5, r5, r9\n\t"
  11331. "ADCS r6, r6, r10\n\t"
  11332. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11333. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11334. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11335. "ADCS r3, r3, r7\n\t"
  11336. "ADCS r4, r4, r8\n\t"
  11337. "ADCS r5, r5, r9\n\t"
  11338. "ADCS r6, r6, r10\n\t"
  11339. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11340. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11341. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11342. "ADCS r3, r3, r7\n\t"
  11343. "ADCS r4, r4, r8\n\t"
  11344. "ADCS r5, r5, r9\n\t"
  11345. "ADCS r6, r6, r10\n\t"
  11346. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11347. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11348. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11349. "ADCS r3, r3, r7\n\t"
  11350. "ADCS r4, r4, r8\n\t"
  11351. "ADCS r5, r5, r9\n\t"
  11352. "ADCS r6, r6, r10\n\t"
  11353. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11354. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11355. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11356. "ADCS r3, r3, r7\n\t"
  11357. "ADCS r4, r4, r8\n\t"
  11358. "ADCS r5, r5, r9\n\t"
  11359. "ADCS r6, r6, r10\n\t"
  11360. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11361. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11362. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11363. "ADCS r3, r3, r7\n\t"
  11364. "ADCS r4, r4, r8\n\t"
  11365. "ADCS r5, r5, r9\n\t"
  11366. "ADCS r6, r6, r10\n\t"
  11367. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11368. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11369. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11370. "ADCS r3, r3, r7\n\t"
  11371. "ADCS r4, r4, r8\n\t"
  11372. "ADCS r5, r5, r9\n\t"
  11373. "ADCS r6, r6, r10\n\t"
  11374. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11375. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11376. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11377. "ADCS r3, r3, r7\n\t"
  11378. "ADCS r4, r4, r8\n\t"
  11379. "ADCS r5, r5, r9\n\t"
  11380. "ADCS r6, r6, r10\n\t"
  11381. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11382. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11383. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11384. "ADCS r3, r3, r7\n\t"
  11385. "ADCS r4, r4, r8\n\t"
  11386. "ADCS r5, r5, r9\n\t"
  11387. "ADCS r6, r6, r10\n\t"
  11388. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11389. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11390. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11391. "ADCS r3, r3, r7\n\t"
  11392. "ADCS r4, r4, r8\n\t"
  11393. "ADCS r5, r5, r9\n\t"
  11394. "ADCS r6, r6, r10\n\t"
  11395. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11396. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11397. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11398. "ADCS r3, r3, r7\n\t"
  11399. "ADCS r4, r4, r8\n\t"
  11400. "ADCS r5, r5, r9\n\t"
  11401. "ADCS r6, r6, r10\n\t"
  11402. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11403. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11404. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11405. "ADCS r3, r3, r7\n\t"
  11406. "ADCS r4, r4, r8\n\t"
  11407. "ADCS r5, r5, r9\n\t"
  11408. "ADCS r6, r6, r10\n\t"
  11409. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11410. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11411. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11412. "ADCS r3, r3, r7\n\t"
  11413. "ADCS r4, r4, r8\n\t"
  11414. "ADCS r5, r5, r9\n\t"
  11415. "ADCS r6, r6, r10\n\t"
  11416. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11417. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11418. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11419. "ADCS r3, r3, r7\n\t"
  11420. "ADCS r4, r4, r8\n\t"
  11421. "ADCS r5, r5, r9\n\t"
  11422. "ADCS r6, r6, r10\n\t"
  11423. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11424. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  11425. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  11426. "ADCS r3, r3, r7\n\t"
  11427. "ADCS r4, r4, r8\n\t"
  11428. "ADCS r5, r5, r9\n\t"
  11429. "ADCS r6, r6, r10\n\t"
  11430. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  11431. "MOV %[r], #0x0\n\t"
  11432. "ADC %[r], %[r], #0x0\n\t"
  11433. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  11434. :
  11435. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  11436. );
  11437. return (uint32_t)(size_t)r;
  11438. }
  11439. /* AND m into each word of a and store in r.
  11440. *
  11441. * r A single precision integer.
  11442. * a A single precision integer.
  11443. * m Mask to AND against each digit.
  11444. */
  11445. static void sp_3072_mask_48(sp_digit* r, const sp_digit* a, sp_digit m)
  11446. {
  11447. #ifdef WOLFSSL_SP_SMALL
  11448. int i;
  11449. for (i=0; i<48; i++) {
  11450. r[i] = a[i] & m;
  11451. }
  11452. #else
  11453. int i;
  11454. for (i = 0; i < 48; i += 8) {
  11455. r[i+0] = a[i+0] & m;
  11456. r[i+1] = a[i+1] & m;
  11457. r[i+2] = a[i+2] & m;
  11458. r[i+3] = a[i+3] & m;
  11459. r[i+4] = a[i+4] & m;
  11460. r[i+5] = a[i+5] & m;
  11461. r[i+6] = a[i+6] & m;
  11462. r[i+7] = a[i+7] & m;
  11463. }
  11464. #endif
  11465. }
  11466. /* Multiply a and b into r. (r = a * b)
  11467. *
  11468. * r A single precision integer.
  11469. * a A single precision integer.
  11470. * b A single precision integer.
  11471. */
  11472. SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a,
  11473. const sp_digit* b)
  11474. {
  11475. sp_digit* z0 = r;
  11476. sp_digit z1[96];
  11477. sp_digit a1[48];
  11478. sp_digit b1[48];
  11479. sp_digit* z2 = r + 96;
  11480. sp_digit u;
  11481. sp_digit ca;
  11482. sp_digit cb;
  11483. ca = sp_3072_add_48(a1, a, &a[48]);
  11484. cb = sp_3072_add_48(b1, b, &b[48]);
  11485. u = ca & cb;
  11486. sp_3072_mul_48(z2, &a[48], &b[48]);
  11487. sp_3072_mul_48(z0, a, b);
  11488. sp_3072_mul_48(z1, a1, b1);
  11489. u += sp_3072_sub_in_place_96(z1, z0);
  11490. u += sp_3072_sub_in_place_96(z1, z2);
  11491. sp_3072_mask_48(a1, a1, 0 - cb);
  11492. u += sp_3072_add_48(z1 + 48, z1 + 48, a1);
  11493. sp_3072_mask_48(b1, b1, 0 - ca);
  11494. u += sp_3072_add_48(z1 + 48, z1 + 48, b1);
  11495. u += sp_3072_add_96(r + 48, r + 48, z1);
  11496. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (48 - 1));
  11497. a1[0] = u;
  11498. (void)sp_3072_add_48(r + 144, r + 144, a1);
  11499. }
  11500. /* Square a and put result in r. (r = a * a)
  11501. *
  11502. * r A single precision integer.
  11503. * a A single precision integer.
  11504. */
  11505. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  11506. static void sp_3072_sqr_12(sp_digit* r_p, const sp_digit* a_p)
  11507. #else
  11508. static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
  11509. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  11510. {
  11511. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  11512. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  11513. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  11514. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  11515. __asm__ __volatile__ (
  11516. "SUB sp, sp, #0x30\n\t"
  11517. /* A[0] * A[0] */
  11518. "LDR r10, [%[a]]\n\t"
  11519. "UMULL r8, r3, r10, r10\n\t"
  11520. "MOV r4, #0x0\n\t"
  11521. "STR r8, [sp]\n\t"
  11522. /* A[0] * A[1] */
  11523. "LDR r10, [%[a], #4]\n\t"
  11524. "LDR r12, [%[a]]\n\t"
  11525. "UMULL r8, r9, r10, r12\n\t"
  11526. "ADDS r3, r3, r8\n\t"
  11527. "ADCS r4, r4, r9\n\t"
  11528. "MOV r2, #0x0\n\t"
  11529. "ADC r2, r2, #0x0\n\t"
  11530. "ADDS r3, r3, r8\n\t"
  11531. "ADCS r4, r4, r9\n\t"
  11532. "MOV r2, #0x0\n\t"
  11533. "ADC r2, r2, #0x0\n\t"
  11534. "STR r3, [sp, #4]\n\t"
  11535. /* A[0] * A[2] */
  11536. "LDR r10, [%[a], #8]\n\t"
  11537. "LDR r12, [%[a]]\n\t"
  11538. "UMULL r8, r9, r10, r12\n\t"
  11539. "ADDS r4, r4, r8\n\t"
  11540. "ADCS r2, r2, r9\n\t"
  11541. "MOV r3, #0x0\n\t"
  11542. "ADC r3, r3, #0x0\n\t"
  11543. "ADDS r4, r4, r8\n\t"
  11544. "ADCS r2, r2, r9\n\t"
  11545. "MOV r3, #0x0\n\t"
  11546. "ADC r3, r3, #0x0\n\t"
  11547. /* A[1] * A[1] */
  11548. "LDR r10, [%[a], #4]\n\t"
  11549. "UMULL r8, r9, r10, r10\n\t"
  11550. "ADDS r4, r4, r8\n\t"
  11551. "ADCS r2, r2, r9\n\t"
  11552. "ADC r3, r3, #0x0\n\t"
  11553. "STR r4, [sp, #8]\n\t"
  11554. /* A[0] * A[3] */
  11555. "LDR r10, [%[a], #12]\n\t"
  11556. "LDR r12, [%[a]]\n\t"
  11557. "UMULL r8, r9, r10, r12\n\t"
  11558. "ADDS r2, r2, r8\n\t"
  11559. "ADCS r3, r3, r9\n\t"
  11560. "MOV r4, #0x0\n\t"
  11561. "ADC r4, r4, #0x0\n\t"
  11562. "ADDS r2, r2, r8\n\t"
  11563. "ADCS r3, r3, r9\n\t"
  11564. "MOV r4, #0x0\n\t"
  11565. "ADC r4, r4, #0x0\n\t"
  11566. /* A[1] * A[2] */
  11567. "LDR r10, [%[a], #8]\n\t"
  11568. "LDR r12, [%[a], #4]\n\t"
  11569. "UMULL r8, r9, r10, r12\n\t"
  11570. "ADDS r2, r2, r8\n\t"
  11571. "ADCS r3, r3, r9\n\t"
  11572. "ADC r4, r4, #0x0\n\t"
  11573. "ADDS r2, r2, r8\n\t"
  11574. "ADCS r3, r3, r9\n\t"
  11575. "ADC r4, r4, #0x0\n\t"
  11576. "STR r2, [sp, #12]\n\t"
  11577. /* A[0] * A[4] */
  11578. "LDR r10, [%[a], #16]\n\t"
  11579. "LDR r12, [%[a]]\n\t"
  11580. "UMULL r8, r9, r10, r12\n\t"
  11581. "ADDS r3, r3, r8\n\t"
  11582. "ADCS r4, r4, r9\n\t"
  11583. "MOV r2, #0x0\n\t"
  11584. "ADC r2, r2, #0x0\n\t"
  11585. "ADDS r3, r3, r8\n\t"
  11586. "ADCS r4, r4, r9\n\t"
  11587. "MOV r2, #0x0\n\t"
  11588. "ADC r2, r2, #0x0\n\t"
  11589. /* A[1] * A[3] */
  11590. "LDR r10, [%[a], #12]\n\t"
  11591. "LDR r12, [%[a], #4]\n\t"
  11592. "UMULL r8, r9, r10, r12\n\t"
  11593. "ADDS r3, r3, r8\n\t"
  11594. "ADCS r4, r4, r9\n\t"
  11595. "ADC r2, r2, #0x0\n\t"
  11596. "ADDS r3, r3, r8\n\t"
  11597. "ADCS r4, r4, r9\n\t"
  11598. "ADC r2, r2, #0x0\n\t"
  11599. /* A[2] * A[2] */
  11600. "LDR r10, [%[a], #8]\n\t"
  11601. "UMULL r8, r9, r10, r10\n\t"
  11602. "ADDS r3, r3, r8\n\t"
  11603. "ADCS r4, r4, r9\n\t"
  11604. "ADC r2, r2, #0x0\n\t"
  11605. "STR r3, [sp, #16]\n\t"
  11606. /* A[0] * A[5] */
  11607. "LDR r10, [%[a], #20]\n\t"
  11608. "LDR r12, [%[a]]\n\t"
  11609. "UMULL r5, r6, r10, r12\n\t"
  11610. "MOV r3, #0x0\n\t"
  11611. "MOV r7, #0x0\n\t"
  11612. /* A[1] * A[4] */
  11613. "LDR r10, [%[a], #16]\n\t"
  11614. "LDR r12, [%[a], #4]\n\t"
  11615. "UMULL r8, r9, r10, r12\n\t"
  11616. "ADDS r5, r5, r8\n\t"
  11617. "ADCS r6, r6, r9\n\t"
  11618. "ADC r7, r7, #0x0\n\t"
  11619. /* A[2] * A[3] */
  11620. "LDR r10, [%[a], #12]\n\t"
  11621. "LDR r12, [%[a], #8]\n\t"
  11622. "UMULL r8, r9, r10, r12\n\t"
  11623. "ADDS r5, r5, r8\n\t"
  11624. "ADCS r6, r6, r9\n\t"
  11625. "ADC r7, r7, #0x0\n\t"
  11626. "ADDS r5, r5, r5\n\t"
  11627. "ADCS r6, r6, r6\n\t"
  11628. "ADC r7, r7, r7\n\t"
  11629. "ADDS r4, r4, r5\n\t"
  11630. "ADCS r2, r2, r6\n\t"
  11631. "ADC r3, r3, r7\n\t"
  11632. "STR r4, [sp, #20]\n\t"
  11633. /* A[0] * A[6] */
  11634. "LDR r10, [%[a], #24]\n\t"
  11635. "LDR r12, [%[a]]\n\t"
  11636. "UMULL r5, r6, r10, r12\n\t"
  11637. "MOV r4, #0x0\n\t"
  11638. "MOV r7, #0x0\n\t"
  11639. /* A[1] * A[5] */
  11640. "LDR r10, [%[a], #20]\n\t"
  11641. "LDR r12, [%[a], #4]\n\t"
  11642. "UMULL r8, r9, r10, r12\n\t"
  11643. "ADDS r5, r5, r8\n\t"
  11644. "ADCS r6, r6, r9\n\t"
  11645. "ADC r7, r7, #0x0\n\t"
  11646. /* A[2] * A[4] */
  11647. "LDR r10, [%[a], #16]\n\t"
  11648. "LDR r12, [%[a], #8]\n\t"
  11649. "UMULL r8, r9, r10, r12\n\t"
  11650. "ADDS r5, r5, r8\n\t"
  11651. "ADCS r6, r6, r9\n\t"
  11652. "ADC r7, r7, #0x0\n\t"
  11653. /* A[3] * A[3] */
  11654. "LDR r10, [%[a], #12]\n\t"
  11655. "UMULL r8, r9, r10, r10\n\t"
  11656. "ADDS r5, r5, r5\n\t"
  11657. "ADCS r6, r6, r6\n\t"
  11658. "ADC r7, r7, r7\n\t"
  11659. "ADDS r2, r2, r8\n\t"
  11660. "ADCS r3, r3, r9\n\t"
  11661. "ADC r4, r4, #0x0\n\t"
  11662. "ADDS r2, r2, r5\n\t"
  11663. "ADCS r3, r3, r6\n\t"
  11664. "ADC r4, r4, r7\n\t"
  11665. "STR r2, [sp, #24]\n\t"
  11666. /* A[0] * A[7] */
  11667. "LDR r10, [%[a], #28]\n\t"
  11668. "LDR r12, [%[a]]\n\t"
  11669. "UMULL r5, r6, r10, r12\n\t"
  11670. "MOV r2, #0x0\n\t"
  11671. "MOV r7, #0x0\n\t"
  11672. /* A[1] * A[6] */
  11673. "LDR r10, [%[a], #24]\n\t"
  11674. "LDR r12, [%[a], #4]\n\t"
  11675. "UMULL r8, r9, r10, r12\n\t"
  11676. "ADDS r5, r5, r8\n\t"
  11677. "ADCS r6, r6, r9\n\t"
  11678. "ADC r7, r7, #0x0\n\t"
  11679. /* A[2] * A[5] */
  11680. "LDR r10, [%[a], #20]\n\t"
  11681. "LDR r12, [%[a], #8]\n\t"
  11682. "UMULL r8, r9, r10, r12\n\t"
  11683. "ADDS r5, r5, r8\n\t"
  11684. "ADCS r6, r6, r9\n\t"
  11685. "ADC r7, r7, #0x0\n\t"
  11686. /* A[3] * A[4] */
  11687. "LDR r10, [%[a], #16]\n\t"
  11688. "LDR r12, [%[a], #12]\n\t"
  11689. "UMULL r8, r9, r10, r12\n\t"
  11690. "ADDS r5, r5, r8\n\t"
  11691. "ADCS r6, r6, r9\n\t"
  11692. "ADC r7, r7, #0x0\n\t"
  11693. "ADDS r5, r5, r5\n\t"
  11694. "ADCS r6, r6, r6\n\t"
  11695. "ADC r7, r7, r7\n\t"
  11696. "ADDS r3, r3, r5\n\t"
  11697. "ADCS r4, r4, r6\n\t"
  11698. "ADC r2, r2, r7\n\t"
  11699. "STR r3, [sp, #28]\n\t"
  11700. /* A[0] * A[8] */
  11701. "LDR r10, [%[a], #32]\n\t"
  11702. "LDR r12, [%[a]]\n\t"
  11703. "UMULL r5, r6, r10, r12\n\t"
  11704. "MOV r3, #0x0\n\t"
  11705. "MOV r7, #0x0\n\t"
  11706. /* A[1] * A[7] */
  11707. "LDR r10, [%[a], #28]\n\t"
  11708. "LDR r12, [%[a], #4]\n\t"
  11709. "UMULL r8, r9, r10, r12\n\t"
  11710. "ADDS r5, r5, r8\n\t"
  11711. "ADCS r6, r6, r9\n\t"
  11712. "ADC r7, r7, #0x0\n\t"
  11713. /* A[2] * A[6] */
  11714. "LDR r10, [%[a], #24]\n\t"
  11715. "LDR r12, [%[a], #8]\n\t"
  11716. "UMULL r8, r9, r10, r12\n\t"
  11717. "ADDS r5, r5, r8\n\t"
  11718. "ADCS r6, r6, r9\n\t"
  11719. "ADC r7, r7, #0x0\n\t"
  11720. /* A[3] * A[5] */
  11721. "LDR r10, [%[a], #20]\n\t"
  11722. "LDR r12, [%[a], #12]\n\t"
  11723. "UMULL r8, r9, r10, r12\n\t"
  11724. "ADDS r5, r5, r8\n\t"
  11725. "ADCS r6, r6, r9\n\t"
  11726. "ADC r7, r7, #0x0\n\t"
  11727. /* A[4] * A[4] */
  11728. "LDR r10, [%[a], #16]\n\t"
  11729. "UMULL r8, r9, r10, r10\n\t"
  11730. "ADDS r5, r5, r5\n\t"
  11731. "ADCS r6, r6, r6\n\t"
  11732. "ADC r7, r7, r7\n\t"
  11733. "ADDS r4, r4, r8\n\t"
  11734. "ADCS r2, r2, r9\n\t"
  11735. "ADC r3, r3, #0x0\n\t"
  11736. "ADDS r4, r4, r5\n\t"
  11737. "ADCS r2, r2, r6\n\t"
  11738. "ADC r3, r3, r7\n\t"
  11739. "STR r4, [sp, #32]\n\t"
  11740. /* A[0] * A[9] */
  11741. "LDR r10, [%[a], #36]\n\t"
  11742. "LDR r12, [%[a]]\n\t"
  11743. "UMULL r5, r6, r10, r12\n\t"
  11744. "MOV r4, #0x0\n\t"
  11745. "MOV r7, #0x0\n\t"
  11746. /* A[1] * A[8] */
  11747. "LDR r10, [%[a], #32]\n\t"
  11748. "LDR r12, [%[a], #4]\n\t"
  11749. "UMULL r8, r9, r10, r12\n\t"
  11750. "ADDS r5, r5, r8\n\t"
  11751. "ADCS r6, r6, r9\n\t"
  11752. "ADC r7, r7, #0x0\n\t"
  11753. /* A[2] * A[7] */
  11754. "LDR r10, [%[a], #28]\n\t"
  11755. "LDR r12, [%[a], #8]\n\t"
  11756. "UMULL r8, r9, r10, r12\n\t"
  11757. "ADDS r5, r5, r8\n\t"
  11758. "ADCS r6, r6, r9\n\t"
  11759. "ADC r7, r7, #0x0\n\t"
  11760. /* A[3] * A[6] */
  11761. "LDR r10, [%[a], #24]\n\t"
  11762. "LDR r12, [%[a], #12]\n\t"
  11763. "UMULL r8, r9, r10, r12\n\t"
  11764. "ADDS r5, r5, r8\n\t"
  11765. "ADCS r6, r6, r9\n\t"
  11766. "ADC r7, r7, #0x0\n\t"
  11767. /* A[4] * A[5] */
  11768. "LDR r10, [%[a], #20]\n\t"
  11769. "LDR r12, [%[a], #16]\n\t"
  11770. "UMULL r8, r9, r10, r12\n\t"
  11771. "ADDS r5, r5, r8\n\t"
  11772. "ADCS r6, r6, r9\n\t"
  11773. "ADC r7, r7, #0x0\n\t"
  11774. "ADDS r5, r5, r5\n\t"
  11775. "ADCS r6, r6, r6\n\t"
  11776. "ADC r7, r7, r7\n\t"
  11777. "ADDS r2, r2, r5\n\t"
  11778. "ADCS r3, r3, r6\n\t"
  11779. "ADC r4, r4, r7\n\t"
  11780. "STR r2, [sp, #36]\n\t"
  11781. /* A[0] * A[10] */
  11782. "LDR r10, [%[a], #40]\n\t"
  11783. "LDR r12, [%[a]]\n\t"
  11784. "UMULL r5, r6, r10, r12\n\t"
  11785. "MOV r2, #0x0\n\t"
  11786. "MOV r7, #0x0\n\t"
  11787. /* A[1] * A[9] */
  11788. "LDR r10, [%[a], #36]\n\t"
  11789. "LDR r12, [%[a], #4]\n\t"
  11790. "UMULL r8, r9, r10, r12\n\t"
  11791. "ADDS r5, r5, r8\n\t"
  11792. "ADCS r6, r6, r9\n\t"
  11793. "ADC r7, r7, #0x0\n\t"
  11794. /* A[2] * A[8] */
  11795. "LDR r10, [%[a], #32]\n\t"
  11796. "LDR r12, [%[a], #8]\n\t"
  11797. "UMULL r8, r9, r10, r12\n\t"
  11798. "ADDS r5, r5, r8\n\t"
  11799. "ADCS r6, r6, r9\n\t"
  11800. "ADC r7, r7, #0x0\n\t"
  11801. /* A[3] * A[7] */
  11802. "LDR r10, [%[a], #28]\n\t"
  11803. "LDR r12, [%[a], #12]\n\t"
  11804. "UMULL r8, r9, r10, r12\n\t"
  11805. "ADDS r5, r5, r8\n\t"
  11806. "ADCS r6, r6, r9\n\t"
  11807. "ADC r7, r7, #0x0\n\t"
  11808. /* A[4] * A[6] */
  11809. "LDR r10, [%[a], #24]\n\t"
  11810. "LDR r12, [%[a], #16]\n\t"
  11811. "UMULL r8, r9, r10, r12\n\t"
  11812. "ADDS r5, r5, r8\n\t"
  11813. "ADCS r6, r6, r9\n\t"
  11814. "ADC r7, r7, #0x0\n\t"
  11815. /* A[5] * A[5] */
  11816. "LDR r10, [%[a], #20]\n\t"
  11817. "UMULL r8, r9, r10, r10\n\t"
  11818. "ADDS r5, r5, r5\n\t"
  11819. "ADCS r6, r6, r6\n\t"
  11820. "ADC r7, r7, r7\n\t"
  11821. "ADDS r3, r3, r8\n\t"
  11822. "ADCS r4, r4, r9\n\t"
  11823. "ADC r2, r2, #0x0\n\t"
  11824. "ADDS r3, r3, r5\n\t"
  11825. "ADCS r4, r4, r6\n\t"
  11826. "ADC r2, r2, r7\n\t"
  11827. "STR r3, [sp, #40]\n\t"
  11828. /* A[0] * A[11] */
  11829. "LDR r10, [%[a], #44]\n\t"
  11830. "LDR r12, [%[a]]\n\t"
  11831. "UMULL r5, r6, r10, r12\n\t"
  11832. "MOV r3, #0x0\n\t"
  11833. "MOV r7, #0x0\n\t"
  11834. /* A[1] * A[10] */
  11835. "LDR r10, [%[a], #40]\n\t"
  11836. "LDR r12, [%[a], #4]\n\t"
  11837. "UMULL r8, r9, r10, r12\n\t"
  11838. "ADDS r5, r5, r8\n\t"
  11839. "ADCS r6, r6, r9\n\t"
  11840. "ADC r7, r7, #0x0\n\t"
  11841. /* A[2] * A[9] */
  11842. "LDR r10, [%[a], #36]\n\t"
  11843. "LDR r12, [%[a], #8]\n\t"
  11844. "UMULL r8, r9, r10, r12\n\t"
  11845. "ADDS r5, r5, r8\n\t"
  11846. "ADCS r6, r6, r9\n\t"
  11847. "ADC r7, r7, #0x0\n\t"
  11848. /* A[3] * A[8] */
  11849. "LDR r10, [%[a], #32]\n\t"
  11850. "LDR r12, [%[a], #12]\n\t"
  11851. "UMULL r8, r9, r10, r12\n\t"
  11852. "ADDS r5, r5, r8\n\t"
  11853. "ADCS r6, r6, r9\n\t"
  11854. "ADC r7, r7, #0x0\n\t"
  11855. /* A[4] * A[7] */
  11856. "LDR r10, [%[a], #28]\n\t"
  11857. "LDR r12, [%[a], #16]\n\t"
  11858. "UMULL r8, r9, r10, r12\n\t"
  11859. "ADDS r5, r5, r8\n\t"
  11860. "ADCS r6, r6, r9\n\t"
  11861. "ADC r7, r7, #0x0\n\t"
  11862. /* A[5] * A[6] */
  11863. "LDR r10, [%[a], #24]\n\t"
  11864. "LDR r12, [%[a], #20]\n\t"
  11865. "UMULL r8, r9, r10, r12\n\t"
  11866. "ADDS r5, r5, r8\n\t"
  11867. "ADCS r6, r6, r9\n\t"
  11868. "ADC r7, r7, #0x0\n\t"
  11869. "ADDS r5, r5, r5\n\t"
  11870. "ADCS r6, r6, r6\n\t"
  11871. "ADC r7, r7, r7\n\t"
  11872. "ADDS r4, r4, r5\n\t"
  11873. "ADCS r2, r2, r6\n\t"
  11874. "ADC r3, r3, r7\n\t"
  11875. "STR r4, [sp, #44]\n\t"
  11876. /* A[1] * A[11] */
  11877. "LDR r10, [%[a], #44]\n\t"
  11878. "LDR r12, [%[a], #4]\n\t"
  11879. "UMULL r5, r6, r10, r12\n\t"
  11880. "MOV r4, #0x0\n\t"
  11881. "MOV r7, #0x0\n\t"
  11882. /* A[2] * A[10] */
  11883. "LDR r10, [%[a], #40]\n\t"
  11884. "LDR r12, [%[a], #8]\n\t"
  11885. "UMULL r8, r9, r10, r12\n\t"
  11886. "ADDS r5, r5, r8\n\t"
  11887. "ADCS r6, r6, r9\n\t"
  11888. "ADC r7, r7, #0x0\n\t"
  11889. /* A[3] * A[9] */
  11890. "LDR r10, [%[a], #36]\n\t"
  11891. "LDR r12, [%[a], #12]\n\t"
  11892. "UMULL r8, r9, r10, r12\n\t"
  11893. "ADDS r5, r5, r8\n\t"
  11894. "ADCS r6, r6, r9\n\t"
  11895. "ADC r7, r7, #0x0\n\t"
  11896. /* A[4] * A[8] */
  11897. "LDR r10, [%[a], #32]\n\t"
  11898. "LDR r12, [%[a], #16]\n\t"
  11899. "UMULL r8, r9, r10, r12\n\t"
  11900. "ADDS r5, r5, r8\n\t"
  11901. "ADCS r6, r6, r9\n\t"
  11902. "ADC r7, r7, #0x0\n\t"
  11903. /* A[5] * A[7] */
  11904. "LDR r10, [%[a], #28]\n\t"
  11905. "LDR r12, [%[a], #20]\n\t"
  11906. "UMULL r8, r9, r10, r12\n\t"
  11907. "ADDS r5, r5, r8\n\t"
  11908. "ADCS r6, r6, r9\n\t"
  11909. "ADC r7, r7, #0x0\n\t"
  11910. /* A[6] * A[6] */
  11911. "LDR r10, [%[a], #24]\n\t"
  11912. "UMULL r8, r9, r10, r10\n\t"
  11913. "ADDS r5, r5, r5\n\t"
  11914. "ADCS r6, r6, r6\n\t"
  11915. "ADC r7, r7, r7\n\t"
  11916. "ADDS r2, r2, r8\n\t"
  11917. "ADCS r3, r3, r9\n\t"
  11918. "ADC r4, r4, #0x0\n\t"
  11919. "ADDS r2, r2, r5\n\t"
  11920. "ADCS r3, r3, r6\n\t"
  11921. "ADC r4, r4, r7\n\t"
  11922. "STR r2, [%[r], #48]\n\t"
  11923. /* A[2] * A[11] */
  11924. "LDR r10, [%[a], #44]\n\t"
  11925. "LDR r12, [%[a], #8]\n\t"
  11926. "UMULL r5, r6, r10, r12\n\t"
  11927. "MOV r2, #0x0\n\t"
  11928. "MOV r7, #0x0\n\t"
  11929. /* A[3] * A[10] */
  11930. "LDR r10, [%[a], #40]\n\t"
  11931. "LDR r12, [%[a], #12]\n\t"
  11932. "UMULL r8, r9, r10, r12\n\t"
  11933. "ADDS r5, r5, r8\n\t"
  11934. "ADCS r6, r6, r9\n\t"
  11935. "ADC r7, r7, #0x0\n\t"
  11936. /* A[4] * A[9] */
  11937. "LDR r10, [%[a], #36]\n\t"
  11938. "LDR r12, [%[a], #16]\n\t"
  11939. "UMULL r8, r9, r10, r12\n\t"
  11940. "ADDS r5, r5, r8\n\t"
  11941. "ADCS r6, r6, r9\n\t"
  11942. "ADC r7, r7, #0x0\n\t"
  11943. /* A[5] * A[8] */
  11944. "LDR r10, [%[a], #32]\n\t"
  11945. "LDR r12, [%[a], #20]\n\t"
  11946. "UMULL r8, r9, r10, r12\n\t"
  11947. "ADDS r5, r5, r8\n\t"
  11948. "ADCS r6, r6, r9\n\t"
  11949. "ADC r7, r7, #0x0\n\t"
  11950. /* A[6] * A[7] */
  11951. "LDR r10, [%[a], #28]\n\t"
  11952. "LDR r12, [%[a], #24]\n\t"
  11953. "UMULL r8, r9, r10, r12\n\t"
  11954. "ADDS r5, r5, r8\n\t"
  11955. "ADCS r6, r6, r9\n\t"
  11956. "ADC r7, r7, #0x0\n\t"
  11957. "ADDS r5, r5, r5\n\t"
  11958. "ADCS r6, r6, r6\n\t"
  11959. "ADC r7, r7, r7\n\t"
  11960. "ADDS r3, r3, r5\n\t"
  11961. "ADCS r4, r4, r6\n\t"
  11962. "ADC r2, r2, r7\n\t"
  11963. "STR r3, [%[r], #52]\n\t"
  11964. /* A[3] * A[11] */
  11965. "LDR r10, [%[a], #44]\n\t"
  11966. "LDR r12, [%[a], #12]\n\t"
  11967. "UMULL r5, r6, r10, r12\n\t"
  11968. "MOV r3, #0x0\n\t"
  11969. "MOV r7, #0x0\n\t"
  11970. /* A[4] * A[10] */
  11971. "LDR r10, [%[a], #40]\n\t"
  11972. "LDR r12, [%[a], #16]\n\t"
  11973. "UMULL r8, r9, r10, r12\n\t"
  11974. "ADDS r5, r5, r8\n\t"
  11975. "ADCS r6, r6, r9\n\t"
  11976. "ADC r7, r7, #0x0\n\t"
  11977. /* A[5] * A[9] */
  11978. "LDR r10, [%[a], #36]\n\t"
  11979. "LDR r12, [%[a], #20]\n\t"
  11980. "UMULL r8, r9, r10, r12\n\t"
  11981. "ADDS r5, r5, r8\n\t"
  11982. "ADCS r6, r6, r9\n\t"
  11983. "ADC r7, r7, #0x0\n\t"
  11984. /* A[6] * A[8] */
  11985. "LDR r10, [%[a], #32]\n\t"
  11986. "LDR r12, [%[a], #24]\n\t"
  11987. "UMULL r8, r9, r10, r12\n\t"
  11988. "ADDS r5, r5, r8\n\t"
  11989. "ADCS r6, r6, r9\n\t"
  11990. "ADC r7, r7, #0x0\n\t"
  11991. /* A[7] * A[7] */
  11992. "LDR r10, [%[a], #28]\n\t"
  11993. "UMULL r8, r9, r10, r10\n\t"
  11994. "ADDS r5, r5, r5\n\t"
  11995. "ADCS r6, r6, r6\n\t"
  11996. "ADC r7, r7, r7\n\t"
  11997. "ADDS r4, r4, r8\n\t"
  11998. "ADCS r2, r2, r9\n\t"
  11999. "ADC r3, r3, #0x0\n\t"
  12000. "ADDS r4, r4, r5\n\t"
  12001. "ADCS r2, r2, r6\n\t"
  12002. "ADC r3, r3, r7\n\t"
  12003. "STR r4, [%[r], #56]\n\t"
  12004. /* A[4] * A[11] */
  12005. "LDR r10, [%[a], #44]\n\t"
  12006. "LDR r12, [%[a], #16]\n\t"
  12007. "UMULL r5, r6, r10, r12\n\t"
  12008. "MOV r4, #0x0\n\t"
  12009. "MOV r7, #0x0\n\t"
  12010. /* A[5] * A[10] */
  12011. "LDR r10, [%[a], #40]\n\t"
  12012. "LDR r12, [%[a], #20]\n\t"
  12013. "UMULL r8, r9, r10, r12\n\t"
  12014. "ADDS r5, r5, r8\n\t"
  12015. "ADCS r6, r6, r9\n\t"
  12016. "ADC r7, r7, #0x0\n\t"
  12017. /* A[6] * A[9] */
  12018. "LDR r10, [%[a], #36]\n\t"
  12019. "LDR r12, [%[a], #24]\n\t"
  12020. "UMULL r8, r9, r10, r12\n\t"
  12021. "ADDS r5, r5, r8\n\t"
  12022. "ADCS r6, r6, r9\n\t"
  12023. "ADC r7, r7, #0x0\n\t"
  12024. /* A[7] * A[8] */
  12025. "LDR r10, [%[a], #32]\n\t"
  12026. "LDR r12, [%[a], #28]\n\t"
  12027. "UMULL r8, r9, r10, r12\n\t"
  12028. "ADDS r5, r5, r8\n\t"
  12029. "ADCS r6, r6, r9\n\t"
  12030. "ADC r7, r7, #0x0\n\t"
  12031. "ADDS r5, r5, r5\n\t"
  12032. "ADCS r6, r6, r6\n\t"
  12033. "ADC r7, r7, r7\n\t"
  12034. "ADDS r2, r2, r5\n\t"
  12035. "ADCS r3, r3, r6\n\t"
  12036. "ADC r4, r4, r7\n\t"
  12037. "STR r2, [%[r], #60]\n\t"
  12038. /* A[5] * A[11] */
  12039. "LDR r10, [%[a], #44]\n\t"
  12040. "LDR r12, [%[a], #20]\n\t"
  12041. "UMULL r5, r6, r10, r12\n\t"
  12042. "MOV r2, #0x0\n\t"
  12043. "MOV r7, #0x0\n\t"
  12044. /* A[6] * A[10] */
  12045. "LDR r10, [%[a], #40]\n\t"
  12046. "LDR r12, [%[a], #24]\n\t"
  12047. "UMULL r8, r9, r10, r12\n\t"
  12048. "ADDS r5, r5, r8\n\t"
  12049. "ADCS r6, r6, r9\n\t"
  12050. "ADC r7, r7, #0x0\n\t"
  12051. /* A[7] * A[9] */
  12052. "LDR r10, [%[a], #36]\n\t"
  12053. "LDR r12, [%[a], #28]\n\t"
  12054. "UMULL r8, r9, r10, r12\n\t"
  12055. "ADDS r5, r5, r8\n\t"
  12056. "ADCS r6, r6, r9\n\t"
  12057. "ADC r7, r7, #0x0\n\t"
  12058. /* A[8] * A[8] */
  12059. "LDR r10, [%[a], #32]\n\t"
  12060. "UMULL r8, r9, r10, r10\n\t"
  12061. "ADDS r5, r5, r5\n\t"
  12062. "ADCS r6, r6, r6\n\t"
  12063. "ADC r7, r7, r7\n\t"
  12064. "ADDS r3, r3, r8\n\t"
  12065. "ADCS r4, r4, r9\n\t"
  12066. "ADC r2, r2, #0x0\n\t"
  12067. "ADDS r3, r3, r5\n\t"
  12068. "ADCS r4, r4, r6\n\t"
  12069. "ADC r2, r2, r7\n\t"
  12070. "STR r3, [%[r], #64]\n\t"
  12071. /* A[6] * A[11] */
  12072. "LDR r10, [%[a], #44]\n\t"
  12073. "LDR r12, [%[a], #24]\n\t"
  12074. "UMULL r5, r6, r10, r12\n\t"
  12075. "MOV r3, #0x0\n\t"
  12076. "MOV r7, #0x0\n\t"
  12077. /* A[7] * A[10] */
  12078. "LDR r10, [%[a], #40]\n\t"
  12079. "LDR r12, [%[a], #28]\n\t"
  12080. "UMULL r8, r9, r10, r12\n\t"
  12081. "ADDS r5, r5, r8\n\t"
  12082. "ADCS r6, r6, r9\n\t"
  12083. "ADC r7, r7, #0x0\n\t"
  12084. /* A[8] * A[9] */
  12085. "LDR r10, [%[a], #36]\n\t"
  12086. "LDR r12, [%[a], #32]\n\t"
  12087. "UMULL r8, r9, r10, r12\n\t"
  12088. "ADDS r5, r5, r8\n\t"
  12089. "ADCS r6, r6, r9\n\t"
  12090. "ADC r7, r7, #0x0\n\t"
  12091. "ADDS r5, r5, r5\n\t"
  12092. "ADCS r6, r6, r6\n\t"
  12093. "ADC r7, r7, r7\n\t"
  12094. "ADDS r4, r4, r5\n\t"
  12095. "ADCS r2, r2, r6\n\t"
  12096. "ADC r3, r3, r7\n\t"
  12097. "STR r4, [%[r], #68]\n\t"
  12098. /* A[7] * A[11] */
  12099. "LDR r10, [%[a], #44]\n\t"
  12100. "LDR r12, [%[a], #28]\n\t"
  12101. "UMULL r8, r9, r10, r12\n\t"
  12102. "ADDS r2, r2, r8\n\t"
  12103. "ADCS r3, r3, r9\n\t"
  12104. "MOV r4, #0x0\n\t"
  12105. "ADC r4, r4, #0x0\n\t"
  12106. "ADDS r2, r2, r8\n\t"
  12107. "ADCS r3, r3, r9\n\t"
  12108. "MOV r4, #0x0\n\t"
  12109. "ADC r4, r4, #0x0\n\t"
  12110. /* A[8] * A[10] */
  12111. "LDR r10, [%[a], #40]\n\t"
  12112. "LDR r12, [%[a], #32]\n\t"
  12113. "UMULL r8, r9, r10, r12\n\t"
  12114. "ADDS r2, r2, r8\n\t"
  12115. "ADCS r3, r3, r9\n\t"
  12116. "ADC r4, r4, #0x0\n\t"
  12117. "ADDS r2, r2, r8\n\t"
  12118. "ADCS r3, r3, r9\n\t"
  12119. "ADC r4, r4, #0x0\n\t"
  12120. /* A[9] * A[9] */
  12121. "LDR r10, [%[a], #36]\n\t"
  12122. "UMULL r8, r9, r10, r10\n\t"
  12123. "ADDS r2, r2, r8\n\t"
  12124. "ADCS r3, r3, r9\n\t"
  12125. "ADC r4, r4, #0x0\n\t"
  12126. "STR r2, [%[r], #72]\n\t"
  12127. /* A[8] * A[11] */
  12128. "LDR r10, [%[a], #44]\n\t"
  12129. "LDR r12, [%[a], #32]\n\t"
  12130. "UMULL r8, r9, r10, r12\n\t"
  12131. "ADDS r3, r3, r8\n\t"
  12132. "ADCS r4, r4, r9\n\t"
  12133. "MOV r2, #0x0\n\t"
  12134. "ADC r2, r2, #0x0\n\t"
  12135. "ADDS r3, r3, r8\n\t"
  12136. "ADCS r4, r4, r9\n\t"
  12137. "MOV r2, #0x0\n\t"
  12138. "ADC r2, r2, #0x0\n\t"
  12139. /* A[9] * A[10] */
  12140. "LDR r10, [%[a], #40]\n\t"
  12141. "LDR r12, [%[a], #36]\n\t"
  12142. "UMULL r8, r9, r10, r12\n\t"
  12143. "ADDS r3, r3, r8\n\t"
  12144. "ADCS r4, r4, r9\n\t"
  12145. "ADC r2, r2, #0x0\n\t"
  12146. "ADDS r3, r3, r8\n\t"
  12147. "ADCS r4, r4, r9\n\t"
  12148. "ADC r2, r2, #0x0\n\t"
  12149. "STR r3, [%[r], #76]\n\t"
  12150. /* A[9] * A[11] */
  12151. "LDR r10, [%[a], #44]\n\t"
  12152. "LDR r12, [%[a], #36]\n\t"
  12153. "UMULL r8, r9, r10, r12\n\t"
  12154. "ADDS r4, r4, r8\n\t"
  12155. "ADCS r2, r2, r9\n\t"
  12156. "MOV r3, #0x0\n\t"
  12157. "ADC r3, r3, #0x0\n\t"
  12158. "ADDS r4, r4, r8\n\t"
  12159. "ADCS r2, r2, r9\n\t"
  12160. "MOV r3, #0x0\n\t"
  12161. "ADC r3, r3, #0x0\n\t"
  12162. /* A[10] * A[10] */
  12163. "LDR r10, [%[a], #40]\n\t"
  12164. "UMULL r8, r9, r10, r10\n\t"
  12165. "ADDS r4, r4, r8\n\t"
  12166. "ADCS r2, r2, r9\n\t"
  12167. "ADC r3, r3, #0x0\n\t"
  12168. "STR r4, [%[r], #80]\n\t"
  12169. /* A[10] * A[11] */
  12170. "LDR r10, [%[a], #44]\n\t"
  12171. "LDR r12, [%[a], #40]\n\t"
  12172. "UMULL r8, r9, r10, r12\n\t"
  12173. "ADDS r2, r2, r8\n\t"
  12174. "ADCS r3, r3, r9\n\t"
  12175. "MOV r4, #0x0\n\t"
  12176. "ADC r4, r4, #0x0\n\t"
  12177. "ADDS r2, r2, r8\n\t"
  12178. "ADCS r3, r3, r9\n\t"
  12179. "MOV r4, #0x0\n\t"
  12180. "ADC r4, r4, #0x0\n\t"
  12181. "STR r2, [%[r], #84]\n\t"
  12182. /* A[11] * A[11] */
  12183. "LDR r10, [%[a], #44]\n\t"
  12184. "UMLAL r3, r4, r10, r10\n\t"
  12185. "STR r3, [%[r], #88]\n\t"
  12186. "STR r4, [%[r], #92]\n\t"
  12187. "LDM sp!, {r2, r3, r4, r8}\n\t"
  12188. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  12189. "LDM sp!, {r2, r3, r4, r8}\n\t"
  12190. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  12191. "LDM sp!, {r2, r3, r4, r8}\n\t"
  12192. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  12193. : [r] "+r" (r), [a] "+r" (a)
  12194. :
  12195. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "cc"
  12196. );
  12197. }
  12198. /* Sub b from a into r. (r = a - b)
  12199. *
  12200. * r A single precision integer.
  12201. * a A single precision integer.
  12202. * b A single precision integer.
  12203. */
  12204. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12205. static sp_digit sp_3072_sub_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  12206. #else
  12207. static sp_digit sp_3072_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  12208. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12209. {
  12210. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12211. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12212. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12213. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  12214. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12215. __asm__ __volatile__ (
  12216. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12217. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12218. "SUBS r3, r3, r7\n\t"
  12219. "SBCS r4, r4, r8\n\t"
  12220. "SBCS r5, r5, r9\n\t"
  12221. "SBCS r6, r6, r10\n\t"
  12222. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12223. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12224. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12225. "SBCS r3, r3, r7\n\t"
  12226. "SBCS r4, r4, r8\n\t"
  12227. "SBCS r5, r5, r9\n\t"
  12228. "SBCS r6, r6, r10\n\t"
  12229. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12230. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12231. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12232. "SBCS r3, r3, r7\n\t"
  12233. "SBCS r4, r4, r8\n\t"
  12234. "SBCS r5, r5, r9\n\t"
  12235. "SBCS r6, r6, r10\n\t"
  12236. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12237. "SBC %[r], r6, r6\n\t"
  12238. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  12239. :
  12240. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  12241. );
  12242. return (uint32_t)(size_t)r;
  12243. }
  12244. /* Square a and put result in r. (r = a * a)
  12245. *
  12246. * r A single precision integer.
  12247. * a A single precision integer.
  12248. */
  12249. SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
  12250. {
  12251. sp_digit* z0 = r;
  12252. sp_digit* z2 = r + 24;
  12253. sp_digit z1[24];
  12254. sp_digit* a1 = z1;
  12255. sp_digit zero[12];
  12256. sp_digit u;
  12257. sp_digit mask;
  12258. sp_digit* p1;
  12259. sp_digit* p2;
  12260. XMEMSET(zero, 0, sizeof(sp_digit) * 12);
  12261. mask = sp_3072_sub_12(a1, a, &a[12]);
  12262. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  12263. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  12264. (void)sp_3072_sub_12(a1, p1, p2);
  12265. sp_3072_sqr_12(z2, &a[12]);
  12266. sp_3072_sqr_12(z0, a);
  12267. sp_3072_sqr_12(z1, a1);
  12268. u = 0;
  12269. u -= sp_3072_sub_in_place_24(z1, z2);
  12270. u -= sp_3072_sub_in_place_24(z1, z0);
  12271. u += sp_3072_sub_in_place_24(r + 12, z1);
  12272. zero[0] = u;
  12273. (void)sp_3072_add_12(r + 36, r + 36, zero);
  12274. }
  12275. /* Sub b from a into r. (r = a - b)
  12276. *
  12277. * r A single precision integer.
  12278. * a A single precision integer.
  12279. * b A single precision integer.
  12280. */
  12281. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12282. static sp_digit sp_3072_sub_24(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  12283. #else
  12284. static sp_digit sp_3072_sub_24(sp_digit* r, const sp_digit* a, const sp_digit* b)
  12285. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12286. {
  12287. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12288. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12289. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12290. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  12291. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12292. __asm__ __volatile__ (
  12293. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12294. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12295. "SUBS r3, r3, r7\n\t"
  12296. "SBCS r4, r4, r8\n\t"
  12297. "SBCS r5, r5, r9\n\t"
  12298. "SBCS r6, r6, r10\n\t"
  12299. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12300. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12301. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12302. "SBCS r3, r3, r7\n\t"
  12303. "SBCS r4, r4, r8\n\t"
  12304. "SBCS r5, r5, r9\n\t"
  12305. "SBCS r6, r6, r10\n\t"
  12306. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12307. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12308. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12309. "SBCS r3, r3, r7\n\t"
  12310. "SBCS r4, r4, r8\n\t"
  12311. "SBCS r5, r5, r9\n\t"
  12312. "SBCS r6, r6, r10\n\t"
  12313. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12314. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12315. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12316. "SBCS r3, r3, r7\n\t"
  12317. "SBCS r4, r4, r8\n\t"
  12318. "SBCS r5, r5, r9\n\t"
  12319. "SBCS r6, r6, r10\n\t"
  12320. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12321. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12322. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12323. "SBCS r3, r3, r7\n\t"
  12324. "SBCS r4, r4, r8\n\t"
  12325. "SBCS r5, r5, r9\n\t"
  12326. "SBCS r6, r6, r10\n\t"
  12327. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12328. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12329. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12330. "SBCS r3, r3, r7\n\t"
  12331. "SBCS r4, r4, r8\n\t"
  12332. "SBCS r5, r5, r9\n\t"
  12333. "SBCS r6, r6, r10\n\t"
  12334. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12335. "SBC %[r], r6, r6\n\t"
  12336. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  12337. :
  12338. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  12339. );
  12340. return (uint32_t)(size_t)r;
  12341. }
  12342. /* Square a and put result in r. (r = a * a)
  12343. *
  12344. * r A single precision integer.
  12345. * a A single precision integer.
  12346. */
  12347. SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
  12348. {
  12349. sp_digit* z0 = r;
  12350. sp_digit* z2 = r + 48;
  12351. sp_digit z1[48];
  12352. sp_digit* a1 = z1;
  12353. sp_digit zero[24];
  12354. sp_digit u;
  12355. sp_digit mask;
  12356. sp_digit* p1;
  12357. sp_digit* p2;
  12358. XMEMSET(zero, 0, sizeof(sp_digit) * 24);
  12359. mask = sp_3072_sub_24(a1, a, &a[24]);
  12360. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  12361. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  12362. (void)sp_3072_sub_24(a1, p1, p2);
  12363. sp_3072_sqr_24(z2, &a[24]);
  12364. sp_3072_sqr_24(z0, a);
  12365. sp_3072_sqr_24(z1, a1);
  12366. u = 0;
  12367. u -= sp_3072_sub_in_place_48(z1, z2);
  12368. u -= sp_3072_sub_in_place_48(z1, z0);
  12369. u += sp_3072_sub_in_place_48(r + 24, z1);
  12370. zero[0] = u;
  12371. (void)sp_3072_add_24(r + 72, r + 72, zero);
  12372. }
  12373. /* Sub b from a into r. (r = a - b)
  12374. *
  12375. * r A single precision integer.
  12376. * a A single precision integer.
  12377. * b A single precision integer.
  12378. */
  12379. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12380. static sp_digit sp_3072_sub_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  12381. #else
  12382. static sp_digit sp_3072_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b)
  12383. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12384. {
  12385. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12386. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12387. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12388. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  12389. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12390. __asm__ __volatile__ (
  12391. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12392. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12393. "SUBS r3, r3, r7\n\t"
  12394. "SBCS r4, r4, r8\n\t"
  12395. "SBCS r5, r5, r9\n\t"
  12396. "SBCS r6, r6, r10\n\t"
  12397. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12398. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12399. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12400. "SBCS r3, r3, r7\n\t"
  12401. "SBCS r4, r4, r8\n\t"
  12402. "SBCS r5, r5, r9\n\t"
  12403. "SBCS r6, r6, r10\n\t"
  12404. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12405. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12406. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12407. "SBCS r3, r3, r7\n\t"
  12408. "SBCS r4, r4, r8\n\t"
  12409. "SBCS r5, r5, r9\n\t"
  12410. "SBCS r6, r6, r10\n\t"
  12411. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12412. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12413. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12414. "SBCS r3, r3, r7\n\t"
  12415. "SBCS r4, r4, r8\n\t"
  12416. "SBCS r5, r5, r9\n\t"
  12417. "SBCS r6, r6, r10\n\t"
  12418. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12419. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12420. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12421. "SBCS r3, r3, r7\n\t"
  12422. "SBCS r4, r4, r8\n\t"
  12423. "SBCS r5, r5, r9\n\t"
  12424. "SBCS r6, r6, r10\n\t"
  12425. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12426. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12427. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12428. "SBCS r3, r3, r7\n\t"
  12429. "SBCS r4, r4, r8\n\t"
  12430. "SBCS r5, r5, r9\n\t"
  12431. "SBCS r6, r6, r10\n\t"
  12432. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12433. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12434. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12435. "SBCS r3, r3, r7\n\t"
  12436. "SBCS r4, r4, r8\n\t"
  12437. "SBCS r5, r5, r9\n\t"
  12438. "SBCS r6, r6, r10\n\t"
  12439. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12440. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12441. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12442. "SBCS r3, r3, r7\n\t"
  12443. "SBCS r4, r4, r8\n\t"
  12444. "SBCS r5, r5, r9\n\t"
  12445. "SBCS r6, r6, r10\n\t"
  12446. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12447. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12448. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12449. "SBCS r3, r3, r7\n\t"
  12450. "SBCS r4, r4, r8\n\t"
  12451. "SBCS r5, r5, r9\n\t"
  12452. "SBCS r6, r6, r10\n\t"
  12453. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12454. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12455. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12456. "SBCS r3, r3, r7\n\t"
  12457. "SBCS r4, r4, r8\n\t"
  12458. "SBCS r5, r5, r9\n\t"
  12459. "SBCS r6, r6, r10\n\t"
  12460. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12461. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12462. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12463. "SBCS r3, r3, r7\n\t"
  12464. "SBCS r4, r4, r8\n\t"
  12465. "SBCS r5, r5, r9\n\t"
  12466. "SBCS r6, r6, r10\n\t"
  12467. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12468. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  12469. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  12470. "SBCS r3, r3, r7\n\t"
  12471. "SBCS r4, r4, r8\n\t"
  12472. "SBCS r5, r5, r9\n\t"
  12473. "SBCS r6, r6, r10\n\t"
  12474. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  12475. "SBC %[r], r6, r6\n\t"
  12476. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  12477. :
  12478. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  12479. );
  12480. return (uint32_t)(size_t)r;
  12481. }
  12482. /* Square a and put result in r. (r = a * a)
  12483. *
  12484. * r A single precision integer.
  12485. * a A single precision integer.
  12486. */
  12487. SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a)
  12488. {
  12489. sp_digit* z0 = r;
  12490. sp_digit* z2 = r + 96;
  12491. sp_digit z1[96];
  12492. sp_digit* a1 = z1;
  12493. sp_digit zero[48];
  12494. sp_digit u;
  12495. sp_digit mask;
  12496. sp_digit* p1;
  12497. sp_digit* p2;
  12498. XMEMSET(zero, 0, sizeof(sp_digit) * 48);
  12499. mask = sp_3072_sub_48(a1, a, &a[48]);
  12500. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  12501. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  12502. (void)sp_3072_sub_48(a1, p1, p2);
  12503. sp_3072_sqr_48(z2, &a[48]);
  12504. sp_3072_sqr_48(z0, a);
  12505. sp_3072_sqr_48(z1, a1);
  12506. u = 0;
  12507. u -= sp_3072_sub_in_place_96(z1, z2);
  12508. u -= sp_3072_sub_in_place_96(z1, z0);
  12509. u += sp_3072_sub_in_place_96(r + 48, z1);
  12510. zero[0] = u;
  12511. (void)sp_3072_add_48(r + 144, r + 144, zero);
  12512. }
  12513. #endif /* !WOLFSSL_SP_SMALL */
  12514. #ifdef WOLFSSL_SP_SMALL
  12515. /* Add b to a into r. (r = a + b)
  12516. *
  12517. * r A single precision integer.
  12518. * a A single precision integer.
  12519. * b A single precision integer.
  12520. */
  12521. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12522. static sp_digit sp_3072_add_96(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  12523. #else
  12524. static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, const sp_digit* b)
  12525. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12526. {
  12527. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12528. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12529. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12530. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  12531. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12532. __asm__ __volatile__ (
  12533. "MOV r3, #0x0\n\t"
  12534. "ADD r12, %[a], #0x180\n\t"
  12535. "\n"
  12536. "L_sp_3072_add_96_word:\n\t"
  12537. "ADDS r3, r3, #0xffffffff\n\t"
  12538. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  12539. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  12540. "ADCS r4, r4, r8\n\t"
  12541. "ADCS r5, r5, r9\n\t"
  12542. "ADCS r6, r6, r10\n\t"
  12543. "ADCS r7, r7, r11\n\t"
  12544. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  12545. "MOV r4, #0x0\n\t"
  12546. "ADC r3, r4, #0x0\n\t"
  12547. "CMP %[a], r12\n\t"
  12548. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12549. "BNE L_sp_3072_add_96_word\n\t"
  12550. #else
  12551. "BNE.N L_sp_3072_add_96_word\n\t"
  12552. #endif
  12553. "MOV %[r], r3\n\t"
  12554. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  12555. :
  12556. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  12557. );
  12558. return (uint32_t)(size_t)r;
  12559. }
  12560. #endif /* WOLFSSL_SP_SMALL */
  12561. #ifdef WOLFSSL_SP_SMALL
  12562. /* Sub b from a into a. (a -= b)
  12563. *
  12564. * a A single precision integer.
  12565. * b A single precision integer.
  12566. */
  12567. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12568. static sp_digit sp_3072_sub_in_place_96(sp_digit* a_p, const sp_digit* b_p)
  12569. #else
  12570. static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b)
  12571. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12572. {
  12573. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12574. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  12575. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  12576. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12577. __asm__ __volatile__ (
  12578. "MOV r10, #0x0\n\t"
  12579. "ADD r11, %[a], #0x180\n\t"
  12580. "\n"
  12581. "L_sp_3072_sub_in_pkace_96_word:\n\t"
  12582. "RSBS r10, r10, #0x0\n\t"
  12583. "LDM %[a], {r2, r3, r4, r5}\n\t"
  12584. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  12585. "SBCS r2, r2, r6\n\t"
  12586. "SBCS r3, r3, r7\n\t"
  12587. "SBCS r4, r4, r8\n\t"
  12588. "SBCS r5, r5, r9\n\t"
  12589. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  12590. "SBC r10, r10, r10\n\t"
  12591. "CMP %[a], r11\n\t"
  12592. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12593. "BNE L_sp_3072_sub_in_pkace_96_word\n\t"
  12594. #else
  12595. "BNE.N L_sp_3072_sub_in_pkace_96_word\n\t"
  12596. #endif
  12597. "MOV %[a], r10\n\t"
  12598. : [a] "+r" (a), [b] "+r" (b)
  12599. :
  12600. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  12601. );
  12602. return (uint32_t)(size_t)a;
  12603. }
  12604. #endif /* WOLFSSL_SP_SMALL */
  12605. #ifdef WOLFSSL_SP_SMALL
  12606. /* Multiply a and b into r. (r = a * b)
  12607. *
  12608. * r A single precision integer.
  12609. * a A single precision integer.
  12610. * b A single precision integer.
  12611. */
  12612. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12613. static void sp_3072_mul_96(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  12614. #else
  12615. static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b)
  12616. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12617. {
  12618. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12619. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12620. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12621. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  12622. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12623. __asm__ __volatile__ (
  12624. "SUB sp, sp, #0x300\n\t"
  12625. "LDR lr, [%[a]]\n\t"
  12626. "LDR r11, [%[b]]\n\t"
  12627. "UMULL r8, r6, lr, r11\n\t"
  12628. "STR r8, [sp]\n\t"
  12629. "MOV r7, #0x0\n\t"
  12630. "MOV r8, #0x0\n\t"
  12631. "MOV r5, #0x4\n\t"
  12632. "\n"
  12633. "L_sp_3072_mul_96_outer:\n\t"
  12634. "SUBS r3, r5, #0x17c\n\t"
  12635. "IT cc\n\t"
  12636. "MOVCC r3, #0x0\n\t"
  12637. "SUB r4, r5, r3\n\t"
  12638. "\n"
  12639. "L_sp_3072_mul_96_inner:\n\t"
  12640. "LDR lr, [%[a], r3]\n\t"
  12641. "LDR r11, [%[b], r4]\n\t"
  12642. "UMULL r9, r10, lr, r11\n\t"
  12643. "ADDS r6, r6, r9\n\t"
  12644. "ADCS r7, r7, r10\n\t"
  12645. "ADC r8, r8, #0x0\n\t"
  12646. "LDR lr, [%[a], r4]\n\t"
  12647. "LDR r11, [%[b], r3]\n\t"
  12648. "UMULL r9, r10, lr, r11\n\t"
  12649. "ADDS r6, r6, r9\n\t"
  12650. "ADCS r7, r7, r10\n\t"
  12651. "ADC r8, r8, #0x0\n\t"
  12652. "ADD r3, r3, #0x4\n\t"
  12653. "SUB r4, r4, #0x4\n\t"
  12654. "CMP r3, r4\n\t"
  12655. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12656. "BGT L_sp_3072_mul_96_inner_done\n\t"
  12657. #else
  12658. "BGT.N L_sp_3072_mul_96_inner_done\n\t"
  12659. #endif
  12660. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12661. "BLT L_sp_3072_mul_96_inner\n\t"
  12662. #else
  12663. "BLT.N L_sp_3072_mul_96_inner\n\t"
  12664. #endif
  12665. "LDR lr, [%[a], r3]\n\t"
  12666. "LDR r11, [%[b], r3]\n\t"
  12667. "UMULL r9, r10, lr, r11\n\t"
  12668. "ADDS r6, r6, r9\n\t"
  12669. "ADCS r7, r7, r10\n\t"
  12670. "ADC r8, r8, #0x0\n\t"
  12671. "\n"
  12672. "L_sp_3072_mul_96_inner_done:\n\t"
  12673. "STR r6, [sp, r5]\n\t"
  12674. "MOV r6, r7\n\t"
  12675. "MOV r7, r8\n\t"
  12676. "MOV r8, #0x0\n\t"
  12677. "ADD r5, r5, #0x4\n\t"
  12678. "CMP r5, #0x2f4\n\t"
  12679. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12680. "BLE L_sp_3072_mul_96_outer\n\t"
  12681. #else
  12682. "BLE.N L_sp_3072_mul_96_outer\n\t"
  12683. #endif
  12684. "LDR lr, [%[a], #380]\n\t"
  12685. "LDR r11, [%[b], #380]\n\t"
  12686. "UMLAL r6, r7, lr, r11\n\t"
  12687. "STR r6, [sp, r5]\n\t"
  12688. "ADD r5, r5, #0x4\n\t"
  12689. "STR r7, [sp, r5]\n\t"
  12690. "\n"
  12691. "L_sp_3072_mul_96_store:\n\t"
  12692. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  12693. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  12694. "SUBS r5, r5, #0x20\n\t"
  12695. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12696. "BGT L_sp_3072_mul_96_store\n\t"
  12697. #else
  12698. "BGT.N L_sp_3072_mul_96_store\n\t"
  12699. #endif
  12700. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  12701. :
  12702. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  12703. );
  12704. }
  12705. /* Square a and put result in r. (r = a * a)
  12706. *
  12707. * r A single precision integer.
  12708. * a A single precision integer.
  12709. */
  12710. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12711. static void sp_3072_sqr_96(sp_digit* r_p, const sp_digit* a_p)
  12712. #else
  12713. static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a)
  12714. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12715. {
  12716. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12717. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12718. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12719. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12720. __asm__ __volatile__ (
  12721. "SUB sp, sp, #0x300\n\t"
  12722. "LDR lr, [%[a]]\n\t"
  12723. "UMULL r8, r6, lr, lr\n\t"
  12724. "STR r8, [sp]\n\t"
  12725. "MOV r7, #0x0\n\t"
  12726. "MOV r8, #0x0\n\t"
  12727. "MOV r5, #0x4\n\t"
  12728. "\n"
  12729. "L_sp_3072_sqr_96_outer:\n\t"
  12730. "SUBS r3, r5, #0x17c\n\t"
  12731. "IT cc\n\t"
  12732. "MOVCC r3, #0x0\n\t"
  12733. "SUB r4, r5, r3\n\t"
  12734. "\n"
  12735. "L_sp_3072_sqr_96_inner:\n\t"
  12736. "LDR lr, [%[a], r3]\n\t"
  12737. "LDR r11, [%[a], r4]\n\t"
  12738. "UMULL r9, r10, lr, r11\n\t"
  12739. "ADDS r6, r6, r9\n\t"
  12740. "ADCS r7, r7, r10\n\t"
  12741. "ADC r8, r8, #0x0\n\t"
  12742. "ADDS r6, r6, r9\n\t"
  12743. "ADCS r7, r7, r10\n\t"
  12744. "ADC r8, r8, #0x0\n\t"
  12745. "ADD r3, r3, #0x4\n\t"
  12746. "SUB r4, r4, #0x4\n\t"
  12747. "CMP r3, r4\n\t"
  12748. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12749. "BGT L_sp_3072_sqr_96_inner_done\n\t"
  12750. #else
  12751. "BGT.N L_sp_3072_sqr_96_inner_done\n\t"
  12752. #endif
  12753. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12754. "BLT L_sp_3072_sqr_96_inner\n\t"
  12755. #else
  12756. "BLT.N L_sp_3072_sqr_96_inner\n\t"
  12757. #endif
  12758. "LDR lr, [%[a], r3]\n\t"
  12759. "UMULL r9, r10, lr, lr\n\t"
  12760. "ADDS r6, r6, r9\n\t"
  12761. "ADCS r7, r7, r10\n\t"
  12762. "ADC r8, r8, #0x0\n\t"
  12763. "\n"
  12764. "L_sp_3072_sqr_96_inner_done:\n\t"
  12765. "STR r6, [sp, r5]\n\t"
  12766. "MOV r6, r7\n\t"
  12767. "MOV r7, r8\n\t"
  12768. "MOV r8, #0x0\n\t"
  12769. "ADD r5, r5, #0x4\n\t"
  12770. "CMP r5, #0x2f4\n\t"
  12771. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12772. "BLE L_sp_3072_sqr_96_outer\n\t"
  12773. #else
  12774. "BLE.N L_sp_3072_sqr_96_outer\n\t"
  12775. #endif
  12776. "LDR lr, [%[a], #380]\n\t"
  12777. "UMLAL r6, r7, lr, lr\n\t"
  12778. "STR r6, [sp, r5]\n\t"
  12779. "ADD r5, r5, #0x4\n\t"
  12780. "STR r7, [sp, r5]\n\t"
  12781. "\n"
  12782. "L_sp_3072_sqr_96_store:\n\t"
  12783. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  12784. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  12785. "SUBS r5, r5, #0x20\n\t"
  12786. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12787. "BGT L_sp_3072_sqr_96_store\n\t"
  12788. #else
  12789. "BGT.N L_sp_3072_sqr_96_store\n\t"
  12790. #endif
  12791. : [r] "+r" (r), [a] "+r" (a)
  12792. :
  12793. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  12794. );
  12795. }
  12796. #endif /* WOLFSSL_SP_SMALL */
  12797. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  12798. #ifdef WOLFSSL_SP_SMALL
  12799. /* AND m into each word of a and store in r.
  12800. *
  12801. * r A single precision integer.
  12802. * a A single precision integer.
  12803. * m Mask to AND against each digit.
  12804. */
  12805. static void sp_3072_mask_48(sp_digit* r, const sp_digit* a, sp_digit m)
  12806. {
  12807. int i;
  12808. for (i=0; i<48; i++) {
  12809. r[i] = a[i] & m;
  12810. }
  12811. }
  12812. #endif /* WOLFSSL_SP_SMALL */
  12813. #ifdef WOLFSSL_SP_SMALL
  12814. /* Add b to a into r. (r = a + b)
  12815. *
  12816. * r A single precision integer.
  12817. * a A single precision integer.
  12818. * b A single precision integer.
  12819. */
  12820. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12821. static sp_digit sp_3072_add_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  12822. #else
  12823. static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b)
  12824. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12825. {
  12826. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12827. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12828. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12829. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  12830. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12831. __asm__ __volatile__ (
  12832. "MOV r3, #0x0\n\t"
  12833. "ADD r12, %[a], #0xc0\n\t"
  12834. "\n"
  12835. "L_sp_3072_add_48_word:\n\t"
  12836. "ADDS r3, r3, #0xffffffff\n\t"
  12837. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  12838. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  12839. "ADCS r4, r4, r8\n\t"
  12840. "ADCS r5, r5, r9\n\t"
  12841. "ADCS r6, r6, r10\n\t"
  12842. "ADCS r7, r7, r11\n\t"
  12843. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  12844. "MOV r4, #0x0\n\t"
  12845. "ADC r3, r4, #0x0\n\t"
  12846. "CMP %[a], r12\n\t"
  12847. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12848. "BNE L_sp_3072_add_48_word\n\t"
  12849. #else
  12850. "BNE.N L_sp_3072_add_48_word\n\t"
  12851. #endif
  12852. "MOV %[r], r3\n\t"
  12853. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  12854. :
  12855. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  12856. );
  12857. return (uint32_t)(size_t)r;
  12858. }
  12859. #endif /* WOLFSSL_SP_SMALL */
  12860. #ifdef WOLFSSL_SP_SMALL
  12861. /* Sub b from a into a. (a -= b)
  12862. *
  12863. * a A single precision integer.
  12864. * b A single precision integer.
  12865. */
  12866. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12867. static sp_digit sp_3072_sub_in_place_48(sp_digit* a_p, const sp_digit* b_p)
  12868. #else
  12869. static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b)
  12870. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12871. {
  12872. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12873. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  12874. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  12875. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12876. __asm__ __volatile__ (
  12877. "MOV r10, #0x0\n\t"
  12878. "ADD r11, %[a], #0xc0\n\t"
  12879. "\n"
  12880. "L_sp_3072_sub_in_pkace_48_word:\n\t"
  12881. "RSBS r10, r10, #0x0\n\t"
  12882. "LDM %[a], {r2, r3, r4, r5}\n\t"
  12883. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  12884. "SBCS r2, r2, r6\n\t"
  12885. "SBCS r3, r3, r7\n\t"
  12886. "SBCS r4, r4, r8\n\t"
  12887. "SBCS r5, r5, r9\n\t"
  12888. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  12889. "SBC r10, r10, r10\n\t"
  12890. "CMP %[a], r11\n\t"
  12891. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12892. "BNE L_sp_3072_sub_in_pkace_48_word\n\t"
  12893. #else
  12894. "BNE.N L_sp_3072_sub_in_pkace_48_word\n\t"
  12895. #endif
  12896. "MOV %[a], r10\n\t"
  12897. : [a] "+r" (a), [b] "+r" (b)
  12898. :
  12899. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  12900. );
  12901. return (uint32_t)(size_t)a;
  12902. }
  12903. #endif /* WOLFSSL_SP_SMALL */
  12904. #ifdef WOLFSSL_SP_SMALL
  12905. /* Multiply a and b into r. (r = a * b)
  12906. *
  12907. * r A single precision integer.
  12908. * a A single precision integer.
  12909. * b A single precision integer.
  12910. */
  12911. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12912. static void sp_3072_mul_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  12913. #else
  12914. static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b)
  12915. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12916. {
  12917. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  12918. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  12919. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  12920. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  12921. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  12922. __asm__ __volatile__ (
  12923. "SUB sp, sp, #0x180\n\t"
  12924. "LDR lr, [%[a]]\n\t"
  12925. "LDR r11, [%[b]]\n\t"
  12926. "UMULL r8, r6, lr, r11\n\t"
  12927. "STR r8, [sp]\n\t"
  12928. "MOV r7, #0x0\n\t"
  12929. "MOV r8, #0x0\n\t"
  12930. "MOV r5, #0x4\n\t"
  12931. "\n"
  12932. "L_sp_3072_mul_48_outer:\n\t"
  12933. "SUBS r3, r5, #0xbc\n\t"
  12934. "IT cc\n\t"
  12935. "MOVCC r3, #0x0\n\t"
  12936. "SUB r4, r5, r3\n\t"
  12937. "\n"
  12938. "L_sp_3072_mul_48_inner:\n\t"
  12939. "LDR lr, [%[a], r3]\n\t"
  12940. "LDR r11, [%[b], r4]\n\t"
  12941. "UMULL r9, r10, lr, r11\n\t"
  12942. "ADDS r6, r6, r9\n\t"
  12943. "ADCS r7, r7, r10\n\t"
  12944. "ADC r8, r8, #0x0\n\t"
  12945. "LDR lr, [%[a], r4]\n\t"
  12946. "LDR r11, [%[b], r3]\n\t"
  12947. "UMULL r9, r10, lr, r11\n\t"
  12948. "ADDS r6, r6, r9\n\t"
  12949. "ADCS r7, r7, r10\n\t"
  12950. "ADC r8, r8, #0x0\n\t"
  12951. "ADD r3, r3, #0x4\n\t"
  12952. "SUB r4, r4, #0x4\n\t"
  12953. "CMP r3, r4\n\t"
  12954. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12955. "BGT L_sp_3072_mul_48_inner_done\n\t"
  12956. #else
  12957. "BGT.N L_sp_3072_mul_48_inner_done\n\t"
  12958. #endif
  12959. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12960. "BLT L_sp_3072_mul_48_inner\n\t"
  12961. #else
  12962. "BLT.N L_sp_3072_mul_48_inner\n\t"
  12963. #endif
  12964. "LDR lr, [%[a], r3]\n\t"
  12965. "LDR r11, [%[b], r3]\n\t"
  12966. "UMULL r9, r10, lr, r11\n\t"
  12967. "ADDS r6, r6, r9\n\t"
  12968. "ADCS r7, r7, r10\n\t"
  12969. "ADC r8, r8, #0x0\n\t"
  12970. "\n"
  12971. "L_sp_3072_mul_48_inner_done:\n\t"
  12972. "STR r6, [sp, r5]\n\t"
  12973. "MOV r6, r7\n\t"
  12974. "MOV r7, r8\n\t"
  12975. "MOV r8, #0x0\n\t"
  12976. "ADD r5, r5, #0x4\n\t"
  12977. "CMP r5, #0x174\n\t"
  12978. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12979. "BLE L_sp_3072_mul_48_outer\n\t"
  12980. #else
  12981. "BLE.N L_sp_3072_mul_48_outer\n\t"
  12982. #endif
  12983. "LDR lr, [%[a], #188]\n\t"
  12984. "LDR r11, [%[b], #188]\n\t"
  12985. "UMLAL r6, r7, lr, r11\n\t"
  12986. "STR r6, [sp, r5]\n\t"
  12987. "ADD r5, r5, #0x4\n\t"
  12988. "STR r7, [sp, r5]\n\t"
  12989. "\n"
  12990. "L_sp_3072_mul_48_store:\n\t"
  12991. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  12992. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  12993. "SUBS r5, r5, #0x20\n\t"
  12994. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  12995. "BGT L_sp_3072_mul_48_store\n\t"
  12996. #else
  12997. "BGT.N L_sp_3072_mul_48_store\n\t"
  12998. #endif
  12999. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  13000. :
  13001. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  13002. );
  13003. }
  13004. /* Square a and put result in r. (r = a * a)
  13005. *
  13006. * r A single precision integer.
  13007. * a A single precision integer.
  13008. */
  13009. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13010. static void sp_3072_sqr_48(sp_digit* r_p, const sp_digit* a_p)
  13011. #else
  13012. static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
  13013. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13014. {
  13015. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13016. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  13017. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  13018. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13019. __asm__ __volatile__ (
  13020. "SUB sp, sp, #0x180\n\t"
  13021. "LDR lr, [%[a]]\n\t"
  13022. "UMULL r8, r6, lr, lr\n\t"
  13023. "STR r8, [sp]\n\t"
  13024. "MOV r7, #0x0\n\t"
  13025. "MOV r8, #0x0\n\t"
  13026. "MOV r5, #0x4\n\t"
  13027. "\n"
  13028. "L_sp_3072_sqr_48_outer:\n\t"
  13029. "SUBS r3, r5, #0xbc\n\t"
  13030. "IT cc\n\t"
  13031. "MOVCC r3, #0x0\n\t"
  13032. "SUB r4, r5, r3\n\t"
  13033. "\n"
  13034. "L_sp_3072_sqr_48_inner:\n\t"
  13035. "LDR lr, [%[a], r3]\n\t"
  13036. "LDR r11, [%[a], r4]\n\t"
  13037. "UMULL r9, r10, lr, r11\n\t"
  13038. "ADDS r6, r6, r9\n\t"
  13039. "ADCS r7, r7, r10\n\t"
  13040. "ADC r8, r8, #0x0\n\t"
  13041. "ADDS r6, r6, r9\n\t"
  13042. "ADCS r7, r7, r10\n\t"
  13043. "ADC r8, r8, #0x0\n\t"
  13044. "ADD r3, r3, #0x4\n\t"
  13045. "SUB r4, r4, #0x4\n\t"
  13046. "CMP r3, r4\n\t"
  13047. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  13048. "BGT L_sp_3072_sqr_48_inner_done\n\t"
  13049. #else
  13050. "BGT.N L_sp_3072_sqr_48_inner_done\n\t"
  13051. #endif
  13052. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  13053. "BLT L_sp_3072_sqr_48_inner\n\t"
  13054. #else
  13055. "BLT.N L_sp_3072_sqr_48_inner\n\t"
  13056. #endif
  13057. "LDR lr, [%[a], r3]\n\t"
  13058. "UMULL r9, r10, lr, lr\n\t"
  13059. "ADDS r6, r6, r9\n\t"
  13060. "ADCS r7, r7, r10\n\t"
  13061. "ADC r8, r8, #0x0\n\t"
  13062. "\n"
  13063. "L_sp_3072_sqr_48_inner_done:\n\t"
  13064. "STR r6, [sp, r5]\n\t"
  13065. "MOV r6, r7\n\t"
  13066. "MOV r7, r8\n\t"
  13067. "MOV r8, #0x0\n\t"
  13068. "ADD r5, r5, #0x4\n\t"
  13069. "CMP r5, #0x174\n\t"
  13070. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  13071. "BLE L_sp_3072_sqr_48_outer\n\t"
  13072. #else
  13073. "BLE.N L_sp_3072_sqr_48_outer\n\t"
  13074. #endif
  13075. "LDR lr, [%[a], #188]\n\t"
  13076. "UMLAL r6, r7, lr, lr\n\t"
  13077. "STR r6, [sp, r5]\n\t"
  13078. "ADD r5, r5, #0x4\n\t"
  13079. "STR r7, [sp, r5]\n\t"
  13080. "\n"
  13081. "L_sp_3072_sqr_48_store:\n\t"
  13082. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  13083. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  13084. "SUBS r5, r5, #0x20\n\t"
  13085. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  13086. "BGT L_sp_3072_sqr_48_store\n\t"
  13087. #else
  13088. "BGT.N L_sp_3072_sqr_48_store\n\t"
  13089. #endif
  13090. : [r] "+r" (r), [a] "+r" (a)
  13091. :
  13092. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  13093. );
  13094. }
  13095. #endif /* WOLFSSL_SP_SMALL */
  13096. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  13097. /* Calculate the bottom digit of -1/a mod 2^n.
  13098. *
  13099. * a A single precision number.
  13100. * rho Bottom word of inverse.
  13101. */
  13102. static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
  13103. {
  13104. sp_digit x;
  13105. sp_digit b;
  13106. b = a[0];
  13107. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  13108. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  13109. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  13110. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  13111. /* rho = -1/m mod b */
  13112. *rho = (sp_digit)0 - x;
  13113. }
  13114. #ifdef WOLFSSL_SP_SMALL
  13115. /* Mul a by digit b into r. (r = a * b)
  13116. *
  13117. * r A single precision integer.
  13118. * a A single precision integer.
  13119. * b A single precision digit.
  13120. */
  13121. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13122. static void sp_3072_mul_d_96(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  13123. #else
  13124. static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, sp_digit b)
  13125. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13126. {
  13127. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13128. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  13129. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  13130. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  13131. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13132. __asm__ __volatile__ (
  13133. /* A[0] * B */
  13134. "LDR r8, [%[a]]\n\t"
  13135. "UMULL r5, r3, %[b], r8\n\t"
  13136. "MOV r4, #0x0\n\t"
  13137. "STR r5, [%[r]]\n\t"
  13138. "MOV r5, #0x0\n\t"
  13139. "MOV r9, #0x4\n\t"
  13140. "\n"
  13141. "L_sp_3072_mul_d_96_word:\n\t"
  13142. /* A[i] * B */
  13143. "LDR r8, [%[a], r9]\n\t"
  13144. "UMULL r6, r7, %[b], r8\n\t"
  13145. "ADDS r3, r3, r6\n\t"
  13146. "ADCS r4, r4, r7\n\t"
  13147. "ADC r5, r5, #0x0\n\t"
  13148. "STR r3, [%[r], r9]\n\t"
  13149. "MOV r3, r4\n\t"
  13150. "MOV r4, r5\n\t"
  13151. "MOV r5, #0x0\n\t"
  13152. "ADD r9, r9, #0x4\n\t"
  13153. "CMP r9, #0x180\n\t"
  13154. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  13155. "BLT L_sp_3072_mul_d_96_word\n\t"
  13156. #else
  13157. "BLT.N L_sp_3072_mul_d_96_word\n\t"
  13158. #endif
  13159. "STR r3, [%[r], #384]\n\t"
  13160. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  13161. :
  13162. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  13163. );
  13164. }
  13165. #else
  13166. /* Mul a by digit b into r. (r = a * b)
  13167. *
  13168. * r A single precision integer.
  13169. * a A single precision integer.
  13170. * b A single precision digit.
  13171. */
  13172. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13173. static void sp_3072_mul_d_96(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  13174. #else
  13175. static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, sp_digit b)
  13176. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13177. {
  13178. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13179. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  13180. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  13181. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  13182. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13183. __asm__ __volatile__ (
  13184. /* A[0] * B */
  13185. "LDM %[a]!, {r8}\n\t"
  13186. "UMULL r3, r4, %[b], r8\n\t"
  13187. "STM %[r]!, {r3}\n\t"
  13188. "MOV r5, #0x0\n\t"
  13189. /* A[1] * B */
  13190. "LDM %[a]!, {r8}\n\t"
  13191. "UMLAL r4, r5, %[b], r8\n\t"
  13192. "STM %[r]!, {r4}\n\t"
  13193. "MOV r3, #0x0\n\t"
  13194. /* A[2] * B */
  13195. "LDM %[a]!, {r8}\n\t"
  13196. "UMLAL r5, r3, %[b], r8\n\t"
  13197. "STM %[r]!, {r5}\n\t"
  13198. "MOV r4, #0x0\n\t"
  13199. /* A[3] * B */
  13200. "LDM %[a]!, {r8}\n\t"
  13201. "UMLAL r3, r4, %[b], r8\n\t"
  13202. "STM %[r]!, {r3}\n\t"
  13203. "MOV r5, #0x0\n\t"
  13204. /* A[4] * B */
  13205. "LDM %[a]!, {r8}\n\t"
  13206. "UMLAL r4, r5, %[b], r8\n\t"
  13207. "STM %[r]!, {r4}\n\t"
  13208. "MOV r3, #0x0\n\t"
  13209. /* A[5] * B */
  13210. "LDM %[a]!, {r8}\n\t"
  13211. "UMLAL r5, r3, %[b], r8\n\t"
  13212. "STM %[r]!, {r5}\n\t"
  13213. "MOV r4, #0x0\n\t"
  13214. /* A[6] * B */
  13215. "LDM %[a]!, {r8}\n\t"
  13216. "UMLAL r3, r4, %[b], r8\n\t"
  13217. "STM %[r]!, {r3}\n\t"
  13218. "MOV r5, #0x0\n\t"
  13219. /* A[7] * B */
  13220. "LDM %[a]!, {r8}\n\t"
  13221. "UMLAL r4, r5, %[b], r8\n\t"
  13222. "STM %[r]!, {r4}\n\t"
  13223. "MOV r3, #0x0\n\t"
  13224. /* A[8] * B */
  13225. "LDM %[a]!, {r8}\n\t"
  13226. "UMLAL r5, r3, %[b], r8\n\t"
  13227. "STM %[r]!, {r5}\n\t"
  13228. "MOV r4, #0x0\n\t"
  13229. /* A[9] * B */
  13230. "LDM %[a]!, {r8}\n\t"
  13231. "UMLAL r3, r4, %[b], r8\n\t"
  13232. "STM %[r]!, {r3}\n\t"
  13233. "MOV r5, #0x0\n\t"
  13234. /* A[10] * B */
  13235. "LDM %[a]!, {r8}\n\t"
  13236. "UMLAL r4, r5, %[b], r8\n\t"
  13237. "STM %[r]!, {r4}\n\t"
  13238. "MOV r3, #0x0\n\t"
  13239. /* A[11] * B */
  13240. "LDM %[a]!, {r8}\n\t"
  13241. "UMLAL r5, r3, %[b], r8\n\t"
  13242. "STM %[r]!, {r5}\n\t"
  13243. "MOV r4, #0x0\n\t"
  13244. /* A[12] * B */
  13245. "LDM %[a]!, {r8}\n\t"
  13246. "UMLAL r3, r4, %[b], r8\n\t"
  13247. "STM %[r]!, {r3}\n\t"
  13248. "MOV r5, #0x0\n\t"
  13249. /* A[13] * B */
  13250. "LDM %[a]!, {r8}\n\t"
  13251. "UMLAL r4, r5, %[b], r8\n\t"
  13252. "STM %[r]!, {r4}\n\t"
  13253. "MOV r3, #0x0\n\t"
  13254. /* A[14] * B */
  13255. "LDM %[a]!, {r8}\n\t"
  13256. "UMLAL r5, r3, %[b], r8\n\t"
  13257. "STM %[r]!, {r5}\n\t"
  13258. "MOV r4, #0x0\n\t"
  13259. /* A[15] * B */
  13260. "LDM %[a]!, {r8}\n\t"
  13261. "UMLAL r3, r4, %[b], r8\n\t"
  13262. "STM %[r]!, {r3}\n\t"
  13263. "MOV r5, #0x0\n\t"
  13264. /* A[16] * B */
  13265. "LDM %[a]!, {r8}\n\t"
  13266. "UMLAL r4, r5, %[b], r8\n\t"
  13267. "STM %[r]!, {r4}\n\t"
  13268. "MOV r3, #0x0\n\t"
  13269. /* A[17] * B */
  13270. "LDM %[a]!, {r8}\n\t"
  13271. "UMLAL r5, r3, %[b], r8\n\t"
  13272. "STM %[r]!, {r5}\n\t"
  13273. "MOV r4, #0x0\n\t"
  13274. /* A[18] * B */
  13275. "LDM %[a]!, {r8}\n\t"
  13276. "UMLAL r3, r4, %[b], r8\n\t"
  13277. "STM %[r]!, {r3}\n\t"
  13278. "MOV r5, #0x0\n\t"
  13279. /* A[19] * B */
  13280. "LDM %[a]!, {r8}\n\t"
  13281. "UMLAL r4, r5, %[b], r8\n\t"
  13282. "STM %[r]!, {r4}\n\t"
  13283. "MOV r3, #0x0\n\t"
  13284. /* A[20] * B */
  13285. "LDM %[a]!, {r8}\n\t"
  13286. "UMLAL r5, r3, %[b], r8\n\t"
  13287. "STM %[r]!, {r5}\n\t"
  13288. "MOV r4, #0x0\n\t"
  13289. /* A[21] * B */
  13290. "LDM %[a]!, {r8}\n\t"
  13291. "UMLAL r3, r4, %[b], r8\n\t"
  13292. "STM %[r]!, {r3}\n\t"
  13293. "MOV r5, #0x0\n\t"
  13294. /* A[22] * B */
  13295. "LDM %[a]!, {r8}\n\t"
  13296. "UMLAL r4, r5, %[b], r8\n\t"
  13297. "STM %[r]!, {r4}\n\t"
  13298. "MOV r3, #0x0\n\t"
  13299. /* A[23] * B */
  13300. "LDM %[a]!, {r8}\n\t"
  13301. "UMLAL r5, r3, %[b], r8\n\t"
  13302. "STM %[r]!, {r5}\n\t"
  13303. "MOV r4, #0x0\n\t"
  13304. /* A[24] * B */
  13305. "LDM %[a]!, {r8}\n\t"
  13306. "UMLAL r3, r4, %[b], r8\n\t"
  13307. "STM %[r]!, {r3}\n\t"
  13308. "MOV r5, #0x0\n\t"
  13309. /* A[25] * B */
  13310. "LDM %[a]!, {r8}\n\t"
  13311. "UMLAL r4, r5, %[b], r8\n\t"
  13312. "STM %[r]!, {r4}\n\t"
  13313. "MOV r3, #0x0\n\t"
  13314. /* A[26] * B */
  13315. "LDM %[a]!, {r8}\n\t"
  13316. "UMLAL r5, r3, %[b], r8\n\t"
  13317. "STM %[r]!, {r5}\n\t"
  13318. "MOV r4, #0x0\n\t"
  13319. /* A[27] * B */
  13320. "LDM %[a]!, {r8}\n\t"
  13321. "UMLAL r3, r4, %[b], r8\n\t"
  13322. "STM %[r]!, {r3}\n\t"
  13323. "MOV r5, #0x0\n\t"
  13324. /* A[28] * B */
  13325. "LDM %[a]!, {r8}\n\t"
  13326. "UMLAL r4, r5, %[b], r8\n\t"
  13327. "STM %[r]!, {r4}\n\t"
  13328. "MOV r3, #0x0\n\t"
  13329. /* A[29] * B */
  13330. "LDM %[a]!, {r8}\n\t"
  13331. "UMLAL r5, r3, %[b], r8\n\t"
  13332. "STM %[r]!, {r5}\n\t"
  13333. "MOV r4, #0x0\n\t"
  13334. /* A[30] * B */
  13335. "LDM %[a]!, {r8}\n\t"
  13336. "UMLAL r3, r4, %[b], r8\n\t"
  13337. "STM %[r]!, {r3}\n\t"
  13338. "MOV r5, #0x0\n\t"
  13339. /* A[31] * B */
  13340. "LDM %[a]!, {r8}\n\t"
  13341. "UMLAL r4, r5, %[b], r8\n\t"
  13342. "STM %[r]!, {r4}\n\t"
  13343. "MOV r3, #0x0\n\t"
  13344. /* A[32] * B */
  13345. "LDM %[a]!, {r8}\n\t"
  13346. "UMLAL r5, r3, %[b], r8\n\t"
  13347. "STM %[r]!, {r5}\n\t"
  13348. "MOV r4, #0x0\n\t"
  13349. /* A[33] * B */
  13350. "LDM %[a]!, {r8}\n\t"
  13351. "UMLAL r3, r4, %[b], r8\n\t"
  13352. "STM %[r]!, {r3}\n\t"
  13353. "MOV r5, #0x0\n\t"
  13354. /* A[34] * B */
  13355. "LDM %[a]!, {r8}\n\t"
  13356. "UMLAL r4, r5, %[b], r8\n\t"
  13357. "STM %[r]!, {r4}\n\t"
  13358. "MOV r3, #0x0\n\t"
  13359. /* A[35] * B */
  13360. "LDM %[a]!, {r8}\n\t"
  13361. "UMLAL r5, r3, %[b], r8\n\t"
  13362. "STM %[r]!, {r5}\n\t"
  13363. "MOV r4, #0x0\n\t"
  13364. /* A[36] * B */
  13365. "LDM %[a]!, {r8}\n\t"
  13366. "UMLAL r3, r4, %[b], r8\n\t"
  13367. "STM %[r]!, {r3}\n\t"
  13368. "MOV r5, #0x0\n\t"
  13369. /* A[37] * B */
  13370. "LDM %[a]!, {r8}\n\t"
  13371. "UMLAL r4, r5, %[b], r8\n\t"
  13372. "STM %[r]!, {r4}\n\t"
  13373. "MOV r3, #0x0\n\t"
  13374. /* A[38] * B */
  13375. "LDM %[a]!, {r8}\n\t"
  13376. "UMLAL r5, r3, %[b], r8\n\t"
  13377. "STM %[r]!, {r5}\n\t"
  13378. "MOV r4, #0x0\n\t"
  13379. /* A[39] * B */
  13380. "LDM %[a]!, {r8}\n\t"
  13381. "UMLAL r3, r4, %[b], r8\n\t"
  13382. "STM %[r]!, {r3}\n\t"
  13383. "MOV r5, #0x0\n\t"
  13384. /* A[40] * B */
  13385. "LDM %[a]!, {r8}\n\t"
  13386. "UMLAL r4, r5, %[b], r8\n\t"
  13387. "STM %[r]!, {r4}\n\t"
  13388. "MOV r3, #0x0\n\t"
  13389. /* A[41] * B */
  13390. "LDM %[a]!, {r8}\n\t"
  13391. "UMLAL r5, r3, %[b], r8\n\t"
  13392. "STM %[r]!, {r5}\n\t"
  13393. "MOV r4, #0x0\n\t"
  13394. /* A[42] * B */
  13395. "LDM %[a]!, {r8}\n\t"
  13396. "UMLAL r3, r4, %[b], r8\n\t"
  13397. "STM %[r]!, {r3}\n\t"
  13398. "MOV r5, #0x0\n\t"
  13399. /* A[43] * B */
  13400. "LDM %[a]!, {r8}\n\t"
  13401. "UMLAL r4, r5, %[b], r8\n\t"
  13402. "STM %[r]!, {r4}\n\t"
  13403. "MOV r3, #0x0\n\t"
  13404. /* A[44] * B */
  13405. "LDM %[a]!, {r8}\n\t"
  13406. "UMLAL r5, r3, %[b], r8\n\t"
  13407. "STM %[r]!, {r5}\n\t"
  13408. "MOV r4, #0x0\n\t"
  13409. /* A[45] * B */
  13410. "LDM %[a]!, {r8}\n\t"
  13411. "UMLAL r3, r4, %[b], r8\n\t"
  13412. "STM %[r]!, {r3}\n\t"
  13413. "MOV r5, #0x0\n\t"
  13414. /* A[46] * B */
  13415. "LDM %[a]!, {r8}\n\t"
  13416. "UMLAL r4, r5, %[b], r8\n\t"
  13417. "STM %[r]!, {r4}\n\t"
  13418. "MOV r3, #0x0\n\t"
  13419. /* A[47] * B */
  13420. "LDM %[a]!, {r8}\n\t"
  13421. "UMLAL r5, r3, %[b], r8\n\t"
  13422. "STM %[r]!, {r5}\n\t"
  13423. "MOV r4, #0x0\n\t"
  13424. /* A[48] * B */
  13425. "LDM %[a]!, {r8}\n\t"
  13426. "UMLAL r3, r4, %[b], r8\n\t"
  13427. "STM %[r]!, {r3}\n\t"
  13428. "MOV r5, #0x0\n\t"
  13429. /* A[49] * B */
  13430. "LDM %[a]!, {r8}\n\t"
  13431. "UMLAL r4, r5, %[b], r8\n\t"
  13432. "STM %[r]!, {r4}\n\t"
  13433. "MOV r3, #0x0\n\t"
  13434. /* A[50] * B */
  13435. "LDM %[a]!, {r8}\n\t"
  13436. "UMLAL r5, r3, %[b], r8\n\t"
  13437. "STM %[r]!, {r5}\n\t"
  13438. "MOV r4, #0x0\n\t"
  13439. /* A[51] * B */
  13440. "LDM %[a]!, {r8}\n\t"
  13441. "UMLAL r3, r4, %[b], r8\n\t"
  13442. "STM %[r]!, {r3}\n\t"
  13443. "MOV r5, #0x0\n\t"
  13444. /* A[52] * B */
  13445. "LDM %[a]!, {r8}\n\t"
  13446. "UMLAL r4, r5, %[b], r8\n\t"
  13447. "STM %[r]!, {r4}\n\t"
  13448. "MOV r3, #0x0\n\t"
  13449. /* A[53] * B */
  13450. "LDM %[a]!, {r8}\n\t"
  13451. "UMLAL r5, r3, %[b], r8\n\t"
  13452. "STM %[r]!, {r5}\n\t"
  13453. "MOV r4, #0x0\n\t"
  13454. /* A[54] * B */
  13455. "LDM %[a]!, {r8}\n\t"
  13456. "UMLAL r3, r4, %[b], r8\n\t"
  13457. "STM %[r]!, {r3}\n\t"
  13458. "MOV r5, #0x0\n\t"
  13459. /* A[55] * B */
  13460. "LDM %[a]!, {r8}\n\t"
  13461. "UMLAL r4, r5, %[b], r8\n\t"
  13462. "STM %[r]!, {r4}\n\t"
  13463. "MOV r3, #0x0\n\t"
  13464. /* A[56] * B */
  13465. "LDM %[a]!, {r8}\n\t"
  13466. "UMLAL r5, r3, %[b], r8\n\t"
  13467. "STM %[r]!, {r5}\n\t"
  13468. "MOV r4, #0x0\n\t"
  13469. /* A[57] * B */
  13470. "LDM %[a]!, {r8}\n\t"
  13471. "UMLAL r3, r4, %[b], r8\n\t"
  13472. "STM %[r]!, {r3}\n\t"
  13473. "MOV r5, #0x0\n\t"
  13474. /* A[58] * B */
  13475. "LDM %[a]!, {r8}\n\t"
  13476. "UMLAL r4, r5, %[b], r8\n\t"
  13477. "STM %[r]!, {r4}\n\t"
  13478. "MOV r3, #0x0\n\t"
  13479. /* A[59] * B */
  13480. "LDM %[a]!, {r8}\n\t"
  13481. "UMLAL r5, r3, %[b], r8\n\t"
  13482. "STM %[r]!, {r5}\n\t"
  13483. "MOV r4, #0x0\n\t"
  13484. /* A[60] * B */
  13485. "LDM %[a]!, {r8}\n\t"
  13486. "UMLAL r3, r4, %[b], r8\n\t"
  13487. "STM %[r]!, {r3}\n\t"
  13488. "MOV r5, #0x0\n\t"
  13489. /* A[61] * B */
  13490. "LDM %[a]!, {r8}\n\t"
  13491. "UMLAL r4, r5, %[b], r8\n\t"
  13492. "STM %[r]!, {r4}\n\t"
  13493. "MOV r3, #0x0\n\t"
  13494. /* A[62] * B */
  13495. "LDM %[a]!, {r8}\n\t"
  13496. "UMLAL r5, r3, %[b], r8\n\t"
  13497. "STM %[r]!, {r5}\n\t"
  13498. "MOV r4, #0x0\n\t"
  13499. /* A[63] * B */
  13500. "LDM %[a]!, {r8}\n\t"
  13501. "UMLAL r3, r4, %[b], r8\n\t"
  13502. "STM %[r]!, {r3}\n\t"
  13503. "MOV r5, #0x0\n\t"
  13504. /* A[64] * B */
  13505. "LDM %[a]!, {r8}\n\t"
  13506. "UMLAL r4, r5, %[b], r8\n\t"
  13507. "STM %[r]!, {r4}\n\t"
  13508. "MOV r3, #0x0\n\t"
  13509. /* A[65] * B */
  13510. "LDM %[a]!, {r8}\n\t"
  13511. "UMLAL r5, r3, %[b], r8\n\t"
  13512. "STM %[r]!, {r5}\n\t"
  13513. "MOV r4, #0x0\n\t"
  13514. /* A[66] * B */
  13515. "LDM %[a]!, {r8}\n\t"
  13516. "UMLAL r3, r4, %[b], r8\n\t"
  13517. "STM %[r]!, {r3}\n\t"
  13518. "MOV r5, #0x0\n\t"
  13519. /* A[67] * B */
  13520. "LDM %[a]!, {r8}\n\t"
  13521. "UMLAL r4, r5, %[b], r8\n\t"
  13522. "STM %[r]!, {r4}\n\t"
  13523. "MOV r3, #0x0\n\t"
  13524. /* A[68] * B */
  13525. "LDM %[a]!, {r8}\n\t"
  13526. "UMLAL r5, r3, %[b], r8\n\t"
  13527. "STM %[r]!, {r5}\n\t"
  13528. "MOV r4, #0x0\n\t"
  13529. /* A[69] * B */
  13530. "LDM %[a]!, {r8}\n\t"
  13531. "UMLAL r3, r4, %[b], r8\n\t"
  13532. "STM %[r]!, {r3}\n\t"
  13533. "MOV r5, #0x0\n\t"
  13534. /* A[70] * B */
  13535. "LDM %[a]!, {r8}\n\t"
  13536. "UMLAL r4, r5, %[b], r8\n\t"
  13537. "STM %[r]!, {r4}\n\t"
  13538. "MOV r3, #0x0\n\t"
  13539. /* A[71] * B */
  13540. "LDM %[a]!, {r8}\n\t"
  13541. "UMLAL r5, r3, %[b], r8\n\t"
  13542. "STM %[r]!, {r5}\n\t"
  13543. "MOV r4, #0x0\n\t"
  13544. /* A[72] * B */
  13545. "LDM %[a]!, {r8}\n\t"
  13546. "UMLAL r3, r4, %[b], r8\n\t"
  13547. "STM %[r]!, {r3}\n\t"
  13548. "MOV r5, #0x0\n\t"
  13549. /* A[73] * B */
  13550. "LDM %[a]!, {r8}\n\t"
  13551. "UMLAL r4, r5, %[b], r8\n\t"
  13552. "STM %[r]!, {r4}\n\t"
  13553. "MOV r3, #0x0\n\t"
  13554. /* A[74] * B */
  13555. "LDM %[a]!, {r8}\n\t"
  13556. "UMLAL r5, r3, %[b], r8\n\t"
  13557. "STM %[r]!, {r5}\n\t"
  13558. "MOV r4, #0x0\n\t"
  13559. /* A[75] * B */
  13560. "LDM %[a]!, {r8}\n\t"
  13561. "UMLAL r3, r4, %[b], r8\n\t"
  13562. "STM %[r]!, {r3}\n\t"
  13563. "MOV r5, #0x0\n\t"
  13564. /* A[76] * B */
  13565. "LDM %[a]!, {r8}\n\t"
  13566. "UMLAL r4, r5, %[b], r8\n\t"
  13567. "STM %[r]!, {r4}\n\t"
  13568. "MOV r3, #0x0\n\t"
  13569. /* A[77] * B */
  13570. "LDM %[a]!, {r8}\n\t"
  13571. "UMLAL r5, r3, %[b], r8\n\t"
  13572. "STM %[r]!, {r5}\n\t"
  13573. "MOV r4, #0x0\n\t"
  13574. /* A[78] * B */
  13575. "LDM %[a]!, {r8}\n\t"
  13576. "UMLAL r3, r4, %[b], r8\n\t"
  13577. "STM %[r]!, {r3}\n\t"
  13578. "MOV r5, #0x0\n\t"
  13579. /* A[79] * B */
  13580. "LDM %[a]!, {r8}\n\t"
  13581. "UMLAL r4, r5, %[b], r8\n\t"
  13582. "STM %[r]!, {r4}\n\t"
  13583. "MOV r3, #0x0\n\t"
  13584. /* A[80] * B */
  13585. "LDM %[a]!, {r8}\n\t"
  13586. "UMLAL r5, r3, %[b], r8\n\t"
  13587. "STM %[r]!, {r5}\n\t"
  13588. "MOV r4, #0x0\n\t"
  13589. /* A[81] * B */
  13590. "LDM %[a]!, {r8}\n\t"
  13591. "UMLAL r3, r4, %[b], r8\n\t"
  13592. "STM %[r]!, {r3}\n\t"
  13593. "MOV r5, #0x0\n\t"
  13594. /* A[82] * B */
  13595. "LDM %[a]!, {r8}\n\t"
  13596. "UMLAL r4, r5, %[b], r8\n\t"
  13597. "STM %[r]!, {r4}\n\t"
  13598. "MOV r3, #0x0\n\t"
  13599. /* A[83] * B */
  13600. "LDM %[a]!, {r8}\n\t"
  13601. "UMLAL r5, r3, %[b], r8\n\t"
  13602. "STM %[r]!, {r5}\n\t"
  13603. "MOV r4, #0x0\n\t"
  13604. /* A[84] * B */
  13605. "LDM %[a]!, {r8}\n\t"
  13606. "UMLAL r3, r4, %[b], r8\n\t"
  13607. "STM %[r]!, {r3}\n\t"
  13608. "MOV r5, #0x0\n\t"
  13609. /* A[85] * B */
  13610. "LDM %[a]!, {r8}\n\t"
  13611. "UMLAL r4, r5, %[b], r8\n\t"
  13612. "STM %[r]!, {r4}\n\t"
  13613. "MOV r3, #0x0\n\t"
  13614. /* A[86] * B */
  13615. "LDM %[a]!, {r8}\n\t"
  13616. "UMLAL r5, r3, %[b], r8\n\t"
  13617. "STM %[r]!, {r5}\n\t"
  13618. "MOV r4, #0x0\n\t"
  13619. /* A[87] * B */
  13620. "LDM %[a]!, {r8}\n\t"
  13621. "UMLAL r3, r4, %[b], r8\n\t"
  13622. "STM %[r]!, {r3}\n\t"
  13623. "MOV r5, #0x0\n\t"
  13624. /* A[88] * B */
  13625. "LDM %[a]!, {r8}\n\t"
  13626. "UMLAL r4, r5, %[b], r8\n\t"
  13627. "STM %[r]!, {r4}\n\t"
  13628. "MOV r3, #0x0\n\t"
  13629. /* A[89] * B */
  13630. "LDM %[a]!, {r8}\n\t"
  13631. "UMLAL r5, r3, %[b], r8\n\t"
  13632. "STM %[r]!, {r5}\n\t"
  13633. "MOV r4, #0x0\n\t"
  13634. /* A[90] * B */
  13635. "LDM %[a]!, {r8}\n\t"
  13636. "UMLAL r3, r4, %[b], r8\n\t"
  13637. "STM %[r]!, {r3}\n\t"
  13638. "MOV r5, #0x0\n\t"
  13639. /* A[91] * B */
  13640. "LDM %[a]!, {r8}\n\t"
  13641. "UMLAL r4, r5, %[b], r8\n\t"
  13642. "STM %[r]!, {r4}\n\t"
  13643. "MOV r3, #0x0\n\t"
  13644. /* A[92] * B */
  13645. "LDM %[a]!, {r8}\n\t"
  13646. "UMLAL r5, r3, %[b], r8\n\t"
  13647. "STM %[r]!, {r5}\n\t"
  13648. "MOV r4, #0x0\n\t"
  13649. /* A[93] * B */
  13650. "LDM %[a]!, {r8}\n\t"
  13651. "UMLAL r3, r4, %[b], r8\n\t"
  13652. "STM %[r]!, {r3}\n\t"
  13653. "MOV r5, #0x0\n\t"
  13654. /* A[94] * B */
  13655. "LDM %[a]!, {r8}\n\t"
  13656. "UMLAL r4, r5, %[b], r8\n\t"
  13657. "STM %[r]!, {r4}\n\t"
  13658. "MOV r3, #0x0\n\t"
  13659. /* A[95] * B */
  13660. "LDM %[a]!, {r8}\n\t"
  13661. "UMLAL r5, r3, %[b], r8\n\t"
  13662. "STM %[r]!, {r5}\n\t"
  13663. "STR r3, [%[r]]\n\t"
  13664. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  13665. :
  13666. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  13667. );
  13668. }
  13669. #endif /* WOLFSSL_SP_SMALL */
  13670. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  13671. /* r = 2^n mod m where n is the number of bits to reduce by.
  13672. * Given m must be 3072 bits, just need to subtract.
  13673. *
  13674. * r A single precision number.
  13675. * m A single precision number.
  13676. */
  13677. static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m)
  13678. {
  13679. XMEMSET(r, 0, sizeof(sp_digit) * 48);
  13680. /* r = 2^n mod m */
  13681. sp_3072_sub_in_place_48(r, m);
  13682. }
  13683. #ifdef WOLFSSL_SP_SMALL
  13684. /* Conditionally subtract b from a using the mask m.
  13685. * m is -1 to subtract and 0 when not copying.
  13686. *
  13687. * r A single precision number representing condition subtract result.
  13688. * a A single precision number to subtract from.
  13689. * b A single precision number to subtract.
  13690. * m Mask value to apply.
  13691. */
  13692. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13693. static sp_digit sp_3072_cond_sub_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  13694. #else
  13695. static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  13696. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13697. {
  13698. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13699. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  13700. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  13701. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  13702. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  13703. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13704. __asm__ __volatile__ (
  13705. "MOV r8, #0x0\n\t"
  13706. "MOV r4, #0x0\n\t"
  13707. "MOV r5, #0x0\n\t"
  13708. "\n"
  13709. "L_sp_3072_cond_sub_48_words:\n\t"
  13710. "SUBS r4, r8, r4\n\t"
  13711. "LDR r6, [%[a], r5]\n\t"
  13712. "LDR r7, [%[b], r5]\n\t"
  13713. "AND r7, r7, %[m]\n\t"
  13714. "SBCS r6, r6, r7\n\t"
  13715. "SBC r4, r8, r8\n\t"
  13716. "STR r6, [%[r], r5]\n\t"
  13717. "ADD r5, r5, #0x4\n\t"
  13718. "CMP r5, #0xc0\n\t"
  13719. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  13720. "BLT L_sp_3072_cond_sub_48_words\n\t"
  13721. #else
  13722. "BLT.N L_sp_3072_cond_sub_48_words\n\t"
  13723. #endif
  13724. "MOV %[r], r4\n\t"
  13725. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  13726. :
  13727. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  13728. );
  13729. return (uint32_t)(size_t)r;
  13730. }
  13731. #else
  13732. /* Conditionally subtract b from a using the mask m.
  13733. * m is -1 to subtract and 0 when not copying.
  13734. *
  13735. * r A single precision number representing condition subtract result.
  13736. * a A single precision number to subtract from.
  13737. * b A single precision number to subtract.
  13738. * m Mask value to apply.
  13739. */
  13740. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13741. static sp_digit sp_3072_cond_sub_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  13742. #else
  13743. static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  13744. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13745. {
  13746. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13747. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  13748. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  13749. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  13750. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  13751. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13752. __asm__ __volatile__ (
  13753. "MOV r5, #0x0\n\t"
  13754. "LDM %[a]!, {r6, r7}\n\t"
  13755. "LDM %[b]!, {r8, r9}\n\t"
  13756. "AND r8, r8, %[m]\n\t"
  13757. "AND r9, r9, %[m]\n\t"
  13758. "SUBS r6, r6, r8\n\t"
  13759. "SBCS r7, r7, r9\n\t"
  13760. "STM %[r]!, {r6, r7}\n\t"
  13761. "LDM %[a]!, {r6, r7}\n\t"
  13762. "LDM %[b]!, {r8, r9}\n\t"
  13763. "AND r8, r8, %[m]\n\t"
  13764. "AND r9, r9, %[m]\n\t"
  13765. "SBCS r6, r6, r8\n\t"
  13766. "SBCS r7, r7, r9\n\t"
  13767. "STM %[r]!, {r6, r7}\n\t"
  13768. "LDM %[a]!, {r6, r7}\n\t"
  13769. "LDM %[b]!, {r8, r9}\n\t"
  13770. "AND r8, r8, %[m]\n\t"
  13771. "AND r9, r9, %[m]\n\t"
  13772. "SBCS r6, r6, r8\n\t"
  13773. "SBCS r7, r7, r9\n\t"
  13774. "STM %[r]!, {r6, r7}\n\t"
  13775. "LDM %[a]!, {r6, r7}\n\t"
  13776. "LDM %[b]!, {r8, r9}\n\t"
  13777. "AND r8, r8, %[m]\n\t"
  13778. "AND r9, r9, %[m]\n\t"
  13779. "SBCS r6, r6, r8\n\t"
  13780. "SBCS r7, r7, r9\n\t"
  13781. "STM %[r]!, {r6, r7}\n\t"
  13782. "LDM %[a]!, {r6, r7}\n\t"
  13783. "LDM %[b]!, {r8, r9}\n\t"
  13784. "AND r8, r8, %[m]\n\t"
  13785. "AND r9, r9, %[m]\n\t"
  13786. "SBCS r6, r6, r8\n\t"
  13787. "SBCS r7, r7, r9\n\t"
  13788. "STM %[r]!, {r6, r7}\n\t"
  13789. "LDM %[a]!, {r6, r7}\n\t"
  13790. "LDM %[b]!, {r8, r9}\n\t"
  13791. "AND r8, r8, %[m]\n\t"
  13792. "AND r9, r9, %[m]\n\t"
  13793. "SBCS r6, r6, r8\n\t"
  13794. "SBCS r7, r7, r9\n\t"
  13795. "STM %[r]!, {r6, r7}\n\t"
  13796. "LDM %[a]!, {r6, r7}\n\t"
  13797. "LDM %[b]!, {r8, r9}\n\t"
  13798. "AND r8, r8, %[m]\n\t"
  13799. "AND r9, r9, %[m]\n\t"
  13800. "SBCS r6, r6, r8\n\t"
  13801. "SBCS r7, r7, r9\n\t"
  13802. "STM %[r]!, {r6, r7}\n\t"
  13803. "LDM %[a]!, {r6, r7}\n\t"
  13804. "LDM %[b]!, {r8, r9}\n\t"
  13805. "AND r8, r8, %[m]\n\t"
  13806. "AND r9, r9, %[m]\n\t"
  13807. "SBCS r6, r6, r8\n\t"
  13808. "SBCS r7, r7, r9\n\t"
  13809. "STM %[r]!, {r6, r7}\n\t"
  13810. "LDM %[a]!, {r6, r7}\n\t"
  13811. "LDM %[b]!, {r8, r9}\n\t"
  13812. "AND r8, r8, %[m]\n\t"
  13813. "AND r9, r9, %[m]\n\t"
  13814. "SBCS r6, r6, r8\n\t"
  13815. "SBCS r7, r7, r9\n\t"
  13816. "STM %[r]!, {r6, r7}\n\t"
  13817. "LDM %[a]!, {r6, r7}\n\t"
  13818. "LDM %[b]!, {r8, r9}\n\t"
  13819. "AND r8, r8, %[m]\n\t"
  13820. "AND r9, r9, %[m]\n\t"
  13821. "SBCS r6, r6, r8\n\t"
  13822. "SBCS r7, r7, r9\n\t"
  13823. "STM %[r]!, {r6, r7}\n\t"
  13824. "LDM %[a]!, {r6, r7}\n\t"
  13825. "LDM %[b]!, {r8, r9}\n\t"
  13826. "AND r8, r8, %[m]\n\t"
  13827. "AND r9, r9, %[m]\n\t"
  13828. "SBCS r6, r6, r8\n\t"
  13829. "SBCS r7, r7, r9\n\t"
  13830. "STM %[r]!, {r6, r7}\n\t"
  13831. "LDM %[a]!, {r6, r7}\n\t"
  13832. "LDM %[b]!, {r8, r9}\n\t"
  13833. "AND r8, r8, %[m]\n\t"
  13834. "AND r9, r9, %[m]\n\t"
  13835. "SBCS r6, r6, r8\n\t"
  13836. "SBCS r7, r7, r9\n\t"
  13837. "STM %[r]!, {r6, r7}\n\t"
  13838. "LDM %[a]!, {r6, r7}\n\t"
  13839. "LDM %[b]!, {r8, r9}\n\t"
  13840. "AND r8, r8, %[m]\n\t"
  13841. "AND r9, r9, %[m]\n\t"
  13842. "SBCS r6, r6, r8\n\t"
  13843. "SBCS r7, r7, r9\n\t"
  13844. "STM %[r]!, {r6, r7}\n\t"
  13845. "LDM %[a]!, {r6, r7}\n\t"
  13846. "LDM %[b]!, {r8, r9}\n\t"
  13847. "AND r8, r8, %[m]\n\t"
  13848. "AND r9, r9, %[m]\n\t"
  13849. "SBCS r6, r6, r8\n\t"
  13850. "SBCS r7, r7, r9\n\t"
  13851. "STM %[r]!, {r6, r7}\n\t"
  13852. "LDM %[a]!, {r6, r7}\n\t"
  13853. "LDM %[b]!, {r8, r9}\n\t"
  13854. "AND r8, r8, %[m]\n\t"
  13855. "AND r9, r9, %[m]\n\t"
  13856. "SBCS r6, r6, r8\n\t"
  13857. "SBCS r7, r7, r9\n\t"
  13858. "STM %[r]!, {r6, r7}\n\t"
  13859. "LDM %[a]!, {r6, r7}\n\t"
  13860. "LDM %[b]!, {r8, r9}\n\t"
  13861. "AND r8, r8, %[m]\n\t"
  13862. "AND r9, r9, %[m]\n\t"
  13863. "SBCS r6, r6, r8\n\t"
  13864. "SBCS r7, r7, r9\n\t"
  13865. "STM %[r]!, {r6, r7}\n\t"
  13866. "LDM %[a]!, {r6, r7}\n\t"
  13867. "LDM %[b]!, {r8, r9}\n\t"
  13868. "AND r8, r8, %[m]\n\t"
  13869. "AND r9, r9, %[m]\n\t"
  13870. "SBCS r6, r6, r8\n\t"
  13871. "SBCS r7, r7, r9\n\t"
  13872. "STM %[r]!, {r6, r7}\n\t"
  13873. "LDM %[a]!, {r6, r7}\n\t"
  13874. "LDM %[b]!, {r8, r9}\n\t"
  13875. "AND r8, r8, %[m]\n\t"
  13876. "AND r9, r9, %[m]\n\t"
  13877. "SBCS r6, r6, r8\n\t"
  13878. "SBCS r7, r7, r9\n\t"
  13879. "STM %[r]!, {r6, r7}\n\t"
  13880. "LDM %[a]!, {r6, r7}\n\t"
  13881. "LDM %[b]!, {r8, r9}\n\t"
  13882. "AND r8, r8, %[m]\n\t"
  13883. "AND r9, r9, %[m]\n\t"
  13884. "SBCS r6, r6, r8\n\t"
  13885. "SBCS r7, r7, r9\n\t"
  13886. "STM %[r]!, {r6, r7}\n\t"
  13887. "LDM %[a]!, {r6, r7}\n\t"
  13888. "LDM %[b]!, {r8, r9}\n\t"
  13889. "AND r8, r8, %[m]\n\t"
  13890. "AND r9, r9, %[m]\n\t"
  13891. "SBCS r6, r6, r8\n\t"
  13892. "SBCS r7, r7, r9\n\t"
  13893. "STM %[r]!, {r6, r7}\n\t"
  13894. "LDM %[a]!, {r6, r7}\n\t"
  13895. "LDM %[b]!, {r8, r9}\n\t"
  13896. "AND r8, r8, %[m]\n\t"
  13897. "AND r9, r9, %[m]\n\t"
  13898. "SBCS r6, r6, r8\n\t"
  13899. "SBCS r7, r7, r9\n\t"
  13900. "STM %[r]!, {r6, r7}\n\t"
  13901. "LDM %[a]!, {r6, r7}\n\t"
  13902. "LDM %[b]!, {r8, r9}\n\t"
  13903. "AND r8, r8, %[m]\n\t"
  13904. "AND r9, r9, %[m]\n\t"
  13905. "SBCS r6, r6, r8\n\t"
  13906. "SBCS r7, r7, r9\n\t"
  13907. "STM %[r]!, {r6, r7}\n\t"
  13908. "LDM %[a]!, {r6, r7}\n\t"
  13909. "LDM %[b]!, {r8, r9}\n\t"
  13910. "AND r8, r8, %[m]\n\t"
  13911. "AND r9, r9, %[m]\n\t"
  13912. "SBCS r6, r6, r8\n\t"
  13913. "SBCS r7, r7, r9\n\t"
  13914. "STM %[r]!, {r6, r7}\n\t"
  13915. "LDM %[a]!, {r6, r7}\n\t"
  13916. "LDM %[b]!, {r8, r9}\n\t"
  13917. "AND r8, r8, %[m]\n\t"
  13918. "AND r9, r9, %[m]\n\t"
  13919. "SBCS r6, r6, r8\n\t"
  13920. "SBCS r7, r7, r9\n\t"
  13921. "STM %[r]!, {r6, r7}\n\t"
  13922. "SBC %[r], r5, r5\n\t"
  13923. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  13924. :
  13925. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  13926. );
  13927. return (uint32_t)(size_t)r;
  13928. }
  13929. #endif /* WOLFSSL_SP_SMALL */
  13930. #ifdef WOLFSSL_SP_NO_UMAAL
  13931. #ifndef WOLFSSL_SP_SMALL
  13932. /* Reduce the number back to 3072 bits using Montgomery reduction.
  13933. *
  13934. * a A single precision number to reduce in place.
  13935. * m The single precision number representing the modulus.
  13936. * mp The digit representing the negative inverse of m mod 2^n.
  13937. */
  13938. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13939. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  13940. #else
  13941. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp)
  13942. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13943. {
  13944. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  13945. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  13946. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  13947. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  13948. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  13949. __asm__ __volatile__ (
  13950. "LDR lr, [%[m]]\n\t"
  13951. /* i = 0 */
  13952. "MOV r11, #0x0\n\t"
  13953. "MOV r3, #0x0\n\t"
  13954. "LDR r4, [%[a]]\n\t"
  13955. "LDR r5, [%[a], #4]\n\t"
  13956. "\n"
  13957. "L_sp_3072_mont_reduce_48_word:\n\t"
  13958. /* mu = a[i] * mp */
  13959. "MUL r10, %[mp], r4\n\t"
  13960. /* a[i+0] += m[0] * mu */
  13961. "MOV r7, #0x0\n\t"
  13962. "UMLAL r4, r7, r10, lr\n\t"
  13963. /* a[i+1] += m[1] * mu */
  13964. "LDR r9, [%[m], #4]\n\t"
  13965. "MOV r6, #0x0\n\t"
  13966. "UMLAL r5, r6, r10, r9\n\t"
  13967. "MOV r4, r5\n\t"
  13968. "ADDS r4, r4, r7\n\t"
  13969. "ADC r6, r6, #0x0\n\t"
  13970. /* a[i+2] += m[2] * mu */
  13971. "LDR r9, [%[m], #8]\n\t"
  13972. "LDR r5, [%[a], #8]\n\t"
  13973. "MOV r7, #0x0\n\t"
  13974. "UMLAL r5, r7, r10, r9\n\t"
  13975. "ADDS r5, r5, r6\n\t"
  13976. "ADC r7, r7, #0x0\n\t"
  13977. /* a[i+3] += m[3] * mu */
  13978. "LDR r9, [%[m], #12]\n\t"
  13979. "LDR r12, [%[a], #12]\n\t"
  13980. "MOV r6, #0x0\n\t"
  13981. "UMLAL r12, r6, r10, r9\n\t"
  13982. "ADDS r12, r12, r7\n\t"
  13983. "STR r12, [%[a], #12]\n\t"
  13984. "ADC r6, r6, #0x0\n\t"
  13985. /* a[i+4] += m[4] * mu */
  13986. "LDR r9, [%[m], #16]\n\t"
  13987. "LDR r12, [%[a], #16]\n\t"
  13988. "MOV r7, #0x0\n\t"
  13989. "UMLAL r12, r7, r10, r9\n\t"
  13990. "ADDS r12, r12, r6\n\t"
  13991. "STR r12, [%[a], #16]\n\t"
  13992. "ADC r7, r7, #0x0\n\t"
  13993. /* a[i+5] += m[5] * mu */
  13994. "LDR r9, [%[m], #20]\n\t"
  13995. "LDR r12, [%[a], #20]\n\t"
  13996. "MOV r6, #0x0\n\t"
  13997. "UMLAL r12, r6, r10, r9\n\t"
  13998. "ADDS r12, r12, r7\n\t"
  13999. "STR r12, [%[a], #20]\n\t"
  14000. "ADC r6, r6, #0x0\n\t"
  14001. /* a[i+6] += m[6] * mu */
  14002. "LDR r9, [%[m], #24]\n\t"
  14003. "LDR r12, [%[a], #24]\n\t"
  14004. "MOV r7, #0x0\n\t"
  14005. "UMLAL r12, r7, r10, r9\n\t"
  14006. "ADDS r12, r12, r6\n\t"
  14007. "STR r12, [%[a], #24]\n\t"
  14008. "ADC r7, r7, #0x0\n\t"
  14009. /* a[i+7] += m[7] * mu */
  14010. "LDR r9, [%[m], #28]\n\t"
  14011. "LDR r12, [%[a], #28]\n\t"
  14012. "MOV r6, #0x0\n\t"
  14013. "UMLAL r12, r6, r10, r9\n\t"
  14014. "ADDS r12, r12, r7\n\t"
  14015. "STR r12, [%[a], #28]\n\t"
  14016. "ADC r6, r6, #0x0\n\t"
  14017. /* a[i+8] += m[8] * mu */
  14018. "LDR r9, [%[m], #32]\n\t"
  14019. "LDR r12, [%[a], #32]\n\t"
  14020. "MOV r7, #0x0\n\t"
  14021. "UMLAL r12, r7, r10, r9\n\t"
  14022. "ADDS r12, r12, r6\n\t"
  14023. "STR r12, [%[a], #32]\n\t"
  14024. "ADC r7, r7, #0x0\n\t"
  14025. /* a[i+9] += m[9] * mu */
  14026. "LDR r9, [%[m], #36]\n\t"
  14027. "LDR r12, [%[a], #36]\n\t"
  14028. "MOV r6, #0x0\n\t"
  14029. "UMLAL r12, r6, r10, r9\n\t"
  14030. "ADDS r12, r12, r7\n\t"
  14031. "STR r12, [%[a], #36]\n\t"
  14032. "ADC r6, r6, #0x0\n\t"
  14033. /* a[i+10] += m[10] * mu */
  14034. "LDR r9, [%[m], #40]\n\t"
  14035. "LDR r12, [%[a], #40]\n\t"
  14036. "MOV r7, #0x0\n\t"
  14037. "UMLAL r12, r7, r10, r9\n\t"
  14038. "ADDS r12, r12, r6\n\t"
  14039. "STR r12, [%[a], #40]\n\t"
  14040. "ADC r7, r7, #0x0\n\t"
  14041. /* a[i+11] += m[11] * mu */
  14042. "LDR r9, [%[m], #44]\n\t"
  14043. "LDR r12, [%[a], #44]\n\t"
  14044. "MOV r6, #0x0\n\t"
  14045. "UMLAL r12, r6, r10, r9\n\t"
  14046. "ADDS r12, r12, r7\n\t"
  14047. "STR r12, [%[a], #44]\n\t"
  14048. "ADC r6, r6, #0x0\n\t"
  14049. /* a[i+12] += m[12] * mu */
  14050. "LDR r9, [%[m], #48]\n\t"
  14051. "LDR r12, [%[a], #48]\n\t"
  14052. "MOV r7, #0x0\n\t"
  14053. "UMLAL r12, r7, r10, r9\n\t"
  14054. "ADDS r12, r12, r6\n\t"
  14055. "STR r12, [%[a], #48]\n\t"
  14056. "ADC r7, r7, #0x0\n\t"
  14057. /* a[i+13] += m[13] * mu */
  14058. "LDR r9, [%[m], #52]\n\t"
  14059. "LDR r12, [%[a], #52]\n\t"
  14060. "MOV r6, #0x0\n\t"
  14061. "UMLAL r12, r6, r10, r9\n\t"
  14062. "ADDS r12, r12, r7\n\t"
  14063. "STR r12, [%[a], #52]\n\t"
  14064. "ADC r6, r6, #0x0\n\t"
  14065. /* a[i+14] += m[14] * mu */
  14066. "LDR r9, [%[m], #56]\n\t"
  14067. "LDR r12, [%[a], #56]\n\t"
  14068. "MOV r7, #0x0\n\t"
  14069. "UMLAL r12, r7, r10, r9\n\t"
  14070. "ADDS r12, r12, r6\n\t"
  14071. "STR r12, [%[a], #56]\n\t"
  14072. "ADC r7, r7, #0x0\n\t"
  14073. /* a[i+15] += m[15] * mu */
  14074. "LDR r9, [%[m], #60]\n\t"
  14075. "LDR r12, [%[a], #60]\n\t"
  14076. "MOV r6, #0x0\n\t"
  14077. "UMLAL r12, r6, r10, r9\n\t"
  14078. "ADDS r12, r12, r7\n\t"
  14079. "STR r12, [%[a], #60]\n\t"
  14080. "ADC r6, r6, #0x0\n\t"
  14081. /* a[i+16] += m[16] * mu */
  14082. "LDR r9, [%[m], #64]\n\t"
  14083. "LDR r12, [%[a], #64]\n\t"
  14084. "MOV r7, #0x0\n\t"
  14085. "UMLAL r12, r7, r10, r9\n\t"
  14086. "ADDS r12, r12, r6\n\t"
  14087. "STR r12, [%[a], #64]\n\t"
  14088. "ADC r7, r7, #0x0\n\t"
  14089. /* a[i+17] += m[17] * mu */
  14090. "LDR r9, [%[m], #68]\n\t"
  14091. "LDR r12, [%[a], #68]\n\t"
  14092. "MOV r6, #0x0\n\t"
  14093. "UMLAL r12, r6, r10, r9\n\t"
  14094. "ADDS r12, r12, r7\n\t"
  14095. "STR r12, [%[a], #68]\n\t"
  14096. "ADC r6, r6, #0x0\n\t"
  14097. /* a[i+18] += m[18] * mu */
  14098. "LDR r9, [%[m], #72]\n\t"
  14099. "LDR r12, [%[a], #72]\n\t"
  14100. "MOV r7, #0x0\n\t"
  14101. "UMLAL r12, r7, r10, r9\n\t"
  14102. "ADDS r12, r12, r6\n\t"
  14103. "STR r12, [%[a], #72]\n\t"
  14104. "ADC r7, r7, #0x0\n\t"
  14105. /* a[i+19] += m[19] * mu */
  14106. "LDR r9, [%[m], #76]\n\t"
  14107. "LDR r12, [%[a], #76]\n\t"
  14108. "MOV r6, #0x0\n\t"
  14109. "UMLAL r12, r6, r10, r9\n\t"
  14110. "ADDS r12, r12, r7\n\t"
  14111. "STR r12, [%[a], #76]\n\t"
  14112. "ADC r6, r6, #0x0\n\t"
  14113. /* a[i+20] += m[20] * mu */
  14114. "LDR r9, [%[m], #80]\n\t"
  14115. "LDR r12, [%[a], #80]\n\t"
  14116. "MOV r7, #0x0\n\t"
  14117. "UMLAL r12, r7, r10, r9\n\t"
  14118. "ADDS r12, r12, r6\n\t"
  14119. "STR r12, [%[a], #80]\n\t"
  14120. "ADC r7, r7, #0x0\n\t"
  14121. /* a[i+21] += m[21] * mu */
  14122. "LDR r9, [%[m], #84]\n\t"
  14123. "LDR r12, [%[a], #84]\n\t"
  14124. "MOV r6, #0x0\n\t"
  14125. "UMLAL r12, r6, r10, r9\n\t"
  14126. "ADDS r12, r12, r7\n\t"
  14127. "STR r12, [%[a], #84]\n\t"
  14128. "ADC r6, r6, #0x0\n\t"
  14129. /* a[i+22] += m[22] * mu */
  14130. "LDR r9, [%[m], #88]\n\t"
  14131. "LDR r12, [%[a], #88]\n\t"
  14132. "MOV r7, #0x0\n\t"
  14133. "UMLAL r12, r7, r10, r9\n\t"
  14134. "ADDS r12, r12, r6\n\t"
  14135. "STR r12, [%[a], #88]\n\t"
  14136. "ADC r7, r7, #0x0\n\t"
  14137. /* a[i+23] += m[23] * mu */
  14138. "LDR r9, [%[m], #92]\n\t"
  14139. "LDR r12, [%[a], #92]\n\t"
  14140. "MOV r6, #0x0\n\t"
  14141. "UMLAL r12, r6, r10, r9\n\t"
  14142. "ADDS r12, r12, r7\n\t"
  14143. "STR r12, [%[a], #92]\n\t"
  14144. "ADC r6, r6, #0x0\n\t"
  14145. /* a[i+24] += m[24] * mu */
  14146. "LDR r9, [%[m], #96]\n\t"
  14147. "LDR r12, [%[a], #96]\n\t"
  14148. "MOV r7, #0x0\n\t"
  14149. "UMLAL r12, r7, r10, r9\n\t"
  14150. "ADDS r12, r12, r6\n\t"
  14151. "STR r12, [%[a], #96]\n\t"
  14152. "ADC r7, r7, #0x0\n\t"
  14153. /* a[i+25] += m[25] * mu */
  14154. "LDR r9, [%[m], #100]\n\t"
  14155. "LDR r12, [%[a], #100]\n\t"
  14156. "MOV r6, #0x0\n\t"
  14157. "UMLAL r12, r6, r10, r9\n\t"
  14158. "ADDS r12, r12, r7\n\t"
  14159. "STR r12, [%[a], #100]\n\t"
  14160. "ADC r6, r6, #0x0\n\t"
  14161. /* a[i+26] += m[26] * mu */
  14162. "LDR r9, [%[m], #104]\n\t"
  14163. "LDR r12, [%[a], #104]\n\t"
  14164. "MOV r7, #0x0\n\t"
  14165. "UMLAL r12, r7, r10, r9\n\t"
  14166. "ADDS r12, r12, r6\n\t"
  14167. "STR r12, [%[a], #104]\n\t"
  14168. "ADC r7, r7, #0x0\n\t"
  14169. /* a[i+27] += m[27] * mu */
  14170. "LDR r9, [%[m], #108]\n\t"
  14171. "LDR r12, [%[a], #108]\n\t"
  14172. "MOV r6, #0x0\n\t"
  14173. "UMLAL r12, r6, r10, r9\n\t"
  14174. "ADDS r12, r12, r7\n\t"
  14175. "STR r12, [%[a], #108]\n\t"
  14176. "ADC r6, r6, #0x0\n\t"
  14177. /* a[i+28] += m[28] * mu */
  14178. "LDR r9, [%[m], #112]\n\t"
  14179. "LDR r12, [%[a], #112]\n\t"
  14180. "MOV r7, #0x0\n\t"
  14181. "UMLAL r12, r7, r10, r9\n\t"
  14182. "ADDS r12, r12, r6\n\t"
  14183. "STR r12, [%[a], #112]\n\t"
  14184. "ADC r7, r7, #0x0\n\t"
  14185. /* a[i+29] += m[29] * mu */
  14186. "LDR r9, [%[m], #116]\n\t"
  14187. "LDR r12, [%[a], #116]\n\t"
  14188. "MOV r6, #0x0\n\t"
  14189. "UMLAL r12, r6, r10, r9\n\t"
  14190. "ADDS r12, r12, r7\n\t"
  14191. "STR r12, [%[a], #116]\n\t"
  14192. "ADC r6, r6, #0x0\n\t"
  14193. /* a[i+30] += m[30] * mu */
  14194. "LDR r9, [%[m], #120]\n\t"
  14195. "LDR r12, [%[a], #120]\n\t"
  14196. "MOV r7, #0x0\n\t"
  14197. "UMLAL r12, r7, r10, r9\n\t"
  14198. "ADDS r12, r12, r6\n\t"
  14199. "STR r12, [%[a], #120]\n\t"
  14200. "ADC r7, r7, #0x0\n\t"
  14201. /* a[i+31] += m[31] * mu */
  14202. "LDR r9, [%[m], #124]\n\t"
  14203. "LDR r12, [%[a], #124]\n\t"
  14204. "MOV r6, #0x0\n\t"
  14205. "UMLAL r12, r6, r10, r9\n\t"
  14206. "ADDS r12, r12, r7\n\t"
  14207. "STR r12, [%[a], #124]\n\t"
  14208. "ADC r6, r6, #0x0\n\t"
  14209. /* a[i+32] += m[32] * mu */
  14210. "LDR r9, [%[m], #128]\n\t"
  14211. "LDR r12, [%[a], #128]\n\t"
  14212. "MOV r7, #0x0\n\t"
  14213. "UMLAL r12, r7, r10, r9\n\t"
  14214. "ADDS r12, r12, r6\n\t"
  14215. "STR r12, [%[a], #128]\n\t"
  14216. "ADC r7, r7, #0x0\n\t"
  14217. /* a[i+33] += m[33] * mu */
  14218. "LDR r9, [%[m], #132]\n\t"
  14219. "LDR r12, [%[a], #132]\n\t"
  14220. "MOV r6, #0x0\n\t"
  14221. "UMLAL r12, r6, r10, r9\n\t"
  14222. "ADDS r12, r12, r7\n\t"
  14223. "STR r12, [%[a], #132]\n\t"
  14224. "ADC r6, r6, #0x0\n\t"
  14225. /* a[i+34] += m[34] * mu */
  14226. "LDR r9, [%[m], #136]\n\t"
  14227. "LDR r12, [%[a], #136]\n\t"
  14228. "MOV r7, #0x0\n\t"
  14229. "UMLAL r12, r7, r10, r9\n\t"
  14230. "ADDS r12, r12, r6\n\t"
  14231. "STR r12, [%[a], #136]\n\t"
  14232. "ADC r7, r7, #0x0\n\t"
  14233. /* a[i+35] += m[35] * mu */
  14234. "LDR r9, [%[m], #140]\n\t"
  14235. "LDR r12, [%[a], #140]\n\t"
  14236. "MOV r6, #0x0\n\t"
  14237. "UMLAL r12, r6, r10, r9\n\t"
  14238. "ADDS r12, r12, r7\n\t"
  14239. "STR r12, [%[a], #140]\n\t"
  14240. "ADC r6, r6, #0x0\n\t"
  14241. /* a[i+36] += m[36] * mu */
  14242. "LDR r9, [%[m], #144]\n\t"
  14243. "LDR r12, [%[a], #144]\n\t"
  14244. "MOV r7, #0x0\n\t"
  14245. "UMLAL r12, r7, r10, r9\n\t"
  14246. "ADDS r12, r12, r6\n\t"
  14247. "STR r12, [%[a], #144]\n\t"
  14248. "ADC r7, r7, #0x0\n\t"
  14249. /* a[i+37] += m[37] * mu */
  14250. "LDR r9, [%[m], #148]\n\t"
  14251. "LDR r12, [%[a], #148]\n\t"
  14252. "MOV r6, #0x0\n\t"
  14253. "UMLAL r12, r6, r10, r9\n\t"
  14254. "ADDS r12, r12, r7\n\t"
  14255. "STR r12, [%[a], #148]\n\t"
  14256. "ADC r6, r6, #0x0\n\t"
  14257. /* a[i+38] += m[38] * mu */
  14258. "LDR r9, [%[m], #152]\n\t"
  14259. "LDR r12, [%[a], #152]\n\t"
  14260. "MOV r7, #0x0\n\t"
  14261. "UMLAL r12, r7, r10, r9\n\t"
  14262. "ADDS r12, r12, r6\n\t"
  14263. "STR r12, [%[a], #152]\n\t"
  14264. "ADC r7, r7, #0x0\n\t"
  14265. /* a[i+39] += m[39] * mu */
  14266. "LDR r9, [%[m], #156]\n\t"
  14267. "LDR r12, [%[a], #156]\n\t"
  14268. "MOV r6, #0x0\n\t"
  14269. "UMLAL r12, r6, r10, r9\n\t"
  14270. "ADDS r12, r12, r7\n\t"
  14271. "STR r12, [%[a], #156]\n\t"
  14272. "ADC r6, r6, #0x0\n\t"
  14273. /* a[i+40] += m[40] * mu */
  14274. "LDR r9, [%[m], #160]\n\t"
  14275. "LDR r12, [%[a], #160]\n\t"
  14276. "MOV r7, #0x0\n\t"
  14277. "UMLAL r12, r7, r10, r9\n\t"
  14278. "ADDS r12, r12, r6\n\t"
  14279. "STR r12, [%[a], #160]\n\t"
  14280. "ADC r7, r7, #0x0\n\t"
  14281. /* a[i+41] += m[41] * mu */
  14282. "LDR r9, [%[m], #164]\n\t"
  14283. "LDR r12, [%[a], #164]\n\t"
  14284. "MOV r6, #0x0\n\t"
  14285. "UMLAL r12, r6, r10, r9\n\t"
  14286. "ADDS r12, r12, r7\n\t"
  14287. "STR r12, [%[a], #164]\n\t"
  14288. "ADC r6, r6, #0x0\n\t"
  14289. /* a[i+42] += m[42] * mu */
  14290. "LDR r9, [%[m], #168]\n\t"
  14291. "LDR r12, [%[a], #168]\n\t"
  14292. "MOV r7, #0x0\n\t"
  14293. "UMLAL r12, r7, r10, r9\n\t"
  14294. "ADDS r12, r12, r6\n\t"
  14295. "STR r12, [%[a], #168]\n\t"
  14296. "ADC r7, r7, #0x0\n\t"
  14297. /* a[i+43] += m[43] * mu */
  14298. "LDR r9, [%[m], #172]\n\t"
  14299. "LDR r12, [%[a], #172]\n\t"
  14300. "MOV r6, #0x0\n\t"
  14301. "UMLAL r12, r6, r10, r9\n\t"
  14302. "ADDS r12, r12, r7\n\t"
  14303. "STR r12, [%[a], #172]\n\t"
  14304. "ADC r6, r6, #0x0\n\t"
  14305. /* a[i+44] += m[44] * mu */
  14306. "LDR r9, [%[m], #176]\n\t"
  14307. "LDR r12, [%[a], #176]\n\t"
  14308. "MOV r7, #0x0\n\t"
  14309. "UMLAL r12, r7, r10, r9\n\t"
  14310. "ADDS r12, r12, r6\n\t"
  14311. "STR r12, [%[a], #176]\n\t"
  14312. "ADC r7, r7, #0x0\n\t"
  14313. /* a[i+45] += m[45] * mu */
  14314. "LDR r9, [%[m], #180]\n\t"
  14315. "LDR r12, [%[a], #180]\n\t"
  14316. "MOV r6, #0x0\n\t"
  14317. "UMLAL r12, r6, r10, r9\n\t"
  14318. "ADDS r12, r12, r7\n\t"
  14319. "STR r12, [%[a], #180]\n\t"
  14320. "ADC r6, r6, #0x0\n\t"
  14321. /* a[i+46] += m[46] * mu */
  14322. "LDR r9, [%[m], #184]\n\t"
  14323. "LDR r12, [%[a], #184]\n\t"
  14324. "MOV r7, #0x0\n\t"
  14325. "UMLAL r12, r7, r10, r9\n\t"
  14326. "ADDS r12, r12, r6\n\t"
  14327. "STR r12, [%[a], #184]\n\t"
  14328. "ADC r7, r7, #0x0\n\t"
  14329. /* a[i+47] += m[47] * mu */
  14330. "LDR r9, [%[m], #188]\n\t"
  14331. "LDR r12, [%[a], #188]\n\t"
  14332. "UMULL r8, r9, r10, r9\n\t"
  14333. "ADDS r7, r7, r8\n\t"
  14334. "ADCS r6, r9, r3\n\t"
  14335. "MOV r3, #0x0\n\t"
  14336. "ADC r3, r3, r3\n\t"
  14337. "ADDS r12, r12, r7\n\t"
  14338. "STR r12, [%[a], #188]\n\t"
  14339. "LDR r12, [%[a], #192]\n\t"
  14340. "ADCS r12, r12, r6\n\t"
  14341. "STR r12, [%[a], #192]\n\t"
  14342. "ADC r3, r3, #0x0\n\t"
  14343. /* i += 1 */
  14344. "ADD r11, r11, #0x4\n\t"
  14345. "ADD %[a], %[a], #0x4\n\t"
  14346. "CMP r11, #0xc0\n\t"
  14347. #ifdef __GNUC__
  14348. "BLT L_sp_3072_mont_reduce_48_word\n\t"
  14349. #else
  14350. "BLT.W L_sp_3072_mont_reduce_48_word\n\t"
  14351. #endif
  14352. /* Loop Done */
  14353. "STR r4, [%[a]]\n\t"
  14354. "STR r5, [%[a], #4]\n\t"
  14355. "MOV %[mp], r3\n\t"
  14356. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  14357. :
  14358. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  14359. );
  14360. sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - mp);
  14361. }
  14362. #else
  14363. /* Reduce the number back to 3072 bits using Montgomery reduction.
  14364. *
  14365. * a A single precision number to reduce in place.
  14366. * m The single precision number representing the modulus.
  14367. * mp The digit representing the negative inverse of m mod 2^n.
  14368. */
  14369. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14370. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  14371. #else
  14372. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp)
  14373. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14374. {
  14375. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14376. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  14377. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  14378. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  14379. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14380. __asm__ __volatile__ (
  14381. "LDR r11, [%[m]]\n\t"
  14382. /* i = 0 */
  14383. "MOV r9, #0x0\n\t"
  14384. /* ca = 0 */
  14385. "MOV r3, #0x0\n\t"
  14386. "\n"
  14387. "L_sp_3072_mont_reduce_48_word:\n\t"
  14388. /* mu = a[i] * mp */
  14389. "LDR r10, [%[a]]\n\t"
  14390. "MUL r8, %[mp], r10\n\t"
  14391. /* j = 0 */
  14392. "MOV r12, #0x0\n\t"
  14393. "MOV r4, #0x0\n\t"
  14394. "\n"
  14395. "L_sp_3072_mont_reduce_48_mul:\n\t"
  14396. /* a[i+j+0] += m[j+0] * mu */
  14397. "LDR r7, [%[m], r12]\n\t"
  14398. "LDR r10, [%[a], r12]\n\t"
  14399. "MOV r5, #0x0\n\t"
  14400. "UMLAL r10, r5, r8, r7\n\t"
  14401. "ADDS r10, r10, r4\n\t"
  14402. "STR r10, [%[a], r12]\n\t"
  14403. "ADC r4, r5, #0x0\n\t"
  14404. /* j += 1 */
  14405. "ADD r12, r12, #0x4\n\t"
  14406. /* a[i+j+1] += m[j+1] * mu */
  14407. "LDR r7, [%[m], r12]\n\t"
  14408. "LDR r10, [%[a], r12]\n\t"
  14409. "MOV r5, #0x0\n\t"
  14410. "UMLAL r10, r5, r8, r7\n\t"
  14411. "ADDS r10, r10, r4\n\t"
  14412. "STR r10, [%[a], r12]\n\t"
  14413. "ADC r4, r5, #0x0\n\t"
  14414. /* j += 1 */
  14415. "ADD r12, r12, #0x4\n\t"
  14416. /* a[i+j+2] += m[j+2] * mu */
  14417. "LDR r7, [%[m], r12]\n\t"
  14418. "LDR r10, [%[a], r12]\n\t"
  14419. "MOV r5, #0x0\n\t"
  14420. "UMLAL r10, r5, r8, r7\n\t"
  14421. "ADDS r10, r10, r4\n\t"
  14422. "STR r10, [%[a], r12]\n\t"
  14423. "ADC r4, r5, #0x0\n\t"
  14424. /* j += 1 */
  14425. "ADD r12, r12, #0x4\n\t"
  14426. /* a[i+j+3] += m[j+3] * mu */
  14427. "LDR r7, [%[m], r12]\n\t"
  14428. "LDR r10, [%[a], r12]\n\t"
  14429. "MOV r5, #0x0\n\t"
  14430. "UMLAL r10, r5, r8, r7\n\t"
  14431. "ADDS r10, r10, r4\n\t"
  14432. "STR r10, [%[a], r12]\n\t"
  14433. "ADC r4, r5, #0x0\n\t"
  14434. /* j += 1 */
  14435. "ADD r12, r12, #0x4\n\t"
  14436. "CMP r12, #0xc0\n\t"
  14437. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  14438. "BLT L_sp_3072_mont_reduce_48_mul\n\t"
  14439. #else
  14440. "BLT.N L_sp_3072_mont_reduce_48_mul\n\t"
  14441. #endif
  14442. "LDR r10, [%[a], #192]\n\t"
  14443. "ADDS r4, r4, r3\n\t"
  14444. "MOV r3, #0x0\n\t"
  14445. "ADC r3, r3, #0x0\n\t"
  14446. "ADDS r10, r10, r4\n\t"
  14447. "ADC r3, r3, r3\n\t"
  14448. "STR r10, [%[a], #192]\n\t"
  14449. /* i += 1 */
  14450. "ADD r9, r9, #0x4\n\t"
  14451. "ADD %[a], %[a], #0x4\n\t"
  14452. "CMP r9, #0xc0\n\t"
  14453. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  14454. "BLT L_sp_3072_mont_reduce_48_word\n\t"
  14455. #else
  14456. "BLT.N L_sp_3072_mont_reduce_48_word\n\t"
  14457. #endif
  14458. /* Loop Done */
  14459. "MOV %[mp], r3\n\t"
  14460. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  14461. :
  14462. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  14463. );
  14464. sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - mp);
  14465. }
  14466. #endif /* !WOLFSSL_SP_SMALL */
  14467. #else
  14468. #ifndef WOLFSSL_SP_SMALL
  14469. /* Reduce the number back to 3072 bits using Montgomery reduction.
  14470. *
  14471. * a A single precision number to reduce in place.
  14472. * m The single precision number representing the modulus.
  14473. * mp The digit representing the negative inverse of m mod 2^n.
  14474. */
  14475. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14476. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  14477. #else
  14478. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp)
  14479. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14480. {
  14481. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14482. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  14483. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  14484. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  14485. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14486. __asm__ __volatile__ (
  14487. /* i = 0 */
  14488. "MOV r4, #0x0\n\t"
  14489. "MOV r5, #0x0\n\t"
  14490. "LDR r6, [%[a]]\n\t"
  14491. "LDR r7, [%[a], #4]\n\t"
  14492. "LDR r8, [%[a], #8]\n\t"
  14493. "LDR r9, [%[a], #12]\n\t"
  14494. "LDR r10, [%[a], #16]\n\t"
  14495. "\n"
  14496. "L_sp_3072_mont_reduce_48_word:\n\t"
  14497. /* mu = a[i] * mp */
  14498. "MUL lr, %[mp], r6\n\t"
  14499. /* a[i+0] += m[0] * mu */
  14500. "LDR r12, [%[m]]\n\t"
  14501. "MOV r3, #0x0\n\t"
  14502. "UMAAL r6, r3, lr, r12\n\t"
  14503. /* a[i+1] += m[1] * mu */
  14504. "LDR r12, [%[m], #4]\n\t"
  14505. "MOV r6, r7\n\t"
  14506. "UMAAL r6, r3, lr, r12\n\t"
  14507. /* a[i+2] += m[2] * mu */
  14508. "LDR r12, [%[m], #8]\n\t"
  14509. "MOV r7, r8\n\t"
  14510. "UMAAL r7, r3, lr, r12\n\t"
  14511. /* a[i+3] += m[3] * mu */
  14512. "LDR r12, [%[m], #12]\n\t"
  14513. "MOV r8, r9\n\t"
  14514. "UMAAL r8, r3, lr, r12\n\t"
  14515. /* a[i+4] += m[4] * mu */
  14516. "LDR r12, [%[m], #16]\n\t"
  14517. "MOV r9, r10\n\t"
  14518. "UMAAL r9, r3, lr, r12\n\t"
  14519. /* a[i+5] += m[5] * mu */
  14520. "LDR r12, [%[m], #20]\n\t"
  14521. "LDR r10, [%[a], #20]\n\t"
  14522. "UMAAL r10, r3, lr, r12\n\t"
  14523. /* a[i+6] += m[6] * mu */
  14524. "LDR r12, [%[m], #24]\n\t"
  14525. "LDR r11, [%[a], #24]\n\t"
  14526. "UMAAL r11, r3, lr, r12\n\t"
  14527. "STR r11, [%[a], #24]\n\t"
  14528. /* a[i+7] += m[7] * mu */
  14529. "LDR r12, [%[m], #28]\n\t"
  14530. "LDR r11, [%[a], #28]\n\t"
  14531. "UMAAL r11, r3, lr, r12\n\t"
  14532. "STR r11, [%[a], #28]\n\t"
  14533. /* a[i+8] += m[8] * mu */
  14534. "LDR r12, [%[m], #32]\n\t"
  14535. "LDR r11, [%[a], #32]\n\t"
  14536. "UMAAL r11, r3, lr, r12\n\t"
  14537. "STR r11, [%[a], #32]\n\t"
  14538. /* a[i+9] += m[9] * mu */
  14539. "LDR r12, [%[m], #36]\n\t"
  14540. "LDR r11, [%[a], #36]\n\t"
  14541. "UMAAL r11, r3, lr, r12\n\t"
  14542. "STR r11, [%[a], #36]\n\t"
  14543. /* a[i+10] += m[10] * mu */
  14544. "LDR r12, [%[m], #40]\n\t"
  14545. "LDR r11, [%[a], #40]\n\t"
  14546. "UMAAL r11, r3, lr, r12\n\t"
  14547. "STR r11, [%[a], #40]\n\t"
  14548. /* a[i+11] += m[11] * mu */
  14549. "LDR r12, [%[m], #44]\n\t"
  14550. "LDR r11, [%[a], #44]\n\t"
  14551. "UMAAL r11, r3, lr, r12\n\t"
  14552. "STR r11, [%[a], #44]\n\t"
  14553. /* a[i+12] += m[12] * mu */
  14554. "LDR r12, [%[m], #48]\n\t"
  14555. "LDR r11, [%[a], #48]\n\t"
  14556. "UMAAL r11, r3, lr, r12\n\t"
  14557. "STR r11, [%[a], #48]\n\t"
  14558. /* a[i+13] += m[13] * mu */
  14559. "LDR r12, [%[m], #52]\n\t"
  14560. "LDR r11, [%[a], #52]\n\t"
  14561. "UMAAL r11, r3, lr, r12\n\t"
  14562. "STR r11, [%[a], #52]\n\t"
  14563. /* a[i+14] += m[14] * mu */
  14564. "LDR r12, [%[m], #56]\n\t"
  14565. "LDR r11, [%[a], #56]\n\t"
  14566. "UMAAL r11, r3, lr, r12\n\t"
  14567. "STR r11, [%[a], #56]\n\t"
  14568. /* a[i+15] += m[15] * mu */
  14569. "LDR r12, [%[m], #60]\n\t"
  14570. "LDR r11, [%[a], #60]\n\t"
  14571. "UMAAL r11, r3, lr, r12\n\t"
  14572. "STR r11, [%[a], #60]\n\t"
  14573. /* a[i+16] += m[16] * mu */
  14574. "LDR r12, [%[m], #64]\n\t"
  14575. "LDR r11, [%[a], #64]\n\t"
  14576. "UMAAL r11, r3, lr, r12\n\t"
  14577. "STR r11, [%[a], #64]\n\t"
  14578. /* a[i+17] += m[17] * mu */
  14579. "LDR r12, [%[m], #68]\n\t"
  14580. "LDR r11, [%[a], #68]\n\t"
  14581. "UMAAL r11, r3, lr, r12\n\t"
  14582. "STR r11, [%[a], #68]\n\t"
  14583. /* a[i+18] += m[18] * mu */
  14584. "LDR r12, [%[m], #72]\n\t"
  14585. "LDR r11, [%[a], #72]\n\t"
  14586. "UMAAL r11, r3, lr, r12\n\t"
  14587. "STR r11, [%[a], #72]\n\t"
  14588. /* a[i+19] += m[19] * mu */
  14589. "LDR r12, [%[m], #76]\n\t"
  14590. "LDR r11, [%[a], #76]\n\t"
  14591. "UMAAL r11, r3, lr, r12\n\t"
  14592. "STR r11, [%[a], #76]\n\t"
  14593. /* a[i+20] += m[20] * mu */
  14594. "LDR r12, [%[m], #80]\n\t"
  14595. "LDR r11, [%[a], #80]\n\t"
  14596. "UMAAL r11, r3, lr, r12\n\t"
  14597. "STR r11, [%[a], #80]\n\t"
  14598. /* a[i+21] += m[21] * mu */
  14599. "LDR r12, [%[m], #84]\n\t"
  14600. "LDR r11, [%[a], #84]\n\t"
  14601. "UMAAL r11, r3, lr, r12\n\t"
  14602. "STR r11, [%[a], #84]\n\t"
  14603. /* a[i+22] += m[22] * mu */
  14604. "LDR r12, [%[m], #88]\n\t"
  14605. "LDR r11, [%[a], #88]\n\t"
  14606. "UMAAL r11, r3, lr, r12\n\t"
  14607. "STR r11, [%[a], #88]\n\t"
  14608. /* a[i+23] += m[23] * mu */
  14609. "LDR r12, [%[m], #92]\n\t"
  14610. "LDR r11, [%[a], #92]\n\t"
  14611. "UMAAL r11, r3, lr, r12\n\t"
  14612. "STR r11, [%[a], #92]\n\t"
  14613. /* a[i+24] += m[24] * mu */
  14614. "LDR r12, [%[m], #96]\n\t"
  14615. "LDR r11, [%[a], #96]\n\t"
  14616. "UMAAL r11, r3, lr, r12\n\t"
  14617. "STR r11, [%[a], #96]\n\t"
  14618. /* a[i+25] += m[25] * mu */
  14619. "LDR r12, [%[m], #100]\n\t"
  14620. "LDR r11, [%[a], #100]\n\t"
  14621. "UMAAL r11, r3, lr, r12\n\t"
  14622. "STR r11, [%[a], #100]\n\t"
  14623. /* a[i+26] += m[26] * mu */
  14624. "LDR r12, [%[m], #104]\n\t"
  14625. "LDR r11, [%[a], #104]\n\t"
  14626. "UMAAL r11, r3, lr, r12\n\t"
  14627. "STR r11, [%[a], #104]\n\t"
  14628. /* a[i+27] += m[27] * mu */
  14629. "LDR r12, [%[m], #108]\n\t"
  14630. "LDR r11, [%[a], #108]\n\t"
  14631. "UMAAL r11, r3, lr, r12\n\t"
  14632. "STR r11, [%[a], #108]\n\t"
  14633. /* a[i+28] += m[28] * mu */
  14634. "LDR r12, [%[m], #112]\n\t"
  14635. "LDR r11, [%[a], #112]\n\t"
  14636. "UMAAL r11, r3, lr, r12\n\t"
  14637. "STR r11, [%[a], #112]\n\t"
  14638. /* a[i+29] += m[29] * mu */
  14639. "LDR r12, [%[m], #116]\n\t"
  14640. "LDR r11, [%[a], #116]\n\t"
  14641. "UMAAL r11, r3, lr, r12\n\t"
  14642. "STR r11, [%[a], #116]\n\t"
  14643. /* a[i+30] += m[30] * mu */
  14644. "LDR r12, [%[m], #120]\n\t"
  14645. "LDR r11, [%[a], #120]\n\t"
  14646. "UMAAL r11, r3, lr, r12\n\t"
  14647. "STR r11, [%[a], #120]\n\t"
  14648. /* a[i+31] += m[31] * mu */
  14649. "LDR r12, [%[m], #124]\n\t"
  14650. "LDR r11, [%[a], #124]\n\t"
  14651. "UMAAL r11, r3, lr, r12\n\t"
  14652. "STR r11, [%[a], #124]\n\t"
  14653. /* a[i+32] += m[32] * mu */
  14654. "LDR r12, [%[m], #128]\n\t"
  14655. "LDR r11, [%[a], #128]\n\t"
  14656. "UMAAL r11, r3, lr, r12\n\t"
  14657. "STR r11, [%[a], #128]\n\t"
  14658. /* a[i+33] += m[33] * mu */
  14659. "LDR r12, [%[m], #132]\n\t"
  14660. "LDR r11, [%[a], #132]\n\t"
  14661. "UMAAL r11, r3, lr, r12\n\t"
  14662. "STR r11, [%[a], #132]\n\t"
  14663. /* a[i+34] += m[34] * mu */
  14664. "LDR r12, [%[m], #136]\n\t"
  14665. "LDR r11, [%[a], #136]\n\t"
  14666. "UMAAL r11, r3, lr, r12\n\t"
  14667. "STR r11, [%[a], #136]\n\t"
  14668. /* a[i+35] += m[35] * mu */
  14669. "LDR r12, [%[m], #140]\n\t"
  14670. "LDR r11, [%[a], #140]\n\t"
  14671. "UMAAL r11, r3, lr, r12\n\t"
  14672. "STR r11, [%[a], #140]\n\t"
  14673. /* a[i+36] += m[36] * mu */
  14674. "LDR r12, [%[m], #144]\n\t"
  14675. "LDR r11, [%[a], #144]\n\t"
  14676. "UMAAL r11, r3, lr, r12\n\t"
  14677. "STR r11, [%[a], #144]\n\t"
  14678. /* a[i+37] += m[37] * mu */
  14679. "LDR r12, [%[m], #148]\n\t"
  14680. "LDR r11, [%[a], #148]\n\t"
  14681. "UMAAL r11, r3, lr, r12\n\t"
  14682. "STR r11, [%[a], #148]\n\t"
  14683. /* a[i+38] += m[38] * mu */
  14684. "LDR r12, [%[m], #152]\n\t"
  14685. "LDR r11, [%[a], #152]\n\t"
  14686. "UMAAL r11, r3, lr, r12\n\t"
  14687. "STR r11, [%[a], #152]\n\t"
  14688. /* a[i+39] += m[39] * mu */
  14689. "LDR r12, [%[m], #156]\n\t"
  14690. "LDR r11, [%[a], #156]\n\t"
  14691. "UMAAL r11, r3, lr, r12\n\t"
  14692. "STR r11, [%[a], #156]\n\t"
  14693. /* a[i+40] += m[40] * mu */
  14694. "LDR r12, [%[m], #160]\n\t"
  14695. "LDR r11, [%[a], #160]\n\t"
  14696. "UMAAL r11, r3, lr, r12\n\t"
  14697. "STR r11, [%[a], #160]\n\t"
  14698. /* a[i+41] += m[41] * mu */
  14699. "LDR r12, [%[m], #164]\n\t"
  14700. "LDR r11, [%[a], #164]\n\t"
  14701. "UMAAL r11, r3, lr, r12\n\t"
  14702. "STR r11, [%[a], #164]\n\t"
  14703. /* a[i+42] += m[42] * mu */
  14704. "LDR r12, [%[m], #168]\n\t"
  14705. "LDR r11, [%[a], #168]\n\t"
  14706. "UMAAL r11, r3, lr, r12\n\t"
  14707. "STR r11, [%[a], #168]\n\t"
  14708. /* a[i+43] += m[43] * mu */
  14709. "LDR r12, [%[m], #172]\n\t"
  14710. "LDR r11, [%[a], #172]\n\t"
  14711. "UMAAL r11, r3, lr, r12\n\t"
  14712. "STR r11, [%[a], #172]\n\t"
  14713. /* a[i+44] += m[44] * mu */
  14714. "LDR r12, [%[m], #176]\n\t"
  14715. "LDR r11, [%[a], #176]\n\t"
  14716. "UMAAL r11, r3, lr, r12\n\t"
  14717. "STR r11, [%[a], #176]\n\t"
  14718. /* a[i+45] += m[45] * mu */
  14719. "LDR r12, [%[m], #180]\n\t"
  14720. "LDR r11, [%[a], #180]\n\t"
  14721. "UMAAL r11, r3, lr, r12\n\t"
  14722. "STR r11, [%[a], #180]\n\t"
  14723. /* a[i+46] += m[46] * mu */
  14724. "LDR r12, [%[m], #184]\n\t"
  14725. "LDR r11, [%[a], #184]\n\t"
  14726. "UMAAL r11, r3, lr, r12\n\t"
  14727. "STR r11, [%[a], #184]\n\t"
  14728. /* a[i+47] += m[47] * mu */
  14729. "LDR r12, [%[m], #188]\n\t"
  14730. "LDR r11, [%[a], #188]\n\t"
  14731. "UMAAL r11, r3, lr, r12\n\t"
  14732. "LDR lr, [%[a], #192]\n\t"
  14733. "MOV r12, #0x0\n\t"
  14734. "UMAAL r3, lr, r12, r12\n\t"
  14735. "STR r11, [%[a], #188]\n\t"
  14736. "ADDS r3, r3, r5\n\t"
  14737. "ADC r5, lr, #0x0\n\t"
  14738. "STR r3, [%[a], #192]\n\t"
  14739. /* i += 1 */
  14740. "ADD r4, r4, #0x4\n\t"
  14741. "ADD %[a], %[a], #0x4\n\t"
  14742. "CMP r4, #0xc0\n\t"
  14743. #ifdef __GNUC__
  14744. "BLT L_sp_3072_mont_reduce_48_word\n\t"
  14745. #else
  14746. "BLT.W L_sp_3072_mont_reduce_48_word\n\t"
  14747. #endif
  14748. /* Loop Done */
  14749. "STR r6, [%[a]]\n\t"
  14750. "STR r7, [%[a], #4]\n\t"
  14751. "STR r8, [%[a], #8]\n\t"
  14752. "STR r9, [%[a], #12]\n\t"
  14753. "STR r10, [%[a], #16]\n\t"
  14754. "MOV %[mp], r5\n\t"
  14755. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  14756. :
  14757. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  14758. );
  14759. sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - mp);
  14760. }
  14761. #else
  14762. /* Reduce the number back to 3072 bits using Montgomery reduction.
  14763. *
  14764. * a A single precision number to reduce in place.
  14765. * m The single precision number representing the modulus.
  14766. * mp The digit representing the negative inverse of m mod 2^n.
  14767. */
  14768. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14769. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  14770. #else
  14771. SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp)
  14772. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14773. {
  14774. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14775. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  14776. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  14777. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  14778. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14779. __asm__ __volatile__ (
  14780. "LDR r11, [%[m]]\n\t"
  14781. /* i = 0 */
  14782. "MOV r9, #0x0\n\t"
  14783. /* ca = 0 */
  14784. "MOV r3, #0x0\n\t"
  14785. "\n"
  14786. "L_sp_3072_mont_reduce_48_word:\n\t"
  14787. /* mu = a[i] * mp */
  14788. "LDR r10, [%[a]]\n\t"
  14789. "MUL r8, %[mp], r10\n\t"
  14790. /* j = 0 */
  14791. "MOV r12, #0x0\n\t"
  14792. "MOV r4, #0x0\n\t"
  14793. "\n"
  14794. "L_sp_3072_mont_reduce_48_mul:\n\t"
  14795. /* a[i+j+0] += m[j+0] * mu */
  14796. "LDR r7, [%[m], r12]\n\t"
  14797. "LDR r10, [%[a], r12]\n\t"
  14798. "UMAAL r10, r4, r8, r7\n\t"
  14799. "STR r10, [%[a], r12]\n\t"
  14800. /* j += 1 */
  14801. "ADD r12, r12, #0x4\n\t"
  14802. /* a[i+j+1] += m[j+1] * mu */
  14803. "LDR r7, [%[m], r12]\n\t"
  14804. "LDR r10, [%[a], r12]\n\t"
  14805. "UMAAL r10, r4, r8, r7\n\t"
  14806. "STR r10, [%[a], r12]\n\t"
  14807. /* j += 1 */
  14808. "ADD r12, r12, #0x4\n\t"
  14809. /* a[i+j+2] += m[j+2] * mu */
  14810. "LDR r7, [%[m], r12]\n\t"
  14811. "LDR r10, [%[a], r12]\n\t"
  14812. "UMAAL r10, r4, r8, r7\n\t"
  14813. "STR r10, [%[a], r12]\n\t"
  14814. /* j += 1 */
  14815. "ADD r12, r12, #0x4\n\t"
  14816. /* a[i+j+3] += m[j+3] * mu */
  14817. "LDR r7, [%[m], r12]\n\t"
  14818. "LDR r10, [%[a], r12]\n\t"
  14819. "UMAAL r10, r4, r8, r7\n\t"
  14820. "STR r10, [%[a], r12]\n\t"
  14821. /* j += 1 */
  14822. "ADD r12, r12, #0x4\n\t"
  14823. "CMP r12, #0xc0\n\t"
  14824. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  14825. "BLT L_sp_3072_mont_reduce_48_mul\n\t"
  14826. #else
  14827. "BLT.N L_sp_3072_mont_reduce_48_mul\n\t"
  14828. #endif
  14829. "LDR r10, [%[a], #192]\n\t"
  14830. "ADDS r4, r4, r3\n\t"
  14831. "MOV r3, #0x0\n\t"
  14832. "ADC r3, r3, #0x0\n\t"
  14833. "ADDS r10, r10, r4\n\t"
  14834. "ADC r3, r3, r3\n\t"
  14835. "STR r10, [%[a], #192]\n\t"
  14836. /* i += 1 */
  14837. "ADD r9, r9, #0x4\n\t"
  14838. "ADD %[a], %[a], #0x4\n\t"
  14839. "CMP r9, #0xc0\n\t"
  14840. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  14841. "BLT L_sp_3072_mont_reduce_48_word\n\t"
  14842. #else
  14843. "BLT.N L_sp_3072_mont_reduce_48_word\n\t"
  14844. #endif
  14845. /* Loop Done */
  14846. "MOV %[mp], r3\n\t"
  14847. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  14848. :
  14849. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  14850. );
  14851. sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - mp);
  14852. }
  14853. #endif /* !WOLFSSL_SP_SMALL */
  14854. #endif
  14855. /* Multiply two Montgomery form numbers mod the modulus (prime).
  14856. * (r = a * b mod m)
  14857. *
  14858. * r Result of multiplication.
  14859. * a First number to multiply in Montgomery form.
  14860. * b Second number to multiply in Montgomery form.
  14861. * m Modulus (prime).
  14862. * mp Montgomery multiplier.
  14863. */
  14864. SP_NOINLINE static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a,
  14865. const sp_digit* b, const sp_digit* m, sp_digit mp)
  14866. {
  14867. sp_3072_mul_48(r, a, b);
  14868. sp_3072_mont_reduce_48(r, m, mp);
  14869. }
  14870. /* Square the Montgomery form number. (r = a * a mod m)
  14871. *
  14872. * r Result of squaring.
  14873. * a Number to square in Montgomery form.
  14874. * m Modulus (prime).
  14875. * mp Montgomery multiplier.
  14876. */
  14877. SP_NOINLINE static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a,
  14878. const sp_digit* m, sp_digit mp)
  14879. {
  14880. sp_3072_sqr_48(r, a);
  14881. sp_3072_mont_reduce_48(r, m, mp);
  14882. }
  14883. #ifdef WOLFSSL_SP_SMALL
  14884. /* Mul a by digit b into r. (r = a * b)
  14885. *
  14886. * r A single precision integer.
  14887. * a A single precision integer.
  14888. * b A single precision digit.
  14889. */
  14890. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14891. static void sp_3072_mul_d_48(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  14892. #else
  14893. static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, sp_digit b)
  14894. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14895. {
  14896. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14897. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  14898. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  14899. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  14900. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14901. __asm__ __volatile__ (
  14902. /* A[0] * B */
  14903. "LDR r8, [%[a]]\n\t"
  14904. "UMULL r5, r3, %[b], r8\n\t"
  14905. "MOV r4, #0x0\n\t"
  14906. "STR r5, [%[r]]\n\t"
  14907. "MOV r5, #0x0\n\t"
  14908. "MOV r9, #0x4\n\t"
  14909. "\n"
  14910. "L_sp_3072_mul_d_48_word:\n\t"
  14911. /* A[i] * B */
  14912. "LDR r8, [%[a], r9]\n\t"
  14913. "UMULL r6, r7, %[b], r8\n\t"
  14914. "ADDS r3, r3, r6\n\t"
  14915. "ADCS r4, r4, r7\n\t"
  14916. "ADC r5, r5, #0x0\n\t"
  14917. "STR r3, [%[r], r9]\n\t"
  14918. "MOV r3, r4\n\t"
  14919. "MOV r4, r5\n\t"
  14920. "MOV r5, #0x0\n\t"
  14921. "ADD r9, r9, #0x4\n\t"
  14922. "CMP r9, #0xc0\n\t"
  14923. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  14924. "BLT L_sp_3072_mul_d_48_word\n\t"
  14925. #else
  14926. "BLT.N L_sp_3072_mul_d_48_word\n\t"
  14927. #endif
  14928. "STR r3, [%[r], #192]\n\t"
  14929. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  14930. :
  14931. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  14932. );
  14933. }
  14934. #else
  14935. /* Mul a by digit b into r. (r = a * b)
  14936. *
  14937. * r A single precision integer.
  14938. * a A single precision integer.
  14939. * b A single precision digit.
  14940. */
  14941. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14942. static void sp_3072_mul_d_48(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  14943. #else
  14944. static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, sp_digit b)
  14945. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14946. {
  14947. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  14948. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  14949. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  14950. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  14951. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  14952. __asm__ __volatile__ (
  14953. /* A[0] * B */
  14954. "LDM %[a]!, {r8}\n\t"
  14955. "UMULL r3, r4, %[b], r8\n\t"
  14956. "STM %[r]!, {r3}\n\t"
  14957. "MOV r5, #0x0\n\t"
  14958. /* A[1] * B */
  14959. "LDM %[a]!, {r8}\n\t"
  14960. "UMLAL r4, r5, %[b], r8\n\t"
  14961. "STM %[r]!, {r4}\n\t"
  14962. "MOV r3, #0x0\n\t"
  14963. /* A[2] * B */
  14964. "LDM %[a]!, {r8}\n\t"
  14965. "UMLAL r5, r3, %[b], r8\n\t"
  14966. "STM %[r]!, {r5}\n\t"
  14967. "MOV r4, #0x0\n\t"
  14968. /* A[3] * B */
  14969. "LDM %[a]!, {r8}\n\t"
  14970. "UMLAL r3, r4, %[b], r8\n\t"
  14971. "STM %[r]!, {r3}\n\t"
  14972. "MOV r5, #0x0\n\t"
  14973. /* A[4] * B */
  14974. "LDM %[a]!, {r8}\n\t"
  14975. "UMLAL r4, r5, %[b], r8\n\t"
  14976. "STM %[r]!, {r4}\n\t"
  14977. "MOV r3, #0x0\n\t"
  14978. /* A[5] * B */
  14979. "LDM %[a]!, {r8}\n\t"
  14980. "UMLAL r5, r3, %[b], r8\n\t"
  14981. "STM %[r]!, {r5}\n\t"
  14982. "MOV r4, #0x0\n\t"
  14983. /* A[6] * B */
  14984. "LDM %[a]!, {r8}\n\t"
  14985. "UMLAL r3, r4, %[b], r8\n\t"
  14986. "STM %[r]!, {r3}\n\t"
  14987. "MOV r5, #0x0\n\t"
  14988. /* A[7] * B */
  14989. "LDM %[a]!, {r8}\n\t"
  14990. "UMLAL r4, r5, %[b], r8\n\t"
  14991. "STM %[r]!, {r4}\n\t"
  14992. "MOV r3, #0x0\n\t"
  14993. /* A[8] * B */
  14994. "LDM %[a]!, {r8}\n\t"
  14995. "UMLAL r5, r3, %[b], r8\n\t"
  14996. "STM %[r]!, {r5}\n\t"
  14997. "MOV r4, #0x0\n\t"
  14998. /* A[9] * B */
  14999. "LDM %[a]!, {r8}\n\t"
  15000. "UMLAL r3, r4, %[b], r8\n\t"
  15001. "STM %[r]!, {r3}\n\t"
  15002. "MOV r5, #0x0\n\t"
  15003. /* A[10] * B */
  15004. "LDM %[a]!, {r8}\n\t"
  15005. "UMLAL r4, r5, %[b], r8\n\t"
  15006. "STM %[r]!, {r4}\n\t"
  15007. "MOV r3, #0x0\n\t"
  15008. /* A[11] * B */
  15009. "LDM %[a]!, {r8}\n\t"
  15010. "UMLAL r5, r3, %[b], r8\n\t"
  15011. "STM %[r]!, {r5}\n\t"
  15012. "MOV r4, #0x0\n\t"
  15013. /* A[12] * B */
  15014. "LDM %[a]!, {r8}\n\t"
  15015. "UMLAL r3, r4, %[b], r8\n\t"
  15016. "STM %[r]!, {r3}\n\t"
  15017. "MOV r5, #0x0\n\t"
  15018. /* A[13] * B */
  15019. "LDM %[a]!, {r8}\n\t"
  15020. "UMLAL r4, r5, %[b], r8\n\t"
  15021. "STM %[r]!, {r4}\n\t"
  15022. "MOV r3, #0x0\n\t"
  15023. /* A[14] * B */
  15024. "LDM %[a]!, {r8}\n\t"
  15025. "UMLAL r5, r3, %[b], r8\n\t"
  15026. "STM %[r]!, {r5}\n\t"
  15027. "MOV r4, #0x0\n\t"
  15028. /* A[15] * B */
  15029. "LDM %[a]!, {r8}\n\t"
  15030. "UMLAL r3, r4, %[b], r8\n\t"
  15031. "STM %[r]!, {r3}\n\t"
  15032. "MOV r5, #0x0\n\t"
  15033. /* A[16] * B */
  15034. "LDM %[a]!, {r8}\n\t"
  15035. "UMLAL r4, r5, %[b], r8\n\t"
  15036. "STM %[r]!, {r4}\n\t"
  15037. "MOV r3, #0x0\n\t"
  15038. /* A[17] * B */
  15039. "LDM %[a]!, {r8}\n\t"
  15040. "UMLAL r5, r3, %[b], r8\n\t"
  15041. "STM %[r]!, {r5}\n\t"
  15042. "MOV r4, #0x0\n\t"
  15043. /* A[18] * B */
  15044. "LDM %[a]!, {r8}\n\t"
  15045. "UMLAL r3, r4, %[b], r8\n\t"
  15046. "STM %[r]!, {r3}\n\t"
  15047. "MOV r5, #0x0\n\t"
  15048. /* A[19] * B */
  15049. "LDM %[a]!, {r8}\n\t"
  15050. "UMLAL r4, r5, %[b], r8\n\t"
  15051. "STM %[r]!, {r4}\n\t"
  15052. "MOV r3, #0x0\n\t"
  15053. /* A[20] * B */
  15054. "LDM %[a]!, {r8}\n\t"
  15055. "UMLAL r5, r3, %[b], r8\n\t"
  15056. "STM %[r]!, {r5}\n\t"
  15057. "MOV r4, #0x0\n\t"
  15058. /* A[21] * B */
  15059. "LDM %[a]!, {r8}\n\t"
  15060. "UMLAL r3, r4, %[b], r8\n\t"
  15061. "STM %[r]!, {r3}\n\t"
  15062. "MOV r5, #0x0\n\t"
  15063. /* A[22] * B */
  15064. "LDM %[a]!, {r8}\n\t"
  15065. "UMLAL r4, r5, %[b], r8\n\t"
  15066. "STM %[r]!, {r4}\n\t"
  15067. "MOV r3, #0x0\n\t"
  15068. /* A[23] * B */
  15069. "LDM %[a]!, {r8}\n\t"
  15070. "UMLAL r5, r3, %[b], r8\n\t"
  15071. "STM %[r]!, {r5}\n\t"
  15072. "MOV r4, #0x0\n\t"
  15073. /* A[24] * B */
  15074. "LDM %[a]!, {r8}\n\t"
  15075. "UMLAL r3, r4, %[b], r8\n\t"
  15076. "STM %[r]!, {r3}\n\t"
  15077. "MOV r5, #0x0\n\t"
  15078. /* A[25] * B */
  15079. "LDM %[a]!, {r8}\n\t"
  15080. "UMLAL r4, r5, %[b], r8\n\t"
  15081. "STM %[r]!, {r4}\n\t"
  15082. "MOV r3, #0x0\n\t"
  15083. /* A[26] * B */
  15084. "LDM %[a]!, {r8}\n\t"
  15085. "UMLAL r5, r3, %[b], r8\n\t"
  15086. "STM %[r]!, {r5}\n\t"
  15087. "MOV r4, #0x0\n\t"
  15088. /* A[27] * B */
  15089. "LDM %[a]!, {r8}\n\t"
  15090. "UMLAL r3, r4, %[b], r8\n\t"
  15091. "STM %[r]!, {r3}\n\t"
  15092. "MOV r5, #0x0\n\t"
  15093. /* A[28] * B */
  15094. "LDM %[a]!, {r8}\n\t"
  15095. "UMLAL r4, r5, %[b], r8\n\t"
  15096. "STM %[r]!, {r4}\n\t"
  15097. "MOV r3, #0x0\n\t"
  15098. /* A[29] * B */
  15099. "LDM %[a]!, {r8}\n\t"
  15100. "UMLAL r5, r3, %[b], r8\n\t"
  15101. "STM %[r]!, {r5}\n\t"
  15102. "MOV r4, #0x0\n\t"
  15103. /* A[30] * B */
  15104. "LDM %[a]!, {r8}\n\t"
  15105. "UMLAL r3, r4, %[b], r8\n\t"
  15106. "STM %[r]!, {r3}\n\t"
  15107. "MOV r5, #0x0\n\t"
  15108. /* A[31] * B */
  15109. "LDM %[a]!, {r8}\n\t"
  15110. "UMLAL r4, r5, %[b], r8\n\t"
  15111. "STM %[r]!, {r4}\n\t"
  15112. "MOV r3, #0x0\n\t"
  15113. /* A[32] * B */
  15114. "LDM %[a]!, {r8}\n\t"
  15115. "UMLAL r5, r3, %[b], r8\n\t"
  15116. "STM %[r]!, {r5}\n\t"
  15117. "MOV r4, #0x0\n\t"
  15118. /* A[33] * B */
  15119. "LDM %[a]!, {r8}\n\t"
  15120. "UMLAL r3, r4, %[b], r8\n\t"
  15121. "STM %[r]!, {r3}\n\t"
  15122. "MOV r5, #0x0\n\t"
  15123. /* A[34] * B */
  15124. "LDM %[a]!, {r8}\n\t"
  15125. "UMLAL r4, r5, %[b], r8\n\t"
  15126. "STM %[r]!, {r4}\n\t"
  15127. "MOV r3, #0x0\n\t"
  15128. /* A[35] * B */
  15129. "LDM %[a]!, {r8}\n\t"
  15130. "UMLAL r5, r3, %[b], r8\n\t"
  15131. "STM %[r]!, {r5}\n\t"
  15132. "MOV r4, #0x0\n\t"
  15133. /* A[36] * B */
  15134. "LDM %[a]!, {r8}\n\t"
  15135. "UMLAL r3, r4, %[b], r8\n\t"
  15136. "STM %[r]!, {r3}\n\t"
  15137. "MOV r5, #0x0\n\t"
  15138. /* A[37] * B */
  15139. "LDM %[a]!, {r8}\n\t"
  15140. "UMLAL r4, r5, %[b], r8\n\t"
  15141. "STM %[r]!, {r4}\n\t"
  15142. "MOV r3, #0x0\n\t"
  15143. /* A[38] * B */
  15144. "LDM %[a]!, {r8}\n\t"
  15145. "UMLAL r5, r3, %[b], r8\n\t"
  15146. "STM %[r]!, {r5}\n\t"
  15147. "MOV r4, #0x0\n\t"
  15148. /* A[39] * B */
  15149. "LDM %[a]!, {r8}\n\t"
  15150. "UMLAL r3, r4, %[b], r8\n\t"
  15151. "STM %[r]!, {r3}\n\t"
  15152. "MOV r5, #0x0\n\t"
  15153. /* A[40] * B */
  15154. "LDM %[a]!, {r8}\n\t"
  15155. "UMLAL r4, r5, %[b], r8\n\t"
  15156. "STM %[r]!, {r4}\n\t"
  15157. "MOV r3, #0x0\n\t"
  15158. /* A[41] * B */
  15159. "LDM %[a]!, {r8}\n\t"
  15160. "UMLAL r5, r3, %[b], r8\n\t"
  15161. "STM %[r]!, {r5}\n\t"
  15162. "MOV r4, #0x0\n\t"
  15163. /* A[42] * B */
  15164. "LDM %[a]!, {r8}\n\t"
  15165. "UMLAL r3, r4, %[b], r8\n\t"
  15166. "STM %[r]!, {r3}\n\t"
  15167. "MOV r5, #0x0\n\t"
  15168. /* A[43] * B */
  15169. "LDM %[a]!, {r8}\n\t"
  15170. "UMLAL r4, r5, %[b], r8\n\t"
  15171. "STM %[r]!, {r4}\n\t"
  15172. "MOV r3, #0x0\n\t"
  15173. /* A[44] * B */
  15174. "LDM %[a]!, {r8}\n\t"
  15175. "UMLAL r5, r3, %[b], r8\n\t"
  15176. "STM %[r]!, {r5}\n\t"
  15177. "MOV r4, #0x0\n\t"
  15178. /* A[45] * B */
  15179. "LDM %[a]!, {r8}\n\t"
  15180. "UMLAL r3, r4, %[b], r8\n\t"
  15181. "STM %[r]!, {r3}\n\t"
  15182. "MOV r5, #0x0\n\t"
  15183. /* A[46] * B */
  15184. "LDM %[a]!, {r8}\n\t"
  15185. "UMLAL r4, r5, %[b], r8\n\t"
  15186. "STM %[r]!, {r4}\n\t"
  15187. "MOV r3, #0x0\n\t"
  15188. /* A[47] * B */
  15189. "LDM %[a]!, {r8}\n\t"
  15190. "UMLAL r5, r3, %[b], r8\n\t"
  15191. "STM %[r]!, {r5}\n\t"
  15192. "STR r3, [%[r]]\n\t"
  15193. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  15194. :
  15195. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  15196. );
  15197. }
  15198. #endif /* WOLFSSL_SP_SMALL */
  15199. #ifdef WOLFSSL_SP_USE_UDIV
  15200. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  15201. *
  15202. * d1 The high order half of the number to divide.
  15203. * d0 The low order half of the number to divide.
  15204. * div The divisor.
  15205. * returns the result of the division.
  15206. *
  15207. * Note that this is an approximate div. It may give an answer 1 larger.
  15208. */
  15209. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  15210. SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  15211. #else
  15212. SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div)
  15213. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  15214. {
  15215. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  15216. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  15217. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  15218. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  15219. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  15220. __asm__ __volatile__ (
  15221. "LSR r8, %[div], #16\n\t"
  15222. "ADD r5, r8, #0x1\n\t"
  15223. "UDIV r6, %[d1], r5\n\t"
  15224. "LSL r7, %[div], #16\n\t"
  15225. "LSL r6, r6, #16\n\t"
  15226. "UMULL r3, r4, %[div], r6\n\t"
  15227. "SUBS %[d0], %[d0], r3\n\t"
  15228. "SBC %[d1], %[d1], r4\n\t"
  15229. "SUBS r3, %[d1], r5\n\t"
  15230. "SBC r9, r9, r9\n\t"
  15231. "ADD r9, r9, #0x1\n\t"
  15232. "RSB r10, r9, #0x0\n\t"
  15233. "LSL r9, r9, #16\n\t"
  15234. "AND r7, r7, r10\n\t"
  15235. "AND r8, r8, r10\n\t"
  15236. "SUBS %[d0], %[d0], r7\n\t"
  15237. "ADD r6, r6, r9\n\t"
  15238. "SBC %[d1], %[d1], r8\n\t"
  15239. "LSL r4, %[d1], #16\n\t"
  15240. "LSR r3, %[d0], #16\n\t"
  15241. "ORR r3, r3, r4\n\t"
  15242. "UDIV r3, r3, r5\n\t"
  15243. "ADD r6, r6, r3\n\t"
  15244. "UMULL r3, r4, %[div], r3\n\t"
  15245. "SUBS %[d0], %[d0], r3\n\t"
  15246. "SBC %[d1], %[d1], r4\n\t"
  15247. "LSL r4, %[d1], #16\n\t"
  15248. "LSR r3, %[d0], #16\n\t"
  15249. "ORR r3, r3, r4\n\t"
  15250. "UDIV r3, r3, r5\n\t"
  15251. "ADD r6, r6, r3\n\t"
  15252. "MUL r3, %[div], r3\n\t"
  15253. "SUB %[d0], %[d0], r3\n\t"
  15254. "UDIV r3, %[d0], %[div]\n\t"
  15255. "ADD %[d1], r6, r3\n\t"
  15256. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  15257. :
  15258. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  15259. );
  15260. return (uint32_t)(size_t)d1;
  15261. }
  15262. #else
  15263. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  15264. *
  15265. * d1 The high order half of the number to divide.
  15266. * d0 The low order half of the number to divide.
  15267. * div The divisor.
  15268. * returns the result of the division.
  15269. *
  15270. * Note that this is an approximate div. It may give an answer 1 larger.
  15271. */
  15272. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  15273. SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  15274. #else
  15275. SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div)
  15276. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  15277. {
  15278. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  15279. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  15280. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  15281. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  15282. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  15283. __asm__ __volatile__ (
  15284. "LSR r5, %[div], #1\n\t"
  15285. "ADD r5, r5, #0x1\n\t"
  15286. "MOV r6, %[d0]\n\t"
  15287. "MOV r7, %[d1]\n\t"
  15288. /* Do top 32 */
  15289. "SUBS r8, r5, r7\n\t"
  15290. "SBC r8, r8, r8\n\t"
  15291. "MOV r3, #0x0\n\t"
  15292. "SUB r3, r3, r8\n\t"
  15293. "AND r8, r8, r5\n\t"
  15294. "SUBS r7, r7, r8\n\t"
  15295. /* Next 30 bits */
  15296. "MOV r4, #0x1d\n\t"
  15297. "\n"
  15298. "L_div_3072_word_48_bit:\n\t"
  15299. "LSLS r6, r6, #1\n\t"
  15300. "ADC r7, r7, r7\n\t"
  15301. "SUBS r8, r5, r7\n\t"
  15302. "SBC r8, r8, r8\n\t"
  15303. "ADD r3, r3, r3\n\t"
  15304. "SUB r3, r3, r8\n\t"
  15305. "AND r8, r8, r5\n\t"
  15306. "SUBS r7, r7, r8\n\t"
  15307. "SUBS r4, r4, #0x1\n\t"
  15308. "bpl L_div_3072_word_48_bit\n\t"
  15309. "ADD r3, r3, r3\n\t"
  15310. "ADD r3, r3, #0x1\n\t"
  15311. "UMULL r6, r7, r3, %[div]\n\t"
  15312. "SUBS r9, %[d0], r6\n\t"
  15313. "SBC r10, %[d1], r7\n\t"
  15314. "ADD r3, r3, r10\n\t"
  15315. "UMULL r6, r7, r3, %[div]\n\t"
  15316. "SUBS r9, %[d0], r6\n\t"
  15317. "SBC r10, %[d1], r7\n\t"
  15318. "ADD r3, r3, r10\n\t"
  15319. "UMULL r6, r7, r3, %[div]\n\t"
  15320. "SUBS r9, %[d0], r6\n\t"
  15321. "SBC r10, %[d1], r7\n\t"
  15322. "ADD r3, r3, r10\n\t"
  15323. "SUBS r8, %[div], r9\n\t"
  15324. "SBC r8, r8, r8\n\t"
  15325. "SUB %[d1], r3, r8\n\t"
  15326. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  15327. :
  15328. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  15329. );
  15330. return (uint32_t)(size_t)d1;
  15331. }
  15332. #endif
  15333. /* Compare a with b in constant time.
  15334. *
  15335. * a A single precision integer.
  15336. * b A single precision integer.
  15337. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  15338. * respectively.
  15339. */
  15340. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  15341. static sp_int32 sp_3072_cmp_48(const sp_digit* a_p, const sp_digit* b_p)
  15342. #else
  15343. static sp_int32 sp_3072_cmp_48(const sp_digit* a, const sp_digit* b)
  15344. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  15345. {
  15346. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  15347. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  15348. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  15349. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  15350. __asm__ __volatile__ (
  15351. "MOV r2, #0xffffffff\n\t"
  15352. "MOV r8, #0x1\n\t"
  15353. "MOV r7, #0x0\n\t"
  15354. "MOV r3, #0xffffffff\n\t"
  15355. #ifdef WOLFSSL_SP_SMALL
  15356. "MOV r6, #0xbc\n\t"
  15357. "\n"
  15358. "L_sp_3072_cmp_48_words:\n\t"
  15359. "LDR r4, [%[a], r6]\n\t"
  15360. "LDR r5, [%[b], r6]\n\t"
  15361. "AND r4, r4, r3\n\t"
  15362. "AND r5, r5, r3\n\t"
  15363. "SUBS r4, r4, r5\n\t"
  15364. "IT hi\n\t"
  15365. "movhi r2, r8\n\t"
  15366. "IT lo\n\t"
  15367. "movlo r2, r3\n\t"
  15368. "IT ne\n\t"
  15369. "movne r3, r7\n\t"
  15370. "SUBS r6, r6, #0x4\n\t"
  15371. "bcs L_sp_3072_cmp_48_words\n\t"
  15372. "EOR r2, r2, r3\n\t"
  15373. #else
  15374. "LDR r4, [%[a], #188]\n\t"
  15375. "LDR r5, [%[b], #188]\n\t"
  15376. "AND r4, r4, r3\n\t"
  15377. "AND r5, r5, r3\n\t"
  15378. "SUBS r4, r4, r5\n\t"
  15379. "IT hi\n\t"
  15380. "movhi r2, r8\n\t"
  15381. "IT lo\n\t"
  15382. "movlo r2, r3\n\t"
  15383. "IT ne\n\t"
  15384. "movne r3, r7\n\t"
  15385. "LDR r4, [%[a], #184]\n\t"
  15386. "LDR r5, [%[b], #184]\n\t"
  15387. "AND r4, r4, r3\n\t"
  15388. "AND r5, r5, r3\n\t"
  15389. "SUBS r4, r4, r5\n\t"
  15390. "IT hi\n\t"
  15391. "movhi r2, r8\n\t"
  15392. "IT lo\n\t"
  15393. "movlo r2, r3\n\t"
  15394. "IT ne\n\t"
  15395. "movne r3, r7\n\t"
  15396. "LDR r4, [%[a], #180]\n\t"
  15397. "LDR r5, [%[b], #180]\n\t"
  15398. "AND r4, r4, r3\n\t"
  15399. "AND r5, r5, r3\n\t"
  15400. "SUBS r4, r4, r5\n\t"
  15401. "IT hi\n\t"
  15402. "movhi r2, r8\n\t"
  15403. "IT lo\n\t"
  15404. "movlo r2, r3\n\t"
  15405. "IT ne\n\t"
  15406. "movne r3, r7\n\t"
  15407. "LDR r4, [%[a], #176]\n\t"
  15408. "LDR r5, [%[b], #176]\n\t"
  15409. "AND r4, r4, r3\n\t"
  15410. "AND r5, r5, r3\n\t"
  15411. "SUBS r4, r4, r5\n\t"
  15412. "IT hi\n\t"
  15413. "movhi r2, r8\n\t"
  15414. "IT lo\n\t"
  15415. "movlo r2, r3\n\t"
  15416. "IT ne\n\t"
  15417. "movne r3, r7\n\t"
  15418. "LDR r4, [%[a], #172]\n\t"
  15419. "LDR r5, [%[b], #172]\n\t"
  15420. "AND r4, r4, r3\n\t"
  15421. "AND r5, r5, r3\n\t"
  15422. "SUBS r4, r4, r5\n\t"
  15423. "IT hi\n\t"
  15424. "movhi r2, r8\n\t"
  15425. "IT lo\n\t"
  15426. "movlo r2, r3\n\t"
  15427. "IT ne\n\t"
  15428. "movne r3, r7\n\t"
  15429. "LDR r4, [%[a], #168]\n\t"
  15430. "LDR r5, [%[b], #168]\n\t"
  15431. "AND r4, r4, r3\n\t"
  15432. "AND r5, r5, r3\n\t"
  15433. "SUBS r4, r4, r5\n\t"
  15434. "IT hi\n\t"
  15435. "movhi r2, r8\n\t"
  15436. "IT lo\n\t"
  15437. "movlo r2, r3\n\t"
  15438. "IT ne\n\t"
  15439. "movne r3, r7\n\t"
  15440. "LDR r4, [%[a], #164]\n\t"
  15441. "LDR r5, [%[b], #164]\n\t"
  15442. "AND r4, r4, r3\n\t"
  15443. "AND r5, r5, r3\n\t"
  15444. "SUBS r4, r4, r5\n\t"
  15445. "IT hi\n\t"
  15446. "movhi r2, r8\n\t"
  15447. "IT lo\n\t"
  15448. "movlo r2, r3\n\t"
  15449. "IT ne\n\t"
  15450. "movne r3, r7\n\t"
  15451. "LDR r4, [%[a], #160]\n\t"
  15452. "LDR r5, [%[b], #160]\n\t"
  15453. "AND r4, r4, r3\n\t"
  15454. "AND r5, r5, r3\n\t"
  15455. "SUBS r4, r4, r5\n\t"
  15456. "IT hi\n\t"
  15457. "movhi r2, r8\n\t"
  15458. "IT lo\n\t"
  15459. "movlo r2, r3\n\t"
  15460. "IT ne\n\t"
  15461. "movne r3, r7\n\t"
  15462. "LDR r4, [%[a], #156]\n\t"
  15463. "LDR r5, [%[b], #156]\n\t"
  15464. "AND r4, r4, r3\n\t"
  15465. "AND r5, r5, r3\n\t"
  15466. "SUBS r4, r4, r5\n\t"
  15467. "IT hi\n\t"
  15468. "movhi r2, r8\n\t"
  15469. "IT lo\n\t"
  15470. "movlo r2, r3\n\t"
  15471. "IT ne\n\t"
  15472. "movne r3, r7\n\t"
  15473. "LDR r4, [%[a], #152]\n\t"
  15474. "LDR r5, [%[b], #152]\n\t"
  15475. "AND r4, r4, r3\n\t"
  15476. "AND r5, r5, r3\n\t"
  15477. "SUBS r4, r4, r5\n\t"
  15478. "IT hi\n\t"
  15479. "movhi r2, r8\n\t"
  15480. "IT lo\n\t"
  15481. "movlo r2, r3\n\t"
  15482. "IT ne\n\t"
  15483. "movne r3, r7\n\t"
  15484. "LDR r4, [%[a], #148]\n\t"
  15485. "LDR r5, [%[b], #148]\n\t"
  15486. "AND r4, r4, r3\n\t"
  15487. "AND r5, r5, r3\n\t"
  15488. "SUBS r4, r4, r5\n\t"
  15489. "IT hi\n\t"
  15490. "movhi r2, r8\n\t"
  15491. "IT lo\n\t"
  15492. "movlo r2, r3\n\t"
  15493. "IT ne\n\t"
  15494. "movne r3, r7\n\t"
  15495. "LDR r4, [%[a], #144]\n\t"
  15496. "LDR r5, [%[b], #144]\n\t"
  15497. "AND r4, r4, r3\n\t"
  15498. "AND r5, r5, r3\n\t"
  15499. "SUBS r4, r4, r5\n\t"
  15500. "IT hi\n\t"
  15501. "movhi r2, r8\n\t"
  15502. "IT lo\n\t"
  15503. "movlo r2, r3\n\t"
  15504. "IT ne\n\t"
  15505. "movne r3, r7\n\t"
  15506. "LDR r4, [%[a], #140]\n\t"
  15507. "LDR r5, [%[b], #140]\n\t"
  15508. "AND r4, r4, r3\n\t"
  15509. "AND r5, r5, r3\n\t"
  15510. "SUBS r4, r4, r5\n\t"
  15511. "IT hi\n\t"
  15512. "movhi r2, r8\n\t"
  15513. "IT lo\n\t"
  15514. "movlo r2, r3\n\t"
  15515. "IT ne\n\t"
  15516. "movne r3, r7\n\t"
  15517. "LDR r4, [%[a], #136]\n\t"
  15518. "LDR r5, [%[b], #136]\n\t"
  15519. "AND r4, r4, r3\n\t"
  15520. "AND r5, r5, r3\n\t"
  15521. "SUBS r4, r4, r5\n\t"
  15522. "IT hi\n\t"
  15523. "movhi r2, r8\n\t"
  15524. "IT lo\n\t"
  15525. "movlo r2, r3\n\t"
  15526. "IT ne\n\t"
  15527. "movne r3, r7\n\t"
  15528. "LDR r4, [%[a], #132]\n\t"
  15529. "LDR r5, [%[b], #132]\n\t"
  15530. "AND r4, r4, r3\n\t"
  15531. "AND r5, r5, r3\n\t"
  15532. "SUBS r4, r4, r5\n\t"
  15533. "IT hi\n\t"
  15534. "movhi r2, r8\n\t"
  15535. "IT lo\n\t"
  15536. "movlo r2, r3\n\t"
  15537. "IT ne\n\t"
  15538. "movne r3, r7\n\t"
  15539. "LDR r4, [%[a], #128]\n\t"
  15540. "LDR r5, [%[b], #128]\n\t"
  15541. "AND r4, r4, r3\n\t"
  15542. "AND r5, r5, r3\n\t"
  15543. "SUBS r4, r4, r5\n\t"
  15544. "IT hi\n\t"
  15545. "movhi r2, r8\n\t"
  15546. "IT lo\n\t"
  15547. "movlo r2, r3\n\t"
  15548. "IT ne\n\t"
  15549. "movne r3, r7\n\t"
  15550. "LDR r4, [%[a], #124]\n\t"
  15551. "LDR r5, [%[b], #124]\n\t"
  15552. "AND r4, r4, r3\n\t"
  15553. "AND r5, r5, r3\n\t"
  15554. "SUBS r4, r4, r5\n\t"
  15555. "IT hi\n\t"
  15556. "movhi r2, r8\n\t"
  15557. "IT lo\n\t"
  15558. "movlo r2, r3\n\t"
  15559. "IT ne\n\t"
  15560. "movne r3, r7\n\t"
  15561. "LDR r4, [%[a], #120]\n\t"
  15562. "LDR r5, [%[b], #120]\n\t"
  15563. "AND r4, r4, r3\n\t"
  15564. "AND r5, r5, r3\n\t"
  15565. "SUBS r4, r4, r5\n\t"
  15566. "IT hi\n\t"
  15567. "movhi r2, r8\n\t"
  15568. "IT lo\n\t"
  15569. "movlo r2, r3\n\t"
  15570. "IT ne\n\t"
  15571. "movne r3, r7\n\t"
  15572. "LDR r4, [%[a], #116]\n\t"
  15573. "LDR r5, [%[b], #116]\n\t"
  15574. "AND r4, r4, r3\n\t"
  15575. "AND r5, r5, r3\n\t"
  15576. "SUBS r4, r4, r5\n\t"
  15577. "IT hi\n\t"
  15578. "movhi r2, r8\n\t"
  15579. "IT lo\n\t"
  15580. "movlo r2, r3\n\t"
  15581. "IT ne\n\t"
  15582. "movne r3, r7\n\t"
  15583. "LDR r4, [%[a], #112]\n\t"
  15584. "LDR r5, [%[b], #112]\n\t"
  15585. "AND r4, r4, r3\n\t"
  15586. "AND r5, r5, r3\n\t"
  15587. "SUBS r4, r4, r5\n\t"
  15588. "IT hi\n\t"
  15589. "movhi r2, r8\n\t"
  15590. "IT lo\n\t"
  15591. "movlo r2, r3\n\t"
  15592. "IT ne\n\t"
  15593. "movne r3, r7\n\t"
  15594. "LDR r4, [%[a], #108]\n\t"
  15595. "LDR r5, [%[b], #108]\n\t"
  15596. "AND r4, r4, r3\n\t"
  15597. "AND r5, r5, r3\n\t"
  15598. "SUBS r4, r4, r5\n\t"
  15599. "IT hi\n\t"
  15600. "movhi r2, r8\n\t"
  15601. "IT lo\n\t"
  15602. "movlo r2, r3\n\t"
  15603. "IT ne\n\t"
  15604. "movne r3, r7\n\t"
  15605. "LDR r4, [%[a], #104]\n\t"
  15606. "LDR r5, [%[b], #104]\n\t"
  15607. "AND r4, r4, r3\n\t"
  15608. "AND r5, r5, r3\n\t"
  15609. "SUBS r4, r4, r5\n\t"
  15610. "IT hi\n\t"
  15611. "movhi r2, r8\n\t"
  15612. "IT lo\n\t"
  15613. "movlo r2, r3\n\t"
  15614. "IT ne\n\t"
  15615. "movne r3, r7\n\t"
  15616. "LDR r4, [%[a], #100]\n\t"
  15617. "LDR r5, [%[b], #100]\n\t"
  15618. "AND r4, r4, r3\n\t"
  15619. "AND r5, r5, r3\n\t"
  15620. "SUBS r4, r4, r5\n\t"
  15621. "IT hi\n\t"
  15622. "movhi r2, r8\n\t"
  15623. "IT lo\n\t"
  15624. "movlo r2, r3\n\t"
  15625. "IT ne\n\t"
  15626. "movne r3, r7\n\t"
  15627. "LDR r4, [%[a], #96]\n\t"
  15628. "LDR r5, [%[b], #96]\n\t"
  15629. "AND r4, r4, r3\n\t"
  15630. "AND r5, r5, r3\n\t"
  15631. "SUBS r4, r4, r5\n\t"
  15632. "IT hi\n\t"
  15633. "movhi r2, r8\n\t"
  15634. "IT lo\n\t"
  15635. "movlo r2, r3\n\t"
  15636. "IT ne\n\t"
  15637. "movne r3, r7\n\t"
  15638. "LDR r4, [%[a], #92]\n\t"
  15639. "LDR r5, [%[b], #92]\n\t"
  15640. "AND r4, r4, r3\n\t"
  15641. "AND r5, r5, r3\n\t"
  15642. "SUBS r4, r4, r5\n\t"
  15643. "IT hi\n\t"
  15644. "movhi r2, r8\n\t"
  15645. "IT lo\n\t"
  15646. "movlo r2, r3\n\t"
  15647. "IT ne\n\t"
  15648. "movne r3, r7\n\t"
  15649. "LDR r4, [%[a], #88]\n\t"
  15650. "LDR r5, [%[b], #88]\n\t"
  15651. "AND r4, r4, r3\n\t"
  15652. "AND r5, r5, r3\n\t"
  15653. "SUBS r4, r4, r5\n\t"
  15654. "IT hi\n\t"
  15655. "movhi r2, r8\n\t"
  15656. "IT lo\n\t"
  15657. "movlo r2, r3\n\t"
  15658. "IT ne\n\t"
  15659. "movne r3, r7\n\t"
  15660. "LDR r4, [%[a], #84]\n\t"
  15661. "LDR r5, [%[b], #84]\n\t"
  15662. "AND r4, r4, r3\n\t"
  15663. "AND r5, r5, r3\n\t"
  15664. "SUBS r4, r4, r5\n\t"
  15665. "IT hi\n\t"
  15666. "movhi r2, r8\n\t"
  15667. "IT lo\n\t"
  15668. "movlo r2, r3\n\t"
  15669. "IT ne\n\t"
  15670. "movne r3, r7\n\t"
  15671. "LDR r4, [%[a], #80]\n\t"
  15672. "LDR r5, [%[b], #80]\n\t"
  15673. "AND r4, r4, r3\n\t"
  15674. "AND r5, r5, r3\n\t"
  15675. "SUBS r4, r4, r5\n\t"
  15676. "IT hi\n\t"
  15677. "movhi r2, r8\n\t"
  15678. "IT lo\n\t"
  15679. "movlo r2, r3\n\t"
  15680. "IT ne\n\t"
  15681. "movne r3, r7\n\t"
  15682. "LDR r4, [%[a], #76]\n\t"
  15683. "LDR r5, [%[b], #76]\n\t"
  15684. "AND r4, r4, r3\n\t"
  15685. "AND r5, r5, r3\n\t"
  15686. "SUBS r4, r4, r5\n\t"
  15687. "IT hi\n\t"
  15688. "movhi r2, r8\n\t"
  15689. "IT lo\n\t"
  15690. "movlo r2, r3\n\t"
  15691. "IT ne\n\t"
  15692. "movne r3, r7\n\t"
  15693. "LDR r4, [%[a], #72]\n\t"
  15694. "LDR r5, [%[b], #72]\n\t"
  15695. "AND r4, r4, r3\n\t"
  15696. "AND r5, r5, r3\n\t"
  15697. "SUBS r4, r4, r5\n\t"
  15698. "IT hi\n\t"
  15699. "movhi r2, r8\n\t"
  15700. "IT lo\n\t"
  15701. "movlo r2, r3\n\t"
  15702. "IT ne\n\t"
  15703. "movne r3, r7\n\t"
  15704. "LDR r4, [%[a], #68]\n\t"
  15705. "LDR r5, [%[b], #68]\n\t"
  15706. "AND r4, r4, r3\n\t"
  15707. "AND r5, r5, r3\n\t"
  15708. "SUBS r4, r4, r5\n\t"
  15709. "IT hi\n\t"
  15710. "movhi r2, r8\n\t"
  15711. "IT lo\n\t"
  15712. "movlo r2, r3\n\t"
  15713. "IT ne\n\t"
  15714. "movne r3, r7\n\t"
  15715. "LDR r4, [%[a], #64]\n\t"
  15716. "LDR r5, [%[b], #64]\n\t"
  15717. "AND r4, r4, r3\n\t"
  15718. "AND r5, r5, r3\n\t"
  15719. "SUBS r4, r4, r5\n\t"
  15720. "IT hi\n\t"
  15721. "movhi r2, r8\n\t"
  15722. "IT lo\n\t"
  15723. "movlo r2, r3\n\t"
  15724. "IT ne\n\t"
  15725. "movne r3, r7\n\t"
  15726. "LDR r4, [%[a], #60]\n\t"
  15727. "LDR r5, [%[b], #60]\n\t"
  15728. "AND r4, r4, r3\n\t"
  15729. "AND r5, r5, r3\n\t"
  15730. "SUBS r4, r4, r5\n\t"
  15731. "IT hi\n\t"
  15732. "movhi r2, r8\n\t"
  15733. "IT lo\n\t"
  15734. "movlo r2, r3\n\t"
  15735. "IT ne\n\t"
  15736. "movne r3, r7\n\t"
  15737. "LDR r4, [%[a], #56]\n\t"
  15738. "LDR r5, [%[b], #56]\n\t"
  15739. "AND r4, r4, r3\n\t"
  15740. "AND r5, r5, r3\n\t"
  15741. "SUBS r4, r4, r5\n\t"
  15742. "IT hi\n\t"
  15743. "movhi r2, r8\n\t"
  15744. "IT lo\n\t"
  15745. "movlo r2, r3\n\t"
  15746. "IT ne\n\t"
  15747. "movne r3, r7\n\t"
  15748. "LDR r4, [%[a], #52]\n\t"
  15749. "LDR r5, [%[b], #52]\n\t"
  15750. "AND r4, r4, r3\n\t"
  15751. "AND r5, r5, r3\n\t"
  15752. "SUBS r4, r4, r5\n\t"
  15753. "IT hi\n\t"
  15754. "movhi r2, r8\n\t"
  15755. "IT lo\n\t"
  15756. "movlo r2, r3\n\t"
  15757. "IT ne\n\t"
  15758. "movne r3, r7\n\t"
  15759. "LDR r4, [%[a], #48]\n\t"
  15760. "LDR r5, [%[b], #48]\n\t"
  15761. "AND r4, r4, r3\n\t"
  15762. "AND r5, r5, r3\n\t"
  15763. "SUBS r4, r4, r5\n\t"
  15764. "IT hi\n\t"
  15765. "movhi r2, r8\n\t"
  15766. "IT lo\n\t"
  15767. "movlo r2, r3\n\t"
  15768. "IT ne\n\t"
  15769. "movne r3, r7\n\t"
  15770. "LDR r4, [%[a], #44]\n\t"
  15771. "LDR r5, [%[b], #44]\n\t"
  15772. "AND r4, r4, r3\n\t"
  15773. "AND r5, r5, r3\n\t"
  15774. "SUBS r4, r4, r5\n\t"
  15775. "IT hi\n\t"
  15776. "movhi r2, r8\n\t"
  15777. "IT lo\n\t"
  15778. "movlo r2, r3\n\t"
  15779. "IT ne\n\t"
  15780. "movne r3, r7\n\t"
  15781. "LDR r4, [%[a], #40]\n\t"
  15782. "LDR r5, [%[b], #40]\n\t"
  15783. "AND r4, r4, r3\n\t"
  15784. "AND r5, r5, r3\n\t"
  15785. "SUBS r4, r4, r5\n\t"
  15786. "IT hi\n\t"
  15787. "movhi r2, r8\n\t"
  15788. "IT lo\n\t"
  15789. "movlo r2, r3\n\t"
  15790. "IT ne\n\t"
  15791. "movne r3, r7\n\t"
  15792. "LDR r4, [%[a], #36]\n\t"
  15793. "LDR r5, [%[b], #36]\n\t"
  15794. "AND r4, r4, r3\n\t"
  15795. "AND r5, r5, r3\n\t"
  15796. "SUBS r4, r4, r5\n\t"
  15797. "IT hi\n\t"
  15798. "movhi r2, r8\n\t"
  15799. "IT lo\n\t"
  15800. "movlo r2, r3\n\t"
  15801. "IT ne\n\t"
  15802. "movne r3, r7\n\t"
  15803. "LDR r4, [%[a], #32]\n\t"
  15804. "LDR r5, [%[b], #32]\n\t"
  15805. "AND r4, r4, r3\n\t"
  15806. "AND r5, r5, r3\n\t"
  15807. "SUBS r4, r4, r5\n\t"
  15808. "IT hi\n\t"
  15809. "movhi r2, r8\n\t"
  15810. "IT lo\n\t"
  15811. "movlo r2, r3\n\t"
  15812. "IT ne\n\t"
  15813. "movne r3, r7\n\t"
  15814. "LDR r4, [%[a], #28]\n\t"
  15815. "LDR r5, [%[b], #28]\n\t"
  15816. "AND r4, r4, r3\n\t"
  15817. "AND r5, r5, r3\n\t"
  15818. "SUBS r4, r4, r5\n\t"
  15819. "IT hi\n\t"
  15820. "movhi r2, r8\n\t"
  15821. "IT lo\n\t"
  15822. "movlo r2, r3\n\t"
  15823. "IT ne\n\t"
  15824. "movne r3, r7\n\t"
  15825. "LDR r4, [%[a], #24]\n\t"
  15826. "LDR r5, [%[b], #24]\n\t"
  15827. "AND r4, r4, r3\n\t"
  15828. "AND r5, r5, r3\n\t"
  15829. "SUBS r4, r4, r5\n\t"
  15830. "IT hi\n\t"
  15831. "movhi r2, r8\n\t"
  15832. "IT lo\n\t"
  15833. "movlo r2, r3\n\t"
  15834. "IT ne\n\t"
  15835. "movne r3, r7\n\t"
  15836. "LDR r4, [%[a], #20]\n\t"
  15837. "LDR r5, [%[b], #20]\n\t"
  15838. "AND r4, r4, r3\n\t"
  15839. "AND r5, r5, r3\n\t"
  15840. "SUBS r4, r4, r5\n\t"
  15841. "IT hi\n\t"
  15842. "movhi r2, r8\n\t"
  15843. "IT lo\n\t"
  15844. "movlo r2, r3\n\t"
  15845. "IT ne\n\t"
  15846. "movne r3, r7\n\t"
  15847. "LDR r4, [%[a], #16]\n\t"
  15848. "LDR r5, [%[b], #16]\n\t"
  15849. "AND r4, r4, r3\n\t"
  15850. "AND r5, r5, r3\n\t"
  15851. "SUBS r4, r4, r5\n\t"
  15852. "IT hi\n\t"
  15853. "movhi r2, r8\n\t"
  15854. "IT lo\n\t"
  15855. "movlo r2, r3\n\t"
  15856. "IT ne\n\t"
  15857. "movne r3, r7\n\t"
  15858. "LDR r4, [%[a], #12]\n\t"
  15859. "LDR r5, [%[b], #12]\n\t"
  15860. "AND r4, r4, r3\n\t"
  15861. "AND r5, r5, r3\n\t"
  15862. "SUBS r4, r4, r5\n\t"
  15863. "IT hi\n\t"
  15864. "movhi r2, r8\n\t"
  15865. "IT lo\n\t"
  15866. "movlo r2, r3\n\t"
  15867. "IT ne\n\t"
  15868. "movne r3, r7\n\t"
  15869. "LDR r4, [%[a], #8]\n\t"
  15870. "LDR r5, [%[b], #8]\n\t"
  15871. "AND r4, r4, r3\n\t"
  15872. "AND r5, r5, r3\n\t"
  15873. "SUBS r4, r4, r5\n\t"
  15874. "IT hi\n\t"
  15875. "movhi r2, r8\n\t"
  15876. "IT lo\n\t"
  15877. "movlo r2, r3\n\t"
  15878. "IT ne\n\t"
  15879. "movne r3, r7\n\t"
  15880. "LDR r4, [%[a], #4]\n\t"
  15881. "LDR r5, [%[b], #4]\n\t"
  15882. "AND r4, r4, r3\n\t"
  15883. "AND r5, r5, r3\n\t"
  15884. "SUBS r4, r4, r5\n\t"
  15885. "IT hi\n\t"
  15886. "movhi r2, r8\n\t"
  15887. "IT lo\n\t"
  15888. "movlo r2, r3\n\t"
  15889. "IT ne\n\t"
  15890. "movne r3, r7\n\t"
  15891. "LDR r4, [%[a]]\n\t"
  15892. "LDR r5, [%[b]]\n\t"
  15893. "AND r4, r4, r3\n\t"
  15894. "AND r5, r5, r3\n\t"
  15895. "SUBS r4, r4, r5\n\t"
  15896. "IT hi\n\t"
  15897. "movhi r2, r8\n\t"
  15898. "IT lo\n\t"
  15899. "movlo r2, r3\n\t"
  15900. "IT ne\n\t"
  15901. "movne r3, r7\n\t"
  15902. "EOR r2, r2, r3\n\t"
  15903. #endif /*WOLFSSL_SP_SMALL */
  15904. "MOV %[a], r2\n\t"
  15905. : [a] "+r" (a), [b] "+r" (b)
  15906. :
  15907. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  15908. );
  15909. return (uint32_t)(size_t)a;
  15910. }
  15911. /* Divide d in a and put remainder into r (m*d + r = a)
  15912. * m is not calculated as it is not needed at this time.
  15913. *
  15914. * a Number to be divided.
  15915. * d Number to divide with.
  15916. * m Multiplier result.
  15917. * r Remainder from the division.
  15918. * returns MP_OKAY indicating success.
  15919. */
  15920. static WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d,
  15921. sp_digit* m, sp_digit* r)
  15922. {
  15923. sp_digit t1[96], t2[49];
  15924. sp_digit div, r1;
  15925. int i;
  15926. (void)m;
  15927. div = d[47];
  15928. XMEMCPY(t1, a, sizeof(*t1) * 2 * 48);
  15929. r1 = sp_3072_cmp_48(&t1[48], d) >= 0;
  15930. sp_3072_cond_sub_48(&t1[48], &t1[48], d, (sp_digit)0 - r1);
  15931. for (i = 47; i >= 0; i--) {
  15932. volatile sp_digit mask = (sp_digit)0 - (t1[48 + i] == div);
  15933. sp_digit hi = t1[48 + i] + mask;
  15934. r1 = div_3072_word_48(hi, t1[48 + i - 1], div);
  15935. r1 |= mask;
  15936. sp_3072_mul_d_48(t2, d, r1);
  15937. t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2);
  15938. t1[48 + i] -= t2[48];
  15939. sp_3072_mask_48(t2, d, t1[48 + i]);
  15940. t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
  15941. sp_3072_mask_48(t2, d, t1[48 + i]);
  15942. t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
  15943. }
  15944. r1 = sp_3072_cmp_48(t1, d) >= 0;
  15945. sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1);
  15946. return MP_OKAY;
  15947. }
  15948. /* Reduce a modulo m into r. (r = a mod m)
  15949. *
  15950. * r A single precision number that is the reduced result.
  15951. * a A single precision number that is to be reduced.
  15952. * m A single precision number that is the modulus to reduce with.
  15953. * returns MP_OKAY indicating success.
  15954. */
  15955. static WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m)
  15956. {
  15957. return sp_3072_div_48(a, m, NULL, r);
  15958. }
  15959. #ifdef WOLFSSL_SP_SMALL
  15960. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  15961. *
  15962. * r A single precision number that is the result of the operation.
  15963. * a A single precision number being exponentiated.
  15964. * e A single precision number that is the exponent.
  15965. * bits The number of bits in the exponent.
  15966. * m A single precision number that is the modulus.
  15967. * returns 0 on success.
  15968. * returns MEMORY_E on dynamic memory allocation failure.
  15969. * returns MP_VAL when base is even or exponent is 0.
  15970. */
  15971. static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
  15972. int bits, const sp_digit* m, int reduceA)
  15973. {
  15974. #ifdef WOLFSSL_SP_SMALL_STACK
  15975. sp_digit* td = NULL;
  15976. #else
  15977. sp_digit td[16 * 96];
  15978. #endif
  15979. sp_digit* t[16];
  15980. sp_digit* norm = NULL;
  15981. sp_digit mp = 1;
  15982. sp_digit n;
  15983. sp_digit mask;
  15984. int i;
  15985. int c;
  15986. byte y;
  15987. int err = MP_OKAY;
  15988. if (bits == 0) {
  15989. err = MP_VAL;
  15990. }
  15991. #ifdef WOLFSSL_SP_SMALL_STACK
  15992. if (err == MP_OKAY) {
  15993. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 96), NULL,
  15994. DYNAMIC_TYPE_TMP_BUFFER);
  15995. if (td == NULL)
  15996. err = MEMORY_E;
  15997. }
  15998. #endif
  15999. if (err == MP_OKAY) {
  16000. norm = td;
  16001. for (i=0; i<16; i++) {
  16002. t[i] = td + i * 96;
  16003. }
  16004. sp_3072_mont_setup(m, &mp);
  16005. sp_3072_mont_norm_48(norm, m);
  16006. XMEMSET(t[1], 0, sizeof(sp_digit) * 48U);
  16007. if (reduceA != 0) {
  16008. err = sp_3072_mod_48(t[1] + 48, a, m);
  16009. if (err == MP_OKAY) {
  16010. err = sp_3072_mod_48(t[1], t[1], m);
  16011. }
  16012. }
  16013. else {
  16014. XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
  16015. err = sp_3072_mod_48(t[1], t[1], m);
  16016. }
  16017. }
  16018. if (err == MP_OKAY) {
  16019. sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
  16020. sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
  16021. sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
  16022. sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
  16023. sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
  16024. sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
  16025. sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
  16026. sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
  16027. sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
  16028. sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
  16029. sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
  16030. sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
  16031. sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
  16032. sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
  16033. i = (bits - 1) / 32;
  16034. n = e[i--];
  16035. c = bits & 31;
  16036. if (c == 0) {
  16037. c = 32;
  16038. }
  16039. c -= bits % 4;
  16040. if (c == 32) {
  16041. c = 28;
  16042. }
  16043. if (c < 0) {
  16044. /* Number of bits in top word is less than number needed. */
  16045. c = -c;
  16046. y = (byte)(n << c);
  16047. n = e[i--];
  16048. y |= (byte)(n >> (64 - c));
  16049. n <<= c;
  16050. c = 64 - c;
  16051. }
  16052. else if (c == 0) {
  16053. /* All bits in top word used. */
  16054. y = (byte)n;
  16055. }
  16056. else {
  16057. y = (byte)(n >> c);
  16058. n <<= 32 - c;
  16059. }
  16060. XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
  16061. for (; i>=0 || c>=4; ) {
  16062. if (c == 0) {
  16063. n = e[i--];
  16064. y = (byte)(n >> 28);
  16065. n <<= 4;
  16066. c = 28;
  16067. }
  16068. else if (c < 4) {
  16069. y = (byte)(n >> 28);
  16070. n = e[i--];
  16071. c = 4 - c;
  16072. y |= (byte)(n >> (32 - c));
  16073. n <<= c;
  16074. c = 32 - c;
  16075. }
  16076. else {
  16077. y = (byte)((n >> 28) & 0xf);
  16078. n <<= 4;
  16079. c -= 4;
  16080. }
  16081. sp_3072_mont_sqr_48(r, r, m, mp);
  16082. sp_3072_mont_sqr_48(r, r, m, mp);
  16083. sp_3072_mont_sqr_48(r, r, m, mp);
  16084. sp_3072_mont_sqr_48(r, r, m, mp);
  16085. sp_3072_mont_mul_48(r, r, t[y], m, mp);
  16086. }
  16087. XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U);
  16088. sp_3072_mont_reduce_48(r, m, mp);
  16089. mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
  16090. sp_3072_cond_sub_48(r, r, m, mask);
  16091. }
  16092. #ifdef WOLFSSL_SP_SMALL_STACK
  16093. if (td != NULL)
  16094. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  16095. #endif
  16096. return err;
  16097. }
  16098. #else
  16099. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  16100. *
  16101. * r A single precision number that is the result of the operation.
  16102. * a A single precision number being exponentiated.
  16103. * e A single precision number that is the exponent.
  16104. * bits The number of bits in the exponent.
  16105. * m A single precision number that is the modulus.
  16106. * returns 0 on success.
  16107. * returns MEMORY_E on dynamic memory allocation failure.
  16108. * returns MP_VAL when base is even or exponent is 0.
  16109. */
  16110. static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e,
  16111. int bits, const sp_digit* m, int reduceA)
  16112. {
  16113. #ifdef WOLFSSL_SP_SMALL_STACK
  16114. sp_digit* td = NULL;
  16115. #else
  16116. sp_digit td[32 * 96];
  16117. #endif
  16118. sp_digit* t[32];
  16119. sp_digit* norm = NULL;
  16120. sp_digit mp = 1;
  16121. sp_digit n;
  16122. sp_digit mask;
  16123. int i;
  16124. int c;
  16125. byte y;
  16126. int err = MP_OKAY;
  16127. if (bits == 0) {
  16128. err = MP_VAL;
  16129. }
  16130. #ifdef WOLFSSL_SP_SMALL_STACK
  16131. if (err == MP_OKAY) {
  16132. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 96), NULL,
  16133. DYNAMIC_TYPE_TMP_BUFFER);
  16134. if (td == NULL)
  16135. err = MEMORY_E;
  16136. }
  16137. #endif
  16138. if (err == MP_OKAY) {
  16139. norm = td;
  16140. for (i=0; i<32; i++) {
  16141. t[i] = td + i * 96;
  16142. }
  16143. sp_3072_mont_setup(m, &mp);
  16144. sp_3072_mont_norm_48(norm, m);
  16145. XMEMSET(t[1], 0, sizeof(sp_digit) * 48U);
  16146. if (reduceA != 0) {
  16147. err = sp_3072_mod_48(t[1] + 48, a, m);
  16148. if (err == MP_OKAY) {
  16149. err = sp_3072_mod_48(t[1], t[1], m);
  16150. }
  16151. }
  16152. else {
  16153. XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
  16154. err = sp_3072_mod_48(t[1], t[1], m);
  16155. }
  16156. }
  16157. if (err == MP_OKAY) {
  16158. sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
  16159. sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
  16160. sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
  16161. sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
  16162. sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
  16163. sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
  16164. sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
  16165. sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
  16166. sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
  16167. sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
  16168. sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
  16169. sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
  16170. sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
  16171. sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
  16172. sp_3072_mont_sqr_48(t[16], t[ 8], m, mp);
  16173. sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp);
  16174. sp_3072_mont_sqr_48(t[18], t[ 9], m, mp);
  16175. sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp);
  16176. sp_3072_mont_sqr_48(t[20], t[10], m, mp);
  16177. sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp);
  16178. sp_3072_mont_sqr_48(t[22], t[11], m, mp);
  16179. sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp);
  16180. sp_3072_mont_sqr_48(t[24], t[12], m, mp);
  16181. sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp);
  16182. sp_3072_mont_sqr_48(t[26], t[13], m, mp);
  16183. sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp);
  16184. sp_3072_mont_sqr_48(t[28], t[14], m, mp);
  16185. sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp);
  16186. sp_3072_mont_sqr_48(t[30], t[15], m, mp);
  16187. sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp);
  16188. i = (bits - 1) / 32;
  16189. n = e[i--];
  16190. c = bits & 31;
  16191. if (c == 0) {
  16192. c = 32;
  16193. }
  16194. c -= bits % 5;
  16195. if (c == 32) {
  16196. c = 27;
  16197. }
  16198. if (c < 0) {
  16199. /* Number of bits in top word is less than number needed. */
  16200. c = -c;
  16201. y = (byte)(n << c);
  16202. n = e[i--];
  16203. y |= (byte)(n >> (64 - c));
  16204. n <<= c;
  16205. c = 64 - c;
  16206. }
  16207. else if (c == 0) {
  16208. /* All bits in top word used. */
  16209. y = (byte)n;
  16210. }
  16211. else {
  16212. y = (byte)(n >> c);
  16213. n <<= 32 - c;
  16214. }
  16215. XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
  16216. for (; i>=0 || c>=5; ) {
  16217. if (c == 0) {
  16218. n = e[i--];
  16219. y = (byte)(n >> 27);
  16220. n <<= 5;
  16221. c = 27;
  16222. }
  16223. else if (c < 5) {
  16224. y = (byte)(n >> 27);
  16225. n = e[i--];
  16226. c = 5 - c;
  16227. y |= (byte)(n >> (32 - c));
  16228. n <<= c;
  16229. c = 32 - c;
  16230. }
  16231. else {
  16232. y = (byte)((n >> 27) & 0x1f);
  16233. n <<= 5;
  16234. c -= 5;
  16235. }
  16236. sp_3072_mont_sqr_48(r, r, m, mp);
  16237. sp_3072_mont_sqr_48(r, r, m, mp);
  16238. sp_3072_mont_sqr_48(r, r, m, mp);
  16239. sp_3072_mont_sqr_48(r, r, m, mp);
  16240. sp_3072_mont_sqr_48(r, r, m, mp);
  16241. sp_3072_mont_mul_48(r, r, t[y], m, mp);
  16242. }
  16243. XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U);
  16244. sp_3072_mont_reduce_48(r, m, mp);
  16245. mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
  16246. sp_3072_cond_sub_48(r, r, m, mask);
  16247. }
  16248. #ifdef WOLFSSL_SP_SMALL_STACK
  16249. if (td != NULL)
  16250. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  16251. #endif
  16252. return err;
  16253. }
  16254. #endif /* WOLFSSL_SP_SMALL */
  16255. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  16256. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  16257. /* r = 2^n mod m where n is the number of bits to reduce by.
  16258. * Given m must be 3072 bits, just need to subtract.
  16259. *
  16260. * r A single precision number.
  16261. * m A single precision number.
  16262. */
  16263. static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m)
  16264. {
  16265. XMEMSET(r, 0, sizeof(sp_digit) * 96);
  16266. /* r = 2^n mod m */
  16267. sp_3072_sub_in_place_96(r, m);
  16268. }
  16269. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  16270. #ifdef WOLFSSL_SP_SMALL
  16271. /* Conditionally subtract b from a using the mask m.
  16272. * m is -1 to subtract and 0 when not copying.
  16273. *
  16274. * r A single precision number representing condition subtract result.
  16275. * a A single precision number to subtract from.
  16276. * b A single precision number to subtract.
  16277. * m Mask value to apply.
  16278. */
  16279. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  16280. static sp_digit sp_3072_cond_sub_96(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  16281. #else
  16282. static sp_digit sp_3072_cond_sub_96(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  16283. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  16284. {
  16285. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  16286. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  16287. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  16288. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  16289. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  16290. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  16291. __asm__ __volatile__ (
  16292. "MOV r8, #0x0\n\t"
  16293. "MOV r4, #0x0\n\t"
  16294. "MOV r5, #0x0\n\t"
  16295. "\n"
  16296. "L_sp_3072_cond_sub_96_words:\n\t"
  16297. "SUBS r4, r8, r4\n\t"
  16298. "LDR r6, [%[a], r5]\n\t"
  16299. "LDR r7, [%[b], r5]\n\t"
  16300. "AND r7, r7, %[m]\n\t"
  16301. "SBCS r6, r6, r7\n\t"
  16302. "SBC r4, r8, r8\n\t"
  16303. "STR r6, [%[r], r5]\n\t"
  16304. "ADD r5, r5, #0x4\n\t"
  16305. "CMP r5, #0x180\n\t"
  16306. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  16307. "BLT L_sp_3072_cond_sub_96_words\n\t"
  16308. #else
  16309. "BLT.N L_sp_3072_cond_sub_96_words\n\t"
  16310. #endif
  16311. "MOV %[r], r4\n\t"
  16312. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  16313. :
  16314. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  16315. );
  16316. return (uint32_t)(size_t)r;
  16317. }
  16318. #else
  16319. /* Conditionally subtract b from a using the mask m.
  16320. * m is -1 to subtract and 0 when not copying.
  16321. *
  16322. * r A single precision number representing condition subtract result.
  16323. * a A single precision number to subtract from.
  16324. * b A single precision number to subtract.
  16325. * m Mask value to apply.
  16326. */
  16327. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  16328. static sp_digit sp_3072_cond_sub_96(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  16329. #else
  16330. static sp_digit sp_3072_cond_sub_96(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  16331. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  16332. {
  16333. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  16334. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  16335. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  16336. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  16337. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  16338. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  16339. __asm__ __volatile__ (
  16340. "MOV r5, #0x0\n\t"
  16341. "LDM %[a]!, {r6, r7}\n\t"
  16342. "LDM %[b]!, {r8, r9}\n\t"
  16343. "AND r8, r8, %[m]\n\t"
  16344. "AND r9, r9, %[m]\n\t"
  16345. "SUBS r6, r6, r8\n\t"
  16346. "SBCS r7, r7, r9\n\t"
  16347. "STM %[r]!, {r6, r7}\n\t"
  16348. "LDM %[a]!, {r6, r7}\n\t"
  16349. "LDM %[b]!, {r8, r9}\n\t"
  16350. "AND r8, r8, %[m]\n\t"
  16351. "AND r9, r9, %[m]\n\t"
  16352. "SBCS r6, r6, r8\n\t"
  16353. "SBCS r7, r7, r9\n\t"
  16354. "STM %[r]!, {r6, r7}\n\t"
  16355. "LDM %[a]!, {r6, r7}\n\t"
  16356. "LDM %[b]!, {r8, r9}\n\t"
  16357. "AND r8, r8, %[m]\n\t"
  16358. "AND r9, r9, %[m]\n\t"
  16359. "SBCS r6, r6, r8\n\t"
  16360. "SBCS r7, r7, r9\n\t"
  16361. "STM %[r]!, {r6, r7}\n\t"
  16362. "LDM %[a]!, {r6, r7}\n\t"
  16363. "LDM %[b]!, {r8, r9}\n\t"
  16364. "AND r8, r8, %[m]\n\t"
  16365. "AND r9, r9, %[m]\n\t"
  16366. "SBCS r6, r6, r8\n\t"
  16367. "SBCS r7, r7, r9\n\t"
  16368. "STM %[r]!, {r6, r7}\n\t"
  16369. "LDM %[a]!, {r6, r7}\n\t"
  16370. "LDM %[b]!, {r8, r9}\n\t"
  16371. "AND r8, r8, %[m]\n\t"
  16372. "AND r9, r9, %[m]\n\t"
  16373. "SBCS r6, r6, r8\n\t"
  16374. "SBCS r7, r7, r9\n\t"
  16375. "STM %[r]!, {r6, r7}\n\t"
  16376. "LDM %[a]!, {r6, r7}\n\t"
  16377. "LDM %[b]!, {r8, r9}\n\t"
  16378. "AND r8, r8, %[m]\n\t"
  16379. "AND r9, r9, %[m]\n\t"
  16380. "SBCS r6, r6, r8\n\t"
  16381. "SBCS r7, r7, r9\n\t"
  16382. "STM %[r]!, {r6, r7}\n\t"
  16383. "LDM %[a]!, {r6, r7}\n\t"
  16384. "LDM %[b]!, {r8, r9}\n\t"
  16385. "AND r8, r8, %[m]\n\t"
  16386. "AND r9, r9, %[m]\n\t"
  16387. "SBCS r6, r6, r8\n\t"
  16388. "SBCS r7, r7, r9\n\t"
  16389. "STM %[r]!, {r6, r7}\n\t"
  16390. "LDM %[a]!, {r6, r7}\n\t"
  16391. "LDM %[b]!, {r8, r9}\n\t"
  16392. "AND r8, r8, %[m]\n\t"
  16393. "AND r9, r9, %[m]\n\t"
  16394. "SBCS r6, r6, r8\n\t"
  16395. "SBCS r7, r7, r9\n\t"
  16396. "STM %[r]!, {r6, r7}\n\t"
  16397. "LDM %[a]!, {r6, r7}\n\t"
  16398. "LDM %[b]!, {r8, r9}\n\t"
  16399. "AND r8, r8, %[m]\n\t"
  16400. "AND r9, r9, %[m]\n\t"
  16401. "SBCS r6, r6, r8\n\t"
  16402. "SBCS r7, r7, r9\n\t"
  16403. "STM %[r]!, {r6, r7}\n\t"
  16404. "LDM %[a]!, {r6, r7}\n\t"
  16405. "LDM %[b]!, {r8, r9}\n\t"
  16406. "AND r8, r8, %[m]\n\t"
  16407. "AND r9, r9, %[m]\n\t"
  16408. "SBCS r6, r6, r8\n\t"
  16409. "SBCS r7, r7, r9\n\t"
  16410. "STM %[r]!, {r6, r7}\n\t"
  16411. "LDM %[a]!, {r6, r7}\n\t"
  16412. "LDM %[b]!, {r8, r9}\n\t"
  16413. "AND r8, r8, %[m]\n\t"
  16414. "AND r9, r9, %[m]\n\t"
  16415. "SBCS r6, r6, r8\n\t"
  16416. "SBCS r7, r7, r9\n\t"
  16417. "STM %[r]!, {r6, r7}\n\t"
  16418. "LDM %[a]!, {r6, r7}\n\t"
  16419. "LDM %[b]!, {r8, r9}\n\t"
  16420. "AND r8, r8, %[m]\n\t"
  16421. "AND r9, r9, %[m]\n\t"
  16422. "SBCS r6, r6, r8\n\t"
  16423. "SBCS r7, r7, r9\n\t"
  16424. "STM %[r]!, {r6, r7}\n\t"
  16425. "LDM %[a]!, {r6, r7}\n\t"
  16426. "LDM %[b]!, {r8, r9}\n\t"
  16427. "AND r8, r8, %[m]\n\t"
  16428. "AND r9, r9, %[m]\n\t"
  16429. "SBCS r6, r6, r8\n\t"
  16430. "SBCS r7, r7, r9\n\t"
  16431. "STM %[r]!, {r6, r7}\n\t"
  16432. "LDM %[a]!, {r6, r7}\n\t"
  16433. "LDM %[b]!, {r8, r9}\n\t"
  16434. "AND r8, r8, %[m]\n\t"
  16435. "AND r9, r9, %[m]\n\t"
  16436. "SBCS r6, r6, r8\n\t"
  16437. "SBCS r7, r7, r9\n\t"
  16438. "STM %[r]!, {r6, r7}\n\t"
  16439. "LDM %[a]!, {r6, r7}\n\t"
  16440. "LDM %[b]!, {r8, r9}\n\t"
  16441. "AND r8, r8, %[m]\n\t"
  16442. "AND r9, r9, %[m]\n\t"
  16443. "SBCS r6, r6, r8\n\t"
  16444. "SBCS r7, r7, r9\n\t"
  16445. "STM %[r]!, {r6, r7}\n\t"
  16446. "LDM %[a]!, {r6, r7}\n\t"
  16447. "LDM %[b]!, {r8, r9}\n\t"
  16448. "AND r8, r8, %[m]\n\t"
  16449. "AND r9, r9, %[m]\n\t"
  16450. "SBCS r6, r6, r8\n\t"
  16451. "SBCS r7, r7, r9\n\t"
  16452. "STM %[r]!, {r6, r7}\n\t"
  16453. "LDM %[a]!, {r6, r7}\n\t"
  16454. "LDM %[b]!, {r8, r9}\n\t"
  16455. "AND r8, r8, %[m]\n\t"
  16456. "AND r9, r9, %[m]\n\t"
  16457. "SBCS r6, r6, r8\n\t"
  16458. "SBCS r7, r7, r9\n\t"
  16459. "STM %[r]!, {r6, r7}\n\t"
  16460. "LDM %[a]!, {r6, r7}\n\t"
  16461. "LDM %[b]!, {r8, r9}\n\t"
  16462. "AND r8, r8, %[m]\n\t"
  16463. "AND r9, r9, %[m]\n\t"
  16464. "SBCS r6, r6, r8\n\t"
  16465. "SBCS r7, r7, r9\n\t"
  16466. "STM %[r]!, {r6, r7}\n\t"
  16467. "LDM %[a]!, {r6, r7}\n\t"
  16468. "LDM %[b]!, {r8, r9}\n\t"
  16469. "AND r8, r8, %[m]\n\t"
  16470. "AND r9, r9, %[m]\n\t"
  16471. "SBCS r6, r6, r8\n\t"
  16472. "SBCS r7, r7, r9\n\t"
  16473. "STM %[r]!, {r6, r7}\n\t"
  16474. "LDM %[a]!, {r6, r7}\n\t"
  16475. "LDM %[b]!, {r8, r9}\n\t"
  16476. "AND r8, r8, %[m]\n\t"
  16477. "AND r9, r9, %[m]\n\t"
  16478. "SBCS r6, r6, r8\n\t"
  16479. "SBCS r7, r7, r9\n\t"
  16480. "STM %[r]!, {r6, r7}\n\t"
  16481. "LDM %[a]!, {r6, r7}\n\t"
  16482. "LDM %[b]!, {r8, r9}\n\t"
  16483. "AND r8, r8, %[m]\n\t"
  16484. "AND r9, r9, %[m]\n\t"
  16485. "SBCS r6, r6, r8\n\t"
  16486. "SBCS r7, r7, r9\n\t"
  16487. "STM %[r]!, {r6, r7}\n\t"
  16488. "LDM %[a]!, {r6, r7}\n\t"
  16489. "LDM %[b]!, {r8, r9}\n\t"
  16490. "AND r8, r8, %[m]\n\t"
  16491. "AND r9, r9, %[m]\n\t"
  16492. "SBCS r6, r6, r8\n\t"
  16493. "SBCS r7, r7, r9\n\t"
  16494. "STM %[r]!, {r6, r7}\n\t"
  16495. "LDM %[a]!, {r6, r7}\n\t"
  16496. "LDM %[b]!, {r8, r9}\n\t"
  16497. "AND r8, r8, %[m]\n\t"
  16498. "AND r9, r9, %[m]\n\t"
  16499. "SBCS r6, r6, r8\n\t"
  16500. "SBCS r7, r7, r9\n\t"
  16501. "STM %[r]!, {r6, r7}\n\t"
  16502. "LDM %[a]!, {r6, r7}\n\t"
  16503. "LDM %[b]!, {r8, r9}\n\t"
  16504. "AND r8, r8, %[m]\n\t"
  16505. "AND r9, r9, %[m]\n\t"
  16506. "SBCS r6, r6, r8\n\t"
  16507. "SBCS r7, r7, r9\n\t"
  16508. "STM %[r]!, {r6, r7}\n\t"
  16509. "LDM %[a]!, {r6, r7}\n\t"
  16510. "LDM %[b]!, {r8, r9}\n\t"
  16511. "AND r8, r8, %[m]\n\t"
  16512. "AND r9, r9, %[m]\n\t"
  16513. "SBCS r6, r6, r8\n\t"
  16514. "SBCS r7, r7, r9\n\t"
  16515. "STM %[r]!, {r6, r7}\n\t"
  16516. "LDM %[a]!, {r6, r7}\n\t"
  16517. "LDM %[b]!, {r8, r9}\n\t"
  16518. "AND r8, r8, %[m]\n\t"
  16519. "AND r9, r9, %[m]\n\t"
  16520. "SBCS r6, r6, r8\n\t"
  16521. "SBCS r7, r7, r9\n\t"
  16522. "STM %[r]!, {r6, r7}\n\t"
  16523. "LDM %[a]!, {r6, r7}\n\t"
  16524. "LDM %[b]!, {r8, r9}\n\t"
  16525. "AND r8, r8, %[m]\n\t"
  16526. "AND r9, r9, %[m]\n\t"
  16527. "SBCS r6, r6, r8\n\t"
  16528. "SBCS r7, r7, r9\n\t"
  16529. "STM %[r]!, {r6, r7}\n\t"
  16530. "LDM %[a]!, {r6, r7}\n\t"
  16531. "LDM %[b]!, {r8, r9}\n\t"
  16532. "AND r8, r8, %[m]\n\t"
  16533. "AND r9, r9, %[m]\n\t"
  16534. "SBCS r6, r6, r8\n\t"
  16535. "SBCS r7, r7, r9\n\t"
  16536. "STM %[r]!, {r6, r7}\n\t"
  16537. "LDM %[a]!, {r6, r7}\n\t"
  16538. "LDM %[b]!, {r8, r9}\n\t"
  16539. "AND r8, r8, %[m]\n\t"
  16540. "AND r9, r9, %[m]\n\t"
  16541. "SBCS r6, r6, r8\n\t"
  16542. "SBCS r7, r7, r9\n\t"
  16543. "STM %[r]!, {r6, r7}\n\t"
  16544. "LDM %[a]!, {r6, r7}\n\t"
  16545. "LDM %[b]!, {r8, r9}\n\t"
  16546. "AND r8, r8, %[m]\n\t"
  16547. "AND r9, r9, %[m]\n\t"
  16548. "SBCS r6, r6, r8\n\t"
  16549. "SBCS r7, r7, r9\n\t"
  16550. "STM %[r]!, {r6, r7}\n\t"
  16551. "LDM %[a]!, {r6, r7}\n\t"
  16552. "LDM %[b]!, {r8, r9}\n\t"
  16553. "AND r8, r8, %[m]\n\t"
  16554. "AND r9, r9, %[m]\n\t"
  16555. "SBCS r6, r6, r8\n\t"
  16556. "SBCS r7, r7, r9\n\t"
  16557. "STM %[r]!, {r6, r7}\n\t"
  16558. "LDM %[a]!, {r6, r7}\n\t"
  16559. "LDM %[b]!, {r8, r9}\n\t"
  16560. "AND r8, r8, %[m]\n\t"
  16561. "AND r9, r9, %[m]\n\t"
  16562. "SBCS r6, r6, r8\n\t"
  16563. "SBCS r7, r7, r9\n\t"
  16564. "STM %[r]!, {r6, r7}\n\t"
  16565. "LDM %[a]!, {r6, r7}\n\t"
  16566. "LDM %[b]!, {r8, r9}\n\t"
  16567. "AND r8, r8, %[m]\n\t"
  16568. "AND r9, r9, %[m]\n\t"
  16569. "SBCS r6, r6, r8\n\t"
  16570. "SBCS r7, r7, r9\n\t"
  16571. "STM %[r]!, {r6, r7}\n\t"
  16572. "LDM %[a]!, {r6, r7}\n\t"
  16573. "LDM %[b]!, {r8, r9}\n\t"
  16574. "AND r8, r8, %[m]\n\t"
  16575. "AND r9, r9, %[m]\n\t"
  16576. "SBCS r6, r6, r8\n\t"
  16577. "SBCS r7, r7, r9\n\t"
  16578. "STM %[r]!, {r6, r7}\n\t"
  16579. "LDM %[a]!, {r6, r7}\n\t"
  16580. "LDM %[b]!, {r8, r9}\n\t"
  16581. "AND r8, r8, %[m]\n\t"
  16582. "AND r9, r9, %[m]\n\t"
  16583. "SBCS r6, r6, r8\n\t"
  16584. "SBCS r7, r7, r9\n\t"
  16585. "STM %[r]!, {r6, r7}\n\t"
  16586. "LDM %[a]!, {r6, r7}\n\t"
  16587. "LDM %[b]!, {r8, r9}\n\t"
  16588. "AND r8, r8, %[m]\n\t"
  16589. "AND r9, r9, %[m]\n\t"
  16590. "SBCS r6, r6, r8\n\t"
  16591. "SBCS r7, r7, r9\n\t"
  16592. "STM %[r]!, {r6, r7}\n\t"
  16593. "LDM %[a]!, {r6, r7}\n\t"
  16594. "LDM %[b]!, {r8, r9}\n\t"
  16595. "AND r8, r8, %[m]\n\t"
  16596. "AND r9, r9, %[m]\n\t"
  16597. "SBCS r6, r6, r8\n\t"
  16598. "SBCS r7, r7, r9\n\t"
  16599. "STM %[r]!, {r6, r7}\n\t"
  16600. "LDM %[a]!, {r6, r7}\n\t"
  16601. "LDM %[b]!, {r8, r9}\n\t"
  16602. "AND r8, r8, %[m]\n\t"
  16603. "AND r9, r9, %[m]\n\t"
  16604. "SBCS r6, r6, r8\n\t"
  16605. "SBCS r7, r7, r9\n\t"
  16606. "STM %[r]!, {r6, r7}\n\t"
  16607. "LDM %[a]!, {r6, r7}\n\t"
  16608. "LDM %[b]!, {r8, r9}\n\t"
  16609. "AND r8, r8, %[m]\n\t"
  16610. "AND r9, r9, %[m]\n\t"
  16611. "SBCS r6, r6, r8\n\t"
  16612. "SBCS r7, r7, r9\n\t"
  16613. "STM %[r]!, {r6, r7}\n\t"
  16614. "LDM %[a]!, {r6, r7}\n\t"
  16615. "LDM %[b]!, {r8, r9}\n\t"
  16616. "AND r8, r8, %[m]\n\t"
  16617. "AND r9, r9, %[m]\n\t"
  16618. "SBCS r6, r6, r8\n\t"
  16619. "SBCS r7, r7, r9\n\t"
  16620. "STM %[r]!, {r6, r7}\n\t"
  16621. "LDM %[a]!, {r6, r7}\n\t"
  16622. "LDM %[b]!, {r8, r9}\n\t"
  16623. "AND r8, r8, %[m]\n\t"
  16624. "AND r9, r9, %[m]\n\t"
  16625. "SBCS r6, r6, r8\n\t"
  16626. "SBCS r7, r7, r9\n\t"
  16627. "STM %[r]!, {r6, r7}\n\t"
  16628. "LDM %[a]!, {r6, r7}\n\t"
  16629. "LDM %[b]!, {r8, r9}\n\t"
  16630. "AND r8, r8, %[m]\n\t"
  16631. "AND r9, r9, %[m]\n\t"
  16632. "SBCS r6, r6, r8\n\t"
  16633. "SBCS r7, r7, r9\n\t"
  16634. "STM %[r]!, {r6, r7}\n\t"
  16635. "LDM %[a]!, {r6, r7}\n\t"
  16636. "LDM %[b]!, {r8, r9}\n\t"
  16637. "AND r8, r8, %[m]\n\t"
  16638. "AND r9, r9, %[m]\n\t"
  16639. "SBCS r6, r6, r8\n\t"
  16640. "SBCS r7, r7, r9\n\t"
  16641. "STM %[r]!, {r6, r7}\n\t"
  16642. "LDM %[a]!, {r6, r7}\n\t"
  16643. "LDM %[b]!, {r8, r9}\n\t"
  16644. "AND r8, r8, %[m]\n\t"
  16645. "AND r9, r9, %[m]\n\t"
  16646. "SBCS r6, r6, r8\n\t"
  16647. "SBCS r7, r7, r9\n\t"
  16648. "STM %[r]!, {r6, r7}\n\t"
  16649. "LDM %[a]!, {r6, r7}\n\t"
  16650. "LDM %[b]!, {r8, r9}\n\t"
  16651. "AND r8, r8, %[m]\n\t"
  16652. "AND r9, r9, %[m]\n\t"
  16653. "SBCS r6, r6, r8\n\t"
  16654. "SBCS r7, r7, r9\n\t"
  16655. "STM %[r]!, {r6, r7}\n\t"
  16656. "LDM %[a]!, {r6, r7}\n\t"
  16657. "LDM %[b]!, {r8, r9}\n\t"
  16658. "AND r8, r8, %[m]\n\t"
  16659. "AND r9, r9, %[m]\n\t"
  16660. "SBCS r6, r6, r8\n\t"
  16661. "SBCS r7, r7, r9\n\t"
  16662. "STM %[r]!, {r6, r7}\n\t"
  16663. "LDM %[a]!, {r6, r7}\n\t"
  16664. "LDM %[b]!, {r8, r9}\n\t"
  16665. "AND r8, r8, %[m]\n\t"
  16666. "AND r9, r9, %[m]\n\t"
  16667. "SBCS r6, r6, r8\n\t"
  16668. "SBCS r7, r7, r9\n\t"
  16669. "STM %[r]!, {r6, r7}\n\t"
  16670. "LDM %[a]!, {r6, r7}\n\t"
  16671. "LDM %[b]!, {r8, r9}\n\t"
  16672. "AND r8, r8, %[m]\n\t"
  16673. "AND r9, r9, %[m]\n\t"
  16674. "SBCS r6, r6, r8\n\t"
  16675. "SBCS r7, r7, r9\n\t"
  16676. "STM %[r]!, {r6, r7}\n\t"
  16677. "SBC %[r], r5, r5\n\t"
  16678. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  16679. :
  16680. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  16681. );
  16682. return (uint32_t)(size_t)r;
  16683. }
  16684. #endif /* WOLFSSL_SP_SMALL */
  16685. #ifdef WOLFSSL_SP_NO_UMAAL
  16686. #ifndef WOLFSSL_SP_SMALL
  16687. /* Reduce the number back to 3072 bits using Montgomery reduction.
  16688. *
  16689. * a A single precision number to reduce in place.
  16690. * m The single precision number representing the modulus.
  16691. * mp The digit representing the negative inverse of m mod 2^n.
  16692. */
  16693. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  16694. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  16695. #else
  16696. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, sp_digit mp)
  16697. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  16698. {
  16699. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  16700. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  16701. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  16702. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  16703. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  16704. __asm__ __volatile__ (
  16705. "LDR lr, [%[m]]\n\t"
  16706. /* i = 0 */
  16707. "MOV r11, #0x0\n\t"
  16708. "MOV r3, #0x0\n\t"
  16709. "LDR r4, [%[a]]\n\t"
  16710. "LDR r5, [%[a], #4]\n\t"
  16711. "\n"
  16712. "L_sp_3072_mont_reduce_96_word:\n\t"
  16713. /* mu = a[i] * mp */
  16714. "MUL r10, %[mp], r4\n\t"
  16715. /* a[i+0] += m[0] * mu */
  16716. "MOV r7, #0x0\n\t"
  16717. "UMLAL r4, r7, r10, lr\n\t"
  16718. /* a[i+1] += m[1] * mu */
  16719. "LDR r9, [%[m], #4]\n\t"
  16720. "MOV r6, #0x0\n\t"
  16721. "UMLAL r5, r6, r10, r9\n\t"
  16722. "MOV r4, r5\n\t"
  16723. "ADDS r4, r4, r7\n\t"
  16724. "ADC r6, r6, #0x0\n\t"
  16725. /* a[i+2] += m[2] * mu */
  16726. "LDR r9, [%[m], #8]\n\t"
  16727. "LDR r5, [%[a], #8]\n\t"
  16728. "MOV r7, #0x0\n\t"
  16729. "UMLAL r5, r7, r10, r9\n\t"
  16730. "ADDS r5, r5, r6\n\t"
  16731. "ADC r7, r7, #0x0\n\t"
  16732. /* a[i+3] += m[3] * mu */
  16733. "LDR r9, [%[m], #12]\n\t"
  16734. "LDR r12, [%[a], #12]\n\t"
  16735. "MOV r6, #0x0\n\t"
  16736. "UMLAL r12, r6, r10, r9\n\t"
  16737. "ADDS r12, r12, r7\n\t"
  16738. "STR r12, [%[a], #12]\n\t"
  16739. "ADC r6, r6, #0x0\n\t"
  16740. /* a[i+4] += m[4] * mu */
  16741. "LDR r9, [%[m], #16]\n\t"
  16742. "LDR r12, [%[a], #16]\n\t"
  16743. "MOV r7, #0x0\n\t"
  16744. "UMLAL r12, r7, r10, r9\n\t"
  16745. "ADDS r12, r12, r6\n\t"
  16746. "STR r12, [%[a], #16]\n\t"
  16747. "ADC r7, r7, #0x0\n\t"
  16748. /* a[i+5] += m[5] * mu */
  16749. "LDR r9, [%[m], #20]\n\t"
  16750. "LDR r12, [%[a], #20]\n\t"
  16751. "MOV r6, #0x0\n\t"
  16752. "UMLAL r12, r6, r10, r9\n\t"
  16753. "ADDS r12, r12, r7\n\t"
  16754. "STR r12, [%[a], #20]\n\t"
  16755. "ADC r6, r6, #0x0\n\t"
  16756. /* a[i+6] += m[6] * mu */
  16757. "LDR r9, [%[m], #24]\n\t"
  16758. "LDR r12, [%[a], #24]\n\t"
  16759. "MOV r7, #0x0\n\t"
  16760. "UMLAL r12, r7, r10, r9\n\t"
  16761. "ADDS r12, r12, r6\n\t"
  16762. "STR r12, [%[a], #24]\n\t"
  16763. "ADC r7, r7, #0x0\n\t"
  16764. /* a[i+7] += m[7] * mu */
  16765. "LDR r9, [%[m], #28]\n\t"
  16766. "LDR r12, [%[a], #28]\n\t"
  16767. "MOV r6, #0x0\n\t"
  16768. "UMLAL r12, r6, r10, r9\n\t"
  16769. "ADDS r12, r12, r7\n\t"
  16770. "STR r12, [%[a], #28]\n\t"
  16771. "ADC r6, r6, #0x0\n\t"
  16772. /* a[i+8] += m[8] * mu */
  16773. "LDR r9, [%[m], #32]\n\t"
  16774. "LDR r12, [%[a], #32]\n\t"
  16775. "MOV r7, #0x0\n\t"
  16776. "UMLAL r12, r7, r10, r9\n\t"
  16777. "ADDS r12, r12, r6\n\t"
  16778. "STR r12, [%[a], #32]\n\t"
  16779. "ADC r7, r7, #0x0\n\t"
  16780. /* a[i+9] += m[9] * mu */
  16781. "LDR r9, [%[m], #36]\n\t"
  16782. "LDR r12, [%[a], #36]\n\t"
  16783. "MOV r6, #0x0\n\t"
  16784. "UMLAL r12, r6, r10, r9\n\t"
  16785. "ADDS r12, r12, r7\n\t"
  16786. "STR r12, [%[a], #36]\n\t"
  16787. "ADC r6, r6, #0x0\n\t"
  16788. /* a[i+10] += m[10] * mu */
  16789. "LDR r9, [%[m], #40]\n\t"
  16790. "LDR r12, [%[a], #40]\n\t"
  16791. "MOV r7, #0x0\n\t"
  16792. "UMLAL r12, r7, r10, r9\n\t"
  16793. "ADDS r12, r12, r6\n\t"
  16794. "STR r12, [%[a], #40]\n\t"
  16795. "ADC r7, r7, #0x0\n\t"
  16796. /* a[i+11] += m[11] * mu */
  16797. "LDR r9, [%[m], #44]\n\t"
  16798. "LDR r12, [%[a], #44]\n\t"
  16799. "MOV r6, #0x0\n\t"
  16800. "UMLAL r12, r6, r10, r9\n\t"
  16801. "ADDS r12, r12, r7\n\t"
  16802. "STR r12, [%[a], #44]\n\t"
  16803. "ADC r6, r6, #0x0\n\t"
  16804. /* a[i+12] += m[12] * mu */
  16805. "LDR r9, [%[m], #48]\n\t"
  16806. "LDR r12, [%[a], #48]\n\t"
  16807. "MOV r7, #0x0\n\t"
  16808. "UMLAL r12, r7, r10, r9\n\t"
  16809. "ADDS r12, r12, r6\n\t"
  16810. "STR r12, [%[a], #48]\n\t"
  16811. "ADC r7, r7, #0x0\n\t"
  16812. /* a[i+13] += m[13] * mu */
  16813. "LDR r9, [%[m], #52]\n\t"
  16814. "LDR r12, [%[a], #52]\n\t"
  16815. "MOV r6, #0x0\n\t"
  16816. "UMLAL r12, r6, r10, r9\n\t"
  16817. "ADDS r12, r12, r7\n\t"
  16818. "STR r12, [%[a], #52]\n\t"
  16819. "ADC r6, r6, #0x0\n\t"
  16820. /* a[i+14] += m[14] * mu */
  16821. "LDR r9, [%[m], #56]\n\t"
  16822. "LDR r12, [%[a], #56]\n\t"
  16823. "MOV r7, #0x0\n\t"
  16824. "UMLAL r12, r7, r10, r9\n\t"
  16825. "ADDS r12, r12, r6\n\t"
  16826. "STR r12, [%[a], #56]\n\t"
  16827. "ADC r7, r7, #0x0\n\t"
  16828. /* a[i+15] += m[15] * mu */
  16829. "LDR r9, [%[m], #60]\n\t"
  16830. "LDR r12, [%[a], #60]\n\t"
  16831. "MOV r6, #0x0\n\t"
  16832. "UMLAL r12, r6, r10, r9\n\t"
  16833. "ADDS r12, r12, r7\n\t"
  16834. "STR r12, [%[a], #60]\n\t"
  16835. "ADC r6, r6, #0x0\n\t"
  16836. /* a[i+16] += m[16] * mu */
  16837. "LDR r9, [%[m], #64]\n\t"
  16838. "LDR r12, [%[a], #64]\n\t"
  16839. "MOV r7, #0x0\n\t"
  16840. "UMLAL r12, r7, r10, r9\n\t"
  16841. "ADDS r12, r12, r6\n\t"
  16842. "STR r12, [%[a], #64]\n\t"
  16843. "ADC r7, r7, #0x0\n\t"
  16844. /* a[i+17] += m[17] * mu */
  16845. "LDR r9, [%[m], #68]\n\t"
  16846. "LDR r12, [%[a], #68]\n\t"
  16847. "MOV r6, #0x0\n\t"
  16848. "UMLAL r12, r6, r10, r9\n\t"
  16849. "ADDS r12, r12, r7\n\t"
  16850. "STR r12, [%[a], #68]\n\t"
  16851. "ADC r6, r6, #0x0\n\t"
  16852. /* a[i+18] += m[18] * mu */
  16853. "LDR r9, [%[m], #72]\n\t"
  16854. "LDR r12, [%[a], #72]\n\t"
  16855. "MOV r7, #0x0\n\t"
  16856. "UMLAL r12, r7, r10, r9\n\t"
  16857. "ADDS r12, r12, r6\n\t"
  16858. "STR r12, [%[a], #72]\n\t"
  16859. "ADC r7, r7, #0x0\n\t"
  16860. /* a[i+19] += m[19] * mu */
  16861. "LDR r9, [%[m], #76]\n\t"
  16862. "LDR r12, [%[a], #76]\n\t"
  16863. "MOV r6, #0x0\n\t"
  16864. "UMLAL r12, r6, r10, r9\n\t"
  16865. "ADDS r12, r12, r7\n\t"
  16866. "STR r12, [%[a], #76]\n\t"
  16867. "ADC r6, r6, #0x0\n\t"
  16868. /* a[i+20] += m[20] * mu */
  16869. "LDR r9, [%[m], #80]\n\t"
  16870. "LDR r12, [%[a], #80]\n\t"
  16871. "MOV r7, #0x0\n\t"
  16872. "UMLAL r12, r7, r10, r9\n\t"
  16873. "ADDS r12, r12, r6\n\t"
  16874. "STR r12, [%[a], #80]\n\t"
  16875. "ADC r7, r7, #0x0\n\t"
  16876. /* a[i+21] += m[21] * mu */
  16877. "LDR r9, [%[m], #84]\n\t"
  16878. "LDR r12, [%[a], #84]\n\t"
  16879. "MOV r6, #0x0\n\t"
  16880. "UMLAL r12, r6, r10, r9\n\t"
  16881. "ADDS r12, r12, r7\n\t"
  16882. "STR r12, [%[a], #84]\n\t"
  16883. "ADC r6, r6, #0x0\n\t"
  16884. /* a[i+22] += m[22] * mu */
  16885. "LDR r9, [%[m], #88]\n\t"
  16886. "LDR r12, [%[a], #88]\n\t"
  16887. "MOV r7, #0x0\n\t"
  16888. "UMLAL r12, r7, r10, r9\n\t"
  16889. "ADDS r12, r12, r6\n\t"
  16890. "STR r12, [%[a], #88]\n\t"
  16891. "ADC r7, r7, #0x0\n\t"
  16892. /* a[i+23] += m[23] * mu */
  16893. "LDR r9, [%[m], #92]\n\t"
  16894. "LDR r12, [%[a], #92]\n\t"
  16895. "MOV r6, #0x0\n\t"
  16896. "UMLAL r12, r6, r10, r9\n\t"
  16897. "ADDS r12, r12, r7\n\t"
  16898. "STR r12, [%[a], #92]\n\t"
  16899. "ADC r6, r6, #0x0\n\t"
  16900. /* a[i+24] += m[24] * mu */
  16901. "LDR r9, [%[m], #96]\n\t"
  16902. "LDR r12, [%[a], #96]\n\t"
  16903. "MOV r7, #0x0\n\t"
  16904. "UMLAL r12, r7, r10, r9\n\t"
  16905. "ADDS r12, r12, r6\n\t"
  16906. "STR r12, [%[a], #96]\n\t"
  16907. "ADC r7, r7, #0x0\n\t"
  16908. /* a[i+25] += m[25] * mu */
  16909. "LDR r9, [%[m], #100]\n\t"
  16910. "LDR r12, [%[a], #100]\n\t"
  16911. "MOV r6, #0x0\n\t"
  16912. "UMLAL r12, r6, r10, r9\n\t"
  16913. "ADDS r12, r12, r7\n\t"
  16914. "STR r12, [%[a], #100]\n\t"
  16915. "ADC r6, r6, #0x0\n\t"
  16916. /* a[i+26] += m[26] * mu */
  16917. "LDR r9, [%[m], #104]\n\t"
  16918. "LDR r12, [%[a], #104]\n\t"
  16919. "MOV r7, #0x0\n\t"
  16920. "UMLAL r12, r7, r10, r9\n\t"
  16921. "ADDS r12, r12, r6\n\t"
  16922. "STR r12, [%[a], #104]\n\t"
  16923. "ADC r7, r7, #0x0\n\t"
  16924. /* a[i+27] += m[27] * mu */
  16925. "LDR r9, [%[m], #108]\n\t"
  16926. "LDR r12, [%[a], #108]\n\t"
  16927. "MOV r6, #0x0\n\t"
  16928. "UMLAL r12, r6, r10, r9\n\t"
  16929. "ADDS r12, r12, r7\n\t"
  16930. "STR r12, [%[a], #108]\n\t"
  16931. "ADC r6, r6, #0x0\n\t"
  16932. /* a[i+28] += m[28] * mu */
  16933. "LDR r9, [%[m], #112]\n\t"
  16934. "LDR r12, [%[a], #112]\n\t"
  16935. "MOV r7, #0x0\n\t"
  16936. "UMLAL r12, r7, r10, r9\n\t"
  16937. "ADDS r12, r12, r6\n\t"
  16938. "STR r12, [%[a], #112]\n\t"
  16939. "ADC r7, r7, #0x0\n\t"
  16940. /* a[i+29] += m[29] * mu */
  16941. "LDR r9, [%[m], #116]\n\t"
  16942. "LDR r12, [%[a], #116]\n\t"
  16943. "MOV r6, #0x0\n\t"
  16944. "UMLAL r12, r6, r10, r9\n\t"
  16945. "ADDS r12, r12, r7\n\t"
  16946. "STR r12, [%[a], #116]\n\t"
  16947. "ADC r6, r6, #0x0\n\t"
  16948. /* a[i+30] += m[30] * mu */
  16949. "LDR r9, [%[m], #120]\n\t"
  16950. "LDR r12, [%[a], #120]\n\t"
  16951. "MOV r7, #0x0\n\t"
  16952. "UMLAL r12, r7, r10, r9\n\t"
  16953. "ADDS r12, r12, r6\n\t"
  16954. "STR r12, [%[a], #120]\n\t"
  16955. "ADC r7, r7, #0x0\n\t"
  16956. /* a[i+31] += m[31] * mu */
  16957. "LDR r9, [%[m], #124]\n\t"
  16958. "LDR r12, [%[a], #124]\n\t"
  16959. "MOV r6, #0x0\n\t"
  16960. "UMLAL r12, r6, r10, r9\n\t"
  16961. "ADDS r12, r12, r7\n\t"
  16962. "STR r12, [%[a], #124]\n\t"
  16963. "ADC r6, r6, #0x0\n\t"
  16964. /* a[i+32] += m[32] * mu */
  16965. "LDR r9, [%[m], #128]\n\t"
  16966. "LDR r12, [%[a], #128]\n\t"
  16967. "MOV r7, #0x0\n\t"
  16968. "UMLAL r12, r7, r10, r9\n\t"
  16969. "ADDS r12, r12, r6\n\t"
  16970. "STR r12, [%[a], #128]\n\t"
  16971. "ADC r7, r7, #0x0\n\t"
  16972. /* a[i+33] += m[33] * mu */
  16973. "LDR r9, [%[m], #132]\n\t"
  16974. "LDR r12, [%[a], #132]\n\t"
  16975. "MOV r6, #0x0\n\t"
  16976. "UMLAL r12, r6, r10, r9\n\t"
  16977. "ADDS r12, r12, r7\n\t"
  16978. "STR r12, [%[a], #132]\n\t"
  16979. "ADC r6, r6, #0x0\n\t"
  16980. /* a[i+34] += m[34] * mu */
  16981. "LDR r9, [%[m], #136]\n\t"
  16982. "LDR r12, [%[a], #136]\n\t"
  16983. "MOV r7, #0x0\n\t"
  16984. "UMLAL r12, r7, r10, r9\n\t"
  16985. "ADDS r12, r12, r6\n\t"
  16986. "STR r12, [%[a], #136]\n\t"
  16987. "ADC r7, r7, #0x0\n\t"
  16988. /* a[i+35] += m[35] * mu */
  16989. "LDR r9, [%[m], #140]\n\t"
  16990. "LDR r12, [%[a], #140]\n\t"
  16991. "MOV r6, #0x0\n\t"
  16992. "UMLAL r12, r6, r10, r9\n\t"
  16993. "ADDS r12, r12, r7\n\t"
  16994. "STR r12, [%[a], #140]\n\t"
  16995. "ADC r6, r6, #0x0\n\t"
  16996. /* a[i+36] += m[36] * mu */
  16997. "LDR r9, [%[m], #144]\n\t"
  16998. "LDR r12, [%[a], #144]\n\t"
  16999. "MOV r7, #0x0\n\t"
  17000. "UMLAL r12, r7, r10, r9\n\t"
  17001. "ADDS r12, r12, r6\n\t"
  17002. "STR r12, [%[a], #144]\n\t"
  17003. "ADC r7, r7, #0x0\n\t"
  17004. /* a[i+37] += m[37] * mu */
  17005. "LDR r9, [%[m], #148]\n\t"
  17006. "LDR r12, [%[a], #148]\n\t"
  17007. "MOV r6, #0x0\n\t"
  17008. "UMLAL r12, r6, r10, r9\n\t"
  17009. "ADDS r12, r12, r7\n\t"
  17010. "STR r12, [%[a], #148]\n\t"
  17011. "ADC r6, r6, #0x0\n\t"
  17012. /* a[i+38] += m[38] * mu */
  17013. "LDR r9, [%[m], #152]\n\t"
  17014. "LDR r12, [%[a], #152]\n\t"
  17015. "MOV r7, #0x0\n\t"
  17016. "UMLAL r12, r7, r10, r9\n\t"
  17017. "ADDS r12, r12, r6\n\t"
  17018. "STR r12, [%[a], #152]\n\t"
  17019. "ADC r7, r7, #0x0\n\t"
  17020. /* a[i+39] += m[39] * mu */
  17021. "LDR r9, [%[m], #156]\n\t"
  17022. "LDR r12, [%[a], #156]\n\t"
  17023. "MOV r6, #0x0\n\t"
  17024. "UMLAL r12, r6, r10, r9\n\t"
  17025. "ADDS r12, r12, r7\n\t"
  17026. "STR r12, [%[a], #156]\n\t"
  17027. "ADC r6, r6, #0x0\n\t"
  17028. /* a[i+40] += m[40] * mu */
  17029. "LDR r9, [%[m], #160]\n\t"
  17030. "LDR r12, [%[a], #160]\n\t"
  17031. "MOV r7, #0x0\n\t"
  17032. "UMLAL r12, r7, r10, r9\n\t"
  17033. "ADDS r12, r12, r6\n\t"
  17034. "STR r12, [%[a], #160]\n\t"
  17035. "ADC r7, r7, #0x0\n\t"
  17036. /* a[i+41] += m[41] * mu */
  17037. "LDR r9, [%[m], #164]\n\t"
  17038. "LDR r12, [%[a], #164]\n\t"
  17039. "MOV r6, #0x0\n\t"
  17040. "UMLAL r12, r6, r10, r9\n\t"
  17041. "ADDS r12, r12, r7\n\t"
  17042. "STR r12, [%[a], #164]\n\t"
  17043. "ADC r6, r6, #0x0\n\t"
  17044. /* a[i+42] += m[42] * mu */
  17045. "LDR r9, [%[m], #168]\n\t"
  17046. "LDR r12, [%[a], #168]\n\t"
  17047. "MOV r7, #0x0\n\t"
  17048. "UMLAL r12, r7, r10, r9\n\t"
  17049. "ADDS r12, r12, r6\n\t"
  17050. "STR r12, [%[a], #168]\n\t"
  17051. "ADC r7, r7, #0x0\n\t"
  17052. /* a[i+43] += m[43] * mu */
  17053. "LDR r9, [%[m], #172]\n\t"
  17054. "LDR r12, [%[a], #172]\n\t"
  17055. "MOV r6, #0x0\n\t"
  17056. "UMLAL r12, r6, r10, r9\n\t"
  17057. "ADDS r12, r12, r7\n\t"
  17058. "STR r12, [%[a], #172]\n\t"
  17059. "ADC r6, r6, #0x0\n\t"
  17060. /* a[i+44] += m[44] * mu */
  17061. "LDR r9, [%[m], #176]\n\t"
  17062. "LDR r12, [%[a], #176]\n\t"
  17063. "MOV r7, #0x0\n\t"
  17064. "UMLAL r12, r7, r10, r9\n\t"
  17065. "ADDS r12, r12, r6\n\t"
  17066. "STR r12, [%[a], #176]\n\t"
  17067. "ADC r7, r7, #0x0\n\t"
  17068. /* a[i+45] += m[45] * mu */
  17069. "LDR r9, [%[m], #180]\n\t"
  17070. "LDR r12, [%[a], #180]\n\t"
  17071. "MOV r6, #0x0\n\t"
  17072. "UMLAL r12, r6, r10, r9\n\t"
  17073. "ADDS r12, r12, r7\n\t"
  17074. "STR r12, [%[a], #180]\n\t"
  17075. "ADC r6, r6, #0x0\n\t"
  17076. /* a[i+46] += m[46] * mu */
  17077. "LDR r9, [%[m], #184]\n\t"
  17078. "LDR r12, [%[a], #184]\n\t"
  17079. "MOV r7, #0x0\n\t"
  17080. "UMLAL r12, r7, r10, r9\n\t"
  17081. "ADDS r12, r12, r6\n\t"
  17082. "STR r12, [%[a], #184]\n\t"
  17083. "ADC r7, r7, #0x0\n\t"
  17084. /* a[i+47] += m[47] * mu */
  17085. "LDR r9, [%[m], #188]\n\t"
  17086. "LDR r12, [%[a], #188]\n\t"
  17087. "MOV r6, #0x0\n\t"
  17088. "UMLAL r12, r6, r10, r9\n\t"
  17089. "ADDS r12, r12, r7\n\t"
  17090. "STR r12, [%[a], #188]\n\t"
  17091. "ADC r6, r6, #0x0\n\t"
  17092. /* a[i+48] += m[48] * mu */
  17093. "LDR r9, [%[m], #192]\n\t"
  17094. "LDR r12, [%[a], #192]\n\t"
  17095. "MOV r7, #0x0\n\t"
  17096. "UMLAL r12, r7, r10, r9\n\t"
  17097. "ADDS r12, r12, r6\n\t"
  17098. "STR r12, [%[a], #192]\n\t"
  17099. "ADC r7, r7, #0x0\n\t"
  17100. /* a[i+49] += m[49] * mu */
  17101. "LDR r9, [%[m], #196]\n\t"
  17102. "LDR r12, [%[a], #196]\n\t"
  17103. "MOV r6, #0x0\n\t"
  17104. "UMLAL r12, r6, r10, r9\n\t"
  17105. "ADDS r12, r12, r7\n\t"
  17106. "STR r12, [%[a], #196]\n\t"
  17107. "ADC r6, r6, #0x0\n\t"
  17108. /* a[i+50] += m[50] * mu */
  17109. "LDR r9, [%[m], #200]\n\t"
  17110. "LDR r12, [%[a], #200]\n\t"
  17111. "MOV r7, #0x0\n\t"
  17112. "UMLAL r12, r7, r10, r9\n\t"
  17113. "ADDS r12, r12, r6\n\t"
  17114. "STR r12, [%[a], #200]\n\t"
  17115. "ADC r7, r7, #0x0\n\t"
  17116. /* a[i+51] += m[51] * mu */
  17117. "LDR r9, [%[m], #204]\n\t"
  17118. "LDR r12, [%[a], #204]\n\t"
  17119. "MOV r6, #0x0\n\t"
  17120. "UMLAL r12, r6, r10, r9\n\t"
  17121. "ADDS r12, r12, r7\n\t"
  17122. "STR r12, [%[a], #204]\n\t"
  17123. "ADC r6, r6, #0x0\n\t"
  17124. /* a[i+52] += m[52] * mu */
  17125. "LDR r9, [%[m], #208]\n\t"
  17126. "LDR r12, [%[a], #208]\n\t"
  17127. "MOV r7, #0x0\n\t"
  17128. "UMLAL r12, r7, r10, r9\n\t"
  17129. "ADDS r12, r12, r6\n\t"
  17130. "STR r12, [%[a], #208]\n\t"
  17131. "ADC r7, r7, #0x0\n\t"
  17132. /* a[i+53] += m[53] * mu */
  17133. "LDR r9, [%[m], #212]\n\t"
  17134. "LDR r12, [%[a], #212]\n\t"
  17135. "MOV r6, #0x0\n\t"
  17136. "UMLAL r12, r6, r10, r9\n\t"
  17137. "ADDS r12, r12, r7\n\t"
  17138. "STR r12, [%[a], #212]\n\t"
  17139. "ADC r6, r6, #0x0\n\t"
  17140. /* a[i+54] += m[54] * mu */
  17141. "LDR r9, [%[m], #216]\n\t"
  17142. "LDR r12, [%[a], #216]\n\t"
  17143. "MOV r7, #0x0\n\t"
  17144. "UMLAL r12, r7, r10, r9\n\t"
  17145. "ADDS r12, r12, r6\n\t"
  17146. "STR r12, [%[a], #216]\n\t"
  17147. "ADC r7, r7, #0x0\n\t"
  17148. /* a[i+55] += m[55] * mu */
  17149. "LDR r9, [%[m], #220]\n\t"
  17150. "LDR r12, [%[a], #220]\n\t"
  17151. "MOV r6, #0x0\n\t"
  17152. "UMLAL r12, r6, r10, r9\n\t"
  17153. "ADDS r12, r12, r7\n\t"
  17154. "STR r12, [%[a], #220]\n\t"
  17155. "ADC r6, r6, #0x0\n\t"
  17156. /* a[i+56] += m[56] * mu */
  17157. "LDR r9, [%[m], #224]\n\t"
  17158. "LDR r12, [%[a], #224]\n\t"
  17159. "MOV r7, #0x0\n\t"
  17160. "UMLAL r12, r7, r10, r9\n\t"
  17161. "ADDS r12, r12, r6\n\t"
  17162. "STR r12, [%[a], #224]\n\t"
  17163. "ADC r7, r7, #0x0\n\t"
  17164. /* a[i+57] += m[57] * mu */
  17165. "LDR r9, [%[m], #228]\n\t"
  17166. "LDR r12, [%[a], #228]\n\t"
  17167. "MOV r6, #0x0\n\t"
  17168. "UMLAL r12, r6, r10, r9\n\t"
  17169. "ADDS r12, r12, r7\n\t"
  17170. "STR r12, [%[a], #228]\n\t"
  17171. "ADC r6, r6, #0x0\n\t"
  17172. /* a[i+58] += m[58] * mu */
  17173. "LDR r9, [%[m], #232]\n\t"
  17174. "LDR r12, [%[a], #232]\n\t"
  17175. "MOV r7, #0x0\n\t"
  17176. "UMLAL r12, r7, r10, r9\n\t"
  17177. "ADDS r12, r12, r6\n\t"
  17178. "STR r12, [%[a], #232]\n\t"
  17179. "ADC r7, r7, #0x0\n\t"
  17180. /* a[i+59] += m[59] * mu */
  17181. "LDR r9, [%[m], #236]\n\t"
  17182. "LDR r12, [%[a], #236]\n\t"
  17183. "MOV r6, #0x0\n\t"
  17184. "UMLAL r12, r6, r10, r9\n\t"
  17185. "ADDS r12, r12, r7\n\t"
  17186. "STR r12, [%[a], #236]\n\t"
  17187. "ADC r6, r6, #0x0\n\t"
  17188. /* a[i+60] += m[60] * mu */
  17189. "LDR r9, [%[m], #240]\n\t"
  17190. "LDR r12, [%[a], #240]\n\t"
  17191. "MOV r7, #0x0\n\t"
  17192. "UMLAL r12, r7, r10, r9\n\t"
  17193. "ADDS r12, r12, r6\n\t"
  17194. "STR r12, [%[a], #240]\n\t"
  17195. "ADC r7, r7, #0x0\n\t"
  17196. /* a[i+61] += m[61] * mu */
  17197. "LDR r9, [%[m], #244]\n\t"
  17198. "LDR r12, [%[a], #244]\n\t"
  17199. "MOV r6, #0x0\n\t"
  17200. "UMLAL r12, r6, r10, r9\n\t"
  17201. "ADDS r12, r12, r7\n\t"
  17202. "STR r12, [%[a], #244]\n\t"
  17203. "ADC r6, r6, #0x0\n\t"
  17204. /* a[i+62] += m[62] * mu */
  17205. "LDR r9, [%[m], #248]\n\t"
  17206. "LDR r12, [%[a], #248]\n\t"
  17207. "MOV r7, #0x0\n\t"
  17208. "UMLAL r12, r7, r10, r9\n\t"
  17209. "ADDS r12, r12, r6\n\t"
  17210. "STR r12, [%[a], #248]\n\t"
  17211. "ADC r7, r7, #0x0\n\t"
  17212. /* a[i+63] += m[63] * mu */
  17213. "LDR r9, [%[m], #252]\n\t"
  17214. "LDR r12, [%[a], #252]\n\t"
  17215. "MOV r6, #0x0\n\t"
  17216. "UMLAL r12, r6, r10, r9\n\t"
  17217. "ADDS r12, r12, r7\n\t"
  17218. "STR r12, [%[a], #252]\n\t"
  17219. "ADC r6, r6, #0x0\n\t"
  17220. /* a[i+64] += m[64] * mu */
  17221. "LDR r9, [%[m], #256]\n\t"
  17222. "LDR r12, [%[a], #256]\n\t"
  17223. "MOV r7, #0x0\n\t"
  17224. "UMLAL r12, r7, r10, r9\n\t"
  17225. "ADDS r12, r12, r6\n\t"
  17226. "STR r12, [%[a], #256]\n\t"
  17227. "ADC r7, r7, #0x0\n\t"
  17228. /* a[i+65] += m[65] * mu */
  17229. "LDR r9, [%[m], #260]\n\t"
  17230. "LDR r12, [%[a], #260]\n\t"
  17231. "MOV r6, #0x0\n\t"
  17232. "UMLAL r12, r6, r10, r9\n\t"
  17233. "ADDS r12, r12, r7\n\t"
  17234. "STR r12, [%[a], #260]\n\t"
  17235. "ADC r6, r6, #0x0\n\t"
  17236. /* a[i+66] += m[66] * mu */
  17237. "LDR r9, [%[m], #264]\n\t"
  17238. "LDR r12, [%[a], #264]\n\t"
  17239. "MOV r7, #0x0\n\t"
  17240. "UMLAL r12, r7, r10, r9\n\t"
  17241. "ADDS r12, r12, r6\n\t"
  17242. "STR r12, [%[a], #264]\n\t"
  17243. "ADC r7, r7, #0x0\n\t"
  17244. /* a[i+67] += m[67] * mu */
  17245. "LDR r9, [%[m], #268]\n\t"
  17246. "LDR r12, [%[a], #268]\n\t"
  17247. "MOV r6, #0x0\n\t"
  17248. "UMLAL r12, r6, r10, r9\n\t"
  17249. "ADDS r12, r12, r7\n\t"
  17250. "STR r12, [%[a], #268]\n\t"
  17251. "ADC r6, r6, #0x0\n\t"
  17252. /* a[i+68] += m[68] * mu */
  17253. "LDR r9, [%[m], #272]\n\t"
  17254. "LDR r12, [%[a], #272]\n\t"
  17255. "MOV r7, #0x0\n\t"
  17256. "UMLAL r12, r7, r10, r9\n\t"
  17257. "ADDS r12, r12, r6\n\t"
  17258. "STR r12, [%[a], #272]\n\t"
  17259. "ADC r7, r7, #0x0\n\t"
  17260. /* a[i+69] += m[69] * mu */
  17261. "LDR r9, [%[m], #276]\n\t"
  17262. "LDR r12, [%[a], #276]\n\t"
  17263. "MOV r6, #0x0\n\t"
  17264. "UMLAL r12, r6, r10, r9\n\t"
  17265. "ADDS r12, r12, r7\n\t"
  17266. "STR r12, [%[a], #276]\n\t"
  17267. "ADC r6, r6, #0x0\n\t"
  17268. /* a[i+70] += m[70] * mu */
  17269. "LDR r9, [%[m], #280]\n\t"
  17270. "LDR r12, [%[a], #280]\n\t"
  17271. "MOV r7, #0x0\n\t"
  17272. "UMLAL r12, r7, r10, r9\n\t"
  17273. "ADDS r12, r12, r6\n\t"
  17274. "STR r12, [%[a], #280]\n\t"
  17275. "ADC r7, r7, #0x0\n\t"
  17276. /* a[i+71] += m[71] * mu */
  17277. "LDR r9, [%[m], #284]\n\t"
  17278. "LDR r12, [%[a], #284]\n\t"
  17279. "MOV r6, #0x0\n\t"
  17280. "UMLAL r12, r6, r10, r9\n\t"
  17281. "ADDS r12, r12, r7\n\t"
  17282. "STR r12, [%[a], #284]\n\t"
  17283. "ADC r6, r6, #0x0\n\t"
  17284. /* a[i+72] += m[72] * mu */
  17285. "LDR r9, [%[m], #288]\n\t"
  17286. "LDR r12, [%[a], #288]\n\t"
  17287. "MOV r7, #0x0\n\t"
  17288. "UMLAL r12, r7, r10, r9\n\t"
  17289. "ADDS r12, r12, r6\n\t"
  17290. "STR r12, [%[a], #288]\n\t"
  17291. "ADC r7, r7, #0x0\n\t"
  17292. /* a[i+73] += m[73] * mu */
  17293. "LDR r9, [%[m], #292]\n\t"
  17294. "LDR r12, [%[a], #292]\n\t"
  17295. "MOV r6, #0x0\n\t"
  17296. "UMLAL r12, r6, r10, r9\n\t"
  17297. "ADDS r12, r12, r7\n\t"
  17298. "STR r12, [%[a], #292]\n\t"
  17299. "ADC r6, r6, #0x0\n\t"
  17300. /* a[i+74] += m[74] * mu */
  17301. "LDR r9, [%[m], #296]\n\t"
  17302. "LDR r12, [%[a], #296]\n\t"
  17303. "MOV r7, #0x0\n\t"
  17304. "UMLAL r12, r7, r10, r9\n\t"
  17305. "ADDS r12, r12, r6\n\t"
  17306. "STR r12, [%[a], #296]\n\t"
  17307. "ADC r7, r7, #0x0\n\t"
  17308. /* a[i+75] += m[75] * mu */
  17309. "LDR r9, [%[m], #300]\n\t"
  17310. "LDR r12, [%[a], #300]\n\t"
  17311. "MOV r6, #0x0\n\t"
  17312. "UMLAL r12, r6, r10, r9\n\t"
  17313. "ADDS r12, r12, r7\n\t"
  17314. "STR r12, [%[a], #300]\n\t"
  17315. "ADC r6, r6, #0x0\n\t"
  17316. /* a[i+76] += m[76] * mu */
  17317. "LDR r9, [%[m], #304]\n\t"
  17318. "LDR r12, [%[a], #304]\n\t"
  17319. "MOV r7, #0x0\n\t"
  17320. "UMLAL r12, r7, r10, r9\n\t"
  17321. "ADDS r12, r12, r6\n\t"
  17322. "STR r12, [%[a], #304]\n\t"
  17323. "ADC r7, r7, #0x0\n\t"
  17324. /* a[i+77] += m[77] * mu */
  17325. "LDR r9, [%[m], #308]\n\t"
  17326. "LDR r12, [%[a], #308]\n\t"
  17327. "MOV r6, #0x0\n\t"
  17328. "UMLAL r12, r6, r10, r9\n\t"
  17329. "ADDS r12, r12, r7\n\t"
  17330. "STR r12, [%[a], #308]\n\t"
  17331. "ADC r6, r6, #0x0\n\t"
  17332. /* a[i+78] += m[78] * mu */
  17333. "LDR r9, [%[m], #312]\n\t"
  17334. "LDR r12, [%[a], #312]\n\t"
  17335. "MOV r7, #0x0\n\t"
  17336. "UMLAL r12, r7, r10, r9\n\t"
  17337. "ADDS r12, r12, r6\n\t"
  17338. "STR r12, [%[a], #312]\n\t"
  17339. "ADC r7, r7, #0x0\n\t"
  17340. /* a[i+79] += m[79] * mu */
  17341. "LDR r9, [%[m], #316]\n\t"
  17342. "LDR r12, [%[a], #316]\n\t"
  17343. "MOV r6, #0x0\n\t"
  17344. "UMLAL r12, r6, r10, r9\n\t"
  17345. "ADDS r12, r12, r7\n\t"
  17346. "STR r12, [%[a], #316]\n\t"
  17347. "ADC r6, r6, #0x0\n\t"
  17348. /* a[i+80] += m[80] * mu */
  17349. "LDR r9, [%[m], #320]\n\t"
  17350. "LDR r12, [%[a], #320]\n\t"
  17351. "MOV r7, #0x0\n\t"
  17352. "UMLAL r12, r7, r10, r9\n\t"
  17353. "ADDS r12, r12, r6\n\t"
  17354. "STR r12, [%[a], #320]\n\t"
  17355. "ADC r7, r7, #0x0\n\t"
  17356. /* a[i+81] += m[81] * mu */
  17357. "LDR r9, [%[m], #324]\n\t"
  17358. "LDR r12, [%[a], #324]\n\t"
  17359. "MOV r6, #0x0\n\t"
  17360. "UMLAL r12, r6, r10, r9\n\t"
  17361. "ADDS r12, r12, r7\n\t"
  17362. "STR r12, [%[a], #324]\n\t"
  17363. "ADC r6, r6, #0x0\n\t"
  17364. /* a[i+82] += m[82] * mu */
  17365. "LDR r9, [%[m], #328]\n\t"
  17366. "LDR r12, [%[a], #328]\n\t"
  17367. "MOV r7, #0x0\n\t"
  17368. "UMLAL r12, r7, r10, r9\n\t"
  17369. "ADDS r12, r12, r6\n\t"
  17370. "STR r12, [%[a], #328]\n\t"
  17371. "ADC r7, r7, #0x0\n\t"
  17372. /* a[i+83] += m[83] * mu */
  17373. "LDR r9, [%[m], #332]\n\t"
  17374. "LDR r12, [%[a], #332]\n\t"
  17375. "MOV r6, #0x0\n\t"
  17376. "UMLAL r12, r6, r10, r9\n\t"
  17377. "ADDS r12, r12, r7\n\t"
  17378. "STR r12, [%[a], #332]\n\t"
  17379. "ADC r6, r6, #0x0\n\t"
  17380. /* a[i+84] += m[84] * mu */
  17381. "LDR r9, [%[m], #336]\n\t"
  17382. "LDR r12, [%[a], #336]\n\t"
  17383. "MOV r7, #0x0\n\t"
  17384. "UMLAL r12, r7, r10, r9\n\t"
  17385. "ADDS r12, r12, r6\n\t"
  17386. "STR r12, [%[a], #336]\n\t"
  17387. "ADC r7, r7, #0x0\n\t"
  17388. /* a[i+85] += m[85] * mu */
  17389. "LDR r9, [%[m], #340]\n\t"
  17390. "LDR r12, [%[a], #340]\n\t"
  17391. "MOV r6, #0x0\n\t"
  17392. "UMLAL r12, r6, r10, r9\n\t"
  17393. "ADDS r12, r12, r7\n\t"
  17394. "STR r12, [%[a], #340]\n\t"
  17395. "ADC r6, r6, #0x0\n\t"
  17396. /* a[i+86] += m[86] * mu */
  17397. "LDR r9, [%[m], #344]\n\t"
  17398. "LDR r12, [%[a], #344]\n\t"
  17399. "MOV r7, #0x0\n\t"
  17400. "UMLAL r12, r7, r10, r9\n\t"
  17401. "ADDS r12, r12, r6\n\t"
  17402. "STR r12, [%[a], #344]\n\t"
  17403. "ADC r7, r7, #0x0\n\t"
  17404. /* a[i+87] += m[87] * mu */
  17405. "LDR r9, [%[m], #348]\n\t"
  17406. "LDR r12, [%[a], #348]\n\t"
  17407. "MOV r6, #0x0\n\t"
  17408. "UMLAL r12, r6, r10, r9\n\t"
  17409. "ADDS r12, r12, r7\n\t"
  17410. "STR r12, [%[a], #348]\n\t"
  17411. "ADC r6, r6, #0x0\n\t"
  17412. /* a[i+88] += m[88] * mu */
  17413. "LDR r9, [%[m], #352]\n\t"
  17414. "LDR r12, [%[a], #352]\n\t"
  17415. "MOV r7, #0x0\n\t"
  17416. "UMLAL r12, r7, r10, r9\n\t"
  17417. "ADDS r12, r12, r6\n\t"
  17418. "STR r12, [%[a], #352]\n\t"
  17419. "ADC r7, r7, #0x0\n\t"
  17420. /* a[i+89] += m[89] * mu */
  17421. "LDR r9, [%[m], #356]\n\t"
  17422. "LDR r12, [%[a], #356]\n\t"
  17423. "MOV r6, #0x0\n\t"
  17424. "UMLAL r12, r6, r10, r9\n\t"
  17425. "ADDS r12, r12, r7\n\t"
  17426. "STR r12, [%[a], #356]\n\t"
  17427. "ADC r6, r6, #0x0\n\t"
  17428. /* a[i+90] += m[90] * mu */
  17429. "LDR r9, [%[m], #360]\n\t"
  17430. "LDR r12, [%[a], #360]\n\t"
  17431. "MOV r7, #0x0\n\t"
  17432. "UMLAL r12, r7, r10, r9\n\t"
  17433. "ADDS r12, r12, r6\n\t"
  17434. "STR r12, [%[a], #360]\n\t"
  17435. "ADC r7, r7, #0x0\n\t"
  17436. /* a[i+91] += m[91] * mu */
  17437. "LDR r9, [%[m], #364]\n\t"
  17438. "LDR r12, [%[a], #364]\n\t"
  17439. "MOV r6, #0x0\n\t"
  17440. "UMLAL r12, r6, r10, r9\n\t"
  17441. "ADDS r12, r12, r7\n\t"
  17442. "STR r12, [%[a], #364]\n\t"
  17443. "ADC r6, r6, #0x0\n\t"
  17444. /* a[i+92] += m[92] * mu */
  17445. "LDR r9, [%[m], #368]\n\t"
  17446. "LDR r12, [%[a], #368]\n\t"
  17447. "MOV r7, #0x0\n\t"
  17448. "UMLAL r12, r7, r10, r9\n\t"
  17449. "ADDS r12, r12, r6\n\t"
  17450. "STR r12, [%[a], #368]\n\t"
  17451. "ADC r7, r7, #0x0\n\t"
  17452. /* a[i+93] += m[93] * mu */
  17453. "LDR r9, [%[m], #372]\n\t"
  17454. "LDR r12, [%[a], #372]\n\t"
  17455. "MOV r6, #0x0\n\t"
  17456. "UMLAL r12, r6, r10, r9\n\t"
  17457. "ADDS r12, r12, r7\n\t"
  17458. "STR r12, [%[a], #372]\n\t"
  17459. "ADC r6, r6, #0x0\n\t"
  17460. /* a[i+94] += m[94] * mu */
  17461. "LDR r9, [%[m], #376]\n\t"
  17462. "LDR r12, [%[a], #376]\n\t"
  17463. "MOV r7, #0x0\n\t"
  17464. "UMLAL r12, r7, r10, r9\n\t"
  17465. "ADDS r12, r12, r6\n\t"
  17466. "STR r12, [%[a], #376]\n\t"
  17467. "ADC r7, r7, #0x0\n\t"
  17468. /* a[i+95] += m[95] * mu */
  17469. "LDR r9, [%[m], #380]\n\t"
  17470. "LDR r12, [%[a], #380]\n\t"
  17471. "UMULL r8, r9, r10, r9\n\t"
  17472. "ADDS r7, r7, r8\n\t"
  17473. "ADCS r6, r9, r3\n\t"
  17474. "MOV r3, #0x0\n\t"
  17475. "ADC r3, r3, r3\n\t"
  17476. "ADDS r12, r12, r7\n\t"
  17477. "STR r12, [%[a], #380]\n\t"
  17478. "LDR r12, [%[a], #384]\n\t"
  17479. "ADCS r12, r12, r6\n\t"
  17480. "STR r12, [%[a], #384]\n\t"
  17481. "ADC r3, r3, #0x0\n\t"
  17482. /* i += 1 */
  17483. "ADD r11, r11, #0x4\n\t"
  17484. "ADD %[a], %[a], #0x4\n\t"
  17485. "CMP r11, #0x180\n\t"
  17486. #ifdef __GNUC__
  17487. "BLT L_sp_3072_mont_reduce_96_word\n\t"
  17488. #else
  17489. "BLT.W L_sp_3072_mont_reduce_96_word\n\t"
  17490. #endif
  17491. /* Loop Done */
  17492. "STR r4, [%[a]]\n\t"
  17493. "STR r5, [%[a], #4]\n\t"
  17494. "MOV %[mp], r3\n\t"
  17495. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  17496. :
  17497. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  17498. );
  17499. sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - mp);
  17500. }
  17501. #else
  17502. /* Reduce the number back to 3072 bits using Montgomery reduction.
  17503. *
  17504. * a A single precision number to reduce in place.
  17505. * m The single precision number representing the modulus.
  17506. * mp The digit representing the negative inverse of m mod 2^n.
  17507. */
  17508. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  17509. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  17510. #else
  17511. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, sp_digit mp)
  17512. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  17513. {
  17514. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  17515. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  17516. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  17517. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  17518. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  17519. __asm__ __volatile__ (
  17520. "LDR r11, [%[m]]\n\t"
  17521. /* i = 0 */
  17522. "MOV r9, #0x0\n\t"
  17523. /* ca = 0 */
  17524. "MOV r3, #0x0\n\t"
  17525. "\n"
  17526. "L_sp_3072_mont_reduce_96_word:\n\t"
  17527. /* mu = a[i] * mp */
  17528. "LDR r10, [%[a]]\n\t"
  17529. "MUL r8, %[mp], r10\n\t"
  17530. /* j = 0 */
  17531. "MOV r12, #0x0\n\t"
  17532. "MOV r4, #0x0\n\t"
  17533. "\n"
  17534. "L_sp_3072_mont_reduce_96_mul:\n\t"
  17535. /* a[i+j+0] += m[j+0] * mu */
  17536. "LDR r7, [%[m], r12]\n\t"
  17537. "LDR r10, [%[a], r12]\n\t"
  17538. "MOV r5, #0x0\n\t"
  17539. "UMLAL r10, r5, r8, r7\n\t"
  17540. "ADDS r10, r10, r4\n\t"
  17541. "STR r10, [%[a], r12]\n\t"
  17542. "ADC r4, r5, #0x0\n\t"
  17543. /* j += 1 */
  17544. "ADD r12, r12, #0x4\n\t"
  17545. /* a[i+j+1] += m[j+1] * mu */
  17546. "LDR r7, [%[m], r12]\n\t"
  17547. "LDR r10, [%[a], r12]\n\t"
  17548. "MOV r5, #0x0\n\t"
  17549. "UMLAL r10, r5, r8, r7\n\t"
  17550. "ADDS r10, r10, r4\n\t"
  17551. "STR r10, [%[a], r12]\n\t"
  17552. "ADC r4, r5, #0x0\n\t"
  17553. /* j += 1 */
  17554. "ADD r12, r12, #0x4\n\t"
  17555. /* a[i+j+2] += m[j+2] * mu */
  17556. "LDR r7, [%[m], r12]\n\t"
  17557. "LDR r10, [%[a], r12]\n\t"
  17558. "MOV r5, #0x0\n\t"
  17559. "UMLAL r10, r5, r8, r7\n\t"
  17560. "ADDS r10, r10, r4\n\t"
  17561. "STR r10, [%[a], r12]\n\t"
  17562. "ADC r4, r5, #0x0\n\t"
  17563. /* j += 1 */
  17564. "ADD r12, r12, #0x4\n\t"
  17565. /* a[i+j+3] += m[j+3] * mu */
  17566. "LDR r7, [%[m], r12]\n\t"
  17567. "LDR r10, [%[a], r12]\n\t"
  17568. "MOV r5, #0x0\n\t"
  17569. "UMLAL r10, r5, r8, r7\n\t"
  17570. "ADDS r10, r10, r4\n\t"
  17571. "STR r10, [%[a], r12]\n\t"
  17572. "ADC r4, r5, #0x0\n\t"
  17573. /* j += 1 */
  17574. "ADD r12, r12, #0x4\n\t"
  17575. "CMP r12, #0x180\n\t"
  17576. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  17577. "BLT L_sp_3072_mont_reduce_96_mul\n\t"
  17578. #else
  17579. "BLT.N L_sp_3072_mont_reduce_96_mul\n\t"
  17580. #endif
  17581. "LDR r10, [%[a], #384]\n\t"
  17582. "ADDS r4, r4, r3\n\t"
  17583. "MOV r3, #0x0\n\t"
  17584. "ADC r3, r3, #0x0\n\t"
  17585. "ADDS r10, r10, r4\n\t"
  17586. "ADC r3, r3, r3\n\t"
  17587. "STR r10, [%[a], #384]\n\t"
  17588. /* i += 1 */
  17589. "ADD r9, r9, #0x4\n\t"
  17590. "ADD %[a], %[a], #0x4\n\t"
  17591. "CMP r9, #0x180\n\t"
  17592. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  17593. "BLT L_sp_3072_mont_reduce_96_word\n\t"
  17594. #else
  17595. "BLT.N L_sp_3072_mont_reduce_96_word\n\t"
  17596. #endif
  17597. /* Loop Done */
  17598. "MOV %[mp], r3\n\t"
  17599. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  17600. :
  17601. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  17602. );
  17603. sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - mp);
  17604. }
  17605. #endif /* !WOLFSSL_SP_SMALL */
  17606. #else
  17607. #ifndef WOLFSSL_SP_SMALL
  17608. /* Reduce the number back to 3072 bits using Montgomery reduction.
  17609. *
  17610. * a A single precision number to reduce in place.
  17611. * m The single precision number representing the modulus.
  17612. * mp The digit representing the negative inverse of m mod 2^n.
  17613. */
  17614. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  17615. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  17616. #else
  17617. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, sp_digit mp)
  17618. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  17619. {
  17620. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  17621. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  17622. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  17623. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  17624. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  17625. __asm__ __volatile__ (
  17626. /* i = 0 */
  17627. "MOV r4, #0x0\n\t"
  17628. "MOV r5, #0x0\n\t"
  17629. "LDR r6, [%[a]]\n\t"
  17630. "LDR r7, [%[a], #4]\n\t"
  17631. "LDR r8, [%[a], #8]\n\t"
  17632. "LDR r9, [%[a], #12]\n\t"
  17633. "LDR r10, [%[a], #16]\n\t"
  17634. "\n"
  17635. "L_sp_3072_mont_reduce_96_word:\n\t"
  17636. /* mu = a[i] * mp */
  17637. "MUL lr, %[mp], r6\n\t"
  17638. /* a[i+0] += m[0] * mu */
  17639. "LDR r12, [%[m]]\n\t"
  17640. "MOV r3, #0x0\n\t"
  17641. "UMAAL r6, r3, lr, r12\n\t"
  17642. /* a[i+1] += m[1] * mu */
  17643. "LDR r12, [%[m], #4]\n\t"
  17644. "MOV r6, r7\n\t"
  17645. "UMAAL r6, r3, lr, r12\n\t"
  17646. /* a[i+2] += m[2] * mu */
  17647. "LDR r12, [%[m], #8]\n\t"
  17648. "MOV r7, r8\n\t"
  17649. "UMAAL r7, r3, lr, r12\n\t"
  17650. /* a[i+3] += m[3] * mu */
  17651. "LDR r12, [%[m], #12]\n\t"
  17652. "MOV r8, r9\n\t"
  17653. "UMAAL r8, r3, lr, r12\n\t"
  17654. /* a[i+4] += m[4] * mu */
  17655. "LDR r12, [%[m], #16]\n\t"
  17656. "MOV r9, r10\n\t"
  17657. "UMAAL r9, r3, lr, r12\n\t"
  17658. /* a[i+5] += m[5] * mu */
  17659. "LDR r12, [%[m], #20]\n\t"
  17660. "LDR r10, [%[a], #20]\n\t"
  17661. "UMAAL r10, r3, lr, r12\n\t"
  17662. /* a[i+6] += m[6] * mu */
  17663. "LDR r12, [%[m], #24]\n\t"
  17664. "LDR r11, [%[a], #24]\n\t"
  17665. "UMAAL r11, r3, lr, r12\n\t"
  17666. "STR r11, [%[a], #24]\n\t"
  17667. /* a[i+7] += m[7] * mu */
  17668. "LDR r12, [%[m], #28]\n\t"
  17669. "LDR r11, [%[a], #28]\n\t"
  17670. "UMAAL r11, r3, lr, r12\n\t"
  17671. "STR r11, [%[a], #28]\n\t"
  17672. /* a[i+8] += m[8] * mu */
  17673. "LDR r12, [%[m], #32]\n\t"
  17674. "LDR r11, [%[a], #32]\n\t"
  17675. "UMAAL r11, r3, lr, r12\n\t"
  17676. "STR r11, [%[a], #32]\n\t"
  17677. /* a[i+9] += m[9] * mu */
  17678. "LDR r12, [%[m], #36]\n\t"
  17679. "LDR r11, [%[a], #36]\n\t"
  17680. "UMAAL r11, r3, lr, r12\n\t"
  17681. "STR r11, [%[a], #36]\n\t"
  17682. /* a[i+10] += m[10] * mu */
  17683. "LDR r12, [%[m], #40]\n\t"
  17684. "LDR r11, [%[a], #40]\n\t"
  17685. "UMAAL r11, r3, lr, r12\n\t"
  17686. "STR r11, [%[a], #40]\n\t"
  17687. /* a[i+11] += m[11] * mu */
  17688. "LDR r12, [%[m], #44]\n\t"
  17689. "LDR r11, [%[a], #44]\n\t"
  17690. "UMAAL r11, r3, lr, r12\n\t"
  17691. "STR r11, [%[a], #44]\n\t"
  17692. /* a[i+12] += m[12] * mu */
  17693. "LDR r12, [%[m], #48]\n\t"
  17694. "LDR r11, [%[a], #48]\n\t"
  17695. "UMAAL r11, r3, lr, r12\n\t"
  17696. "STR r11, [%[a], #48]\n\t"
  17697. /* a[i+13] += m[13] * mu */
  17698. "LDR r12, [%[m], #52]\n\t"
  17699. "LDR r11, [%[a], #52]\n\t"
  17700. "UMAAL r11, r3, lr, r12\n\t"
  17701. "STR r11, [%[a], #52]\n\t"
  17702. /* a[i+14] += m[14] * mu */
  17703. "LDR r12, [%[m], #56]\n\t"
  17704. "LDR r11, [%[a], #56]\n\t"
  17705. "UMAAL r11, r3, lr, r12\n\t"
  17706. "STR r11, [%[a], #56]\n\t"
  17707. /* a[i+15] += m[15] * mu */
  17708. "LDR r12, [%[m], #60]\n\t"
  17709. "LDR r11, [%[a], #60]\n\t"
  17710. "UMAAL r11, r3, lr, r12\n\t"
  17711. "STR r11, [%[a], #60]\n\t"
  17712. /* a[i+16] += m[16] * mu */
  17713. "LDR r12, [%[m], #64]\n\t"
  17714. "LDR r11, [%[a], #64]\n\t"
  17715. "UMAAL r11, r3, lr, r12\n\t"
  17716. "STR r11, [%[a], #64]\n\t"
  17717. /* a[i+17] += m[17] * mu */
  17718. "LDR r12, [%[m], #68]\n\t"
  17719. "LDR r11, [%[a], #68]\n\t"
  17720. "UMAAL r11, r3, lr, r12\n\t"
  17721. "STR r11, [%[a], #68]\n\t"
  17722. /* a[i+18] += m[18] * mu */
  17723. "LDR r12, [%[m], #72]\n\t"
  17724. "LDR r11, [%[a], #72]\n\t"
  17725. "UMAAL r11, r3, lr, r12\n\t"
  17726. "STR r11, [%[a], #72]\n\t"
  17727. /* a[i+19] += m[19] * mu */
  17728. "LDR r12, [%[m], #76]\n\t"
  17729. "LDR r11, [%[a], #76]\n\t"
  17730. "UMAAL r11, r3, lr, r12\n\t"
  17731. "STR r11, [%[a], #76]\n\t"
  17732. /* a[i+20] += m[20] * mu */
  17733. "LDR r12, [%[m], #80]\n\t"
  17734. "LDR r11, [%[a], #80]\n\t"
  17735. "UMAAL r11, r3, lr, r12\n\t"
  17736. "STR r11, [%[a], #80]\n\t"
  17737. /* a[i+21] += m[21] * mu */
  17738. "LDR r12, [%[m], #84]\n\t"
  17739. "LDR r11, [%[a], #84]\n\t"
  17740. "UMAAL r11, r3, lr, r12\n\t"
  17741. "STR r11, [%[a], #84]\n\t"
  17742. /* a[i+22] += m[22] * mu */
  17743. "LDR r12, [%[m], #88]\n\t"
  17744. "LDR r11, [%[a], #88]\n\t"
  17745. "UMAAL r11, r3, lr, r12\n\t"
  17746. "STR r11, [%[a], #88]\n\t"
  17747. /* a[i+23] += m[23] * mu */
  17748. "LDR r12, [%[m], #92]\n\t"
  17749. "LDR r11, [%[a], #92]\n\t"
  17750. "UMAAL r11, r3, lr, r12\n\t"
  17751. "STR r11, [%[a], #92]\n\t"
  17752. /* a[i+24] += m[24] * mu */
  17753. "LDR r12, [%[m], #96]\n\t"
  17754. "LDR r11, [%[a], #96]\n\t"
  17755. "UMAAL r11, r3, lr, r12\n\t"
  17756. "STR r11, [%[a], #96]\n\t"
  17757. /* a[i+25] += m[25] * mu */
  17758. "LDR r12, [%[m], #100]\n\t"
  17759. "LDR r11, [%[a], #100]\n\t"
  17760. "UMAAL r11, r3, lr, r12\n\t"
  17761. "STR r11, [%[a], #100]\n\t"
  17762. /* a[i+26] += m[26] * mu */
  17763. "LDR r12, [%[m], #104]\n\t"
  17764. "LDR r11, [%[a], #104]\n\t"
  17765. "UMAAL r11, r3, lr, r12\n\t"
  17766. "STR r11, [%[a], #104]\n\t"
  17767. /* a[i+27] += m[27] * mu */
  17768. "LDR r12, [%[m], #108]\n\t"
  17769. "LDR r11, [%[a], #108]\n\t"
  17770. "UMAAL r11, r3, lr, r12\n\t"
  17771. "STR r11, [%[a], #108]\n\t"
  17772. /* a[i+28] += m[28] * mu */
  17773. "LDR r12, [%[m], #112]\n\t"
  17774. "LDR r11, [%[a], #112]\n\t"
  17775. "UMAAL r11, r3, lr, r12\n\t"
  17776. "STR r11, [%[a], #112]\n\t"
  17777. /* a[i+29] += m[29] * mu */
  17778. "LDR r12, [%[m], #116]\n\t"
  17779. "LDR r11, [%[a], #116]\n\t"
  17780. "UMAAL r11, r3, lr, r12\n\t"
  17781. "STR r11, [%[a], #116]\n\t"
  17782. /* a[i+30] += m[30] * mu */
  17783. "LDR r12, [%[m], #120]\n\t"
  17784. "LDR r11, [%[a], #120]\n\t"
  17785. "UMAAL r11, r3, lr, r12\n\t"
  17786. "STR r11, [%[a], #120]\n\t"
  17787. /* a[i+31] += m[31] * mu */
  17788. "LDR r12, [%[m], #124]\n\t"
  17789. "LDR r11, [%[a], #124]\n\t"
  17790. "UMAAL r11, r3, lr, r12\n\t"
  17791. "STR r11, [%[a], #124]\n\t"
  17792. /* a[i+32] += m[32] * mu */
  17793. "LDR r12, [%[m], #128]\n\t"
  17794. "LDR r11, [%[a], #128]\n\t"
  17795. "UMAAL r11, r3, lr, r12\n\t"
  17796. "STR r11, [%[a], #128]\n\t"
  17797. /* a[i+33] += m[33] * mu */
  17798. "LDR r12, [%[m], #132]\n\t"
  17799. "LDR r11, [%[a], #132]\n\t"
  17800. "UMAAL r11, r3, lr, r12\n\t"
  17801. "STR r11, [%[a], #132]\n\t"
  17802. /* a[i+34] += m[34] * mu */
  17803. "LDR r12, [%[m], #136]\n\t"
  17804. "LDR r11, [%[a], #136]\n\t"
  17805. "UMAAL r11, r3, lr, r12\n\t"
  17806. "STR r11, [%[a], #136]\n\t"
  17807. /* a[i+35] += m[35] * mu */
  17808. "LDR r12, [%[m], #140]\n\t"
  17809. "LDR r11, [%[a], #140]\n\t"
  17810. "UMAAL r11, r3, lr, r12\n\t"
  17811. "STR r11, [%[a], #140]\n\t"
  17812. /* a[i+36] += m[36] * mu */
  17813. "LDR r12, [%[m], #144]\n\t"
  17814. "LDR r11, [%[a], #144]\n\t"
  17815. "UMAAL r11, r3, lr, r12\n\t"
  17816. "STR r11, [%[a], #144]\n\t"
  17817. /* a[i+37] += m[37] * mu */
  17818. "LDR r12, [%[m], #148]\n\t"
  17819. "LDR r11, [%[a], #148]\n\t"
  17820. "UMAAL r11, r3, lr, r12\n\t"
  17821. "STR r11, [%[a], #148]\n\t"
  17822. /* a[i+38] += m[38] * mu */
  17823. "LDR r12, [%[m], #152]\n\t"
  17824. "LDR r11, [%[a], #152]\n\t"
  17825. "UMAAL r11, r3, lr, r12\n\t"
  17826. "STR r11, [%[a], #152]\n\t"
  17827. /* a[i+39] += m[39] * mu */
  17828. "LDR r12, [%[m], #156]\n\t"
  17829. "LDR r11, [%[a], #156]\n\t"
  17830. "UMAAL r11, r3, lr, r12\n\t"
  17831. "STR r11, [%[a], #156]\n\t"
  17832. /* a[i+40] += m[40] * mu */
  17833. "LDR r12, [%[m], #160]\n\t"
  17834. "LDR r11, [%[a], #160]\n\t"
  17835. "UMAAL r11, r3, lr, r12\n\t"
  17836. "STR r11, [%[a], #160]\n\t"
  17837. /* a[i+41] += m[41] * mu */
  17838. "LDR r12, [%[m], #164]\n\t"
  17839. "LDR r11, [%[a], #164]\n\t"
  17840. "UMAAL r11, r3, lr, r12\n\t"
  17841. "STR r11, [%[a], #164]\n\t"
  17842. /* a[i+42] += m[42] * mu */
  17843. "LDR r12, [%[m], #168]\n\t"
  17844. "LDR r11, [%[a], #168]\n\t"
  17845. "UMAAL r11, r3, lr, r12\n\t"
  17846. "STR r11, [%[a], #168]\n\t"
  17847. /* a[i+43] += m[43] * mu */
  17848. "LDR r12, [%[m], #172]\n\t"
  17849. "LDR r11, [%[a], #172]\n\t"
  17850. "UMAAL r11, r3, lr, r12\n\t"
  17851. "STR r11, [%[a], #172]\n\t"
  17852. /* a[i+44] += m[44] * mu */
  17853. "LDR r12, [%[m], #176]\n\t"
  17854. "LDR r11, [%[a], #176]\n\t"
  17855. "UMAAL r11, r3, lr, r12\n\t"
  17856. "STR r11, [%[a], #176]\n\t"
  17857. /* a[i+45] += m[45] * mu */
  17858. "LDR r12, [%[m], #180]\n\t"
  17859. "LDR r11, [%[a], #180]\n\t"
  17860. "UMAAL r11, r3, lr, r12\n\t"
  17861. "STR r11, [%[a], #180]\n\t"
  17862. /* a[i+46] += m[46] * mu */
  17863. "LDR r12, [%[m], #184]\n\t"
  17864. "LDR r11, [%[a], #184]\n\t"
  17865. "UMAAL r11, r3, lr, r12\n\t"
  17866. "STR r11, [%[a], #184]\n\t"
  17867. /* a[i+47] += m[47] * mu */
  17868. "LDR r12, [%[m], #188]\n\t"
  17869. "LDR r11, [%[a], #188]\n\t"
  17870. "UMAAL r11, r3, lr, r12\n\t"
  17871. "STR r11, [%[a], #188]\n\t"
  17872. /* a[i+48] += m[48] * mu */
  17873. "LDR r12, [%[m], #192]\n\t"
  17874. "LDR r11, [%[a], #192]\n\t"
  17875. "UMAAL r11, r3, lr, r12\n\t"
  17876. "STR r11, [%[a], #192]\n\t"
  17877. /* a[i+49] += m[49] * mu */
  17878. "LDR r12, [%[m], #196]\n\t"
  17879. "LDR r11, [%[a], #196]\n\t"
  17880. "UMAAL r11, r3, lr, r12\n\t"
  17881. "STR r11, [%[a], #196]\n\t"
  17882. /* a[i+50] += m[50] * mu */
  17883. "LDR r12, [%[m], #200]\n\t"
  17884. "LDR r11, [%[a], #200]\n\t"
  17885. "UMAAL r11, r3, lr, r12\n\t"
  17886. "STR r11, [%[a], #200]\n\t"
  17887. /* a[i+51] += m[51] * mu */
  17888. "LDR r12, [%[m], #204]\n\t"
  17889. "LDR r11, [%[a], #204]\n\t"
  17890. "UMAAL r11, r3, lr, r12\n\t"
  17891. "STR r11, [%[a], #204]\n\t"
  17892. /* a[i+52] += m[52] * mu */
  17893. "LDR r12, [%[m], #208]\n\t"
  17894. "LDR r11, [%[a], #208]\n\t"
  17895. "UMAAL r11, r3, lr, r12\n\t"
  17896. "STR r11, [%[a], #208]\n\t"
  17897. /* a[i+53] += m[53] * mu */
  17898. "LDR r12, [%[m], #212]\n\t"
  17899. "LDR r11, [%[a], #212]\n\t"
  17900. "UMAAL r11, r3, lr, r12\n\t"
  17901. "STR r11, [%[a], #212]\n\t"
  17902. /* a[i+54] += m[54] * mu */
  17903. "LDR r12, [%[m], #216]\n\t"
  17904. "LDR r11, [%[a], #216]\n\t"
  17905. "UMAAL r11, r3, lr, r12\n\t"
  17906. "STR r11, [%[a], #216]\n\t"
  17907. /* a[i+55] += m[55] * mu */
  17908. "LDR r12, [%[m], #220]\n\t"
  17909. "LDR r11, [%[a], #220]\n\t"
  17910. "UMAAL r11, r3, lr, r12\n\t"
  17911. "STR r11, [%[a], #220]\n\t"
  17912. /* a[i+56] += m[56] * mu */
  17913. "LDR r12, [%[m], #224]\n\t"
  17914. "LDR r11, [%[a], #224]\n\t"
  17915. "UMAAL r11, r3, lr, r12\n\t"
  17916. "STR r11, [%[a], #224]\n\t"
  17917. /* a[i+57] += m[57] * mu */
  17918. "LDR r12, [%[m], #228]\n\t"
  17919. "LDR r11, [%[a], #228]\n\t"
  17920. "UMAAL r11, r3, lr, r12\n\t"
  17921. "STR r11, [%[a], #228]\n\t"
  17922. /* a[i+58] += m[58] * mu */
  17923. "LDR r12, [%[m], #232]\n\t"
  17924. "LDR r11, [%[a], #232]\n\t"
  17925. "UMAAL r11, r3, lr, r12\n\t"
  17926. "STR r11, [%[a], #232]\n\t"
  17927. /* a[i+59] += m[59] * mu */
  17928. "LDR r12, [%[m], #236]\n\t"
  17929. "LDR r11, [%[a], #236]\n\t"
  17930. "UMAAL r11, r3, lr, r12\n\t"
  17931. "STR r11, [%[a], #236]\n\t"
  17932. /* a[i+60] += m[60] * mu */
  17933. "LDR r12, [%[m], #240]\n\t"
  17934. "LDR r11, [%[a], #240]\n\t"
  17935. "UMAAL r11, r3, lr, r12\n\t"
  17936. "STR r11, [%[a], #240]\n\t"
  17937. /* a[i+61] += m[61] * mu */
  17938. "LDR r12, [%[m], #244]\n\t"
  17939. "LDR r11, [%[a], #244]\n\t"
  17940. "UMAAL r11, r3, lr, r12\n\t"
  17941. "STR r11, [%[a], #244]\n\t"
  17942. /* a[i+62] += m[62] * mu */
  17943. "LDR r12, [%[m], #248]\n\t"
  17944. "LDR r11, [%[a], #248]\n\t"
  17945. "UMAAL r11, r3, lr, r12\n\t"
  17946. "STR r11, [%[a], #248]\n\t"
  17947. /* a[i+63] += m[63] * mu */
  17948. "LDR r12, [%[m], #252]\n\t"
  17949. "LDR r11, [%[a], #252]\n\t"
  17950. "UMAAL r11, r3, lr, r12\n\t"
  17951. "STR r11, [%[a], #252]\n\t"
  17952. /* a[i+64] += m[64] * mu */
  17953. "LDR r12, [%[m], #256]\n\t"
  17954. "LDR r11, [%[a], #256]\n\t"
  17955. "UMAAL r11, r3, lr, r12\n\t"
  17956. "STR r11, [%[a], #256]\n\t"
  17957. /* a[i+65] += m[65] * mu */
  17958. "LDR r12, [%[m], #260]\n\t"
  17959. "LDR r11, [%[a], #260]\n\t"
  17960. "UMAAL r11, r3, lr, r12\n\t"
  17961. "STR r11, [%[a], #260]\n\t"
  17962. /* a[i+66] += m[66] * mu */
  17963. "LDR r12, [%[m], #264]\n\t"
  17964. "LDR r11, [%[a], #264]\n\t"
  17965. "UMAAL r11, r3, lr, r12\n\t"
  17966. "STR r11, [%[a], #264]\n\t"
  17967. /* a[i+67] += m[67] * mu */
  17968. "LDR r12, [%[m], #268]\n\t"
  17969. "LDR r11, [%[a], #268]\n\t"
  17970. "UMAAL r11, r3, lr, r12\n\t"
  17971. "STR r11, [%[a], #268]\n\t"
  17972. /* a[i+68] += m[68] * mu */
  17973. "LDR r12, [%[m], #272]\n\t"
  17974. "LDR r11, [%[a], #272]\n\t"
  17975. "UMAAL r11, r3, lr, r12\n\t"
  17976. "STR r11, [%[a], #272]\n\t"
  17977. /* a[i+69] += m[69] * mu */
  17978. "LDR r12, [%[m], #276]\n\t"
  17979. "LDR r11, [%[a], #276]\n\t"
  17980. "UMAAL r11, r3, lr, r12\n\t"
  17981. "STR r11, [%[a], #276]\n\t"
  17982. /* a[i+70] += m[70] * mu */
  17983. "LDR r12, [%[m], #280]\n\t"
  17984. "LDR r11, [%[a], #280]\n\t"
  17985. "UMAAL r11, r3, lr, r12\n\t"
  17986. "STR r11, [%[a], #280]\n\t"
  17987. /* a[i+71] += m[71] * mu */
  17988. "LDR r12, [%[m], #284]\n\t"
  17989. "LDR r11, [%[a], #284]\n\t"
  17990. "UMAAL r11, r3, lr, r12\n\t"
  17991. "STR r11, [%[a], #284]\n\t"
  17992. /* a[i+72] += m[72] * mu */
  17993. "LDR r12, [%[m], #288]\n\t"
  17994. "LDR r11, [%[a], #288]\n\t"
  17995. "UMAAL r11, r3, lr, r12\n\t"
  17996. "STR r11, [%[a], #288]\n\t"
  17997. /* a[i+73] += m[73] * mu */
  17998. "LDR r12, [%[m], #292]\n\t"
  17999. "LDR r11, [%[a], #292]\n\t"
  18000. "UMAAL r11, r3, lr, r12\n\t"
  18001. "STR r11, [%[a], #292]\n\t"
  18002. /* a[i+74] += m[74] * mu */
  18003. "LDR r12, [%[m], #296]\n\t"
  18004. "LDR r11, [%[a], #296]\n\t"
  18005. "UMAAL r11, r3, lr, r12\n\t"
  18006. "STR r11, [%[a], #296]\n\t"
  18007. /* a[i+75] += m[75] * mu */
  18008. "LDR r12, [%[m], #300]\n\t"
  18009. "LDR r11, [%[a], #300]\n\t"
  18010. "UMAAL r11, r3, lr, r12\n\t"
  18011. "STR r11, [%[a], #300]\n\t"
  18012. /* a[i+76] += m[76] * mu */
  18013. "LDR r12, [%[m], #304]\n\t"
  18014. "LDR r11, [%[a], #304]\n\t"
  18015. "UMAAL r11, r3, lr, r12\n\t"
  18016. "STR r11, [%[a], #304]\n\t"
  18017. /* a[i+77] += m[77] * mu */
  18018. "LDR r12, [%[m], #308]\n\t"
  18019. "LDR r11, [%[a], #308]\n\t"
  18020. "UMAAL r11, r3, lr, r12\n\t"
  18021. "STR r11, [%[a], #308]\n\t"
  18022. /* a[i+78] += m[78] * mu */
  18023. "LDR r12, [%[m], #312]\n\t"
  18024. "LDR r11, [%[a], #312]\n\t"
  18025. "UMAAL r11, r3, lr, r12\n\t"
  18026. "STR r11, [%[a], #312]\n\t"
  18027. /* a[i+79] += m[79] * mu */
  18028. "LDR r12, [%[m], #316]\n\t"
  18029. "LDR r11, [%[a], #316]\n\t"
  18030. "UMAAL r11, r3, lr, r12\n\t"
  18031. "STR r11, [%[a], #316]\n\t"
  18032. /* a[i+80] += m[80] * mu */
  18033. "LDR r12, [%[m], #320]\n\t"
  18034. "LDR r11, [%[a], #320]\n\t"
  18035. "UMAAL r11, r3, lr, r12\n\t"
  18036. "STR r11, [%[a], #320]\n\t"
  18037. /* a[i+81] += m[81] * mu */
  18038. "LDR r12, [%[m], #324]\n\t"
  18039. "LDR r11, [%[a], #324]\n\t"
  18040. "UMAAL r11, r3, lr, r12\n\t"
  18041. "STR r11, [%[a], #324]\n\t"
  18042. /* a[i+82] += m[82] * mu */
  18043. "LDR r12, [%[m], #328]\n\t"
  18044. "LDR r11, [%[a], #328]\n\t"
  18045. "UMAAL r11, r3, lr, r12\n\t"
  18046. "STR r11, [%[a], #328]\n\t"
  18047. /* a[i+83] += m[83] * mu */
  18048. "LDR r12, [%[m], #332]\n\t"
  18049. "LDR r11, [%[a], #332]\n\t"
  18050. "UMAAL r11, r3, lr, r12\n\t"
  18051. "STR r11, [%[a], #332]\n\t"
  18052. /* a[i+84] += m[84] * mu */
  18053. "LDR r12, [%[m], #336]\n\t"
  18054. "LDR r11, [%[a], #336]\n\t"
  18055. "UMAAL r11, r3, lr, r12\n\t"
  18056. "STR r11, [%[a], #336]\n\t"
  18057. /* a[i+85] += m[85] * mu */
  18058. "LDR r12, [%[m], #340]\n\t"
  18059. "LDR r11, [%[a], #340]\n\t"
  18060. "UMAAL r11, r3, lr, r12\n\t"
  18061. "STR r11, [%[a], #340]\n\t"
  18062. /* a[i+86] += m[86] * mu */
  18063. "LDR r12, [%[m], #344]\n\t"
  18064. "LDR r11, [%[a], #344]\n\t"
  18065. "UMAAL r11, r3, lr, r12\n\t"
  18066. "STR r11, [%[a], #344]\n\t"
  18067. /* a[i+87] += m[87] * mu */
  18068. "LDR r12, [%[m], #348]\n\t"
  18069. "LDR r11, [%[a], #348]\n\t"
  18070. "UMAAL r11, r3, lr, r12\n\t"
  18071. "STR r11, [%[a], #348]\n\t"
  18072. /* a[i+88] += m[88] * mu */
  18073. "LDR r12, [%[m], #352]\n\t"
  18074. "LDR r11, [%[a], #352]\n\t"
  18075. "UMAAL r11, r3, lr, r12\n\t"
  18076. "STR r11, [%[a], #352]\n\t"
  18077. /* a[i+89] += m[89] * mu */
  18078. "LDR r12, [%[m], #356]\n\t"
  18079. "LDR r11, [%[a], #356]\n\t"
  18080. "UMAAL r11, r3, lr, r12\n\t"
  18081. "STR r11, [%[a], #356]\n\t"
  18082. /* a[i+90] += m[90] * mu */
  18083. "LDR r12, [%[m], #360]\n\t"
  18084. "LDR r11, [%[a], #360]\n\t"
  18085. "UMAAL r11, r3, lr, r12\n\t"
  18086. "STR r11, [%[a], #360]\n\t"
  18087. /* a[i+91] += m[91] * mu */
  18088. "LDR r12, [%[m], #364]\n\t"
  18089. "LDR r11, [%[a], #364]\n\t"
  18090. "UMAAL r11, r3, lr, r12\n\t"
  18091. "STR r11, [%[a], #364]\n\t"
  18092. /* a[i+92] += m[92] * mu */
  18093. "LDR r12, [%[m], #368]\n\t"
  18094. "LDR r11, [%[a], #368]\n\t"
  18095. "UMAAL r11, r3, lr, r12\n\t"
  18096. "STR r11, [%[a], #368]\n\t"
  18097. /* a[i+93] += m[93] * mu */
  18098. "LDR r12, [%[m], #372]\n\t"
  18099. "LDR r11, [%[a], #372]\n\t"
  18100. "UMAAL r11, r3, lr, r12\n\t"
  18101. "STR r11, [%[a], #372]\n\t"
  18102. /* a[i+94] += m[94] * mu */
  18103. "LDR r12, [%[m], #376]\n\t"
  18104. "LDR r11, [%[a], #376]\n\t"
  18105. "UMAAL r11, r3, lr, r12\n\t"
  18106. "STR r11, [%[a], #376]\n\t"
  18107. /* a[i+95] += m[95] * mu */
  18108. "LDR r12, [%[m], #380]\n\t"
  18109. "LDR r11, [%[a], #380]\n\t"
  18110. "UMAAL r11, r3, lr, r12\n\t"
  18111. "LDR lr, [%[a], #384]\n\t"
  18112. "MOV r12, #0x0\n\t"
  18113. "UMAAL r3, lr, r12, r12\n\t"
  18114. "STR r11, [%[a], #380]\n\t"
  18115. "ADDS r3, r3, r5\n\t"
  18116. "ADC r5, lr, #0x0\n\t"
  18117. "STR r3, [%[a], #384]\n\t"
  18118. /* i += 1 */
  18119. "ADD r4, r4, #0x4\n\t"
  18120. "ADD %[a], %[a], #0x4\n\t"
  18121. "CMP r4, #0x180\n\t"
  18122. #ifdef __GNUC__
  18123. "BLT L_sp_3072_mont_reduce_96_word\n\t"
  18124. #else
  18125. "BLT.W L_sp_3072_mont_reduce_96_word\n\t"
  18126. #endif
  18127. /* Loop Done */
  18128. "STR r6, [%[a]]\n\t"
  18129. "STR r7, [%[a], #4]\n\t"
  18130. "STR r8, [%[a], #8]\n\t"
  18131. "STR r9, [%[a], #12]\n\t"
  18132. "STR r10, [%[a], #16]\n\t"
  18133. "MOV %[mp], r5\n\t"
  18134. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  18135. :
  18136. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  18137. );
  18138. sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - mp);
  18139. }
  18140. #else
  18141. /* Reduce the number back to 3072 bits using Montgomery reduction.
  18142. *
  18143. * a A single precision number to reduce in place.
  18144. * m The single precision number representing the modulus.
  18145. * mp The digit representing the negative inverse of m mod 2^n.
  18146. */
  18147. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18148. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  18149. #else
  18150. SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, sp_digit mp)
  18151. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18152. {
  18153. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18154. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  18155. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  18156. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  18157. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18158. __asm__ __volatile__ (
  18159. "LDR r11, [%[m]]\n\t"
  18160. /* i = 0 */
  18161. "MOV r9, #0x0\n\t"
  18162. /* ca = 0 */
  18163. "MOV r3, #0x0\n\t"
  18164. "\n"
  18165. "L_sp_3072_mont_reduce_96_word:\n\t"
  18166. /* mu = a[i] * mp */
  18167. "LDR r10, [%[a]]\n\t"
  18168. "MUL r8, %[mp], r10\n\t"
  18169. /* j = 0 */
  18170. "MOV r12, #0x0\n\t"
  18171. "MOV r4, #0x0\n\t"
  18172. "\n"
  18173. "L_sp_3072_mont_reduce_96_mul:\n\t"
  18174. /* a[i+j+0] += m[j+0] * mu */
  18175. "LDR r7, [%[m], r12]\n\t"
  18176. "LDR r10, [%[a], r12]\n\t"
  18177. "UMAAL r10, r4, r8, r7\n\t"
  18178. "STR r10, [%[a], r12]\n\t"
  18179. /* j += 1 */
  18180. "ADD r12, r12, #0x4\n\t"
  18181. /* a[i+j+1] += m[j+1] * mu */
  18182. "LDR r7, [%[m], r12]\n\t"
  18183. "LDR r10, [%[a], r12]\n\t"
  18184. "UMAAL r10, r4, r8, r7\n\t"
  18185. "STR r10, [%[a], r12]\n\t"
  18186. /* j += 1 */
  18187. "ADD r12, r12, #0x4\n\t"
  18188. /* a[i+j+2] += m[j+2] * mu */
  18189. "LDR r7, [%[m], r12]\n\t"
  18190. "LDR r10, [%[a], r12]\n\t"
  18191. "UMAAL r10, r4, r8, r7\n\t"
  18192. "STR r10, [%[a], r12]\n\t"
  18193. /* j += 1 */
  18194. "ADD r12, r12, #0x4\n\t"
  18195. /* a[i+j+3] += m[j+3] * mu */
  18196. "LDR r7, [%[m], r12]\n\t"
  18197. "LDR r10, [%[a], r12]\n\t"
  18198. "UMAAL r10, r4, r8, r7\n\t"
  18199. "STR r10, [%[a], r12]\n\t"
  18200. /* j += 1 */
  18201. "ADD r12, r12, #0x4\n\t"
  18202. "CMP r12, #0x180\n\t"
  18203. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  18204. "BLT L_sp_3072_mont_reduce_96_mul\n\t"
  18205. #else
  18206. "BLT.N L_sp_3072_mont_reduce_96_mul\n\t"
  18207. #endif
  18208. "LDR r10, [%[a], #384]\n\t"
  18209. "ADDS r4, r4, r3\n\t"
  18210. "MOV r3, #0x0\n\t"
  18211. "ADC r3, r3, #0x0\n\t"
  18212. "ADDS r10, r10, r4\n\t"
  18213. "ADC r3, r3, r3\n\t"
  18214. "STR r10, [%[a], #384]\n\t"
  18215. /* i += 1 */
  18216. "ADD r9, r9, #0x4\n\t"
  18217. "ADD %[a], %[a], #0x4\n\t"
  18218. "CMP r9, #0x180\n\t"
  18219. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  18220. "BLT L_sp_3072_mont_reduce_96_word\n\t"
  18221. #else
  18222. "BLT.N L_sp_3072_mont_reduce_96_word\n\t"
  18223. #endif
  18224. /* Loop Done */
  18225. "MOV %[mp], r3\n\t"
  18226. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  18227. :
  18228. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  18229. );
  18230. sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - mp);
  18231. }
  18232. #endif /* !WOLFSSL_SP_SMALL */
  18233. #endif
  18234. /* Multiply two Montgomery form numbers mod the modulus (prime).
  18235. * (r = a * b mod m)
  18236. *
  18237. * r Result of multiplication.
  18238. * a First number to multiply in Montgomery form.
  18239. * b Second number to multiply in Montgomery form.
  18240. * m Modulus (prime).
  18241. * mp Montgomery multiplier.
  18242. */
  18243. SP_NOINLINE static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a,
  18244. const sp_digit* b, const sp_digit* m, sp_digit mp)
  18245. {
  18246. sp_3072_mul_96(r, a, b);
  18247. sp_3072_mont_reduce_96(r, m, mp);
  18248. }
  18249. /* Square the Montgomery form number. (r = a * a mod m)
  18250. *
  18251. * r Result of squaring.
  18252. * a Number to square in Montgomery form.
  18253. * m Modulus (prime).
  18254. * mp Montgomery multiplier.
  18255. */
  18256. SP_NOINLINE static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a,
  18257. const sp_digit* m, sp_digit mp)
  18258. {
  18259. sp_3072_sqr_96(r, a);
  18260. sp_3072_mont_reduce_96(r, m, mp);
  18261. }
  18262. #ifdef WOLFSSL_SP_SMALL
  18263. /* Sub b from a into r. (r = a - b)
  18264. *
  18265. * r A single precision integer.
  18266. * a A single precision integer.
  18267. * b A single precision integer.
  18268. */
  18269. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18270. static sp_digit sp_3072_sub_96(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  18271. #else
  18272. static sp_digit sp_3072_sub_96(sp_digit* r, const sp_digit* a, const sp_digit* b)
  18273. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18274. {
  18275. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18276. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  18277. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  18278. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  18279. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18280. __asm__ __volatile__ (
  18281. "MOV r11, #0x0\n\t"
  18282. "ADD r12, %[a], #0x180\n\t"
  18283. "\n"
  18284. "L_sp_3072_sub_96_word:\n\t"
  18285. "RSBS r11, r11, #0x0\n\t"
  18286. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18287. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18288. "SBCS r3, r3, r7\n\t"
  18289. "SBCS r4, r4, r8\n\t"
  18290. "SBCS r5, r5, r9\n\t"
  18291. "SBCS r6, r6, r10\n\t"
  18292. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18293. "SBC r11, r3, r3\n\t"
  18294. "CMP %[a], r12\n\t"
  18295. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  18296. "BNE L_sp_3072_sub_96_word\n\t"
  18297. #else
  18298. "BNE.N L_sp_3072_sub_96_word\n\t"
  18299. #endif
  18300. "MOV %[r], r11\n\t"
  18301. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  18302. :
  18303. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  18304. );
  18305. return (uint32_t)(size_t)r;
  18306. }
  18307. #else
  18308. /* Sub b from a into r. (r = a - b)
  18309. *
  18310. * r A single precision integer.
  18311. * a A single precision integer.
  18312. * b A single precision integer.
  18313. */
  18314. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18315. static sp_digit sp_3072_sub_96(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  18316. #else
  18317. static sp_digit sp_3072_sub_96(sp_digit* r, const sp_digit* a, const sp_digit* b)
  18318. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18319. {
  18320. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18321. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  18322. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  18323. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  18324. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18325. __asm__ __volatile__ (
  18326. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18327. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18328. "SUBS r3, r3, r7\n\t"
  18329. "SBCS r4, r4, r8\n\t"
  18330. "SBCS r5, r5, r9\n\t"
  18331. "SBCS r6, r6, r10\n\t"
  18332. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18333. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18334. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18335. "SBCS r3, r3, r7\n\t"
  18336. "SBCS r4, r4, r8\n\t"
  18337. "SBCS r5, r5, r9\n\t"
  18338. "SBCS r6, r6, r10\n\t"
  18339. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18340. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18341. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18342. "SBCS r3, r3, r7\n\t"
  18343. "SBCS r4, r4, r8\n\t"
  18344. "SBCS r5, r5, r9\n\t"
  18345. "SBCS r6, r6, r10\n\t"
  18346. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18347. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18348. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18349. "SBCS r3, r3, r7\n\t"
  18350. "SBCS r4, r4, r8\n\t"
  18351. "SBCS r5, r5, r9\n\t"
  18352. "SBCS r6, r6, r10\n\t"
  18353. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18354. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18355. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18356. "SBCS r3, r3, r7\n\t"
  18357. "SBCS r4, r4, r8\n\t"
  18358. "SBCS r5, r5, r9\n\t"
  18359. "SBCS r6, r6, r10\n\t"
  18360. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18361. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18362. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18363. "SBCS r3, r3, r7\n\t"
  18364. "SBCS r4, r4, r8\n\t"
  18365. "SBCS r5, r5, r9\n\t"
  18366. "SBCS r6, r6, r10\n\t"
  18367. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18368. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18369. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18370. "SBCS r3, r3, r7\n\t"
  18371. "SBCS r4, r4, r8\n\t"
  18372. "SBCS r5, r5, r9\n\t"
  18373. "SBCS r6, r6, r10\n\t"
  18374. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18375. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18376. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18377. "SBCS r3, r3, r7\n\t"
  18378. "SBCS r4, r4, r8\n\t"
  18379. "SBCS r5, r5, r9\n\t"
  18380. "SBCS r6, r6, r10\n\t"
  18381. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18382. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18383. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18384. "SBCS r3, r3, r7\n\t"
  18385. "SBCS r4, r4, r8\n\t"
  18386. "SBCS r5, r5, r9\n\t"
  18387. "SBCS r6, r6, r10\n\t"
  18388. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18389. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18390. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18391. "SBCS r3, r3, r7\n\t"
  18392. "SBCS r4, r4, r8\n\t"
  18393. "SBCS r5, r5, r9\n\t"
  18394. "SBCS r6, r6, r10\n\t"
  18395. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18396. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18397. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18398. "SBCS r3, r3, r7\n\t"
  18399. "SBCS r4, r4, r8\n\t"
  18400. "SBCS r5, r5, r9\n\t"
  18401. "SBCS r6, r6, r10\n\t"
  18402. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18403. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18404. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18405. "SBCS r3, r3, r7\n\t"
  18406. "SBCS r4, r4, r8\n\t"
  18407. "SBCS r5, r5, r9\n\t"
  18408. "SBCS r6, r6, r10\n\t"
  18409. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18410. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18411. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18412. "SBCS r3, r3, r7\n\t"
  18413. "SBCS r4, r4, r8\n\t"
  18414. "SBCS r5, r5, r9\n\t"
  18415. "SBCS r6, r6, r10\n\t"
  18416. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18417. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18418. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18419. "SBCS r3, r3, r7\n\t"
  18420. "SBCS r4, r4, r8\n\t"
  18421. "SBCS r5, r5, r9\n\t"
  18422. "SBCS r6, r6, r10\n\t"
  18423. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18424. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18425. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18426. "SBCS r3, r3, r7\n\t"
  18427. "SBCS r4, r4, r8\n\t"
  18428. "SBCS r5, r5, r9\n\t"
  18429. "SBCS r6, r6, r10\n\t"
  18430. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18431. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18432. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18433. "SBCS r3, r3, r7\n\t"
  18434. "SBCS r4, r4, r8\n\t"
  18435. "SBCS r5, r5, r9\n\t"
  18436. "SBCS r6, r6, r10\n\t"
  18437. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18438. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18439. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18440. "SBCS r3, r3, r7\n\t"
  18441. "SBCS r4, r4, r8\n\t"
  18442. "SBCS r5, r5, r9\n\t"
  18443. "SBCS r6, r6, r10\n\t"
  18444. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18445. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18446. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18447. "SBCS r3, r3, r7\n\t"
  18448. "SBCS r4, r4, r8\n\t"
  18449. "SBCS r5, r5, r9\n\t"
  18450. "SBCS r6, r6, r10\n\t"
  18451. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18452. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18453. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18454. "SBCS r3, r3, r7\n\t"
  18455. "SBCS r4, r4, r8\n\t"
  18456. "SBCS r5, r5, r9\n\t"
  18457. "SBCS r6, r6, r10\n\t"
  18458. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18459. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18460. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18461. "SBCS r3, r3, r7\n\t"
  18462. "SBCS r4, r4, r8\n\t"
  18463. "SBCS r5, r5, r9\n\t"
  18464. "SBCS r6, r6, r10\n\t"
  18465. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18466. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18467. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18468. "SBCS r3, r3, r7\n\t"
  18469. "SBCS r4, r4, r8\n\t"
  18470. "SBCS r5, r5, r9\n\t"
  18471. "SBCS r6, r6, r10\n\t"
  18472. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18473. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18474. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18475. "SBCS r3, r3, r7\n\t"
  18476. "SBCS r4, r4, r8\n\t"
  18477. "SBCS r5, r5, r9\n\t"
  18478. "SBCS r6, r6, r10\n\t"
  18479. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18480. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18481. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18482. "SBCS r3, r3, r7\n\t"
  18483. "SBCS r4, r4, r8\n\t"
  18484. "SBCS r5, r5, r9\n\t"
  18485. "SBCS r6, r6, r10\n\t"
  18486. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18487. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  18488. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  18489. "SBCS r3, r3, r7\n\t"
  18490. "SBCS r4, r4, r8\n\t"
  18491. "SBCS r5, r5, r9\n\t"
  18492. "SBCS r6, r6, r10\n\t"
  18493. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  18494. "SBC %[r], r6, r6\n\t"
  18495. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  18496. :
  18497. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  18498. );
  18499. return (uint32_t)(size_t)r;
  18500. }
  18501. #endif /* WOLFSSL_SP_SMALL */
  18502. #ifdef WOLFSSL_SP_USE_UDIV
  18503. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  18504. *
  18505. * d1 The high order half of the number to divide.
  18506. * d0 The low order half of the number to divide.
  18507. * div The divisor.
  18508. * returns the result of the division.
  18509. *
  18510. * Note that this is an approximate div. It may give an answer 1 larger.
  18511. */
  18512. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18513. SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  18514. #else
  18515. SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, sp_digit div)
  18516. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18517. {
  18518. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18519. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  18520. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  18521. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  18522. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18523. __asm__ __volatile__ (
  18524. "LSR r8, %[div], #16\n\t"
  18525. "ADD r5, r8, #0x1\n\t"
  18526. "UDIV r6, %[d1], r5\n\t"
  18527. "LSL r7, %[div], #16\n\t"
  18528. "LSL r6, r6, #16\n\t"
  18529. "UMULL r3, r4, %[div], r6\n\t"
  18530. "SUBS %[d0], %[d0], r3\n\t"
  18531. "SBC %[d1], %[d1], r4\n\t"
  18532. "SUBS r3, %[d1], r5\n\t"
  18533. "SBC r9, r9, r9\n\t"
  18534. "ADD r9, r9, #0x1\n\t"
  18535. "RSB r10, r9, #0x0\n\t"
  18536. "LSL r9, r9, #16\n\t"
  18537. "AND r7, r7, r10\n\t"
  18538. "AND r8, r8, r10\n\t"
  18539. "SUBS %[d0], %[d0], r7\n\t"
  18540. "ADD r6, r6, r9\n\t"
  18541. "SBC %[d1], %[d1], r8\n\t"
  18542. "LSL r4, %[d1], #16\n\t"
  18543. "LSR r3, %[d0], #16\n\t"
  18544. "ORR r3, r3, r4\n\t"
  18545. "UDIV r3, r3, r5\n\t"
  18546. "ADD r6, r6, r3\n\t"
  18547. "UMULL r3, r4, %[div], r3\n\t"
  18548. "SUBS %[d0], %[d0], r3\n\t"
  18549. "SBC %[d1], %[d1], r4\n\t"
  18550. "LSL r4, %[d1], #16\n\t"
  18551. "LSR r3, %[d0], #16\n\t"
  18552. "ORR r3, r3, r4\n\t"
  18553. "UDIV r3, r3, r5\n\t"
  18554. "ADD r6, r6, r3\n\t"
  18555. "MUL r3, %[div], r3\n\t"
  18556. "SUB %[d0], %[d0], r3\n\t"
  18557. "UDIV r3, %[d0], %[div]\n\t"
  18558. "ADD %[d1], r6, r3\n\t"
  18559. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  18560. :
  18561. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  18562. );
  18563. return (uint32_t)(size_t)d1;
  18564. }
  18565. #else
  18566. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  18567. *
  18568. * d1 The high order half of the number to divide.
  18569. * d0 The low order half of the number to divide.
  18570. * div The divisor.
  18571. * returns the result of the division.
  18572. *
  18573. * Note that this is an approximate div. It may give an answer 1 larger.
  18574. */
  18575. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18576. SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  18577. #else
  18578. SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, sp_digit div)
  18579. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18580. {
  18581. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18582. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  18583. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  18584. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  18585. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18586. __asm__ __volatile__ (
  18587. "LSR r5, %[div], #1\n\t"
  18588. "ADD r5, r5, #0x1\n\t"
  18589. "MOV r6, %[d0]\n\t"
  18590. "MOV r7, %[d1]\n\t"
  18591. /* Do top 32 */
  18592. "SUBS r8, r5, r7\n\t"
  18593. "SBC r8, r8, r8\n\t"
  18594. "MOV r3, #0x0\n\t"
  18595. "SUB r3, r3, r8\n\t"
  18596. "AND r8, r8, r5\n\t"
  18597. "SUBS r7, r7, r8\n\t"
  18598. /* Next 30 bits */
  18599. "MOV r4, #0x1d\n\t"
  18600. "\n"
  18601. "L_div_3072_word_96_bit:\n\t"
  18602. "LSLS r6, r6, #1\n\t"
  18603. "ADC r7, r7, r7\n\t"
  18604. "SUBS r8, r5, r7\n\t"
  18605. "SBC r8, r8, r8\n\t"
  18606. "ADD r3, r3, r3\n\t"
  18607. "SUB r3, r3, r8\n\t"
  18608. "AND r8, r8, r5\n\t"
  18609. "SUBS r7, r7, r8\n\t"
  18610. "SUBS r4, r4, #0x1\n\t"
  18611. "bpl L_div_3072_word_96_bit\n\t"
  18612. "ADD r3, r3, r3\n\t"
  18613. "ADD r3, r3, #0x1\n\t"
  18614. "UMULL r6, r7, r3, %[div]\n\t"
  18615. "SUBS r9, %[d0], r6\n\t"
  18616. "SBC r10, %[d1], r7\n\t"
  18617. "ADD r3, r3, r10\n\t"
  18618. "UMULL r6, r7, r3, %[div]\n\t"
  18619. "SUBS r9, %[d0], r6\n\t"
  18620. "SBC r10, %[d1], r7\n\t"
  18621. "ADD r3, r3, r10\n\t"
  18622. "UMULL r6, r7, r3, %[div]\n\t"
  18623. "SUBS r9, %[d0], r6\n\t"
  18624. "SBC r10, %[d1], r7\n\t"
  18625. "ADD r3, r3, r10\n\t"
  18626. "SUBS r8, %[div], r9\n\t"
  18627. "SBC r8, r8, r8\n\t"
  18628. "SUB %[d1], r3, r8\n\t"
  18629. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  18630. :
  18631. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  18632. );
  18633. return (uint32_t)(size_t)d1;
  18634. }
  18635. #endif
  18636. /* Divide d in a and put remainder into r (m*d + r = a)
  18637. * m is not calculated as it is not needed at this time.
  18638. *
  18639. * a Number to be divided.
  18640. * d Number to divide with.
  18641. * m Multiplier result.
  18642. * r Remainder from the division.
  18643. * returns MP_OKAY indicating success.
  18644. */
  18645. static WC_INLINE int sp_3072_div_96_cond(const sp_digit* a, const sp_digit* d,
  18646. sp_digit* m, sp_digit* r)
  18647. {
  18648. sp_digit t1[192], t2[97];
  18649. sp_digit div, r1;
  18650. int i;
  18651. (void)m;
  18652. div = d[95];
  18653. XMEMCPY(t1, a, sizeof(*t1) * 2 * 96);
  18654. for (i = 95; i > 0; i--) {
  18655. if (t1[i + 96] != d[i])
  18656. break;
  18657. }
  18658. if (t1[i + 96] >= d[i]) {
  18659. sp_3072_sub_in_place_96(&t1[96], d);
  18660. }
  18661. for (i = 95; i >= 0; i--) {
  18662. if (t1[96 + i] == div) {
  18663. r1 = SP_DIGIT_MAX;
  18664. }
  18665. else {
  18666. r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div);
  18667. }
  18668. sp_3072_mul_d_96(t2, d, r1);
  18669. t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2);
  18670. t1[96 + i] -= t2[96];
  18671. if (t1[96 + i] != 0) {
  18672. t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d);
  18673. if (t1[96 + i] != 0)
  18674. t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d);
  18675. }
  18676. }
  18677. for (i = 95; i > 0; i--) {
  18678. if (t1[i] != d[i])
  18679. break;
  18680. }
  18681. if (t1[i] >= d[i]) {
  18682. sp_3072_sub_96(r, t1, d);
  18683. }
  18684. else {
  18685. XMEMCPY(r, t1, sizeof(*t1) * 96);
  18686. }
  18687. return MP_OKAY;
  18688. }
  18689. /* Reduce a modulo m into r. (r = a mod m)
  18690. *
  18691. * r A single precision number that is the reduced result.
  18692. * a A single precision number that is to be reduced.
  18693. * m A single precision number that is the modulus to reduce with.
  18694. * returns MP_OKAY indicating success.
  18695. */
  18696. static WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
  18697. {
  18698. return sp_3072_div_96_cond(a, m, NULL, r);
  18699. }
  18700. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  18701. #if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)
  18702. /* AND m into each word of a and store in r.
  18703. *
  18704. * r A single precision integer.
  18705. * a A single precision integer.
  18706. * m Mask to AND against each digit.
  18707. */
  18708. static void sp_3072_mask_96(sp_digit* r, const sp_digit* a, sp_digit m)
  18709. {
  18710. #ifdef WOLFSSL_SP_SMALL
  18711. int i;
  18712. for (i=0; i<96; i++) {
  18713. r[i] = a[i] & m;
  18714. }
  18715. #else
  18716. int i;
  18717. for (i = 0; i < 96; i += 8) {
  18718. r[i+0] = a[i+0] & m;
  18719. r[i+1] = a[i+1] & m;
  18720. r[i+2] = a[i+2] & m;
  18721. r[i+3] = a[i+3] & m;
  18722. r[i+4] = a[i+4] & m;
  18723. r[i+5] = a[i+5] & m;
  18724. r[i+6] = a[i+6] & m;
  18725. r[i+7] = a[i+7] & m;
  18726. }
  18727. #endif
  18728. }
  18729. /* Compare a with b in constant time.
  18730. *
  18731. * a A single precision integer.
  18732. * b A single precision integer.
  18733. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  18734. * respectively.
  18735. */
  18736. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18737. static sp_int32 sp_3072_cmp_96(const sp_digit* a_p, const sp_digit* b_p)
  18738. #else
  18739. static sp_int32 sp_3072_cmp_96(const sp_digit* a, const sp_digit* b)
  18740. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18741. {
  18742. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  18743. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  18744. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  18745. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  18746. __asm__ __volatile__ (
  18747. "MOV r2, #0xffffffff\n\t"
  18748. "MOV r8, #0x1\n\t"
  18749. "MOV r7, #0x0\n\t"
  18750. "MOV r3, #0xffffffff\n\t"
  18751. #ifdef WOLFSSL_SP_SMALL
  18752. "MOV r6, #0x17c\n\t"
  18753. "\n"
  18754. "L_sp_3072_cmp_96_words:\n\t"
  18755. "LDR r4, [%[a], r6]\n\t"
  18756. "LDR r5, [%[b], r6]\n\t"
  18757. "AND r4, r4, r3\n\t"
  18758. "AND r5, r5, r3\n\t"
  18759. "SUBS r4, r4, r5\n\t"
  18760. "IT hi\n\t"
  18761. "movhi r2, r8\n\t"
  18762. "IT lo\n\t"
  18763. "movlo r2, r3\n\t"
  18764. "IT ne\n\t"
  18765. "movne r3, r7\n\t"
  18766. "SUBS r6, r6, #0x4\n\t"
  18767. "bcs L_sp_3072_cmp_96_words\n\t"
  18768. "EOR r2, r2, r3\n\t"
  18769. #else
  18770. "LDR r4, [%[a], #380]\n\t"
  18771. "LDR r5, [%[b], #380]\n\t"
  18772. "AND r4, r4, r3\n\t"
  18773. "AND r5, r5, r3\n\t"
  18774. "SUBS r4, r4, r5\n\t"
  18775. "IT hi\n\t"
  18776. "movhi r2, r8\n\t"
  18777. "IT lo\n\t"
  18778. "movlo r2, r3\n\t"
  18779. "IT ne\n\t"
  18780. "movne r3, r7\n\t"
  18781. "LDR r4, [%[a], #376]\n\t"
  18782. "LDR r5, [%[b], #376]\n\t"
  18783. "AND r4, r4, r3\n\t"
  18784. "AND r5, r5, r3\n\t"
  18785. "SUBS r4, r4, r5\n\t"
  18786. "IT hi\n\t"
  18787. "movhi r2, r8\n\t"
  18788. "IT lo\n\t"
  18789. "movlo r2, r3\n\t"
  18790. "IT ne\n\t"
  18791. "movne r3, r7\n\t"
  18792. "LDR r4, [%[a], #372]\n\t"
  18793. "LDR r5, [%[b], #372]\n\t"
  18794. "AND r4, r4, r3\n\t"
  18795. "AND r5, r5, r3\n\t"
  18796. "SUBS r4, r4, r5\n\t"
  18797. "IT hi\n\t"
  18798. "movhi r2, r8\n\t"
  18799. "IT lo\n\t"
  18800. "movlo r2, r3\n\t"
  18801. "IT ne\n\t"
  18802. "movne r3, r7\n\t"
  18803. "LDR r4, [%[a], #368]\n\t"
  18804. "LDR r5, [%[b], #368]\n\t"
  18805. "AND r4, r4, r3\n\t"
  18806. "AND r5, r5, r3\n\t"
  18807. "SUBS r4, r4, r5\n\t"
  18808. "IT hi\n\t"
  18809. "movhi r2, r8\n\t"
  18810. "IT lo\n\t"
  18811. "movlo r2, r3\n\t"
  18812. "IT ne\n\t"
  18813. "movne r3, r7\n\t"
  18814. "LDR r4, [%[a], #364]\n\t"
  18815. "LDR r5, [%[b], #364]\n\t"
  18816. "AND r4, r4, r3\n\t"
  18817. "AND r5, r5, r3\n\t"
  18818. "SUBS r4, r4, r5\n\t"
  18819. "IT hi\n\t"
  18820. "movhi r2, r8\n\t"
  18821. "IT lo\n\t"
  18822. "movlo r2, r3\n\t"
  18823. "IT ne\n\t"
  18824. "movne r3, r7\n\t"
  18825. "LDR r4, [%[a], #360]\n\t"
  18826. "LDR r5, [%[b], #360]\n\t"
  18827. "AND r4, r4, r3\n\t"
  18828. "AND r5, r5, r3\n\t"
  18829. "SUBS r4, r4, r5\n\t"
  18830. "IT hi\n\t"
  18831. "movhi r2, r8\n\t"
  18832. "IT lo\n\t"
  18833. "movlo r2, r3\n\t"
  18834. "IT ne\n\t"
  18835. "movne r3, r7\n\t"
  18836. "LDR r4, [%[a], #356]\n\t"
  18837. "LDR r5, [%[b], #356]\n\t"
  18838. "AND r4, r4, r3\n\t"
  18839. "AND r5, r5, r3\n\t"
  18840. "SUBS r4, r4, r5\n\t"
  18841. "IT hi\n\t"
  18842. "movhi r2, r8\n\t"
  18843. "IT lo\n\t"
  18844. "movlo r2, r3\n\t"
  18845. "IT ne\n\t"
  18846. "movne r3, r7\n\t"
  18847. "LDR r4, [%[a], #352]\n\t"
  18848. "LDR r5, [%[b], #352]\n\t"
  18849. "AND r4, r4, r3\n\t"
  18850. "AND r5, r5, r3\n\t"
  18851. "SUBS r4, r4, r5\n\t"
  18852. "IT hi\n\t"
  18853. "movhi r2, r8\n\t"
  18854. "IT lo\n\t"
  18855. "movlo r2, r3\n\t"
  18856. "IT ne\n\t"
  18857. "movne r3, r7\n\t"
  18858. "LDR r4, [%[a], #348]\n\t"
  18859. "LDR r5, [%[b], #348]\n\t"
  18860. "AND r4, r4, r3\n\t"
  18861. "AND r5, r5, r3\n\t"
  18862. "SUBS r4, r4, r5\n\t"
  18863. "IT hi\n\t"
  18864. "movhi r2, r8\n\t"
  18865. "IT lo\n\t"
  18866. "movlo r2, r3\n\t"
  18867. "IT ne\n\t"
  18868. "movne r3, r7\n\t"
  18869. "LDR r4, [%[a], #344]\n\t"
  18870. "LDR r5, [%[b], #344]\n\t"
  18871. "AND r4, r4, r3\n\t"
  18872. "AND r5, r5, r3\n\t"
  18873. "SUBS r4, r4, r5\n\t"
  18874. "IT hi\n\t"
  18875. "movhi r2, r8\n\t"
  18876. "IT lo\n\t"
  18877. "movlo r2, r3\n\t"
  18878. "IT ne\n\t"
  18879. "movne r3, r7\n\t"
  18880. "LDR r4, [%[a], #340]\n\t"
  18881. "LDR r5, [%[b], #340]\n\t"
  18882. "AND r4, r4, r3\n\t"
  18883. "AND r5, r5, r3\n\t"
  18884. "SUBS r4, r4, r5\n\t"
  18885. "IT hi\n\t"
  18886. "movhi r2, r8\n\t"
  18887. "IT lo\n\t"
  18888. "movlo r2, r3\n\t"
  18889. "IT ne\n\t"
  18890. "movne r3, r7\n\t"
  18891. "LDR r4, [%[a], #336]\n\t"
  18892. "LDR r5, [%[b], #336]\n\t"
  18893. "AND r4, r4, r3\n\t"
  18894. "AND r5, r5, r3\n\t"
  18895. "SUBS r4, r4, r5\n\t"
  18896. "IT hi\n\t"
  18897. "movhi r2, r8\n\t"
  18898. "IT lo\n\t"
  18899. "movlo r2, r3\n\t"
  18900. "IT ne\n\t"
  18901. "movne r3, r7\n\t"
  18902. "LDR r4, [%[a], #332]\n\t"
  18903. "LDR r5, [%[b], #332]\n\t"
  18904. "AND r4, r4, r3\n\t"
  18905. "AND r5, r5, r3\n\t"
  18906. "SUBS r4, r4, r5\n\t"
  18907. "IT hi\n\t"
  18908. "movhi r2, r8\n\t"
  18909. "IT lo\n\t"
  18910. "movlo r2, r3\n\t"
  18911. "IT ne\n\t"
  18912. "movne r3, r7\n\t"
  18913. "LDR r4, [%[a], #328]\n\t"
  18914. "LDR r5, [%[b], #328]\n\t"
  18915. "AND r4, r4, r3\n\t"
  18916. "AND r5, r5, r3\n\t"
  18917. "SUBS r4, r4, r5\n\t"
  18918. "IT hi\n\t"
  18919. "movhi r2, r8\n\t"
  18920. "IT lo\n\t"
  18921. "movlo r2, r3\n\t"
  18922. "IT ne\n\t"
  18923. "movne r3, r7\n\t"
  18924. "LDR r4, [%[a], #324]\n\t"
  18925. "LDR r5, [%[b], #324]\n\t"
  18926. "AND r4, r4, r3\n\t"
  18927. "AND r5, r5, r3\n\t"
  18928. "SUBS r4, r4, r5\n\t"
  18929. "IT hi\n\t"
  18930. "movhi r2, r8\n\t"
  18931. "IT lo\n\t"
  18932. "movlo r2, r3\n\t"
  18933. "IT ne\n\t"
  18934. "movne r3, r7\n\t"
  18935. "LDR r4, [%[a], #320]\n\t"
  18936. "LDR r5, [%[b], #320]\n\t"
  18937. "AND r4, r4, r3\n\t"
  18938. "AND r5, r5, r3\n\t"
  18939. "SUBS r4, r4, r5\n\t"
  18940. "IT hi\n\t"
  18941. "movhi r2, r8\n\t"
  18942. "IT lo\n\t"
  18943. "movlo r2, r3\n\t"
  18944. "IT ne\n\t"
  18945. "movne r3, r7\n\t"
  18946. "LDR r4, [%[a], #316]\n\t"
  18947. "LDR r5, [%[b], #316]\n\t"
  18948. "AND r4, r4, r3\n\t"
  18949. "AND r5, r5, r3\n\t"
  18950. "SUBS r4, r4, r5\n\t"
  18951. "IT hi\n\t"
  18952. "movhi r2, r8\n\t"
  18953. "IT lo\n\t"
  18954. "movlo r2, r3\n\t"
  18955. "IT ne\n\t"
  18956. "movne r3, r7\n\t"
  18957. "LDR r4, [%[a], #312]\n\t"
  18958. "LDR r5, [%[b], #312]\n\t"
  18959. "AND r4, r4, r3\n\t"
  18960. "AND r5, r5, r3\n\t"
  18961. "SUBS r4, r4, r5\n\t"
  18962. "IT hi\n\t"
  18963. "movhi r2, r8\n\t"
  18964. "IT lo\n\t"
  18965. "movlo r2, r3\n\t"
  18966. "IT ne\n\t"
  18967. "movne r3, r7\n\t"
  18968. "LDR r4, [%[a], #308]\n\t"
  18969. "LDR r5, [%[b], #308]\n\t"
  18970. "AND r4, r4, r3\n\t"
  18971. "AND r5, r5, r3\n\t"
  18972. "SUBS r4, r4, r5\n\t"
  18973. "IT hi\n\t"
  18974. "movhi r2, r8\n\t"
  18975. "IT lo\n\t"
  18976. "movlo r2, r3\n\t"
  18977. "IT ne\n\t"
  18978. "movne r3, r7\n\t"
  18979. "LDR r4, [%[a], #304]\n\t"
  18980. "LDR r5, [%[b], #304]\n\t"
  18981. "AND r4, r4, r3\n\t"
  18982. "AND r5, r5, r3\n\t"
  18983. "SUBS r4, r4, r5\n\t"
  18984. "IT hi\n\t"
  18985. "movhi r2, r8\n\t"
  18986. "IT lo\n\t"
  18987. "movlo r2, r3\n\t"
  18988. "IT ne\n\t"
  18989. "movne r3, r7\n\t"
  18990. "LDR r4, [%[a], #300]\n\t"
  18991. "LDR r5, [%[b], #300]\n\t"
  18992. "AND r4, r4, r3\n\t"
  18993. "AND r5, r5, r3\n\t"
  18994. "SUBS r4, r4, r5\n\t"
  18995. "IT hi\n\t"
  18996. "movhi r2, r8\n\t"
  18997. "IT lo\n\t"
  18998. "movlo r2, r3\n\t"
  18999. "IT ne\n\t"
  19000. "movne r3, r7\n\t"
  19001. "LDR r4, [%[a], #296]\n\t"
  19002. "LDR r5, [%[b], #296]\n\t"
  19003. "AND r4, r4, r3\n\t"
  19004. "AND r5, r5, r3\n\t"
  19005. "SUBS r4, r4, r5\n\t"
  19006. "IT hi\n\t"
  19007. "movhi r2, r8\n\t"
  19008. "IT lo\n\t"
  19009. "movlo r2, r3\n\t"
  19010. "IT ne\n\t"
  19011. "movne r3, r7\n\t"
  19012. "LDR r4, [%[a], #292]\n\t"
  19013. "LDR r5, [%[b], #292]\n\t"
  19014. "AND r4, r4, r3\n\t"
  19015. "AND r5, r5, r3\n\t"
  19016. "SUBS r4, r4, r5\n\t"
  19017. "IT hi\n\t"
  19018. "movhi r2, r8\n\t"
  19019. "IT lo\n\t"
  19020. "movlo r2, r3\n\t"
  19021. "IT ne\n\t"
  19022. "movne r3, r7\n\t"
  19023. "LDR r4, [%[a], #288]\n\t"
  19024. "LDR r5, [%[b], #288]\n\t"
  19025. "AND r4, r4, r3\n\t"
  19026. "AND r5, r5, r3\n\t"
  19027. "SUBS r4, r4, r5\n\t"
  19028. "IT hi\n\t"
  19029. "movhi r2, r8\n\t"
  19030. "IT lo\n\t"
  19031. "movlo r2, r3\n\t"
  19032. "IT ne\n\t"
  19033. "movne r3, r7\n\t"
  19034. "LDR r4, [%[a], #284]\n\t"
  19035. "LDR r5, [%[b], #284]\n\t"
  19036. "AND r4, r4, r3\n\t"
  19037. "AND r5, r5, r3\n\t"
  19038. "SUBS r4, r4, r5\n\t"
  19039. "IT hi\n\t"
  19040. "movhi r2, r8\n\t"
  19041. "IT lo\n\t"
  19042. "movlo r2, r3\n\t"
  19043. "IT ne\n\t"
  19044. "movne r3, r7\n\t"
  19045. "LDR r4, [%[a], #280]\n\t"
  19046. "LDR r5, [%[b], #280]\n\t"
  19047. "AND r4, r4, r3\n\t"
  19048. "AND r5, r5, r3\n\t"
  19049. "SUBS r4, r4, r5\n\t"
  19050. "IT hi\n\t"
  19051. "movhi r2, r8\n\t"
  19052. "IT lo\n\t"
  19053. "movlo r2, r3\n\t"
  19054. "IT ne\n\t"
  19055. "movne r3, r7\n\t"
  19056. "LDR r4, [%[a], #276]\n\t"
  19057. "LDR r5, [%[b], #276]\n\t"
  19058. "AND r4, r4, r3\n\t"
  19059. "AND r5, r5, r3\n\t"
  19060. "SUBS r4, r4, r5\n\t"
  19061. "IT hi\n\t"
  19062. "movhi r2, r8\n\t"
  19063. "IT lo\n\t"
  19064. "movlo r2, r3\n\t"
  19065. "IT ne\n\t"
  19066. "movne r3, r7\n\t"
  19067. "LDR r4, [%[a], #272]\n\t"
  19068. "LDR r5, [%[b], #272]\n\t"
  19069. "AND r4, r4, r3\n\t"
  19070. "AND r5, r5, r3\n\t"
  19071. "SUBS r4, r4, r5\n\t"
  19072. "IT hi\n\t"
  19073. "movhi r2, r8\n\t"
  19074. "IT lo\n\t"
  19075. "movlo r2, r3\n\t"
  19076. "IT ne\n\t"
  19077. "movne r3, r7\n\t"
  19078. "LDR r4, [%[a], #268]\n\t"
  19079. "LDR r5, [%[b], #268]\n\t"
  19080. "AND r4, r4, r3\n\t"
  19081. "AND r5, r5, r3\n\t"
  19082. "SUBS r4, r4, r5\n\t"
  19083. "IT hi\n\t"
  19084. "movhi r2, r8\n\t"
  19085. "IT lo\n\t"
  19086. "movlo r2, r3\n\t"
  19087. "IT ne\n\t"
  19088. "movne r3, r7\n\t"
  19089. "LDR r4, [%[a], #264]\n\t"
  19090. "LDR r5, [%[b], #264]\n\t"
  19091. "AND r4, r4, r3\n\t"
  19092. "AND r5, r5, r3\n\t"
  19093. "SUBS r4, r4, r5\n\t"
  19094. "IT hi\n\t"
  19095. "movhi r2, r8\n\t"
  19096. "IT lo\n\t"
  19097. "movlo r2, r3\n\t"
  19098. "IT ne\n\t"
  19099. "movne r3, r7\n\t"
  19100. "LDR r4, [%[a], #260]\n\t"
  19101. "LDR r5, [%[b], #260]\n\t"
  19102. "AND r4, r4, r3\n\t"
  19103. "AND r5, r5, r3\n\t"
  19104. "SUBS r4, r4, r5\n\t"
  19105. "IT hi\n\t"
  19106. "movhi r2, r8\n\t"
  19107. "IT lo\n\t"
  19108. "movlo r2, r3\n\t"
  19109. "IT ne\n\t"
  19110. "movne r3, r7\n\t"
  19111. "LDR r4, [%[a], #256]\n\t"
  19112. "LDR r5, [%[b], #256]\n\t"
  19113. "AND r4, r4, r3\n\t"
  19114. "AND r5, r5, r3\n\t"
  19115. "SUBS r4, r4, r5\n\t"
  19116. "IT hi\n\t"
  19117. "movhi r2, r8\n\t"
  19118. "IT lo\n\t"
  19119. "movlo r2, r3\n\t"
  19120. "IT ne\n\t"
  19121. "movne r3, r7\n\t"
  19122. "LDR r4, [%[a], #252]\n\t"
  19123. "LDR r5, [%[b], #252]\n\t"
  19124. "AND r4, r4, r3\n\t"
  19125. "AND r5, r5, r3\n\t"
  19126. "SUBS r4, r4, r5\n\t"
  19127. "IT hi\n\t"
  19128. "movhi r2, r8\n\t"
  19129. "IT lo\n\t"
  19130. "movlo r2, r3\n\t"
  19131. "IT ne\n\t"
  19132. "movne r3, r7\n\t"
  19133. "LDR r4, [%[a], #248]\n\t"
  19134. "LDR r5, [%[b], #248]\n\t"
  19135. "AND r4, r4, r3\n\t"
  19136. "AND r5, r5, r3\n\t"
  19137. "SUBS r4, r4, r5\n\t"
  19138. "IT hi\n\t"
  19139. "movhi r2, r8\n\t"
  19140. "IT lo\n\t"
  19141. "movlo r2, r3\n\t"
  19142. "IT ne\n\t"
  19143. "movne r3, r7\n\t"
  19144. "LDR r4, [%[a], #244]\n\t"
  19145. "LDR r5, [%[b], #244]\n\t"
  19146. "AND r4, r4, r3\n\t"
  19147. "AND r5, r5, r3\n\t"
  19148. "SUBS r4, r4, r5\n\t"
  19149. "IT hi\n\t"
  19150. "movhi r2, r8\n\t"
  19151. "IT lo\n\t"
  19152. "movlo r2, r3\n\t"
  19153. "IT ne\n\t"
  19154. "movne r3, r7\n\t"
  19155. "LDR r4, [%[a], #240]\n\t"
  19156. "LDR r5, [%[b], #240]\n\t"
  19157. "AND r4, r4, r3\n\t"
  19158. "AND r5, r5, r3\n\t"
  19159. "SUBS r4, r4, r5\n\t"
  19160. "IT hi\n\t"
  19161. "movhi r2, r8\n\t"
  19162. "IT lo\n\t"
  19163. "movlo r2, r3\n\t"
  19164. "IT ne\n\t"
  19165. "movne r3, r7\n\t"
  19166. "LDR r4, [%[a], #236]\n\t"
  19167. "LDR r5, [%[b], #236]\n\t"
  19168. "AND r4, r4, r3\n\t"
  19169. "AND r5, r5, r3\n\t"
  19170. "SUBS r4, r4, r5\n\t"
  19171. "IT hi\n\t"
  19172. "movhi r2, r8\n\t"
  19173. "IT lo\n\t"
  19174. "movlo r2, r3\n\t"
  19175. "IT ne\n\t"
  19176. "movne r3, r7\n\t"
  19177. "LDR r4, [%[a], #232]\n\t"
  19178. "LDR r5, [%[b], #232]\n\t"
  19179. "AND r4, r4, r3\n\t"
  19180. "AND r5, r5, r3\n\t"
  19181. "SUBS r4, r4, r5\n\t"
  19182. "IT hi\n\t"
  19183. "movhi r2, r8\n\t"
  19184. "IT lo\n\t"
  19185. "movlo r2, r3\n\t"
  19186. "IT ne\n\t"
  19187. "movne r3, r7\n\t"
  19188. "LDR r4, [%[a], #228]\n\t"
  19189. "LDR r5, [%[b], #228]\n\t"
  19190. "AND r4, r4, r3\n\t"
  19191. "AND r5, r5, r3\n\t"
  19192. "SUBS r4, r4, r5\n\t"
  19193. "IT hi\n\t"
  19194. "movhi r2, r8\n\t"
  19195. "IT lo\n\t"
  19196. "movlo r2, r3\n\t"
  19197. "IT ne\n\t"
  19198. "movne r3, r7\n\t"
  19199. "LDR r4, [%[a], #224]\n\t"
  19200. "LDR r5, [%[b], #224]\n\t"
  19201. "AND r4, r4, r3\n\t"
  19202. "AND r5, r5, r3\n\t"
  19203. "SUBS r4, r4, r5\n\t"
  19204. "IT hi\n\t"
  19205. "movhi r2, r8\n\t"
  19206. "IT lo\n\t"
  19207. "movlo r2, r3\n\t"
  19208. "IT ne\n\t"
  19209. "movne r3, r7\n\t"
  19210. "LDR r4, [%[a], #220]\n\t"
  19211. "LDR r5, [%[b], #220]\n\t"
  19212. "AND r4, r4, r3\n\t"
  19213. "AND r5, r5, r3\n\t"
  19214. "SUBS r4, r4, r5\n\t"
  19215. "IT hi\n\t"
  19216. "movhi r2, r8\n\t"
  19217. "IT lo\n\t"
  19218. "movlo r2, r3\n\t"
  19219. "IT ne\n\t"
  19220. "movne r3, r7\n\t"
  19221. "LDR r4, [%[a], #216]\n\t"
  19222. "LDR r5, [%[b], #216]\n\t"
  19223. "AND r4, r4, r3\n\t"
  19224. "AND r5, r5, r3\n\t"
  19225. "SUBS r4, r4, r5\n\t"
  19226. "IT hi\n\t"
  19227. "movhi r2, r8\n\t"
  19228. "IT lo\n\t"
  19229. "movlo r2, r3\n\t"
  19230. "IT ne\n\t"
  19231. "movne r3, r7\n\t"
  19232. "LDR r4, [%[a], #212]\n\t"
  19233. "LDR r5, [%[b], #212]\n\t"
  19234. "AND r4, r4, r3\n\t"
  19235. "AND r5, r5, r3\n\t"
  19236. "SUBS r4, r4, r5\n\t"
  19237. "IT hi\n\t"
  19238. "movhi r2, r8\n\t"
  19239. "IT lo\n\t"
  19240. "movlo r2, r3\n\t"
  19241. "IT ne\n\t"
  19242. "movne r3, r7\n\t"
  19243. "LDR r4, [%[a], #208]\n\t"
  19244. "LDR r5, [%[b], #208]\n\t"
  19245. "AND r4, r4, r3\n\t"
  19246. "AND r5, r5, r3\n\t"
  19247. "SUBS r4, r4, r5\n\t"
  19248. "IT hi\n\t"
  19249. "movhi r2, r8\n\t"
  19250. "IT lo\n\t"
  19251. "movlo r2, r3\n\t"
  19252. "IT ne\n\t"
  19253. "movne r3, r7\n\t"
  19254. "LDR r4, [%[a], #204]\n\t"
  19255. "LDR r5, [%[b], #204]\n\t"
  19256. "AND r4, r4, r3\n\t"
  19257. "AND r5, r5, r3\n\t"
  19258. "SUBS r4, r4, r5\n\t"
  19259. "IT hi\n\t"
  19260. "movhi r2, r8\n\t"
  19261. "IT lo\n\t"
  19262. "movlo r2, r3\n\t"
  19263. "IT ne\n\t"
  19264. "movne r3, r7\n\t"
  19265. "LDR r4, [%[a], #200]\n\t"
  19266. "LDR r5, [%[b], #200]\n\t"
  19267. "AND r4, r4, r3\n\t"
  19268. "AND r5, r5, r3\n\t"
  19269. "SUBS r4, r4, r5\n\t"
  19270. "IT hi\n\t"
  19271. "movhi r2, r8\n\t"
  19272. "IT lo\n\t"
  19273. "movlo r2, r3\n\t"
  19274. "IT ne\n\t"
  19275. "movne r3, r7\n\t"
  19276. "LDR r4, [%[a], #196]\n\t"
  19277. "LDR r5, [%[b], #196]\n\t"
  19278. "AND r4, r4, r3\n\t"
  19279. "AND r5, r5, r3\n\t"
  19280. "SUBS r4, r4, r5\n\t"
  19281. "IT hi\n\t"
  19282. "movhi r2, r8\n\t"
  19283. "IT lo\n\t"
  19284. "movlo r2, r3\n\t"
  19285. "IT ne\n\t"
  19286. "movne r3, r7\n\t"
  19287. "LDR r4, [%[a], #192]\n\t"
  19288. "LDR r5, [%[b], #192]\n\t"
  19289. "AND r4, r4, r3\n\t"
  19290. "AND r5, r5, r3\n\t"
  19291. "SUBS r4, r4, r5\n\t"
  19292. "IT hi\n\t"
  19293. "movhi r2, r8\n\t"
  19294. "IT lo\n\t"
  19295. "movlo r2, r3\n\t"
  19296. "IT ne\n\t"
  19297. "movne r3, r7\n\t"
  19298. "LDR r4, [%[a], #188]\n\t"
  19299. "LDR r5, [%[b], #188]\n\t"
  19300. "AND r4, r4, r3\n\t"
  19301. "AND r5, r5, r3\n\t"
  19302. "SUBS r4, r4, r5\n\t"
  19303. "IT hi\n\t"
  19304. "movhi r2, r8\n\t"
  19305. "IT lo\n\t"
  19306. "movlo r2, r3\n\t"
  19307. "IT ne\n\t"
  19308. "movne r3, r7\n\t"
  19309. "LDR r4, [%[a], #184]\n\t"
  19310. "LDR r5, [%[b], #184]\n\t"
  19311. "AND r4, r4, r3\n\t"
  19312. "AND r5, r5, r3\n\t"
  19313. "SUBS r4, r4, r5\n\t"
  19314. "IT hi\n\t"
  19315. "movhi r2, r8\n\t"
  19316. "IT lo\n\t"
  19317. "movlo r2, r3\n\t"
  19318. "IT ne\n\t"
  19319. "movne r3, r7\n\t"
  19320. "LDR r4, [%[a], #180]\n\t"
  19321. "LDR r5, [%[b], #180]\n\t"
  19322. "AND r4, r4, r3\n\t"
  19323. "AND r5, r5, r3\n\t"
  19324. "SUBS r4, r4, r5\n\t"
  19325. "IT hi\n\t"
  19326. "movhi r2, r8\n\t"
  19327. "IT lo\n\t"
  19328. "movlo r2, r3\n\t"
  19329. "IT ne\n\t"
  19330. "movne r3, r7\n\t"
  19331. "LDR r4, [%[a], #176]\n\t"
  19332. "LDR r5, [%[b], #176]\n\t"
  19333. "AND r4, r4, r3\n\t"
  19334. "AND r5, r5, r3\n\t"
  19335. "SUBS r4, r4, r5\n\t"
  19336. "IT hi\n\t"
  19337. "movhi r2, r8\n\t"
  19338. "IT lo\n\t"
  19339. "movlo r2, r3\n\t"
  19340. "IT ne\n\t"
  19341. "movne r3, r7\n\t"
  19342. "LDR r4, [%[a], #172]\n\t"
  19343. "LDR r5, [%[b], #172]\n\t"
  19344. "AND r4, r4, r3\n\t"
  19345. "AND r5, r5, r3\n\t"
  19346. "SUBS r4, r4, r5\n\t"
  19347. "IT hi\n\t"
  19348. "movhi r2, r8\n\t"
  19349. "IT lo\n\t"
  19350. "movlo r2, r3\n\t"
  19351. "IT ne\n\t"
  19352. "movne r3, r7\n\t"
  19353. "LDR r4, [%[a], #168]\n\t"
  19354. "LDR r5, [%[b], #168]\n\t"
  19355. "AND r4, r4, r3\n\t"
  19356. "AND r5, r5, r3\n\t"
  19357. "SUBS r4, r4, r5\n\t"
  19358. "IT hi\n\t"
  19359. "movhi r2, r8\n\t"
  19360. "IT lo\n\t"
  19361. "movlo r2, r3\n\t"
  19362. "IT ne\n\t"
  19363. "movne r3, r7\n\t"
  19364. "LDR r4, [%[a], #164]\n\t"
  19365. "LDR r5, [%[b], #164]\n\t"
  19366. "AND r4, r4, r3\n\t"
  19367. "AND r5, r5, r3\n\t"
  19368. "SUBS r4, r4, r5\n\t"
  19369. "IT hi\n\t"
  19370. "movhi r2, r8\n\t"
  19371. "IT lo\n\t"
  19372. "movlo r2, r3\n\t"
  19373. "IT ne\n\t"
  19374. "movne r3, r7\n\t"
  19375. "LDR r4, [%[a], #160]\n\t"
  19376. "LDR r5, [%[b], #160]\n\t"
  19377. "AND r4, r4, r3\n\t"
  19378. "AND r5, r5, r3\n\t"
  19379. "SUBS r4, r4, r5\n\t"
  19380. "IT hi\n\t"
  19381. "movhi r2, r8\n\t"
  19382. "IT lo\n\t"
  19383. "movlo r2, r3\n\t"
  19384. "IT ne\n\t"
  19385. "movne r3, r7\n\t"
  19386. "LDR r4, [%[a], #156]\n\t"
  19387. "LDR r5, [%[b], #156]\n\t"
  19388. "AND r4, r4, r3\n\t"
  19389. "AND r5, r5, r3\n\t"
  19390. "SUBS r4, r4, r5\n\t"
  19391. "IT hi\n\t"
  19392. "movhi r2, r8\n\t"
  19393. "IT lo\n\t"
  19394. "movlo r2, r3\n\t"
  19395. "IT ne\n\t"
  19396. "movne r3, r7\n\t"
  19397. "LDR r4, [%[a], #152]\n\t"
  19398. "LDR r5, [%[b], #152]\n\t"
  19399. "AND r4, r4, r3\n\t"
  19400. "AND r5, r5, r3\n\t"
  19401. "SUBS r4, r4, r5\n\t"
  19402. "IT hi\n\t"
  19403. "movhi r2, r8\n\t"
  19404. "IT lo\n\t"
  19405. "movlo r2, r3\n\t"
  19406. "IT ne\n\t"
  19407. "movne r3, r7\n\t"
  19408. "LDR r4, [%[a], #148]\n\t"
  19409. "LDR r5, [%[b], #148]\n\t"
  19410. "AND r4, r4, r3\n\t"
  19411. "AND r5, r5, r3\n\t"
  19412. "SUBS r4, r4, r5\n\t"
  19413. "IT hi\n\t"
  19414. "movhi r2, r8\n\t"
  19415. "IT lo\n\t"
  19416. "movlo r2, r3\n\t"
  19417. "IT ne\n\t"
  19418. "movne r3, r7\n\t"
  19419. "LDR r4, [%[a], #144]\n\t"
  19420. "LDR r5, [%[b], #144]\n\t"
  19421. "AND r4, r4, r3\n\t"
  19422. "AND r5, r5, r3\n\t"
  19423. "SUBS r4, r4, r5\n\t"
  19424. "IT hi\n\t"
  19425. "movhi r2, r8\n\t"
  19426. "IT lo\n\t"
  19427. "movlo r2, r3\n\t"
  19428. "IT ne\n\t"
  19429. "movne r3, r7\n\t"
  19430. "LDR r4, [%[a], #140]\n\t"
  19431. "LDR r5, [%[b], #140]\n\t"
  19432. "AND r4, r4, r3\n\t"
  19433. "AND r5, r5, r3\n\t"
  19434. "SUBS r4, r4, r5\n\t"
  19435. "IT hi\n\t"
  19436. "movhi r2, r8\n\t"
  19437. "IT lo\n\t"
  19438. "movlo r2, r3\n\t"
  19439. "IT ne\n\t"
  19440. "movne r3, r7\n\t"
  19441. "LDR r4, [%[a], #136]\n\t"
  19442. "LDR r5, [%[b], #136]\n\t"
  19443. "AND r4, r4, r3\n\t"
  19444. "AND r5, r5, r3\n\t"
  19445. "SUBS r4, r4, r5\n\t"
  19446. "IT hi\n\t"
  19447. "movhi r2, r8\n\t"
  19448. "IT lo\n\t"
  19449. "movlo r2, r3\n\t"
  19450. "IT ne\n\t"
  19451. "movne r3, r7\n\t"
  19452. "LDR r4, [%[a], #132]\n\t"
  19453. "LDR r5, [%[b], #132]\n\t"
  19454. "AND r4, r4, r3\n\t"
  19455. "AND r5, r5, r3\n\t"
  19456. "SUBS r4, r4, r5\n\t"
  19457. "IT hi\n\t"
  19458. "movhi r2, r8\n\t"
  19459. "IT lo\n\t"
  19460. "movlo r2, r3\n\t"
  19461. "IT ne\n\t"
  19462. "movne r3, r7\n\t"
  19463. "LDR r4, [%[a], #128]\n\t"
  19464. "LDR r5, [%[b], #128]\n\t"
  19465. "AND r4, r4, r3\n\t"
  19466. "AND r5, r5, r3\n\t"
  19467. "SUBS r4, r4, r5\n\t"
  19468. "IT hi\n\t"
  19469. "movhi r2, r8\n\t"
  19470. "IT lo\n\t"
  19471. "movlo r2, r3\n\t"
  19472. "IT ne\n\t"
  19473. "movne r3, r7\n\t"
  19474. "LDR r4, [%[a], #124]\n\t"
  19475. "LDR r5, [%[b], #124]\n\t"
  19476. "AND r4, r4, r3\n\t"
  19477. "AND r5, r5, r3\n\t"
  19478. "SUBS r4, r4, r5\n\t"
  19479. "IT hi\n\t"
  19480. "movhi r2, r8\n\t"
  19481. "IT lo\n\t"
  19482. "movlo r2, r3\n\t"
  19483. "IT ne\n\t"
  19484. "movne r3, r7\n\t"
  19485. "LDR r4, [%[a], #120]\n\t"
  19486. "LDR r5, [%[b], #120]\n\t"
  19487. "AND r4, r4, r3\n\t"
  19488. "AND r5, r5, r3\n\t"
  19489. "SUBS r4, r4, r5\n\t"
  19490. "IT hi\n\t"
  19491. "movhi r2, r8\n\t"
  19492. "IT lo\n\t"
  19493. "movlo r2, r3\n\t"
  19494. "IT ne\n\t"
  19495. "movne r3, r7\n\t"
  19496. "LDR r4, [%[a], #116]\n\t"
  19497. "LDR r5, [%[b], #116]\n\t"
  19498. "AND r4, r4, r3\n\t"
  19499. "AND r5, r5, r3\n\t"
  19500. "SUBS r4, r4, r5\n\t"
  19501. "IT hi\n\t"
  19502. "movhi r2, r8\n\t"
  19503. "IT lo\n\t"
  19504. "movlo r2, r3\n\t"
  19505. "IT ne\n\t"
  19506. "movne r3, r7\n\t"
  19507. "LDR r4, [%[a], #112]\n\t"
  19508. "LDR r5, [%[b], #112]\n\t"
  19509. "AND r4, r4, r3\n\t"
  19510. "AND r5, r5, r3\n\t"
  19511. "SUBS r4, r4, r5\n\t"
  19512. "IT hi\n\t"
  19513. "movhi r2, r8\n\t"
  19514. "IT lo\n\t"
  19515. "movlo r2, r3\n\t"
  19516. "IT ne\n\t"
  19517. "movne r3, r7\n\t"
  19518. "LDR r4, [%[a], #108]\n\t"
  19519. "LDR r5, [%[b], #108]\n\t"
  19520. "AND r4, r4, r3\n\t"
  19521. "AND r5, r5, r3\n\t"
  19522. "SUBS r4, r4, r5\n\t"
  19523. "IT hi\n\t"
  19524. "movhi r2, r8\n\t"
  19525. "IT lo\n\t"
  19526. "movlo r2, r3\n\t"
  19527. "IT ne\n\t"
  19528. "movne r3, r7\n\t"
  19529. "LDR r4, [%[a], #104]\n\t"
  19530. "LDR r5, [%[b], #104]\n\t"
  19531. "AND r4, r4, r3\n\t"
  19532. "AND r5, r5, r3\n\t"
  19533. "SUBS r4, r4, r5\n\t"
  19534. "IT hi\n\t"
  19535. "movhi r2, r8\n\t"
  19536. "IT lo\n\t"
  19537. "movlo r2, r3\n\t"
  19538. "IT ne\n\t"
  19539. "movne r3, r7\n\t"
  19540. "LDR r4, [%[a], #100]\n\t"
  19541. "LDR r5, [%[b], #100]\n\t"
  19542. "AND r4, r4, r3\n\t"
  19543. "AND r5, r5, r3\n\t"
  19544. "SUBS r4, r4, r5\n\t"
  19545. "IT hi\n\t"
  19546. "movhi r2, r8\n\t"
  19547. "IT lo\n\t"
  19548. "movlo r2, r3\n\t"
  19549. "IT ne\n\t"
  19550. "movne r3, r7\n\t"
  19551. "LDR r4, [%[a], #96]\n\t"
  19552. "LDR r5, [%[b], #96]\n\t"
  19553. "AND r4, r4, r3\n\t"
  19554. "AND r5, r5, r3\n\t"
  19555. "SUBS r4, r4, r5\n\t"
  19556. "IT hi\n\t"
  19557. "movhi r2, r8\n\t"
  19558. "IT lo\n\t"
  19559. "movlo r2, r3\n\t"
  19560. "IT ne\n\t"
  19561. "movne r3, r7\n\t"
  19562. "LDR r4, [%[a], #92]\n\t"
  19563. "LDR r5, [%[b], #92]\n\t"
  19564. "AND r4, r4, r3\n\t"
  19565. "AND r5, r5, r3\n\t"
  19566. "SUBS r4, r4, r5\n\t"
  19567. "IT hi\n\t"
  19568. "movhi r2, r8\n\t"
  19569. "IT lo\n\t"
  19570. "movlo r2, r3\n\t"
  19571. "IT ne\n\t"
  19572. "movne r3, r7\n\t"
  19573. "LDR r4, [%[a], #88]\n\t"
  19574. "LDR r5, [%[b], #88]\n\t"
  19575. "AND r4, r4, r3\n\t"
  19576. "AND r5, r5, r3\n\t"
  19577. "SUBS r4, r4, r5\n\t"
  19578. "IT hi\n\t"
  19579. "movhi r2, r8\n\t"
  19580. "IT lo\n\t"
  19581. "movlo r2, r3\n\t"
  19582. "IT ne\n\t"
  19583. "movne r3, r7\n\t"
  19584. "LDR r4, [%[a], #84]\n\t"
  19585. "LDR r5, [%[b], #84]\n\t"
  19586. "AND r4, r4, r3\n\t"
  19587. "AND r5, r5, r3\n\t"
  19588. "SUBS r4, r4, r5\n\t"
  19589. "IT hi\n\t"
  19590. "movhi r2, r8\n\t"
  19591. "IT lo\n\t"
  19592. "movlo r2, r3\n\t"
  19593. "IT ne\n\t"
  19594. "movne r3, r7\n\t"
  19595. "LDR r4, [%[a], #80]\n\t"
  19596. "LDR r5, [%[b], #80]\n\t"
  19597. "AND r4, r4, r3\n\t"
  19598. "AND r5, r5, r3\n\t"
  19599. "SUBS r4, r4, r5\n\t"
  19600. "IT hi\n\t"
  19601. "movhi r2, r8\n\t"
  19602. "IT lo\n\t"
  19603. "movlo r2, r3\n\t"
  19604. "IT ne\n\t"
  19605. "movne r3, r7\n\t"
  19606. "LDR r4, [%[a], #76]\n\t"
  19607. "LDR r5, [%[b], #76]\n\t"
  19608. "AND r4, r4, r3\n\t"
  19609. "AND r5, r5, r3\n\t"
  19610. "SUBS r4, r4, r5\n\t"
  19611. "IT hi\n\t"
  19612. "movhi r2, r8\n\t"
  19613. "IT lo\n\t"
  19614. "movlo r2, r3\n\t"
  19615. "IT ne\n\t"
  19616. "movne r3, r7\n\t"
  19617. "LDR r4, [%[a], #72]\n\t"
  19618. "LDR r5, [%[b], #72]\n\t"
  19619. "AND r4, r4, r3\n\t"
  19620. "AND r5, r5, r3\n\t"
  19621. "SUBS r4, r4, r5\n\t"
  19622. "IT hi\n\t"
  19623. "movhi r2, r8\n\t"
  19624. "IT lo\n\t"
  19625. "movlo r2, r3\n\t"
  19626. "IT ne\n\t"
  19627. "movne r3, r7\n\t"
  19628. "LDR r4, [%[a], #68]\n\t"
  19629. "LDR r5, [%[b], #68]\n\t"
  19630. "AND r4, r4, r3\n\t"
  19631. "AND r5, r5, r3\n\t"
  19632. "SUBS r4, r4, r5\n\t"
  19633. "IT hi\n\t"
  19634. "movhi r2, r8\n\t"
  19635. "IT lo\n\t"
  19636. "movlo r2, r3\n\t"
  19637. "IT ne\n\t"
  19638. "movne r3, r7\n\t"
  19639. "LDR r4, [%[a], #64]\n\t"
  19640. "LDR r5, [%[b], #64]\n\t"
  19641. "AND r4, r4, r3\n\t"
  19642. "AND r5, r5, r3\n\t"
  19643. "SUBS r4, r4, r5\n\t"
  19644. "IT hi\n\t"
  19645. "movhi r2, r8\n\t"
  19646. "IT lo\n\t"
  19647. "movlo r2, r3\n\t"
  19648. "IT ne\n\t"
  19649. "movne r3, r7\n\t"
  19650. "LDR r4, [%[a], #60]\n\t"
  19651. "LDR r5, [%[b], #60]\n\t"
  19652. "AND r4, r4, r3\n\t"
  19653. "AND r5, r5, r3\n\t"
  19654. "SUBS r4, r4, r5\n\t"
  19655. "IT hi\n\t"
  19656. "movhi r2, r8\n\t"
  19657. "IT lo\n\t"
  19658. "movlo r2, r3\n\t"
  19659. "IT ne\n\t"
  19660. "movne r3, r7\n\t"
  19661. "LDR r4, [%[a], #56]\n\t"
  19662. "LDR r5, [%[b], #56]\n\t"
  19663. "AND r4, r4, r3\n\t"
  19664. "AND r5, r5, r3\n\t"
  19665. "SUBS r4, r4, r5\n\t"
  19666. "IT hi\n\t"
  19667. "movhi r2, r8\n\t"
  19668. "IT lo\n\t"
  19669. "movlo r2, r3\n\t"
  19670. "IT ne\n\t"
  19671. "movne r3, r7\n\t"
  19672. "LDR r4, [%[a], #52]\n\t"
  19673. "LDR r5, [%[b], #52]\n\t"
  19674. "AND r4, r4, r3\n\t"
  19675. "AND r5, r5, r3\n\t"
  19676. "SUBS r4, r4, r5\n\t"
  19677. "IT hi\n\t"
  19678. "movhi r2, r8\n\t"
  19679. "IT lo\n\t"
  19680. "movlo r2, r3\n\t"
  19681. "IT ne\n\t"
  19682. "movne r3, r7\n\t"
  19683. "LDR r4, [%[a], #48]\n\t"
  19684. "LDR r5, [%[b], #48]\n\t"
  19685. "AND r4, r4, r3\n\t"
  19686. "AND r5, r5, r3\n\t"
  19687. "SUBS r4, r4, r5\n\t"
  19688. "IT hi\n\t"
  19689. "movhi r2, r8\n\t"
  19690. "IT lo\n\t"
  19691. "movlo r2, r3\n\t"
  19692. "IT ne\n\t"
  19693. "movne r3, r7\n\t"
  19694. "LDR r4, [%[a], #44]\n\t"
  19695. "LDR r5, [%[b], #44]\n\t"
  19696. "AND r4, r4, r3\n\t"
  19697. "AND r5, r5, r3\n\t"
  19698. "SUBS r4, r4, r5\n\t"
  19699. "IT hi\n\t"
  19700. "movhi r2, r8\n\t"
  19701. "IT lo\n\t"
  19702. "movlo r2, r3\n\t"
  19703. "IT ne\n\t"
  19704. "movne r3, r7\n\t"
  19705. "LDR r4, [%[a], #40]\n\t"
  19706. "LDR r5, [%[b], #40]\n\t"
  19707. "AND r4, r4, r3\n\t"
  19708. "AND r5, r5, r3\n\t"
  19709. "SUBS r4, r4, r5\n\t"
  19710. "IT hi\n\t"
  19711. "movhi r2, r8\n\t"
  19712. "IT lo\n\t"
  19713. "movlo r2, r3\n\t"
  19714. "IT ne\n\t"
  19715. "movne r3, r7\n\t"
  19716. "LDR r4, [%[a], #36]\n\t"
  19717. "LDR r5, [%[b], #36]\n\t"
  19718. "AND r4, r4, r3\n\t"
  19719. "AND r5, r5, r3\n\t"
  19720. "SUBS r4, r4, r5\n\t"
  19721. "IT hi\n\t"
  19722. "movhi r2, r8\n\t"
  19723. "IT lo\n\t"
  19724. "movlo r2, r3\n\t"
  19725. "IT ne\n\t"
  19726. "movne r3, r7\n\t"
  19727. "LDR r4, [%[a], #32]\n\t"
  19728. "LDR r5, [%[b], #32]\n\t"
  19729. "AND r4, r4, r3\n\t"
  19730. "AND r5, r5, r3\n\t"
  19731. "SUBS r4, r4, r5\n\t"
  19732. "IT hi\n\t"
  19733. "movhi r2, r8\n\t"
  19734. "IT lo\n\t"
  19735. "movlo r2, r3\n\t"
  19736. "IT ne\n\t"
  19737. "movne r3, r7\n\t"
  19738. "LDR r4, [%[a], #28]\n\t"
  19739. "LDR r5, [%[b], #28]\n\t"
  19740. "AND r4, r4, r3\n\t"
  19741. "AND r5, r5, r3\n\t"
  19742. "SUBS r4, r4, r5\n\t"
  19743. "IT hi\n\t"
  19744. "movhi r2, r8\n\t"
  19745. "IT lo\n\t"
  19746. "movlo r2, r3\n\t"
  19747. "IT ne\n\t"
  19748. "movne r3, r7\n\t"
  19749. "LDR r4, [%[a], #24]\n\t"
  19750. "LDR r5, [%[b], #24]\n\t"
  19751. "AND r4, r4, r3\n\t"
  19752. "AND r5, r5, r3\n\t"
  19753. "SUBS r4, r4, r5\n\t"
  19754. "IT hi\n\t"
  19755. "movhi r2, r8\n\t"
  19756. "IT lo\n\t"
  19757. "movlo r2, r3\n\t"
  19758. "IT ne\n\t"
  19759. "movne r3, r7\n\t"
  19760. "LDR r4, [%[a], #20]\n\t"
  19761. "LDR r5, [%[b], #20]\n\t"
  19762. "AND r4, r4, r3\n\t"
  19763. "AND r5, r5, r3\n\t"
  19764. "SUBS r4, r4, r5\n\t"
  19765. "IT hi\n\t"
  19766. "movhi r2, r8\n\t"
  19767. "IT lo\n\t"
  19768. "movlo r2, r3\n\t"
  19769. "IT ne\n\t"
  19770. "movne r3, r7\n\t"
  19771. "LDR r4, [%[a], #16]\n\t"
  19772. "LDR r5, [%[b], #16]\n\t"
  19773. "AND r4, r4, r3\n\t"
  19774. "AND r5, r5, r3\n\t"
  19775. "SUBS r4, r4, r5\n\t"
  19776. "IT hi\n\t"
  19777. "movhi r2, r8\n\t"
  19778. "IT lo\n\t"
  19779. "movlo r2, r3\n\t"
  19780. "IT ne\n\t"
  19781. "movne r3, r7\n\t"
  19782. "LDR r4, [%[a], #12]\n\t"
  19783. "LDR r5, [%[b], #12]\n\t"
  19784. "AND r4, r4, r3\n\t"
  19785. "AND r5, r5, r3\n\t"
  19786. "SUBS r4, r4, r5\n\t"
  19787. "IT hi\n\t"
  19788. "movhi r2, r8\n\t"
  19789. "IT lo\n\t"
  19790. "movlo r2, r3\n\t"
  19791. "IT ne\n\t"
  19792. "movne r3, r7\n\t"
  19793. "LDR r4, [%[a], #8]\n\t"
  19794. "LDR r5, [%[b], #8]\n\t"
  19795. "AND r4, r4, r3\n\t"
  19796. "AND r5, r5, r3\n\t"
  19797. "SUBS r4, r4, r5\n\t"
  19798. "IT hi\n\t"
  19799. "movhi r2, r8\n\t"
  19800. "IT lo\n\t"
  19801. "movlo r2, r3\n\t"
  19802. "IT ne\n\t"
  19803. "movne r3, r7\n\t"
  19804. "LDR r4, [%[a], #4]\n\t"
  19805. "LDR r5, [%[b], #4]\n\t"
  19806. "AND r4, r4, r3\n\t"
  19807. "AND r5, r5, r3\n\t"
  19808. "SUBS r4, r4, r5\n\t"
  19809. "IT hi\n\t"
  19810. "movhi r2, r8\n\t"
  19811. "IT lo\n\t"
  19812. "movlo r2, r3\n\t"
  19813. "IT ne\n\t"
  19814. "movne r3, r7\n\t"
  19815. "LDR r4, [%[a]]\n\t"
  19816. "LDR r5, [%[b]]\n\t"
  19817. "AND r4, r4, r3\n\t"
  19818. "AND r5, r5, r3\n\t"
  19819. "SUBS r4, r4, r5\n\t"
  19820. "IT hi\n\t"
  19821. "movhi r2, r8\n\t"
  19822. "IT lo\n\t"
  19823. "movlo r2, r3\n\t"
  19824. "IT ne\n\t"
  19825. "movne r3, r7\n\t"
  19826. "EOR r2, r2, r3\n\t"
  19827. #endif /*WOLFSSL_SP_SMALL */
  19828. "MOV %[a], r2\n\t"
  19829. : [a] "+r" (a), [b] "+r" (b)
  19830. :
  19831. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  19832. );
  19833. return (uint32_t)(size_t)a;
  19834. }
  19835. /* Divide d in a and put remainder into r (m*d + r = a)
  19836. * m is not calculated as it is not needed at this time.
  19837. *
  19838. * a Number to be divided.
  19839. * d Number to divide with.
  19840. * m Multiplier result.
  19841. * r Remainder from the division.
  19842. * returns MP_OKAY indicating success.
  19843. */
  19844. static WC_INLINE int sp_3072_div_96(const sp_digit* a, const sp_digit* d,
  19845. sp_digit* m, sp_digit* r)
  19846. {
  19847. sp_digit t1[192], t2[97];
  19848. sp_digit div, r1;
  19849. int i;
  19850. (void)m;
  19851. div = d[95];
  19852. XMEMCPY(t1, a, sizeof(*t1) * 2 * 96);
  19853. r1 = sp_3072_cmp_96(&t1[96], d) >= 0;
  19854. sp_3072_cond_sub_96(&t1[96], &t1[96], d, (sp_digit)0 - r1);
  19855. for (i = 95; i >= 0; i--) {
  19856. volatile sp_digit mask = (sp_digit)0 - (t1[96 + i] == div);
  19857. sp_digit hi = t1[96 + i] + mask;
  19858. r1 = div_3072_word_96(hi, t1[96 + i - 1], div);
  19859. r1 |= mask;
  19860. sp_3072_mul_d_96(t2, d, r1);
  19861. t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2);
  19862. t1[96 + i] -= t2[96];
  19863. sp_3072_mask_96(t2, d, t1[96 + i]);
  19864. t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2);
  19865. sp_3072_mask_96(t2, d, t1[96 + i]);
  19866. t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2);
  19867. }
  19868. r1 = sp_3072_cmp_96(t1, d) >= 0;
  19869. sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1);
  19870. return MP_OKAY;
  19871. }
  19872. /* Reduce a modulo m into r. (r = a mod m)
  19873. *
  19874. * r A single precision number that is the reduced result.
  19875. * a A single precision number that is to be reduced.
  19876. * m A single precision number that is the modulus to reduce with.
  19877. * returns MP_OKAY indicating success.
  19878. */
  19879. static WC_INLINE int sp_3072_mod_96(sp_digit* r, const sp_digit* a, const sp_digit* m)
  19880. {
  19881. return sp_3072_div_96(a, m, NULL, r);
  19882. }
  19883. #endif /* WOLFSSL_HAVE_SP_DH || !WOLFSSL_RSA_PUBLIC_ONLY */
  19884. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
  19885. defined(WOLFSSL_HAVE_SP_DH)
  19886. #ifdef WOLFSSL_SP_SMALL
  19887. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  19888. *
  19889. * r A single precision number that is the result of the operation.
  19890. * a A single precision number being exponentiated.
  19891. * e A single precision number that is the exponent.
  19892. * bits The number of bits in the exponent.
  19893. * m A single precision number that is the modulus.
  19894. * returns 0 on success.
  19895. * returns MEMORY_E on dynamic memory allocation failure.
  19896. * returns MP_VAL when base is even or exponent is 0.
  19897. */
  19898. static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
  19899. int bits, const sp_digit* m, int reduceA)
  19900. {
  19901. #ifdef WOLFSSL_SP_SMALL_STACK
  19902. sp_digit* td = NULL;
  19903. #else
  19904. sp_digit td[8 * 192];
  19905. #endif
  19906. sp_digit* t[8];
  19907. sp_digit* norm = NULL;
  19908. sp_digit mp = 1;
  19909. sp_digit n;
  19910. sp_digit mask;
  19911. int i;
  19912. int c;
  19913. byte y;
  19914. int err = MP_OKAY;
  19915. if (bits == 0) {
  19916. err = MP_VAL;
  19917. }
  19918. #ifdef WOLFSSL_SP_SMALL_STACK
  19919. if (err == MP_OKAY) {
  19920. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 * 192), NULL,
  19921. DYNAMIC_TYPE_TMP_BUFFER);
  19922. if (td == NULL)
  19923. err = MEMORY_E;
  19924. }
  19925. #endif
  19926. if (err == MP_OKAY) {
  19927. norm = td;
  19928. for (i=0; i<8; i++) {
  19929. t[i] = td + i * 192;
  19930. }
  19931. sp_3072_mont_setup(m, &mp);
  19932. sp_3072_mont_norm_96(norm, m);
  19933. XMEMSET(t[1], 0, sizeof(sp_digit) * 96U);
  19934. if (reduceA != 0) {
  19935. err = sp_3072_mod_96(t[1] + 96, a, m);
  19936. if (err == MP_OKAY) {
  19937. err = sp_3072_mod_96(t[1], t[1], m);
  19938. }
  19939. }
  19940. else {
  19941. XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96);
  19942. err = sp_3072_mod_96(t[1], t[1], m);
  19943. }
  19944. }
  19945. if (err == MP_OKAY) {
  19946. sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp);
  19947. sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp);
  19948. sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp);
  19949. sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp);
  19950. sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp);
  19951. sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp);
  19952. i = (bits - 1) / 32;
  19953. n = e[i--];
  19954. c = bits & 31;
  19955. if (c == 0) {
  19956. c = 32;
  19957. }
  19958. c -= bits % 3;
  19959. if (c == 32) {
  19960. c = 29;
  19961. }
  19962. if (c < 0) {
  19963. /* Number of bits in top word is less than number needed. */
  19964. c = -c;
  19965. y = (byte)(n << c);
  19966. n = e[i--];
  19967. y |= (byte)(n >> (64 - c));
  19968. n <<= c;
  19969. c = 64 - c;
  19970. }
  19971. else if (c == 0) {
  19972. /* All bits in top word used. */
  19973. y = (byte)n;
  19974. }
  19975. else {
  19976. y = (byte)(n >> c);
  19977. n <<= 32 - c;
  19978. }
  19979. XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
  19980. for (; i>=0 || c>=3; ) {
  19981. if (c == 0) {
  19982. n = e[i--];
  19983. y = (byte)(n >> 29);
  19984. n <<= 3;
  19985. c = 29;
  19986. }
  19987. else if (c < 3) {
  19988. y = (byte)(n >> 29);
  19989. n = e[i--];
  19990. c = 3 - c;
  19991. y |= (byte)(n >> (32 - c));
  19992. n <<= c;
  19993. c = 32 - c;
  19994. }
  19995. else {
  19996. y = (byte)((n >> 29) & 0x7);
  19997. n <<= 3;
  19998. c -= 3;
  19999. }
  20000. sp_3072_mont_sqr_96(r, r, m, mp);
  20001. sp_3072_mont_sqr_96(r, r, m, mp);
  20002. sp_3072_mont_sqr_96(r, r, m, mp);
  20003. sp_3072_mont_mul_96(r, r, t[y], m, mp);
  20004. }
  20005. XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U);
  20006. sp_3072_mont_reduce_96(r, m, mp);
  20007. mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
  20008. sp_3072_cond_sub_96(r, r, m, mask);
  20009. }
  20010. #ifdef WOLFSSL_SP_SMALL_STACK
  20011. if (td != NULL)
  20012. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  20013. #endif
  20014. return err;
  20015. }
  20016. #else
  20017. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  20018. *
  20019. * r A single precision number that is the result of the operation.
  20020. * a A single precision number being exponentiated.
  20021. * e A single precision number that is the exponent.
  20022. * bits The number of bits in the exponent.
  20023. * m A single precision number that is the modulus.
  20024. * returns 0 on success.
  20025. * returns MEMORY_E on dynamic memory allocation failure.
  20026. * returns MP_VAL when base is even or exponent is 0.
  20027. */
  20028. static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e,
  20029. int bits, const sp_digit* m, int reduceA)
  20030. {
  20031. #ifdef WOLFSSL_SP_SMALL_STACK
  20032. sp_digit* td = NULL;
  20033. #else
  20034. sp_digit td[16 * 192];
  20035. #endif
  20036. sp_digit* t[16];
  20037. sp_digit* norm = NULL;
  20038. sp_digit mp = 1;
  20039. sp_digit n;
  20040. sp_digit mask;
  20041. int i;
  20042. int c;
  20043. byte y;
  20044. int err = MP_OKAY;
  20045. if (bits == 0) {
  20046. err = MP_VAL;
  20047. }
  20048. #ifdef WOLFSSL_SP_SMALL_STACK
  20049. if (err == MP_OKAY) {
  20050. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 192), NULL,
  20051. DYNAMIC_TYPE_TMP_BUFFER);
  20052. if (td == NULL)
  20053. err = MEMORY_E;
  20054. }
  20055. #endif
  20056. if (err == MP_OKAY) {
  20057. norm = td;
  20058. for (i=0; i<16; i++) {
  20059. t[i] = td + i * 192;
  20060. }
  20061. sp_3072_mont_setup(m, &mp);
  20062. sp_3072_mont_norm_96(norm, m);
  20063. XMEMSET(t[1], 0, sizeof(sp_digit) * 96U);
  20064. if (reduceA != 0) {
  20065. err = sp_3072_mod_96(t[1] + 96, a, m);
  20066. if (err == MP_OKAY) {
  20067. err = sp_3072_mod_96(t[1], t[1], m);
  20068. }
  20069. }
  20070. else {
  20071. XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96);
  20072. err = sp_3072_mod_96(t[1], t[1], m);
  20073. }
  20074. }
  20075. if (err == MP_OKAY) {
  20076. sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp);
  20077. sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp);
  20078. sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp);
  20079. sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp);
  20080. sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp);
  20081. sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp);
  20082. sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp);
  20083. sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp);
  20084. sp_3072_mont_sqr_96(t[10], t[ 5], m, mp);
  20085. sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp);
  20086. sp_3072_mont_sqr_96(t[12], t[ 6], m, mp);
  20087. sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp);
  20088. sp_3072_mont_sqr_96(t[14], t[ 7], m, mp);
  20089. sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp);
  20090. i = (bits - 1) / 32;
  20091. n = e[i--];
  20092. c = bits & 31;
  20093. if (c == 0) {
  20094. c = 32;
  20095. }
  20096. c -= bits % 4;
  20097. if (c == 32) {
  20098. c = 28;
  20099. }
  20100. if (c < 0) {
  20101. /* Number of bits in top word is less than number needed. */
  20102. c = -c;
  20103. y = (byte)(n << c);
  20104. n = e[i--];
  20105. y |= (byte)(n >> (64 - c));
  20106. n <<= c;
  20107. c = 64 - c;
  20108. }
  20109. else if (c == 0) {
  20110. /* All bits in top word used. */
  20111. y = (byte)n;
  20112. }
  20113. else {
  20114. y = (byte)(n >> c);
  20115. n <<= 32 - c;
  20116. }
  20117. XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
  20118. for (; i>=0 || c>=4; ) {
  20119. if (c == 0) {
  20120. n = e[i--];
  20121. y = (byte)(n >> 28);
  20122. n <<= 4;
  20123. c = 28;
  20124. }
  20125. else if (c < 4) {
  20126. y = (byte)(n >> 28);
  20127. n = e[i--];
  20128. c = 4 - c;
  20129. y |= (byte)(n >> (32 - c));
  20130. n <<= c;
  20131. c = 32 - c;
  20132. }
  20133. else {
  20134. y = (byte)((n >> 28) & 0xf);
  20135. n <<= 4;
  20136. c -= 4;
  20137. }
  20138. sp_3072_mont_sqr_96(r, r, m, mp);
  20139. sp_3072_mont_sqr_96(r, r, m, mp);
  20140. sp_3072_mont_sqr_96(r, r, m, mp);
  20141. sp_3072_mont_sqr_96(r, r, m, mp);
  20142. sp_3072_mont_mul_96(r, r, t[y], m, mp);
  20143. }
  20144. XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U);
  20145. sp_3072_mont_reduce_96(r, m, mp);
  20146. mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
  20147. sp_3072_cond_sub_96(r, r, m, mask);
  20148. }
  20149. #ifdef WOLFSSL_SP_SMALL_STACK
  20150. if (td != NULL)
  20151. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  20152. #endif
  20153. return err;
  20154. }
  20155. #endif /* WOLFSSL_SP_SMALL */
  20156. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  20157. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  20158. #ifdef WOLFSSL_HAVE_SP_RSA
  20159. /* RSA public key operation.
  20160. *
  20161. * in Array of bytes representing the number to exponentiate, base.
  20162. * inLen Number of bytes in base.
  20163. * em Public exponent.
  20164. * mm Modulus.
  20165. * out Buffer to hold big-endian bytes of exponentiation result.
  20166. * Must be at least 384 bytes long.
  20167. * outLen Number of bytes in result.
  20168. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  20169. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  20170. */
  20171. int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
  20172. const mp_int* mm, byte* out, word32* outLen)
  20173. {
  20174. #ifdef WOLFSSL_SP_SMALL_STACK
  20175. sp_digit* a = NULL;
  20176. #else
  20177. sp_digit a[96 * 5];
  20178. #endif
  20179. sp_digit* m = NULL;
  20180. sp_digit* r = NULL;
  20181. sp_digit *ah = NULL;
  20182. sp_digit e[1] = {0};
  20183. int err = MP_OKAY;
  20184. if (*outLen < 384) {
  20185. err = MP_TO_E;
  20186. }
  20187. else if (mp_count_bits(em) > 32 || inLen > 384 ||
  20188. mp_count_bits(mm) != 3072) {
  20189. err = MP_READ_E;
  20190. }
  20191. else if (mp_iseven(mm)) {
  20192. err = MP_VAL;
  20193. }
  20194. #ifdef WOLFSSL_SP_SMALL_STACK
  20195. if (err == MP_OKAY) {
  20196. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL,
  20197. DYNAMIC_TYPE_RSA);
  20198. if (a == NULL)
  20199. err = MEMORY_E;
  20200. }
  20201. #endif
  20202. if (err == MP_OKAY) {
  20203. ah = a + 96;
  20204. r = a + 96 * 2;
  20205. m = r + 96 * 2;
  20206. sp_3072_from_bin(ah, 96, in, inLen);
  20207. #if DIGIT_BIT >= 32
  20208. e[0] = em->dp[0];
  20209. #else
  20210. e[0] = em->dp[0];
  20211. if (em->used > 1) {
  20212. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  20213. }
  20214. #endif
  20215. if (e[0] == 0) {
  20216. err = MP_EXPTMOD_E;
  20217. }
  20218. }
  20219. if (err == MP_OKAY) {
  20220. sp_3072_from_mp(m, 96, mm);
  20221. if (e[0] == 0x10001) {
  20222. int i;
  20223. sp_digit mp;
  20224. sp_3072_mont_setup(m, &mp);
  20225. /* Convert to Montgomery form. */
  20226. XMEMSET(a, 0, sizeof(sp_digit) * 96);
  20227. err = sp_3072_mod_96_cond(r, a, m);
  20228. /* Montgomery form: r = a.R mod m */
  20229. if (err == MP_OKAY) {
  20230. /* r = a ^ 0x10000 => r = a squared 16 times */
  20231. for (i = 15; i >= 0; i--) {
  20232. sp_3072_mont_sqr_96(r, r, m, mp);
  20233. }
  20234. /* mont_red(r.R.R) = (r.R.R / R) mod m = r.R mod m
  20235. * mont_red(r.R * a) = (r.R.a / R) mod m = r.a mod m
  20236. */
  20237. sp_3072_mont_mul_96(r, r, ah, m, mp);
  20238. for (i = 95; i > 0; i--) {
  20239. if (r[i] != m[i]) {
  20240. break;
  20241. }
  20242. }
  20243. if (r[i] >= m[i]) {
  20244. sp_3072_sub_in_place_96(r, m);
  20245. }
  20246. }
  20247. }
  20248. else if (e[0] == 0x3) {
  20249. if (err == MP_OKAY) {
  20250. sp_3072_sqr_96(r, ah);
  20251. err = sp_3072_mod_96_cond(r, r, m);
  20252. }
  20253. if (err == MP_OKAY) {
  20254. sp_3072_mul_96(r, ah, r);
  20255. err = sp_3072_mod_96_cond(r, r, m);
  20256. }
  20257. }
  20258. else {
  20259. int i;
  20260. sp_digit mp;
  20261. sp_3072_mont_setup(m, &mp);
  20262. /* Convert to Montgomery form. */
  20263. XMEMSET(a, 0, sizeof(sp_digit) * 96);
  20264. err = sp_3072_mod_96_cond(a, a, m);
  20265. if (err == MP_OKAY) {
  20266. for (i = 31; i >= 0; i--) {
  20267. if (e[0] >> i) {
  20268. break;
  20269. }
  20270. }
  20271. XMEMCPY(r, a, sizeof(sp_digit) * 96);
  20272. for (i--; i >= 0; i--) {
  20273. sp_3072_mont_sqr_96(r, r, m, mp);
  20274. if (((e[0] >> i) & 1) == 1) {
  20275. sp_3072_mont_mul_96(r, r, a, m, mp);
  20276. }
  20277. }
  20278. XMEMSET(&r[96], 0, sizeof(sp_digit) * 96);
  20279. sp_3072_mont_reduce_96(r, m, mp);
  20280. for (i = 95; i > 0; i--) {
  20281. if (r[i] != m[i]) {
  20282. break;
  20283. }
  20284. }
  20285. if (r[i] >= m[i]) {
  20286. sp_3072_sub_in_place_96(r, m);
  20287. }
  20288. }
  20289. }
  20290. }
  20291. if (err == MP_OKAY) {
  20292. sp_3072_to_bin_96(r, out);
  20293. *outLen = 384;
  20294. }
  20295. #ifdef WOLFSSL_SP_SMALL_STACK
  20296. if (a != NULL)
  20297. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  20298. #endif
  20299. return err;
  20300. }
  20301. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  20302. #ifdef WOLFSSL_SP_SMALL
  20303. /* Conditionally add a and b using the mask m.
  20304. * m is -1 to add and 0 when not.
  20305. *
  20306. * r A single precision number representing conditional add result.
  20307. * a A single precision number to add with.
  20308. * b A single precision number to add.
  20309. * m Mask value to apply.
  20310. */
  20311. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  20312. static sp_digit sp_3072_cond_add_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  20313. #else
  20314. static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  20315. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  20316. {
  20317. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  20318. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  20319. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  20320. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  20321. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  20322. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  20323. __asm__ __volatile__ (
  20324. "MOV r5, #0x0\n\t"
  20325. "MOV r8, #0x0\n\t"
  20326. "MOV r4, #0x0\n\t"
  20327. "\n"
  20328. "L_sp_3072_cond_add_48_words:\n\t"
  20329. "ADDS r5, r5, #0xffffffff\n\t"
  20330. "LDR r6, [%[a], r4]\n\t"
  20331. "LDR r7, [%[b], r4]\n\t"
  20332. "AND r7, r7, %[m]\n\t"
  20333. "ADCS r6, r6, r7\n\t"
  20334. "ADC r5, r8, r8\n\t"
  20335. "STR r6, [%[r], r4]\n\t"
  20336. "ADD r4, r4, #0x4\n\t"
  20337. "CMP r4, #0xc0\n\t"
  20338. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  20339. "BLT L_sp_3072_cond_add_48_words\n\t"
  20340. #else
  20341. "BLT.N L_sp_3072_cond_add_48_words\n\t"
  20342. #endif
  20343. "MOV %[r], r5\n\t"
  20344. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  20345. :
  20346. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  20347. );
  20348. return (uint32_t)(size_t)r;
  20349. }
  20350. #else
  20351. /* Conditionally add a and b using the mask m.
  20352. * m is -1 to add and 0 when not.
  20353. *
  20354. * r A single precision number representing conditional add result.
  20355. * a A single precision number to add with.
  20356. * b A single precision number to add.
  20357. * m Mask value to apply.
  20358. */
  20359. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  20360. static sp_digit sp_3072_cond_add_48(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  20361. #else
  20362. static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  20363. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  20364. {
  20365. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  20366. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  20367. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  20368. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  20369. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  20370. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  20371. __asm__ __volatile__ (
  20372. "MOV r10, #0x0\n\t"
  20373. "LDM %[a]!, {r6, r7}\n\t"
  20374. "LDM %[b]!, {r8, r9}\n\t"
  20375. "AND r8, r8, %[m]\n\t"
  20376. "AND r9, r9, %[m]\n\t"
  20377. "ADDS r6, r6, r8\n\t"
  20378. "ADCS r7, r7, r9\n\t"
  20379. "STM %[r]!, {r6, r7}\n\t"
  20380. "LDM %[a]!, {r6, r7}\n\t"
  20381. "LDM %[b]!, {r8, r9}\n\t"
  20382. "AND r8, r8, %[m]\n\t"
  20383. "AND r9, r9, %[m]\n\t"
  20384. "ADCS r6, r6, r8\n\t"
  20385. "ADCS r7, r7, r9\n\t"
  20386. "STM %[r]!, {r6, r7}\n\t"
  20387. "LDM %[a]!, {r6, r7}\n\t"
  20388. "LDM %[b]!, {r8, r9}\n\t"
  20389. "AND r8, r8, %[m]\n\t"
  20390. "AND r9, r9, %[m]\n\t"
  20391. "ADCS r6, r6, r8\n\t"
  20392. "ADCS r7, r7, r9\n\t"
  20393. "STM %[r]!, {r6, r7}\n\t"
  20394. "LDM %[a]!, {r6, r7}\n\t"
  20395. "LDM %[b]!, {r8, r9}\n\t"
  20396. "AND r8, r8, %[m]\n\t"
  20397. "AND r9, r9, %[m]\n\t"
  20398. "ADCS r6, r6, r8\n\t"
  20399. "ADCS r7, r7, r9\n\t"
  20400. "STM %[r]!, {r6, r7}\n\t"
  20401. "LDM %[a]!, {r6, r7}\n\t"
  20402. "LDM %[b]!, {r8, r9}\n\t"
  20403. "AND r8, r8, %[m]\n\t"
  20404. "AND r9, r9, %[m]\n\t"
  20405. "ADCS r6, r6, r8\n\t"
  20406. "ADCS r7, r7, r9\n\t"
  20407. "STM %[r]!, {r6, r7}\n\t"
  20408. "LDM %[a]!, {r6, r7}\n\t"
  20409. "LDM %[b]!, {r8, r9}\n\t"
  20410. "AND r8, r8, %[m]\n\t"
  20411. "AND r9, r9, %[m]\n\t"
  20412. "ADCS r6, r6, r8\n\t"
  20413. "ADCS r7, r7, r9\n\t"
  20414. "STM %[r]!, {r6, r7}\n\t"
  20415. "LDM %[a]!, {r6, r7}\n\t"
  20416. "LDM %[b]!, {r8, r9}\n\t"
  20417. "AND r8, r8, %[m]\n\t"
  20418. "AND r9, r9, %[m]\n\t"
  20419. "ADCS r6, r6, r8\n\t"
  20420. "ADCS r7, r7, r9\n\t"
  20421. "STM %[r]!, {r6, r7}\n\t"
  20422. "LDM %[a]!, {r6, r7}\n\t"
  20423. "LDM %[b]!, {r8, r9}\n\t"
  20424. "AND r8, r8, %[m]\n\t"
  20425. "AND r9, r9, %[m]\n\t"
  20426. "ADCS r6, r6, r8\n\t"
  20427. "ADCS r7, r7, r9\n\t"
  20428. "STM %[r]!, {r6, r7}\n\t"
  20429. "LDM %[a]!, {r6, r7}\n\t"
  20430. "LDM %[b]!, {r8, r9}\n\t"
  20431. "AND r8, r8, %[m]\n\t"
  20432. "AND r9, r9, %[m]\n\t"
  20433. "ADCS r6, r6, r8\n\t"
  20434. "ADCS r7, r7, r9\n\t"
  20435. "STM %[r]!, {r6, r7}\n\t"
  20436. "LDM %[a]!, {r6, r7}\n\t"
  20437. "LDM %[b]!, {r8, r9}\n\t"
  20438. "AND r8, r8, %[m]\n\t"
  20439. "AND r9, r9, %[m]\n\t"
  20440. "ADCS r6, r6, r8\n\t"
  20441. "ADCS r7, r7, r9\n\t"
  20442. "STM %[r]!, {r6, r7}\n\t"
  20443. "LDM %[a]!, {r6, r7}\n\t"
  20444. "LDM %[b]!, {r8, r9}\n\t"
  20445. "AND r8, r8, %[m]\n\t"
  20446. "AND r9, r9, %[m]\n\t"
  20447. "ADCS r6, r6, r8\n\t"
  20448. "ADCS r7, r7, r9\n\t"
  20449. "STM %[r]!, {r6, r7}\n\t"
  20450. "LDM %[a]!, {r6, r7}\n\t"
  20451. "LDM %[b]!, {r8, r9}\n\t"
  20452. "AND r8, r8, %[m]\n\t"
  20453. "AND r9, r9, %[m]\n\t"
  20454. "ADCS r6, r6, r8\n\t"
  20455. "ADCS r7, r7, r9\n\t"
  20456. "STM %[r]!, {r6, r7}\n\t"
  20457. "LDM %[a]!, {r6, r7}\n\t"
  20458. "LDM %[b]!, {r8, r9}\n\t"
  20459. "AND r8, r8, %[m]\n\t"
  20460. "AND r9, r9, %[m]\n\t"
  20461. "ADCS r6, r6, r8\n\t"
  20462. "ADCS r7, r7, r9\n\t"
  20463. "STM %[r]!, {r6, r7}\n\t"
  20464. "LDM %[a]!, {r6, r7}\n\t"
  20465. "LDM %[b]!, {r8, r9}\n\t"
  20466. "AND r8, r8, %[m]\n\t"
  20467. "AND r9, r9, %[m]\n\t"
  20468. "ADCS r6, r6, r8\n\t"
  20469. "ADCS r7, r7, r9\n\t"
  20470. "STM %[r]!, {r6, r7}\n\t"
  20471. "LDM %[a]!, {r6, r7}\n\t"
  20472. "LDM %[b]!, {r8, r9}\n\t"
  20473. "AND r8, r8, %[m]\n\t"
  20474. "AND r9, r9, %[m]\n\t"
  20475. "ADCS r6, r6, r8\n\t"
  20476. "ADCS r7, r7, r9\n\t"
  20477. "STM %[r]!, {r6, r7}\n\t"
  20478. "LDM %[a]!, {r6, r7}\n\t"
  20479. "LDM %[b]!, {r8, r9}\n\t"
  20480. "AND r8, r8, %[m]\n\t"
  20481. "AND r9, r9, %[m]\n\t"
  20482. "ADCS r6, r6, r8\n\t"
  20483. "ADCS r7, r7, r9\n\t"
  20484. "STM %[r]!, {r6, r7}\n\t"
  20485. "LDM %[a]!, {r6, r7}\n\t"
  20486. "LDM %[b]!, {r8, r9}\n\t"
  20487. "AND r8, r8, %[m]\n\t"
  20488. "AND r9, r9, %[m]\n\t"
  20489. "ADCS r6, r6, r8\n\t"
  20490. "ADCS r7, r7, r9\n\t"
  20491. "STM %[r]!, {r6, r7}\n\t"
  20492. "LDM %[a]!, {r6, r7}\n\t"
  20493. "LDM %[b]!, {r8, r9}\n\t"
  20494. "AND r8, r8, %[m]\n\t"
  20495. "AND r9, r9, %[m]\n\t"
  20496. "ADCS r6, r6, r8\n\t"
  20497. "ADCS r7, r7, r9\n\t"
  20498. "STM %[r]!, {r6, r7}\n\t"
  20499. "LDM %[a]!, {r6, r7}\n\t"
  20500. "LDM %[b]!, {r8, r9}\n\t"
  20501. "AND r8, r8, %[m]\n\t"
  20502. "AND r9, r9, %[m]\n\t"
  20503. "ADCS r6, r6, r8\n\t"
  20504. "ADCS r7, r7, r9\n\t"
  20505. "STM %[r]!, {r6, r7}\n\t"
  20506. "LDM %[a]!, {r6, r7}\n\t"
  20507. "LDM %[b]!, {r8, r9}\n\t"
  20508. "AND r8, r8, %[m]\n\t"
  20509. "AND r9, r9, %[m]\n\t"
  20510. "ADCS r6, r6, r8\n\t"
  20511. "ADCS r7, r7, r9\n\t"
  20512. "STM %[r]!, {r6, r7}\n\t"
  20513. "LDM %[a]!, {r6, r7}\n\t"
  20514. "LDM %[b]!, {r8, r9}\n\t"
  20515. "AND r8, r8, %[m]\n\t"
  20516. "AND r9, r9, %[m]\n\t"
  20517. "ADCS r6, r6, r8\n\t"
  20518. "ADCS r7, r7, r9\n\t"
  20519. "STM %[r]!, {r6, r7}\n\t"
  20520. "LDM %[a]!, {r6, r7}\n\t"
  20521. "LDM %[b]!, {r8, r9}\n\t"
  20522. "AND r8, r8, %[m]\n\t"
  20523. "AND r9, r9, %[m]\n\t"
  20524. "ADCS r6, r6, r8\n\t"
  20525. "ADCS r7, r7, r9\n\t"
  20526. "STM %[r]!, {r6, r7}\n\t"
  20527. "LDM %[a]!, {r6, r7}\n\t"
  20528. "LDM %[b]!, {r8, r9}\n\t"
  20529. "AND r8, r8, %[m]\n\t"
  20530. "AND r9, r9, %[m]\n\t"
  20531. "ADCS r6, r6, r8\n\t"
  20532. "ADCS r7, r7, r9\n\t"
  20533. "STM %[r]!, {r6, r7}\n\t"
  20534. "LDM %[a]!, {r6, r7}\n\t"
  20535. "LDM %[b]!, {r8, r9}\n\t"
  20536. "AND r8, r8, %[m]\n\t"
  20537. "AND r9, r9, %[m]\n\t"
  20538. "ADCS r6, r6, r8\n\t"
  20539. "ADCS r7, r7, r9\n\t"
  20540. "STM %[r]!, {r6, r7}\n\t"
  20541. "ADC %[r], r10, r10\n\t"
  20542. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  20543. :
  20544. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  20545. );
  20546. return (uint32_t)(size_t)r;
  20547. }
  20548. #endif /* WOLFSSL_SP_SMALL */
  20549. /* RSA private key operation.
  20550. *
  20551. * in Array of bytes representing the number to exponentiate, base.
  20552. * inLen Number of bytes in base.
  20553. * dm Private exponent.
  20554. * pm First prime.
  20555. * qm Second prime.
  20556. * dpm First prime's CRT exponent.
  20557. * dqm Second prime's CRT exponent.
  20558. * qim Inverse of second prime mod p.
  20559. * mm Modulus.
  20560. * out Buffer to hold big-endian bytes of exponentiation result.
  20561. * Must be at least 384 bytes long.
  20562. * outLen Number of bytes in result.
  20563. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  20564. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  20565. */
  20566. int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
  20567. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  20568. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  20569. {
  20570. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  20571. #ifdef WOLFSSL_SP_SMALL_STACK
  20572. sp_digit* d = NULL;
  20573. #else
  20574. sp_digit d[96 * 4];
  20575. #endif
  20576. sp_digit* a = NULL;
  20577. sp_digit* m = NULL;
  20578. sp_digit* r = NULL;
  20579. int err = MP_OKAY;
  20580. (void)pm;
  20581. (void)qm;
  20582. (void)dpm;
  20583. (void)dqm;
  20584. (void)qim;
  20585. if (*outLen < 384U) {
  20586. err = MP_TO_E;
  20587. }
  20588. if (err == MP_OKAY) {
  20589. if (mp_count_bits(dm) > 3072) {
  20590. err = MP_READ_E;
  20591. }
  20592. else if (inLen > 384) {
  20593. err = MP_READ_E;
  20594. }
  20595. else if (mp_count_bits(mm) != 3072) {
  20596. err = MP_READ_E;
  20597. }
  20598. else if (mp_iseven(mm)) {
  20599. err = MP_VAL;
  20600. }
  20601. }
  20602. #ifdef WOLFSSL_SP_SMALL_STACK
  20603. if (err == MP_OKAY) {
  20604. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 4, NULL,
  20605. DYNAMIC_TYPE_RSA);
  20606. if (d == NULL)
  20607. err = MEMORY_E;
  20608. }
  20609. #endif
  20610. if (err == MP_OKAY) {
  20611. a = d + 96;
  20612. m = a + 192;
  20613. r = a;
  20614. sp_3072_from_bin(a, 96, in, inLen);
  20615. sp_3072_from_mp(d, 96, dm);
  20616. sp_3072_from_mp(m, 96, mm);
  20617. err = sp_3072_mod_exp_96(r, a, d, 3072, m, 0);
  20618. }
  20619. if (err == MP_OKAY) {
  20620. sp_3072_to_bin_96(r, out);
  20621. *outLen = 384;
  20622. }
  20623. #ifdef WOLFSSL_SP_SMALL_STACK
  20624. if (d != NULL)
  20625. #endif
  20626. {
  20627. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  20628. if (a != NULL)
  20629. ForceZero(a, sizeof(sp_digit) * 96);
  20630. #ifdef WOLFSSL_SP_SMALL_STACK
  20631. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  20632. #endif
  20633. }
  20634. return err;
  20635. #else
  20636. #ifdef WOLFSSL_SP_SMALL_STACK
  20637. sp_digit* a = NULL;
  20638. #else
  20639. sp_digit a[48 * 11];
  20640. #endif
  20641. sp_digit* p = NULL;
  20642. sp_digit* q = NULL;
  20643. sp_digit* dp = NULL;
  20644. sp_digit* tmpa = NULL;
  20645. sp_digit* tmpb = NULL;
  20646. sp_digit* r = NULL;
  20647. sp_digit* qi = NULL;
  20648. sp_digit* dq = NULL;
  20649. sp_digit c;
  20650. int err = MP_OKAY;
  20651. (void)dm;
  20652. (void)mm;
  20653. if (*outLen < 384) {
  20654. err = MP_TO_E;
  20655. }
  20656. else if (inLen > 384 || mp_count_bits(mm) != 3072) {
  20657. err = MP_READ_E;
  20658. }
  20659. else if (mp_iseven(mm)) {
  20660. err = MP_VAL;
  20661. }
  20662. else if (mp_iseven(pm)) {
  20663. err = MP_VAL;
  20664. }
  20665. else if (mp_iseven(qm)) {
  20666. err = MP_VAL;
  20667. }
  20668. #ifdef WOLFSSL_SP_SMALL_STACK
  20669. if (err == MP_OKAY) {
  20670. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL,
  20671. DYNAMIC_TYPE_RSA);
  20672. if (a == NULL)
  20673. err = MEMORY_E;
  20674. }
  20675. #endif
  20676. if (err == MP_OKAY) {
  20677. p = a + 96 * 2;
  20678. q = p + 48;
  20679. qi = dq = dp = q + 48;
  20680. tmpa = qi + 48;
  20681. tmpb = tmpa + 96;
  20682. r = a;
  20683. sp_3072_from_bin(a, 96, in, inLen);
  20684. sp_3072_from_mp(p, 48, pm);
  20685. sp_3072_from_mp(q, 48, qm);
  20686. sp_3072_from_mp(dp, 48, dpm);
  20687. err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1);
  20688. }
  20689. if (err == MP_OKAY) {
  20690. sp_3072_from_mp(dq, 48, dqm);
  20691. err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1);
  20692. }
  20693. if (err == MP_OKAY) {
  20694. c = sp_3072_sub_in_place_48(tmpa, tmpb);
  20695. c += sp_3072_cond_add_48(tmpa, tmpa, p, c);
  20696. sp_3072_cond_add_48(tmpa, tmpa, p, c);
  20697. sp_3072_from_mp(qi, 48, qim);
  20698. sp_3072_mul_48(tmpa, tmpa, qi);
  20699. err = sp_3072_mod_48(tmpa, tmpa, p);
  20700. }
  20701. if (err == MP_OKAY) {
  20702. sp_3072_mul_48(tmpa, q, tmpa);
  20703. XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48);
  20704. sp_3072_add_96(r, tmpb, tmpa);
  20705. sp_3072_to_bin_96(r, out);
  20706. *outLen = 384;
  20707. }
  20708. #ifdef WOLFSSL_SP_SMALL_STACK
  20709. if (a != NULL)
  20710. #endif
  20711. {
  20712. ForceZero(a, sizeof(sp_digit) * 48 * 11);
  20713. #ifdef WOLFSSL_SP_SMALL_STACK
  20714. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  20715. #endif
  20716. }
  20717. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  20718. return err;
  20719. }
  20720. #endif /* WOLFSSL_RSA_PUBLIC_ONLY */
  20721. #endif /* WOLFSSL_HAVE_SP_RSA */
  20722. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  20723. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  20724. /* Convert an array of sp_digit to an mp_int.
  20725. *
  20726. * a A single precision integer.
  20727. * r A multi-precision integer.
  20728. */
  20729. static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
  20730. {
  20731. int err;
  20732. err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
  20733. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  20734. #if DIGIT_BIT == 32
  20735. XMEMCPY(r->dp, a, sizeof(sp_digit) * 96);
  20736. r->used = 96;
  20737. mp_clamp(r);
  20738. #elif DIGIT_BIT < 32
  20739. int i;
  20740. int j = 0;
  20741. int s = 0;
  20742. r->dp[0] = 0;
  20743. for (i = 0; i < 96; i++) {
  20744. r->dp[j] |= (mp_digit)(a[i] << s);
  20745. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  20746. s = DIGIT_BIT - s;
  20747. r->dp[++j] = (mp_digit)(a[i] >> s);
  20748. while (s + DIGIT_BIT <= 32) {
  20749. s += DIGIT_BIT;
  20750. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  20751. if (s == SP_WORD_SIZE) {
  20752. r->dp[j] = 0;
  20753. }
  20754. else {
  20755. r->dp[j] = (mp_digit)(a[i] >> s);
  20756. }
  20757. }
  20758. s = 32 - s;
  20759. }
  20760. r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
  20761. mp_clamp(r);
  20762. #else
  20763. int i;
  20764. int j = 0;
  20765. int s = 0;
  20766. r->dp[0] = 0;
  20767. for (i = 0; i < 96; i++) {
  20768. r->dp[j] |= ((mp_digit)a[i]) << s;
  20769. if (s + 32 >= DIGIT_BIT) {
  20770. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  20771. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  20772. #endif
  20773. s = DIGIT_BIT - s;
  20774. r->dp[++j] = a[i] >> s;
  20775. s = 32 - s;
  20776. }
  20777. else {
  20778. s += 32;
  20779. }
  20780. }
  20781. r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
  20782. mp_clamp(r);
  20783. #endif
  20784. }
  20785. return err;
  20786. }
  20787. /* Perform the modular exponentiation for Diffie-Hellman.
  20788. *
  20789. * base Base. MP integer.
  20790. * exp Exponent. MP integer.
  20791. * mod Modulus. MP integer.
  20792. * res Result. MP integer.
  20793. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  20794. * and MEMORY_E if memory allocation fails.
  20795. */
  20796. int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
  20797. mp_int* res)
  20798. {
  20799. int err = MP_OKAY;
  20800. sp_digit b[192];
  20801. sp_digit e[96];
  20802. sp_digit m[96];
  20803. sp_digit* r = b;
  20804. int expBits = mp_count_bits(exp);
  20805. if (mp_count_bits(base) > 3072) {
  20806. err = MP_READ_E;
  20807. }
  20808. else if (expBits > 3072) {
  20809. err = MP_READ_E;
  20810. }
  20811. else if (mp_count_bits(mod) != 3072) {
  20812. err = MP_READ_E;
  20813. }
  20814. else if (mp_iseven(mod)) {
  20815. err = MP_VAL;
  20816. }
  20817. if (err == MP_OKAY) {
  20818. sp_3072_from_mp(b, 96, base);
  20819. sp_3072_from_mp(e, 96, exp);
  20820. sp_3072_from_mp(m, 96, mod);
  20821. err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0);
  20822. }
  20823. if (err == MP_OKAY) {
  20824. err = sp_3072_to_mp(r, res);
  20825. }
  20826. XMEMSET(e, 0, sizeof(e));
  20827. return err;
  20828. }
  20829. #ifdef WOLFSSL_HAVE_SP_DH
  20830. #ifdef HAVE_FFDHE_3072
  20831. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  20832. static void sp_3072_lshift_96(sp_digit* r_p, const sp_digit* a_p, byte n_p)
  20833. #else
  20834. static void sp_3072_lshift_96(sp_digit* r, const sp_digit* a, byte n)
  20835. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  20836. {
  20837. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  20838. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  20839. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  20840. register byte n __asm__ ("r2") = (byte)n_p;
  20841. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  20842. __asm__ __volatile__ (
  20843. "RSB r7, %[n], #0x1f\n\t"
  20844. "LDR r5, [%[a], #380]\n\t"
  20845. "LSR r6, r5, #1\n\t"
  20846. "LSL r5, r5, %[n]\n\t"
  20847. "LSR r6, r6, r7\n\t"
  20848. "LDR r4, [%[a], #376]\n\t"
  20849. "STR r6, [%[r], #384]\n\t"
  20850. "LSR r3, r4, #1\n\t"
  20851. "LSL r4, r4, %[n]\n\t"
  20852. "LSR r3, r3, r7\n\t"
  20853. "ORR r5, r5, r3\n\t"
  20854. "LDR r6, [%[a], #372]\n\t"
  20855. "STR r5, [%[r], #380]\n\t"
  20856. "LSR r3, r6, #1\n\t"
  20857. "LSL r6, r6, %[n]\n\t"
  20858. "LSR r3, r3, r7\n\t"
  20859. "ORR r4, r4, r3\n\t"
  20860. "LDR r5, [%[a], #368]\n\t"
  20861. "STR r4, [%[r], #376]\n\t"
  20862. "LSR r3, r5, #1\n\t"
  20863. "LSL r5, r5, %[n]\n\t"
  20864. "LSR r3, r3, r7\n\t"
  20865. "ORR r6, r6, r3\n\t"
  20866. "LDR r4, [%[a], #364]\n\t"
  20867. "STR r6, [%[r], #372]\n\t"
  20868. "LSR r3, r4, #1\n\t"
  20869. "LSL r4, r4, %[n]\n\t"
  20870. "LSR r3, r3, r7\n\t"
  20871. "ORR r5, r5, r3\n\t"
  20872. "LDR r6, [%[a], #360]\n\t"
  20873. "STR r5, [%[r], #368]\n\t"
  20874. "LSR r3, r6, #1\n\t"
  20875. "LSL r6, r6, %[n]\n\t"
  20876. "LSR r3, r3, r7\n\t"
  20877. "ORR r4, r4, r3\n\t"
  20878. "LDR r5, [%[a], #356]\n\t"
  20879. "STR r4, [%[r], #364]\n\t"
  20880. "LSR r3, r5, #1\n\t"
  20881. "LSL r5, r5, %[n]\n\t"
  20882. "LSR r3, r3, r7\n\t"
  20883. "ORR r6, r6, r3\n\t"
  20884. "LDR r4, [%[a], #352]\n\t"
  20885. "STR r6, [%[r], #360]\n\t"
  20886. "LSR r3, r4, #1\n\t"
  20887. "LSL r4, r4, %[n]\n\t"
  20888. "LSR r3, r3, r7\n\t"
  20889. "ORR r5, r5, r3\n\t"
  20890. "LDR r6, [%[a], #348]\n\t"
  20891. "STR r5, [%[r], #356]\n\t"
  20892. "LSR r3, r6, #1\n\t"
  20893. "LSL r6, r6, %[n]\n\t"
  20894. "LSR r3, r3, r7\n\t"
  20895. "ORR r4, r4, r3\n\t"
  20896. "LDR r5, [%[a], #344]\n\t"
  20897. "STR r4, [%[r], #352]\n\t"
  20898. "LSR r3, r5, #1\n\t"
  20899. "LSL r5, r5, %[n]\n\t"
  20900. "LSR r3, r3, r7\n\t"
  20901. "ORR r6, r6, r3\n\t"
  20902. "LDR r4, [%[a], #340]\n\t"
  20903. "STR r6, [%[r], #348]\n\t"
  20904. "LSR r3, r4, #1\n\t"
  20905. "LSL r4, r4, %[n]\n\t"
  20906. "LSR r3, r3, r7\n\t"
  20907. "ORR r5, r5, r3\n\t"
  20908. "LDR r6, [%[a], #336]\n\t"
  20909. "STR r5, [%[r], #344]\n\t"
  20910. "LSR r3, r6, #1\n\t"
  20911. "LSL r6, r6, %[n]\n\t"
  20912. "LSR r3, r3, r7\n\t"
  20913. "ORR r4, r4, r3\n\t"
  20914. "LDR r5, [%[a], #332]\n\t"
  20915. "STR r4, [%[r], #340]\n\t"
  20916. "LSR r3, r5, #1\n\t"
  20917. "LSL r5, r5, %[n]\n\t"
  20918. "LSR r3, r3, r7\n\t"
  20919. "ORR r6, r6, r3\n\t"
  20920. "LDR r4, [%[a], #328]\n\t"
  20921. "STR r6, [%[r], #336]\n\t"
  20922. "LSR r3, r4, #1\n\t"
  20923. "LSL r4, r4, %[n]\n\t"
  20924. "LSR r3, r3, r7\n\t"
  20925. "ORR r5, r5, r3\n\t"
  20926. "LDR r6, [%[a], #324]\n\t"
  20927. "STR r5, [%[r], #332]\n\t"
  20928. "LSR r3, r6, #1\n\t"
  20929. "LSL r6, r6, %[n]\n\t"
  20930. "LSR r3, r3, r7\n\t"
  20931. "ORR r4, r4, r3\n\t"
  20932. "LDR r5, [%[a], #320]\n\t"
  20933. "STR r4, [%[r], #328]\n\t"
  20934. "LSR r3, r5, #1\n\t"
  20935. "LSL r5, r5, %[n]\n\t"
  20936. "LSR r3, r3, r7\n\t"
  20937. "ORR r6, r6, r3\n\t"
  20938. "LDR r4, [%[a], #316]\n\t"
  20939. "STR r6, [%[r], #324]\n\t"
  20940. "LSR r3, r4, #1\n\t"
  20941. "LSL r4, r4, %[n]\n\t"
  20942. "LSR r3, r3, r7\n\t"
  20943. "ORR r5, r5, r3\n\t"
  20944. "LDR r6, [%[a], #312]\n\t"
  20945. "STR r5, [%[r], #320]\n\t"
  20946. "LSR r3, r6, #1\n\t"
  20947. "LSL r6, r6, %[n]\n\t"
  20948. "LSR r3, r3, r7\n\t"
  20949. "ORR r4, r4, r3\n\t"
  20950. "LDR r5, [%[a], #308]\n\t"
  20951. "STR r4, [%[r], #316]\n\t"
  20952. "LSR r3, r5, #1\n\t"
  20953. "LSL r5, r5, %[n]\n\t"
  20954. "LSR r3, r3, r7\n\t"
  20955. "ORR r6, r6, r3\n\t"
  20956. "LDR r4, [%[a], #304]\n\t"
  20957. "STR r6, [%[r], #312]\n\t"
  20958. "LSR r3, r4, #1\n\t"
  20959. "LSL r4, r4, %[n]\n\t"
  20960. "LSR r3, r3, r7\n\t"
  20961. "ORR r5, r5, r3\n\t"
  20962. "LDR r6, [%[a], #300]\n\t"
  20963. "STR r5, [%[r], #308]\n\t"
  20964. "LSR r3, r6, #1\n\t"
  20965. "LSL r6, r6, %[n]\n\t"
  20966. "LSR r3, r3, r7\n\t"
  20967. "ORR r4, r4, r3\n\t"
  20968. "LDR r5, [%[a], #296]\n\t"
  20969. "STR r4, [%[r], #304]\n\t"
  20970. "LSR r3, r5, #1\n\t"
  20971. "LSL r5, r5, %[n]\n\t"
  20972. "LSR r3, r3, r7\n\t"
  20973. "ORR r6, r6, r3\n\t"
  20974. "LDR r4, [%[a], #292]\n\t"
  20975. "STR r6, [%[r], #300]\n\t"
  20976. "LSR r3, r4, #1\n\t"
  20977. "LSL r4, r4, %[n]\n\t"
  20978. "LSR r3, r3, r7\n\t"
  20979. "ORR r5, r5, r3\n\t"
  20980. "LDR r6, [%[a], #288]\n\t"
  20981. "STR r5, [%[r], #296]\n\t"
  20982. "LSR r3, r6, #1\n\t"
  20983. "LSL r6, r6, %[n]\n\t"
  20984. "LSR r3, r3, r7\n\t"
  20985. "ORR r4, r4, r3\n\t"
  20986. "LDR r5, [%[a], #284]\n\t"
  20987. "STR r4, [%[r], #292]\n\t"
  20988. "LSR r3, r5, #1\n\t"
  20989. "LSL r5, r5, %[n]\n\t"
  20990. "LSR r3, r3, r7\n\t"
  20991. "ORR r6, r6, r3\n\t"
  20992. "LDR r4, [%[a], #280]\n\t"
  20993. "STR r6, [%[r], #288]\n\t"
  20994. "LSR r3, r4, #1\n\t"
  20995. "LSL r4, r4, %[n]\n\t"
  20996. "LSR r3, r3, r7\n\t"
  20997. "ORR r5, r5, r3\n\t"
  20998. "LDR r6, [%[a], #276]\n\t"
  20999. "STR r5, [%[r], #284]\n\t"
  21000. "LSR r3, r6, #1\n\t"
  21001. "LSL r6, r6, %[n]\n\t"
  21002. "LSR r3, r3, r7\n\t"
  21003. "ORR r4, r4, r3\n\t"
  21004. "LDR r5, [%[a], #272]\n\t"
  21005. "STR r4, [%[r], #280]\n\t"
  21006. "LSR r3, r5, #1\n\t"
  21007. "LSL r5, r5, %[n]\n\t"
  21008. "LSR r3, r3, r7\n\t"
  21009. "ORR r6, r6, r3\n\t"
  21010. "LDR r4, [%[a], #268]\n\t"
  21011. "STR r6, [%[r], #276]\n\t"
  21012. "LSR r3, r4, #1\n\t"
  21013. "LSL r4, r4, %[n]\n\t"
  21014. "LSR r3, r3, r7\n\t"
  21015. "ORR r5, r5, r3\n\t"
  21016. "LDR r6, [%[a], #264]\n\t"
  21017. "STR r5, [%[r], #272]\n\t"
  21018. "LSR r3, r6, #1\n\t"
  21019. "LSL r6, r6, %[n]\n\t"
  21020. "LSR r3, r3, r7\n\t"
  21021. "ORR r4, r4, r3\n\t"
  21022. "LDR r5, [%[a], #260]\n\t"
  21023. "STR r4, [%[r], #268]\n\t"
  21024. "LSR r3, r5, #1\n\t"
  21025. "LSL r5, r5, %[n]\n\t"
  21026. "LSR r3, r3, r7\n\t"
  21027. "ORR r6, r6, r3\n\t"
  21028. "LDR r4, [%[a], #256]\n\t"
  21029. "STR r6, [%[r], #264]\n\t"
  21030. "LSR r3, r4, #1\n\t"
  21031. "LSL r4, r4, %[n]\n\t"
  21032. "LSR r3, r3, r7\n\t"
  21033. "ORR r5, r5, r3\n\t"
  21034. "LDR r6, [%[a], #252]\n\t"
  21035. "STR r5, [%[r], #260]\n\t"
  21036. "LSR r3, r6, #1\n\t"
  21037. "LSL r6, r6, %[n]\n\t"
  21038. "LSR r3, r3, r7\n\t"
  21039. "ORR r4, r4, r3\n\t"
  21040. "LDR r5, [%[a], #248]\n\t"
  21041. "STR r4, [%[r], #256]\n\t"
  21042. "LSR r3, r5, #1\n\t"
  21043. "LSL r5, r5, %[n]\n\t"
  21044. "LSR r3, r3, r7\n\t"
  21045. "ORR r6, r6, r3\n\t"
  21046. "LDR r4, [%[a], #244]\n\t"
  21047. "STR r6, [%[r], #252]\n\t"
  21048. "LSR r3, r4, #1\n\t"
  21049. "LSL r4, r4, %[n]\n\t"
  21050. "LSR r3, r3, r7\n\t"
  21051. "ORR r5, r5, r3\n\t"
  21052. "LDR r6, [%[a], #240]\n\t"
  21053. "STR r5, [%[r], #248]\n\t"
  21054. "LSR r3, r6, #1\n\t"
  21055. "LSL r6, r6, %[n]\n\t"
  21056. "LSR r3, r3, r7\n\t"
  21057. "ORR r4, r4, r3\n\t"
  21058. "LDR r5, [%[a], #236]\n\t"
  21059. "STR r4, [%[r], #244]\n\t"
  21060. "LSR r3, r5, #1\n\t"
  21061. "LSL r5, r5, %[n]\n\t"
  21062. "LSR r3, r3, r7\n\t"
  21063. "ORR r6, r6, r3\n\t"
  21064. "LDR r4, [%[a], #232]\n\t"
  21065. "STR r6, [%[r], #240]\n\t"
  21066. "LSR r3, r4, #1\n\t"
  21067. "LSL r4, r4, %[n]\n\t"
  21068. "LSR r3, r3, r7\n\t"
  21069. "ORR r5, r5, r3\n\t"
  21070. "LDR r6, [%[a], #228]\n\t"
  21071. "STR r5, [%[r], #236]\n\t"
  21072. "LSR r3, r6, #1\n\t"
  21073. "LSL r6, r6, %[n]\n\t"
  21074. "LSR r3, r3, r7\n\t"
  21075. "ORR r4, r4, r3\n\t"
  21076. "LDR r5, [%[a], #224]\n\t"
  21077. "STR r4, [%[r], #232]\n\t"
  21078. "LSR r3, r5, #1\n\t"
  21079. "LSL r5, r5, %[n]\n\t"
  21080. "LSR r3, r3, r7\n\t"
  21081. "ORR r6, r6, r3\n\t"
  21082. "LDR r4, [%[a], #220]\n\t"
  21083. "STR r6, [%[r], #228]\n\t"
  21084. "LSR r3, r4, #1\n\t"
  21085. "LSL r4, r4, %[n]\n\t"
  21086. "LSR r3, r3, r7\n\t"
  21087. "ORR r5, r5, r3\n\t"
  21088. "LDR r6, [%[a], #216]\n\t"
  21089. "STR r5, [%[r], #224]\n\t"
  21090. "LSR r3, r6, #1\n\t"
  21091. "LSL r6, r6, %[n]\n\t"
  21092. "LSR r3, r3, r7\n\t"
  21093. "ORR r4, r4, r3\n\t"
  21094. "LDR r5, [%[a], #212]\n\t"
  21095. "STR r4, [%[r], #220]\n\t"
  21096. "LSR r3, r5, #1\n\t"
  21097. "LSL r5, r5, %[n]\n\t"
  21098. "LSR r3, r3, r7\n\t"
  21099. "ORR r6, r6, r3\n\t"
  21100. "LDR r4, [%[a], #208]\n\t"
  21101. "STR r6, [%[r], #216]\n\t"
  21102. "LSR r3, r4, #1\n\t"
  21103. "LSL r4, r4, %[n]\n\t"
  21104. "LSR r3, r3, r7\n\t"
  21105. "ORR r5, r5, r3\n\t"
  21106. "LDR r6, [%[a], #204]\n\t"
  21107. "STR r5, [%[r], #212]\n\t"
  21108. "LSR r3, r6, #1\n\t"
  21109. "LSL r6, r6, %[n]\n\t"
  21110. "LSR r3, r3, r7\n\t"
  21111. "ORR r4, r4, r3\n\t"
  21112. "LDR r5, [%[a], #200]\n\t"
  21113. "STR r4, [%[r], #208]\n\t"
  21114. "LSR r3, r5, #1\n\t"
  21115. "LSL r5, r5, %[n]\n\t"
  21116. "LSR r3, r3, r7\n\t"
  21117. "ORR r6, r6, r3\n\t"
  21118. "LDR r4, [%[a], #196]\n\t"
  21119. "STR r6, [%[r], #204]\n\t"
  21120. "LSR r3, r4, #1\n\t"
  21121. "LSL r4, r4, %[n]\n\t"
  21122. "LSR r3, r3, r7\n\t"
  21123. "ORR r5, r5, r3\n\t"
  21124. "LDR r6, [%[a], #192]\n\t"
  21125. "STR r5, [%[r], #200]\n\t"
  21126. "LSR r3, r6, #1\n\t"
  21127. "LSL r6, r6, %[n]\n\t"
  21128. "LSR r3, r3, r7\n\t"
  21129. "ORR r4, r4, r3\n\t"
  21130. "LDR r5, [%[a], #188]\n\t"
  21131. "STR r4, [%[r], #196]\n\t"
  21132. "LSR r3, r5, #1\n\t"
  21133. "LSL r5, r5, %[n]\n\t"
  21134. "LSR r3, r3, r7\n\t"
  21135. "ORR r6, r6, r3\n\t"
  21136. "LDR r4, [%[a], #184]\n\t"
  21137. "STR r6, [%[r], #192]\n\t"
  21138. "LSR r3, r4, #1\n\t"
  21139. "LSL r4, r4, %[n]\n\t"
  21140. "LSR r3, r3, r7\n\t"
  21141. "ORR r5, r5, r3\n\t"
  21142. "LDR r6, [%[a], #180]\n\t"
  21143. "STR r5, [%[r], #188]\n\t"
  21144. "LSR r3, r6, #1\n\t"
  21145. "LSL r6, r6, %[n]\n\t"
  21146. "LSR r3, r3, r7\n\t"
  21147. "ORR r4, r4, r3\n\t"
  21148. "LDR r5, [%[a], #176]\n\t"
  21149. "STR r4, [%[r], #184]\n\t"
  21150. "LSR r3, r5, #1\n\t"
  21151. "LSL r5, r5, %[n]\n\t"
  21152. "LSR r3, r3, r7\n\t"
  21153. "ORR r6, r6, r3\n\t"
  21154. "LDR r4, [%[a], #172]\n\t"
  21155. "STR r6, [%[r], #180]\n\t"
  21156. "LSR r3, r4, #1\n\t"
  21157. "LSL r4, r4, %[n]\n\t"
  21158. "LSR r3, r3, r7\n\t"
  21159. "ORR r5, r5, r3\n\t"
  21160. "LDR r6, [%[a], #168]\n\t"
  21161. "STR r5, [%[r], #176]\n\t"
  21162. "LSR r3, r6, #1\n\t"
  21163. "LSL r6, r6, %[n]\n\t"
  21164. "LSR r3, r3, r7\n\t"
  21165. "ORR r4, r4, r3\n\t"
  21166. "LDR r5, [%[a], #164]\n\t"
  21167. "STR r4, [%[r], #172]\n\t"
  21168. "LSR r3, r5, #1\n\t"
  21169. "LSL r5, r5, %[n]\n\t"
  21170. "LSR r3, r3, r7\n\t"
  21171. "ORR r6, r6, r3\n\t"
  21172. "LDR r4, [%[a], #160]\n\t"
  21173. "STR r6, [%[r], #168]\n\t"
  21174. "LSR r3, r4, #1\n\t"
  21175. "LSL r4, r4, %[n]\n\t"
  21176. "LSR r3, r3, r7\n\t"
  21177. "ORR r5, r5, r3\n\t"
  21178. "LDR r6, [%[a], #156]\n\t"
  21179. "STR r5, [%[r], #164]\n\t"
  21180. "LSR r3, r6, #1\n\t"
  21181. "LSL r6, r6, %[n]\n\t"
  21182. "LSR r3, r3, r7\n\t"
  21183. "ORR r4, r4, r3\n\t"
  21184. "LDR r5, [%[a], #152]\n\t"
  21185. "STR r4, [%[r], #160]\n\t"
  21186. "LSR r3, r5, #1\n\t"
  21187. "LSL r5, r5, %[n]\n\t"
  21188. "LSR r3, r3, r7\n\t"
  21189. "ORR r6, r6, r3\n\t"
  21190. "LDR r4, [%[a], #148]\n\t"
  21191. "STR r6, [%[r], #156]\n\t"
  21192. "LSR r3, r4, #1\n\t"
  21193. "LSL r4, r4, %[n]\n\t"
  21194. "LSR r3, r3, r7\n\t"
  21195. "ORR r5, r5, r3\n\t"
  21196. "LDR r6, [%[a], #144]\n\t"
  21197. "STR r5, [%[r], #152]\n\t"
  21198. "LSR r3, r6, #1\n\t"
  21199. "LSL r6, r6, %[n]\n\t"
  21200. "LSR r3, r3, r7\n\t"
  21201. "ORR r4, r4, r3\n\t"
  21202. "LDR r5, [%[a], #140]\n\t"
  21203. "STR r4, [%[r], #148]\n\t"
  21204. "LSR r3, r5, #1\n\t"
  21205. "LSL r5, r5, %[n]\n\t"
  21206. "LSR r3, r3, r7\n\t"
  21207. "ORR r6, r6, r3\n\t"
  21208. "LDR r4, [%[a], #136]\n\t"
  21209. "STR r6, [%[r], #144]\n\t"
  21210. "LSR r3, r4, #1\n\t"
  21211. "LSL r4, r4, %[n]\n\t"
  21212. "LSR r3, r3, r7\n\t"
  21213. "ORR r5, r5, r3\n\t"
  21214. "LDR r6, [%[a], #132]\n\t"
  21215. "STR r5, [%[r], #140]\n\t"
  21216. "LSR r3, r6, #1\n\t"
  21217. "LSL r6, r6, %[n]\n\t"
  21218. "LSR r3, r3, r7\n\t"
  21219. "ORR r4, r4, r3\n\t"
  21220. "LDR r5, [%[a], #128]\n\t"
  21221. "STR r4, [%[r], #136]\n\t"
  21222. "LSR r3, r5, #1\n\t"
  21223. "LSL r5, r5, %[n]\n\t"
  21224. "LSR r3, r3, r7\n\t"
  21225. "ORR r6, r6, r3\n\t"
  21226. "LDR r4, [%[a], #124]\n\t"
  21227. "STR r6, [%[r], #132]\n\t"
  21228. "LSR r3, r4, #1\n\t"
  21229. "LSL r4, r4, %[n]\n\t"
  21230. "LSR r3, r3, r7\n\t"
  21231. "ORR r5, r5, r3\n\t"
  21232. "LDR r6, [%[a], #120]\n\t"
  21233. "STR r5, [%[r], #128]\n\t"
  21234. "LSR r3, r6, #1\n\t"
  21235. "LSL r6, r6, %[n]\n\t"
  21236. "LSR r3, r3, r7\n\t"
  21237. "ORR r4, r4, r3\n\t"
  21238. "LDR r5, [%[a], #116]\n\t"
  21239. "STR r4, [%[r], #124]\n\t"
  21240. "LSR r3, r5, #1\n\t"
  21241. "LSL r5, r5, %[n]\n\t"
  21242. "LSR r3, r3, r7\n\t"
  21243. "ORR r6, r6, r3\n\t"
  21244. "LDR r4, [%[a], #112]\n\t"
  21245. "STR r6, [%[r], #120]\n\t"
  21246. "LSR r3, r4, #1\n\t"
  21247. "LSL r4, r4, %[n]\n\t"
  21248. "LSR r3, r3, r7\n\t"
  21249. "ORR r5, r5, r3\n\t"
  21250. "LDR r6, [%[a], #108]\n\t"
  21251. "STR r5, [%[r], #116]\n\t"
  21252. "LSR r3, r6, #1\n\t"
  21253. "LSL r6, r6, %[n]\n\t"
  21254. "LSR r3, r3, r7\n\t"
  21255. "ORR r4, r4, r3\n\t"
  21256. "LDR r5, [%[a], #104]\n\t"
  21257. "STR r4, [%[r], #112]\n\t"
  21258. "LSR r3, r5, #1\n\t"
  21259. "LSL r5, r5, %[n]\n\t"
  21260. "LSR r3, r3, r7\n\t"
  21261. "ORR r6, r6, r3\n\t"
  21262. "LDR r4, [%[a], #100]\n\t"
  21263. "STR r6, [%[r], #108]\n\t"
  21264. "LSR r3, r4, #1\n\t"
  21265. "LSL r4, r4, %[n]\n\t"
  21266. "LSR r3, r3, r7\n\t"
  21267. "ORR r5, r5, r3\n\t"
  21268. "LDR r6, [%[a], #96]\n\t"
  21269. "STR r5, [%[r], #104]\n\t"
  21270. "LSR r3, r6, #1\n\t"
  21271. "LSL r6, r6, %[n]\n\t"
  21272. "LSR r3, r3, r7\n\t"
  21273. "ORR r4, r4, r3\n\t"
  21274. "LDR r5, [%[a], #92]\n\t"
  21275. "STR r4, [%[r], #100]\n\t"
  21276. "LSR r3, r5, #1\n\t"
  21277. "LSL r5, r5, %[n]\n\t"
  21278. "LSR r3, r3, r7\n\t"
  21279. "ORR r6, r6, r3\n\t"
  21280. "LDR r4, [%[a], #88]\n\t"
  21281. "STR r6, [%[r], #96]\n\t"
  21282. "LSR r3, r4, #1\n\t"
  21283. "LSL r4, r4, %[n]\n\t"
  21284. "LSR r3, r3, r7\n\t"
  21285. "ORR r5, r5, r3\n\t"
  21286. "LDR r6, [%[a], #84]\n\t"
  21287. "STR r5, [%[r], #92]\n\t"
  21288. "LSR r3, r6, #1\n\t"
  21289. "LSL r6, r6, %[n]\n\t"
  21290. "LSR r3, r3, r7\n\t"
  21291. "ORR r4, r4, r3\n\t"
  21292. "LDR r5, [%[a], #80]\n\t"
  21293. "STR r4, [%[r], #88]\n\t"
  21294. "LSR r3, r5, #1\n\t"
  21295. "LSL r5, r5, %[n]\n\t"
  21296. "LSR r3, r3, r7\n\t"
  21297. "ORR r6, r6, r3\n\t"
  21298. "LDR r4, [%[a], #76]\n\t"
  21299. "STR r6, [%[r], #84]\n\t"
  21300. "LSR r3, r4, #1\n\t"
  21301. "LSL r4, r4, %[n]\n\t"
  21302. "LSR r3, r3, r7\n\t"
  21303. "ORR r5, r5, r3\n\t"
  21304. "LDR r6, [%[a], #72]\n\t"
  21305. "STR r5, [%[r], #80]\n\t"
  21306. "LSR r3, r6, #1\n\t"
  21307. "LSL r6, r6, %[n]\n\t"
  21308. "LSR r3, r3, r7\n\t"
  21309. "ORR r4, r4, r3\n\t"
  21310. "LDR r5, [%[a], #68]\n\t"
  21311. "STR r4, [%[r], #76]\n\t"
  21312. "LSR r3, r5, #1\n\t"
  21313. "LSL r5, r5, %[n]\n\t"
  21314. "LSR r3, r3, r7\n\t"
  21315. "ORR r6, r6, r3\n\t"
  21316. "LDR r4, [%[a], #64]\n\t"
  21317. "STR r6, [%[r], #72]\n\t"
  21318. "LSR r3, r4, #1\n\t"
  21319. "LSL r4, r4, %[n]\n\t"
  21320. "LSR r3, r3, r7\n\t"
  21321. "ORR r5, r5, r3\n\t"
  21322. "LDR r6, [%[a], #60]\n\t"
  21323. "STR r5, [%[r], #68]\n\t"
  21324. "LSR r3, r6, #1\n\t"
  21325. "LSL r6, r6, %[n]\n\t"
  21326. "LSR r3, r3, r7\n\t"
  21327. "ORR r4, r4, r3\n\t"
  21328. "LDR r5, [%[a], #56]\n\t"
  21329. "STR r4, [%[r], #64]\n\t"
  21330. "LSR r3, r5, #1\n\t"
  21331. "LSL r5, r5, %[n]\n\t"
  21332. "LSR r3, r3, r7\n\t"
  21333. "ORR r6, r6, r3\n\t"
  21334. "LDR r4, [%[a], #52]\n\t"
  21335. "STR r6, [%[r], #60]\n\t"
  21336. "LSR r3, r4, #1\n\t"
  21337. "LSL r4, r4, %[n]\n\t"
  21338. "LSR r3, r3, r7\n\t"
  21339. "ORR r5, r5, r3\n\t"
  21340. "LDR r6, [%[a], #48]\n\t"
  21341. "STR r5, [%[r], #56]\n\t"
  21342. "LSR r3, r6, #1\n\t"
  21343. "LSL r6, r6, %[n]\n\t"
  21344. "LSR r3, r3, r7\n\t"
  21345. "ORR r4, r4, r3\n\t"
  21346. "LDR r5, [%[a], #44]\n\t"
  21347. "STR r4, [%[r], #52]\n\t"
  21348. "LSR r3, r5, #1\n\t"
  21349. "LSL r5, r5, %[n]\n\t"
  21350. "LSR r3, r3, r7\n\t"
  21351. "ORR r6, r6, r3\n\t"
  21352. "LDR r4, [%[a], #40]\n\t"
  21353. "STR r6, [%[r], #48]\n\t"
  21354. "LSR r3, r4, #1\n\t"
  21355. "LSL r4, r4, %[n]\n\t"
  21356. "LSR r3, r3, r7\n\t"
  21357. "ORR r5, r5, r3\n\t"
  21358. "LDR r6, [%[a], #36]\n\t"
  21359. "STR r5, [%[r], #44]\n\t"
  21360. "LSR r3, r6, #1\n\t"
  21361. "LSL r6, r6, %[n]\n\t"
  21362. "LSR r3, r3, r7\n\t"
  21363. "ORR r4, r4, r3\n\t"
  21364. "LDR r5, [%[a], #32]\n\t"
  21365. "STR r4, [%[r], #40]\n\t"
  21366. "LSR r3, r5, #1\n\t"
  21367. "LSL r5, r5, %[n]\n\t"
  21368. "LSR r3, r3, r7\n\t"
  21369. "ORR r6, r6, r3\n\t"
  21370. "LDR r4, [%[a], #28]\n\t"
  21371. "STR r6, [%[r], #36]\n\t"
  21372. "LSR r3, r4, #1\n\t"
  21373. "LSL r4, r4, %[n]\n\t"
  21374. "LSR r3, r3, r7\n\t"
  21375. "ORR r5, r5, r3\n\t"
  21376. "LDR r6, [%[a], #24]\n\t"
  21377. "STR r5, [%[r], #32]\n\t"
  21378. "LSR r3, r6, #1\n\t"
  21379. "LSL r6, r6, %[n]\n\t"
  21380. "LSR r3, r3, r7\n\t"
  21381. "ORR r4, r4, r3\n\t"
  21382. "LDR r5, [%[a], #20]\n\t"
  21383. "STR r4, [%[r], #28]\n\t"
  21384. "LSR r3, r5, #1\n\t"
  21385. "LSL r5, r5, %[n]\n\t"
  21386. "LSR r3, r3, r7\n\t"
  21387. "ORR r6, r6, r3\n\t"
  21388. "LDR r4, [%[a], #16]\n\t"
  21389. "STR r6, [%[r], #24]\n\t"
  21390. "LSR r3, r4, #1\n\t"
  21391. "LSL r4, r4, %[n]\n\t"
  21392. "LSR r3, r3, r7\n\t"
  21393. "ORR r5, r5, r3\n\t"
  21394. "LDR r6, [%[a], #12]\n\t"
  21395. "STR r5, [%[r], #20]\n\t"
  21396. "LSR r3, r6, #1\n\t"
  21397. "LSL r6, r6, %[n]\n\t"
  21398. "LSR r3, r3, r7\n\t"
  21399. "ORR r4, r4, r3\n\t"
  21400. "LDR r5, [%[a], #8]\n\t"
  21401. "STR r4, [%[r], #16]\n\t"
  21402. "LSR r3, r5, #1\n\t"
  21403. "LSL r5, r5, %[n]\n\t"
  21404. "LSR r3, r3, r7\n\t"
  21405. "ORR r6, r6, r3\n\t"
  21406. "LDR r4, [%[a], #4]\n\t"
  21407. "STR r6, [%[r], #12]\n\t"
  21408. "LSR r3, r4, #1\n\t"
  21409. "LSL r4, r4, %[n]\n\t"
  21410. "LSR r3, r3, r7\n\t"
  21411. "ORR r5, r5, r3\n\t"
  21412. "LDR r6, [%[a]]\n\t"
  21413. "STR r5, [%[r], #8]\n\t"
  21414. "LSR r3, r6, #1\n\t"
  21415. "LSL r6, r6, %[n]\n\t"
  21416. "LSR r3, r3, r7\n\t"
  21417. "ORR r4, r4, r3\n\t"
  21418. "STR r6, [%[r]]\n\t"
  21419. "STR r4, [%[r], #4]\n\t"
  21420. : [r] "+r" (r), [a] "+r" (a), [n] "+r" (n)
  21421. :
  21422. : "memory", "r4", "r5", "r6", "r3", "r7", "cc"
  21423. );
  21424. }
  21425. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  21426. *
  21427. * r A single precision number that is the result of the operation.
  21428. * e A single precision number that is the exponent.
  21429. * bits The number of bits in the exponent.
  21430. * m A single precision number that is the modulus.
  21431. * returns 0 on success.
  21432. * returns MEMORY_E on dynamic memory allocation failure.
  21433. * returns MP_VAL when base is even.
  21434. */
  21435. static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits,
  21436. const sp_digit* m)
  21437. {
  21438. #ifdef WOLFSSL_SP_SMALL_STACK
  21439. sp_digit* td = NULL;
  21440. #else
  21441. sp_digit td[289];
  21442. #endif
  21443. sp_digit* norm = NULL;
  21444. sp_digit* tmp = NULL;
  21445. sp_digit mp = 1;
  21446. sp_digit n;
  21447. sp_digit o;
  21448. sp_digit mask;
  21449. int i;
  21450. int c;
  21451. byte y;
  21452. int err = MP_OKAY;
  21453. if (bits == 0) {
  21454. err = MP_VAL;
  21455. }
  21456. #ifdef WOLFSSL_SP_SMALL_STACK
  21457. if (err == MP_OKAY) {
  21458. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL,
  21459. DYNAMIC_TYPE_TMP_BUFFER);
  21460. if (td == NULL)
  21461. err = MEMORY_E;
  21462. }
  21463. #endif
  21464. if (err == MP_OKAY) {
  21465. norm = td;
  21466. tmp = td + 192;
  21467. sp_3072_mont_setup(m, &mp);
  21468. sp_3072_mont_norm_96(norm, m);
  21469. i = (bits - 1) / 32;
  21470. n = e[i--];
  21471. c = bits & 31;
  21472. if (c == 0) {
  21473. c = 32;
  21474. }
  21475. c -= bits % 5;
  21476. if (c == 32) {
  21477. c = 27;
  21478. }
  21479. if (c < 0) {
  21480. /* Number of bits in top word is less than number needed. */
  21481. c = -c;
  21482. y = (byte)(n << c);
  21483. n = e[i--];
  21484. y |= (byte)(n >> (64 - c));
  21485. n <<= c;
  21486. c = 64 - c;
  21487. }
  21488. else if (c == 0) {
  21489. /* All bits in top word used. */
  21490. y = (byte)n;
  21491. }
  21492. else {
  21493. y = (byte)(n >> c);
  21494. n <<= 32 - c;
  21495. }
  21496. sp_3072_lshift_96(r, norm, y);
  21497. for (; i>=0 || c>=5; ) {
  21498. if (c == 0) {
  21499. n = e[i--];
  21500. y = (byte)(n >> 27);
  21501. n <<= 5;
  21502. c = 27;
  21503. }
  21504. else if (c < 5) {
  21505. y = (byte)(n >> 27);
  21506. n = e[i--];
  21507. c = 5 - c;
  21508. y |= (byte)(n >> (32 - c));
  21509. n <<= c;
  21510. c = 32 - c;
  21511. }
  21512. else {
  21513. y = (byte)((n >> 27) & 0x1f);
  21514. n <<= 5;
  21515. c -= 5;
  21516. }
  21517. sp_3072_mont_sqr_96(r, r, m, mp);
  21518. sp_3072_mont_sqr_96(r, r, m, mp);
  21519. sp_3072_mont_sqr_96(r, r, m, mp);
  21520. sp_3072_mont_sqr_96(r, r, m, mp);
  21521. sp_3072_mont_sqr_96(r, r, m, mp);
  21522. sp_3072_lshift_96(r, r, y);
  21523. sp_3072_mul_d_96(tmp, norm, r[96]);
  21524. r[96] = 0;
  21525. o = sp_3072_add_96(r, r, tmp);
  21526. sp_3072_cond_sub_96(r, r, m, (sp_digit)0 - o);
  21527. }
  21528. XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U);
  21529. sp_3072_mont_reduce_96(r, m, mp);
  21530. mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
  21531. sp_3072_cond_sub_96(r, r, m, mask);
  21532. }
  21533. #ifdef WOLFSSL_SP_SMALL_STACK
  21534. if (td != NULL)
  21535. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  21536. #endif
  21537. return err;
  21538. }
  21539. #endif /* HAVE_FFDHE_3072 */
  21540. /* Perform the modular exponentiation for Diffie-Hellman.
  21541. *
  21542. * base Base.
  21543. * exp Array of bytes that is the exponent.
  21544. * expLen Length of data, in bytes, in exponent.
  21545. * mod Modulus.
  21546. * out Buffer to hold big-endian bytes of exponentiation result.
  21547. * Must be at least 384 bytes long.
  21548. * outLen Length, in bytes, of exponentiation result.
  21549. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  21550. * and MEMORY_E if memory allocation fails.
  21551. */
  21552. int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
  21553. const mp_int* mod, byte* out, word32* outLen)
  21554. {
  21555. int err = MP_OKAY;
  21556. sp_digit b[192];
  21557. sp_digit e[96];
  21558. sp_digit m[96];
  21559. sp_digit* r = b;
  21560. word32 i;
  21561. if (mp_count_bits(base) > 3072) {
  21562. err = MP_READ_E;
  21563. }
  21564. else if (expLen > 384) {
  21565. err = MP_READ_E;
  21566. }
  21567. else if (mp_count_bits(mod) != 3072) {
  21568. err = MP_READ_E;
  21569. }
  21570. else if (mp_iseven(mod)) {
  21571. err = MP_VAL;
  21572. }
  21573. if (err == MP_OKAY) {
  21574. sp_3072_from_mp(b, 96, base);
  21575. sp_3072_from_bin(e, 96, exp, expLen);
  21576. sp_3072_from_mp(m, 96, mod);
  21577. #ifdef HAVE_FFDHE_3072
  21578. if (base->used == 1 && base->dp[0] == 2 && m[95] == (sp_digit)-1)
  21579. err = sp_3072_mod_exp_2_96(r, e, expLen * 8, m);
  21580. else
  21581. #endif
  21582. err = sp_3072_mod_exp_96(r, b, e, expLen * 8, m, 0);
  21583. }
  21584. if (err == MP_OKAY) {
  21585. sp_3072_to_bin_96(r, out);
  21586. *outLen = 384;
  21587. for (i=0; i<384 && out[i] == 0; i++) {
  21588. /* Search for first non-zero. */
  21589. }
  21590. *outLen -= i;
  21591. XMEMMOVE(out, out + i, *outLen);
  21592. }
  21593. XMEMSET(e, 0, sizeof(e));
  21594. return err;
  21595. }
  21596. #endif /* WOLFSSL_HAVE_SP_DH */
  21597. /* Perform the modular exponentiation for Diffie-Hellman.
  21598. *
  21599. * base Base. MP integer.
  21600. * exp Exponent. MP integer.
  21601. * mod Modulus. MP integer.
  21602. * res Result. MP integer.
  21603. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  21604. * and MEMORY_E if memory allocation fails.
  21605. */
  21606. int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
  21607. mp_int* res)
  21608. {
  21609. int err = MP_OKAY;
  21610. sp_digit b[96];
  21611. sp_digit e[48];
  21612. sp_digit m[48];
  21613. sp_digit* r = b;
  21614. int expBits = mp_count_bits(exp);
  21615. if (mp_count_bits(base) > 1536) {
  21616. err = MP_READ_E;
  21617. }
  21618. else if (expBits > 1536) {
  21619. err = MP_READ_E;
  21620. }
  21621. else if (mp_count_bits(mod) != 1536) {
  21622. err = MP_READ_E;
  21623. }
  21624. else if (mp_iseven(mod)) {
  21625. err = MP_VAL;
  21626. }
  21627. if (err == MP_OKAY) {
  21628. sp_3072_from_mp(b, 48, base);
  21629. sp_3072_from_mp(e, 48, exp);
  21630. sp_3072_from_mp(m, 48, mod);
  21631. err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0);
  21632. }
  21633. if (err == MP_OKAY) {
  21634. XMEMSET(r + 48, 0, sizeof(*r) * 48U);
  21635. err = sp_3072_to_mp(r, res);
  21636. res->used = mod->used;
  21637. mp_clamp(res);
  21638. }
  21639. XMEMSET(e, 0, sizeof(e));
  21640. return err;
  21641. }
  21642. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  21643. #endif /* !WOLFSSL_SP_NO_3072 */
  21644. #ifdef WOLFSSL_SP_4096
  21645. /* Read big endian unsigned byte array into r.
  21646. *
  21647. * r A single precision integer.
  21648. * size Maximum number of bytes to convert
  21649. * a Byte array.
  21650. * n Number of bytes in array to read.
  21651. */
  21652. static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
  21653. {
  21654. int i;
  21655. int j;
  21656. byte* d;
  21657. for (i = n - 1,j = 0; i >= 3; i -= 4) {
  21658. r[j] = ((sp_digit)a[i - 0] << 0) |
  21659. ((sp_digit)a[i - 1] << 8) |
  21660. ((sp_digit)a[i - 2] << 16) |
  21661. ((sp_digit)a[i - 3] << 24);
  21662. j++;
  21663. }
  21664. if (i >= 0) {
  21665. r[j] = 0;
  21666. d = (byte*)r;
  21667. switch (i) {
  21668. case 2: d[n - 1 - 2] = a[2]; //fallthrough
  21669. case 1: d[n - 1 - 1] = a[1]; //fallthrough
  21670. case 0: d[n - 1 - 0] = a[0]; //fallthrough
  21671. }
  21672. j++;
  21673. }
  21674. for (; j < size; j++) {
  21675. r[j] = 0;
  21676. }
  21677. }
  21678. /* Convert an mp_int to an array of sp_digit.
  21679. *
  21680. * r A single precision integer.
  21681. * size Maximum number of bytes to convert
  21682. * a A multi-precision integer.
  21683. */
  21684. static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
  21685. {
  21686. #if DIGIT_BIT == 32
  21687. int i;
  21688. sp_digit j = (sp_digit)0 - (sp_digit)a->used;
  21689. int o = 0;
  21690. for (i = 0; i < size; i++) {
  21691. sp_digit mask = (sp_digit)0 - (j >> 31);
  21692. r[i] = a->dp[o] & mask;
  21693. j++;
  21694. o += (int)(j >> 31);
  21695. }
  21696. #elif DIGIT_BIT > 32
  21697. unsigned int i;
  21698. int j = 0;
  21699. word32 s = 0;
  21700. r[0] = 0;
  21701. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  21702. r[j] |= ((sp_digit)a->dp[i] << s);
  21703. r[j] &= 0xffffffff;
  21704. s = 32U - s;
  21705. if (j + 1 >= size) {
  21706. break;
  21707. }
  21708. /* lint allow cast of mismatch word32 and mp_digit */
  21709. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  21710. while ((s + 32U) <= (word32)DIGIT_BIT) {
  21711. s += 32U;
  21712. r[j] &= 0xffffffff;
  21713. if (j + 1 >= size) {
  21714. break;
  21715. }
  21716. if (s < (word32)DIGIT_BIT) {
  21717. /* lint allow cast of mismatch word32 and mp_digit */
  21718. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  21719. }
  21720. else {
  21721. r[++j] = (sp_digit)0;
  21722. }
  21723. }
  21724. s = (word32)DIGIT_BIT - s;
  21725. }
  21726. for (j++; j < size; j++) {
  21727. r[j] = 0;
  21728. }
  21729. #else
  21730. unsigned int i;
  21731. int j = 0;
  21732. int s = 0;
  21733. r[0] = 0;
  21734. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  21735. r[j] |= ((sp_digit)a->dp[i]) << s;
  21736. if (s + DIGIT_BIT >= 32) {
  21737. r[j] &= 0xffffffff;
  21738. if (j + 1 >= size) {
  21739. break;
  21740. }
  21741. s = 32 - s;
  21742. if (s == DIGIT_BIT) {
  21743. r[++j] = 0;
  21744. s = 0;
  21745. }
  21746. else {
  21747. r[++j] = a->dp[i] >> s;
  21748. s = DIGIT_BIT - s;
  21749. }
  21750. }
  21751. else {
  21752. s += DIGIT_BIT;
  21753. }
  21754. }
  21755. for (j++; j < size; j++) {
  21756. r[j] = 0;
  21757. }
  21758. #endif
  21759. }
  21760. /* Write r as big endian to byte array.
  21761. * Fixed length number of bytes written: 512
  21762. *
  21763. * r A single precision integer.
  21764. * a Byte array.
  21765. */
  21766. static void sp_4096_to_bin_128(sp_digit* r, byte* a)
  21767. {
  21768. int i;
  21769. int j = 0;
  21770. for (i = 127; i >= 0; i--) {
  21771. a[j++] = r[i] >> 24;
  21772. a[j++] = r[i] >> 16;
  21773. a[j++] = r[i] >> 8;
  21774. a[j++] = r[i] >> 0;
  21775. }
  21776. }
  21777. #if (defined(WOLFSSL_HAVE_SP_RSA) && (!defined(WOLFSSL_RSA_PUBLIC_ONLY) || !defined(WOLFSSL_SP_SMALL))) || defined(WOLFSSL_HAVE_SP_DH)
  21778. /* Normalize the values in each word to 32.
  21779. *
  21780. * a Array of sp_digit to normalize.
  21781. */
  21782. #define sp_4096_norm_128(a)
  21783. #endif /* (WOLFSSL_HAVE_SP_RSA && (!WOLFSSL_RSA_PUBLIC_ONLY || !WOLFSSL_SP_SMALL)) || WOLFSSL_HAVE_SP_DH */
  21784. /* Normalize the values in each word to 32.
  21785. *
  21786. * a Array of sp_digit to normalize.
  21787. */
  21788. #define sp_4096_norm_128(a)
  21789. #ifndef WOLFSSL_SP_SMALL
  21790. /* Sub b from a into a. (a -= b)
  21791. *
  21792. * a A single precision integer and result.
  21793. * b A single precision integer.
  21794. */
  21795. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  21796. static sp_digit sp_4096_sub_in_place_128(sp_digit* a_p, const sp_digit* b_p)
  21797. #else
  21798. static sp_digit sp_4096_sub_in_place_128(sp_digit* a, const sp_digit* b)
  21799. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  21800. {
  21801. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  21802. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  21803. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  21804. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  21805. __asm__ __volatile__ (
  21806. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21807. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21808. "SUBS r2, r2, r6\n\t"
  21809. "SBCS r3, r3, r7\n\t"
  21810. "SBCS r4, r4, r8\n\t"
  21811. "SBCS r5, r5, r9\n\t"
  21812. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21813. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21814. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21815. "SBCS r2, r2, r6\n\t"
  21816. "SBCS r3, r3, r7\n\t"
  21817. "SBCS r4, r4, r8\n\t"
  21818. "SBCS r5, r5, r9\n\t"
  21819. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21820. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21821. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21822. "SBCS r2, r2, r6\n\t"
  21823. "SBCS r3, r3, r7\n\t"
  21824. "SBCS r4, r4, r8\n\t"
  21825. "SBCS r5, r5, r9\n\t"
  21826. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21827. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21828. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21829. "SBCS r2, r2, r6\n\t"
  21830. "SBCS r3, r3, r7\n\t"
  21831. "SBCS r4, r4, r8\n\t"
  21832. "SBCS r5, r5, r9\n\t"
  21833. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21834. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21835. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21836. "SBCS r2, r2, r6\n\t"
  21837. "SBCS r3, r3, r7\n\t"
  21838. "SBCS r4, r4, r8\n\t"
  21839. "SBCS r5, r5, r9\n\t"
  21840. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21841. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21842. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21843. "SBCS r2, r2, r6\n\t"
  21844. "SBCS r3, r3, r7\n\t"
  21845. "SBCS r4, r4, r8\n\t"
  21846. "SBCS r5, r5, r9\n\t"
  21847. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21848. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21849. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21850. "SBCS r2, r2, r6\n\t"
  21851. "SBCS r3, r3, r7\n\t"
  21852. "SBCS r4, r4, r8\n\t"
  21853. "SBCS r5, r5, r9\n\t"
  21854. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21855. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21856. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21857. "SBCS r2, r2, r6\n\t"
  21858. "SBCS r3, r3, r7\n\t"
  21859. "SBCS r4, r4, r8\n\t"
  21860. "SBCS r5, r5, r9\n\t"
  21861. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21862. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21863. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21864. "SBCS r2, r2, r6\n\t"
  21865. "SBCS r3, r3, r7\n\t"
  21866. "SBCS r4, r4, r8\n\t"
  21867. "SBCS r5, r5, r9\n\t"
  21868. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21869. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21870. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21871. "SBCS r2, r2, r6\n\t"
  21872. "SBCS r3, r3, r7\n\t"
  21873. "SBCS r4, r4, r8\n\t"
  21874. "SBCS r5, r5, r9\n\t"
  21875. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21876. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21877. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21878. "SBCS r2, r2, r6\n\t"
  21879. "SBCS r3, r3, r7\n\t"
  21880. "SBCS r4, r4, r8\n\t"
  21881. "SBCS r5, r5, r9\n\t"
  21882. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21883. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21884. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21885. "SBCS r2, r2, r6\n\t"
  21886. "SBCS r3, r3, r7\n\t"
  21887. "SBCS r4, r4, r8\n\t"
  21888. "SBCS r5, r5, r9\n\t"
  21889. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21890. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21891. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21892. "SBCS r2, r2, r6\n\t"
  21893. "SBCS r3, r3, r7\n\t"
  21894. "SBCS r4, r4, r8\n\t"
  21895. "SBCS r5, r5, r9\n\t"
  21896. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21897. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21898. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21899. "SBCS r2, r2, r6\n\t"
  21900. "SBCS r3, r3, r7\n\t"
  21901. "SBCS r4, r4, r8\n\t"
  21902. "SBCS r5, r5, r9\n\t"
  21903. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21904. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21905. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21906. "SBCS r2, r2, r6\n\t"
  21907. "SBCS r3, r3, r7\n\t"
  21908. "SBCS r4, r4, r8\n\t"
  21909. "SBCS r5, r5, r9\n\t"
  21910. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21911. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21912. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21913. "SBCS r2, r2, r6\n\t"
  21914. "SBCS r3, r3, r7\n\t"
  21915. "SBCS r4, r4, r8\n\t"
  21916. "SBCS r5, r5, r9\n\t"
  21917. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21918. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21919. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21920. "SBCS r2, r2, r6\n\t"
  21921. "SBCS r3, r3, r7\n\t"
  21922. "SBCS r4, r4, r8\n\t"
  21923. "SBCS r5, r5, r9\n\t"
  21924. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21925. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21926. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21927. "SBCS r2, r2, r6\n\t"
  21928. "SBCS r3, r3, r7\n\t"
  21929. "SBCS r4, r4, r8\n\t"
  21930. "SBCS r5, r5, r9\n\t"
  21931. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21932. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21933. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21934. "SBCS r2, r2, r6\n\t"
  21935. "SBCS r3, r3, r7\n\t"
  21936. "SBCS r4, r4, r8\n\t"
  21937. "SBCS r5, r5, r9\n\t"
  21938. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21939. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21940. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21941. "SBCS r2, r2, r6\n\t"
  21942. "SBCS r3, r3, r7\n\t"
  21943. "SBCS r4, r4, r8\n\t"
  21944. "SBCS r5, r5, r9\n\t"
  21945. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21946. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21947. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21948. "SBCS r2, r2, r6\n\t"
  21949. "SBCS r3, r3, r7\n\t"
  21950. "SBCS r4, r4, r8\n\t"
  21951. "SBCS r5, r5, r9\n\t"
  21952. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21953. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21954. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21955. "SBCS r2, r2, r6\n\t"
  21956. "SBCS r3, r3, r7\n\t"
  21957. "SBCS r4, r4, r8\n\t"
  21958. "SBCS r5, r5, r9\n\t"
  21959. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21960. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21961. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21962. "SBCS r2, r2, r6\n\t"
  21963. "SBCS r3, r3, r7\n\t"
  21964. "SBCS r4, r4, r8\n\t"
  21965. "SBCS r5, r5, r9\n\t"
  21966. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21967. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21968. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21969. "SBCS r2, r2, r6\n\t"
  21970. "SBCS r3, r3, r7\n\t"
  21971. "SBCS r4, r4, r8\n\t"
  21972. "SBCS r5, r5, r9\n\t"
  21973. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21974. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21975. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21976. "SBCS r2, r2, r6\n\t"
  21977. "SBCS r3, r3, r7\n\t"
  21978. "SBCS r4, r4, r8\n\t"
  21979. "SBCS r5, r5, r9\n\t"
  21980. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21981. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21982. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21983. "SBCS r2, r2, r6\n\t"
  21984. "SBCS r3, r3, r7\n\t"
  21985. "SBCS r4, r4, r8\n\t"
  21986. "SBCS r5, r5, r9\n\t"
  21987. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21988. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21989. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21990. "SBCS r2, r2, r6\n\t"
  21991. "SBCS r3, r3, r7\n\t"
  21992. "SBCS r4, r4, r8\n\t"
  21993. "SBCS r5, r5, r9\n\t"
  21994. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  21995. "LDM %[a], {r2, r3, r4, r5}\n\t"
  21996. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  21997. "SBCS r2, r2, r6\n\t"
  21998. "SBCS r3, r3, r7\n\t"
  21999. "SBCS r4, r4, r8\n\t"
  22000. "SBCS r5, r5, r9\n\t"
  22001. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  22002. "LDM %[a], {r2, r3, r4, r5}\n\t"
  22003. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  22004. "SBCS r2, r2, r6\n\t"
  22005. "SBCS r3, r3, r7\n\t"
  22006. "SBCS r4, r4, r8\n\t"
  22007. "SBCS r5, r5, r9\n\t"
  22008. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  22009. "LDM %[a], {r2, r3, r4, r5}\n\t"
  22010. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  22011. "SBCS r2, r2, r6\n\t"
  22012. "SBCS r3, r3, r7\n\t"
  22013. "SBCS r4, r4, r8\n\t"
  22014. "SBCS r5, r5, r9\n\t"
  22015. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  22016. "LDM %[a], {r2, r3, r4, r5}\n\t"
  22017. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  22018. "SBCS r2, r2, r6\n\t"
  22019. "SBCS r3, r3, r7\n\t"
  22020. "SBCS r4, r4, r8\n\t"
  22021. "SBCS r5, r5, r9\n\t"
  22022. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  22023. "LDM %[a], {r2, r3, r4, r5}\n\t"
  22024. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  22025. "SBCS r2, r2, r6\n\t"
  22026. "SBCS r3, r3, r7\n\t"
  22027. "SBCS r4, r4, r8\n\t"
  22028. "SBCS r5, r5, r9\n\t"
  22029. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  22030. "SBC %[a], r9, r9\n\t"
  22031. : [a] "+r" (a), [b] "+r" (b)
  22032. :
  22033. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  22034. );
  22035. return (uint32_t)(size_t)a;
  22036. }
  22037. /* Add b to a into r. (r = a + b)
  22038. *
  22039. * r A single precision integer.
  22040. * a A single precision integer.
  22041. * b A single precision integer.
  22042. */
  22043. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22044. static sp_digit sp_4096_add_128(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  22045. #else
  22046. static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, const sp_digit* b)
  22047. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22048. {
  22049. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22050. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  22051. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  22052. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  22053. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22054. __asm__ __volatile__ (
  22055. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22056. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22057. "ADDS r3, r3, r7\n\t"
  22058. "ADCS r4, r4, r8\n\t"
  22059. "ADCS r5, r5, r9\n\t"
  22060. "ADCS r6, r6, r10\n\t"
  22061. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22062. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22063. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22064. "ADCS r3, r3, r7\n\t"
  22065. "ADCS r4, r4, r8\n\t"
  22066. "ADCS r5, r5, r9\n\t"
  22067. "ADCS r6, r6, r10\n\t"
  22068. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22069. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22070. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22071. "ADCS r3, r3, r7\n\t"
  22072. "ADCS r4, r4, r8\n\t"
  22073. "ADCS r5, r5, r9\n\t"
  22074. "ADCS r6, r6, r10\n\t"
  22075. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22076. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22077. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22078. "ADCS r3, r3, r7\n\t"
  22079. "ADCS r4, r4, r8\n\t"
  22080. "ADCS r5, r5, r9\n\t"
  22081. "ADCS r6, r6, r10\n\t"
  22082. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22083. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22084. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22085. "ADCS r3, r3, r7\n\t"
  22086. "ADCS r4, r4, r8\n\t"
  22087. "ADCS r5, r5, r9\n\t"
  22088. "ADCS r6, r6, r10\n\t"
  22089. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22090. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22091. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22092. "ADCS r3, r3, r7\n\t"
  22093. "ADCS r4, r4, r8\n\t"
  22094. "ADCS r5, r5, r9\n\t"
  22095. "ADCS r6, r6, r10\n\t"
  22096. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22097. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22098. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22099. "ADCS r3, r3, r7\n\t"
  22100. "ADCS r4, r4, r8\n\t"
  22101. "ADCS r5, r5, r9\n\t"
  22102. "ADCS r6, r6, r10\n\t"
  22103. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22104. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22105. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22106. "ADCS r3, r3, r7\n\t"
  22107. "ADCS r4, r4, r8\n\t"
  22108. "ADCS r5, r5, r9\n\t"
  22109. "ADCS r6, r6, r10\n\t"
  22110. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22111. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22112. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22113. "ADCS r3, r3, r7\n\t"
  22114. "ADCS r4, r4, r8\n\t"
  22115. "ADCS r5, r5, r9\n\t"
  22116. "ADCS r6, r6, r10\n\t"
  22117. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22118. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22119. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22120. "ADCS r3, r3, r7\n\t"
  22121. "ADCS r4, r4, r8\n\t"
  22122. "ADCS r5, r5, r9\n\t"
  22123. "ADCS r6, r6, r10\n\t"
  22124. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22125. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22126. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22127. "ADCS r3, r3, r7\n\t"
  22128. "ADCS r4, r4, r8\n\t"
  22129. "ADCS r5, r5, r9\n\t"
  22130. "ADCS r6, r6, r10\n\t"
  22131. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22132. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22133. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22134. "ADCS r3, r3, r7\n\t"
  22135. "ADCS r4, r4, r8\n\t"
  22136. "ADCS r5, r5, r9\n\t"
  22137. "ADCS r6, r6, r10\n\t"
  22138. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22139. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22140. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22141. "ADCS r3, r3, r7\n\t"
  22142. "ADCS r4, r4, r8\n\t"
  22143. "ADCS r5, r5, r9\n\t"
  22144. "ADCS r6, r6, r10\n\t"
  22145. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22146. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22147. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22148. "ADCS r3, r3, r7\n\t"
  22149. "ADCS r4, r4, r8\n\t"
  22150. "ADCS r5, r5, r9\n\t"
  22151. "ADCS r6, r6, r10\n\t"
  22152. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22153. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22154. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22155. "ADCS r3, r3, r7\n\t"
  22156. "ADCS r4, r4, r8\n\t"
  22157. "ADCS r5, r5, r9\n\t"
  22158. "ADCS r6, r6, r10\n\t"
  22159. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22160. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22161. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22162. "ADCS r3, r3, r7\n\t"
  22163. "ADCS r4, r4, r8\n\t"
  22164. "ADCS r5, r5, r9\n\t"
  22165. "ADCS r6, r6, r10\n\t"
  22166. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22167. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22168. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22169. "ADCS r3, r3, r7\n\t"
  22170. "ADCS r4, r4, r8\n\t"
  22171. "ADCS r5, r5, r9\n\t"
  22172. "ADCS r6, r6, r10\n\t"
  22173. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22174. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22175. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22176. "ADCS r3, r3, r7\n\t"
  22177. "ADCS r4, r4, r8\n\t"
  22178. "ADCS r5, r5, r9\n\t"
  22179. "ADCS r6, r6, r10\n\t"
  22180. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22181. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22182. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22183. "ADCS r3, r3, r7\n\t"
  22184. "ADCS r4, r4, r8\n\t"
  22185. "ADCS r5, r5, r9\n\t"
  22186. "ADCS r6, r6, r10\n\t"
  22187. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22188. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22189. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22190. "ADCS r3, r3, r7\n\t"
  22191. "ADCS r4, r4, r8\n\t"
  22192. "ADCS r5, r5, r9\n\t"
  22193. "ADCS r6, r6, r10\n\t"
  22194. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22195. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22196. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22197. "ADCS r3, r3, r7\n\t"
  22198. "ADCS r4, r4, r8\n\t"
  22199. "ADCS r5, r5, r9\n\t"
  22200. "ADCS r6, r6, r10\n\t"
  22201. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22202. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22203. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22204. "ADCS r3, r3, r7\n\t"
  22205. "ADCS r4, r4, r8\n\t"
  22206. "ADCS r5, r5, r9\n\t"
  22207. "ADCS r6, r6, r10\n\t"
  22208. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22209. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22210. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22211. "ADCS r3, r3, r7\n\t"
  22212. "ADCS r4, r4, r8\n\t"
  22213. "ADCS r5, r5, r9\n\t"
  22214. "ADCS r6, r6, r10\n\t"
  22215. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22216. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22217. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22218. "ADCS r3, r3, r7\n\t"
  22219. "ADCS r4, r4, r8\n\t"
  22220. "ADCS r5, r5, r9\n\t"
  22221. "ADCS r6, r6, r10\n\t"
  22222. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22223. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22224. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22225. "ADCS r3, r3, r7\n\t"
  22226. "ADCS r4, r4, r8\n\t"
  22227. "ADCS r5, r5, r9\n\t"
  22228. "ADCS r6, r6, r10\n\t"
  22229. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22230. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22231. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22232. "ADCS r3, r3, r7\n\t"
  22233. "ADCS r4, r4, r8\n\t"
  22234. "ADCS r5, r5, r9\n\t"
  22235. "ADCS r6, r6, r10\n\t"
  22236. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22237. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22238. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22239. "ADCS r3, r3, r7\n\t"
  22240. "ADCS r4, r4, r8\n\t"
  22241. "ADCS r5, r5, r9\n\t"
  22242. "ADCS r6, r6, r10\n\t"
  22243. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22244. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22245. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22246. "ADCS r3, r3, r7\n\t"
  22247. "ADCS r4, r4, r8\n\t"
  22248. "ADCS r5, r5, r9\n\t"
  22249. "ADCS r6, r6, r10\n\t"
  22250. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22251. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22252. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22253. "ADCS r3, r3, r7\n\t"
  22254. "ADCS r4, r4, r8\n\t"
  22255. "ADCS r5, r5, r9\n\t"
  22256. "ADCS r6, r6, r10\n\t"
  22257. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22258. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22259. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22260. "ADCS r3, r3, r7\n\t"
  22261. "ADCS r4, r4, r8\n\t"
  22262. "ADCS r5, r5, r9\n\t"
  22263. "ADCS r6, r6, r10\n\t"
  22264. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22265. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22266. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22267. "ADCS r3, r3, r7\n\t"
  22268. "ADCS r4, r4, r8\n\t"
  22269. "ADCS r5, r5, r9\n\t"
  22270. "ADCS r6, r6, r10\n\t"
  22271. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22272. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  22273. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  22274. "ADCS r3, r3, r7\n\t"
  22275. "ADCS r4, r4, r8\n\t"
  22276. "ADCS r5, r5, r9\n\t"
  22277. "ADCS r6, r6, r10\n\t"
  22278. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  22279. "MOV %[r], #0x0\n\t"
  22280. "ADC %[r], %[r], #0x0\n\t"
  22281. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  22282. :
  22283. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  22284. );
  22285. return (uint32_t)(size_t)r;
  22286. }
  22287. /* Multiply a and b into r. (r = a * b)
  22288. *
  22289. * r A single precision integer.
  22290. * a A single precision integer.
  22291. * b A single precision integer.
  22292. */
  22293. SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a,
  22294. const sp_digit* b)
  22295. {
  22296. sp_digit* z0 = r;
  22297. sp_digit z1[128];
  22298. sp_digit a1[64];
  22299. sp_digit b1[64];
  22300. sp_digit* z2 = r + 128;
  22301. sp_digit u;
  22302. sp_digit ca;
  22303. sp_digit cb;
  22304. ca = sp_2048_add_64(a1, a, &a[64]);
  22305. cb = sp_2048_add_64(b1, b, &b[64]);
  22306. u = ca & cb;
  22307. sp_2048_mul_64(z2, &a[64], &b[64]);
  22308. sp_2048_mul_64(z0, a, b);
  22309. sp_2048_mul_64(z1, a1, b1);
  22310. u += sp_4096_sub_in_place_128(z1, z0);
  22311. u += sp_4096_sub_in_place_128(z1, z2);
  22312. sp_2048_mask_64(a1, a1, 0 - cb);
  22313. u += sp_2048_add_64(z1 + 64, z1 + 64, a1);
  22314. sp_2048_mask_64(b1, b1, 0 - ca);
  22315. u += sp_2048_add_64(z1 + 64, z1 + 64, b1);
  22316. u += sp_4096_add_128(r + 64, r + 64, z1);
  22317. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (64 - 1));
  22318. a1[0] = u;
  22319. (void)sp_2048_add_64(r + 192, r + 192, a1);
  22320. }
  22321. /* Square a and put result in r. (r = a * a)
  22322. *
  22323. * r A single precision integer.
  22324. * a A single precision integer.
  22325. */
  22326. SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a)
  22327. {
  22328. sp_digit* z0 = r;
  22329. sp_digit* z2 = r + 128;
  22330. sp_digit z1[128];
  22331. sp_digit* a1 = z1;
  22332. sp_digit zero[64];
  22333. sp_digit u;
  22334. sp_digit mask;
  22335. sp_digit* p1;
  22336. sp_digit* p2;
  22337. XMEMSET(zero, 0, sizeof(sp_digit) * 64);
  22338. mask = sp_2048_sub_64(a1, a, &a[64]);
  22339. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  22340. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  22341. (void)sp_2048_sub_64(a1, p1, p2);
  22342. sp_2048_sqr_64(z2, &a[64]);
  22343. sp_2048_sqr_64(z0, a);
  22344. sp_2048_sqr_64(z1, a1);
  22345. u = 0;
  22346. u -= sp_4096_sub_in_place_128(z1, z2);
  22347. u -= sp_4096_sub_in_place_128(z1, z0);
  22348. u += sp_4096_sub_in_place_128(r + 64, z1);
  22349. zero[0] = u;
  22350. (void)sp_2048_add_64(r + 192, r + 192, zero);
  22351. }
  22352. #endif /* !WOLFSSL_SP_SMALL */
  22353. #ifdef WOLFSSL_SP_SMALL
  22354. /* Add b to a into r. (r = a + b)
  22355. *
  22356. * r A single precision integer.
  22357. * a A single precision integer.
  22358. * b A single precision integer.
  22359. */
  22360. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22361. static sp_digit sp_4096_add_128(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  22362. #else
  22363. static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, const sp_digit* b)
  22364. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22365. {
  22366. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22367. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  22368. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  22369. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  22370. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22371. __asm__ __volatile__ (
  22372. "MOV r3, #0x0\n\t"
  22373. "ADD r12, %[a], #0x200\n\t"
  22374. "\n"
  22375. "L_sp_4096_add_128_word:\n\t"
  22376. "ADDS r3, r3, #0xffffffff\n\t"
  22377. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  22378. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  22379. "ADCS r4, r4, r8\n\t"
  22380. "ADCS r5, r5, r9\n\t"
  22381. "ADCS r6, r6, r10\n\t"
  22382. "ADCS r7, r7, r11\n\t"
  22383. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  22384. "MOV r4, #0x0\n\t"
  22385. "ADC r3, r4, #0x0\n\t"
  22386. "CMP %[a], r12\n\t"
  22387. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22388. "BNE L_sp_4096_add_128_word\n\t"
  22389. #else
  22390. "BNE.N L_sp_4096_add_128_word\n\t"
  22391. #endif
  22392. "MOV %[r], r3\n\t"
  22393. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  22394. :
  22395. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  22396. );
  22397. return (uint32_t)(size_t)r;
  22398. }
  22399. #endif /* WOLFSSL_SP_SMALL */
  22400. #ifdef WOLFSSL_SP_SMALL
  22401. /* Sub b from a into a. (a -= b)
  22402. *
  22403. * a A single precision integer.
  22404. * b A single precision integer.
  22405. */
  22406. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22407. static sp_digit sp_4096_sub_in_place_128(sp_digit* a_p, const sp_digit* b_p)
  22408. #else
  22409. static sp_digit sp_4096_sub_in_place_128(sp_digit* a, const sp_digit* b)
  22410. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22411. {
  22412. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22413. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  22414. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  22415. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22416. __asm__ __volatile__ (
  22417. "MOV r10, #0x0\n\t"
  22418. "ADD r11, %[a], #0x200\n\t"
  22419. "\n"
  22420. "L_sp_4096_sub_in_pkace_128_word:\n\t"
  22421. "RSBS r10, r10, #0x0\n\t"
  22422. "LDM %[a], {r2, r3, r4, r5}\n\t"
  22423. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  22424. "SBCS r2, r2, r6\n\t"
  22425. "SBCS r3, r3, r7\n\t"
  22426. "SBCS r4, r4, r8\n\t"
  22427. "SBCS r5, r5, r9\n\t"
  22428. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  22429. "SBC r10, r10, r10\n\t"
  22430. "CMP %[a], r11\n\t"
  22431. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22432. "BNE L_sp_4096_sub_in_pkace_128_word\n\t"
  22433. #else
  22434. "BNE.N L_sp_4096_sub_in_pkace_128_word\n\t"
  22435. #endif
  22436. "MOV %[a], r10\n\t"
  22437. : [a] "+r" (a), [b] "+r" (b)
  22438. :
  22439. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  22440. );
  22441. return (uint32_t)(size_t)a;
  22442. }
  22443. #endif /* WOLFSSL_SP_SMALL */
  22444. #ifdef WOLFSSL_SP_SMALL
  22445. /* Multiply a and b into r. (r = a * b)
  22446. *
  22447. * r A single precision integer.
  22448. * a A single precision integer.
  22449. * b A single precision integer.
  22450. */
  22451. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22452. static void sp_4096_mul_128(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  22453. #else
  22454. static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b)
  22455. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22456. {
  22457. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22458. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  22459. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  22460. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  22461. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22462. __asm__ __volatile__ (
  22463. "SUB sp, sp, #0x400\n\t"
  22464. "LDR lr, [%[a]]\n\t"
  22465. "LDR r11, [%[b]]\n\t"
  22466. "UMULL r8, r6, lr, r11\n\t"
  22467. "STR r8, [sp]\n\t"
  22468. "MOV r7, #0x0\n\t"
  22469. "MOV r8, #0x0\n\t"
  22470. "MOV r5, #0x4\n\t"
  22471. "\n"
  22472. "L_sp_4096_mul_128_outer:\n\t"
  22473. "SUBS r3, r5, #0x1fc\n\t"
  22474. "IT cc\n\t"
  22475. "MOVCC r3, #0x0\n\t"
  22476. "SUB r4, r5, r3\n\t"
  22477. "\n"
  22478. "L_sp_4096_mul_128_inner:\n\t"
  22479. "LDR lr, [%[a], r3]\n\t"
  22480. "LDR r11, [%[b], r4]\n\t"
  22481. "UMULL r9, r10, lr, r11\n\t"
  22482. "ADDS r6, r6, r9\n\t"
  22483. "ADCS r7, r7, r10\n\t"
  22484. "ADC r8, r8, #0x0\n\t"
  22485. "LDR lr, [%[a], r4]\n\t"
  22486. "LDR r11, [%[b], r3]\n\t"
  22487. "UMULL r9, r10, lr, r11\n\t"
  22488. "ADDS r6, r6, r9\n\t"
  22489. "ADCS r7, r7, r10\n\t"
  22490. "ADC r8, r8, #0x0\n\t"
  22491. "ADD r3, r3, #0x4\n\t"
  22492. "SUB r4, r4, #0x4\n\t"
  22493. "CMP r3, r4\n\t"
  22494. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22495. "BGT L_sp_4096_mul_128_inner_done\n\t"
  22496. #else
  22497. "BGT.N L_sp_4096_mul_128_inner_done\n\t"
  22498. #endif
  22499. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22500. "BLT L_sp_4096_mul_128_inner\n\t"
  22501. #else
  22502. "BLT.N L_sp_4096_mul_128_inner\n\t"
  22503. #endif
  22504. "LDR lr, [%[a], r3]\n\t"
  22505. "LDR r11, [%[b], r3]\n\t"
  22506. "UMULL r9, r10, lr, r11\n\t"
  22507. "ADDS r6, r6, r9\n\t"
  22508. "ADCS r7, r7, r10\n\t"
  22509. "ADC r8, r8, #0x0\n\t"
  22510. "\n"
  22511. "L_sp_4096_mul_128_inner_done:\n\t"
  22512. "STR r6, [sp, r5]\n\t"
  22513. "MOV r6, r7\n\t"
  22514. "MOV r7, r8\n\t"
  22515. "MOV r8, #0x0\n\t"
  22516. "ADD r5, r5, #0x4\n\t"
  22517. "CMP r5, #0x3f4\n\t"
  22518. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22519. "BLE L_sp_4096_mul_128_outer\n\t"
  22520. #else
  22521. "BLE.N L_sp_4096_mul_128_outer\n\t"
  22522. #endif
  22523. "LDR lr, [%[a], #508]\n\t"
  22524. "LDR r11, [%[b], #508]\n\t"
  22525. "UMLAL r6, r7, lr, r11\n\t"
  22526. "STR r6, [sp, r5]\n\t"
  22527. "ADD r5, r5, #0x4\n\t"
  22528. "STR r7, [sp, r5]\n\t"
  22529. "\n"
  22530. "L_sp_4096_mul_128_store:\n\t"
  22531. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  22532. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  22533. "SUBS r5, r5, #0x20\n\t"
  22534. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22535. "BGT L_sp_4096_mul_128_store\n\t"
  22536. #else
  22537. "BGT.N L_sp_4096_mul_128_store\n\t"
  22538. #endif
  22539. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  22540. :
  22541. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  22542. );
  22543. }
  22544. /* Square a and put result in r. (r = a * a)
  22545. *
  22546. * r A single precision integer.
  22547. * a A single precision integer.
  22548. */
  22549. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22550. static void sp_4096_sqr_128(sp_digit* r_p, const sp_digit* a_p)
  22551. #else
  22552. static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a)
  22553. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22554. {
  22555. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22556. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  22557. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  22558. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22559. __asm__ __volatile__ (
  22560. "SUB sp, sp, #0x400\n\t"
  22561. "LDR lr, [%[a]]\n\t"
  22562. "UMULL r8, r6, lr, lr\n\t"
  22563. "STR r8, [sp]\n\t"
  22564. "MOV r7, #0x0\n\t"
  22565. "MOV r8, #0x0\n\t"
  22566. "MOV r5, #0x4\n\t"
  22567. "\n"
  22568. "L_sp_4096_sqr_128_outer:\n\t"
  22569. "SUBS r3, r5, #0x1fc\n\t"
  22570. "IT cc\n\t"
  22571. "MOVCC r3, #0x0\n\t"
  22572. "SUB r4, r5, r3\n\t"
  22573. "\n"
  22574. "L_sp_4096_sqr_128_inner:\n\t"
  22575. "LDR lr, [%[a], r3]\n\t"
  22576. "LDR r11, [%[a], r4]\n\t"
  22577. "UMULL r9, r10, lr, r11\n\t"
  22578. "ADDS r6, r6, r9\n\t"
  22579. "ADCS r7, r7, r10\n\t"
  22580. "ADC r8, r8, #0x0\n\t"
  22581. "ADDS r6, r6, r9\n\t"
  22582. "ADCS r7, r7, r10\n\t"
  22583. "ADC r8, r8, #0x0\n\t"
  22584. "ADD r3, r3, #0x4\n\t"
  22585. "SUB r4, r4, #0x4\n\t"
  22586. "CMP r3, r4\n\t"
  22587. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22588. "BGT L_sp_4096_sqr_128_inner_done\n\t"
  22589. #else
  22590. "BGT.N L_sp_4096_sqr_128_inner_done\n\t"
  22591. #endif
  22592. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22593. "BLT L_sp_4096_sqr_128_inner\n\t"
  22594. #else
  22595. "BLT.N L_sp_4096_sqr_128_inner\n\t"
  22596. #endif
  22597. "LDR lr, [%[a], r3]\n\t"
  22598. "UMULL r9, r10, lr, lr\n\t"
  22599. "ADDS r6, r6, r9\n\t"
  22600. "ADCS r7, r7, r10\n\t"
  22601. "ADC r8, r8, #0x0\n\t"
  22602. "\n"
  22603. "L_sp_4096_sqr_128_inner_done:\n\t"
  22604. "STR r6, [sp, r5]\n\t"
  22605. "MOV r6, r7\n\t"
  22606. "MOV r7, r8\n\t"
  22607. "MOV r8, #0x0\n\t"
  22608. "ADD r5, r5, #0x4\n\t"
  22609. "CMP r5, #0x3f4\n\t"
  22610. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22611. "BLE L_sp_4096_sqr_128_outer\n\t"
  22612. #else
  22613. "BLE.N L_sp_4096_sqr_128_outer\n\t"
  22614. #endif
  22615. "LDR lr, [%[a], #508]\n\t"
  22616. "UMLAL r6, r7, lr, lr\n\t"
  22617. "STR r6, [sp, r5]\n\t"
  22618. "ADD r5, r5, #0x4\n\t"
  22619. "STR r7, [sp, r5]\n\t"
  22620. "\n"
  22621. "L_sp_4096_sqr_128_store:\n\t"
  22622. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  22623. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  22624. "SUBS r5, r5, #0x20\n\t"
  22625. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22626. "BGT L_sp_4096_sqr_128_store\n\t"
  22627. #else
  22628. "BGT.N L_sp_4096_sqr_128_store\n\t"
  22629. #endif
  22630. : [r] "+r" (r), [a] "+r" (a)
  22631. :
  22632. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  22633. );
  22634. }
  22635. #endif /* WOLFSSL_SP_SMALL */
  22636. /* Calculate the bottom digit of -1/a mod 2^n.
  22637. *
  22638. * a A single precision number.
  22639. * rho Bottom word of inverse.
  22640. */
  22641. static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
  22642. {
  22643. sp_digit x;
  22644. sp_digit b;
  22645. b = a[0];
  22646. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  22647. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  22648. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  22649. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  22650. /* rho = -1/m mod b */
  22651. *rho = (sp_digit)0 - x;
  22652. }
  22653. #ifdef WOLFSSL_SP_SMALL
  22654. /* Mul a by digit b into r. (r = a * b)
  22655. *
  22656. * r A single precision integer.
  22657. * a A single precision integer.
  22658. * b A single precision digit.
  22659. */
  22660. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22661. static void sp_4096_mul_d_128(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  22662. #else
  22663. static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a, sp_digit b)
  22664. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22665. {
  22666. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22667. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  22668. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  22669. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  22670. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22671. __asm__ __volatile__ (
  22672. /* A[0] * B */
  22673. "LDR r8, [%[a]]\n\t"
  22674. "UMULL r5, r3, %[b], r8\n\t"
  22675. "MOV r4, #0x0\n\t"
  22676. "STR r5, [%[r]]\n\t"
  22677. "MOV r5, #0x0\n\t"
  22678. "MOV r9, #0x4\n\t"
  22679. "\n"
  22680. "L_sp_4096_mul_d_128_word:\n\t"
  22681. /* A[i] * B */
  22682. "LDR r8, [%[a], r9]\n\t"
  22683. "UMULL r6, r7, %[b], r8\n\t"
  22684. "ADDS r3, r3, r6\n\t"
  22685. "ADCS r4, r4, r7\n\t"
  22686. "ADC r5, r5, #0x0\n\t"
  22687. "STR r3, [%[r], r9]\n\t"
  22688. "MOV r3, r4\n\t"
  22689. "MOV r4, r5\n\t"
  22690. "MOV r5, #0x0\n\t"
  22691. "ADD r9, r9, #0x4\n\t"
  22692. "CMP r9, #0x200\n\t"
  22693. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  22694. "BLT L_sp_4096_mul_d_128_word\n\t"
  22695. #else
  22696. "BLT.N L_sp_4096_mul_d_128_word\n\t"
  22697. #endif
  22698. "STR r3, [%[r], #512]\n\t"
  22699. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  22700. :
  22701. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  22702. );
  22703. }
  22704. #else
  22705. /* Mul a by digit b into r. (r = a * b)
  22706. *
  22707. * r A single precision integer.
  22708. * a A single precision integer.
  22709. * b A single precision digit.
  22710. */
  22711. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22712. static void sp_4096_mul_d_128(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  22713. #else
  22714. static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a, sp_digit b)
  22715. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22716. {
  22717. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  22718. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  22719. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  22720. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  22721. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  22722. __asm__ __volatile__ (
  22723. /* A[0] * B */
  22724. "LDM %[a]!, {r8}\n\t"
  22725. "UMULL r3, r4, %[b], r8\n\t"
  22726. "STM %[r]!, {r3}\n\t"
  22727. "MOV r5, #0x0\n\t"
  22728. /* A[1] * B */
  22729. "LDM %[a]!, {r8}\n\t"
  22730. "UMLAL r4, r5, %[b], r8\n\t"
  22731. "STM %[r]!, {r4}\n\t"
  22732. "MOV r3, #0x0\n\t"
  22733. /* A[2] * B */
  22734. "LDM %[a]!, {r8}\n\t"
  22735. "UMLAL r5, r3, %[b], r8\n\t"
  22736. "STM %[r]!, {r5}\n\t"
  22737. "MOV r4, #0x0\n\t"
  22738. /* A[3] * B */
  22739. "LDM %[a]!, {r8}\n\t"
  22740. "UMLAL r3, r4, %[b], r8\n\t"
  22741. "STM %[r]!, {r3}\n\t"
  22742. "MOV r5, #0x0\n\t"
  22743. /* A[4] * B */
  22744. "LDM %[a]!, {r8}\n\t"
  22745. "UMLAL r4, r5, %[b], r8\n\t"
  22746. "STM %[r]!, {r4}\n\t"
  22747. "MOV r3, #0x0\n\t"
  22748. /* A[5] * B */
  22749. "LDM %[a]!, {r8}\n\t"
  22750. "UMLAL r5, r3, %[b], r8\n\t"
  22751. "STM %[r]!, {r5}\n\t"
  22752. "MOV r4, #0x0\n\t"
  22753. /* A[6] * B */
  22754. "LDM %[a]!, {r8}\n\t"
  22755. "UMLAL r3, r4, %[b], r8\n\t"
  22756. "STM %[r]!, {r3}\n\t"
  22757. "MOV r5, #0x0\n\t"
  22758. /* A[7] * B */
  22759. "LDM %[a]!, {r8}\n\t"
  22760. "UMLAL r4, r5, %[b], r8\n\t"
  22761. "STM %[r]!, {r4}\n\t"
  22762. "MOV r3, #0x0\n\t"
  22763. /* A[8] * B */
  22764. "LDM %[a]!, {r8}\n\t"
  22765. "UMLAL r5, r3, %[b], r8\n\t"
  22766. "STM %[r]!, {r5}\n\t"
  22767. "MOV r4, #0x0\n\t"
  22768. /* A[9] * B */
  22769. "LDM %[a]!, {r8}\n\t"
  22770. "UMLAL r3, r4, %[b], r8\n\t"
  22771. "STM %[r]!, {r3}\n\t"
  22772. "MOV r5, #0x0\n\t"
  22773. /* A[10] * B */
  22774. "LDM %[a]!, {r8}\n\t"
  22775. "UMLAL r4, r5, %[b], r8\n\t"
  22776. "STM %[r]!, {r4}\n\t"
  22777. "MOV r3, #0x0\n\t"
  22778. /* A[11] * B */
  22779. "LDM %[a]!, {r8}\n\t"
  22780. "UMLAL r5, r3, %[b], r8\n\t"
  22781. "STM %[r]!, {r5}\n\t"
  22782. "MOV r4, #0x0\n\t"
  22783. /* A[12] * B */
  22784. "LDM %[a]!, {r8}\n\t"
  22785. "UMLAL r3, r4, %[b], r8\n\t"
  22786. "STM %[r]!, {r3}\n\t"
  22787. "MOV r5, #0x0\n\t"
  22788. /* A[13] * B */
  22789. "LDM %[a]!, {r8}\n\t"
  22790. "UMLAL r4, r5, %[b], r8\n\t"
  22791. "STM %[r]!, {r4}\n\t"
  22792. "MOV r3, #0x0\n\t"
  22793. /* A[14] * B */
  22794. "LDM %[a]!, {r8}\n\t"
  22795. "UMLAL r5, r3, %[b], r8\n\t"
  22796. "STM %[r]!, {r5}\n\t"
  22797. "MOV r4, #0x0\n\t"
  22798. /* A[15] * B */
  22799. "LDM %[a]!, {r8}\n\t"
  22800. "UMLAL r3, r4, %[b], r8\n\t"
  22801. "STM %[r]!, {r3}\n\t"
  22802. "MOV r5, #0x0\n\t"
  22803. /* A[16] * B */
  22804. "LDM %[a]!, {r8}\n\t"
  22805. "UMLAL r4, r5, %[b], r8\n\t"
  22806. "STM %[r]!, {r4}\n\t"
  22807. "MOV r3, #0x0\n\t"
  22808. /* A[17] * B */
  22809. "LDM %[a]!, {r8}\n\t"
  22810. "UMLAL r5, r3, %[b], r8\n\t"
  22811. "STM %[r]!, {r5}\n\t"
  22812. "MOV r4, #0x0\n\t"
  22813. /* A[18] * B */
  22814. "LDM %[a]!, {r8}\n\t"
  22815. "UMLAL r3, r4, %[b], r8\n\t"
  22816. "STM %[r]!, {r3}\n\t"
  22817. "MOV r5, #0x0\n\t"
  22818. /* A[19] * B */
  22819. "LDM %[a]!, {r8}\n\t"
  22820. "UMLAL r4, r5, %[b], r8\n\t"
  22821. "STM %[r]!, {r4}\n\t"
  22822. "MOV r3, #0x0\n\t"
  22823. /* A[20] * B */
  22824. "LDM %[a]!, {r8}\n\t"
  22825. "UMLAL r5, r3, %[b], r8\n\t"
  22826. "STM %[r]!, {r5}\n\t"
  22827. "MOV r4, #0x0\n\t"
  22828. /* A[21] * B */
  22829. "LDM %[a]!, {r8}\n\t"
  22830. "UMLAL r3, r4, %[b], r8\n\t"
  22831. "STM %[r]!, {r3}\n\t"
  22832. "MOV r5, #0x0\n\t"
  22833. /* A[22] * B */
  22834. "LDM %[a]!, {r8}\n\t"
  22835. "UMLAL r4, r5, %[b], r8\n\t"
  22836. "STM %[r]!, {r4}\n\t"
  22837. "MOV r3, #0x0\n\t"
  22838. /* A[23] * B */
  22839. "LDM %[a]!, {r8}\n\t"
  22840. "UMLAL r5, r3, %[b], r8\n\t"
  22841. "STM %[r]!, {r5}\n\t"
  22842. "MOV r4, #0x0\n\t"
  22843. /* A[24] * B */
  22844. "LDM %[a]!, {r8}\n\t"
  22845. "UMLAL r3, r4, %[b], r8\n\t"
  22846. "STM %[r]!, {r3}\n\t"
  22847. "MOV r5, #0x0\n\t"
  22848. /* A[25] * B */
  22849. "LDM %[a]!, {r8}\n\t"
  22850. "UMLAL r4, r5, %[b], r8\n\t"
  22851. "STM %[r]!, {r4}\n\t"
  22852. "MOV r3, #0x0\n\t"
  22853. /* A[26] * B */
  22854. "LDM %[a]!, {r8}\n\t"
  22855. "UMLAL r5, r3, %[b], r8\n\t"
  22856. "STM %[r]!, {r5}\n\t"
  22857. "MOV r4, #0x0\n\t"
  22858. /* A[27] * B */
  22859. "LDM %[a]!, {r8}\n\t"
  22860. "UMLAL r3, r4, %[b], r8\n\t"
  22861. "STM %[r]!, {r3}\n\t"
  22862. "MOV r5, #0x0\n\t"
  22863. /* A[28] * B */
  22864. "LDM %[a]!, {r8}\n\t"
  22865. "UMLAL r4, r5, %[b], r8\n\t"
  22866. "STM %[r]!, {r4}\n\t"
  22867. "MOV r3, #0x0\n\t"
  22868. /* A[29] * B */
  22869. "LDM %[a]!, {r8}\n\t"
  22870. "UMLAL r5, r3, %[b], r8\n\t"
  22871. "STM %[r]!, {r5}\n\t"
  22872. "MOV r4, #0x0\n\t"
  22873. /* A[30] * B */
  22874. "LDM %[a]!, {r8}\n\t"
  22875. "UMLAL r3, r4, %[b], r8\n\t"
  22876. "STM %[r]!, {r3}\n\t"
  22877. "MOV r5, #0x0\n\t"
  22878. /* A[31] * B */
  22879. "LDM %[a]!, {r8}\n\t"
  22880. "UMLAL r4, r5, %[b], r8\n\t"
  22881. "STM %[r]!, {r4}\n\t"
  22882. "MOV r3, #0x0\n\t"
  22883. /* A[32] * B */
  22884. "LDM %[a]!, {r8}\n\t"
  22885. "UMLAL r5, r3, %[b], r8\n\t"
  22886. "STM %[r]!, {r5}\n\t"
  22887. "MOV r4, #0x0\n\t"
  22888. /* A[33] * B */
  22889. "LDM %[a]!, {r8}\n\t"
  22890. "UMLAL r3, r4, %[b], r8\n\t"
  22891. "STM %[r]!, {r3}\n\t"
  22892. "MOV r5, #0x0\n\t"
  22893. /* A[34] * B */
  22894. "LDM %[a]!, {r8}\n\t"
  22895. "UMLAL r4, r5, %[b], r8\n\t"
  22896. "STM %[r]!, {r4}\n\t"
  22897. "MOV r3, #0x0\n\t"
  22898. /* A[35] * B */
  22899. "LDM %[a]!, {r8}\n\t"
  22900. "UMLAL r5, r3, %[b], r8\n\t"
  22901. "STM %[r]!, {r5}\n\t"
  22902. "MOV r4, #0x0\n\t"
  22903. /* A[36] * B */
  22904. "LDM %[a]!, {r8}\n\t"
  22905. "UMLAL r3, r4, %[b], r8\n\t"
  22906. "STM %[r]!, {r3}\n\t"
  22907. "MOV r5, #0x0\n\t"
  22908. /* A[37] * B */
  22909. "LDM %[a]!, {r8}\n\t"
  22910. "UMLAL r4, r5, %[b], r8\n\t"
  22911. "STM %[r]!, {r4}\n\t"
  22912. "MOV r3, #0x0\n\t"
  22913. /* A[38] * B */
  22914. "LDM %[a]!, {r8}\n\t"
  22915. "UMLAL r5, r3, %[b], r8\n\t"
  22916. "STM %[r]!, {r5}\n\t"
  22917. "MOV r4, #0x0\n\t"
  22918. /* A[39] * B */
  22919. "LDM %[a]!, {r8}\n\t"
  22920. "UMLAL r3, r4, %[b], r8\n\t"
  22921. "STM %[r]!, {r3}\n\t"
  22922. "MOV r5, #0x0\n\t"
  22923. /* A[40] * B */
  22924. "LDM %[a]!, {r8}\n\t"
  22925. "UMLAL r4, r5, %[b], r8\n\t"
  22926. "STM %[r]!, {r4}\n\t"
  22927. "MOV r3, #0x0\n\t"
  22928. /* A[41] * B */
  22929. "LDM %[a]!, {r8}\n\t"
  22930. "UMLAL r5, r3, %[b], r8\n\t"
  22931. "STM %[r]!, {r5}\n\t"
  22932. "MOV r4, #0x0\n\t"
  22933. /* A[42] * B */
  22934. "LDM %[a]!, {r8}\n\t"
  22935. "UMLAL r3, r4, %[b], r8\n\t"
  22936. "STM %[r]!, {r3}\n\t"
  22937. "MOV r5, #0x0\n\t"
  22938. /* A[43] * B */
  22939. "LDM %[a]!, {r8}\n\t"
  22940. "UMLAL r4, r5, %[b], r8\n\t"
  22941. "STM %[r]!, {r4}\n\t"
  22942. "MOV r3, #0x0\n\t"
  22943. /* A[44] * B */
  22944. "LDM %[a]!, {r8}\n\t"
  22945. "UMLAL r5, r3, %[b], r8\n\t"
  22946. "STM %[r]!, {r5}\n\t"
  22947. "MOV r4, #0x0\n\t"
  22948. /* A[45] * B */
  22949. "LDM %[a]!, {r8}\n\t"
  22950. "UMLAL r3, r4, %[b], r8\n\t"
  22951. "STM %[r]!, {r3}\n\t"
  22952. "MOV r5, #0x0\n\t"
  22953. /* A[46] * B */
  22954. "LDM %[a]!, {r8}\n\t"
  22955. "UMLAL r4, r5, %[b], r8\n\t"
  22956. "STM %[r]!, {r4}\n\t"
  22957. "MOV r3, #0x0\n\t"
  22958. /* A[47] * B */
  22959. "LDM %[a]!, {r8}\n\t"
  22960. "UMLAL r5, r3, %[b], r8\n\t"
  22961. "STM %[r]!, {r5}\n\t"
  22962. "MOV r4, #0x0\n\t"
  22963. /* A[48] * B */
  22964. "LDM %[a]!, {r8}\n\t"
  22965. "UMLAL r3, r4, %[b], r8\n\t"
  22966. "STM %[r]!, {r3}\n\t"
  22967. "MOV r5, #0x0\n\t"
  22968. /* A[49] * B */
  22969. "LDM %[a]!, {r8}\n\t"
  22970. "UMLAL r4, r5, %[b], r8\n\t"
  22971. "STM %[r]!, {r4}\n\t"
  22972. "MOV r3, #0x0\n\t"
  22973. /* A[50] * B */
  22974. "LDM %[a]!, {r8}\n\t"
  22975. "UMLAL r5, r3, %[b], r8\n\t"
  22976. "STM %[r]!, {r5}\n\t"
  22977. "MOV r4, #0x0\n\t"
  22978. /* A[51] * B */
  22979. "LDM %[a]!, {r8}\n\t"
  22980. "UMLAL r3, r4, %[b], r8\n\t"
  22981. "STM %[r]!, {r3}\n\t"
  22982. "MOV r5, #0x0\n\t"
  22983. /* A[52] * B */
  22984. "LDM %[a]!, {r8}\n\t"
  22985. "UMLAL r4, r5, %[b], r8\n\t"
  22986. "STM %[r]!, {r4}\n\t"
  22987. "MOV r3, #0x0\n\t"
  22988. /* A[53] * B */
  22989. "LDM %[a]!, {r8}\n\t"
  22990. "UMLAL r5, r3, %[b], r8\n\t"
  22991. "STM %[r]!, {r5}\n\t"
  22992. "MOV r4, #0x0\n\t"
  22993. /* A[54] * B */
  22994. "LDM %[a]!, {r8}\n\t"
  22995. "UMLAL r3, r4, %[b], r8\n\t"
  22996. "STM %[r]!, {r3}\n\t"
  22997. "MOV r5, #0x0\n\t"
  22998. /* A[55] * B */
  22999. "LDM %[a]!, {r8}\n\t"
  23000. "UMLAL r4, r5, %[b], r8\n\t"
  23001. "STM %[r]!, {r4}\n\t"
  23002. "MOV r3, #0x0\n\t"
  23003. /* A[56] * B */
  23004. "LDM %[a]!, {r8}\n\t"
  23005. "UMLAL r5, r3, %[b], r8\n\t"
  23006. "STM %[r]!, {r5}\n\t"
  23007. "MOV r4, #0x0\n\t"
  23008. /* A[57] * B */
  23009. "LDM %[a]!, {r8}\n\t"
  23010. "UMLAL r3, r4, %[b], r8\n\t"
  23011. "STM %[r]!, {r3}\n\t"
  23012. "MOV r5, #0x0\n\t"
  23013. /* A[58] * B */
  23014. "LDM %[a]!, {r8}\n\t"
  23015. "UMLAL r4, r5, %[b], r8\n\t"
  23016. "STM %[r]!, {r4}\n\t"
  23017. "MOV r3, #0x0\n\t"
  23018. /* A[59] * B */
  23019. "LDM %[a]!, {r8}\n\t"
  23020. "UMLAL r5, r3, %[b], r8\n\t"
  23021. "STM %[r]!, {r5}\n\t"
  23022. "MOV r4, #0x0\n\t"
  23023. /* A[60] * B */
  23024. "LDM %[a]!, {r8}\n\t"
  23025. "UMLAL r3, r4, %[b], r8\n\t"
  23026. "STM %[r]!, {r3}\n\t"
  23027. "MOV r5, #0x0\n\t"
  23028. /* A[61] * B */
  23029. "LDM %[a]!, {r8}\n\t"
  23030. "UMLAL r4, r5, %[b], r8\n\t"
  23031. "STM %[r]!, {r4}\n\t"
  23032. "MOV r3, #0x0\n\t"
  23033. /* A[62] * B */
  23034. "LDM %[a]!, {r8}\n\t"
  23035. "UMLAL r5, r3, %[b], r8\n\t"
  23036. "STM %[r]!, {r5}\n\t"
  23037. "MOV r4, #0x0\n\t"
  23038. /* A[63] * B */
  23039. "LDM %[a]!, {r8}\n\t"
  23040. "UMLAL r3, r4, %[b], r8\n\t"
  23041. "STM %[r]!, {r3}\n\t"
  23042. "MOV r5, #0x0\n\t"
  23043. /* A[64] * B */
  23044. "LDM %[a]!, {r8}\n\t"
  23045. "UMLAL r4, r5, %[b], r8\n\t"
  23046. "STM %[r]!, {r4}\n\t"
  23047. "MOV r3, #0x0\n\t"
  23048. /* A[65] * B */
  23049. "LDM %[a]!, {r8}\n\t"
  23050. "UMLAL r5, r3, %[b], r8\n\t"
  23051. "STM %[r]!, {r5}\n\t"
  23052. "MOV r4, #0x0\n\t"
  23053. /* A[66] * B */
  23054. "LDM %[a]!, {r8}\n\t"
  23055. "UMLAL r3, r4, %[b], r8\n\t"
  23056. "STM %[r]!, {r3}\n\t"
  23057. "MOV r5, #0x0\n\t"
  23058. /* A[67] * B */
  23059. "LDM %[a]!, {r8}\n\t"
  23060. "UMLAL r4, r5, %[b], r8\n\t"
  23061. "STM %[r]!, {r4}\n\t"
  23062. "MOV r3, #0x0\n\t"
  23063. /* A[68] * B */
  23064. "LDM %[a]!, {r8}\n\t"
  23065. "UMLAL r5, r3, %[b], r8\n\t"
  23066. "STM %[r]!, {r5}\n\t"
  23067. "MOV r4, #0x0\n\t"
  23068. /* A[69] * B */
  23069. "LDM %[a]!, {r8}\n\t"
  23070. "UMLAL r3, r4, %[b], r8\n\t"
  23071. "STM %[r]!, {r3}\n\t"
  23072. "MOV r5, #0x0\n\t"
  23073. /* A[70] * B */
  23074. "LDM %[a]!, {r8}\n\t"
  23075. "UMLAL r4, r5, %[b], r8\n\t"
  23076. "STM %[r]!, {r4}\n\t"
  23077. "MOV r3, #0x0\n\t"
  23078. /* A[71] * B */
  23079. "LDM %[a]!, {r8}\n\t"
  23080. "UMLAL r5, r3, %[b], r8\n\t"
  23081. "STM %[r]!, {r5}\n\t"
  23082. "MOV r4, #0x0\n\t"
  23083. /* A[72] * B */
  23084. "LDM %[a]!, {r8}\n\t"
  23085. "UMLAL r3, r4, %[b], r8\n\t"
  23086. "STM %[r]!, {r3}\n\t"
  23087. "MOV r5, #0x0\n\t"
  23088. /* A[73] * B */
  23089. "LDM %[a]!, {r8}\n\t"
  23090. "UMLAL r4, r5, %[b], r8\n\t"
  23091. "STM %[r]!, {r4}\n\t"
  23092. "MOV r3, #0x0\n\t"
  23093. /* A[74] * B */
  23094. "LDM %[a]!, {r8}\n\t"
  23095. "UMLAL r5, r3, %[b], r8\n\t"
  23096. "STM %[r]!, {r5}\n\t"
  23097. "MOV r4, #0x0\n\t"
  23098. /* A[75] * B */
  23099. "LDM %[a]!, {r8}\n\t"
  23100. "UMLAL r3, r4, %[b], r8\n\t"
  23101. "STM %[r]!, {r3}\n\t"
  23102. "MOV r5, #0x0\n\t"
  23103. /* A[76] * B */
  23104. "LDM %[a]!, {r8}\n\t"
  23105. "UMLAL r4, r5, %[b], r8\n\t"
  23106. "STM %[r]!, {r4}\n\t"
  23107. "MOV r3, #0x0\n\t"
  23108. /* A[77] * B */
  23109. "LDM %[a]!, {r8}\n\t"
  23110. "UMLAL r5, r3, %[b], r8\n\t"
  23111. "STM %[r]!, {r5}\n\t"
  23112. "MOV r4, #0x0\n\t"
  23113. /* A[78] * B */
  23114. "LDM %[a]!, {r8}\n\t"
  23115. "UMLAL r3, r4, %[b], r8\n\t"
  23116. "STM %[r]!, {r3}\n\t"
  23117. "MOV r5, #0x0\n\t"
  23118. /* A[79] * B */
  23119. "LDM %[a]!, {r8}\n\t"
  23120. "UMLAL r4, r5, %[b], r8\n\t"
  23121. "STM %[r]!, {r4}\n\t"
  23122. "MOV r3, #0x0\n\t"
  23123. /* A[80] * B */
  23124. "LDM %[a]!, {r8}\n\t"
  23125. "UMLAL r5, r3, %[b], r8\n\t"
  23126. "STM %[r]!, {r5}\n\t"
  23127. "MOV r4, #0x0\n\t"
  23128. /* A[81] * B */
  23129. "LDM %[a]!, {r8}\n\t"
  23130. "UMLAL r3, r4, %[b], r8\n\t"
  23131. "STM %[r]!, {r3}\n\t"
  23132. "MOV r5, #0x0\n\t"
  23133. /* A[82] * B */
  23134. "LDM %[a]!, {r8}\n\t"
  23135. "UMLAL r4, r5, %[b], r8\n\t"
  23136. "STM %[r]!, {r4}\n\t"
  23137. "MOV r3, #0x0\n\t"
  23138. /* A[83] * B */
  23139. "LDM %[a]!, {r8}\n\t"
  23140. "UMLAL r5, r3, %[b], r8\n\t"
  23141. "STM %[r]!, {r5}\n\t"
  23142. "MOV r4, #0x0\n\t"
  23143. /* A[84] * B */
  23144. "LDM %[a]!, {r8}\n\t"
  23145. "UMLAL r3, r4, %[b], r8\n\t"
  23146. "STM %[r]!, {r3}\n\t"
  23147. "MOV r5, #0x0\n\t"
  23148. /* A[85] * B */
  23149. "LDM %[a]!, {r8}\n\t"
  23150. "UMLAL r4, r5, %[b], r8\n\t"
  23151. "STM %[r]!, {r4}\n\t"
  23152. "MOV r3, #0x0\n\t"
  23153. /* A[86] * B */
  23154. "LDM %[a]!, {r8}\n\t"
  23155. "UMLAL r5, r3, %[b], r8\n\t"
  23156. "STM %[r]!, {r5}\n\t"
  23157. "MOV r4, #0x0\n\t"
  23158. /* A[87] * B */
  23159. "LDM %[a]!, {r8}\n\t"
  23160. "UMLAL r3, r4, %[b], r8\n\t"
  23161. "STM %[r]!, {r3}\n\t"
  23162. "MOV r5, #0x0\n\t"
  23163. /* A[88] * B */
  23164. "LDM %[a]!, {r8}\n\t"
  23165. "UMLAL r4, r5, %[b], r8\n\t"
  23166. "STM %[r]!, {r4}\n\t"
  23167. "MOV r3, #0x0\n\t"
  23168. /* A[89] * B */
  23169. "LDM %[a]!, {r8}\n\t"
  23170. "UMLAL r5, r3, %[b], r8\n\t"
  23171. "STM %[r]!, {r5}\n\t"
  23172. "MOV r4, #0x0\n\t"
  23173. /* A[90] * B */
  23174. "LDM %[a]!, {r8}\n\t"
  23175. "UMLAL r3, r4, %[b], r8\n\t"
  23176. "STM %[r]!, {r3}\n\t"
  23177. "MOV r5, #0x0\n\t"
  23178. /* A[91] * B */
  23179. "LDM %[a]!, {r8}\n\t"
  23180. "UMLAL r4, r5, %[b], r8\n\t"
  23181. "STM %[r]!, {r4}\n\t"
  23182. "MOV r3, #0x0\n\t"
  23183. /* A[92] * B */
  23184. "LDM %[a]!, {r8}\n\t"
  23185. "UMLAL r5, r3, %[b], r8\n\t"
  23186. "STM %[r]!, {r5}\n\t"
  23187. "MOV r4, #0x0\n\t"
  23188. /* A[93] * B */
  23189. "LDM %[a]!, {r8}\n\t"
  23190. "UMLAL r3, r4, %[b], r8\n\t"
  23191. "STM %[r]!, {r3}\n\t"
  23192. "MOV r5, #0x0\n\t"
  23193. /* A[94] * B */
  23194. "LDM %[a]!, {r8}\n\t"
  23195. "UMLAL r4, r5, %[b], r8\n\t"
  23196. "STM %[r]!, {r4}\n\t"
  23197. "MOV r3, #0x0\n\t"
  23198. /* A[95] * B */
  23199. "LDM %[a]!, {r8}\n\t"
  23200. "UMLAL r5, r3, %[b], r8\n\t"
  23201. "STM %[r]!, {r5}\n\t"
  23202. "MOV r4, #0x0\n\t"
  23203. /* A[96] * B */
  23204. "LDM %[a]!, {r8}\n\t"
  23205. "UMLAL r3, r4, %[b], r8\n\t"
  23206. "STM %[r]!, {r3}\n\t"
  23207. "MOV r5, #0x0\n\t"
  23208. /* A[97] * B */
  23209. "LDM %[a]!, {r8}\n\t"
  23210. "UMLAL r4, r5, %[b], r8\n\t"
  23211. "STM %[r]!, {r4}\n\t"
  23212. "MOV r3, #0x0\n\t"
  23213. /* A[98] * B */
  23214. "LDM %[a]!, {r8}\n\t"
  23215. "UMLAL r5, r3, %[b], r8\n\t"
  23216. "STM %[r]!, {r5}\n\t"
  23217. "MOV r4, #0x0\n\t"
  23218. /* A[99] * B */
  23219. "LDM %[a]!, {r8}\n\t"
  23220. "UMLAL r3, r4, %[b], r8\n\t"
  23221. "STM %[r]!, {r3}\n\t"
  23222. "MOV r5, #0x0\n\t"
  23223. /* A[100] * B */
  23224. "LDM %[a]!, {r8}\n\t"
  23225. "UMLAL r4, r5, %[b], r8\n\t"
  23226. "STM %[r]!, {r4}\n\t"
  23227. "MOV r3, #0x0\n\t"
  23228. /* A[101] * B */
  23229. "LDM %[a]!, {r8}\n\t"
  23230. "UMLAL r5, r3, %[b], r8\n\t"
  23231. "STM %[r]!, {r5}\n\t"
  23232. "MOV r4, #0x0\n\t"
  23233. /* A[102] * B */
  23234. "LDM %[a]!, {r8}\n\t"
  23235. "UMLAL r3, r4, %[b], r8\n\t"
  23236. "STM %[r]!, {r3}\n\t"
  23237. "MOV r5, #0x0\n\t"
  23238. /* A[103] * B */
  23239. "LDM %[a]!, {r8}\n\t"
  23240. "UMLAL r4, r5, %[b], r8\n\t"
  23241. "STM %[r]!, {r4}\n\t"
  23242. "MOV r3, #0x0\n\t"
  23243. /* A[104] * B */
  23244. "LDM %[a]!, {r8}\n\t"
  23245. "UMLAL r5, r3, %[b], r8\n\t"
  23246. "STM %[r]!, {r5}\n\t"
  23247. "MOV r4, #0x0\n\t"
  23248. /* A[105] * B */
  23249. "LDM %[a]!, {r8}\n\t"
  23250. "UMLAL r3, r4, %[b], r8\n\t"
  23251. "STM %[r]!, {r3}\n\t"
  23252. "MOV r5, #0x0\n\t"
  23253. /* A[106] * B */
  23254. "LDM %[a]!, {r8}\n\t"
  23255. "UMLAL r4, r5, %[b], r8\n\t"
  23256. "STM %[r]!, {r4}\n\t"
  23257. "MOV r3, #0x0\n\t"
  23258. /* A[107] * B */
  23259. "LDM %[a]!, {r8}\n\t"
  23260. "UMLAL r5, r3, %[b], r8\n\t"
  23261. "STM %[r]!, {r5}\n\t"
  23262. "MOV r4, #0x0\n\t"
  23263. /* A[108] * B */
  23264. "LDM %[a]!, {r8}\n\t"
  23265. "UMLAL r3, r4, %[b], r8\n\t"
  23266. "STM %[r]!, {r3}\n\t"
  23267. "MOV r5, #0x0\n\t"
  23268. /* A[109] * B */
  23269. "LDM %[a]!, {r8}\n\t"
  23270. "UMLAL r4, r5, %[b], r8\n\t"
  23271. "STM %[r]!, {r4}\n\t"
  23272. "MOV r3, #0x0\n\t"
  23273. /* A[110] * B */
  23274. "LDM %[a]!, {r8}\n\t"
  23275. "UMLAL r5, r3, %[b], r8\n\t"
  23276. "STM %[r]!, {r5}\n\t"
  23277. "MOV r4, #0x0\n\t"
  23278. /* A[111] * B */
  23279. "LDM %[a]!, {r8}\n\t"
  23280. "UMLAL r3, r4, %[b], r8\n\t"
  23281. "STM %[r]!, {r3}\n\t"
  23282. "MOV r5, #0x0\n\t"
  23283. /* A[112] * B */
  23284. "LDM %[a]!, {r8}\n\t"
  23285. "UMLAL r4, r5, %[b], r8\n\t"
  23286. "STM %[r]!, {r4}\n\t"
  23287. "MOV r3, #0x0\n\t"
  23288. /* A[113] * B */
  23289. "LDM %[a]!, {r8}\n\t"
  23290. "UMLAL r5, r3, %[b], r8\n\t"
  23291. "STM %[r]!, {r5}\n\t"
  23292. "MOV r4, #0x0\n\t"
  23293. /* A[114] * B */
  23294. "LDM %[a]!, {r8}\n\t"
  23295. "UMLAL r3, r4, %[b], r8\n\t"
  23296. "STM %[r]!, {r3}\n\t"
  23297. "MOV r5, #0x0\n\t"
  23298. /* A[115] * B */
  23299. "LDM %[a]!, {r8}\n\t"
  23300. "UMLAL r4, r5, %[b], r8\n\t"
  23301. "STM %[r]!, {r4}\n\t"
  23302. "MOV r3, #0x0\n\t"
  23303. /* A[116] * B */
  23304. "LDM %[a]!, {r8}\n\t"
  23305. "UMLAL r5, r3, %[b], r8\n\t"
  23306. "STM %[r]!, {r5}\n\t"
  23307. "MOV r4, #0x0\n\t"
  23308. /* A[117] * B */
  23309. "LDM %[a]!, {r8}\n\t"
  23310. "UMLAL r3, r4, %[b], r8\n\t"
  23311. "STM %[r]!, {r3}\n\t"
  23312. "MOV r5, #0x0\n\t"
  23313. /* A[118] * B */
  23314. "LDM %[a]!, {r8}\n\t"
  23315. "UMLAL r4, r5, %[b], r8\n\t"
  23316. "STM %[r]!, {r4}\n\t"
  23317. "MOV r3, #0x0\n\t"
  23318. /* A[119] * B */
  23319. "LDM %[a]!, {r8}\n\t"
  23320. "UMLAL r5, r3, %[b], r8\n\t"
  23321. "STM %[r]!, {r5}\n\t"
  23322. "MOV r4, #0x0\n\t"
  23323. /* A[120] * B */
  23324. "LDM %[a]!, {r8}\n\t"
  23325. "UMLAL r3, r4, %[b], r8\n\t"
  23326. "STM %[r]!, {r3}\n\t"
  23327. "MOV r5, #0x0\n\t"
  23328. /* A[121] * B */
  23329. "LDM %[a]!, {r8}\n\t"
  23330. "UMLAL r4, r5, %[b], r8\n\t"
  23331. "STM %[r]!, {r4}\n\t"
  23332. "MOV r3, #0x0\n\t"
  23333. /* A[122] * B */
  23334. "LDM %[a]!, {r8}\n\t"
  23335. "UMLAL r5, r3, %[b], r8\n\t"
  23336. "STM %[r]!, {r5}\n\t"
  23337. "MOV r4, #0x0\n\t"
  23338. /* A[123] * B */
  23339. "LDM %[a]!, {r8}\n\t"
  23340. "UMLAL r3, r4, %[b], r8\n\t"
  23341. "STM %[r]!, {r3}\n\t"
  23342. "MOV r5, #0x0\n\t"
  23343. /* A[124] * B */
  23344. "LDM %[a]!, {r8}\n\t"
  23345. "UMLAL r4, r5, %[b], r8\n\t"
  23346. "STM %[r]!, {r4}\n\t"
  23347. "MOV r3, #0x0\n\t"
  23348. /* A[125] * B */
  23349. "LDM %[a]!, {r8}\n\t"
  23350. "UMLAL r5, r3, %[b], r8\n\t"
  23351. "STM %[r]!, {r5}\n\t"
  23352. "MOV r4, #0x0\n\t"
  23353. /* A[126] * B */
  23354. "LDM %[a]!, {r8}\n\t"
  23355. "UMLAL r3, r4, %[b], r8\n\t"
  23356. "STM %[r]!, {r3}\n\t"
  23357. "MOV r5, #0x0\n\t"
  23358. /* A[127] * B */
  23359. "LDM %[a]!, {r8}\n\t"
  23360. "UMLAL r4, r5, %[b], r8\n\t"
  23361. "STM %[r]!, {r4}\n\t"
  23362. "STR r5, [%[r]]\n\t"
  23363. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  23364. :
  23365. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  23366. );
  23367. }
  23368. #endif /* WOLFSSL_SP_SMALL */
  23369. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  23370. /* r = 2^n mod m where n is the number of bits to reduce by.
  23371. * Given m must be 4096 bits, just need to subtract.
  23372. *
  23373. * r A single precision number.
  23374. * m A single precision number.
  23375. */
  23376. static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m)
  23377. {
  23378. XMEMSET(r, 0, sizeof(sp_digit) * 128);
  23379. /* r = 2^n mod m */
  23380. sp_4096_sub_in_place_128(r, m);
  23381. }
  23382. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  23383. #ifdef WOLFSSL_SP_SMALL
  23384. /* Conditionally subtract b from a using the mask m.
  23385. * m is -1 to subtract and 0 when not copying.
  23386. *
  23387. * r A single precision number representing condition subtract result.
  23388. * a A single precision number to subtract from.
  23389. * b A single precision number to subtract.
  23390. * m Mask value to apply.
  23391. */
  23392. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  23393. static sp_digit sp_4096_cond_sub_128(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  23394. #else
  23395. static sp_digit sp_4096_cond_sub_128(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  23396. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  23397. {
  23398. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  23399. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  23400. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  23401. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  23402. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  23403. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  23404. __asm__ __volatile__ (
  23405. "MOV r8, #0x0\n\t"
  23406. "MOV r4, #0x0\n\t"
  23407. "MOV r5, #0x0\n\t"
  23408. "\n"
  23409. "L_sp_4096_cond_sub_128_words:\n\t"
  23410. "SUBS r4, r8, r4\n\t"
  23411. "LDR r6, [%[a], r5]\n\t"
  23412. "LDR r7, [%[b], r5]\n\t"
  23413. "AND r7, r7, %[m]\n\t"
  23414. "SBCS r6, r6, r7\n\t"
  23415. "SBC r4, r8, r8\n\t"
  23416. "STR r6, [%[r], r5]\n\t"
  23417. "ADD r5, r5, #0x4\n\t"
  23418. "CMP r5, #0x200\n\t"
  23419. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  23420. "BLT L_sp_4096_cond_sub_128_words\n\t"
  23421. #else
  23422. "BLT.N L_sp_4096_cond_sub_128_words\n\t"
  23423. #endif
  23424. "MOV %[r], r4\n\t"
  23425. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  23426. :
  23427. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  23428. );
  23429. return (uint32_t)(size_t)r;
  23430. }
  23431. #else
  23432. /* Conditionally subtract b from a using the mask m.
  23433. * m is -1 to subtract and 0 when not copying.
  23434. *
  23435. * r A single precision number representing condition subtract result.
  23436. * a A single precision number to subtract from.
  23437. * b A single precision number to subtract.
  23438. * m Mask value to apply.
  23439. */
  23440. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  23441. static sp_digit sp_4096_cond_sub_128(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  23442. #else
  23443. static sp_digit sp_4096_cond_sub_128(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  23444. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  23445. {
  23446. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  23447. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  23448. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  23449. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  23450. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  23451. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  23452. __asm__ __volatile__ (
  23453. "MOV r5, #0x0\n\t"
  23454. "LDM %[a]!, {r6, r7}\n\t"
  23455. "LDM %[b]!, {r8, r9}\n\t"
  23456. "AND r8, r8, %[m]\n\t"
  23457. "AND r9, r9, %[m]\n\t"
  23458. "SUBS r6, r6, r8\n\t"
  23459. "SBCS r7, r7, r9\n\t"
  23460. "STM %[r]!, {r6, r7}\n\t"
  23461. "LDM %[a]!, {r6, r7}\n\t"
  23462. "LDM %[b]!, {r8, r9}\n\t"
  23463. "AND r8, r8, %[m]\n\t"
  23464. "AND r9, r9, %[m]\n\t"
  23465. "SBCS r6, r6, r8\n\t"
  23466. "SBCS r7, r7, r9\n\t"
  23467. "STM %[r]!, {r6, r7}\n\t"
  23468. "LDM %[a]!, {r6, r7}\n\t"
  23469. "LDM %[b]!, {r8, r9}\n\t"
  23470. "AND r8, r8, %[m]\n\t"
  23471. "AND r9, r9, %[m]\n\t"
  23472. "SBCS r6, r6, r8\n\t"
  23473. "SBCS r7, r7, r9\n\t"
  23474. "STM %[r]!, {r6, r7}\n\t"
  23475. "LDM %[a]!, {r6, r7}\n\t"
  23476. "LDM %[b]!, {r8, r9}\n\t"
  23477. "AND r8, r8, %[m]\n\t"
  23478. "AND r9, r9, %[m]\n\t"
  23479. "SBCS r6, r6, r8\n\t"
  23480. "SBCS r7, r7, r9\n\t"
  23481. "STM %[r]!, {r6, r7}\n\t"
  23482. "LDM %[a]!, {r6, r7}\n\t"
  23483. "LDM %[b]!, {r8, r9}\n\t"
  23484. "AND r8, r8, %[m]\n\t"
  23485. "AND r9, r9, %[m]\n\t"
  23486. "SBCS r6, r6, r8\n\t"
  23487. "SBCS r7, r7, r9\n\t"
  23488. "STM %[r]!, {r6, r7}\n\t"
  23489. "LDM %[a]!, {r6, r7}\n\t"
  23490. "LDM %[b]!, {r8, r9}\n\t"
  23491. "AND r8, r8, %[m]\n\t"
  23492. "AND r9, r9, %[m]\n\t"
  23493. "SBCS r6, r6, r8\n\t"
  23494. "SBCS r7, r7, r9\n\t"
  23495. "STM %[r]!, {r6, r7}\n\t"
  23496. "LDM %[a]!, {r6, r7}\n\t"
  23497. "LDM %[b]!, {r8, r9}\n\t"
  23498. "AND r8, r8, %[m]\n\t"
  23499. "AND r9, r9, %[m]\n\t"
  23500. "SBCS r6, r6, r8\n\t"
  23501. "SBCS r7, r7, r9\n\t"
  23502. "STM %[r]!, {r6, r7}\n\t"
  23503. "LDM %[a]!, {r6, r7}\n\t"
  23504. "LDM %[b]!, {r8, r9}\n\t"
  23505. "AND r8, r8, %[m]\n\t"
  23506. "AND r9, r9, %[m]\n\t"
  23507. "SBCS r6, r6, r8\n\t"
  23508. "SBCS r7, r7, r9\n\t"
  23509. "STM %[r]!, {r6, r7}\n\t"
  23510. "LDM %[a]!, {r6, r7}\n\t"
  23511. "LDM %[b]!, {r8, r9}\n\t"
  23512. "AND r8, r8, %[m]\n\t"
  23513. "AND r9, r9, %[m]\n\t"
  23514. "SBCS r6, r6, r8\n\t"
  23515. "SBCS r7, r7, r9\n\t"
  23516. "STM %[r]!, {r6, r7}\n\t"
  23517. "LDM %[a]!, {r6, r7}\n\t"
  23518. "LDM %[b]!, {r8, r9}\n\t"
  23519. "AND r8, r8, %[m]\n\t"
  23520. "AND r9, r9, %[m]\n\t"
  23521. "SBCS r6, r6, r8\n\t"
  23522. "SBCS r7, r7, r9\n\t"
  23523. "STM %[r]!, {r6, r7}\n\t"
  23524. "LDM %[a]!, {r6, r7}\n\t"
  23525. "LDM %[b]!, {r8, r9}\n\t"
  23526. "AND r8, r8, %[m]\n\t"
  23527. "AND r9, r9, %[m]\n\t"
  23528. "SBCS r6, r6, r8\n\t"
  23529. "SBCS r7, r7, r9\n\t"
  23530. "STM %[r]!, {r6, r7}\n\t"
  23531. "LDM %[a]!, {r6, r7}\n\t"
  23532. "LDM %[b]!, {r8, r9}\n\t"
  23533. "AND r8, r8, %[m]\n\t"
  23534. "AND r9, r9, %[m]\n\t"
  23535. "SBCS r6, r6, r8\n\t"
  23536. "SBCS r7, r7, r9\n\t"
  23537. "STM %[r]!, {r6, r7}\n\t"
  23538. "LDM %[a]!, {r6, r7}\n\t"
  23539. "LDM %[b]!, {r8, r9}\n\t"
  23540. "AND r8, r8, %[m]\n\t"
  23541. "AND r9, r9, %[m]\n\t"
  23542. "SBCS r6, r6, r8\n\t"
  23543. "SBCS r7, r7, r9\n\t"
  23544. "STM %[r]!, {r6, r7}\n\t"
  23545. "LDM %[a]!, {r6, r7}\n\t"
  23546. "LDM %[b]!, {r8, r9}\n\t"
  23547. "AND r8, r8, %[m]\n\t"
  23548. "AND r9, r9, %[m]\n\t"
  23549. "SBCS r6, r6, r8\n\t"
  23550. "SBCS r7, r7, r9\n\t"
  23551. "STM %[r]!, {r6, r7}\n\t"
  23552. "LDM %[a]!, {r6, r7}\n\t"
  23553. "LDM %[b]!, {r8, r9}\n\t"
  23554. "AND r8, r8, %[m]\n\t"
  23555. "AND r9, r9, %[m]\n\t"
  23556. "SBCS r6, r6, r8\n\t"
  23557. "SBCS r7, r7, r9\n\t"
  23558. "STM %[r]!, {r6, r7}\n\t"
  23559. "LDM %[a]!, {r6, r7}\n\t"
  23560. "LDM %[b]!, {r8, r9}\n\t"
  23561. "AND r8, r8, %[m]\n\t"
  23562. "AND r9, r9, %[m]\n\t"
  23563. "SBCS r6, r6, r8\n\t"
  23564. "SBCS r7, r7, r9\n\t"
  23565. "STM %[r]!, {r6, r7}\n\t"
  23566. "LDM %[a]!, {r6, r7}\n\t"
  23567. "LDM %[b]!, {r8, r9}\n\t"
  23568. "AND r8, r8, %[m]\n\t"
  23569. "AND r9, r9, %[m]\n\t"
  23570. "SBCS r6, r6, r8\n\t"
  23571. "SBCS r7, r7, r9\n\t"
  23572. "STM %[r]!, {r6, r7}\n\t"
  23573. "LDM %[a]!, {r6, r7}\n\t"
  23574. "LDM %[b]!, {r8, r9}\n\t"
  23575. "AND r8, r8, %[m]\n\t"
  23576. "AND r9, r9, %[m]\n\t"
  23577. "SBCS r6, r6, r8\n\t"
  23578. "SBCS r7, r7, r9\n\t"
  23579. "STM %[r]!, {r6, r7}\n\t"
  23580. "LDM %[a]!, {r6, r7}\n\t"
  23581. "LDM %[b]!, {r8, r9}\n\t"
  23582. "AND r8, r8, %[m]\n\t"
  23583. "AND r9, r9, %[m]\n\t"
  23584. "SBCS r6, r6, r8\n\t"
  23585. "SBCS r7, r7, r9\n\t"
  23586. "STM %[r]!, {r6, r7}\n\t"
  23587. "LDM %[a]!, {r6, r7}\n\t"
  23588. "LDM %[b]!, {r8, r9}\n\t"
  23589. "AND r8, r8, %[m]\n\t"
  23590. "AND r9, r9, %[m]\n\t"
  23591. "SBCS r6, r6, r8\n\t"
  23592. "SBCS r7, r7, r9\n\t"
  23593. "STM %[r]!, {r6, r7}\n\t"
  23594. "LDM %[a]!, {r6, r7}\n\t"
  23595. "LDM %[b]!, {r8, r9}\n\t"
  23596. "AND r8, r8, %[m]\n\t"
  23597. "AND r9, r9, %[m]\n\t"
  23598. "SBCS r6, r6, r8\n\t"
  23599. "SBCS r7, r7, r9\n\t"
  23600. "STM %[r]!, {r6, r7}\n\t"
  23601. "LDM %[a]!, {r6, r7}\n\t"
  23602. "LDM %[b]!, {r8, r9}\n\t"
  23603. "AND r8, r8, %[m]\n\t"
  23604. "AND r9, r9, %[m]\n\t"
  23605. "SBCS r6, r6, r8\n\t"
  23606. "SBCS r7, r7, r9\n\t"
  23607. "STM %[r]!, {r6, r7}\n\t"
  23608. "LDM %[a]!, {r6, r7}\n\t"
  23609. "LDM %[b]!, {r8, r9}\n\t"
  23610. "AND r8, r8, %[m]\n\t"
  23611. "AND r9, r9, %[m]\n\t"
  23612. "SBCS r6, r6, r8\n\t"
  23613. "SBCS r7, r7, r9\n\t"
  23614. "STM %[r]!, {r6, r7}\n\t"
  23615. "LDM %[a]!, {r6, r7}\n\t"
  23616. "LDM %[b]!, {r8, r9}\n\t"
  23617. "AND r8, r8, %[m]\n\t"
  23618. "AND r9, r9, %[m]\n\t"
  23619. "SBCS r6, r6, r8\n\t"
  23620. "SBCS r7, r7, r9\n\t"
  23621. "STM %[r]!, {r6, r7}\n\t"
  23622. "LDM %[a]!, {r6, r7}\n\t"
  23623. "LDM %[b]!, {r8, r9}\n\t"
  23624. "AND r8, r8, %[m]\n\t"
  23625. "AND r9, r9, %[m]\n\t"
  23626. "SBCS r6, r6, r8\n\t"
  23627. "SBCS r7, r7, r9\n\t"
  23628. "STM %[r]!, {r6, r7}\n\t"
  23629. "LDM %[a]!, {r6, r7}\n\t"
  23630. "LDM %[b]!, {r8, r9}\n\t"
  23631. "AND r8, r8, %[m]\n\t"
  23632. "AND r9, r9, %[m]\n\t"
  23633. "SBCS r6, r6, r8\n\t"
  23634. "SBCS r7, r7, r9\n\t"
  23635. "STM %[r]!, {r6, r7}\n\t"
  23636. "LDM %[a]!, {r6, r7}\n\t"
  23637. "LDM %[b]!, {r8, r9}\n\t"
  23638. "AND r8, r8, %[m]\n\t"
  23639. "AND r9, r9, %[m]\n\t"
  23640. "SBCS r6, r6, r8\n\t"
  23641. "SBCS r7, r7, r9\n\t"
  23642. "STM %[r]!, {r6, r7}\n\t"
  23643. "LDM %[a]!, {r6, r7}\n\t"
  23644. "LDM %[b]!, {r8, r9}\n\t"
  23645. "AND r8, r8, %[m]\n\t"
  23646. "AND r9, r9, %[m]\n\t"
  23647. "SBCS r6, r6, r8\n\t"
  23648. "SBCS r7, r7, r9\n\t"
  23649. "STM %[r]!, {r6, r7}\n\t"
  23650. "LDM %[a]!, {r6, r7}\n\t"
  23651. "LDM %[b]!, {r8, r9}\n\t"
  23652. "AND r8, r8, %[m]\n\t"
  23653. "AND r9, r9, %[m]\n\t"
  23654. "SBCS r6, r6, r8\n\t"
  23655. "SBCS r7, r7, r9\n\t"
  23656. "STM %[r]!, {r6, r7}\n\t"
  23657. "LDM %[a]!, {r6, r7}\n\t"
  23658. "LDM %[b]!, {r8, r9}\n\t"
  23659. "AND r8, r8, %[m]\n\t"
  23660. "AND r9, r9, %[m]\n\t"
  23661. "SBCS r6, r6, r8\n\t"
  23662. "SBCS r7, r7, r9\n\t"
  23663. "STM %[r]!, {r6, r7}\n\t"
  23664. "LDM %[a]!, {r6, r7}\n\t"
  23665. "LDM %[b]!, {r8, r9}\n\t"
  23666. "AND r8, r8, %[m]\n\t"
  23667. "AND r9, r9, %[m]\n\t"
  23668. "SBCS r6, r6, r8\n\t"
  23669. "SBCS r7, r7, r9\n\t"
  23670. "STM %[r]!, {r6, r7}\n\t"
  23671. "LDM %[a]!, {r6, r7}\n\t"
  23672. "LDM %[b]!, {r8, r9}\n\t"
  23673. "AND r8, r8, %[m]\n\t"
  23674. "AND r9, r9, %[m]\n\t"
  23675. "SBCS r6, r6, r8\n\t"
  23676. "SBCS r7, r7, r9\n\t"
  23677. "STM %[r]!, {r6, r7}\n\t"
  23678. "LDM %[a]!, {r6, r7}\n\t"
  23679. "LDM %[b]!, {r8, r9}\n\t"
  23680. "AND r8, r8, %[m]\n\t"
  23681. "AND r9, r9, %[m]\n\t"
  23682. "SBCS r6, r6, r8\n\t"
  23683. "SBCS r7, r7, r9\n\t"
  23684. "STM %[r]!, {r6, r7}\n\t"
  23685. "LDM %[a]!, {r6, r7}\n\t"
  23686. "LDM %[b]!, {r8, r9}\n\t"
  23687. "AND r8, r8, %[m]\n\t"
  23688. "AND r9, r9, %[m]\n\t"
  23689. "SBCS r6, r6, r8\n\t"
  23690. "SBCS r7, r7, r9\n\t"
  23691. "STM %[r]!, {r6, r7}\n\t"
  23692. "LDM %[a]!, {r6, r7}\n\t"
  23693. "LDM %[b]!, {r8, r9}\n\t"
  23694. "AND r8, r8, %[m]\n\t"
  23695. "AND r9, r9, %[m]\n\t"
  23696. "SBCS r6, r6, r8\n\t"
  23697. "SBCS r7, r7, r9\n\t"
  23698. "STM %[r]!, {r6, r7}\n\t"
  23699. "LDM %[a]!, {r6, r7}\n\t"
  23700. "LDM %[b]!, {r8, r9}\n\t"
  23701. "AND r8, r8, %[m]\n\t"
  23702. "AND r9, r9, %[m]\n\t"
  23703. "SBCS r6, r6, r8\n\t"
  23704. "SBCS r7, r7, r9\n\t"
  23705. "STM %[r]!, {r6, r7}\n\t"
  23706. "LDM %[a]!, {r6, r7}\n\t"
  23707. "LDM %[b]!, {r8, r9}\n\t"
  23708. "AND r8, r8, %[m]\n\t"
  23709. "AND r9, r9, %[m]\n\t"
  23710. "SBCS r6, r6, r8\n\t"
  23711. "SBCS r7, r7, r9\n\t"
  23712. "STM %[r]!, {r6, r7}\n\t"
  23713. "LDM %[a]!, {r6, r7}\n\t"
  23714. "LDM %[b]!, {r8, r9}\n\t"
  23715. "AND r8, r8, %[m]\n\t"
  23716. "AND r9, r9, %[m]\n\t"
  23717. "SBCS r6, r6, r8\n\t"
  23718. "SBCS r7, r7, r9\n\t"
  23719. "STM %[r]!, {r6, r7}\n\t"
  23720. "LDM %[a]!, {r6, r7}\n\t"
  23721. "LDM %[b]!, {r8, r9}\n\t"
  23722. "AND r8, r8, %[m]\n\t"
  23723. "AND r9, r9, %[m]\n\t"
  23724. "SBCS r6, r6, r8\n\t"
  23725. "SBCS r7, r7, r9\n\t"
  23726. "STM %[r]!, {r6, r7}\n\t"
  23727. "LDM %[a]!, {r6, r7}\n\t"
  23728. "LDM %[b]!, {r8, r9}\n\t"
  23729. "AND r8, r8, %[m]\n\t"
  23730. "AND r9, r9, %[m]\n\t"
  23731. "SBCS r6, r6, r8\n\t"
  23732. "SBCS r7, r7, r9\n\t"
  23733. "STM %[r]!, {r6, r7}\n\t"
  23734. "LDM %[a]!, {r6, r7}\n\t"
  23735. "LDM %[b]!, {r8, r9}\n\t"
  23736. "AND r8, r8, %[m]\n\t"
  23737. "AND r9, r9, %[m]\n\t"
  23738. "SBCS r6, r6, r8\n\t"
  23739. "SBCS r7, r7, r9\n\t"
  23740. "STM %[r]!, {r6, r7}\n\t"
  23741. "LDM %[a]!, {r6, r7}\n\t"
  23742. "LDM %[b]!, {r8, r9}\n\t"
  23743. "AND r8, r8, %[m]\n\t"
  23744. "AND r9, r9, %[m]\n\t"
  23745. "SBCS r6, r6, r8\n\t"
  23746. "SBCS r7, r7, r9\n\t"
  23747. "STM %[r]!, {r6, r7}\n\t"
  23748. "LDM %[a]!, {r6, r7}\n\t"
  23749. "LDM %[b]!, {r8, r9}\n\t"
  23750. "AND r8, r8, %[m]\n\t"
  23751. "AND r9, r9, %[m]\n\t"
  23752. "SBCS r6, r6, r8\n\t"
  23753. "SBCS r7, r7, r9\n\t"
  23754. "STM %[r]!, {r6, r7}\n\t"
  23755. "LDM %[a]!, {r6, r7}\n\t"
  23756. "LDM %[b]!, {r8, r9}\n\t"
  23757. "AND r8, r8, %[m]\n\t"
  23758. "AND r9, r9, %[m]\n\t"
  23759. "SBCS r6, r6, r8\n\t"
  23760. "SBCS r7, r7, r9\n\t"
  23761. "STM %[r]!, {r6, r7}\n\t"
  23762. "LDM %[a]!, {r6, r7}\n\t"
  23763. "LDM %[b]!, {r8, r9}\n\t"
  23764. "AND r8, r8, %[m]\n\t"
  23765. "AND r9, r9, %[m]\n\t"
  23766. "SBCS r6, r6, r8\n\t"
  23767. "SBCS r7, r7, r9\n\t"
  23768. "STM %[r]!, {r6, r7}\n\t"
  23769. "LDM %[a]!, {r6, r7}\n\t"
  23770. "LDM %[b]!, {r8, r9}\n\t"
  23771. "AND r8, r8, %[m]\n\t"
  23772. "AND r9, r9, %[m]\n\t"
  23773. "SBCS r6, r6, r8\n\t"
  23774. "SBCS r7, r7, r9\n\t"
  23775. "STM %[r]!, {r6, r7}\n\t"
  23776. "LDM %[a]!, {r6, r7}\n\t"
  23777. "LDM %[b]!, {r8, r9}\n\t"
  23778. "AND r8, r8, %[m]\n\t"
  23779. "AND r9, r9, %[m]\n\t"
  23780. "SBCS r6, r6, r8\n\t"
  23781. "SBCS r7, r7, r9\n\t"
  23782. "STM %[r]!, {r6, r7}\n\t"
  23783. "LDM %[a]!, {r6, r7}\n\t"
  23784. "LDM %[b]!, {r8, r9}\n\t"
  23785. "AND r8, r8, %[m]\n\t"
  23786. "AND r9, r9, %[m]\n\t"
  23787. "SBCS r6, r6, r8\n\t"
  23788. "SBCS r7, r7, r9\n\t"
  23789. "STM %[r]!, {r6, r7}\n\t"
  23790. "LDM %[a]!, {r6, r7}\n\t"
  23791. "LDM %[b]!, {r8, r9}\n\t"
  23792. "AND r8, r8, %[m]\n\t"
  23793. "AND r9, r9, %[m]\n\t"
  23794. "SBCS r6, r6, r8\n\t"
  23795. "SBCS r7, r7, r9\n\t"
  23796. "STM %[r]!, {r6, r7}\n\t"
  23797. "LDM %[a]!, {r6, r7}\n\t"
  23798. "LDM %[b]!, {r8, r9}\n\t"
  23799. "AND r8, r8, %[m]\n\t"
  23800. "AND r9, r9, %[m]\n\t"
  23801. "SBCS r6, r6, r8\n\t"
  23802. "SBCS r7, r7, r9\n\t"
  23803. "STM %[r]!, {r6, r7}\n\t"
  23804. "LDM %[a]!, {r6, r7}\n\t"
  23805. "LDM %[b]!, {r8, r9}\n\t"
  23806. "AND r8, r8, %[m]\n\t"
  23807. "AND r9, r9, %[m]\n\t"
  23808. "SBCS r6, r6, r8\n\t"
  23809. "SBCS r7, r7, r9\n\t"
  23810. "STM %[r]!, {r6, r7}\n\t"
  23811. "LDM %[a]!, {r6, r7}\n\t"
  23812. "LDM %[b]!, {r8, r9}\n\t"
  23813. "AND r8, r8, %[m]\n\t"
  23814. "AND r9, r9, %[m]\n\t"
  23815. "SBCS r6, r6, r8\n\t"
  23816. "SBCS r7, r7, r9\n\t"
  23817. "STM %[r]!, {r6, r7}\n\t"
  23818. "LDM %[a]!, {r6, r7}\n\t"
  23819. "LDM %[b]!, {r8, r9}\n\t"
  23820. "AND r8, r8, %[m]\n\t"
  23821. "AND r9, r9, %[m]\n\t"
  23822. "SBCS r6, r6, r8\n\t"
  23823. "SBCS r7, r7, r9\n\t"
  23824. "STM %[r]!, {r6, r7}\n\t"
  23825. "LDM %[a]!, {r6, r7}\n\t"
  23826. "LDM %[b]!, {r8, r9}\n\t"
  23827. "AND r8, r8, %[m]\n\t"
  23828. "AND r9, r9, %[m]\n\t"
  23829. "SBCS r6, r6, r8\n\t"
  23830. "SBCS r7, r7, r9\n\t"
  23831. "STM %[r]!, {r6, r7}\n\t"
  23832. "LDM %[a]!, {r6, r7}\n\t"
  23833. "LDM %[b]!, {r8, r9}\n\t"
  23834. "AND r8, r8, %[m]\n\t"
  23835. "AND r9, r9, %[m]\n\t"
  23836. "SBCS r6, r6, r8\n\t"
  23837. "SBCS r7, r7, r9\n\t"
  23838. "STM %[r]!, {r6, r7}\n\t"
  23839. "LDM %[a]!, {r6, r7}\n\t"
  23840. "LDM %[b]!, {r8, r9}\n\t"
  23841. "AND r8, r8, %[m]\n\t"
  23842. "AND r9, r9, %[m]\n\t"
  23843. "SBCS r6, r6, r8\n\t"
  23844. "SBCS r7, r7, r9\n\t"
  23845. "STM %[r]!, {r6, r7}\n\t"
  23846. "LDM %[a]!, {r6, r7}\n\t"
  23847. "LDM %[b]!, {r8, r9}\n\t"
  23848. "AND r8, r8, %[m]\n\t"
  23849. "AND r9, r9, %[m]\n\t"
  23850. "SBCS r6, r6, r8\n\t"
  23851. "SBCS r7, r7, r9\n\t"
  23852. "STM %[r]!, {r6, r7}\n\t"
  23853. "LDM %[a]!, {r6, r7}\n\t"
  23854. "LDM %[b]!, {r8, r9}\n\t"
  23855. "AND r8, r8, %[m]\n\t"
  23856. "AND r9, r9, %[m]\n\t"
  23857. "SBCS r6, r6, r8\n\t"
  23858. "SBCS r7, r7, r9\n\t"
  23859. "STM %[r]!, {r6, r7}\n\t"
  23860. "LDM %[a]!, {r6, r7}\n\t"
  23861. "LDM %[b]!, {r8, r9}\n\t"
  23862. "AND r8, r8, %[m]\n\t"
  23863. "AND r9, r9, %[m]\n\t"
  23864. "SBCS r6, r6, r8\n\t"
  23865. "SBCS r7, r7, r9\n\t"
  23866. "STM %[r]!, {r6, r7}\n\t"
  23867. "LDM %[a]!, {r6, r7}\n\t"
  23868. "LDM %[b]!, {r8, r9}\n\t"
  23869. "AND r8, r8, %[m]\n\t"
  23870. "AND r9, r9, %[m]\n\t"
  23871. "SBCS r6, r6, r8\n\t"
  23872. "SBCS r7, r7, r9\n\t"
  23873. "STM %[r]!, {r6, r7}\n\t"
  23874. "LDM %[a]!, {r6, r7}\n\t"
  23875. "LDM %[b]!, {r8, r9}\n\t"
  23876. "AND r8, r8, %[m]\n\t"
  23877. "AND r9, r9, %[m]\n\t"
  23878. "SBCS r6, r6, r8\n\t"
  23879. "SBCS r7, r7, r9\n\t"
  23880. "STM %[r]!, {r6, r7}\n\t"
  23881. "LDM %[a]!, {r6, r7}\n\t"
  23882. "LDM %[b]!, {r8, r9}\n\t"
  23883. "AND r8, r8, %[m]\n\t"
  23884. "AND r9, r9, %[m]\n\t"
  23885. "SBCS r6, r6, r8\n\t"
  23886. "SBCS r7, r7, r9\n\t"
  23887. "STM %[r]!, {r6, r7}\n\t"
  23888. "LDM %[a]!, {r6, r7}\n\t"
  23889. "LDM %[b]!, {r8, r9}\n\t"
  23890. "AND r8, r8, %[m]\n\t"
  23891. "AND r9, r9, %[m]\n\t"
  23892. "SBCS r6, r6, r8\n\t"
  23893. "SBCS r7, r7, r9\n\t"
  23894. "STM %[r]!, {r6, r7}\n\t"
  23895. "LDM %[a]!, {r6, r7}\n\t"
  23896. "LDM %[b]!, {r8, r9}\n\t"
  23897. "AND r8, r8, %[m]\n\t"
  23898. "AND r9, r9, %[m]\n\t"
  23899. "SBCS r6, r6, r8\n\t"
  23900. "SBCS r7, r7, r9\n\t"
  23901. "STM %[r]!, {r6, r7}\n\t"
  23902. "SBC %[r], r5, r5\n\t"
  23903. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  23904. :
  23905. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  23906. );
  23907. return (uint32_t)(size_t)r;
  23908. }
  23909. #endif /* WOLFSSL_SP_SMALL */
  23910. #ifdef WOLFSSL_SP_NO_UMAAL
  23911. #ifndef WOLFSSL_SP_SMALL
  23912. /* Reduce the number back to 4096 bits using Montgomery reduction.
  23913. *
  23914. * a A single precision number to reduce in place.
  23915. * m The single precision number representing the modulus.
  23916. * mp The digit representing the negative inverse of m mod 2^n.
  23917. */
  23918. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  23919. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  23920. #else
  23921. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, sp_digit mp)
  23922. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  23923. {
  23924. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  23925. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  23926. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  23927. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  23928. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  23929. __asm__ __volatile__ (
  23930. "LDR lr, [%[m]]\n\t"
  23931. /* i = 0 */
  23932. "MOV r11, #0x0\n\t"
  23933. "MOV r3, #0x0\n\t"
  23934. "LDR r4, [%[a]]\n\t"
  23935. "LDR r5, [%[a], #4]\n\t"
  23936. "\n"
  23937. "L_sp_4096_mont_reduce_128_word:\n\t"
  23938. /* mu = a[i] * mp */
  23939. "MUL r10, %[mp], r4\n\t"
  23940. /* a[i+0] += m[0] * mu */
  23941. "MOV r7, #0x0\n\t"
  23942. "UMLAL r4, r7, r10, lr\n\t"
  23943. /* a[i+1] += m[1] * mu */
  23944. "LDR r9, [%[m], #4]\n\t"
  23945. "MOV r6, #0x0\n\t"
  23946. "UMLAL r5, r6, r10, r9\n\t"
  23947. "MOV r4, r5\n\t"
  23948. "ADDS r4, r4, r7\n\t"
  23949. "ADC r6, r6, #0x0\n\t"
  23950. /* a[i+2] += m[2] * mu */
  23951. "LDR r9, [%[m], #8]\n\t"
  23952. "LDR r5, [%[a], #8]\n\t"
  23953. "MOV r7, #0x0\n\t"
  23954. "UMLAL r5, r7, r10, r9\n\t"
  23955. "ADDS r5, r5, r6\n\t"
  23956. "ADC r7, r7, #0x0\n\t"
  23957. /* a[i+3] += m[3] * mu */
  23958. "LDR r9, [%[m], #12]\n\t"
  23959. "LDR r12, [%[a], #12]\n\t"
  23960. "MOV r6, #0x0\n\t"
  23961. "UMLAL r12, r6, r10, r9\n\t"
  23962. "ADDS r12, r12, r7\n\t"
  23963. "STR r12, [%[a], #12]\n\t"
  23964. "ADC r6, r6, #0x0\n\t"
  23965. /* a[i+4] += m[4] * mu */
  23966. "LDR r9, [%[m], #16]\n\t"
  23967. "LDR r12, [%[a], #16]\n\t"
  23968. "MOV r7, #0x0\n\t"
  23969. "UMLAL r12, r7, r10, r9\n\t"
  23970. "ADDS r12, r12, r6\n\t"
  23971. "STR r12, [%[a], #16]\n\t"
  23972. "ADC r7, r7, #0x0\n\t"
  23973. /* a[i+5] += m[5] * mu */
  23974. "LDR r9, [%[m], #20]\n\t"
  23975. "LDR r12, [%[a], #20]\n\t"
  23976. "MOV r6, #0x0\n\t"
  23977. "UMLAL r12, r6, r10, r9\n\t"
  23978. "ADDS r12, r12, r7\n\t"
  23979. "STR r12, [%[a], #20]\n\t"
  23980. "ADC r6, r6, #0x0\n\t"
  23981. /* a[i+6] += m[6] * mu */
  23982. "LDR r9, [%[m], #24]\n\t"
  23983. "LDR r12, [%[a], #24]\n\t"
  23984. "MOV r7, #0x0\n\t"
  23985. "UMLAL r12, r7, r10, r9\n\t"
  23986. "ADDS r12, r12, r6\n\t"
  23987. "STR r12, [%[a], #24]\n\t"
  23988. "ADC r7, r7, #0x0\n\t"
  23989. /* a[i+7] += m[7] * mu */
  23990. "LDR r9, [%[m], #28]\n\t"
  23991. "LDR r12, [%[a], #28]\n\t"
  23992. "MOV r6, #0x0\n\t"
  23993. "UMLAL r12, r6, r10, r9\n\t"
  23994. "ADDS r12, r12, r7\n\t"
  23995. "STR r12, [%[a], #28]\n\t"
  23996. "ADC r6, r6, #0x0\n\t"
  23997. /* a[i+8] += m[8] * mu */
  23998. "LDR r9, [%[m], #32]\n\t"
  23999. "LDR r12, [%[a], #32]\n\t"
  24000. "MOV r7, #0x0\n\t"
  24001. "UMLAL r12, r7, r10, r9\n\t"
  24002. "ADDS r12, r12, r6\n\t"
  24003. "STR r12, [%[a], #32]\n\t"
  24004. "ADC r7, r7, #0x0\n\t"
  24005. /* a[i+9] += m[9] * mu */
  24006. "LDR r9, [%[m], #36]\n\t"
  24007. "LDR r12, [%[a], #36]\n\t"
  24008. "MOV r6, #0x0\n\t"
  24009. "UMLAL r12, r6, r10, r9\n\t"
  24010. "ADDS r12, r12, r7\n\t"
  24011. "STR r12, [%[a], #36]\n\t"
  24012. "ADC r6, r6, #0x0\n\t"
  24013. /* a[i+10] += m[10] * mu */
  24014. "LDR r9, [%[m], #40]\n\t"
  24015. "LDR r12, [%[a], #40]\n\t"
  24016. "MOV r7, #0x0\n\t"
  24017. "UMLAL r12, r7, r10, r9\n\t"
  24018. "ADDS r12, r12, r6\n\t"
  24019. "STR r12, [%[a], #40]\n\t"
  24020. "ADC r7, r7, #0x0\n\t"
  24021. /* a[i+11] += m[11] * mu */
  24022. "LDR r9, [%[m], #44]\n\t"
  24023. "LDR r12, [%[a], #44]\n\t"
  24024. "MOV r6, #0x0\n\t"
  24025. "UMLAL r12, r6, r10, r9\n\t"
  24026. "ADDS r12, r12, r7\n\t"
  24027. "STR r12, [%[a], #44]\n\t"
  24028. "ADC r6, r6, #0x0\n\t"
  24029. /* a[i+12] += m[12] * mu */
  24030. "LDR r9, [%[m], #48]\n\t"
  24031. "LDR r12, [%[a], #48]\n\t"
  24032. "MOV r7, #0x0\n\t"
  24033. "UMLAL r12, r7, r10, r9\n\t"
  24034. "ADDS r12, r12, r6\n\t"
  24035. "STR r12, [%[a], #48]\n\t"
  24036. "ADC r7, r7, #0x0\n\t"
  24037. /* a[i+13] += m[13] * mu */
  24038. "LDR r9, [%[m], #52]\n\t"
  24039. "LDR r12, [%[a], #52]\n\t"
  24040. "MOV r6, #0x0\n\t"
  24041. "UMLAL r12, r6, r10, r9\n\t"
  24042. "ADDS r12, r12, r7\n\t"
  24043. "STR r12, [%[a], #52]\n\t"
  24044. "ADC r6, r6, #0x0\n\t"
  24045. /* a[i+14] += m[14] * mu */
  24046. "LDR r9, [%[m], #56]\n\t"
  24047. "LDR r12, [%[a], #56]\n\t"
  24048. "MOV r7, #0x0\n\t"
  24049. "UMLAL r12, r7, r10, r9\n\t"
  24050. "ADDS r12, r12, r6\n\t"
  24051. "STR r12, [%[a], #56]\n\t"
  24052. "ADC r7, r7, #0x0\n\t"
  24053. /* a[i+15] += m[15] * mu */
  24054. "LDR r9, [%[m], #60]\n\t"
  24055. "LDR r12, [%[a], #60]\n\t"
  24056. "MOV r6, #0x0\n\t"
  24057. "UMLAL r12, r6, r10, r9\n\t"
  24058. "ADDS r12, r12, r7\n\t"
  24059. "STR r12, [%[a], #60]\n\t"
  24060. "ADC r6, r6, #0x0\n\t"
  24061. /* a[i+16] += m[16] * mu */
  24062. "LDR r9, [%[m], #64]\n\t"
  24063. "LDR r12, [%[a], #64]\n\t"
  24064. "MOV r7, #0x0\n\t"
  24065. "UMLAL r12, r7, r10, r9\n\t"
  24066. "ADDS r12, r12, r6\n\t"
  24067. "STR r12, [%[a], #64]\n\t"
  24068. "ADC r7, r7, #0x0\n\t"
  24069. /* a[i+17] += m[17] * mu */
  24070. "LDR r9, [%[m], #68]\n\t"
  24071. "LDR r12, [%[a], #68]\n\t"
  24072. "MOV r6, #0x0\n\t"
  24073. "UMLAL r12, r6, r10, r9\n\t"
  24074. "ADDS r12, r12, r7\n\t"
  24075. "STR r12, [%[a], #68]\n\t"
  24076. "ADC r6, r6, #0x0\n\t"
  24077. /* a[i+18] += m[18] * mu */
  24078. "LDR r9, [%[m], #72]\n\t"
  24079. "LDR r12, [%[a], #72]\n\t"
  24080. "MOV r7, #0x0\n\t"
  24081. "UMLAL r12, r7, r10, r9\n\t"
  24082. "ADDS r12, r12, r6\n\t"
  24083. "STR r12, [%[a], #72]\n\t"
  24084. "ADC r7, r7, #0x0\n\t"
  24085. /* a[i+19] += m[19] * mu */
  24086. "LDR r9, [%[m], #76]\n\t"
  24087. "LDR r12, [%[a], #76]\n\t"
  24088. "MOV r6, #0x0\n\t"
  24089. "UMLAL r12, r6, r10, r9\n\t"
  24090. "ADDS r12, r12, r7\n\t"
  24091. "STR r12, [%[a], #76]\n\t"
  24092. "ADC r6, r6, #0x0\n\t"
  24093. /* a[i+20] += m[20] * mu */
  24094. "LDR r9, [%[m], #80]\n\t"
  24095. "LDR r12, [%[a], #80]\n\t"
  24096. "MOV r7, #0x0\n\t"
  24097. "UMLAL r12, r7, r10, r9\n\t"
  24098. "ADDS r12, r12, r6\n\t"
  24099. "STR r12, [%[a], #80]\n\t"
  24100. "ADC r7, r7, #0x0\n\t"
  24101. /* a[i+21] += m[21] * mu */
  24102. "LDR r9, [%[m], #84]\n\t"
  24103. "LDR r12, [%[a], #84]\n\t"
  24104. "MOV r6, #0x0\n\t"
  24105. "UMLAL r12, r6, r10, r9\n\t"
  24106. "ADDS r12, r12, r7\n\t"
  24107. "STR r12, [%[a], #84]\n\t"
  24108. "ADC r6, r6, #0x0\n\t"
  24109. /* a[i+22] += m[22] * mu */
  24110. "LDR r9, [%[m], #88]\n\t"
  24111. "LDR r12, [%[a], #88]\n\t"
  24112. "MOV r7, #0x0\n\t"
  24113. "UMLAL r12, r7, r10, r9\n\t"
  24114. "ADDS r12, r12, r6\n\t"
  24115. "STR r12, [%[a], #88]\n\t"
  24116. "ADC r7, r7, #0x0\n\t"
  24117. /* a[i+23] += m[23] * mu */
  24118. "LDR r9, [%[m], #92]\n\t"
  24119. "LDR r12, [%[a], #92]\n\t"
  24120. "MOV r6, #0x0\n\t"
  24121. "UMLAL r12, r6, r10, r9\n\t"
  24122. "ADDS r12, r12, r7\n\t"
  24123. "STR r12, [%[a], #92]\n\t"
  24124. "ADC r6, r6, #0x0\n\t"
  24125. /* a[i+24] += m[24] * mu */
  24126. "LDR r9, [%[m], #96]\n\t"
  24127. "LDR r12, [%[a], #96]\n\t"
  24128. "MOV r7, #0x0\n\t"
  24129. "UMLAL r12, r7, r10, r9\n\t"
  24130. "ADDS r12, r12, r6\n\t"
  24131. "STR r12, [%[a], #96]\n\t"
  24132. "ADC r7, r7, #0x0\n\t"
  24133. /* a[i+25] += m[25] * mu */
  24134. "LDR r9, [%[m], #100]\n\t"
  24135. "LDR r12, [%[a], #100]\n\t"
  24136. "MOV r6, #0x0\n\t"
  24137. "UMLAL r12, r6, r10, r9\n\t"
  24138. "ADDS r12, r12, r7\n\t"
  24139. "STR r12, [%[a], #100]\n\t"
  24140. "ADC r6, r6, #0x0\n\t"
  24141. /* a[i+26] += m[26] * mu */
  24142. "LDR r9, [%[m], #104]\n\t"
  24143. "LDR r12, [%[a], #104]\n\t"
  24144. "MOV r7, #0x0\n\t"
  24145. "UMLAL r12, r7, r10, r9\n\t"
  24146. "ADDS r12, r12, r6\n\t"
  24147. "STR r12, [%[a], #104]\n\t"
  24148. "ADC r7, r7, #0x0\n\t"
  24149. /* a[i+27] += m[27] * mu */
  24150. "LDR r9, [%[m], #108]\n\t"
  24151. "LDR r12, [%[a], #108]\n\t"
  24152. "MOV r6, #0x0\n\t"
  24153. "UMLAL r12, r6, r10, r9\n\t"
  24154. "ADDS r12, r12, r7\n\t"
  24155. "STR r12, [%[a], #108]\n\t"
  24156. "ADC r6, r6, #0x0\n\t"
  24157. /* a[i+28] += m[28] * mu */
  24158. "LDR r9, [%[m], #112]\n\t"
  24159. "LDR r12, [%[a], #112]\n\t"
  24160. "MOV r7, #0x0\n\t"
  24161. "UMLAL r12, r7, r10, r9\n\t"
  24162. "ADDS r12, r12, r6\n\t"
  24163. "STR r12, [%[a], #112]\n\t"
  24164. "ADC r7, r7, #0x0\n\t"
  24165. /* a[i+29] += m[29] * mu */
  24166. "LDR r9, [%[m], #116]\n\t"
  24167. "LDR r12, [%[a], #116]\n\t"
  24168. "MOV r6, #0x0\n\t"
  24169. "UMLAL r12, r6, r10, r9\n\t"
  24170. "ADDS r12, r12, r7\n\t"
  24171. "STR r12, [%[a], #116]\n\t"
  24172. "ADC r6, r6, #0x0\n\t"
  24173. /* a[i+30] += m[30] * mu */
  24174. "LDR r9, [%[m], #120]\n\t"
  24175. "LDR r12, [%[a], #120]\n\t"
  24176. "MOV r7, #0x0\n\t"
  24177. "UMLAL r12, r7, r10, r9\n\t"
  24178. "ADDS r12, r12, r6\n\t"
  24179. "STR r12, [%[a], #120]\n\t"
  24180. "ADC r7, r7, #0x0\n\t"
  24181. /* a[i+31] += m[31] * mu */
  24182. "LDR r9, [%[m], #124]\n\t"
  24183. "LDR r12, [%[a], #124]\n\t"
  24184. "MOV r6, #0x0\n\t"
  24185. "UMLAL r12, r6, r10, r9\n\t"
  24186. "ADDS r12, r12, r7\n\t"
  24187. "STR r12, [%[a], #124]\n\t"
  24188. "ADC r6, r6, #0x0\n\t"
  24189. /* a[i+32] += m[32] * mu */
  24190. "LDR r9, [%[m], #128]\n\t"
  24191. "LDR r12, [%[a], #128]\n\t"
  24192. "MOV r7, #0x0\n\t"
  24193. "UMLAL r12, r7, r10, r9\n\t"
  24194. "ADDS r12, r12, r6\n\t"
  24195. "STR r12, [%[a], #128]\n\t"
  24196. "ADC r7, r7, #0x0\n\t"
  24197. /* a[i+33] += m[33] * mu */
  24198. "LDR r9, [%[m], #132]\n\t"
  24199. "LDR r12, [%[a], #132]\n\t"
  24200. "MOV r6, #0x0\n\t"
  24201. "UMLAL r12, r6, r10, r9\n\t"
  24202. "ADDS r12, r12, r7\n\t"
  24203. "STR r12, [%[a], #132]\n\t"
  24204. "ADC r6, r6, #0x0\n\t"
  24205. /* a[i+34] += m[34] * mu */
  24206. "LDR r9, [%[m], #136]\n\t"
  24207. "LDR r12, [%[a], #136]\n\t"
  24208. "MOV r7, #0x0\n\t"
  24209. "UMLAL r12, r7, r10, r9\n\t"
  24210. "ADDS r12, r12, r6\n\t"
  24211. "STR r12, [%[a], #136]\n\t"
  24212. "ADC r7, r7, #0x0\n\t"
  24213. /* a[i+35] += m[35] * mu */
  24214. "LDR r9, [%[m], #140]\n\t"
  24215. "LDR r12, [%[a], #140]\n\t"
  24216. "MOV r6, #0x0\n\t"
  24217. "UMLAL r12, r6, r10, r9\n\t"
  24218. "ADDS r12, r12, r7\n\t"
  24219. "STR r12, [%[a], #140]\n\t"
  24220. "ADC r6, r6, #0x0\n\t"
  24221. /* a[i+36] += m[36] * mu */
  24222. "LDR r9, [%[m], #144]\n\t"
  24223. "LDR r12, [%[a], #144]\n\t"
  24224. "MOV r7, #0x0\n\t"
  24225. "UMLAL r12, r7, r10, r9\n\t"
  24226. "ADDS r12, r12, r6\n\t"
  24227. "STR r12, [%[a], #144]\n\t"
  24228. "ADC r7, r7, #0x0\n\t"
  24229. /* a[i+37] += m[37] * mu */
  24230. "LDR r9, [%[m], #148]\n\t"
  24231. "LDR r12, [%[a], #148]\n\t"
  24232. "MOV r6, #0x0\n\t"
  24233. "UMLAL r12, r6, r10, r9\n\t"
  24234. "ADDS r12, r12, r7\n\t"
  24235. "STR r12, [%[a], #148]\n\t"
  24236. "ADC r6, r6, #0x0\n\t"
  24237. /* a[i+38] += m[38] * mu */
  24238. "LDR r9, [%[m], #152]\n\t"
  24239. "LDR r12, [%[a], #152]\n\t"
  24240. "MOV r7, #0x0\n\t"
  24241. "UMLAL r12, r7, r10, r9\n\t"
  24242. "ADDS r12, r12, r6\n\t"
  24243. "STR r12, [%[a], #152]\n\t"
  24244. "ADC r7, r7, #0x0\n\t"
  24245. /* a[i+39] += m[39] * mu */
  24246. "LDR r9, [%[m], #156]\n\t"
  24247. "LDR r12, [%[a], #156]\n\t"
  24248. "MOV r6, #0x0\n\t"
  24249. "UMLAL r12, r6, r10, r9\n\t"
  24250. "ADDS r12, r12, r7\n\t"
  24251. "STR r12, [%[a], #156]\n\t"
  24252. "ADC r6, r6, #0x0\n\t"
  24253. /* a[i+40] += m[40] * mu */
  24254. "LDR r9, [%[m], #160]\n\t"
  24255. "LDR r12, [%[a], #160]\n\t"
  24256. "MOV r7, #0x0\n\t"
  24257. "UMLAL r12, r7, r10, r9\n\t"
  24258. "ADDS r12, r12, r6\n\t"
  24259. "STR r12, [%[a], #160]\n\t"
  24260. "ADC r7, r7, #0x0\n\t"
  24261. /* a[i+41] += m[41] * mu */
  24262. "LDR r9, [%[m], #164]\n\t"
  24263. "LDR r12, [%[a], #164]\n\t"
  24264. "MOV r6, #0x0\n\t"
  24265. "UMLAL r12, r6, r10, r9\n\t"
  24266. "ADDS r12, r12, r7\n\t"
  24267. "STR r12, [%[a], #164]\n\t"
  24268. "ADC r6, r6, #0x0\n\t"
  24269. /* a[i+42] += m[42] * mu */
  24270. "LDR r9, [%[m], #168]\n\t"
  24271. "LDR r12, [%[a], #168]\n\t"
  24272. "MOV r7, #0x0\n\t"
  24273. "UMLAL r12, r7, r10, r9\n\t"
  24274. "ADDS r12, r12, r6\n\t"
  24275. "STR r12, [%[a], #168]\n\t"
  24276. "ADC r7, r7, #0x0\n\t"
  24277. /* a[i+43] += m[43] * mu */
  24278. "LDR r9, [%[m], #172]\n\t"
  24279. "LDR r12, [%[a], #172]\n\t"
  24280. "MOV r6, #0x0\n\t"
  24281. "UMLAL r12, r6, r10, r9\n\t"
  24282. "ADDS r12, r12, r7\n\t"
  24283. "STR r12, [%[a], #172]\n\t"
  24284. "ADC r6, r6, #0x0\n\t"
  24285. /* a[i+44] += m[44] * mu */
  24286. "LDR r9, [%[m], #176]\n\t"
  24287. "LDR r12, [%[a], #176]\n\t"
  24288. "MOV r7, #0x0\n\t"
  24289. "UMLAL r12, r7, r10, r9\n\t"
  24290. "ADDS r12, r12, r6\n\t"
  24291. "STR r12, [%[a], #176]\n\t"
  24292. "ADC r7, r7, #0x0\n\t"
  24293. /* a[i+45] += m[45] * mu */
  24294. "LDR r9, [%[m], #180]\n\t"
  24295. "LDR r12, [%[a], #180]\n\t"
  24296. "MOV r6, #0x0\n\t"
  24297. "UMLAL r12, r6, r10, r9\n\t"
  24298. "ADDS r12, r12, r7\n\t"
  24299. "STR r12, [%[a], #180]\n\t"
  24300. "ADC r6, r6, #0x0\n\t"
  24301. /* a[i+46] += m[46] * mu */
  24302. "LDR r9, [%[m], #184]\n\t"
  24303. "LDR r12, [%[a], #184]\n\t"
  24304. "MOV r7, #0x0\n\t"
  24305. "UMLAL r12, r7, r10, r9\n\t"
  24306. "ADDS r12, r12, r6\n\t"
  24307. "STR r12, [%[a], #184]\n\t"
  24308. "ADC r7, r7, #0x0\n\t"
  24309. /* a[i+47] += m[47] * mu */
  24310. "LDR r9, [%[m], #188]\n\t"
  24311. "LDR r12, [%[a], #188]\n\t"
  24312. "MOV r6, #0x0\n\t"
  24313. "UMLAL r12, r6, r10, r9\n\t"
  24314. "ADDS r12, r12, r7\n\t"
  24315. "STR r12, [%[a], #188]\n\t"
  24316. "ADC r6, r6, #0x0\n\t"
  24317. /* a[i+48] += m[48] * mu */
  24318. "LDR r9, [%[m], #192]\n\t"
  24319. "LDR r12, [%[a], #192]\n\t"
  24320. "MOV r7, #0x0\n\t"
  24321. "UMLAL r12, r7, r10, r9\n\t"
  24322. "ADDS r12, r12, r6\n\t"
  24323. "STR r12, [%[a], #192]\n\t"
  24324. "ADC r7, r7, #0x0\n\t"
  24325. /* a[i+49] += m[49] * mu */
  24326. "LDR r9, [%[m], #196]\n\t"
  24327. "LDR r12, [%[a], #196]\n\t"
  24328. "MOV r6, #0x0\n\t"
  24329. "UMLAL r12, r6, r10, r9\n\t"
  24330. "ADDS r12, r12, r7\n\t"
  24331. "STR r12, [%[a], #196]\n\t"
  24332. "ADC r6, r6, #0x0\n\t"
  24333. /* a[i+50] += m[50] * mu */
  24334. "LDR r9, [%[m], #200]\n\t"
  24335. "LDR r12, [%[a], #200]\n\t"
  24336. "MOV r7, #0x0\n\t"
  24337. "UMLAL r12, r7, r10, r9\n\t"
  24338. "ADDS r12, r12, r6\n\t"
  24339. "STR r12, [%[a], #200]\n\t"
  24340. "ADC r7, r7, #0x0\n\t"
  24341. /* a[i+51] += m[51] * mu */
  24342. "LDR r9, [%[m], #204]\n\t"
  24343. "LDR r12, [%[a], #204]\n\t"
  24344. "MOV r6, #0x0\n\t"
  24345. "UMLAL r12, r6, r10, r9\n\t"
  24346. "ADDS r12, r12, r7\n\t"
  24347. "STR r12, [%[a], #204]\n\t"
  24348. "ADC r6, r6, #0x0\n\t"
  24349. /* a[i+52] += m[52] * mu */
  24350. "LDR r9, [%[m], #208]\n\t"
  24351. "LDR r12, [%[a], #208]\n\t"
  24352. "MOV r7, #0x0\n\t"
  24353. "UMLAL r12, r7, r10, r9\n\t"
  24354. "ADDS r12, r12, r6\n\t"
  24355. "STR r12, [%[a], #208]\n\t"
  24356. "ADC r7, r7, #0x0\n\t"
  24357. /* a[i+53] += m[53] * mu */
  24358. "LDR r9, [%[m], #212]\n\t"
  24359. "LDR r12, [%[a], #212]\n\t"
  24360. "MOV r6, #0x0\n\t"
  24361. "UMLAL r12, r6, r10, r9\n\t"
  24362. "ADDS r12, r12, r7\n\t"
  24363. "STR r12, [%[a], #212]\n\t"
  24364. "ADC r6, r6, #0x0\n\t"
  24365. /* a[i+54] += m[54] * mu */
  24366. "LDR r9, [%[m], #216]\n\t"
  24367. "LDR r12, [%[a], #216]\n\t"
  24368. "MOV r7, #0x0\n\t"
  24369. "UMLAL r12, r7, r10, r9\n\t"
  24370. "ADDS r12, r12, r6\n\t"
  24371. "STR r12, [%[a], #216]\n\t"
  24372. "ADC r7, r7, #0x0\n\t"
  24373. /* a[i+55] += m[55] * mu */
  24374. "LDR r9, [%[m], #220]\n\t"
  24375. "LDR r12, [%[a], #220]\n\t"
  24376. "MOV r6, #0x0\n\t"
  24377. "UMLAL r12, r6, r10, r9\n\t"
  24378. "ADDS r12, r12, r7\n\t"
  24379. "STR r12, [%[a], #220]\n\t"
  24380. "ADC r6, r6, #0x0\n\t"
  24381. /* a[i+56] += m[56] * mu */
  24382. "LDR r9, [%[m], #224]\n\t"
  24383. "LDR r12, [%[a], #224]\n\t"
  24384. "MOV r7, #0x0\n\t"
  24385. "UMLAL r12, r7, r10, r9\n\t"
  24386. "ADDS r12, r12, r6\n\t"
  24387. "STR r12, [%[a], #224]\n\t"
  24388. "ADC r7, r7, #0x0\n\t"
  24389. /* a[i+57] += m[57] * mu */
  24390. "LDR r9, [%[m], #228]\n\t"
  24391. "LDR r12, [%[a], #228]\n\t"
  24392. "MOV r6, #0x0\n\t"
  24393. "UMLAL r12, r6, r10, r9\n\t"
  24394. "ADDS r12, r12, r7\n\t"
  24395. "STR r12, [%[a], #228]\n\t"
  24396. "ADC r6, r6, #0x0\n\t"
  24397. /* a[i+58] += m[58] * mu */
  24398. "LDR r9, [%[m], #232]\n\t"
  24399. "LDR r12, [%[a], #232]\n\t"
  24400. "MOV r7, #0x0\n\t"
  24401. "UMLAL r12, r7, r10, r9\n\t"
  24402. "ADDS r12, r12, r6\n\t"
  24403. "STR r12, [%[a], #232]\n\t"
  24404. "ADC r7, r7, #0x0\n\t"
  24405. /* a[i+59] += m[59] * mu */
  24406. "LDR r9, [%[m], #236]\n\t"
  24407. "LDR r12, [%[a], #236]\n\t"
  24408. "MOV r6, #0x0\n\t"
  24409. "UMLAL r12, r6, r10, r9\n\t"
  24410. "ADDS r12, r12, r7\n\t"
  24411. "STR r12, [%[a], #236]\n\t"
  24412. "ADC r6, r6, #0x0\n\t"
  24413. /* a[i+60] += m[60] * mu */
  24414. "LDR r9, [%[m], #240]\n\t"
  24415. "LDR r12, [%[a], #240]\n\t"
  24416. "MOV r7, #0x0\n\t"
  24417. "UMLAL r12, r7, r10, r9\n\t"
  24418. "ADDS r12, r12, r6\n\t"
  24419. "STR r12, [%[a], #240]\n\t"
  24420. "ADC r7, r7, #0x0\n\t"
  24421. /* a[i+61] += m[61] * mu */
  24422. "LDR r9, [%[m], #244]\n\t"
  24423. "LDR r12, [%[a], #244]\n\t"
  24424. "MOV r6, #0x0\n\t"
  24425. "UMLAL r12, r6, r10, r9\n\t"
  24426. "ADDS r12, r12, r7\n\t"
  24427. "STR r12, [%[a], #244]\n\t"
  24428. "ADC r6, r6, #0x0\n\t"
  24429. /* a[i+62] += m[62] * mu */
  24430. "LDR r9, [%[m], #248]\n\t"
  24431. "LDR r12, [%[a], #248]\n\t"
  24432. "MOV r7, #0x0\n\t"
  24433. "UMLAL r12, r7, r10, r9\n\t"
  24434. "ADDS r12, r12, r6\n\t"
  24435. "STR r12, [%[a], #248]\n\t"
  24436. "ADC r7, r7, #0x0\n\t"
  24437. /* a[i+63] += m[63] * mu */
  24438. "LDR r9, [%[m], #252]\n\t"
  24439. "LDR r12, [%[a], #252]\n\t"
  24440. "MOV r6, #0x0\n\t"
  24441. "UMLAL r12, r6, r10, r9\n\t"
  24442. "ADDS r12, r12, r7\n\t"
  24443. "STR r12, [%[a], #252]\n\t"
  24444. "ADC r6, r6, #0x0\n\t"
  24445. /* a[i+64] += m[64] * mu */
  24446. "LDR r9, [%[m], #256]\n\t"
  24447. "LDR r12, [%[a], #256]\n\t"
  24448. "MOV r7, #0x0\n\t"
  24449. "UMLAL r12, r7, r10, r9\n\t"
  24450. "ADDS r12, r12, r6\n\t"
  24451. "STR r12, [%[a], #256]\n\t"
  24452. "ADC r7, r7, #0x0\n\t"
  24453. /* a[i+65] += m[65] * mu */
  24454. "LDR r9, [%[m], #260]\n\t"
  24455. "LDR r12, [%[a], #260]\n\t"
  24456. "MOV r6, #0x0\n\t"
  24457. "UMLAL r12, r6, r10, r9\n\t"
  24458. "ADDS r12, r12, r7\n\t"
  24459. "STR r12, [%[a], #260]\n\t"
  24460. "ADC r6, r6, #0x0\n\t"
  24461. /* a[i+66] += m[66] * mu */
  24462. "LDR r9, [%[m], #264]\n\t"
  24463. "LDR r12, [%[a], #264]\n\t"
  24464. "MOV r7, #0x0\n\t"
  24465. "UMLAL r12, r7, r10, r9\n\t"
  24466. "ADDS r12, r12, r6\n\t"
  24467. "STR r12, [%[a], #264]\n\t"
  24468. "ADC r7, r7, #0x0\n\t"
  24469. /* a[i+67] += m[67] * mu */
  24470. "LDR r9, [%[m], #268]\n\t"
  24471. "LDR r12, [%[a], #268]\n\t"
  24472. "MOV r6, #0x0\n\t"
  24473. "UMLAL r12, r6, r10, r9\n\t"
  24474. "ADDS r12, r12, r7\n\t"
  24475. "STR r12, [%[a], #268]\n\t"
  24476. "ADC r6, r6, #0x0\n\t"
  24477. /* a[i+68] += m[68] * mu */
  24478. "LDR r9, [%[m], #272]\n\t"
  24479. "LDR r12, [%[a], #272]\n\t"
  24480. "MOV r7, #0x0\n\t"
  24481. "UMLAL r12, r7, r10, r9\n\t"
  24482. "ADDS r12, r12, r6\n\t"
  24483. "STR r12, [%[a], #272]\n\t"
  24484. "ADC r7, r7, #0x0\n\t"
  24485. /* a[i+69] += m[69] * mu */
  24486. "LDR r9, [%[m], #276]\n\t"
  24487. "LDR r12, [%[a], #276]\n\t"
  24488. "MOV r6, #0x0\n\t"
  24489. "UMLAL r12, r6, r10, r9\n\t"
  24490. "ADDS r12, r12, r7\n\t"
  24491. "STR r12, [%[a], #276]\n\t"
  24492. "ADC r6, r6, #0x0\n\t"
  24493. /* a[i+70] += m[70] * mu */
  24494. "LDR r9, [%[m], #280]\n\t"
  24495. "LDR r12, [%[a], #280]\n\t"
  24496. "MOV r7, #0x0\n\t"
  24497. "UMLAL r12, r7, r10, r9\n\t"
  24498. "ADDS r12, r12, r6\n\t"
  24499. "STR r12, [%[a], #280]\n\t"
  24500. "ADC r7, r7, #0x0\n\t"
  24501. /* a[i+71] += m[71] * mu */
  24502. "LDR r9, [%[m], #284]\n\t"
  24503. "LDR r12, [%[a], #284]\n\t"
  24504. "MOV r6, #0x0\n\t"
  24505. "UMLAL r12, r6, r10, r9\n\t"
  24506. "ADDS r12, r12, r7\n\t"
  24507. "STR r12, [%[a], #284]\n\t"
  24508. "ADC r6, r6, #0x0\n\t"
  24509. /* a[i+72] += m[72] * mu */
  24510. "LDR r9, [%[m], #288]\n\t"
  24511. "LDR r12, [%[a], #288]\n\t"
  24512. "MOV r7, #0x0\n\t"
  24513. "UMLAL r12, r7, r10, r9\n\t"
  24514. "ADDS r12, r12, r6\n\t"
  24515. "STR r12, [%[a], #288]\n\t"
  24516. "ADC r7, r7, #0x0\n\t"
  24517. /* a[i+73] += m[73] * mu */
  24518. "LDR r9, [%[m], #292]\n\t"
  24519. "LDR r12, [%[a], #292]\n\t"
  24520. "MOV r6, #0x0\n\t"
  24521. "UMLAL r12, r6, r10, r9\n\t"
  24522. "ADDS r12, r12, r7\n\t"
  24523. "STR r12, [%[a], #292]\n\t"
  24524. "ADC r6, r6, #0x0\n\t"
  24525. /* a[i+74] += m[74] * mu */
  24526. "LDR r9, [%[m], #296]\n\t"
  24527. "LDR r12, [%[a], #296]\n\t"
  24528. "MOV r7, #0x0\n\t"
  24529. "UMLAL r12, r7, r10, r9\n\t"
  24530. "ADDS r12, r12, r6\n\t"
  24531. "STR r12, [%[a], #296]\n\t"
  24532. "ADC r7, r7, #0x0\n\t"
  24533. /* a[i+75] += m[75] * mu */
  24534. "LDR r9, [%[m], #300]\n\t"
  24535. "LDR r12, [%[a], #300]\n\t"
  24536. "MOV r6, #0x0\n\t"
  24537. "UMLAL r12, r6, r10, r9\n\t"
  24538. "ADDS r12, r12, r7\n\t"
  24539. "STR r12, [%[a], #300]\n\t"
  24540. "ADC r6, r6, #0x0\n\t"
  24541. /* a[i+76] += m[76] * mu */
  24542. "LDR r9, [%[m], #304]\n\t"
  24543. "LDR r12, [%[a], #304]\n\t"
  24544. "MOV r7, #0x0\n\t"
  24545. "UMLAL r12, r7, r10, r9\n\t"
  24546. "ADDS r12, r12, r6\n\t"
  24547. "STR r12, [%[a], #304]\n\t"
  24548. "ADC r7, r7, #0x0\n\t"
  24549. /* a[i+77] += m[77] * mu */
  24550. "LDR r9, [%[m], #308]\n\t"
  24551. "LDR r12, [%[a], #308]\n\t"
  24552. "MOV r6, #0x0\n\t"
  24553. "UMLAL r12, r6, r10, r9\n\t"
  24554. "ADDS r12, r12, r7\n\t"
  24555. "STR r12, [%[a], #308]\n\t"
  24556. "ADC r6, r6, #0x0\n\t"
  24557. /* a[i+78] += m[78] * mu */
  24558. "LDR r9, [%[m], #312]\n\t"
  24559. "LDR r12, [%[a], #312]\n\t"
  24560. "MOV r7, #0x0\n\t"
  24561. "UMLAL r12, r7, r10, r9\n\t"
  24562. "ADDS r12, r12, r6\n\t"
  24563. "STR r12, [%[a], #312]\n\t"
  24564. "ADC r7, r7, #0x0\n\t"
  24565. /* a[i+79] += m[79] * mu */
  24566. "LDR r9, [%[m], #316]\n\t"
  24567. "LDR r12, [%[a], #316]\n\t"
  24568. "MOV r6, #0x0\n\t"
  24569. "UMLAL r12, r6, r10, r9\n\t"
  24570. "ADDS r12, r12, r7\n\t"
  24571. "STR r12, [%[a], #316]\n\t"
  24572. "ADC r6, r6, #0x0\n\t"
  24573. /* a[i+80] += m[80] * mu */
  24574. "LDR r9, [%[m], #320]\n\t"
  24575. "LDR r12, [%[a], #320]\n\t"
  24576. "MOV r7, #0x0\n\t"
  24577. "UMLAL r12, r7, r10, r9\n\t"
  24578. "ADDS r12, r12, r6\n\t"
  24579. "STR r12, [%[a], #320]\n\t"
  24580. "ADC r7, r7, #0x0\n\t"
  24581. /* a[i+81] += m[81] * mu */
  24582. "LDR r9, [%[m], #324]\n\t"
  24583. "LDR r12, [%[a], #324]\n\t"
  24584. "MOV r6, #0x0\n\t"
  24585. "UMLAL r12, r6, r10, r9\n\t"
  24586. "ADDS r12, r12, r7\n\t"
  24587. "STR r12, [%[a], #324]\n\t"
  24588. "ADC r6, r6, #0x0\n\t"
  24589. /* a[i+82] += m[82] * mu */
  24590. "LDR r9, [%[m], #328]\n\t"
  24591. "LDR r12, [%[a], #328]\n\t"
  24592. "MOV r7, #0x0\n\t"
  24593. "UMLAL r12, r7, r10, r9\n\t"
  24594. "ADDS r12, r12, r6\n\t"
  24595. "STR r12, [%[a], #328]\n\t"
  24596. "ADC r7, r7, #0x0\n\t"
  24597. /* a[i+83] += m[83] * mu */
  24598. "LDR r9, [%[m], #332]\n\t"
  24599. "LDR r12, [%[a], #332]\n\t"
  24600. "MOV r6, #0x0\n\t"
  24601. "UMLAL r12, r6, r10, r9\n\t"
  24602. "ADDS r12, r12, r7\n\t"
  24603. "STR r12, [%[a], #332]\n\t"
  24604. "ADC r6, r6, #0x0\n\t"
  24605. /* a[i+84] += m[84] * mu */
  24606. "LDR r9, [%[m], #336]\n\t"
  24607. "LDR r12, [%[a], #336]\n\t"
  24608. "MOV r7, #0x0\n\t"
  24609. "UMLAL r12, r7, r10, r9\n\t"
  24610. "ADDS r12, r12, r6\n\t"
  24611. "STR r12, [%[a], #336]\n\t"
  24612. "ADC r7, r7, #0x0\n\t"
  24613. /* a[i+85] += m[85] * mu */
  24614. "LDR r9, [%[m], #340]\n\t"
  24615. "LDR r12, [%[a], #340]\n\t"
  24616. "MOV r6, #0x0\n\t"
  24617. "UMLAL r12, r6, r10, r9\n\t"
  24618. "ADDS r12, r12, r7\n\t"
  24619. "STR r12, [%[a], #340]\n\t"
  24620. "ADC r6, r6, #0x0\n\t"
  24621. /* a[i+86] += m[86] * mu */
  24622. "LDR r9, [%[m], #344]\n\t"
  24623. "LDR r12, [%[a], #344]\n\t"
  24624. "MOV r7, #0x0\n\t"
  24625. "UMLAL r12, r7, r10, r9\n\t"
  24626. "ADDS r12, r12, r6\n\t"
  24627. "STR r12, [%[a], #344]\n\t"
  24628. "ADC r7, r7, #0x0\n\t"
  24629. /* a[i+87] += m[87] * mu */
  24630. "LDR r9, [%[m], #348]\n\t"
  24631. "LDR r12, [%[a], #348]\n\t"
  24632. "MOV r6, #0x0\n\t"
  24633. "UMLAL r12, r6, r10, r9\n\t"
  24634. "ADDS r12, r12, r7\n\t"
  24635. "STR r12, [%[a], #348]\n\t"
  24636. "ADC r6, r6, #0x0\n\t"
  24637. /* a[i+88] += m[88] * mu */
  24638. "LDR r9, [%[m], #352]\n\t"
  24639. "LDR r12, [%[a], #352]\n\t"
  24640. "MOV r7, #0x0\n\t"
  24641. "UMLAL r12, r7, r10, r9\n\t"
  24642. "ADDS r12, r12, r6\n\t"
  24643. "STR r12, [%[a], #352]\n\t"
  24644. "ADC r7, r7, #0x0\n\t"
  24645. /* a[i+89] += m[89] * mu */
  24646. "LDR r9, [%[m], #356]\n\t"
  24647. "LDR r12, [%[a], #356]\n\t"
  24648. "MOV r6, #0x0\n\t"
  24649. "UMLAL r12, r6, r10, r9\n\t"
  24650. "ADDS r12, r12, r7\n\t"
  24651. "STR r12, [%[a], #356]\n\t"
  24652. "ADC r6, r6, #0x0\n\t"
  24653. /* a[i+90] += m[90] * mu */
  24654. "LDR r9, [%[m], #360]\n\t"
  24655. "LDR r12, [%[a], #360]\n\t"
  24656. "MOV r7, #0x0\n\t"
  24657. "UMLAL r12, r7, r10, r9\n\t"
  24658. "ADDS r12, r12, r6\n\t"
  24659. "STR r12, [%[a], #360]\n\t"
  24660. "ADC r7, r7, #0x0\n\t"
  24661. /* a[i+91] += m[91] * mu */
  24662. "LDR r9, [%[m], #364]\n\t"
  24663. "LDR r12, [%[a], #364]\n\t"
  24664. "MOV r6, #0x0\n\t"
  24665. "UMLAL r12, r6, r10, r9\n\t"
  24666. "ADDS r12, r12, r7\n\t"
  24667. "STR r12, [%[a], #364]\n\t"
  24668. "ADC r6, r6, #0x0\n\t"
  24669. /* a[i+92] += m[92] * mu */
  24670. "LDR r9, [%[m], #368]\n\t"
  24671. "LDR r12, [%[a], #368]\n\t"
  24672. "MOV r7, #0x0\n\t"
  24673. "UMLAL r12, r7, r10, r9\n\t"
  24674. "ADDS r12, r12, r6\n\t"
  24675. "STR r12, [%[a], #368]\n\t"
  24676. "ADC r7, r7, #0x0\n\t"
  24677. /* a[i+93] += m[93] * mu */
  24678. "LDR r9, [%[m], #372]\n\t"
  24679. "LDR r12, [%[a], #372]\n\t"
  24680. "MOV r6, #0x0\n\t"
  24681. "UMLAL r12, r6, r10, r9\n\t"
  24682. "ADDS r12, r12, r7\n\t"
  24683. "STR r12, [%[a], #372]\n\t"
  24684. "ADC r6, r6, #0x0\n\t"
  24685. /* a[i+94] += m[94] * mu */
  24686. "LDR r9, [%[m], #376]\n\t"
  24687. "LDR r12, [%[a], #376]\n\t"
  24688. "MOV r7, #0x0\n\t"
  24689. "UMLAL r12, r7, r10, r9\n\t"
  24690. "ADDS r12, r12, r6\n\t"
  24691. "STR r12, [%[a], #376]\n\t"
  24692. "ADC r7, r7, #0x0\n\t"
  24693. /* a[i+95] += m[95] * mu */
  24694. "LDR r9, [%[m], #380]\n\t"
  24695. "LDR r12, [%[a], #380]\n\t"
  24696. "MOV r6, #0x0\n\t"
  24697. "UMLAL r12, r6, r10, r9\n\t"
  24698. "ADDS r12, r12, r7\n\t"
  24699. "STR r12, [%[a], #380]\n\t"
  24700. "ADC r6, r6, #0x0\n\t"
  24701. /* a[i+96] += m[96] * mu */
  24702. "LDR r9, [%[m], #384]\n\t"
  24703. "LDR r12, [%[a], #384]\n\t"
  24704. "MOV r7, #0x0\n\t"
  24705. "UMLAL r12, r7, r10, r9\n\t"
  24706. "ADDS r12, r12, r6\n\t"
  24707. "STR r12, [%[a], #384]\n\t"
  24708. "ADC r7, r7, #0x0\n\t"
  24709. /* a[i+97] += m[97] * mu */
  24710. "LDR r9, [%[m], #388]\n\t"
  24711. "LDR r12, [%[a], #388]\n\t"
  24712. "MOV r6, #0x0\n\t"
  24713. "UMLAL r12, r6, r10, r9\n\t"
  24714. "ADDS r12, r12, r7\n\t"
  24715. "STR r12, [%[a], #388]\n\t"
  24716. "ADC r6, r6, #0x0\n\t"
  24717. /* a[i+98] += m[98] * mu */
  24718. "LDR r9, [%[m], #392]\n\t"
  24719. "LDR r12, [%[a], #392]\n\t"
  24720. "MOV r7, #0x0\n\t"
  24721. "UMLAL r12, r7, r10, r9\n\t"
  24722. "ADDS r12, r12, r6\n\t"
  24723. "STR r12, [%[a], #392]\n\t"
  24724. "ADC r7, r7, #0x0\n\t"
  24725. /* a[i+99] += m[99] * mu */
  24726. "LDR r9, [%[m], #396]\n\t"
  24727. "LDR r12, [%[a], #396]\n\t"
  24728. "MOV r6, #0x0\n\t"
  24729. "UMLAL r12, r6, r10, r9\n\t"
  24730. "ADDS r12, r12, r7\n\t"
  24731. "STR r12, [%[a], #396]\n\t"
  24732. "ADC r6, r6, #0x0\n\t"
  24733. /* a[i+100] += m[100] * mu */
  24734. "LDR r9, [%[m], #400]\n\t"
  24735. "LDR r12, [%[a], #400]\n\t"
  24736. "MOV r7, #0x0\n\t"
  24737. "UMLAL r12, r7, r10, r9\n\t"
  24738. "ADDS r12, r12, r6\n\t"
  24739. "STR r12, [%[a], #400]\n\t"
  24740. "ADC r7, r7, #0x0\n\t"
  24741. /* a[i+101] += m[101] * mu */
  24742. "LDR r9, [%[m], #404]\n\t"
  24743. "LDR r12, [%[a], #404]\n\t"
  24744. "MOV r6, #0x0\n\t"
  24745. "UMLAL r12, r6, r10, r9\n\t"
  24746. "ADDS r12, r12, r7\n\t"
  24747. "STR r12, [%[a], #404]\n\t"
  24748. "ADC r6, r6, #0x0\n\t"
  24749. /* a[i+102] += m[102] * mu */
  24750. "LDR r9, [%[m], #408]\n\t"
  24751. "LDR r12, [%[a], #408]\n\t"
  24752. "MOV r7, #0x0\n\t"
  24753. "UMLAL r12, r7, r10, r9\n\t"
  24754. "ADDS r12, r12, r6\n\t"
  24755. "STR r12, [%[a], #408]\n\t"
  24756. "ADC r7, r7, #0x0\n\t"
  24757. /* a[i+103] += m[103] * mu */
  24758. "LDR r9, [%[m], #412]\n\t"
  24759. "LDR r12, [%[a], #412]\n\t"
  24760. "MOV r6, #0x0\n\t"
  24761. "UMLAL r12, r6, r10, r9\n\t"
  24762. "ADDS r12, r12, r7\n\t"
  24763. "STR r12, [%[a], #412]\n\t"
  24764. "ADC r6, r6, #0x0\n\t"
  24765. /* a[i+104] += m[104] * mu */
  24766. "LDR r9, [%[m], #416]\n\t"
  24767. "LDR r12, [%[a], #416]\n\t"
  24768. "MOV r7, #0x0\n\t"
  24769. "UMLAL r12, r7, r10, r9\n\t"
  24770. "ADDS r12, r12, r6\n\t"
  24771. "STR r12, [%[a], #416]\n\t"
  24772. "ADC r7, r7, #0x0\n\t"
  24773. /* a[i+105] += m[105] * mu */
  24774. "LDR r9, [%[m], #420]\n\t"
  24775. "LDR r12, [%[a], #420]\n\t"
  24776. "MOV r6, #0x0\n\t"
  24777. "UMLAL r12, r6, r10, r9\n\t"
  24778. "ADDS r12, r12, r7\n\t"
  24779. "STR r12, [%[a], #420]\n\t"
  24780. "ADC r6, r6, #0x0\n\t"
  24781. /* a[i+106] += m[106] * mu */
  24782. "LDR r9, [%[m], #424]\n\t"
  24783. "LDR r12, [%[a], #424]\n\t"
  24784. "MOV r7, #0x0\n\t"
  24785. "UMLAL r12, r7, r10, r9\n\t"
  24786. "ADDS r12, r12, r6\n\t"
  24787. "STR r12, [%[a], #424]\n\t"
  24788. "ADC r7, r7, #0x0\n\t"
  24789. /* a[i+107] += m[107] * mu */
  24790. "LDR r9, [%[m], #428]\n\t"
  24791. "LDR r12, [%[a], #428]\n\t"
  24792. "MOV r6, #0x0\n\t"
  24793. "UMLAL r12, r6, r10, r9\n\t"
  24794. "ADDS r12, r12, r7\n\t"
  24795. "STR r12, [%[a], #428]\n\t"
  24796. "ADC r6, r6, #0x0\n\t"
  24797. /* a[i+108] += m[108] * mu */
  24798. "LDR r9, [%[m], #432]\n\t"
  24799. "LDR r12, [%[a], #432]\n\t"
  24800. "MOV r7, #0x0\n\t"
  24801. "UMLAL r12, r7, r10, r9\n\t"
  24802. "ADDS r12, r12, r6\n\t"
  24803. "STR r12, [%[a], #432]\n\t"
  24804. "ADC r7, r7, #0x0\n\t"
  24805. /* a[i+109] += m[109] * mu */
  24806. "LDR r9, [%[m], #436]\n\t"
  24807. "LDR r12, [%[a], #436]\n\t"
  24808. "MOV r6, #0x0\n\t"
  24809. "UMLAL r12, r6, r10, r9\n\t"
  24810. "ADDS r12, r12, r7\n\t"
  24811. "STR r12, [%[a], #436]\n\t"
  24812. "ADC r6, r6, #0x0\n\t"
  24813. /* a[i+110] += m[110] * mu */
  24814. "LDR r9, [%[m], #440]\n\t"
  24815. "LDR r12, [%[a], #440]\n\t"
  24816. "MOV r7, #0x0\n\t"
  24817. "UMLAL r12, r7, r10, r9\n\t"
  24818. "ADDS r12, r12, r6\n\t"
  24819. "STR r12, [%[a], #440]\n\t"
  24820. "ADC r7, r7, #0x0\n\t"
  24821. /* a[i+111] += m[111] * mu */
  24822. "LDR r9, [%[m], #444]\n\t"
  24823. "LDR r12, [%[a], #444]\n\t"
  24824. "MOV r6, #0x0\n\t"
  24825. "UMLAL r12, r6, r10, r9\n\t"
  24826. "ADDS r12, r12, r7\n\t"
  24827. "STR r12, [%[a], #444]\n\t"
  24828. "ADC r6, r6, #0x0\n\t"
  24829. /* a[i+112] += m[112] * mu */
  24830. "LDR r9, [%[m], #448]\n\t"
  24831. "LDR r12, [%[a], #448]\n\t"
  24832. "MOV r7, #0x0\n\t"
  24833. "UMLAL r12, r7, r10, r9\n\t"
  24834. "ADDS r12, r12, r6\n\t"
  24835. "STR r12, [%[a], #448]\n\t"
  24836. "ADC r7, r7, #0x0\n\t"
  24837. /* a[i+113] += m[113] * mu */
  24838. "LDR r9, [%[m], #452]\n\t"
  24839. "LDR r12, [%[a], #452]\n\t"
  24840. "MOV r6, #0x0\n\t"
  24841. "UMLAL r12, r6, r10, r9\n\t"
  24842. "ADDS r12, r12, r7\n\t"
  24843. "STR r12, [%[a], #452]\n\t"
  24844. "ADC r6, r6, #0x0\n\t"
  24845. /* a[i+114] += m[114] * mu */
  24846. "LDR r9, [%[m], #456]\n\t"
  24847. "LDR r12, [%[a], #456]\n\t"
  24848. "MOV r7, #0x0\n\t"
  24849. "UMLAL r12, r7, r10, r9\n\t"
  24850. "ADDS r12, r12, r6\n\t"
  24851. "STR r12, [%[a], #456]\n\t"
  24852. "ADC r7, r7, #0x0\n\t"
  24853. /* a[i+115] += m[115] * mu */
  24854. "LDR r9, [%[m], #460]\n\t"
  24855. "LDR r12, [%[a], #460]\n\t"
  24856. "MOV r6, #0x0\n\t"
  24857. "UMLAL r12, r6, r10, r9\n\t"
  24858. "ADDS r12, r12, r7\n\t"
  24859. "STR r12, [%[a], #460]\n\t"
  24860. "ADC r6, r6, #0x0\n\t"
  24861. /* a[i+116] += m[116] * mu */
  24862. "LDR r9, [%[m], #464]\n\t"
  24863. "LDR r12, [%[a], #464]\n\t"
  24864. "MOV r7, #0x0\n\t"
  24865. "UMLAL r12, r7, r10, r9\n\t"
  24866. "ADDS r12, r12, r6\n\t"
  24867. "STR r12, [%[a], #464]\n\t"
  24868. "ADC r7, r7, #0x0\n\t"
  24869. /* a[i+117] += m[117] * mu */
  24870. "LDR r9, [%[m], #468]\n\t"
  24871. "LDR r12, [%[a], #468]\n\t"
  24872. "MOV r6, #0x0\n\t"
  24873. "UMLAL r12, r6, r10, r9\n\t"
  24874. "ADDS r12, r12, r7\n\t"
  24875. "STR r12, [%[a], #468]\n\t"
  24876. "ADC r6, r6, #0x0\n\t"
  24877. /* a[i+118] += m[118] * mu */
  24878. "LDR r9, [%[m], #472]\n\t"
  24879. "LDR r12, [%[a], #472]\n\t"
  24880. "MOV r7, #0x0\n\t"
  24881. "UMLAL r12, r7, r10, r9\n\t"
  24882. "ADDS r12, r12, r6\n\t"
  24883. "STR r12, [%[a], #472]\n\t"
  24884. "ADC r7, r7, #0x0\n\t"
  24885. /* a[i+119] += m[119] * mu */
  24886. "LDR r9, [%[m], #476]\n\t"
  24887. "LDR r12, [%[a], #476]\n\t"
  24888. "MOV r6, #0x0\n\t"
  24889. "UMLAL r12, r6, r10, r9\n\t"
  24890. "ADDS r12, r12, r7\n\t"
  24891. "STR r12, [%[a], #476]\n\t"
  24892. "ADC r6, r6, #0x0\n\t"
  24893. /* a[i+120] += m[120] * mu */
  24894. "LDR r9, [%[m], #480]\n\t"
  24895. "LDR r12, [%[a], #480]\n\t"
  24896. "MOV r7, #0x0\n\t"
  24897. "UMLAL r12, r7, r10, r9\n\t"
  24898. "ADDS r12, r12, r6\n\t"
  24899. "STR r12, [%[a], #480]\n\t"
  24900. "ADC r7, r7, #0x0\n\t"
  24901. /* a[i+121] += m[121] * mu */
  24902. "LDR r9, [%[m], #484]\n\t"
  24903. "LDR r12, [%[a], #484]\n\t"
  24904. "MOV r6, #0x0\n\t"
  24905. "UMLAL r12, r6, r10, r9\n\t"
  24906. "ADDS r12, r12, r7\n\t"
  24907. "STR r12, [%[a], #484]\n\t"
  24908. "ADC r6, r6, #0x0\n\t"
  24909. /* a[i+122] += m[122] * mu */
  24910. "LDR r9, [%[m], #488]\n\t"
  24911. "LDR r12, [%[a], #488]\n\t"
  24912. "MOV r7, #0x0\n\t"
  24913. "UMLAL r12, r7, r10, r9\n\t"
  24914. "ADDS r12, r12, r6\n\t"
  24915. "STR r12, [%[a], #488]\n\t"
  24916. "ADC r7, r7, #0x0\n\t"
  24917. /* a[i+123] += m[123] * mu */
  24918. "LDR r9, [%[m], #492]\n\t"
  24919. "LDR r12, [%[a], #492]\n\t"
  24920. "MOV r6, #0x0\n\t"
  24921. "UMLAL r12, r6, r10, r9\n\t"
  24922. "ADDS r12, r12, r7\n\t"
  24923. "STR r12, [%[a], #492]\n\t"
  24924. "ADC r6, r6, #0x0\n\t"
  24925. /* a[i+124] += m[124] * mu */
  24926. "LDR r9, [%[m], #496]\n\t"
  24927. "LDR r12, [%[a], #496]\n\t"
  24928. "MOV r7, #0x0\n\t"
  24929. "UMLAL r12, r7, r10, r9\n\t"
  24930. "ADDS r12, r12, r6\n\t"
  24931. "STR r12, [%[a], #496]\n\t"
  24932. "ADC r7, r7, #0x0\n\t"
  24933. /* a[i+125] += m[125] * mu */
  24934. "LDR r9, [%[m], #500]\n\t"
  24935. "LDR r12, [%[a], #500]\n\t"
  24936. "MOV r6, #0x0\n\t"
  24937. "UMLAL r12, r6, r10, r9\n\t"
  24938. "ADDS r12, r12, r7\n\t"
  24939. "STR r12, [%[a], #500]\n\t"
  24940. "ADC r6, r6, #0x0\n\t"
  24941. /* a[i+126] += m[126] * mu */
  24942. "LDR r9, [%[m], #504]\n\t"
  24943. "LDR r12, [%[a], #504]\n\t"
  24944. "MOV r7, #0x0\n\t"
  24945. "UMLAL r12, r7, r10, r9\n\t"
  24946. "ADDS r12, r12, r6\n\t"
  24947. "STR r12, [%[a], #504]\n\t"
  24948. "ADC r7, r7, #0x0\n\t"
  24949. /* a[i+127] += m[127] * mu */
  24950. "LDR r9, [%[m], #508]\n\t"
  24951. "LDR r12, [%[a], #508]\n\t"
  24952. "UMULL r8, r9, r10, r9\n\t"
  24953. "ADDS r7, r7, r8\n\t"
  24954. "ADCS r6, r9, r3\n\t"
  24955. "MOV r3, #0x0\n\t"
  24956. "ADC r3, r3, r3\n\t"
  24957. "ADDS r12, r12, r7\n\t"
  24958. "STR r12, [%[a], #508]\n\t"
  24959. "LDR r12, [%[a], #512]\n\t"
  24960. "ADCS r12, r12, r6\n\t"
  24961. "STR r12, [%[a], #512]\n\t"
  24962. "ADC r3, r3, #0x0\n\t"
  24963. /* i += 1 */
  24964. "ADD r11, r11, #0x4\n\t"
  24965. "ADD %[a], %[a], #0x4\n\t"
  24966. "CMP r11, #0x200\n\t"
  24967. #ifdef __GNUC__
  24968. "BLT L_sp_4096_mont_reduce_128_word\n\t"
  24969. #else
  24970. "BLT.W L_sp_4096_mont_reduce_128_word\n\t"
  24971. #endif
  24972. /* Loop Done */
  24973. "STR r4, [%[a]]\n\t"
  24974. "STR r5, [%[a], #4]\n\t"
  24975. "MOV %[mp], r3\n\t"
  24976. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  24977. :
  24978. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  24979. );
  24980. sp_4096_cond_sub_128(a - 128, a, m, (sp_digit)0 - mp);
  24981. }
  24982. #else
  24983. /* Reduce the number back to 4096 bits using Montgomery reduction.
  24984. *
  24985. * a A single precision number to reduce in place.
  24986. * m The single precision number representing the modulus.
  24987. * mp The digit representing the negative inverse of m mod 2^n.
  24988. */
  24989. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  24990. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  24991. #else
  24992. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, sp_digit mp)
  24993. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  24994. {
  24995. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  24996. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  24997. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  24998. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  24999. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25000. __asm__ __volatile__ (
  25001. "LDR r11, [%[m]]\n\t"
  25002. /* i = 0 */
  25003. "MOV r9, #0x0\n\t"
  25004. /* ca = 0 */
  25005. "MOV r3, #0x0\n\t"
  25006. "\n"
  25007. "L_sp_4096_mont_reduce_128_word:\n\t"
  25008. /* mu = a[i] * mp */
  25009. "LDR r10, [%[a]]\n\t"
  25010. "MUL r8, %[mp], r10\n\t"
  25011. /* j = 0 */
  25012. "MOV r12, #0x0\n\t"
  25013. "MOV r4, #0x0\n\t"
  25014. "\n"
  25015. "L_sp_4096_mont_reduce_128_mul:\n\t"
  25016. /* a[i+j+0] += m[j+0] * mu */
  25017. "LDR r7, [%[m], r12]\n\t"
  25018. "LDR r10, [%[a], r12]\n\t"
  25019. "MOV r5, #0x0\n\t"
  25020. "UMLAL r10, r5, r8, r7\n\t"
  25021. "ADDS r10, r10, r4\n\t"
  25022. "STR r10, [%[a], r12]\n\t"
  25023. "ADC r4, r5, #0x0\n\t"
  25024. /* j += 1 */
  25025. "ADD r12, r12, #0x4\n\t"
  25026. /* a[i+j+1] += m[j+1] * mu */
  25027. "LDR r7, [%[m], r12]\n\t"
  25028. "LDR r10, [%[a], r12]\n\t"
  25029. "MOV r5, #0x0\n\t"
  25030. "UMLAL r10, r5, r8, r7\n\t"
  25031. "ADDS r10, r10, r4\n\t"
  25032. "STR r10, [%[a], r12]\n\t"
  25033. "ADC r4, r5, #0x0\n\t"
  25034. /* j += 1 */
  25035. "ADD r12, r12, #0x4\n\t"
  25036. /* a[i+j+2] += m[j+2] * mu */
  25037. "LDR r7, [%[m], r12]\n\t"
  25038. "LDR r10, [%[a], r12]\n\t"
  25039. "MOV r5, #0x0\n\t"
  25040. "UMLAL r10, r5, r8, r7\n\t"
  25041. "ADDS r10, r10, r4\n\t"
  25042. "STR r10, [%[a], r12]\n\t"
  25043. "ADC r4, r5, #0x0\n\t"
  25044. /* j += 1 */
  25045. "ADD r12, r12, #0x4\n\t"
  25046. /* a[i+j+3] += m[j+3] * mu */
  25047. "LDR r7, [%[m], r12]\n\t"
  25048. "LDR r10, [%[a], r12]\n\t"
  25049. "MOV r5, #0x0\n\t"
  25050. "UMLAL r10, r5, r8, r7\n\t"
  25051. "ADDS r10, r10, r4\n\t"
  25052. "STR r10, [%[a], r12]\n\t"
  25053. "ADC r4, r5, #0x0\n\t"
  25054. /* j += 1 */
  25055. "ADD r12, r12, #0x4\n\t"
  25056. "CMP r12, #0x200\n\t"
  25057. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  25058. "BLT L_sp_4096_mont_reduce_128_mul\n\t"
  25059. #else
  25060. "BLT.N L_sp_4096_mont_reduce_128_mul\n\t"
  25061. #endif
  25062. "LDR r10, [%[a], #512]\n\t"
  25063. "ADDS r4, r4, r3\n\t"
  25064. "MOV r3, #0x0\n\t"
  25065. "ADC r3, r3, #0x0\n\t"
  25066. "ADDS r10, r10, r4\n\t"
  25067. "ADC r3, r3, r3\n\t"
  25068. "STR r10, [%[a], #512]\n\t"
  25069. /* i += 1 */
  25070. "ADD r9, r9, #0x4\n\t"
  25071. "ADD %[a], %[a], #0x4\n\t"
  25072. "CMP r9, #0x200\n\t"
  25073. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  25074. "BLT L_sp_4096_mont_reduce_128_word\n\t"
  25075. #else
  25076. "BLT.N L_sp_4096_mont_reduce_128_word\n\t"
  25077. #endif
  25078. /* Loop Done */
  25079. "MOV %[mp], r3\n\t"
  25080. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  25081. :
  25082. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  25083. );
  25084. sp_4096_cond_sub_128(a - 128, a, m, (sp_digit)0 - mp);
  25085. }
  25086. #endif /* !WOLFSSL_SP_SMALL */
  25087. #else
  25088. #ifndef WOLFSSL_SP_SMALL
  25089. /* Reduce the number back to 4096 bits using Montgomery reduction.
  25090. *
  25091. * a A single precision number to reduce in place.
  25092. * m The single precision number representing the modulus.
  25093. * mp The digit representing the negative inverse of m mod 2^n.
  25094. */
  25095. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25096. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  25097. #else
  25098. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, sp_digit mp)
  25099. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25100. {
  25101. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25102. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  25103. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  25104. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  25105. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25106. __asm__ __volatile__ (
  25107. /* i = 0 */
  25108. "MOV r4, #0x0\n\t"
  25109. "MOV r5, #0x0\n\t"
  25110. "LDR r6, [%[a]]\n\t"
  25111. "LDR r7, [%[a], #4]\n\t"
  25112. "LDR r8, [%[a], #8]\n\t"
  25113. "LDR r9, [%[a], #12]\n\t"
  25114. "LDR r10, [%[a], #16]\n\t"
  25115. "\n"
  25116. "L_sp_4096_mont_reduce_128_word:\n\t"
  25117. /* mu = a[i] * mp */
  25118. "MUL lr, %[mp], r6\n\t"
  25119. /* a[i+0] += m[0] * mu */
  25120. "LDR r12, [%[m]]\n\t"
  25121. "MOV r3, #0x0\n\t"
  25122. "UMAAL r6, r3, lr, r12\n\t"
  25123. /* a[i+1] += m[1] * mu */
  25124. "LDR r12, [%[m], #4]\n\t"
  25125. "MOV r6, r7\n\t"
  25126. "UMAAL r6, r3, lr, r12\n\t"
  25127. /* a[i+2] += m[2] * mu */
  25128. "LDR r12, [%[m], #8]\n\t"
  25129. "MOV r7, r8\n\t"
  25130. "UMAAL r7, r3, lr, r12\n\t"
  25131. /* a[i+3] += m[3] * mu */
  25132. "LDR r12, [%[m], #12]\n\t"
  25133. "MOV r8, r9\n\t"
  25134. "UMAAL r8, r3, lr, r12\n\t"
  25135. /* a[i+4] += m[4] * mu */
  25136. "LDR r12, [%[m], #16]\n\t"
  25137. "MOV r9, r10\n\t"
  25138. "UMAAL r9, r3, lr, r12\n\t"
  25139. /* a[i+5] += m[5] * mu */
  25140. "LDR r12, [%[m], #20]\n\t"
  25141. "LDR r10, [%[a], #20]\n\t"
  25142. "UMAAL r10, r3, lr, r12\n\t"
  25143. /* a[i+6] += m[6] * mu */
  25144. "LDR r12, [%[m], #24]\n\t"
  25145. "LDR r11, [%[a], #24]\n\t"
  25146. "UMAAL r11, r3, lr, r12\n\t"
  25147. "STR r11, [%[a], #24]\n\t"
  25148. /* a[i+7] += m[7] * mu */
  25149. "LDR r12, [%[m], #28]\n\t"
  25150. "LDR r11, [%[a], #28]\n\t"
  25151. "UMAAL r11, r3, lr, r12\n\t"
  25152. "STR r11, [%[a], #28]\n\t"
  25153. /* a[i+8] += m[8] * mu */
  25154. "LDR r12, [%[m], #32]\n\t"
  25155. "LDR r11, [%[a], #32]\n\t"
  25156. "UMAAL r11, r3, lr, r12\n\t"
  25157. "STR r11, [%[a], #32]\n\t"
  25158. /* a[i+9] += m[9] * mu */
  25159. "LDR r12, [%[m], #36]\n\t"
  25160. "LDR r11, [%[a], #36]\n\t"
  25161. "UMAAL r11, r3, lr, r12\n\t"
  25162. "STR r11, [%[a], #36]\n\t"
  25163. /* a[i+10] += m[10] * mu */
  25164. "LDR r12, [%[m], #40]\n\t"
  25165. "LDR r11, [%[a], #40]\n\t"
  25166. "UMAAL r11, r3, lr, r12\n\t"
  25167. "STR r11, [%[a], #40]\n\t"
  25168. /* a[i+11] += m[11] * mu */
  25169. "LDR r12, [%[m], #44]\n\t"
  25170. "LDR r11, [%[a], #44]\n\t"
  25171. "UMAAL r11, r3, lr, r12\n\t"
  25172. "STR r11, [%[a], #44]\n\t"
  25173. /* a[i+12] += m[12] * mu */
  25174. "LDR r12, [%[m], #48]\n\t"
  25175. "LDR r11, [%[a], #48]\n\t"
  25176. "UMAAL r11, r3, lr, r12\n\t"
  25177. "STR r11, [%[a], #48]\n\t"
  25178. /* a[i+13] += m[13] * mu */
  25179. "LDR r12, [%[m], #52]\n\t"
  25180. "LDR r11, [%[a], #52]\n\t"
  25181. "UMAAL r11, r3, lr, r12\n\t"
  25182. "STR r11, [%[a], #52]\n\t"
  25183. /* a[i+14] += m[14] * mu */
  25184. "LDR r12, [%[m], #56]\n\t"
  25185. "LDR r11, [%[a], #56]\n\t"
  25186. "UMAAL r11, r3, lr, r12\n\t"
  25187. "STR r11, [%[a], #56]\n\t"
  25188. /* a[i+15] += m[15] * mu */
  25189. "LDR r12, [%[m], #60]\n\t"
  25190. "LDR r11, [%[a], #60]\n\t"
  25191. "UMAAL r11, r3, lr, r12\n\t"
  25192. "STR r11, [%[a], #60]\n\t"
  25193. /* a[i+16] += m[16] * mu */
  25194. "LDR r12, [%[m], #64]\n\t"
  25195. "LDR r11, [%[a], #64]\n\t"
  25196. "UMAAL r11, r3, lr, r12\n\t"
  25197. "STR r11, [%[a], #64]\n\t"
  25198. /* a[i+17] += m[17] * mu */
  25199. "LDR r12, [%[m], #68]\n\t"
  25200. "LDR r11, [%[a], #68]\n\t"
  25201. "UMAAL r11, r3, lr, r12\n\t"
  25202. "STR r11, [%[a], #68]\n\t"
  25203. /* a[i+18] += m[18] * mu */
  25204. "LDR r12, [%[m], #72]\n\t"
  25205. "LDR r11, [%[a], #72]\n\t"
  25206. "UMAAL r11, r3, lr, r12\n\t"
  25207. "STR r11, [%[a], #72]\n\t"
  25208. /* a[i+19] += m[19] * mu */
  25209. "LDR r12, [%[m], #76]\n\t"
  25210. "LDR r11, [%[a], #76]\n\t"
  25211. "UMAAL r11, r3, lr, r12\n\t"
  25212. "STR r11, [%[a], #76]\n\t"
  25213. /* a[i+20] += m[20] * mu */
  25214. "LDR r12, [%[m], #80]\n\t"
  25215. "LDR r11, [%[a], #80]\n\t"
  25216. "UMAAL r11, r3, lr, r12\n\t"
  25217. "STR r11, [%[a], #80]\n\t"
  25218. /* a[i+21] += m[21] * mu */
  25219. "LDR r12, [%[m], #84]\n\t"
  25220. "LDR r11, [%[a], #84]\n\t"
  25221. "UMAAL r11, r3, lr, r12\n\t"
  25222. "STR r11, [%[a], #84]\n\t"
  25223. /* a[i+22] += m[22] * mu */
  25224. "LDR r12, [%[m], #88]\n\t"
  25225. "LDR r11, [%[a], #88]\n\t"
  25226. "UMAAL r11, r3, lr, r12\n\t"
  25227. "STR r11, [%[a], #88]\n\t"
  25228. /* a[i+23] += m[23] * mu */
  25229. "LDR r12, [%[m], #92]\n\t"
  25230. "LDR r11, [%[a], #92]\n\t"
  25231. "UMAAL r11, r3, lr, r12\n\t"
  25232. "STR r11, [%[a], #92]\n\t"
  25233. /* a[i+24] += m[24] * mu */
  25234. "LDR r12, [%[m], #96]\n\t"
  25235. "LDR r11, [%[a], #96]\n\t"
  25236. "UMAAL r11, r3, lr, r12\n\t"
  25237. "STR r11, [%[a], #96]\n\t"
  25238. /* a[i+25] += m[25] * mu */
  25239. "LDR r12, [%[m], #100]\n\t"
  25240. "LDR r11, [%[a], #100]\n\t"
  25241. "UMAAL r11, r3, lr, r12\n\t"
  25242. "STR r11, [%[a], #100]\n\t"
  25243. /* a[i+26] += m[26] * mu */
  25244. "LDR r12, [%[m], #104]\n\t"
  25245. "LDR r11, [%[a], #104]\n\t"
  25246. "UMAAL r11, r3, lr, r12\n\t"
  25247. "STR r11, [%[a], #104]\n\t"
  25248. /* a[i+27] += m[27] * mu */
  25249. "LDR r12, [%[m], #108]\n\t"
  25250. "LDR r11, [%[a], #108]\n\t"
  25251. "UMAAL r11, r3, lr, r12\n\t"
  25252. "STR r11, [%[a], #108]\n\t"
  25253. /* a[i+28] += m[28] * mu */
  25254. "LDR r12, [%[m], #112]\n\t"
  25255. "LDR r11, [%[a], #112]\n\t"
  25256. "UMAAL r11, r3, lr, r12\n\t"
  25257. "STR r11, [%[a], #112]\n\t"
  25258. /* a[i+29] += m[29] * mu */
  25259. "LDR r12, [%[m], #116]\n\t"
  25260. "LDR r11, [%[a], #116]\n\t"
  25261. "UMAAL r11, r3, lr, r12\n\t"
  25262. "STR r11, [%[a], #116]\n\t"
  25263. /* a[i+30] += m[30] * mu */
  25264. "LDR r12, [%[m], #120]\n\t"
  25265. "LDR r11, [%[a], #120]\n\t"
  25266. "UMAAL r11, r3, lr, r12\n\t"
  25267. "STR r11, [%[a], #120]\n\t"
  25268. /* a[i+31] += m[31] * mu */
  25269. "LDR r12, [%[m], #124]\n\t"
  25270. "LDR r11, [%[a], #124]\n\t"
  25271. "UMAAL r11, r3, lr, r12\n\t"
  25272. "STR r11, [%[a], #124]\n\t"
  25273. /* a[i+32] += m[32] * mu */
  25274. "LDR r12, [%[m], #128]\n\t"
  25275. "LDR r11, [%[a], #128]\n\t"
  25276. "UMAAL r11, r3, lr, r12\n\t"
  25277. "STR r11, [%[a], #128]\n\t"
  25278. /* a[i+33] += m[33] * mu */
  25279. "LDR r12, [%[m], #132]\n\t"
  25280. "LDR r11, [%[a], #132]\n\t"
  25281. "UMAAL r11, r3, lr, r12\n\t"
  25282. "STR r11, [%[a], #132]\n\t"
  25283. /* a[i+34] += m[34] * mu */
  25284. "LDR r12, [%[m], #136]\n\t"
  25285. "LDR r11, [%[a], #136]\n\t"
  25286. "UMAAL r11, r3, lr, r12\n\t"
  25287. "STR r11, [%[a], #136]\n\t"
  25288. /* a[i+35] += m[35] * mu */
  25289. "LDR r12, [%[m], #140]\n\t"
  25290. "LDR r11, [%[a], #140]\n\t"
  25291. "UMAAL r11, r3, lr, r12\n\t"
  25292. "STR r11, [%[a], #140]\n\t"
  25293. /* a[i+36] += m[36] * mu */
  25294. "LDR r12, [%[m], #144]\n\t"
  25295. "LDR r11, [%[a], #144]\n\t"
  25296. "UMAAL r11, r3, lr, r12\n\t"
  25297. "STR r11, [%[a], #144]\n\t"
  25298. /* a[i+37] += m[37] * mu */
  25299. "LDR r12, [%[m], #148]\n\t"
  25300. "LDR r11, [%[a], #148]\n\t"
  25301. "UMAAL r11, r3, lr, r12\n\t"
  25302. "STR r11, [%[a], #148]\n\t"
  25303. /* a[i+38] += m[38] * mu */
  25304. "LDR r12, [%[m], #152]\n\t"
  25305. "LDR r11, [%[a], #152]\n\t"
  25306. "UMAAL r11, r3, lr, r12\n\t"
  25307. "STR r11, [%[a], #152]\n\t"
  25308. /* a[i+39] += m[39] * mu */
  25309. "LDR r12, [%[m], #156]\n\t"
  25310. "LDR r11, [%[a], #156]\n\t"
  25311. "UMAAL r11, r3, lr, r12\n\t"
  25312. "STR r11, [%[a], #156]\n\t"
  25313. /* a[i+40] += m[40] * mu */
  25314. "LDR r12, [%[m], #160]\n\t"
  25315. "LDR r11, [%[a], #160]\n\t"
  25316. "UMAAL r11, r3, lr, r12\n\t"
  25317. "STR r11, [%[a], #160]\n\t"
  25318. /* a[i+41] += m[41] * mu */
  25319. "LDR r12, [%[m], #164]\n\t"
  25320. "LDR r11, [%[a], #164]\n\t"
  25321. "UMAAL r11, r3, lr, r12\n\t"
  25322. "STR r11, [%[a], #164]\n\t"
  25323. /* a[i+42] += m[42] * mu */
  25324. "LDR r12, [%[m], #168]\n\t"
  25325. "LDR r11, [%[a], #168]\n\t"
  25326. "UMAAL r11, r3, lr, r12\n\t"
  25327. "STR r11, [%[a], #168]\n\t"
  25328. /* a[i+43] += m[43] * mu */
  25329. "LDR r12, [%[m], #172]\n\t"
  25330. "LDR r11, [%[a], #172]\n\t"
  25331. "UMAAL r11, r3, lr, r12\n\t"
  25332. "STR r11, [%[a], #172]\n\t"
  25333. /* a[i+44] += m[44] * mu */
  25334. "LDR r12, [%[m], #176]\n\t"
  25335. "LDR r11, [%[a], #176]\n\t"
  25336. "UMAAL r11, r3, lr, r12\n\t"
  25337. "STR r11, [%[a], #176]\n\t"
  25338. /* a[i+45] += m[45] * mu */
  25339. "LDR r12, [%[m], #180]\n\t"
  25340. "LDR r11, [%[a], #180]\n\t"
  25341. "UMAAL r11, r3, lr, r12\n\t"
  25342. "STR r11, [%[a], #180]\n\t"
  25343. /* a[i+46] += m[46] * mu */
  25344. "LDR r12, [%[m], #184]\n\t"
  25345. "LDR r11, [%[a], #184]\n\t"
  25346. "UMAAL r11, r3, lr, r12\n\t"
  25347. "STR r11, [%[a], #184]\n\t"
  25348. /* a[i+47] += m[47] * mu */
  25349. "LDR r12, [%[m], #188]\n\t"
  25350. "LDR r11, [%[a], #188]\n\t"
  25351. "UMAAL r11, r3, lr, r12\n\t"
  25352. "STR r11, [%[a], #188]\n\t"
  25353. /* a[i+48] += m[48] * mu */
  25354. "LDR r12, [%[m], #192]\n\t"
  25355. "LDR r11, [%[a], #192]\n\t"
  25356. "UMAAL r11, r3, lr, r12\n\t"
  25357. "STR r11, [%[a], #192]\n\t"
  25358. /* a[i+49] += m[49] * mu */
  25359. "LDR r12, [%[m], #196]\n\t"
  25360. "LDR r11, [%[a], #196]\n\t"
  25361. "UMAAL r11, r3, lr, r12\n\t"
  25362. "STR r11, [%[a], #196]\n\t"
  25363. /* a[i+50] += m[50] * mu */
  25364. "LDR r12, [%[m], #200]\n\t"
  25365. "LDR r11, [%[a], #200]\n\t"
  25366. "UMAAL r11, r3, lr, r12\n\t"
  25367. "STR r11, [%[a], #200]\n\t"
  25368. /* a[i+51] += m[51] * mu */
  25369. "LDR r12, [%[m], #204]\n\t"
  25370. "LDR r11, [%[a], #204]\n\t"
  25371. "UMAAL r11, r3, lr, r12\n\t"
  25372. "STR r11, [%[a], #204]\n\t"
  25373. /* a[i+52] += m[52] * mu */
  25374. "LDR r12, [%[m], #208]\n\t"
  25375. "LDR r11, [%[a], #208]\n\t"
  25376. "UMAAL r11, r3, lr, r12\n\t"
  25377. "STR r11, [%[a], #208]\n\t"
  25378. /* a[i+53] += m[53] * mu */
  25379. "LDR r12, [%[m], #212]\n\t"
  25380. "LDR r11, [%[a], #212]\n\t"
  25381. "UMAAL r11, r3, lr, r12\n\t"
  25382. "STR r11, [%[a], #212]\n\t"
  25383. /* a[i+54] += m[54] * mu */
  25384. "LDR r12, [%[m], #216]\n\t"
  25385. "LDR r11, [%[a], #216]\n\t"
  25386. "UMAAL r11, r3, lr, r12\n\t"
  25387. "STR r11, [%[a], #216]\n\t"
  25388. /* a[i+55] += m[55] * mu */
  25389. "LDR r12, [%[m], #220]\n\t"
  25390. "LDR r11, [%[a], #220]\n\t"
  25391. "UMAAL r11, r3, lr, r12\n\t"
  25392. "STR r11, [%[a], #220]\n\t"
  25393. /* a[i+56] += m[56] * mu */
  25394. "LDR r12, [%[m], #224]\n\t"
  25395. "LDR r11, [%[a], #224]\n\t"
  25396. "UMAAL r11, r3, lr, r12\n\t"
  25397. "STR r11, [%[a], #224]\n\t"
  25398. /* a[i+57] += m[57] * mu */
  25399. "LDR r12, [%[m], #228]\n\t"
  25400. "LDR r11, [%[a], #228]\n\t"
  25401. "UMAAL r11, r3, lr, r12\n\t"
  25402. "STR r11, [%[a], #228]\n\t"
  25403. /* a[i+58] += m[58] * mu */
  25404. "LDR r12, [%[m], #232]\n\t"
  25405. "LDR r11, [%[a], #232]\n\t"
  25406. "UMAAL r11, r3, lr, r12\n\t"
  25407. "STR r11, [%[a], #232]\n\t"
  25408. /* a[i+59] += m[59] * mu */
  25409. "LDR r12, [%[m], #236]\n\t"
  25410. "LDR r11, [%[a], #236]\n\t"
  25411. "UMAAL r11, r3, lr, r12\n\t"
  25412. "STR r11, [%[a], #236]\n\t"
  25413. /* a[i+60] += m[60] * mu */
  25414. "LDR r12, [%[m], #240]\n\t"
  25415. "LDR r11, [%[a], #240]\n\t"
  25416. "UMAAL r11, r3, lr, r12\n\t"
  25417. "STR r11, [%[a], #240]\n\t"
  25418. /* a[i+61] += m[61] * mu */
  25419. "LDR r12, [%[m], #244]\n\t"
  25420. "LDR r11, [%[a], #244]\n\t"
  25421. "UMAAL r11, r3, lr, r12\n\t"
  25422. "STR r11, [%[a], #244]\n\t"
  25423. /* a[i+62] += m[62] * mu */
  25424. "LDR r12, [%[m], #248]\n\t"
  25425. "LDR r11, [%[a], #248]\n\t"
  25426. "UMAAL r11, r3, lr, r12\n\t"
  25427. "STR r11, [%[a], #248]\n\t"
  25428. /* a[i+63] += m[63] * mu */
  25429. "LDR r12, [%[m], #252]\n\t"
  25430. "LDR r11, [%[a], #252]\n\t"
  25431. "UMAAL r11, r3, lr, r12\n\t"
  25432. "STR r11, [%[a], #252]\n\t"
  25433. /* a[i+64] += m[64] * mu */
  25434. "LDR r12, [%[m], #256]\n\t"
  25435. "LDR r11, [%[a], #256]\n\t"
  25436. "UMAAL r11, r3, lr, r12\n\t"
  25437. "STR r11, [%[a], #256]\n\t"
  25438. /* a[i+65] += m[65] * mu */
  25439. "LDR r12, [%[m], #260]\n\t"
  25440. "LDR r11, [%[a], #260]\n\t"
  25441. "UMAAL r11, r3, lr, r12\n\t"
  25442. "STR r11, [%[a], #260]\n\t"
  25443. /* a[i+66] += m[66] * mu */
  25444. "LDR r12, [%[m], #264]\n\t"
  25445. "LDR r11, [%[a], #264]\n\t"
  25446. "UMAAL r11, r3, lr, r12\n\t"
  25447. "STR r11, [%[a], #264]\n\t"
  25448. /* a[i+67] += m[67] * mu */
  25449. "LDR r12, [%[m], #268]\n\t"
  25450. "LDR r11, [%[a], #268]\n\t"
  25451. "UMAAL r11, r3, lr, r12\n\t"
  25452. "STR r11, [%[a], #268]\n\t"
  25453. /* a[i+68] += m[68] * mu */
  25454. "LDR r12, [%[m], #272]\n\t"
  25455. "LDR r11, [%[a], #272]\n\t"
  25456. "UMAAL r11, r3, lr, r12\n\t"
  25457. "STR r11, [%[a], #272]\n\t"
  25458. /* a[i+69] += m[69] * mu */
  25459. "LDR r12, [%[m], #276]\n\t"
  25460. "LDR r11, [%[a], #276]\n\t"
  25461. "UMAAL r11, r3, lr, r12\n\t"
  25462. "STR r11, [%[a], #276]\n\t"
  25463. /* a[i+70] += m[70] * mu */
  25464. "LDR r12, [%[m], #280]\n\t"
  25465. "LDR r11, [%[a], #280]\n\t"
  25466. "UMAAL r11, r3, lr, r12\n\t"
  25467. "STR r11, [%[a], #280]\n\t"
  25468. /* a[i+71] += m[71] * mu */
  25469. "LDR r12, [%[m], #284]\n\t"
  25470. "LDR r11, [%[a], #284]\n\t"
  25471. "UMAAL r11, r3, lr, r12\n\t"
  25472. "STR r11, [%[a], #284]\n\t"
  25473. /* a[i+72] += m[72] * mu */
  25474. "LDR r12, [%[m], #288]\n\t"
  25475. "LDR r11, [%[a], #288]\n\t"
  25476. "UMAAL r11, r3, lr, r12\n\t"
  25477. "STR r11, [%[a], #288]\n\t"
  25478. /* a[i+73] += m[73] * mu */
  25479. "LDR r12, [%[m], #292]\n\t"
  25480. "LDR r11, [%[a], #292]\n\t"
  25481. "UMAAL r11, r3, lr, r12\n\t"
  25482. "STR r11, [%[a], #292]\n\t"
  25483. /* a[i+74] += m[74] * mu */
  25484. "LDR r12, [%[m], #296]\n\t"
  25485. "LDR r11, [%[a], #296]\n\t"
  25486. "UMAAL r11, r3, lr, r12\n\t"
  25487. "STR r11, [%[a], #296]\n\t"
  25488. /* a[i+75] += m[75] * mu */
  25489. "LDR r12, [%[m], #300]\n\t"
  25490. "LDR r11, [%[a], #300]\n\t"
  25491. "UMAAL r11, r3, lr, r12\n\t"
  25492. "STR r11, [%[a], #300]\n\t"
  25493. /* a[i+76] += m[76] * mu */
  25494. "LDR r12, [%[m], #304]\n\t"
  25495. "LDR r11, [%[a], #304]\n\t"
  25496. "UMAAL r11, r3, lr, r12\n\t"
  25497. "STR r11, [%[a], #304]\n\t"
  25498. /* a[i+77] += m[77] * mu */
  25499. "LDR r12, [%[m], #308]\n\t"
  25500. "LDR r11, [%[a], #308]\n\t"
  25501. "UMAAL r11, r3, lr, r12\n\t"
  25502. "STR r11, [%[a], #308]\n\t"
  25503. /* a[i+78] += m[78] * mu */
  25504. "LDR r12, [%[m], #312]\n\t"
  25505. "LDR r11, [%[a], #312]\n\t"
  25506. "UMAAL r11, r3, lr, r12\n\t"
  25507. "STR r11, [%[a], #312]\n\t"
  25508. /* a[i+79] += m[79] * mu */
  25509. "LDR r12, [%[m], #316]\n\t"
  25510. "LDR r11, [%[a], #316]\n\t"
  25511. "UMAAL r11, r3, lr, r12\n\t"
  25512. "STR r11, [%[a], #316]\n\t"
  25513. /* a[i+80] += m[80] * mu */
  25514. "LDR r12, [%[m], #320]\n\t"
  25515. "LDR r11, [%[a], #320]\n\t"
  25516. "UMAAL r11, r3, lr, r12\n\t"
  25517. "STR r11, [%[a], #320]\n\t"
  25518. /* a[i+81] += m[81] * mu */
  25519. "LDR r12, [%[m], #324]\n\t"
  25520. "LDR r11, [%[a], #324]\n\t"
  25521. "UMAAL r11, r3, lr, r12\n\t"
  25522. "STR r11, [%[a], #324]\n\t"
  25523. /* a[i+82] += m[82] * mu */
  25524. "LDR r12, [%[m], #328]\n\t"
  25525. "LDR r11, [%[a], #328]\n\t"
  25526. "UMAAL r11, r3, lr, r12\n\t"
  25527. "STR r11, [%[a], #328]\n\t"
  25528. /* a[i+83] += m[83] * mu */
  25529. "LDR r12, [%[m], #332]\n\t"
  25530. "LDR r11, [%[a], #332]\n\t"
  25531. "UMAAL r11, r3, lr, r12\n\t"
  25532. "STR r11, [%[a], #332]\n\t"
  25533. /* a[i+84] += m[84] * mu */
  25534. "LDR r12, [%[m], #336]\n\t"
  25535. "LDR r11, [%[a], #336]\n\t"
  25536. "UMAAL r11, r3, lr, r12\n\t"
  25537. "STR r11, [%[a], #336]\n\t"
  25538. /* a[i+85] += m[85] * mu */
  25539. "LDR r12, [%[m], #340]\n\t"
  25540. "LDR r11, [%[a], #340]\n\t"
  25541. "UMAAL r11, r3, lr, r12\n\t"
  25542. "STR r11, [%[a], #340]\n\t"
  25543. /* a[i+86] += m[86] * mu */
  25544. "LDR r12, [%[m], #344]\n\t"
  25545. "LDR r11, [%[a], #344]\n\t"
  25546. "UMAAL r11, r3, lr, r12\n\t"
  25547. "STR r11, [%[a], #344]\n\t"
  25548. /* a[i+87] += m[87] * mu */
  25549. "LDR r12, [%[m], #348]\n\t"
  25550. "LDR r11, [%[a], #348]\n\t"
  25551. "UMAAL r11, r3, lr, r12\n\t"
  25552. "STR r11, [%[a], #348]\n\t"
  25553. /* a[i+88] += m[88] * mu */
  25554. "LDR r12, [%[m], #352]\n\t"
  25555. "LDR r11, [%[a], #352]\n\t"
  25556. "UMAAL r11, r3, lr, r12\n\t"
  25557. "STR r11, [%[a], #352]\n\t"
  25558. /* a[i+89] += m[89] * mu */
  25559. "LDR r12, [%[m], #356]\n\t"
  25560. "LDR r11, [%[a], #356]\n\t"
  25561. "UMAAL r11, r3, lr, r12\n\t"
  25562. "STR r11, [%[a], #356]\n\t"
  25563. /* a[i+90] += m[90] * mu */
  25564. "LDR r12, [%[m], #360]\n\t"
  25565. "LDR r11, [%[a], #360]\n\t"
  25566. "UMAAL r11, r3, lr, r12\n\t"
  25567. "STR r11, [%[a], #360]\n\t"
  25568. /* a[i+91] += m[91] * mu */
  25569. "LDR r12, [%[m], #364]\n\t"
  25570. "LDR r11, [%[a], #364]\n\t"
  25571. "UMAAL r11, r3, lr, r12\n\t"
  25572. "STR r11, [%[a], #364]\n\t"
  25573. /* a[i+92] += m[92] * mu */
  25574. "LDR r12, [%[m], #368]\n\t"
  25575. "LDR r11, [%[a], #368]\n\t"
  25576. "UMAAL r11, r3, lr, r12\n\t"
  25577. "STR r11, [%[a], #368]\n\t"
  25578. /* a[i+93] += m[93] * mu */
  25579. "LDR r12, [%[m], #372]\n\t"
  25580. "LDR r11, [%[a], #372]\n\t"
  25581. "UMAAL r11, r3, lr, r12\n\t"
  25582. "STR r11, [%[a], #372]\n\t"
  25583. /* a[i+94] += m[94] * mu */
  25584. "LDR r12, [%[m], #376]\n\t"
  25585. "LDR r11, [%[a], #376]\n\t"
  25586. "UMAAL r11, r3, lr, r12\n\t"
  25587. "STR r11, [%[a], #376]\n\t"
  25588. /* a[i+95] += m[95] * mu */
  25589. "LDR r12, [%[m], #380]\n\t"
  25590. "LDR r11, [%[a], #380]\n\t"
  25591. "UMAAL r11, r3, lr, r12\n\t"
  25592. "STR r11, [%[a], #380]\n\t"
  25593. /* a[i+96] += m[96] * mu */
  25594. "LDR r12, [%[m], #384]\n\t"
  25595. "LDR r11, [%[a], #384]\n\t"
  25596. "UMAAL r11, r3, lr, r12\n\t"
  25597. "STR r11, [%[a], #384]\n\t"
  25598. /* a[i+97] += m[97] * mu */
  25599. "LDR r12, [%[m], #388]\n\t"
  25600. "LDR r11, [%[a], #388]\n\t"
  25601. "UMAAL r11, r3, lr, r12\n\t"
  25602. "STR r11, [%[a], #388]\n\t"
  25603. /* a[i+98] += m[98] * mu */
  25604. "LDR r12, [%[m], #392]\n\t"
  25605. "LDR r11, [%[a], #392]\n\t"
  25606. "UMAAL r11, r3, lr, r12\n\t"
  25607. "STR r11, [%[a], #392]\n\t"
  25608. /* a[i+99] += m[99] * mu */
  25609. "LDR r12, [%[m], #396]\n\t"
  25610. "LDR r11, [%[a], #396]\n\t"
  25611. "UMAAL r11, r3, lr, r12\n\t"
  25612. "STR r11, [%[a], #396]\n\t"
  25613. /* a[i+100] += m[100] * mu */
  25614. "LDR r12, [%[m], #400]\n\t"
  25615. "LDR r11, [%[a], #400]\n\t"
  25616. "UMAAL r11, r3, lr, r12\n\t"
  25617. "STR r11, [%[a], #400]\n\t"
  25618. /* a[i+101] += m[101] * mu */
  25619. "LDR r12, [%[m], #404]\n\t"
  25620. "LDR r11, [%[a], #404]\n\t"
  25621. "UMAAL r11, r3, lr, r12\n\t"
  25622. "STR r11, [%[a], #404]\n\t"
  25623. /* a[i+102] += m[102] * mu */
  25624. "LDR r12, [%[m], #408]\n\t"
  25625. "LDR r11, [%[a], #408]\n\t"
  25626. "UMAAL r11, r3, lr, r12\n\t"
  25627. "STR r11, [%[a], #408]\n\t"
  25628. /* a[i+103] += m[103] * mu */
  25629. "LDR r12, [%[m], #412]\n\t"
  25630. "LDR r11, [%[a], #412]\n\t"
  25631. "UMAAL r11, r3, lr, r12\n\t"
  25632. "STR r11, [%[a], #412]\n\t"
  25633. /* a[i+104] += m[104] * mu */
  25634. "LDR r12, [%[m], #416]\n\t"
  25635. "LDR r11, [%[a], #416]\n\t"
  25636. "UMAAL r11, r3, lr, r12\n\t"
  25637. "STR r11, [%[a], #416]\n\t"
  25638. /* a[i+105] += m[105] * mu */
  25639. "LDR r12, [%[m], #420]\n\t"
  25640. "LDR r11, [%[a], #420]\n\t"
  25641. "UMAAL r11, r3, lr, r12\n\t"
  25642. "STR r11, [%[a], #420]\n\t"
  25643. /* a[i+106] += m[106] * mu */
  25644. "LDR r12, [%[m], #424]\n\t"
  25645. "LDR r11, [%[a], #424]\n\t"
  25646. "UMAAL r11, r3, lr, r12\n\t"
  25647. "STR r11, [%[a], #424]\n\t"
  25648. /* a[i+107] += m[107] * mu */
  25649. "LDR r12, [%[m], #428]\n\t"
  25650. "LDR r11, [%[a], #428]\n\t"
  25651. "UMAAL r11, r3, lr, r12\n\t"
  25652. "STR r11, [%[a], #428]\n\t"
  25653. /* a[i+108] += m[108] * mu */
  25654. "LDR r12, [%[m], #432]\n\t"
  25655. "LDR r11, [%[a], #432]\n\t"
  25656. "UMAAL r11, r3, lr, r12\n\t"
  25657. "STR r11, [%[a], #432]\n\t"
  25658. /* a[i+109] += m[109] * mu */
  25659. "LDR r12, [%[m], #436]\n\t"
  25660. "LDR r11, [%[a], #436]\n\t"
  25661. "UMAAL r11, r3, lr, r12\n\t"
  25662. "STR r11, [%[a], #436]\n\t"
  25663. /* a[i+110] += m[110] * mu */
  25664. "LDR r12, [%[m], #440]\n\t"
  25665. "LDR r11, [%[a], #440]\n\t"
  25666. "UMAAL r11, r3, lr, r12\n\t"
  25667. "STR r11, [%[a], #440]\n\t"
  25668. /* a[i+111] += m[111] * mu */
  25669. "LDR r12, [%[m], #444]\n\t"
  25670. "LDR r11, [%[a], #444]\n\t"
  25671. "UMAAL r11, r3, lr, r12\n\t"
  25672. "STR r11, [%[a], #444]\n\t"
  25673. /* a[i+112] += m[112] * mu */
  25674. "LDR r12, [%[m], #448]\n\t"
  25675. "LDR r11, [%[a], #448]\n\t"
  25676. "UMAAL r11, r3, lr, r12\n\t"
  25677. "STR r11, [%[a], #448]\n\t"
  25678. /* a[i+113] += m[113] * mu */
  25679. "LDR r12, [%[m], #452]\n\t"
  25680. "LDR r11, [%[a], #452]\n\t"
  25681. "UMAAL r11, r3, lr, r12\n\t"
  25682. "STR r11, [%[a], #452]\n\t"
  25683. /* a[i+114] += m[114] * mu */
  25684. "LDR r12, [%[m], #456]\n\t"
  25685. "LDR r11, [%[a], #456]\n\t"
  25686. "UMAAL r11, r3, lr, r12\n\t"
  25687. "STR r11, [%[a], #456]\n\t"
  25688. /* a[i+115] += m[115] * mu */
  25689. "LDR r12, [%[m], #460]\n\t"
  25690. "LDR r11, [%[a], #460]\n\t"
  25691. "UMAAL r11, r3, lr, r12\n\t"
  25692. "STR r11, [%[a], #460]\n\t"
  25693. /* a[i+116] += m[116] * mu */
  25694. "LDR r12, [%[m], #464]\n\t"
  25695. "LDR r11, [%[a], #464]\n\t"
  25696. "UMAAL r11, r3, lr, r12\n\t"
  25697. "STR r11, [%[a], #464]\n\t"
  25698. /* a[i+117] += m[117] * mu */
  25699. "LDR r12, [%[m], #468]\n\t"
  25700. "LDR r11, [%[a], #468]\n\t"
  25701. "UMAAL r11, r3, lr, r12\n\t"
  25702. "STR r11, [%[a], #468]\n\t"
  25703. /* a[i+118] += m[118] * mu */
  25704. "LDR r12, [%[m], #472]\n\t"
  25705. "LDR r11, [%[a], #472]\n\t"
  25706. "UMAAL r11, r3, lr, r12\n\t"
  25707. "STR r11, [%[a], #472]\n\t"
  25708. /* a[i+119] += m[119] * mu */
  25709. "LDR r12, [%[m], #476]\n\t"
  25710. "LDR r11, [%[a], #476]\n\t"
  25711. "UMAAL r11, r3, lr, r12\n\t"
  25712. "STR r11, [%[a], #476]\n\t"
  25713. /* a[i+120] += m[120] * mu */
  25714. "LDR r12, [%[m], #480]\n\t"
  25715. "LDR r11, [%[a], #480]\n\t"
  25716. "UMAAL r11, r3, lr, r12\n\t"
  25717. "STR r11, [%[a], #480]\n\t"
  25718. /* a[i+121] += m[121] * mu */
  25719. "LDR r12, [%[m], #484]\n\t"
  25720. "LDR r11, [%[a], #484]\n\t"
  25721. "UMAAL r11, r3, lr, r12\n\t"
  25722. "STR r11, [%[a], #484]\n\t"
  25723. /* a[i+122] += m[122] * mu */
  25724. "LDR r12, [%[m], #488]\n\t"
  25725. "LDR r11, [%[a], #488]\n\t"
  25726. "UMAAL r11, r3, lr, r12\n\t"
  25727. "STR r11, [%[a], #488]\n\t"
  25728. /* a[i+123] += m[123] * mu */
  25729. "LDR r12, [%[m], #492]\n\t"
  25730. "LDR r11, [%[a], #492]\n\t"
  25731. "UMAAL r11, r3, lr, r12\n\t"
  25732. "STR r11, [%[a], #492]\n\t"
  25733. /* a[i+124] += m[124] * mu */
  25734. "LDR r12, [%[m], #496]\n\t"
  25735. "LDR r11, [%[a], #496]\n\t"
  25736. "UMAAL r11, r3, lr, r12\n\t"
  25737. "STR r11, [%[a], #496]\n\t"
  25738. /* a[i+125] += m[125] * mu */
  25739. "LDR r12, [%[m], #500]\n\t"
  25740. "LDR r11, [%[a], #500]\n\t"
  25741. "UMAAL r11, r3, lr, r12\n\t"
  25742. "STR r11, [%[a], #500]\n\t"
  25743. /* a[i+126] += m[126] * mu */
  25744. "LDR r12, [%[m], #504]\n\t"
  25745. "LDR r11, [%[a], #504]\n\t"
  25746. "UMAAL r11, r3, lr, r12\n\t"
  25747. "STR r11, [%[a], #504]\n\t"
  25748. /* a[i+127] += m[127] * mu */
  25749. "LDR r12, [%[m], #508]\n\t"
  25750. "LDR r11, [%[a], #508]\n\t"
  25751. "UMAAL r11, r3, lr, r12\n\t"
  25752. "LDR lr, [%[a], #512]\n\t"
  25753. "MOV r12, #0x0\n\t"
  25754. "UMAAL r3, lr, r12, r12\n\t"
  25755. "STR r11, [%[a], #508]\n\t"
  25756. "ADDS r3, r3, r5\n\t"
  25757. "ADC r5, lr, #0x0\n\t"
  25758. "STR r3, [%[a], #512]\n\t"
  25759. /* i += 1 */
  25760. "ADD r4, r4, #0x4\n\t"
  25761. "ADD %[a], %[a], #0x4\n\t"
  25762. "CMP r4, #0x200\n\t"
  25763. #ifdef __GNUC__
  25764. "BLT L_sp_4096_mont_reduce_128_word\n\t"
  25765. #else
  25766. "BLT.W L_sp_4096_mont_reduce_128_word\n\t"
  25767. #endif
  25768. /* Loop Done */
  25769. "STR r6, [%[a]]\n\t"
  25770. "STR r7, [%[a], #4]\n\t"
  25771. "STR r8, [%[a], #8]\n\t"
  25772. "STR r9, [%[a], #12]\n\t"
  25773. "STR r10, [%[a], #16]\n\t"
  25774. "MOV %[mp], r5\n\t"
  25775. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  25776. :
  25777. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  25778. );
  25779. sp_4096_cond_sub_128(a - 128, a, m, (sp_digit)0 - mp);
  25780. }
  25781. #else
  25782. /* Reduce the number back to 4096 bits using Montgomery reduction.
  25783. *
  25784. * a A single precision number to reduce in place.
  25785. * m The single precision number representing the modulus.
  25786. * mp The digit representing the negative inverse of m mod 2^n.
  25787. */
  25788. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25789. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  25790. #else
  25791. SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, sp_digit mp)
  25792. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25793. {
  25794. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25795. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  25796. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  25797. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  25798. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25799. __asm__ __volatile__ (
  25800. "LDR r11, [%[m]]\n\t"
  25801. /* i = 0 */
  25802. "MOV r9, #0x0\n\t"
  25803. /* ca = 0 */
  25804. "MOV r3, #0x0\n\t"
  25805. "\n"
  25806. "L_sp_4096_mont_reduce_128_word:\n\t"
  25807. /* mu = a[i] * mp */
  25808. "LDR r10, [%[a]]\n\t"
  25809. "MUL r8, %[mp], r10\n\t"
  25810. /* j = 0 */
  25811. "MOV r12, #0x0\n\t"
  25812. "MOV r4, #0x0\n\t"
  25813. "\n"
  25814. "L_sp_4096_mont_reduce_128_mul:\n\t"
  25815. /* a[i+j+0] += m[j+0] * mu */
  25816. "LDR r7, [%[m], r12]\n\t"
  25817. "LDR r10, [%[a], r12]\n\t"
  25818. "UMAAL r10, r4, r8, r7\n\t"
  25819. "STR r10, [%[a], r12]\n\t"
  25820. /* j += 1 */
  25821. "ADD r12, r12, #0x4\n\t"
  25822. /* a[i+j+1] += m[j+1] * mu */
  25823. "LDR r7, [%[m], r12]\n\t"
  25824. "LDR r10, [%[a], r12]\n\t"
  25825. "UMAAL r10, r4, r8, r7\n\t"
  25826. "STR r10, [%[a], r12]\n\t"
  25827. /* j += 1 */
  25828. "ADD r12, r12, #0x4\n\t"
  25829. /* a[i+j+2] += m[j+2] * mu */
  25830. "LDR r7, [%[m], r12]\n\t"
  25831. "LDR r10, [%[a], r12]\n\t"
  25832. "UMAAL r10, r4, r8, r7\n\t"
  25833. "STR r10, [%[a], r12]\n\t"
  25834. /* j += 1 */
  25835. "ADD r12, r12, #0x4\n\t"
  25836. /* a[i+j+3] += m[j+3] * mu */
  25837. "LDR r7, [%[m], r12]\n\t"
  25838. "LDR r10, [%[a], r12]\n\t"
  25839. "UMAAL r10, r4, r8, r7\n\t"
  25840. "STR r10, [%[a], r12]\n\t"
  25841. /* j += 1 */
  25842. "ADD r12, r12, #0x4\n\t"
  25843. "CMP r12, #0x200\n\t"
  25844. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  25845. "BLT L_sp_4096_mont_reduce_128_mul\n\t"
  25846. #else
  25847. "BLT.N L_sp_4096_mont_reduce_128_mul\n\t"
  25848. #endif
  25849. "LDR r10, [%[a], #512]\n\t"
  25850. "ADDS r4, r4, r3\n\t"
  25851. "MOV r3, #0x0\n\t"
  25852. "ADC r3, r3, #0x0\n\t"
  25853. "ADDS r10, r10, r4\n\t"
  25854. "ADC r3, r3, r3\n\t"
  25855. "STR r10, [%[a], #512]\n\t"
  25856. /* i += 1 */
  25857. "ADD r9, r9, #0x4\n\t"
  25858. "ADD %[a], %[a], #0x4\n\t"
  25859. "CMP r9, #0x200\n\t"
  25860. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  25861. "BLT L_sp_4096_mont_reduce_128_word\n\t"
  25862. #else
  25863. "BLT.N L_sp_4096_mont_reduce_128_word\n\t"
  25864. #endif
  25865. /* Loop Done */
  25866. "MOV %[mp], r3\n\t"
  25867. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  25868. :
  25869. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  25870. );
  25871. sp_4096_cond_sub_128(a - 128, a, m, (sp_digit)0 - mp);
  25872. }
  25873. #endif /* !WOLFSSL_SP_SMALL */
  25874. #endif
  25875. /* Multiply two Montgomery form numbers mod the modulus (prime).
  25876. * (r = a * b mod m)
  25877. *
  25878. * r Result of multiplication.
  25879. * a First number to multiply in Montgomery form.
  25880. * b Second number to multiply in Montgomery form.
  25881. * m Modulus (prime).
  25882. * mp Montgomery multiplier.
  25883. */
  25884. SP_NOINLINE static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a,
  25885. const sp_digit* b, const sp_digit* m, sp_digit mp)
  25886. {
  25887. sp_4096_mul_128(r, a, b);
  25888. sp_4096_mont_reduce_128(r, m, mp);
  25889. }
  25890. /* Square the Montgomery form number. (r = a * a mod m)
  25891. *
  25892. * r Result of squaring.
  25893. * a Number to square in Montgomery form.
  25894. * m Modulus (prime).
  25895. * mp Montgomery multiplier.
  25896. */
  25897. SP_NOINLINE static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a,
  25898. const sp_digit* m, sp_digit mp)
  25899. {
  25900. sp_4096_sqr_128(r, a);
  25901. sp_4096_mont_reduce_128(r, m, mp);
  25902. }
  25903. #ifdef WOLFSSL_SP_SMALL
  25904. /* Sub b from a into r. (r = a - b)
  25905. *
  25906. * r A single precision integer.
  25907. * a A single precision integer.
  25908. * b A single precision integer.
  25909. */
  25910. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25911. static sp_digit sp_4096_sub_128(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  25912. #else
  25913. static sp_digit sp_4096_sub_128(sp_digit* r, const sp_digit* a, const sp_digit* b)
  25914. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25915. {
  25916. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25917. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  25918. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  25919. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  25920. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25921. __asm__ __volatile__ (
  25922. "MOV r11, #0x0\n\t"
  25923. "ADD r12, %[a], #0x200\n\t"
  25924. "\n"
  25925. "L_sp_4096_sub_128_word:\n\t"
  25926. "RSBS r11, r11, #0x0\n\t"
  25927. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  25928. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  25929. "SBCS r3, r3, r7\n\t"
  25930. "SBCS r4, r4, r8\n\t"
  25931. "SBCS r5, r5, r9\n\t"
  25932. "SBCS r6, r6, r10\n\t"
  25933. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  25934. "SBC r11, r3, r3\n\t"
  25935. "CMP %[a], r12\n\t"
  25936. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  25937. "BNE L_sp_4096_sub_128_word\n\t"
  25938. #else
  25939. "BNE.N L_sp_4096_sub_128_word\n\t"
  25940. #endif
  25941. "MOV %[r], r11\n\t"
  25942. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  25943. :
  25944. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  25945. );
  25946. return (uint32_t)(size_t)r;
  25947. }
  25948. #else
  25949. /* Sub b from a into r. (r = a - b)
  25950. *
  25951. * r A single precision integer.
  25952. * a A single precision integer.
  25953. * b A single precision integer.
  25954. */
  25955. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25956. static sp_digit sp_4096_sub_128(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  25957. #else
  25958. static sp_digit sp_4096_sub_128(sp_digit* r, const sp_digit* a, const sp_digit* b)
  25959. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25960. {
  25961. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  25962. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  25963. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  25964. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  25965. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  25966. __asm__ __volatile__ (
  25967. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  25968. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  25969. "SUBS r3, r3, r7\n\t"
  25970. "SBCS r4, r4, r8\n\t"
  25971. "SBCS r5, r5, r9\n\t"
  25972. "SBCS r6, r6, r10\n\t"
  25973. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  25974. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  25975. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  25976. "SBCS r3, r3, r7\n\t"
  25977. "SBCS r4, r4, r8\n\t"
  25978. "SBCS r5, r5, r9\n\t"
  25979. "SBCS r6, r6, r10\n\t"
  25980. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  25981. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  25982. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  25983. "SBCS r3, r3, r7\n\t"
  25984. "SBCS r4, r4, r8\n\t"
  25985. "SBCS r5, r5, r9\n\t"
  25986. "SBCS r6, r6, r10\n\t"
  25987. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  25988. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  25989. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  25990. "SBCS r3, r3, r7\n\t"
  25991. "SBCS r4, r4, r8\n\t"
  25992. "SBCS r5, r5, r9\n\t"
  25993. "SBCS r6, r6, r10\n\t"
  25994. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  25995. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  25996. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  25997. "SBCS r3, r3, r7\n\t"
  25998. "SBCS r4, r4, r8\n\t"
  25999. "SBCS r5, r5, r9\n\t"
  26000. "SBCS r6, r6, r10\n\t"
  26001. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26002. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26003. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26004. "SBCS r3, r3, r7\n\t"
  26005. "SBCS r4, r4, r8\n\t"
  26006. "SBCS r5, r5, r9\n\t"
  26007. "SBCS r6, r6, r10\n\t"
  26008. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26009. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26010. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26011. "SBCS r3, r3, r7\n\t"
  26012. "SBCS r4, r4, r8\n\t"
  26013. "SBCS r5, r5, r9\n\t"
  26014. "SBCS r6, r6, r10\n\t"
  26015. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26016. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26017. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26018. "SBCS r3, r3, r7\n\t"
  26019. "SBCS r4, r4, r8\n\t"
  26020. "SBCS r5, r5, r9\n\t"
  26021. "SBCS r6, r6, r10\n\t"
  26022. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26023. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26024. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26025. "SBCS r3, r3, r7\n\t"
  26026. "SBCS r4, r4, r8\n\t"
  26027. "SBCS r5, r5, r9\n\t"
  26028. "SBCS r6, r6, r10\n\t"
  26029. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26030. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26031. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26032. "SBCS r3, r3, r7\n\t"
  26033. "SBCS r4, r4, r8\n\t"
  26034. "SBCS r5, r5, r9\n\t"
  26035. "SBCS r6, r6, r10\n\t"
  26036. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26037. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26038. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26039. "SBCS r3, r3, r7\n\t"
  26040. "SBCS r4, r4, r8\n\t"
  26041. "SBCS r5, r5, r9\n\t"
  26042. "SBCS r6, r6, r10\n\t"
  26043. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26044. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26045. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26046. "SBCS r3, r3, r7\n\t"
  26047. "SBCS r4, r4, r8\n\t"
  26048. "SBCS r5, r5, r9\n\t"
  26049. "SBCS r6, r6, r10\n\t"
  26050. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26051. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26052. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26053. "SBCS r3, r3, r7\n\t"
  26054. "SBCS r4, r4, r8\n\t"
  26055. "SBCS r5, r5, r9\n\t"
  26056. "SBCS r6, r6, r10\n\t"
  26057. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26058. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26059. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26060. "SBCS r3, r3, r7\n\t"
  26061. "SBCS r4, r4, r8\n\t"
  26062. "SBCS r5, r5, r9\n\t"
  26063. "SBCS r6, r6, r10\n\t"
  26064. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26065. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26066. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26067. "SBCS r3, r3, r7\n\t"
  26068. "SBCS r4, r4, r8\n\t"
  26069. "SBCS r5, r5, r9\n\t"
  26070. "SBCS r6, r6, r10\n\t"
  26071. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26072. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26073. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26074. "SBCS r3, r3, r7\n\t"
  26075. "SBCS r4, r4, r8\n\t"
  26076. "SBCS r5, r5, r9\n\t"
  26077. "SBCS r6, r6, r10\n\t"
  26078. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26079. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26080. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26081. "SBCS r3, r3, r7\n\t"
  26082. "SBCS r4, r4, r8\n\t"
  26083. "SBCS r5, r5, r9\n\t"
  26084. "SBCS r6, r6, r10\n\t"
  26085. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26086. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26087. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26088. "SBCS r3, r3, r7\n\t"
  26089. "SBCS r4, r4, r8\n\t"
  26090. "SBCS r5, r5, r9\n\t"
  26091. "SBCS r6, r6, r10\n\t"
  26092. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26093. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26094. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26095. "SBCS r3, r3, r7\n\t"
  26096. "SBCS r4, r4, r8\n\t"
  26097. "SBCS r5, r5, r9\n\t"
  26098. "SBCS r6, r6, r10\n\t"
  26099. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26100. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26101. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26102. "SBCS r3, r3, r7\n\t"
  26103. "SBCS r4, r4, r8\n\t"
  26104. "SBCS r5, r5, r9\n\t"
  26105. "SBCS r6, r6, r10\n\t"
  26106. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26107. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26108. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26109. "SBCS r3, r3, r7\n\t"
  26110. "SBCS r4, r4, r8\n\t"
  26111. "SBCS r5, r5, r9\n\t"
  26112. "SBCS r6, r6, r10\n\t"
  26113. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26114. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26115. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26116. "SBCS r3, r3, r7\n\t"
  26117. "SBCS r4, r4, r8\n\t"
  26118. "SBCS r5, r5, r9\n\t"
  26119. "SBCS r6, r6, r10\n\t"
  26120. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26121. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26122. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26123. "SBCS r3, r3, r7\n\t"
  26124. "SBCS r4, r4, r8\n\t"
  26125. "SBCS r5, r5, r9\n\t"
  26126. "SBCS r6, r6, r10\n\t"
  26127. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26128. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26129. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26130. "SBCS r3, r3, r7\n\t"
  26131. "SBCS r4, r4, r8\n\t"
  26132. "SBCS r5, r5, r9\n\t"
  26133. "SBCS r6, r6, r10\n\t"
  26134. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26135. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26136. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26137. "SBCS r3, r3, r7\n\t"
  26138. "SBCS r4, r4, r8\n\t"
  26139. "SBCS r5, r5, r9\n\t"
  26140. "SBCS r6, r6, r10\n\t"
  26141. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26142. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26143. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26144. "SBCS r3, r3, r7\n\t"
  26145. "SBCS r4, r4, r8\n\t"
  26146. "SBCS r5, r5, r9\n\t"
  26147. "SBCS r6, r6, r10\n\t"
  26148. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26149. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26150. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26151. "SBCS r3, r3, r7\n\t"
  26152. "SBCS r4, r4, r8\n\t"
  26153. "SBCS r5, r5, r9\n\t"
  26154. "SBCS r6, r6, r10\n\t"
  26155. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26156. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26157. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26158. "SBCS r3, r3, r7\n\t"
  26159. "SBCS r4, r4, r8\n\t"
  26160. "SBCS r5, r5, r9\n\t"
  26161. "SBCS r6, r6, r10\n\t"
  26162. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26163. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26164. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26165. "SBCS r3, r3, r7\n\t"
  26166. "SBCS r4, r4, r8\n\t"
  26167. "SBCS r5, r5, r9\n\t"
  26168. "SBCS r6, r6, r10\n\t"
  26169. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26170. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26171. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26172. "SBCS r3, r3, r7\n\t"
  26173. "SBCS r4, r4, r8\n\t"
  26174. "SBCS r5, r5, r9\n\t"
  26175. "SBCS r6, r6, r10\n\t"
  26176. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26177. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26178. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26179. "SBCS r3, r3, r7\n\t"
  26180. "SBCS r4, r4, r8\n\t"
  26181. "SBCS r5, r5, r9\n\t"
  26182. "SBCS r6, r6, r10\n\t"
  26183. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26184. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  26185. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  26186. "SBCS r3, r3, r7\n\t"
  26187. "SBCS r4, r4, r8\n\t"
  26188. "SBCS r5, r5, r9\n\t"
  26189. "SBCS r6, r6, r10\n\t"
  26190. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  26191. "SBC %[r], r6, r6\n\t"
  26192. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  26193. :
  26194. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  26195. );
  26196. return (uint32_t)(size_t)r;
  26197. }
  26198. #endif /* WOLFSSL_SP_SMALL */
  26199. #ifdef WOLFSSL_SP_USE_UDIV
  26200. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  26201. *
  26202. * d1 The high order half of the number to divide.
  26203. * d0 The low order half of the number to divide.
  26204. * div The divisor.
  26205. * returns the result of the division.
  26206. *
  26207. * Note that this is an approximate div. It may give an answer 1 larger.
  26208. */
  26209. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  26210. SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  26211. #else
  26212. SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0, sp_digit div)
  26213. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  26214. {
  26215. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  26216. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  26217. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  26218. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  26219. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  26220. __asm__ __volatile__ (
  26221. "LSR r8, %[div], #16\n\t"
  26222. "ADD r5, r8, #0x1\n\t"
  26223. "UDIV r6, %[d1], r5\n\t"
  26224. "LSL r7, %[div], #16\n\t"
  26225. "LSL r6, r6, #16\n\t"
  26226. "UMULL r3, r4, %[div], r6\n\t"
  26227. "SUBS %[d0], %[d0], r3\n\t"
  26228. "SBC %[d1], %[d1], r4\n\t"
  26229. "SUBS r3, %[d1], r5\n\t"
  26230. "SBC r9, r9, r9\n\t"
  26231. "ADD r9, r9, #0x1\n\t"
  26232. "RSB r10, r9, #0x0\n\t"
  26233. "LSL r9, r9, #16\n\t"
  26234. "AND r7, r7, r10\n\t"
  26235. "AND r8, r8, r10\n\t"
  26236. "SUBS %[d0], %[d0], r7\n\t"
  26237. "ADD r6, r6, r9\n\t"
  26238. "SBC %[d1], %[d1], r8\n\t"
  26239. "LSL r4, %[d1], #16\n\t"
  26240. "LSR r3, %[d0], #16\n\t"
  26241. "ORR r3, r3, r4\n\t"
  26242. "UDIV r3, r3, r5\n\t"
  26243. "ADD r6, r6, r3\n\t"
  26244. "UMULL r3, r4, %[div], r3\n\t"
  26245. "SUBS %[d0], %[d0], r3\n\t"
  26246. "SBC %[d1], %[d1], r4\n\t"
  26247. "LSL r4, %[d1], #16\n\t"
  26248. "LSR r3, %[d0], #16\n\t"
  26249. "ORR r3, r3, r4\n\t"
  26250. "UDIV r3, r3, r5\n\t"
  26251. "ADD r6, r6, r3\n\t"
  26252. "MUL r3, %[div], r3\n\t"
  26253. "SUB %[d0], %[d0], r3\n\t"
  26254. "UDIV r3, %[d0], %[div]\n\t"
  26255. "ADD %[d1], r6, r3\n\t"
  26256. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  26257. :
  26258. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  26259. );
  26260. return (uint32_t)(size_t)d1;
  26261. }
  26262. #else
  26263. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  26264. *
  26265. * d1 The high order half of the number to divide.
  26266. * d0 The low order half of the number to divide.
  26267. * div The divisor.
  26268. * returns the result of the division.
  26269. *
  26270. * Note that this is an approximate div. It may give an answer 1 larger.
  26271. */
  26272. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  26273. SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  26274. #else
  26275. SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0, sp_digit div)
  26276. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  26277. {
  26278. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  26279. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  26280. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  26281. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  26282. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  26283. __asm__ __volatile__ (
  26284. "LSR r5, %[div], #1\n\t"
  26285. "ADD r5, r5, #0x1\n\t"
  26286. "MOV r6, %[d0]\n\t"
  26287. "MOV r7, %[d1]\n\t"
  26288. /* Do top 32 */
  26289. "SUBS r8, r5, r7\n\t"
  26290. "SBC r8, r8, r8\n\t"
  26291. "MOV r3, #0x0\n\t"
  26292. "SUB r3, r3, r8\n\t"
  26293. "AND r8, r8, r5\n\t"
  26294. "SUBS r7, r7, r8\n\t"
  26295. /* Next 30 bits */
  26296. "MOV r4, #0x1d\n\t"
  26297. "\n"
  26298. "L_div_4096_word_128_bit:\n\t"
  26299. "LSLS r6, r6, #1\n\t"
  26300. "ADC r7, r7, r7\n\t"
  26301. "SUBS r8, r5, r7\n\t"
  26302. "SBC r8, r8, r8\n\t"
  26303. "ADD r3, r3, r3\n\t"
  26304. "SUB r3, r3, r8\n\t"
  26305. "AND r8, r8, r5\n\t"
  26306. "SUBS r7, r7, r8\n\t"
  26307. "SUBS r4, r4, #0x1\n\t"
  26308. "bpl L_div_4096_word_128_bit\n\t"
  26309. "ADD r3, r3, r3\n\t"
  26310. "ADD r3, r3, #0x1\n\t"
  26311. "UMULL r6, r7, r3, %[div]\n\t"
  26312. "SUBS r9, %[d0], r6\n\t"
  26313. "SBC r10, %[d1], r7\n\t"
  26314. "ADD r3, r3, r10\n\t"
  26315. "UMULL r6, r7, r3, %[div]\n\t"
  26316. "SUBS r9, %[d0], r6\n\t"
  26317. "SBC r10, %[d1], r7\n\t"
  26318. "ADD r3, r3, r10\n\t"
  26319. "UMULL r6, r7, r3, %[div]\n\t"
  26320. "SUBS r9, %[d0], r6\n\t"
  26321. "SBC r10, %[d1], r7\n\t"
  26322. "ADD r3, r3, r10\n\t"
  26323. "SUBS r8, %[div], r9\n\t"
  26324. "SBC r8, r8, r8\n\t"
  26325. "SUB %[d1], r3, r8\n\t"
  26326. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  26327. :
  26328. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  26329. );
  26330. return (uint32_t)(size_t)d1;
  26331. }
  26332. #endif
  26333. /* Divide d in a and put remainder into r (m*d + r = a)
  26334. * m is not calculated as it is not needed at this time.
  26335. *
  26336. * a Number to be divided.
  26337. * d Number to divide with.
  26338. * m Multiplier result.
  26339. * r Remainder from the division.
  26340. * returns MP_OKAY indicating success.
  26341. */
  26342. static WC_INLINE int sp_4096_div_128_cond(const sp_digit* a, const sp_digit* d,
  26343. sp_digit* m, sp_digit* r)
  26344. {
  26345. sp_digit t1[256], t2[129];
  26346. sp_digit div, r1;
  26347. int i;
  26348. (void)m;
  26349. div = d[127];
  26350. XMEMCPY(t1, a, sizeof(*t1) * 2 * 128);
  26351. for (i = 127; i > 0; i--) {
  26352. if (t1[i + 128] != d[i])
  26353. break;
  26354. }
  26355. if (t1[i + 128] >= d[i]) {
  26356. sp_4096_sub_in_place_128(&t1[128], d);
  26357. }
  26358. for (i = 127; i >= 0; i--) {
  26359. if (t1[128 + i] == div) {
  26360. r1 = SP_DIGIT_MAX;
  26361. }
  26362. else {
  26363. r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div);
  26364. }
  26365. sp_4096_mul_d_128(t2, d, r1);
  26366. t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2);
  26367. t1[128 + i] -= t2[128];
  26368. if (t1[128 + i] != 0) {
  26369. t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d);
  26370. if (t1[128 + i] != 0)
  26371. t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d);
  26372. }
  26373. }
  26374. for (i = 127; i > 0; i--) {
  26375. if (t1[i] != d[i])
  26376. break;
  26377. }
  26378. if (t1[i] >= d[i]) {
  26379. sp_4096_sub_128(r, t1, d);
  26380. }
  26381. else {
  26382. XMEMCPY(r, t1, sizeof(*t1) * 128);
  26383. }
  26384. return MP_OKAY;
  26385. }
  26386. /* Reduce a modulo m into r. (r = a mod m)
  26387. *
  26388. * r A single precision number that is the reduced result.
  26389. * a A single precision number that is to be reduced.
  26390. * m A single precision number that is the modulus to reduce with.
  26391. * returns MP_OKAY indicating success.
  26392. */
  26393. static WC_INLINE int sp_4096_mod_128_cond(sp_digit* r, const sp_digit* a, const sp_digit* m)
  26394. {
  26395. return sp_4096_div_128_cond(a, m, NULL, r);
  26396. }
  26397. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  26398. #if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)
  26399. /* AND m into each word of a and store in r.
  26400. *
  26401. * r A single precision integer.
  26402. * a A single precision integer.
  26403. * m Mask to AND against each digit.
  26404. */
  26405. static void sp_4096_mask_128(sp_digit* r, const sp_digit* a, sp_digit m)
  26406. {
  26407. #ifdef WOLFSSL_SP_SMALL
  26408. int i;
  26409. for (i=0; i<128; i++) {
  26410. r[i] = a[i] & m;
  26411. }
  26412. #else
  26413. int i;
  26414. for (i = 0; i < 128; i += 8) {
  26415. r[i+0] = a[i+0] & m;
  26416. r[i+1] = a[i+1] & m;
  26417. r[i+2] = a[i+2] & m;
  26418. r[i+3] = a[i+3] & m;
  26419. r[i+4] = a[i+4] & m;
  26420. r[i+5] = a[i+5] & m;
  26421. r[i+6] = a[i+6] & m;
  26422. r[i+7] = a[i+7] & m;
  26423. }
  26424. #endif
  26425. }
  26426. /* Compare a with b in constant time.
  26427. *
  26428. * a A single precision integer.
  26429. * b A single precision integer.
  26430. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  26431. * respectively.
  26432. */
  26433. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  26434. static sp_int32 sp_4096_cmp_128(const sp_digit* a_p, const sp_digit* b_p)
  26435. #else
  26436. static sp_int32 sp_4096_cmp_128(const sp_digit* a, const sp_digit* b)
  26437. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  26438. {
  26439. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  26440. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  26441. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  26442. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  26443. __asm__ __volatile__ (
  26444. "MOV r2, #0xffffffff\n\t"
  26445. "MOV r8, #0x1\n\t"
  26446. "MOV r7, #0x0\n\t"
  26447. "MOV r3, #0xffffffff\n\t"
  26448. #ifdef WOLFSSL_SP_SMALL
  26449. "MOV r6, #0x1fc\n\t"
  26450. "\n"
  26451. "L_sp_4096_cmp_128_words:\n\t"
  26452. "LDR r4, [%[a], r6]\n\t"
  26453. "LDR r5, [%[b], r6]\n\t"
  26454. "AND r4, r4, r3\n\t"
  26455. "AND r5, r5, r3\n\t"
  26456. "SUBS r4, r4, r5\n\t"
  26457. "IT hi\n\t"
  26458. "movhi r2, r8\n\t"
  26459. "IT lo\n\t"
  26460. "movlo r2, r3\n\t"
  26461. "IT ne\n\t"
  26462. "movne r3, r7\n\t"
  26463. "SUBS r6, r6, #0x4\n\t"
  26464. "bcs L_sp_4096_cmp_128_words\n\t"
  26465. "EOR r2, r2, r3\n\t"
  26466. #else
  26467. "LDR r4, [%[a], #508]\n\t"
  26468. "LDR r5, [%[b], #508]\n\t"
  26469. "AND r4, r4, r3\n\t"
  26470. "AND r5, r5, r3\n\t"
  26471. "SUBS r4, r4, r5\n\t"
  26472. "IT hi\n\t"
  26473. "movhi r2, r8\n\t"
  26474. "IT lo\n\t"
  26475. "movlo r2, r3\n\t"
  26476. "IT ne\n\t"
  26477. "movne r3, r7\n\t"
  26478. "LDR r4, [%[a], #504]\n\t"
  26479. "LDR r5, [%[b], #504]\n\t"
  26480. "AND r4, r4, r3\n\t"
  26481. "AND r5, r5, r3\n\t"
  26482. "SUBS r4, r4, r5\n\t"
  26483. "IT hi\n\t"
  26484. "movhi r2, r8\n\t"
  26485. "IT lo\n\t"
  26486. "movlo r2, r3\n\t"
  26487. "IT ne\n\t"
  26488. "movne r3, r7\n\t"
  26489. "LDR r4, [%[a], #500]\n\t"
  26490. "LDR r5, [%[b], #500]\n\t"
  26491. "AND r4, r4, r3\n\t"
  26492. "AND r5, r5, r3\n\t"
  26493. "SUBS r4, r4, r5\n\t"
  26494. "IT hi\n\t"
  26495. "movhi r2, r8\n\t"
  26496. "IT lo\n\t"
  26497. "movlo r2, r3\n\t"
  26498. "IT ne\n\t"
  26499. "movne r3, r7\n\t"
  26500. "LDR r4, [%[a], #496]\n\t"
  26501. "LDR r5, [%[b], #496]\n\t"
  26502. "AND r4, r4, r3\n\t"
  26503. "AND r5, r5, r3\n\t"
  26504. "SUBS r4, r4, r5\n\t"
  26505. "IT hi\n\t"
  26506. "movhi r2, r8\n\t"
  26507. "IT lo\n\t"
  26508. "movlo r2, r3\n\t"
  26509. "IT ne\n\t"
  26510. "movne r3, r7\n\t"
  26511. "LDR r4, [%[a], #492]\n\t"
  26512. "LDR r5, [%[b], #492]\n\t"
  26513. "AND r4, r4, r3\n\t"
  26514. "AND r5, r5, r3\n\t"
  26515. "SUBS r4, r4, r5\n\t"
  26516. "IT hi\n\t"
  26517. "movhi r2, r8\n\t"
  26518. "IT lo\n\t"
  26519. "movlo r2, r3\n\t"
  26520. "IT ne\n\t"
  26521. "movne r3, r7\n\t"
  26522. "LDR r4, [%[a], #488]\n\t"
  26523. "LDR r5, [%[b], #488]\n\t"
  26524. "AND r4, r4, r3\n\t"
  26525. "AND r5, r5, r3\n\t"
  26526. "SUBS r4, r4, r5\n\t"
  26527. "IT hi\n\t"
  26528. "movhi r2, r8\n\t"
  26529. "IT lo\n\t"
  26530. "movlo r2, r3\n\t"
  26531. "IT ne\n\t"
  26532. "movne r3, r7\n\t"
  26533. "LDR r4, [%[a], #484]\n\t"
  26534. "LDR r5, [%[b], #484]\n\t"
  26535. "AND r4, r4, r3\n\t"
  26536. "AND r5, r5, r3\n\t"
  26537. "SUBS r4, r4, r5\n\t"
  26538. "IT hi\n\t"
  26539. "movhi r2, r8\n\t"
  26540. "IT lo\n\t"
  26541. "movlo r2, r3\n\t"
  26542. "IT ne\n\t"
  26543. "movne r3, r7\n\t"
  26544. "LDR r4, [%[a], #480]\n\t"
  26545. "LDR r5, [%[b], #480]\n\t"
  26546. "AND r4, r4, r3\n\t"
  26547. "AND r5, r5, r3\n\t"
  26548. "SUBS r4, r4, r5\n\t"
  26549. "IT hi\n\t"
  26550. "movhi r2, r8\n\t"
  26551. "IT lo\n\t"
  26552. "movlo r2, r3\n\t"
  26553. "IT ne\n\t"
  26554. "movne r3, r7\n\t"
  26555. "LDR r4, [%[a], #476]\n\t"
  26556. "LDR r5, [%[b], #476]\n\t"
  26557. "AND r4, r4, r3\n\t"
  26558. "AND r5, r5, r3\n\t"
  26559. "SUBS r4, r4, r5\n\t"
  26560. "IT hi\n\t"
  26561. "movhi r2, r8\n\t"
  26562. "IT lo\n\t"
  26563. "movlo r2, r3\n\t"
  26564. "IT ne\n\t"
  26565. "movne r3, r7\n\t"
  26566. "LDR r4, [%[a], #472]\n\t"
  26567. "LDR r5, [%[b], #472]\n\t"
  26568. "AND r4, r4, r3\n\t"
  26569. "AND r5, r5, r3\n\t"
  26570. "SUBS r4, r4, r5\n\t"
  26571. "IT hi\n\t"
  26572. "movhi r2, r8\n\t"
  26573. "IT lo\n\t"
  26574. "movlo r2, r3\n\t"
  26575. "IT ne\n\t"
  26576. "movne r3, r7\n\t"
  26577. "LDR r4, [%[a], #468]\n\t"
  26578. "LDR r5, [%[b], #468]\n\t"
  26579. "AND r4, r4, r3\n\t"
  26580. "AND r5, r5, r3\n\t"
  26581. "SUBS r4, r4, r5\n\t"
  26582. "IT hi\n\t"
  26583. "movhi r2, r8\n\t"
  26584. "IT lo\n\t"
  26585. "movlo r2, r3\n\t"
  26586. "IT ne\n\t"
  26587. "movne r3, r7\n\t"
  26588. "LDR r4, [%[a], #464]\n\t"
  26589. "LDR r5, [%[b], #464]\n\t"
  26590. "AND r4, r4, r3\n\t"
  26591. "AND r5, r5, r3\n\t"
  26592. "SUBS r4, r4, r5\n\t"
  26593. "IT hi\n\t"
  26594. "movhi r2, r8\n\t"
  26595. "IT lo\n\t"
  26596. "movlo r2, r3\n\t"
  26597. "IT ne\n\t"
  26598. "movne r3, r7\n\t"
  26599. "LDR r4, [%[a], #460]\n\t"
  26600. "LDR r5, [%[b], #460]\n\t"
  26601. "AND r4, r4, r3\n\t"
  26602. "AND r5, r5, r3\n\t"
  26603. "SUBS r4, r4, r5\n\t"
  26604. "IT hi\n\t"
  26605. "movhi r2, r8\n\t"
  26606. "IT lo\n\t"
  26607. "movlo r2, r3\n\t"
  26608. "IT ne\n\t"
  26609. "movne r3, r7\n\t"
  26610. "LDR r4, [%[a], #456]\n\t"
  26611. "LDR r5, [%[b], #456]\n\t"
  26612. "AND r4, r4, r3\n\t"
  26613. "AND r5, r5, r3\n\t"
  26614. "SUBS r4, r4, r5\n\t"
  26615. "IT hi\n\t"
  26616. "movhi r2, r8\n\t"
  26617. "IT lo\n\t"
  26618. "movlo r2, r3\n\t"
  26619. "IT ne\n\t"
  26620. "movne r3, r7\n\t"
  26621. "LDR r4, [%[a], #452]\n\t"
  26622. "LDR r5, [%[b], #452]\n\t"
  26623. "AND r4, r4, r3\n\t"
  26624. "AND r5, r5, r3\n\t"
  26625. "SUBS r4, r4, r5\n\t"
  26626. "IT hi\n\t"
  26627. "movhi r2, r8\n\t"
  26628. "IT lo\n\t"
  26629. "movlo r2, r3\n\t"
  26630. "IT ne\n\t"
  26631. "movne r3, r7\n\t"
  26632. "LDR r4, [%[a], #448]\n\t"
  26633. "LDR r5, [%[b], #448]\n\t"
  26634. "AND r4, r4, r3\n\t"
  26635. "AND r5, r5, r3\n\t"
  26636. "SUBS r4, r4, r5\n\t"
  26637. "IT hi\n\t"
  26638. "movhi r2, r8\n\t"
  26639. "IT lo\n\t"
  26640. "movlo r2, r3\n\t"
  26641. "IT ne\n\t"
  26642. "movne r3, r7\n\t"
  26643. "LDR r4, [%[a], #444]\n\t"
  26644. "LDR r5, [%[b], #444]\n\t"
  26645. "AND r4, r4, r3\n\t"
  26646. "AND r5, r5, r3\n\t"
  26647. "SUBS r4, r4, r5\n\t"
  26648. "IT hi\n\t"
  26649. "movhi r2, r8\n\t"
  26650. "IT lo\n\t"
  26651. "movlo r2, r3\n\t"
  26652. "IT ne\n\t"
  26653. "movne r3, r7\n\t"
  26654. "LDR r4, [%[a], #440]\n\t"
  26655. "LDR r5, [%[b], #440]\n\t"
  26656. "AND r4, r4, r3\n\t"
  26657. "AND r5, r5, r3\n\t"
  26658. "SUBS r4, r4, r5\n\t"
  26659. "IT hi\n\t"
  26660. "movhi r2, r8\n\t"
  26661. "IT lo\n\t"
  26662. "movlo r2, r3\n\t"
  26663. "IT ne\n\t"
  26664. "movne r3, r7\n\t"
  26665. "LDR r4, [%[a], #436]\n\t"
  26666. "LDR r5, [%[b], #436]\n\t"
  26667. "AND r4, r4, r3\n\t"
  26668. "AND r5, r5, r3\n\t"
  26669. "SUBS r4, r4, r5\n\t"
  26670. "IT hi\n\t"
  26671. "movhi r2, r8\n\t"
  26672. "IT lo\n\t"
  26673. "movlo r2, r3\n\t"
  26674. "IT ne\n\t"
  26675. "movne r3, r7\n\t"
  26676. "LDR r4, [%[a], #432]\n\t"
  26677. "LDR r5, [%[b], #432]\n\t"
  26678. "AND r4, r4, r3\n\t"
  26679. "AND r5, r5, r3\n\t"
  26680. "SUBS r4, r4, r5\n\t"
  26681. "IT hi\n\t"
  26682. "movhi r2, r8\n\t"
  26683. "IT lo\n\t"
  26684. "movlo r2, r3\n\t"
  26685. "IT ne\n\t"
  26686. "movne r3, r7\n\t"
  26687. "LDR r4, [%[a], #428]\n\t"
  26688. "LDR r5, [%[b], #428]\n\t"
  26689. "AND r4, r4, r3\n\t"
  26690. "AND r5, r5, r3\n\t"
  26691. "SUBS r4, r4, r5\n\t"
  26692. "IT hi\n\t"
  26693. "movhi r2, r8\n\t"
  26694. "IT lo\n\t"
  26695. "movlo r2, r3\n\t"
  26696. "IT ne\n\t"
  26697. "movne r3, r7\n\t"
  26698. "LDR r4, [%[a], #424]\n\t"
  26699. "LDR r5, [%[b], #424]\n\t"
  26700. "AND r4, r4, r3\n\t"
  26701. "AND r5, r5, r3\n\t"
  26702. "SUBS r4, r4, r5\n\t"
  26703. "IT hi\n\t"
  26704. "movhi r2, r8\n\t"
  26705. "IT lo\n\t"
  26706. "movlo r2, r3\n\t"
  26707. "IT ne\n\t"
  26708. "movne r3, r7\n\t"
  26709. "LDR r4, [%[a], #420]\n\t"
  26710. "LDR r5, [%[b], #420]\n\t"
  26711. "AND r4, r4, r3\n\t"
  26712. "AND r5, r5, r3\n\t"
  26713. "SUBS r4, r4, r5\n\t"
  26714. "IT hi\n\t"
  26715. "movhi r2, r8\n\t"
  26716. "IT lo\n\t"
  26717. "movlo r2, r3\n\t"
  26718. "IT ne\n\t"
  26719. "movne r3, r7\n\t"
  26720. "LDR r4, [%[a], #416]\n\t"
  26721. "LDR r5, [%[b], #416]\n\t"
  26722. "AND r4, r4, r3\n\t"
  26723. "AND r5, r5, r3\n\t"
  26724. "SUBS r4, r4, r5\n\t"
  26725. "IT hi\n\t"
  26726. "movhi r2, r8\n\t"
  26727. "IT lo\n\t"
  26728. "movlo r2, r3\n\t"
  26729. "IT ne\n\t"
  26730. "movne r3, r7\n\t"
  26731. "LDR r4, [%[a], #412]\n\t"
  26732. "LDR r5, [%[b], #412]\n\t"
  26733. "AND r4, r4, r3\n\t"
  26734. "AND r5, r5, r3\n\t"
  26735. "SUBS r4, r4, r5\n\t"
  26736. "IT hi\n\t"
  26737. "movhi r2, r8\n\t"
  26738. "IT lo\n\t"
  26739. "movlo r2, r3\n\t"
  26740. "IT ne\n\t"
  26741. "movne r3, r7\n\t"
  26742. "LDR r4, [%[a], #408]\n\t"
  26743. "LDR r5, [%[b], #408]\n\t"
  26744. "AND r4, r4, r3\n\t"
  26745. "AND r5, r5, r3\n\t"
  26746. "SUBS r4, r4, r5\n\t"
  26747. "IT hi\n\t"
  26748. "movhi r2, r8\n\t"
  26749. "IT lo\n\t"
  26750. "movlo r2, r3\n\t"
  26751. "IT ne\n\t"
  26752. "movne r3, r7\n\t"
  26753. "LDR r4, [%[a], #404]\n\t"
  26754. "LDR r5, [%[b], #404]\n\t"
  26755. "AND r4, r4, r3\n\t"
  26756. "AND r5, r5, r3\n\t"
  26757. "SUBS r4, r4, r5\n\t"
  26758. "IT hi\n\t"
  26759. "movhi r2, r8\n\t"
  26760. "IT lo\n\t"
  26761. "movlo r2, r3\n\t"
  26762. "IT ne\n\t"
  26763. "movne r3, r7\n\t"
  26764. "LDR r4, [%[a], #400]\n\t"
  26765. "LDR r5, [%[b], #400]\n\t"
  26766. "AND r4, r4, r3\n\t"
  26767. "AND r5, r5, r3\n\t"
  26768. "SUBS r4, r4, r5\n\t"
  26769. "IT hi\n\t"
  26770. "movhi r2, r8\n\t"
  26771. "IT lo\n\t"
  26772. "movlo r2, r3\n\t"
  26773. "IT ne\n\t"
  26774. "movne r3, r7\n\t"
  26775. "LDR r4, [%[a], #396]\n\t"
  26776. "LDR r5, [%[b], #396]\n\t"
  26777. "AND r4, r4, r3\n\t"
  26778. "AND r5, r5, r3\n\t"
  26779. "SUBS r4, r4, r5\n\t"
  26780. "IT hi\n\t"
  26781. "movhi r2, r8\n\t"
  26782. "IT lo\n\t"
  26783. "movlo r2, r3\n\t"
  26784. "IT ne\n\t"
  26785. "movne r3, r7\n\t"
  26786. "LDR r4, [%[a], #392]\n\t"
  26787. "LDR r5, [%[b], #392]\n\t"
  26788. "AND r4, r4, r3\n\t"
  26789. "AND r5, r5, r3\n\t"
  26790. "SUBS r4, r4, r5\n\t"
  26791. "IT hi\n\t"
  26792. "movhi r2, r8\n\t"
  26793. "IT lo\n\t"
  26794. "movlo r2, r3\n\t"
  26795. "IT ne\n\t"
  26796. "movne r3, r7\n\t"
  26797. "LDR r4, [%[a], #388]\n\t"
  26798. "LDR r5, [%[b], #388]\n\t"
  26799. "AND r4, r4, r3\n\t"
  26800. "AND r5, r5, r3\n\t"
  26801. "SUBS r4, r4, r5\n\t"
  26802. "IT hi\n\t"
  26803. "movhi r2, r8\n\t"
  26804. "IT lo\n\t"
  26805. "movlo r2, r3\n\t"
  26806. "IT ne\n\t"
  26807. "movne r3, r7\n\t"
  26808. "LDR r4, [%[a], #384]\n\t"
  26809. "LDR r5, [%[b], #384]\n\t"
  26810. "AND r4, r4, r3\n\t"
  26811. "AND r5, r5, r3\n\t"
  26812. "SUBS r4, r4, r5\n\t"
  26813. "IT hi\n\t"
  26814. "movhi r2, r8\n\t"
  26815. "IT lo\n\t"
  26816. "movlo r2, r3\n\t"
  26817. "IT ne\n\t"
  26818. "movne r3, r7\n\t"
  26819. "LDR r4, [%[a], #380]\n\t"
  26820. "LDR r5, [%[b], #380]\n\t"
  26821. "AND r4, r4, r3\n\t"
  26822. "AND r5, r5, r3\n\t"
  26823. "SUBS r4, r4, r5\n\t"
  26824. "IT hi\n\t"
  26825. "movhi r2, r8\n\t"
  26826. "IT lo\n\t"
  26827. "movlo r2, r3\n\t"
  26828. "IT ne\n\t"
  26829. "movne r3, r7\n\t"
  26830. "LDR r4, [%[a], #376]\n\t"
  26831. "LDR r5, [%[b], #376]\n\t"
  26832. "AND r4, r4, r3\n\t"
  26833. "AND r5, r5, r3\n\t"
  26834. "SUBS r4, r4, r5\n\t"
  26835. "IT hi\n\t"
  26836. "movhi r2, r8\n\t"
  26837. "IT lo\n\t"
  26838. "movlo r2, r3\n\t"
  26839. "IT ne\n\t"
  26840. "movne r3, r7\n\t"
  26841. "LDR r4, [%[a], #372]\n\t"
  26842. "LDR r5, [%[b], #372]\n\t"
  26843. "AND r4, r4, r3\n\t"
  26844. "AND r5, r5, r3\n\t"
  26845. "SUBS r4, r4, r5\n\t"
  26846. "IT hi\n\t"
  26847. "movhi r2, r8\n\t"
  26848. "IT lo\n\t"
  26849. "movlo r2, r3\n\t"
  26850. "IT ne\n\t"
  26851. "movne r3, r7\n\t"
  26852. "LDR r4, [%[a], #368]\n\t"
  26853. "LDR r5, [%[b], #368]\n\t"
  26854. "AND r4, r4, r3\n\t"
  26855. "AND r5, r5, r3\n\t"
  26856. "SUBS r4, r4, r5\n\t"
  26857. "IT hi\n\t"
  26858. "movhi r2, r8\n\t"
  26859. "IT lo\n\t"
  26860. "movlo r2, r3\n\t"
  26861. "IT ne\n\t"
  26862. "movne r3, r7\n\t"
  26863. "LDR r4, [%[a], #364]\n\t"
  26864. "LDR r5, [%[b], #364]\n\t"
  26865. "AND r4, r4, r3\n\t"
  26866. "AND r5, r5, r3\n\t"
  26867. "SUBS r4, r4, r5\n\t"
  26868. "IT hi\n\t"
  26869. "movhi r2, r8\n\t"
  26870. "IT lo\n\t"
  26871. "movlo r2, r3\n\t"
  26872. "IT ne\n\t"
  26873. "movne r3, r7\n\t"
  26874. "LDR r4, [%[a], #360]\n\t"
  26875. "LDR r5, [%[b], #360]\n\t"
  26876. "AND r4, r4, r3\n\t"
  26877. "AND r5, r5, r3\n\t"
  26878. "SUBS r4, r4, r5\n\t"
  26879. "IT hi\n\t"
  26880. "movhi r2, r8\n\t"
  26881. "IT lo\n\t"
  26882. "movlo r2, r3\n\t"
  26883. "IT ne\n\t"
  26884. "movne r3, r7\n\t"
  26885. "LDR r4, [%[a], #356]\n\t"
  26886. "LDR r5, [%[b], #356]\n\t"
  26887. "AND r4, r4, r3\n\t"
  26888. "AND r5, r5, r3\n\t"
  26889. "SUBS r4, r4, r5\n\t"
  26890. "IT hi\n\t"
  26891. "movhi r2, r8\n\t"
  26892. "IT lo\n\t"
  26893. "movlo r2, r3\n\t"
  26894. "IT ne\n\t"
  26895. "movne r3, r7\n\t"
  26896. "LDR r4, [%[a], #352]\n\t"
  26897. "LDR r5, [%[b], #352]\n\t"
  26898. "AND r4, r4, r3\n\t"
  26899. "AND r5, r5, r3\n\t"
  26900. "SUBS r4, r4, r5\n\t"
  26901. "IT hi\n\t"
  26902. "movhi r2, r8\n\t"
  26903. "IT lo\n\t"
  26904. "movlo r2, r3\n\t"
  26905. "IT ne\n\t"
  26906. "movne r3, r7\n\t"
  26907. "LDR r4, [%[a], #348]\n\t"
  26908. "LDR r5, [%[b], #348]\n\t"
  26909. "AND r4, r4, r3\n\t"
  26910. "AND r5, r5, r3\n\t"
  26911. "SUBS r4, r4, r5\n\t"
  26912. "IT hi\n\t"
  26913. "movhi r2, r8\n\t"
  26914. "IT lo\n\t"
  26915. "movlo r2, r3\n\t"
  26916. "IT ne\n\t"
  26917. "movne r3, r7\n\t"
  26918. "LDR r4, [%[a], #344]\n\t"
  26919. "LDR r5, [%[b], #344]\n\t"
  26920. "AND r4, r4, r3\n\t"
  26921. "AND r5, r5, r3\n\t"
  26922. "SUBS r4, r4, r5\n\t"
  26923. "IT hi\n\t"
  26924. "movhi r2, r8\n\t"
  26925. "IT lo\n\t"
  26926. "movlo r2, r3\n\t"
  26927. "IT ne\n\t"
  26928. "movne r3, r7\n\t"
  26929. "LDR r4, [%[a], #340]\n\t"
  26930. "LDR r5, [%[b], #340]\n\t"
  26931. "AND r4, r4, r3\n\t"
  26932. "AND r5, r5, r3\n\t"
  26933. "SUBS r4, r4, r5\n\t"
  26934. "IT hi\n\t"
  26935. "movhi r2, r8\n\t"
  26936. "IT lo\n\t"
  26937. "movlo r2, r3\n\t"
  26938. "IT ne\n\t"
  26939. "movne r3, r7\n\t"
  26940. "LDR r4, [%[a], #336]\n\t"
  26941. "LDR r5, [%[b], #336]\n\t"
  26942. "AND r4, r4, r3\n\t"
  26943. "AND r5, r5, r3\n\t"
  26944. "SUBS r4, r4, r5\n\t"
  26945. "IT hi\n\t"
  26946. "movhi r2, r8\n\t"
  26947. "IT lo\n\t"
  26948. "movlo r2, r3\n\t"
  26949. "IT ne\n\t"
  26950. "movne r3, r7\n\t"
  26951. "LDR r4, [%[a], #332]\n\t"
  26952. "LDR r5, [%[b], #332]\n\t"
  26953. "AND r4, r4, r3\n\t"
  26954. "AND r5, r5, r3\n\t"
  26955. "SUBS r4, r4, r5\n\t"
  26956. "IT hi\n\t"
  26957. "movhi r2, r8\n\t"
  26958. "IT lo\n\t"
  26959. "movlo r2, r3\n\t"
  26960. "IT ne\n\t"
  26961. "movne r3, r7\n\t"
  26962. "LDR r4, [%[a], #328]\n\t"
  26963. "LDR r5, [%[b], #328]\n\t"
  26964. "AND r4, r4, r3\n\t"
  26965. "AND r5, r5, r3\n\t"
  26966. "SUBS r4, r4, r5\n\t"
  26967. "IT hi\n\t"
  26968. "movhi r2, r8\n\t"
  26969. "IT lo\n\t"
  26970. "movlo r2, r3\n\t"
  26971. "IT ne\n\t"
  26972. "movne r3, r7\n\t"
  26973. "LDR r4, [%[a], #324]\n\t"
  26974. "LDR r5, [%[b], #324]\n\t"
  26975. "AND r4, r4, r3\n\t"
  26976. "AND r5, r5, r3\n\t"
  26977. "SUBS r4, r4, r5\n\t"
  26978. "IT hi\n\t"
  26979. "movhi r2, r8\n\t"
  26980. "IT lo\n\t"
  26981. "movlo r2, r3\n\t"
  26982. "IT ne\n\t"
  26983. "movne r3, r7\n\t"
  26984. "LDR r4, [%[a], #320]\n\t"
  26985. "LDR r5, [%[b], #320]\n\t"
  26986. "AND r4, r4, r3\n\t"
  26987. "AND r5, r5, r3\n\t"
  26988. "SUBS r4, r4, r5\n\t"
  26989. "IT hi\n\t"
  26990. "movhi r2, r8\n\t"
  26991. "IT lo\n\t"
  26992. "movlo r2, r3\n\t"
  26993. "IT ne\n\t"
  26994. "movne r3, r7\n\t"
  26995. "LDR r4, [%[a], #316]\n\t"
  26996. "LDR r5, [%[b], #316]\n\t"
  26997. "AND r4, r4, r3\n\t"
  26998. "AND r5, r5, r3\n\t"
  26999. "SUBS r4, r4, r5\n\t"
  27000. "IT hi\n\t"
  27001. "movhi r2, r8\n\t"
  27002. "IT lo\n\t"
  27003. "movlo r2, r3\n\t"
  27004. "IT ne\n\t"
  27005. "movne r3, r7\n\t"
  27006. "LDR r4, [%[a], #312]\n\t"
  27007. "LDR r5, [%[b], #312]\n\t"
  27008. "AND r4, r4, r3\n\t"
  27009. "AND r5, r5, r3\n\t"
  27010. "SUBS r4, r4, r5\n\t"
  27011. "IT hi\n\t"
  27012. "movhi r2, r8\n\t"
  27013. "IT lo\n\t"
  27014. "movlo r2, r3\n\t"
  27015. "IT ne\n\t"
  27016. "movne r3, r7\n\t"
  27017. "LDR r4, [%[a], #308]\n\t"
  27018. "LDR r5, [%[b], #308]\n\t"
  27019. "AND r4, r4, r3\n\t"
  27020. "AND r5, r5, r3\n\t"
  27021. "SUBS r4, r4, r5\n\t"
  27022. "IT hi\n\t"
  27023. "movhi r2, r8\n\t"
  27024. "IT lo\n\t"
  27025. "movlo r2, r3\n\t"
  27026. "IT ne\n\t"
  27027. "movne r3, r7\n\t"
  27028. "LDR r4, [%[a], #304]\n\t"
  27029. "LDR r5, [%[b], #304]\n\t"
  27030. "AND r4, r4, r3\n\t"
  27031. "AND r5, r5, r3\n\t"
  27032. "SUBS r4, r4, r5\n\t"
  27033. "IT hi\n\t"
  27034. "movhi r2, r8\n\t"
  27035. "IT lo\n\t"
  27036. "movlo r2, r3\n\t"
  27037. "IT ne\n\t"
  27038. "movne r3, r7\n\t"
  27039. "LDR r4, [%[a], #300]\n\t"
  27040. "LDR r5, [%[b], #300]\n\t"
  27041. "AND r4, r4, r3\n\t"
  27042. "AND r5, r5, r3\n\t"
  27043. "SUBS r4, r4, r5\n\t"
  27044. "IT hi\n\t"
  27045. "movhi r2, r8\n\t"
  27046. "IT lo\n\t"
  27047. "movlo r2, r3\n\t"
  27048. "IT ne\n\t"
  27049. "movne r3, r7\n\t"
  27050. "LDR r4, [%[a], #296]\n\t"
  27051. "LDR r5, [%[b], #296]\n\t"
  27052. "AND r4, r4, r3\n\t"
  27053. "AND r5, r5, r3\n\t"
  27054. "SUBS r4, r4, r5\n\t"
  27055. "IT hi\n\t"
  27056. "movhi r2, r8\n\t"
  27057. "IT lo\n\t"
  27058. "movlo r2, r3\n\t"
  27059. "IT ne\n\t"
  27060. "movne r3, r7\n\t"
  27061. "LDR r4, [%[a], #292]\n\t"
  27062. "LDR r5, [%[b], #292]\n\t"
  27063. "AND r4, r4, r3\n\t"
  27064. "AND r5, r5, r3\n\t"
  27065. "SUBS r4, r4, r5\n\t"
  27066. "IT hi\n\t"
  27067. "movhi r2, r8\n\t"
  27068. "IT lo\n\t"
  27069. "movlo r2, r3\n\t"
  27070. "IT ne\n\t"
  27071. "movne r3, r7\n\t"
  27072. "LDR r4, [%[a], #288]\n\t"
  27073. "LDR r5, [%[b], #288]\n\t"
  27074. "AND r4, r4, r3\n\t"
  27075. "AND r5, r5, r3\n\t"
  27076. "SUBS r4, r4, r5\n\t"
  27077. "IT hi\n\t"
  27078. "movhi r2, r8\n\t"
  27079. "IT lo\n\t"
  27080. "movlo r2, r3\n\t"
  27081. "IT ne\n\t"
  27082. "movne r3, r7\n\t"
  27083. "LDR r4, [%[a], #284]\n\t"
  27084. "LDR r5, [%[b], #284]\n\t"
  27085. "AND r4, r4, r3\n\t"
  27086. "AND r5, r5, r3\n\t"
  27087. "SUBS r4, r4, r5\n\t"
  27088. "IT hi\n\t"
  27089. "movhi r2, r8\n\t"
  27090. "IT lo\n\t"
  27091. "movlo r2, r3\n\t"
  27092. "IT ne\n\t"
  27093. "movne r3, r7\n\t"
  27094. "LDR r4, [%[a], #280]\n\t"
  27095. "LDR r5, [%[b], #280]\n\t"
  27096. "AND r4, r4, r3\n\t"
  27097. "AND r5, r5, r3\n\t"
  27098. "SUBS r4, r4, r5\n\t"
  27099. "IT hi\n\t"
  27100. "movhi r2, r8\n\t"
  27101. "IT lo\n\t"
  27102. "movlo r2, r3\n\t"
  27103. "IT ne\n\t"
  27104. "movne r3, r7\n\t"
  27105. "LDR r4, [%[a], #276]\n\t"
  27106. "LDR r5, [%[b], #276]\n\t"
  27107. "AND r4, r4, r3\n\t"
  27108. "AND r5, r5, r3\n\t"
  27109. "SUBS r4, r4, r5\n\t"
  27110. "IT hi\n\t"
  27111. "movhi r2, r8\n\t"
  27112. "IT lo\n\t"
  27113. "movlo r2, r3\n\t"
  27114. "IT ne\n\t"
  27115. "movne r3, r7\n\t"
  27116. "LDR r4, [%[a], #272]\n\t"
  27117. "LDR r5, [%[b], #272]\n\t"
  27118. "AND r4, r4, r3\n\t"
  27119. "AND r5, r5, r3\n\t"
  27120. "SUBS r4, r4, r5\n\t"
  27121. "IT hi\n\t"
  27122. "movhi r2, r8\n\t"
  27123. "IT lo\n\t"
  27124. "movlo r2, r3\n\t"
  27125. "IT ne\n\t"
  27126. "movne r3, r7\n\t"
  27127. "LDR r4, [%[a], #268]\n\t"
  27128. "LDR r5, [%[b], #268]\n\t"
  27129. "AND r4, r4, r3\n\t"
  27130. "AND r5, r5, r3\n\t"
  27131. "SUBS r4, r4, r5\n\t"
  27132. "IT hi\n\t"
  27133. "movhi r2, r8\n\t"
  27134. "IT lo\n\t"
  27135. "movlo r2, r3\n\t"
  27136. "IT ne\n\t"
  27137. "movne r3, r7\n\t"
  27138. "LDR r4, [%[a], #264]\n\t"
  27139. "LDR r5, [%[b], #264]\n\t"
  27140. "AND r4, r4, r3\n\t"
  27141. "AND r5, r5, r3\n\t"
  27142. "SUBS r4, r4, r5\n\t"
  27143. "IT hi\n\t"
  27144. "movhi r2, r8\n\t"
  27145. "IT lo\n\t"
  27146. "movlo r2, r3\n\t"
  27147. "IT ne\n\t"
  27148. "movne r3, r7\n\t"
  27149. "LDR r4, [%[a], #260]\n\t"
  27150. "LDR r5, [%[b], #260]\n\t"
  27151. "AND r4, r4, r3\n\t"
  27152. "AND r5, r5, r3\n\t"
  27153. "SUBS r4, r4, r5\n\t"
  27154. "IT hi\n\t"
  27155. "movhi r2, r8\n\t"
  27156. "IT lo\n\t"
  27157. "movlo r2, r3\n\t"
  27158. "IT ne\n\t"
  27159. "movne r3, r7\n\t"
  27160. "LDR r4, [%[a], #256]\n\t"
  27161. "LDR r5, [%[b], #256]\n\t"
  27162. "AND r4, r4, r3\n\t"
  27163. "AND r5, r5, r3\n\t"
  27164. "SUBS r4, r4, r5\n\t"
  27165. "IT hi\n\t"
  27166. "movhi r2, r8\n\t"
  27167. "IT lo\n\t"
  27168. "movlo r2, r3\n\t"
  27169. "IT ne\n\t"
  27170. "movne r3, r7\n\t"
  27171. "LDR r4, [%[a], #252]\n\t"
  27172. "LDR r5, [%[b], #252]\n\t"
  27173. "AND r4, r4, r3\n\t"
  27174. "AND r5, r5, r3\n\t"
  27175. "SUBS r4, r4, r5\n\t"
  27176. "IT hi\n\t"
  27177. "movhi r2, r8\n\t"
  27178. "IT lo\n\t"
  27179. "movlo r2, r3\n\t"
  27180. "IT ne\n\t"
  27181. "movne r3, r7\n\t"
  27182. "LDR r4, [%[a], #248]\n\t"
  27183. "LDR r5, [%[b], #248]\n\t"
  27184. "AND r4, r4, r3\n\t"
  27185. "AND r5, r5, r3\n\t"
  27186. "SUBS r4, r4, r5\n\t"
  27187. "IT hi\n\t"
  27188. "movhi r2, r8\n\t"
  27189. "IT lo\n\t"
  27190. "movlo r2, r3\n\t"
  27191. "IT ne\n\t"
  27192. "movne r3, r7\n\t"
  27193. "LDR r4, [%[a], #244]\n\t"
  27194. "LDR r5, [%[b], #244]\n\t"
  27195. "AND r4, r4, r3\n\t"
  27196. "AND r5, r5, r3\n\t"
  27197. "SUBS r4, r4, r5\n\t"
  27198. "IT hi\n\t"
  27199. "movhi r2, r8\n\t"
  27200. "IT lo\n\t"
  27201. "movlo r2, r3\n\t"
  27202. "IT ne\n\t"
  27203. "movne r3, r7\n\t"
  27204. "LDR r4, [%[a], #240]\n\t"
  27205. "LDR r5, [%[b], #240]\n\t"
  27206. "AND r4, r4, r3\n\t"
  27207. "AND r5, r5, r3\n\t"
  27208. "SUBS r4, r4, r5\n\t"
  27209. "IT hi\n\t"
  27210. "movhi r2, r8\n\t"
  27211. "IT lo\n\t"
  27212. "movlo r2, r3\n\t"
  27213. "IT ne\n\t"
  27214. "movne r3, r7\n\t"
  27215. "LDR r4, [%[a], #236]\n\t"
  27216. "LDR r5, [%[b], #236]\n\t"
  27217. "AND r4, r4, r3\n\t"
  27218. "AND r5, r5, r3\n\t"
  27219. "SUBS r4, r4, r5\n\t"
  27220. "IT hi\n\t"
  27221. "movhi r2, r8\n\t"
  27222. "IT lo\n\t"
  27223. "movlo r2, r3\n\t"
  27224. "IT ne\n\t"
  27225. "movne r3, r7\n\t"
  27226. "LDR r4, [%[a], #232]\n\t"
  27227. "LDR r5, [%[b], #232]\n\t"
  27228. "AND r4, r4, r3\n\t"
  27229. "AND r5, r5, r3\n\t"
  27230. "SUBS r4, r4, r5\n\t"
  27231. "IT hi\n\t"
  27232. "movhi r2, r8\n\t"
  27233. "IT lo\n\t"
  27234. "movlo r2, r3\n\t"
  27235. "IT ne\n\t"
  27236. "movne r3, r7\n\t"
  27237. "LDR r4, [%[a], #228]\n\t"
  27238. "LDR r5, [%[b], #228]\n\t"
  27239. "AND r4, r4, r3\n\t"
  27240. "AND r5, r5, r3\n\t"
  27241. "SUBS r4, r4, r5\n\t"
  27242. "IT hi\n\t"
  27243. "movhi r2, r8\n\t"
  27244. "IT lo\n\t"
  27245. "movlo r2, r3\n\t"
  27246. "IT ne\n\t"
  27247. "movne r3, r7\n\t"
  27248. "LDR r4, [%[a], #224]\n\t"
  27249. "LDR r5, [%[b], #224]\n\t"
  27250. "AND r4, r4, r3\n\t"
  27251. "AND r5, r5, r3\n\t"
  27252. "SUBS r4, r4, r5\n\t"
  27253. "IT hi\n\t"
  27254. "movhi r2, r8\n\t"
  27255. "IT lo\n\t"
  27256. "movlo r2, r3\n\t"
  27257. "IT ne\n\t"
  27258. "movne r3, r7\n\t"
  27259. "LDR r4, [%[a], #220]\n\t"
  27260. "LDR r5, [%[b], #220]\n\t"
  27261. "AND r4, r4, r3\n\t"
  27262. "AND r5, r5, r3\n\t"
  27263. "SUBS r4, r4, r5\n\t"
  27264. "IT hi\n\t"
  27265. "movhi r2, r8\n\t"
  27266. "IT lo\n\t"
  27267. "movlo r2, r3\n\t"
  27268. "IT ne\n\t"
  27269. "movne r3, r7\n\t"
  27270. "LDR r4, [%[a], #216]\n\t"
  27271. "LDR r5, [%[b], #216]\n\t"
  27272. "AND r4, r4, r3\n\t"
  27273. "AND r5, r5, r3\n\t"
  27274. "SUBS r4, r4, r5\n\t"
  27275. "IT hi\n\t"
  27276. "movhi r2, r8\n\t"
  27277. "IT lo\n\t"
  27278. "movlo r2, r3\n\t"
  27279. "IT ne\n\t"
  27280. "movne r3, r7\n\t"
  27281. "LDR r4, [%[a], #212]\n\t"
  27282. "LDR r5, [%[b], #212]\n\t"
  27283. "AND r4, r4, r3\n\t"
  27284. "AND r5, r5, r3\n\t"
  27285. "SUBS r4, r4, r5\n\t"
  27286. "IT hi\n\t"
  27287. "movhi r2, r8\n\t"
  27288. "IT lo\n\t"
  27289. "movlo r2, r3\n\t"
  27290. "IT ne\n\t"
  27291. "movne r3, r7\n\t"
  27292. "LDR r4, [%[a], #208]\n\t"
  27293. "LDR r5, [%[b], #208]\n\t"
  27294. "AND r4, r4, r3\n\t"
  27295. "AND r5, r5, r3\n\t"
  27296. "SUBS r4, r4, r5\n\t"
  27297. "IT hi\n\t"
  27298. "movhi r2, r8\n\t"
  27299. "IT lo\n\t"
  27300. "movlo r2, r3\n\t"
  27301. "IT ne\n\t"
  27302. "movne r3, r7\n\t"
  27303. "LDR r4, [%[a], #204]\n\t"
  27304. "LDR r5, [%[b], #204]\n\t"
  27305. "AND r4, r4, r3\n\t"
  27306. "AND r5, r5, r3\n\t"
  27307. "SUBS r4, r4, r5\n\t"
  27308. "IT hi\n\t"
  27309. "movhi r2, r8\n\t"
  27310. "IT lo\n\t"
  27311. "movlo r2, r3\n\t"
  27312. "IT ne\n\t"
  27313. "movne r3, r7\n\t"
  27314. "LDR r4, [%[a], #200]\n\t"
  27315. "LDR r5, [%[b], #200]\n\t"
  27316. "AND r4, r4, r3\n\t"
  27317. "AND r5, r5, r3\n\t"
  27318. "SUBS r4, r4, r5\n\t"
  27319. "IT hi\n\t"
  27320. "movhi r2, r8\n\t"
  27321. "IT lo\n\t"
  27322. "movlo r2, r3\n\t"
  27323. "IT ne\n\t"
  27324. "movne r3, r7\n\t"
  27325. "LDR r4, [%[a], #196]\n\t"
  27326. "LDR r5, [%[b], #196]\n\t"
  27327. "AND r4, r4, r3\n\t"
  27328. "AND r5, r5, r3\n\t"
  27329. "SUBS r4, r4, r5\n\t"
  27330. "IT hi\n\t"
  27331. "movhi r2, r8\n\t"
  27332. "IT lo\n\t"
  27333. "movlo r2, r3\n\t"
  27334. "IT ne\n\t"
  27335. "movne r3, r7\n\t"
  27336. "LDR r4, [%[a], #192]\n\t"
  27337. "LDR r5, [%[b], #192]\n\t"
  27338. "AND r4, r4, r3\n\t"
  27339. "AND r5, r5, r3\n\t"
  27340. "SUBS r4, r4, r5\n\t"
  27341. "IT hi\n\t"
  27342. "movhi r2, r8\n\t"
  27343. "IT lo\n\t"
  27344. "movlo r2, r3\n\t"
  27345. "IT ne\n\t"
  27346. "movne r3, r7\n\t"
  27347. "LDR r4, [%[a], #188]\n\t"
  27348. "LDR r5, [%[b], #188]\n\t"
  27349. "AND r4, r4, r3\n\t"
  27350. "AND r5, r5, r3\n\t"
  27351. "SUBS r4, r4, r5\n\t"
  27352. "IT hi\n\t"
  27353. "movhi r2, r8\n\t"
  27354. "IT lo\n\t"
  27355. "movlo r2, r3\n\t"
  27356. "IT ne\n\t"
  27357. "movne r3, r7\n\t"
  27358. "LDR r4, [%[a], #184]\n\t"
  27359. "LDR r5, [%[b], #184]\n\t"
  27360. "AND r4, r4, r3\n\t"
  27361. "AND r5, r5, r3\n\t"
  27362. "SUBS r4, r4, r5\n\t"
  27363. "IT hi\n\t"
  27364. "movhi r2, r8\n\t"
  27365. "IT lo\n\t"
  27366. "movlo r2, r3\n\t"
  27367. "IT ne\n\t"
  27368. "movne r3, r7\n\t"
  27369. "LDR r4, [%[a], #180]\n\t"
  27370. "LDR r5, [%[b], #180]\n\t"
  27371. "AND r4, r4, r3\n\t"
  27372. "AND r5, r5, r3\n\t"
  27373. "SUBS r4, r4, r5\n\t"
  27374. "IT hi\n\t"
  27375. "movhi r2, r8\n\t"
  27376. "IT lo\n\t"
  27377. "movlo r2, r3\n\t"
  27378. "IT ne\n\t"
  27379. "movne r3, r7\n\t"
  27380. "LDR r4, [%[a], #176]\n\t"
  27381. "LDR r5, [%[b], #176]\n\t"
  27382. "AND r4, r4, r3\n\t"
  27383. "AND r5, r5, r3\n\t"
  27384. "SUBS r4, r4, r5\n\t"
  27385. "IT hi\n\t"
  27386. "movhi r2, r8\n\t"
  27387. "IT lo\n\t"
  27388. "movlo r2, r3\n\t"
  27389. "IT ne\n\t"
  27390. "movne r3, r7\n\t"
  27391. "LDR r4, [%[a], #172]\n\t"
  27392. "LDR r5, [%[b], #172]\n\t"
  27393. "AND r4, r4, r3\n\t"
  27394. "AND r5, r5, r3\n\t"
  27395. "SUBS r4, r4, r5\n\t"
  27396. "IT hi\n\t"
  27397. "movhi r2, r8\n\t"
  27398. "IT lo\n\t"
  27399. "movlo r2, r3\n\t"
  27400. "IT ne\n\t"
  27401. "movne r3, r7\n\t"
  27402. "LDR r4, [%[a], #168]\n\t"
  27403. "LDR r5, [%[b], #168]\n\t"
  27404. "AND r4, r4, r3\n\t"
  27405. "AND r5, r5, r3\n\t"
  27406. "SUBS r4, r4, r5\n\t"
  27407. "IT hi\n\t"
  27408. "movhi r2, r8\n\t"
  27409. "IT lo\n\t"
  27410. "movlo r2, r3\n\t"
  27411. "IT ne\n\t"
  27412. "movne r3, r7\n\t"
  27413. "LDR r4, [%[a], #164]\n\t"
  27414. "LDR r5, [%[b], #164]\n\t"
  27415. "AND r4, r4, r3\n\t"
  27416. "AND r5, r5, r3\n\t"
  27417. "SUBS r4, r4, r5\n\t"
  27418. "IT hi\n\t"
  27419. "movhi r2, r8\n\t"
  27420. "IT lo\n\t"
  27421. "movlo r2, r3\n\t"
  27422. "IT ne\n\t"
  27423. "movne r3, r7\n\t"
  27424. "LDR r4, [%[a], #160]\n\t"
  27425. "LDR r5, [%[b], #160]\n\t"
  27426. "AND r4, r4, r3\n\t"
  27427. "AND r5, r5, r3\n\t"
  27428. "SUBS r4, r4, r5\n\t"
  27429. "IT hi\n\t"
  27430. "movhi r2, r8\n\t"
  27431. "IT lo\n\t"
  27432. "movlo r2, r3\n\t"
  27433. "IT ne\n\t"
  27434. "movne r3, r7\n\t"
  27435. "LDR r4, [%[a], #156]\n\t"
  27436. "LDR r5, [%[b], #156]\n\t"
  27437. "AND r4, r4, r3\n\t"
  27438. "AND r5, r5, r3\n\t"
  27439. "SUBS r4, r4, r5\n\t"
  27440. "IT hi\n\t"
  27441. "movhi r2, r8\n\t"
  27442. "IT lo\n\t"
  27443. "movlo r2, r3\n\t"
  27444. "IT ne\n\t"
  27445. "movne r3, r7\n\t"
  27446. "LDR r4, [%[a], #152]\n\t"
  27447. "LDR r5, [%[b], #152]\n\t"
  27448. "AND r4, r4, r3\n\t"
  27449. "AND r5, r5, r3\n\t"
  27450. "SUBS r4, r4, r5\n\t"
  27451. "IT hi\n\t"
  27452. "movhi r2, r8\n\t"
  27453. "IT lo\n\t"
  27454. "movlo r2, r3\n\t"
  27455. "IT ne\n\t"
  27456. "movne r3, r7\n\t"
  27457. "LDR r4, [%[a], #148]\n\t"
  27458. "LDR r5, [%[b], #148]\n\t"
  27459. "AND r4, r4, r3\n\t"
  27460. "AND r5, r5, r3\n\t"
  27461. "SUBS r4, r4, r5\n\t"
  27462. "IT hi\n\t"
  27463. "movhi r2, r8\n\t"
  27464. "IT lo\n\t"
  27465. "movlo r2, r3\n\t"
  27466. "IT ne\n\t"
  27467. "movne r3, r7\n\t"
  27468. "LDR r4, [%[a], #144]\n\t"
  27469. "LDR r5, [%[b], #144]\n\t"
  27470. "AND r4, r4, r3\n\t"
  27471. "AND r5, r5, r3\n\t"
  27472. "SUBS r4, r4, r5\n\t"
  27473. "IT hi\n\t"
  27474. "movhi r2, r8\n\t"
  27475. "IT lo\n\t"
  27476. "movlo r2, r3\n\t"
  27477. "IT ne\n\t"
  27478. "movne r3, r7\n\t"
  27479. "LDR r4, [%[a], #140]\n\t"
  27480. "LDR r5, [%[b], #140]\n\t"
  27481. "AND r4, r4, r3\n\t"
  27482. "AND r5, r5, r3\n\t"
  27483. "SUBS r4, r4, r5\n\t"
  27484. "IT hi\n\t"
  27485. "movhi r2, r8\n\t"
  27486. "IT lo\n\t"
  27487. "movlo r2, r3\n\t"
  27488. "IT ne\n\t"
  27489. "movne r3, r7\n\t"
  27490. "LDR r4, [%[a], #136]\n\t"
  27491. "LDR r5, [%[b], #136]\n\t"
  27492. "AND r4, r4, r3\n\t"
  27493. "AND r5, r5, r3\n\t"
  27494. "SUBS r4, r4, r5\n\t"
  27495. "IT hi\n\t"
  27496. "movhi r2, r8\n\t"
  27497. "IT lo\n\t"
  27498. "movlo r2, r3\n\t"
  27499. "IT ne\n\t"
  27500. "movne r3, r7\n\t"
  27501. "LDR r4, [%[a], #132]\n\t"
  27502. "LDR r5, [%[b], #132]\n\t"
  27503. "AND r4, r4, r3\n\t"
  27504. "AND r5, r5, r3\n\t"
  27505. "SUBS r4, r4, r5\n\t"
  27506. "IT hi\n\t"
  27507. "movhi r2, r8\n\t"
  27508. "IT lo\n\t"
  27509. "movlo r2, r3\n\t"
  27510. "IT ne\n\t"
  27511. "movne r3, r7\n\t"
  27512. "LDR r4, [%[a], #128]\n\t"
  27513. "LDR r5, [%[b], #128]\n\t"
  27514. "AND r4, r4, r3\n\t"
  27515. "AND r5, r5, r3\n\t"
  27516. "SUBS r4, r4, r5\n\t"
  27517. "IT hi\n\t"
  27518. "movhi r2, r8\n\t"
  27519. "IT lo\n\t"
  27520. "movlo r2, r3\n\t"
  27521. "IT ne\n\t"
  27522. "movne r3, r7\n\t"
  27523. "LDR r4, [%[a], #124]\n\t"
  27524. "LDR r5, [%[b], #124]\n\t"
  27525. "AND r4, r4, r3\n\t"
  27526. "AND r5, r5, r3\n\t"
  27527. "SUBS r4, r4, r5\n\t"
  27528. "IT hi\n\t"
  27529. "movhi r2, r8\n\t"
  27530. "IT lo\n\t"
  27531. "movlo r2, r3\n\t"
  27532. "IT ne\n\t"
  27533. "movne r3, r7\n\t"
  27534. "LDR r4, [%[a], #120]\n\t"
  27535. "LDR r5, [%[b], #120]\n\t"
  27536. "AND r4, r4, r3\n\t"
  27537. "AND r5, r5, r3\n\t"
  27538. "SUBS r4, r4, r5\n\t"
  27539. "IT hi\n\t"
  27540. "movhi r2, r8\n\t"
  27541. "IT lo\n\t"
  27542. "movlo r2, r3\n\t"
  27543. "IT ne\n\t"
  27544. "movne r3, r7\n\t"
  27545. "LDR r4, [%[a], #116]\n\t"
  27546. "LDR r5, [%[b], #116]\n\t"
  27547. "AND r4, r4, r3\n\t"
  27548. "AND r5, r5, r3\n\t"
  27549. "SUBS r4, r4, r5\n\t"
  27550. "IT hi\n\t"
  27551. "movhi r2, r8\n\t"
  27552. "IT lo\n\t"
  27553. "movlo r2, r3\n\t"
  27554. "IT ne\n\t"
  27555. "movne r3, r7\n\t"
  27556. "LDR r4, [%[a], #112]\n\t"
  27557. "LDR r5, [%[b], #112]\n\t"
  27558. "AND r4, r4, r3\n\t"
  27559. "AND r5, r5, r3\n\t"
  27560. "SUBS r4, r4, r5\n\t"
  27561. "IT hi\n\t"
  27562. "movhi r2, r8\n\t"
  27563. "IT lo\n\t"
  27564. "movlo r2, r3\n\t"
  27565. "IT ne\n\t"
  27566. "movne r3, r7\n\t"
  27567. "LDR r4, [%[a], #108]\n\t"
  27568. "LDR r5, [%[b], #108]\n\t"
  27569. "AND r4, r4, r3\n\t"
  27570. "AND r5, r5, r3\n\t"
  27571. "SUBS r4, r4, r5\n\t"
  27572. "IT hi\n\t"
  27573. "movhi r2, r8\n\t"
  27574. "IT lo\n\t"
  27575. "movlo r2, r3\n\t"
  27576. "IT ne\n\t"
  27577. "movne r3, r7\n\t"
  27578. "LDR r4, [%[a], #104]\n\t"
  27579. "LDR r5, [%[b], #104]\n\t"
  27580. "AND r4, r4, r3\n\t"
  27581. "AND r5, r5, r3\n\t"
  27582. "SUBS r4, r4, r5\n\t"
  27583. "IT hi\n\t"
  27584. "movhi r2, r8\n\t"
  27585. "IT lo\n\t"
  27586. "movlo r2, r3\n\t"
  27587. "IT ne\n\t"
  27588. "movne r3, r7\n\t"
  27589. "LDR r4, [%[a], #100]\n\t"
  27590. "LDR r5, [%[b], #100]\n\t"
  27591. "AND r4, r4, r3\n\t"
  27592. "AND r5, r5, r3\n\t"
  27593. "SUBS r4, r4, r5\n\t"
  27594. "IT hi\n\t"
  27595. "movhi r2, r8\n\t"
  27596. "IT lo\n\t"
  27597. "movlo r2, r3\n\t"
  27598. "IT ne\n\t"
  27599. "movne r3, r7\n\t"
  27600. "LDR r4, [%[a], #96]\n\t"
  27601. "LDR r5, [%[b], #96]\n\t"
  27602. "AND r4, r4, r3\n\t"
  27603. "AND r5, r5, r3\n\t"
  27604. "SUBS r4, r4, r5\n\t"
  27605. "IT hi\n\t"
  27606. "movhi r2, r8\n\t"
  27607. "IT lo\n\t"
  27608. "movlo r2, r3\n\t"
  27609. "IT ne\n\t"
  27610. "movne r3, r7\n\t"
  27611. "LDR r4, [%[a], #92]\n\t"
  27612. "LDR r5, [%[b], #92]\n\t"
  27613. "AND r4, r4, r3\n\t"
  27614. "AND r5, r5, r3\n\t"
  27615. "SUBS r4, r4, r5\n\t"
  27616. "IT hi\n\t"
  27617. "movhi r2, r8\n\t"
  27618. "IT lo\n\t"
  27619. "movlo r2, r3\n\t"
  27620. "IT ne\n\t"
  27621. "movne r3, r7\n\t"
  27622. "LDR r4, [%[a], #88]\n\t"
  27623. "LDR r5, [%[b], #88]\n\t"
  27624. "AND r4, r4, r3\n\t"
  27625. "AND r5, r5, r3\n\t"
  27626. "SUBS r4, r4, r5\n\t"
  27627. "IT hi\n\t"
  27628. "movhi r2, r8\n\t"
  27629. "IT lo\n\t"
  27630. "movlo r2, r3\n\t"
  27631. "IT ne\n\t"
  27632. "movne r3, r7\n\t"
  27633. "LDR r4, [%[a], #84]\n\t"
  27634. "LDR r5, [%[b], #84]\n\t"
  27635. "AND r4, r4, r3\n\t"
  27636. "AND r5, r5, r3\n\t"
  27637. "SUBS r4, r4, r5\n\t"
  27638. "IT hi\n\t"
  27639. "movhi r2, r8\n\t"
  27640. "IT lo\n\t"
  27641. "movlo r2, r3\n\t"
  27642. "IT ne\n\t"
  27643. "movne r3, r7\n\t"
  27644. "LDR r4, [%[a], #80]\n\t"
  27645. "LDR r5, [%[b], #80]\n\t"
  27646. "AND r4, r4, r3\n\t"
  27647. "AND r5, r5, r3\n\t"
  27648. "SUBS r4, r4, r5\n\t"
  27649. "IT hi\n\t"
  27650. "movhi r2, r8\n\t"
  27651. "IT lo\n\t"
  27652. "movlo r2, r3\n\t"
  27653. "IT ne\n\t"
  27654. "movne r3, r7\n\t"
  27655. "LDR r4, [%[a], #76]\n\t"
  27656. "LDR r5, [%[b], #76]\n\t"
  27657. "AND r4, r4, r3\n\t"
  27658. "AND r5, r5, r3\n\t"
  27659. "SUBS r4, r4, r5\n\t"
  27660. "IT hi\n\t"
  27661. "movhi r2, r8\n\t"
  27662. "IT lo\n\t"
  27663. "movlo r2, r3\n\t"
  27664. "IT ne\n\t"
  27665. "movne r3, r7\n\t"
  27666. "LDR r4, [%[a], #72]\n\t"
  27667. "LDR r5, [%[b], #72]\n\t"
  27668. "AND r4, r4, r3\n\t"
  27669. "AND r5, r5, r3\n\t"
  27670. "SUBS r4, r4, r5\n\t"
  27671. "IT hi\n\t"
  27672. "movhi r2, r8\n\t"
  27673. "IT lo\n\t"
  27674. "movlo r2, r3\n\t"
  27675. "IT ne\n\t"
  27676. "movne r3, r7\n\t"
  27677. "LDR r4, [%[a], #68]\n\t"
  27678. "LDR r5, [%[b], #68]\n\t"
  27679. "AND r4, r4, r3\n\t"
  27680. "AND r5, r5, r3\n\t"
  27681. "SUBS r4, r4, r5\n\t"
  27682. "IT hi\n\t"
  27683. "movhi r2, r8\n\t"
  27684. "IT lo\n\t"
  27685. "movlo r2, r3\n\t"
  27686. "IT ne\n\t"
  27687. "movne r3, r7\n\t"
  27688. "LDR r4, [%[a], #64]\n\t"
  27689. "LDR r5, [%[b], #64]\n\t"
  27690. "AND r4, r4, r3\n\t"
  27691. "AND r5, r5, r3\n\t"
  27692. "SUBS r4, r4, r5\n\t"
  27693. "IT hi\n\t"
  27694. "movhi r2, r8\n\t"
  27695. "IT lo\n\t"
  27696. "movlo r2, r3\n\t"
  27697. "IT ne\n\t"
  27698. "movne r3, r7\n\t"
  27699. "LDR r4, [%[a], #60]\n\t"
  27700. "LDR r5, [%[b], #60]\n\t"
  27701. "AND r4, r4, r3\n\t"
  27702. "AND r5, r5, r3\n\t"
  27703. "SUBS r4, r4, r5\n\t"
  27704. "IT hi\n\t"
  27705. "movhi r2, r8\n\t"
  27706. "IT lo\n\t"
  27707. "movlo r2, r3\n\t"
  27708. "IT ne\n\t"
  27709. "movne r3, r7\n\t"
  27710. "LDR r4, [%[a], #56]\n\t"
  27711. "LDR r5, [%[b], #56]\n\t"
  27712. "AND r4, r4, r3\n\t"
  27713. "AND r5, r5, r3\n\t"
  27714. "SUBS r4, r4, r5\n\t"
  27715. "IT hi\n\t"
  27716. "movhi r2, r8\n\t"
  27717. "IT lo\n\t"
  27718. "movlo r2, r3\n\t"
  27719. "IT ne\n\t"
  27720. "movne r3, r7\n\t"
  27721. "LDR r4, [%[a], #52]\n\t"
  27722. "LDR r5, [%[b], #52]\n\t"
  27723. "AND r4, r4, r3\n\t"
  27724. "AND r5, r5, r3\n\t"
  27725. "SUBS r4, r4, r5\n\t"
  27726. "IT hi\n\t"
  27727. "movhi r2, r8\n\t"
  27728. "IT lo\n\t"
  27729. "movlo r2, r3\n\t"
  27730. "IT ne\n\t"
  27731. "movne r3, r7\n\t"
  27732. "LDR r4, [%[a], #48]\n\t"
  27733. "LDR r5, [%[b], #48]\n\t"
  27734. "AND r4, r4, r3\n\t"
  27735. "AND r5, r5, r3\n\t"
  27736. "SUBS r4, r4, r5\n\t"
  27737. "IT hi\n\t"
  27738. "movhi r2, r8\n\t"
  27739. "IT lo\n\t"
  27740. "movlo r2, r3\n\t"
  27741. "IT ne\n\t"
  27742. "movne r3, r7\n\t"
  27743. "LDR r4, [%[a], #44]\n\t"
  27744. "LDR r5, [%[b], #44]\n\t"
  27745. "AND r4, r4, r3\n\t"
  27746. "AND r5, r5, r3\n\t"
  27747. "SUBS r4, r4, r5\n\t"
  27748. "IT hi\n\t"
  27749. "movhi r2, r8\n\t"
  27750. "IT lo\n\t"
  27751. "movlo r2, r3\n\t"
  27752. "IT ne\n\t"
  27753. "movne r3, r7\n\t"
  27754. "LDR r4, [%[a], #40]\n\t"
  27755. "LDR r5, [%[b], #40]\n\t"
  27756. "AND r4, r4, r3\n\t"
  27757. "AND r5, r5, r3\n\t"
  27758. "SUBS r4, r4, r5\n\t"
  27759. "IT hi\n\t"
  27760. "movhi r2, r8\n\t"
  27761. "IT lo\n\t"
  27762. "movlo r2, r3\n\t"
  27763. "IT ne\n\t"
  27764. "movne r3, r7\n\t"
  27765. "LDR r4, [%[a], #36]\n\t"
  27766. "LDR r5, [%[b], #36]\n\t"
  27767. "AND r4, r4, r3\n\t"
  27768. "AND r5, r5, r3\n\t"
  27769. "SUBS r4, r4, r5\n\t"
  27770. "IT hi\n\t"
  27771. "movhi r2, r8\n\t"
  27772. "IT lo\n\t"
  27773. "movlo r2, r3\n\t"
  27774. "IT ne\n\t"
  27775. "movne r3, r7\n\t"
  27776. "LDR r4, [%[a], #32]\n\t"
  27777. "LDR r5, [%[b], #32]\n\t"
  27778. "AND r4, r4, r3\n\t"
  27779. "AND r5, r5, r3\n\t"
  27780. "SUBS r4, r4, r5\n\t"
  27781. "IT hi\n\t"
  27782. "movhi r2, r8\n\t"
  27783. "IT lo\n\t"
  27784. "movlo r2, r3\n\t"
  27785. "IT ne\n\t"
  27786. "movne r3, r7\n\t"
  27787. "LDR r4, [%[a], #28]\n\t"
  27788. "LDR r5, [%[b], #28]\n\t"
  27789. "AND r4, r4, r3\n\t"
  27790. "AND r5, r5, r3\n\t"
  27791. "SUBS r4, r4, r5\n\t"
  27792. "IT hi\n\t"
  27793. "movhi r2, r8\n\t"
  27794. "IT lo\n\t"
  27795. "movlo r2, r3\n\t"
  27796. "IT ne\n\t"
  27797. "movne r3, r7\n\t"
  27798. "LDR r4, [%[a], #24]\n\t"
  27799. "LDR r5, [%[b], #24]\n\t"
  27800. "AND r4, r4, r3\n\t"
  27801. "AND r5, r5, r3\n\t"
  27802. "SUBS r4, r4, r5\n\t"
  27803. "IT hi\n\t"
  27804. "movhi r2, r8\n\t"
  27805. "IT lo\n\t"
  27806. "movlo r2, r3\n\t"
  27807. "IT ne\n\t"
  27808. "movne r3, r7\n\t"
  27809. "LDR r4, [%[a], #20]\n\t"
  27810. "LDR r5, [%[b], #20]\n\t"
  27811. "AND r4, r4, r3\n\t"
  27812. "AND r5, r5, r3\n\t"
  27813. "SUBS r4, r4, r5\n\t"
  27814. "IT hi\n\t"
  27815. "movhi r2, r8\n\t"
  27816. "IT lo\n\t"
  27817. "movlo r2, r3\n\t"
  27818. "IT ne\n\t"
  27819. "movne r3, r7\n\t"
  27820. "LDR r4, [%[a], #16]\n\t"
  27821. "LDR r5, [%[b], #16]\n\t"
  27822. "AND r4, r4, r3\n\t"
  27823. "AND r5, r5, r3\n\t"
  27824. "SUBS r4, r4, r5\n\t"
  27825. "IT hi\n\t"
  27826. "movhi r2, r8\n\t"
  27827. "IT lo\n\t"
  27828. "movlo r2, r3\n\t"
  27829. "IT ne\n\t"
  27830. "movne r3, r7\n\t"
  27831. "LDR r4, [%[a], #12]\n\t"
  27832. "LDR r5, [%[b], #12]\n\t"
  27833. "AND r4, r4, r3\n\t"
  27834. "AND r5, r5, r3\n\t"
  27835. "SUBS r4, r4, r5\n\t"
  27836. "IT hi\n\t"
  27837. "movhi r2, r8\n\t"
  27838. "IT lo\n\t"
  27839. "movlo r2, r3\n\t"
  27840. "IT ne\n\t"
  27841. "movne r3, r7\n\t"
  27842. "LDR r4, [%[a], #8]\n\t"
  27843. "LDR r5, [%[b], #8]\n\t"
  27844. "AND r4, r4, r3\n\t"
  27845. "AND r5, r5, r3\n\t"
  27846. "SUBS r4, r4, r5\n\t"
  27847. "IT hi\n\t"
  27848. "movhi r2, r8\n\t"
  27849. "IT lo\n\t"
  27850. "movlo r2, r3\n\t"
  27851. "IT ne\n\t"
  27852. "movne r3, r7\n\t"
  27853. "LDR r4, [%[a], #4]\n\t"
  27854. "LDR r5, [%[b], #4]\n\t"
  27855. "AND r4, r4, r3\n\t"
  27856. "AND r5, r5, r3\n\t"
  27857. "SUBS r4, r4, r5\n\t"
  27858. "IT hi\n\t"
  27859. "movhi r2, r8\n\t"
  27860. "IT lo\n\t"
  27861. "movlo r2, r3\n\t"
  27862. "IT ne\n\t"
  27863. "movne r3, r7\n\t"
  27864. "LDR r4, [%[a]]\n\t"
  27865. "LDR r5, [%[b]]\n\t"
  27866. "AND r4, r4, r3\n\t"
  27867. "AND r5, r5, r3\n\t"
  27868. "SUBS r4, r4, r5\n\t"
  27869. "IT hi\n\t"
  27870. "movhi r2, r8\n\t"
  27871. "IT lo\n\t"
  27872. "movlo r2, r3\n\t"
  27873. "IT ne\n\t"
  27874. "movne r3, r7\n\t"
  27875. "EOR r2, r2, r3\n\t"
  27876. #endif /*WOLFSSL_SP_SMALL */
  27877. "MOV %[a], r2\n\t"
  27878. : [a] "+r" (a), [b] "+r" (b)
  27879. :
  27880. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  27881. );
  27882. return (uint32_t)(size_t)a;
  27883. }
  27884. /* Divide d in a and put remainder into r (m*d + r = a)
  27885. * m is not calculated as it is not needed at this time.
  27886. *
  27887. * a Number to be divided.
  27888. * d Number to divide with.
  27889. * m Multiplier result.
  27890. * r Remainder from the division.
  27891. * returns MP_OKAY indicating success.
  27892. */
  27893. static WC_INLINE int sp_4096_div_128(const sp_digit* a, const sp_digit* d,
  27894. sp_digit* m, sp_digit* r)
  27895. {
  27896. sp_digit t1[256], t2[129];
  27897. sp_digit div, r1;
  27898. int i;
  27899. (void)m;
  27900. div = d[127];
  27901. XMEMCPY(t1, a, sizeof(*t1) * 2 * 128);
  27902. r1 = sp_4096_cmp_128(&t1[128], d) >= 0;
  27903. sp_4096_cond_sub_128(&t1[128], &t1[128], d, (sp_digit)0 - r1);
  27904. for (i = 127; i >= 0; i--) {
  27905. volatile sp_digit mask = (sp_digit)0 - (t1[128 + i] == div);
  27906. sp_digit hi = t1[128 + i] + mask;
  27907. r1 = div_4096_word_128(hi, t1[128 + i - 1], div);
  27908. r1 |= mask;
  27909. sp_4096_mul_d_128(t2, d, r1);
  27910. t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2);
  27911. t1[128 + i] -= t2[128];
  27912. sp_4096_mask_128(t2, d, t1[128 + i]);
  27913. t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2);
  27914. sp_4096_mask_128(t2, d, t1[128 + i]);
  27915. t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2);
  27916. }
  27917. r1 = sp_4096_cmp_128(t1, d) >= 0;
  27918. sp_4096_cond_sub_128(r, t1, d, (sp_digit)0 - r1);
  27919. return MP_OKAY;
  27920. }
  27921. /* Reduce a modulo m into r. (r = a mod m)
  27922. *
  27923. * r A single precision number that is the reduced result.
  27924. * a A single precision number that is to be reduced.
  27925. * m A single precision number that is the modulus to reduce with.
  27926. * returns MP_OKAY indicating success.
  27927. */
  27928. static WC_INLINE int sp_4096_mod_128(sp_digit* r, const sp_digit* a, const sp_digit* m)
  27929. {
  27930. return sp_4096_div_128(a, m, NULL, r);
  27931. }
  27932. #endif /* WOLFSSL_HAVE_SP_DH || !WOLFSSL_RSA_PUBLIC_ONLY */
  27933. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
  27934. defined(WOLFSSL_HAVE_SP_DH)
  27935. #ifdef WOLFSSL_SP_SMALL
  27936. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  27937. *
  27938. * r A single precision number that is the result of the operation.
  27939. * a A single precision number being exponentiated.
  27940. * e A single precision number that is the exponent.
  27941. * bits The number of bits in the exponent.
  27942. * m A single precision number that is the modulus.
  27943. * returns 0 on success.
  27944. * returns MEMORY_E on dynamic memory allocation failure.
  27945. * returns MP_VAL when base is even or exponent is 0.
  27946. */
  27947. static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e,
  27948. int bits, const sp_digit* m, int reduceA)
  27949. {
  27950. #ifdef WOLFSSL_SP_SMALL_STACK
  27951. sp_digit* td = NULL;
  27952. #else
  27953. sp_digit td[8 * 256];
  27954. #endif
  27955. sp_digit* t[8];
  27956. sp_digit* norm = NULL;
  27957. sp_digit mp = 1;
  27958. sp_digit n;
  27959. sp_digit mask;
  27960. int i;
  27961. int c;
  27962. byte y;
  27963. int err = MP_OKAY;
  27964. if (bits == 0) {
  27965. err = MP_VAL;
  27966. }
  27967. #ifdef WOLFSSL_SP_SMALL_STACK
  27968. if (err == MP_OKAY) {
  27969. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (8 * 256), NULL,
  27970. DYNAMIC_TYPE_TMP_BUFFER);
  27971. if (td == NULL)
  27972. err = MEMORY_E;
  27973. }
  27974. #endif
  27975. if (err == MP_OKAY) {
  27976. norm = td;
  27977. for (i=0; i<8; i++) {
  27978. t[i] = td + i * 256;
  27979. }
  27980. sp_4096_mont_setup(m, &mp);
  27981. sp_4096_mont_norm_128(norm, m);
  27982. XMEMSET(t[1], 0, sizeof(sp_digit) * 128U);
  27983. if (reduceA != 0) {
  27984. err = sp_4096_mod_128(t[1] + 128, a, m);
  27985. if (err == MP_OKAY) {
  27986. err = sp_4096_mod_128(t[1], t[1], m);
  27987. }
  27988. }
  27989. else {
  27990. XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128);
  27991. err = sp_4096_mod_128(t[1], t[1], m);
  27992. }
  27993. }
  27994. if (err == MP_OKAY) {
  27995. sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp);
  27996. sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp);
  27997. sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp);
  27998. sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp);
  27999. sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp);
  28000. sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp);
  28001. i = (bits - 1) / 32;
  28002. n = e[i--];
  28003. c = bits & 31;
  28004. if (c == 0) {
  28005. c = 32;
  28006. }
  28007. c -= bits % 3;
  28008. if (c == 32) {
  28009. c = 29;
  28010. }
  28011. if (c < 0) {
  28012. /* Number of bits in top word is less than number needed. */
  28013. c = -c;
  28014. y = (byte)(n << c);
  28015. n = e[i--];
  28016. y |= (byte)(n >> (64 - c));
  28017. n <<= c;
  28018. c = 64 - c;
  28019. }
  28020. else if (c == 0) {
  28021. /* All bits in top word used. */
  28022. y = (byte)n;
  28023. }
  28024. else {
  28025. y = (byte)(n >> c);
  28026. n <<= 32 - c;
  28027. }
  28028. XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
  28029. for (; i>=0 || c>=3; ) {
  28030. if (c == 0) {
  28031. n = e[i--];
  28032. y = (byte)(n >> 29);
  28033. n <<= 3;
  28034. c = 29;
  28035. }
  28036. else if (c < 3) {
  28037. y = (byte)(n >> 29);
  28038. n = e[i--];
  28039. c = 3 - c;
  28040. y |= (byte)(n >> (32 - c));
  28041. n <<= c;
  28042. c = 32 - c;
  28043. }
  28044. else {
  28045. y = (byte)((n >> 29) & 0x7);
  28046. n <<= 3;
  28047. c -= 3;
  28048. }
  28049. sp_4096_mont_sqr_128(r, r, m, mp);
  28050. sp_4096_mont_sqr_128(r, r, m, mp);
  28051. sp_4096_mont_sqr_128(r, r, m, mp);
  28052. sp_4096_mont_mul_128(r, r, t[y], m, mp);
  28053. }
  28054. XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U);
  28055. sp_4096_mont_reduce_128(r, m, mp);
  28056. mask = 0 - (sp_4096_cmp_128(r, m) >= 0);
  28057. sp_4096_cond_sub_128(r, r, m, mask);
  28058. }
  28059. #ifdef WOLFSSL_SP_SMALL_STACK
  28060. if (td != NULL)
  28061. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  28062. #endif
  28063. return err;
  28064. }
  28065. #else
  28066. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  28067. *
  28068. * r A single precision number that is the result of the operation.
  28069. * a A single precision number being exponentiated.
  28070. * e A single precision number that is the exponent.
  28071. * bits The number of bits in the exponent.
  28072. * m A single precision number that is the modulus.
  28073. * returns 0 on success.
  28074. * returns MEMORY_E on dynamic memory allocation failure.
  28075. * returns MP_VAL when base is even or exponent is 0.
  28076. */
  28077. static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e,
  28078. int bits, const sp_digit* m, int reduceA)
  28079. {
  28080. #ifdef WOLFSSL_SP_SMALL_STACK
  28081. sp_digit* td = NULL;
  28082. #else
  28083. sp_digit td[16 * 256];
  28084. #endif
  28085. sp_digit* t[16];
  28086. sp_digit* norm = NULL;
  28087. sp_digit mp = 1;
  28088. sp_digit n;
  28089. sp_digit mask;
  28090. int i;
  28091. int c;
  28092. byte y;
  28093. int err = MP_OKAY;
  28094. if (bits == 0) {
  28095. err = MP_VAL;
  28096. }
  28097. #ifdef WOLFSSL_SP_SMALL_STACK
  28098. if (err == MP_OKAY) {
  28099. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 256), NULL,
  28100. DYNAMIC_TYPE_TMP_BUFFER);
  28101. if (td == NULL)
  28102. err = MEMORY_E;
  28103. }
  28104. #endif
  28105. if (err == MP_OKAY) {
  28106. norm = td;
  28107. for (i=0; i<16; i++) {
  28108. t[i] = td + i * 256;
  28109. }
  28110. sp_4096_mont_setup(m, &mp);
  28111. sp_4096_mont_norm_128(norm, m);
  28112. XMEMSET(t[1], 0, sizeof(sp_digit) * 128U);
  28113. if (reduceA != 0) {
  28114. err = sp_4096_mod_128(t[1] + 128, a, m);
  28115. if (err == MP_OKAY) {
  28116. err = sp_4096_mod_128(t[1], t[1], m);
  28117. }
  28118. }
  28119. else {
  28120. XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128);
  28121. err = sp_4096_mod_128(t[1], t[1], m);
  28122. }
  28123. }
  28124. if (err == MP_OKAY) {
  28125. sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp);
  28126. sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp);
  28127. sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp);
  28128. sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp);
  28129. sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp);
  28130. sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp);
  28131. sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp);
  28132. sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp);
  28133. sp_4096_mont_sqr_128(t[10], t[ 5], m, mp);
  28134. sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp);
  28135. sp_4096_mont_sqr_128(t[12], t[ 6], m, mp);
  28136. sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp);
  28137. sp_4096_mont_sqr_128(t[14], t[ 7], m, mp);
  28138. sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp);
  28139. i = (bits - 1) / 32;
  28140. n = e[i--];
  28141. c = bits & 31;
  28142. if (c == 0) {
  28143. c = 32;
  28144. }
  28145. c -= bits % 4;
  28146. if (c == 32) {
  28147. c = 28;
  28148. }
  28149. if (c < 0) {
  28150. /* Number of bits in top word is less than number needed. */
  28151. c = -c;
  28152. y = (byte)(n << c);
  28153. n = e[i--];
  28154. y |= (byte)(n >> (64 - c));
  28155. n <<= c;
  28156. c = 64 - c;
  28157. }
  28158. else if (c == 0) {
  28159. /* All bits in top word used. */
  28160. y = (byte)n;
  28161. }
  28162. else {
  28163. y = (byte)(n >> c);
  28164. n <<= 32 - c;
  28165. }
  28166. XMEMCPY(r, t[y], sizeof(sp_digit) * 128);
  28167. for (; i>=0 || c>=4; ) {
  28168. if (c == 0) {
  28169. n = e[i--];
  28170. y = (byte)(n >> 28);
  28171. n <<= 4;
  28172. c = 28;
  28173. }
  28174. else if (c < 4) {
  28175. y = (byte)(n >> 28);
  28176. n = e[i--];
  28177. c = 4 - c;
  28178. y |= (byte)(n >> (32 - c));
  28179. n <<= c;
  28180. c = 32 - c;
  28181. }
  28182. else {
  28183. y = (byte)((n >> 28) & 0xf);
  28184. n <<= 4;
  28185. c -= 4;
  28186. }
  28187. sp_4096_mont_sqr_128(r, r, m, mp);
  28188. sp_4096_mont_sqr_128(r, r, m, mp);
  28189. sp_4096_mont_sqr_128(r, r, m, mp);
  28190. sp_4096_mont_sqr_128(r, r, m, mp);
  28191. sp_4096_mont_mul_128(r, r, t[y], m, mp);
  28192. }
  28193. XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U);
  28194. sp_4096_mont_reduce_128(r, m, mp);
  28195. mask = 0 - (sp_4096_cmp_128(r, m) >= 0);
  28196. sp_4096_cond_sub_128(r, r, m, mask);
  28197. }
  28198. #ifdef WOLFSSL_SP_SMALL_STACK
  28199. if (td != NULL)
  28200. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  28201. #endif
  28202. return err;
  28203. }
  28204. #endif /* WOLFSSL_SP_SMALL */
  28205. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  28206. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  28207. #ifdef WOLFSSL_HAVE_SP_RSA
  28208. /* RSA public key operation.
  28209. *
  28210. * in Array of bytes representing the number to exponentiate, base.
  28211. * inLen Number of bytes in base.
  28212. * em Public exponent.
  28213. * mm Modulus.
  28214. * out Buffer to hold big-endian bytes of exponentiation result.
  28215. * Must be at least 512 bytes long.
  28216. * outLen Number of bytes in result.
  28217. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  28218. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  28219. */
  28220. int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
  28221. const mp_int* mm, byte* out, word32* outLen)
  28222. {
  28223. #ifdef WOLFSSL_SP_SMALL_STACK
  28224. sp_digit* a = NULL;
  28225. #else
  28226. sp_digit a[128 * 5];
  28227. #endif
  28228. sp_digit* m = NULL;
  28229. sp_digit* r = NULL;
  28230. sp_digit *ah = NULL;
  28231. sp_digit e[1] = {0};
  28232. int err = MP_OKAY;
  28233. if (*outLen < 512) {
  28234. err = MP_TO_E;
  28235. }
  28236. else if (mp_count_bits(em) > 32 || inLen > 512 ||
  28237. mp_count_bits(mm) != 4096) {
  28238. err = MP_READ_E;
  28239. }
  28240. else if (mp_iseven(mm)) {
  28241. err = MP_VAL;
  28242. }
  28243. #ifdef WOLFSSL_SP_SMALL_STACK
  28244. if (err == MP_OKAY) {
  28245. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL,
  28246. DYNAMIC_TYPE_RSA);
  28247. if (a == NULL)
  28248. err = MEMORY_E;
  28249. }
  28250. #endif
  28251. if (err == MP_OKAY) {
  28252. ah = a + 128;
  28253. r = a + 128 * 2;
  28254. m = r + 128 * 2;
  28255. sp_4096_from_bin(ah, 128, in, inLen);
  28256. #if DIGIT_BIT >= 32
  28257. e[0] = em->dp[0];
  28258. #else
  28259. e[0] = em->dp[0];
  28260. if (em->used > 1) {
  28261. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  28262. }
  28263. #endif
  28264. if (e[0] == 0) {
  28265. err = MP_EXPTMOD_E;
  28266. }
  28267. }
  28268. if (err == MP_OKAY) {
  28269. sp_4096_from_mp(m, 128, mm);
  28270. if (e[0] == 0x10001) {
  28271. int i;
  28272. sp_digit mp;
  28273. sp_4096_mont_setup(m, &mp);
  28274. /* Convert to Montgomery form. */
  28275. XMEMSET(a, 0, sizeof(sp_digit) * 128);
  28276. err = sp_4096_mod_128_cond(r, a, m);
  28277. /* Montgomery form: r = a.R mod m */
  28278. if (err == MP_OKAY) {
  28279. /* r = a ^ 0x10000 => r = a squared 16 times */
  28280. for (i = 15; i >= 0; i--) {
  28281. sp_4096_mont_sqr_128(r, r, m, mp);
  28282. }
  28283. /* mont_red(r.R.R) = (r.R.R / R) mod m = r.R mod m
  28284. * mont_red(r.R * a) = (r.R.a / R) mod m = r.a mod m
  28285. */
  28286. sp_4096_mont_mul_128(r, r, ah, m, mp);
  28287. for (i = 127; i > 0; i--) {
  28288. if (r[i] != m[i]) {
  28289. break;
  28290. }
  28291. }
  28292. if (r[i] >= m[i]) {
  28293. sp_4096_sub_in_place_128(r, m);
  28294. }
  28295. }
  28296. }
  28297. else if (e[0] == 0x3) {
  28298. if (err == MP_OKAY) {
  28299. sp_4096_sqr_128(r, ah);
  28300. err = sp_4096_mod_128_cond(r, r, m);
  28301. }
  28302. if (err == MP_OKAY) {
  28303. sp_4096_mul_128(r, ah, r);
  28304. err = sp_4096_mod_128_cond(r, r, m);
  28305. }
  28306. }
  28307. else {
  28308. int i;
  28309. sp_digit mp;
  28310. sp_4096_mont_setup(m, &mp);
  28311. /* Convert to Montgomery form. */
  28312. XMEMSET(a, 0, sizeof(sp_digit) * 128);
  28313. err = sp_4096_mod_128_cond(a, a, m);
  28314. if (err == MP_OKAY) {
  28315. for (i = 31; i >= 0; i--) {
  28316. if (e[0] >> i) {
  28317. break;
  28318. }
  28319. }
  28320. XMEMCPY(r, a, sizeof(sp_digit) * 128);
  28321. for (i--; i >= 0; i--) {
  28322. sp_4096_mont_sqr_128(r, r, m, mp);
  28323. if (((e[0] >> i) & 1) == 1) {
  28324. sp_4096_mont_mul_128(r, r, a, m, mp);
  28325. }
  28326. }
  28327. XMEMSET(&r[128], 0, sizeof(sp_digit) * 128);
  28328. sp_4096_mont_reduce_128(r, m, mp);
  28329. for (i = 127; i > 0; i--) {
  28330. if (r[i] != m[i]) {
  28331. break;
  28332. }
  28333. }
  28334. if (r[i] >= m[i]) {
  28335. sp_4096_sub_in_place_128(r, m);
  28336. }
  28337. }
  28338. }
  28339. }
  28340. if (err == MP_OKAY) {
  28341. sp_4096_to_bin_128(r, out);
  28342. *outLen = 512;
  28343. }
  28344. #ifdef WOLFSSL_SP_SMALL_STACK
  28345. if (a != NULL)
  28346. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  28347. #endif
  28348. return err;
  28349. }
  28350. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  28351. #ifdef WOLFSSL_SP_SMALL
  28352. /* Conditionally add a and b using the mask m.
  28353. * m is -1 to add and 0 when not.
  28354. *
  28355. * r A single precision number representing conditional add result.
  28356. * a A single precision number to add with.
  28357. * b A single precision number to add.
  28358. * m Mask value to apply.
  28359. */
  28360. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  28361. static sp_digit sp_4096_cond_add_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  28362. #else
  28363. static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  28364. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  28365. {
  28366. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  28367. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  28368. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  28369. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  28370. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  28371. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  28372. __asm__ __volatile__ (
  28373. "MOV r5, #0x0\n\t"
  28374. "MOV r8, #0x0\n\t"
  28375. "MOV r4, #0x0\n\t"
  28376. "\n"
  28377. "L_sp_4096_cond_add_64_words:\n\t"
  28378. "ADDS r5, r5, #0xffffffff\n\t"
  28379. "LDR r6, [%[a], r4]\n\t"
  28380. "LDR r7, [%[b], r4]\n\t"
  28381. "AND r7, r7, %[m]\n\t"
  28382. "ADCS r6, r6, r7\n\t"
  28383. "ADC r5, r8, r8\n\t"
  28384. "STR r6, [%[r], r4]\n\t"
  28385. "ADD r4, r4, #0x4\n\t"
  28386. "CMP r4, #0x100\n\t"
  28387. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  28388. "BLT L_sp_4096_cond_add_64_words\n\t"
  28389. #else
  28390. "BLT.N L_sp_4096_cond_add_64_words\n\t"
  28391. #endif
  28392. "MOV %[r], r5\n\t"
  28393. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  28394. :
  28395. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  28396. );
  28397. return (uint32_t)(size_t)r;
  28398. }
  28399. #else
  28400. /* Conditionally add a and b using the mask m.
  28401. * m is -1 to add and 0 when not.
  28402. *
  28403. * r A single precision number representing conditional add result.
  28404. * a A single precision number to add with.
  28405. * b A single precision number to add.
  28406. * m Mask value to apply.
  28407. */
  28408. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  28409. static sp_digit sp_4096_cond_add_64(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  28410. #else
  28411. static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  28412. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  28413. {
  28414. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  28415. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  28416. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  28417. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  28418. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  28419. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  28420. __asm__ __volatile__ (
  28421. "MOV r10, #0x0\n\t"
  28422. "LDM %[a]!, {r6, r7}\n\t"
  28423. "LDM %[b]!, {r8, r9}\n\t"
  28424. "AND r8, r8, %[m]\n\t"
  28425. "AND r9, r9, %[m]\n\t"
  28426. "ADDS r6, r6, r8\n\t"
  28427. "ADCS r7, r7, r9\n\t"
  28428. "STM %[r]!, {r6, r7}\n\t"
  28429. "LDM %[a]!, {r6, r7}\n\t"
  28430. "LDM %[b]!, {r8, r9}\n\t"
  28431. "AND r8, r8, %[m]\n\t"
  28432. "AND r9, r9, %[m]\n\t"
  28433. "ADCS r6, r6, r8\n\t"
  28434. "ADCS r7, r7, r9\n\t"
  28435. "STM %[r]!, {r6, r7}\n\t"
  28436. "LDM %[a]!, {r6, r7}\n\t"
  28437. "LDM %[b]!, {r8, r9}\n\t"
  28438. "AND r8, r8, %[m]\n\t"
  28439. "AND r9, r9, %[m]\n\t"
  28440. "ADCS r6, r6, r8\n\t"
  28441. "ADCS r7, r7, r9\n\t"
  28442. "STM %[r]!, {r6, r7}\n\t"
  28443. "LDM %[a]!, {r6, r7}\n\t"
  28444. "LDM %[b]!, {r8, r9}\n\t"
  28445. "AND r8, r8, %[m]\n\t"
  28446. "AND r9, r9, %[m]\n\t"
  28447. "ADCS r6, r6, r8\n\t"
  28448. "ADCS r7, r7, r9\n\t"
  28449. "STM %[r]!, {r6, r7}\n\t"
  28450. "LDM %[a]!, {r6, r7}\n\t"
  28451. "LDM %[b]!, {r8, r9}\n\t"
  28452. "AND r8, r8, %[m]\n\t"
  28453. "AND r9, r9, %[m]\n\t"
  28454. "ADCS r6, r6, r8\n\t"
  28455. "ADCS r7, r7, r9\n\t"
  28456. "STM %[r]!, {r6, r7}\n\t"
  28457. "LDM %[a]!, {r6, r7}\n\t"
  28458. "LDM %[b]!, {r8, r9}\n\t"
  28459. "AND r8, r8, %[m]\n\t"
  28460. "AND r9, r9, %[m]\n\t"
  28461. "ADCS r6, r6, r8\n\t"
  28462. "ADCS r7, r7, r9\n\t"
  28463. "STM %[r]!, {r6, r7}\n\t"
  28464. "LDM %[a]!, {r6, r7}\n\t"
  28465. "LDM %[b]!, {r8, r9}\n\t"
  28466. "AND r8, r8, %[m]\n\t"
  28467. "AND r9, r9, %[m]\n\t"
  28468. "ADCS r6, r6, r8\n\t"
  28469. "ADCS r7, r7, r9\n\t"
  28470. "STM %[r]!, {r6, r7}\n\t"
  28471. "LDM %[a]!, {r6, r7}\n\t"
  28472. "LDM %[b]!, {r8, r9}\n\t"
  28473. "AND r8, r8, %[m]\n\t"
  28474. "AND r9, r9, %[m]\n\t"
  28475. "ADCS r6, r6, r8\n\t"
  28476. "ADCS r7, r7, r9\n\t"
  28477. "STM %[r]!, {r6, r7}\n\t"
  28478. "LDM %[a]!, {r6, r7}\n\t"
  28479. "LDM %[b]!, {r8, r9}\n\t"
  28480. "AND r8, r8, %[m]\n\t"
  28481. "AND r9, r9, %[m]\n\t"
  28482. "ADCS r6, r6, r8\n\t"
  28483. "ADCS r7, r7, r9\n\t"
  28484. "STM %[r]!, {r6, r7}\n\t"
  28485. "LDM %[a]!, {r6, r7}\n\t"
  28486. "LDM %[b]!, {r8, r9}\n\t"
  28487. "AND r8, r8, %[m]\n\t"
  28488. "AND r9, r9, %[m]\n\t"
  28489. "ADCS r6, r6, r8\n\t"
  28490. "ADCS r7, r7, r9\n\t"
  28491. "STM %[r]!, {r6, r7}\n\t"
  28492. "LDM %[a]!, {r6, r7}\n\t"
  28493. "LDM %[b]!, {r8, r9}\n\t"
  28494. "AND r8, r8, %[m]\n\t"
  28495. "AND r9, r9, %[m]\n\t"
  28496. "ADCS r6, r6, r8\n\t"
  28497. "ADCS r7, r7, r9\n\t"
  28498. "STM %[r]!, {r6, r7}\n\t"
  28499. "LDM %[a]!, {r6, r7}\n\t"
  28500. "LDM %[b]!, {r8, r9}\n\t"
  28501. "AND r8, r8, %[m]\n\t"
  28502. "AND r9, r9, %[m]\n\t"
  28503. "ADCS r6, r6, r8\n\t"
  28504. "ADCS r7, r7, r9\n\t"
  28505. "STM %[r]!, {r6, r7}\n\t"
  28506. "LDM %[a]!, {r6, r7}\n\t"
  28507. "LDM %[b]!, {r8, r9}\n\t"
  28508. "AND r8, r8, %[m]\n\t"
  28509. "AND r9, r9, %[m]\n\t"
  28510. "ADCS r6, r6, r8\n\t"
  28511. "ADCS r7, r7, r9\n\t"
  28512. "STM %[r]!, {r6, r7}\n\t"
  28513. "LDM %[a]!, {r6, r7}\n\t"
  28514. "LDM %[b]!, {r8, r9}\n\t"
  28515. "AND r8, r8, %[m]\n\t"
  28516. "AND r9, r9, %[m]\n\t"
  28517. "ADCS r6, r6, r8\n\t"
  28518. "ADCS r7, r7, r9\n\t"
  28519. "STM %[r]!, {r6, r7}\n\t"
  28520. "LDM %[a]!, {r6, r7}\n\t"
  28521. "LDM %[b]!, {r8, r9}\n\t"
  28522. "AND r8, r8, %[m]\n\t"
  28523. "AND r9, r9, %[m]\n\t"
  28524. "ADCS r6, r6, r8\n\t"
  28525. "ADCS r7, r7, r9\n\t"
  28526. "STM %[r]!, {r6, r7}\n\t"
  28527. "LDM %[a]!, {r6, r7}\n\t"
  28528. "LDM %[b]!, {r8, r9}\n\t"
  28529. "AND r8, r8, %[m]\n\t"
  28530. "AND r9, r9, %[m]\n\t"
  28531. "ADCS r6, r6, r8\n\t"
  28532. "ADCS r7, r7, r9\n\t"
  28533. "STM %[r]!, {r6, r7}\n\t"
  28534. "LDM %[a]!, {r6, r7}\n\t"
  28535. "LDM %[b]!, {r8, r9}\n\t"
  28536. "AND r8, r8, %[m]\n\t"
  28537. "AND r9, r9, %[m]\n\t"
  28538. "ADCS r6, r6, r8\n\t"
  28539. "ADCS r7, r7, r9\n\t"
  28540. "STM %[r]!, {r6, r7}\n\t"
  28541. "LDM %[a]!, {r6, r7}\n\t"
  28542. "LDM %[b]!, {r8, r9}\n\t"
  28543. "AND r8, r8, %[m]\n\t"
  28544. "AND r9, r9, %[m]\n\t"
  28545. "ADCS r6, r6, r8\n\t"
  28546. "ADCS r7, r7, r9\n\t"
  28547. "STM %[r]!, {r6, r7}\n\t"
  28548. "LDM %[a]!, {r6, r7}\n\t"
  28549. "LDM %[b]!, {r8, r9}\n\t"
  28550. "AND r8, r8, %[m]\n\t"
  28551. "AND r9, r9, %[m]\n\t"
  28552. "ADCS r6, r6, r8\n\t"
  28553. "ADCS r7, r7, r9\n\t"
  28554. "STM %[r]!, {r6, r7}\n\t"
  28555. "LDM %[a]!, {r6, r7}\n\t"
  28556. "LDM %[b]!, {r8, r9}\n\t"
  28557. "AND r8, r8, %[m]\n\t"
  28558. "AND r9, r9, %[m]\n\t"
  28559. "ADCS r6, r6, r8\n\t"
  28560. "ADCS r7, r7, r9\n\t"
  28561. "STM %[r]!, {r6, r7}\n\t"
  28562. "LDM %[a]!, {r6, r7}\n\t"
  28563. "LDM %[b]!, {r8, r9}\n\t"
  28564. "AND r8, r8, %[m]\n\t"
  28565. "AND r9, r9, %[m]\n\t"
  28566. "ADCS r6, r6, r8\n\t"
  28567. "ADCS r7, r7, r9\n\t"
  28568. "STM %[r]!, {r6, r7}\n\t"
  28569. "LDM %[a]!, {r6, r7}\n\t"
  28570. "LDM %[b]!, {r8, r9}\n\t"
  28571. "AND r8, r8, %[m]\n\t"
  28572. "AND r9, r9, %[m]\n\t"
  28573. "ADCS r6, r6, r8\n\t"
  28574. "ADCS r7, r7, r9\n\t"
  28575. "STM %[r]!, {r6, r7}\n\t"
  28576. "LDM %[a]!, {r6, r7}\n\t"
  28577. "LDM %[b]!, {r8, r9}\n\t"
  28578. "AND r8, r8, %[m]\n\t"
  28579. "AND r9, r9, %[m]\n\t"
  28580. "ADCS r6, r6, r8\n\t"
  28581. "ADCS r7, r7, r9\n\t"
  28582. "STM %[r]!, {r6, r7}\n\t"
  28583. "LDM %[a]!, {r6, r7}\n\t"
  28584. "LDM %[b]!, {r8, r9}\n\t"
  28585. "AND r8, r8, %[m]\n\t"
  28586. "AND r9, r9, %[m]\n\t"
  28587. "ADCS r6, r6, r8\n\t"
  28588. "ADCS r7, r7, r9\n\t"
  28589. "STM %[r]!, {r6, r7}\n\t"
  28590. "LDM %[a]!, {r6, r7}\n\t"
  28591. "LDM %[b]!, {r8, r9}\n\t"
  28592. "AND r8, r8, %[m]\n\t"
  28593. "AND r9, r9, %[m]\n\t"
  28594. "ADCS r6, r6, r8\n\t"
  28595. "ADCS r7, r7, r9\n\t"
  28596. "STM %[r]!, {r6, r7}\n\t"
  28597. "LDM %[a]!, {r6, r7}\n\t"
  28598. "LDM %[b]!, {r8, r9}\n\t"
  28599. "AND r8, r8, %[m]\n\t"
  28600. "AND r9, r9, %[m]\n\t"
  28601. "ADCS r6, r6, r8\n\t"
  28602. "ADCS r7, r7, r9\n\t"
  28603. "STM %[r]!, {r6, r7}\n\t"
  28604. "LDM %[a]!, {r6, r7}\n\t"
  28605. "LDM %[b]!, {r8, r9}\n\t"
  28606. "AND r8, r8, %[m]\n\t"
  28607. "AND r9, r9, %[m]\n\t"
  28608. "ADCS r6, r6, r8\n\t"
  28609. "ADCS r7, r7, r9\n\t"
  28610. "STM %[r]!, {r6, r7}\n\t"
  28611. "LDM %[a]!, {r6, r7}\n\t"
  28612. "LDM %[b]!, {r8, r9}\n\t"
  28613. "AND r8, r8, %[m]\n\t"
  28614. "AND r9, r9, %[m]\n\t"
  28615. "ADCS r6, r6, r8\n\t"
  28616. "ADCS r7, r7, r9\n\t"
  28617. "STM %[r]!, {r6, r7}\n\t"
  28618. "LDM %[a]!, {r6, r7}\n\t"
  28619. "LDM %[b]!, {r8, r9}\n\t"
  28620. "AND r8, r8, %[m]\n\t"
  28621. "AND r9, r9, %[m]\n\t"
  28622. "ADCS r6, r6, r8\n\t"
  28623. "ADCS r7, r7, r9\n\t"
  28624. "STM %[r]!, {r6, r7}\n\t"
  28625. "LDM %[a]!, {r6, r7}\n\t"
  28626. "LDM %[b]!, {r8, r9}\n\t"
  28627. "AND r8, r8, %[m]\n\t"
  28628. "AND r9, r9, %[m]\n\t"
  28629. "ADCS r6, r6, r8\n\t"
  28630. "ADCS r7, r7, r9\n\t"
  28631. "STM %[r]!, {r6, r7}\n\t"
  28632. "LDM %[a]!, {r6, r7}\n\t"
  28633. "LDM %[b]!, {r8, r9}\n\t"
  28634. "AND r8, r8, %[m]\n\t"
  28635. "AND r9, r9, %[m]\n\t"
  28636. "ADCS r6, r6, r8\n\t"
  28637. "ADCS r7, r7, r9\n\t"
  28638. "STM %[r]!, {r6, r7}\n\t"
  28639. "LDM %[a]!, {r6, r7}\n\t"
  28640. "LDM %[b]!, {r8, r9}\n\t"
  28641. "AND r8, r8, %[m]\n\t"
  28642. "AND r9, r9, %[m]\n\t"
  28643. "ADCS r6, r6, r8\n\t"
  28644. "ADCS r7, r7, r9\n\t"
  28645. "STM %[r]!, {r6, r7}\n\t"
  28646. "ADC %[r], r10, r10\n\t"
  28647. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  28648. :
  28649. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  28650. );
  28651. return (uint32_t)(size_t)r;
  28652. }
  28653. #endif /* WOLFSSL_SP_SMALL */
  28654. /* RSA private key operation.
  28655. *
  28656. * in Array of bytes representing the number to exponentiate, base.
  28657. * inLen Number of bytes in base.
  28658. * dm Private exponent.
  28659. * pm First prime.
  28660. * qm Second prime.
  28661. * dpm First prime's CRT exponent.
  28662. * dqm Second prime's CRT exponent.
  28663. * qim Inverse of second prime mod p.
  28664. * mm Modulus.
  28665. * out Buffer to hold big-endian bytes of exponentiation result.
  28666. * Must be at least 512 bytes long.
  28667. * outLen Number of bytes in result.
  28668. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  28669. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  28670. */
  28671. int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
  28672. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  28673. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  28674. {
  28675. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  28676. #ifdef WOLFSSL_SP_SMALL_STACK
  28677. sp_digit* d = NULL;
  28678. #else
  28679. sp_digit d[128 * 4];
  28680. #endif
  28681. sp_digit* a = NULL;
  28682. sp_digit* m = NULL;
  28683. sp_digit* r = NULL;
  28684. int err = MP_OKAY;
  28685. (void)pm;
  28686. (void)qm;
  28687. (void)dpm;
  28688. (void)dqm;
  28689. (void)qim;
  28690. if (*outLen < 512U) {
  28691. err = MP_TO_E;
  28692. }
  28693. if (err == MP_OKAY) {
  28694. if (mp_count_bits(dm) > 4096) {
  28695. err = MP_READ_E;
  28696. }
  28697. else if (inLen > 512) {
  28698. err = MP_READ_E;
  28699. }
  28700. else if (mp_count_bits(mm) != 4096) {
  28701. err = MP_READ_E;
  28702. }
  28703. else if (mp_iseven(mm)) {
  28704. err = MP_VAL;
  28705. }
  28706. }
  28707. #ifdef WOLFSSL_SP_SMALL_STACK
  28708. if (err == MP_OKAY) {
  28709. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 4, NULL,
  28710. DYNAMIC_TYPE_RSA);
  28711. if (d == NULL)
  28712. err = MEMORY_E;
  28713. }
  28714. #endif
  28715. if (err == MP_OKAY) {
  28716. a = d + 128;
  28717. m = a + 256;
  28718. r = a;
  28719. sp_4096_from_bin(a, 128, in, inLen);
  28720. sp_4096_from_mp(d, 128, dm);
  28721. sp_4096_from_mp(m, 128, mm);
  28722. err = sp_4096_mod_exp_128(r, a, d, 4096, m, 0);
  28723. }
  28724. if (err == MP_OKAY) {
  28725. sp_4096_to_bin_128(r, out);
  28726. *outLen = 512;
  28727. }
  28728. #ifdef WOLFSSL_SP_SMALL_STACK
  28729. if (d != NULL)
  28730. #endif
  28731. {
  28732. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  28733. if (a != NULL)
  28734. ForceZero(a, sizeof(sp_digit) * 128);
  28735. #ifdef WOLFSSL_SP_SMALL_STACK
  28736. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  28737. #endif
  28738. }
  28739. return err;
  28740. #else
  28741. #ifdef WOLFSSL_SP_SMALL_STACK
  28742. sp_digit* a = NULL;
  28743. #else
  28744. sp_digit a[64 * 11];
  28745. #endif
  28746. sp_digit* p = NULL;
  28747. sp_digit* q = NULL;
  28748. sp_digit* dp = NULL;
  28749. sp_digit* tmpa = NULL;
  28750. sp_digit* tmpb = NULL;
  28751. sp_digit* r = NULL;
  28752. sp_digit* qi = NULL;
  28753. sp_digit* dq = NULL;
  28754. sp_digit c;
  28755. int err = MP_OKAY;
  28756. (void)dm;
  28757. (void)mm;
  28758. if (*outLen < 512) {
  28759. err = MP_TO_E;
  28760. }
  28761. else if (inLen > 512 || mp_count_bits(mm) != 4096) {
  28762. err = MP_READ_E;
  28763. }
  28764. else if (mp_iseven(mm)) {
  28765. err = MP_VAL;
  28766. }
  28767. else if (mp_iseven(pm)) {
  28768. err = MP_VAL;
  28769. }
  28770. else if (mp_iseven(qm)) {
  28771. err = MP_VAL;
  28772. }
  28773. #ifdef WOLFSSL_SP_SMALL_STACK
  28774. if (err == MP_OKAY) {
  28775. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL,
  28776. DYNAMIC_TYPE_RSA);
  28777. if (a == NULL)
  28778. err = MEMORY_E;
  28779. }
  28780. #endif
  28781. if (err == MP_OKAY) {
  28782. p = a + 128 * 2;
  28783. q = p + 64;
  28784. qi = dq = dp = q + 64;
  28785. tmpa = qi + 64;
  28786. tmpb = tmpa + 128;
  28787. r = a;
  28788. sp_4096_from_bin(a, 128, in, inLen);
  28789. sp_4096_from_mp(p, 64, pm);
  28790. sp_4096_from_mp(q, 64, qm);
  28791. sp_4096_from_mp(dp, 64, dpm);
  28792. err = sp_2048_mod_exp_64(tmpa, a, dp, 2048, p, 1);
  28793. }
  28794. if (err == MP_OKAY) {
  28795. sp_4096_from_mp(dq, 64, dqm);
  28796. err = sp_2048_mod_exp_64(tmpb, a, dq, 2048, q, 1);
  28797. }
  28798. if (err == MP_OKAY) {
  28799. c = sp_2048_sub_in_place_64(tmpa, tmpb);
  28800. c += sp_4096_cond_add_64(tmpa, tmpa, p, c);
  28801. sp_4096_cond_add_64(tmpa, tmpa, p, c);
  28802. sp_2048_from_mp(qi, 64, qim);
  28803. sp_2048_mul_64(tmpa, tmpa, qi);
  28804. err = sp_2048_mod_64(tmpa, tmpa, p);
  28805. }
  28806. if (err == MP_OKAY) {
  28807. sp_2048_mul_64(tmpa, q, tmpa);
  28808. XMEMSET(&tmpb[64], 0, sizeof(sp_digit) * 64);
  28809. sp_4096_add_128(r, tmpb, tmpa);
  28810. sp_4096_to_bin_128(r, out);
  28811. *outLen = 512;
  28812. }
  28813. #ifdef WOLFSSL_SP_SMALL_STACK
  28814. if (a != NULL)
  28815. #endif
  28816. {
  28817. ForceZero(a, sizeof(sp_digit) * 64 * 11);
  28818. #ifdef WOLFSSL_SP_SMALL_STACK
  28819. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  28820. #endif
  28821. }
  28822. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  28823. return err;
  28824. }
  28825. #endif /* WOLFSSL_RSA_PUBLIC_ONLY */
  28826. #endif /* WOLFSSL_HAVE_SP_RSA */
  28827. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  28828. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  28829. /* Convert an array of sp_digit to an mp_int.
  28830. *
  28831. * a A single precision integer.
  28832. * r A multi-precision integer.
  28833. */
  28834. static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
  28835. {
  28836. int err;
  28837. err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT);
  28838. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  28839. #if DIGIT_BIT == 32
  28840. XMEMCPY(r->dp, a, sizeof(sp_digit) * 128);
  28841. r->used = 128;
  28842. mp_clamp(r);
  28843. #elif DIGIT_BIT < 32
  28844. int i;
  28845. int j = 0;
  28846. int s = 0;
  28847. r->dp[0] = 0;
  28848. for (i = 0; i < 128; i++) {
  28849. r->dp[j] |= (mp_digit)(a[i] << s);
  28850. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  28851. s = DIGIT_BIT - s;
  28852. r->dp[++j] = (mp_digit)(a[i] >> s);
  28853. while (s + DIGIT_BIT <= 32) {
  28854. s += DIGIT_BIT;
  28855. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  28856. if (s == SP_WORD_SIZE) {
  28857. r->dp[j] = 0;
  28858. }
  28859. else {
  28860. r->dp[j] = (mp_digit)(a[i] >> s);
  28861. }
  28862. }
  28863. s = 32 - s;
  28864. }
  28865. r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
  28866. mp_clamp(r);
  28867. #else
  28868. int i;
  28869. int j = 0;
  28870. int s = 0;
  28871. r->dp[0] = 0;
  28872. for (i = 0; i < 128; i++) {
  28873. r->dp[j] |= ((mp_digit)a[i]) << s;
  28874. if (s + 32 >= DIGIT_BIT) {
  28875. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  28876. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  28877. #endif
  28878. s = DIGIT_BIT - s;
  28879. r->dp[++j] = a[i] >> s;
  28880. s = 32 - s;
  28881. }
  28882. else {
  28883. s += 32;
  28884. }
  28885. }
  28886. r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
  28887. mp_clamp(r);
  28888. #endif
  28889. }
  28890. return err;
  28891. }
  28892. /* Perform the modular exponentiation for Diffie-Hellman.
  28893. *
  28894. * base Base. MP integer.
  28895. * exp Exponent. MP integer.
  28896. * mod Modulus. MP integer.
  28897. * res Result. MP integer.
  28898. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  28899. * and MEMORY_E if memory allocation fails.
  28900. */
  28901. int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
  28902. mp_int* res)
  28903. {
  28904. int err = MP_OKAY;
  28905. sp_digit b[256];
  28906. sp_digit e[128];
  28907. sp_digit m[128];
  28908. sp_digit* r = b;
  28909. int expBits = mp_count_bits(exp);
  28910. if (mp_count_bits(base) > 4096) {
  28911. err = MP_READ_E;
  28912. }
  28913. else if (expBits > 4096) {
  28914. err = MP_READ_E;
  28915. }
  28916. else if (mp_count_bits(mod) != 4096) {
  28917. err = MP_READ_E;
  28918. }
  28919. else if (mp_iseven(mod)) {
  28920. err = MP_VAL;
  28921. }
  28922. if (err == MP_OKAY) {
  28923. sp_4096_from_mp(b, 128, base);
  28924. sp_4096_from_mp(e, 128, exp);
  28925. sp_4096_from_mp(m, 128, mod);
  28926. err = sp_4096_mod_exp_128(r, b, e, expBits, m, 0);
  28927. }
  28928. if (err == MP_OKAY) {
  28929. err = sp_4096_to_mp(r, res);
  28930. }
  28931. XMEMSET(e, 0, sizeof(e));
  28932. return err;
  28933. }
  28934. #ifdef WOLFSSL_HAVE_SP_DH
  28935. #ifdef HAVE_FFDHE_4096
  28936. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  28937. static void sp_4096_lshift_128(sp_digit* r_p, const sp_digit* a_p, byte n_p)
  28938. #else
  28939. static void sp_4096_lshift_128(sp_digit* r, const sp_digit* a, byte n)
  28940. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  28941. {
  28942. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  28943. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  28944. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  28945. register byte n __asm__ ("r2") = (byte)n_p;
  28946. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  28947. __asm__ __volatile__ (
  28948. "RSB r7, %[n], #0x1f\n\t"
  28949. "LDR r5, [%[a], #508]\n\t"
  28950. "LSR r6, r5, #1\n\t"
  28951. "LSL r5, r5, %[n]\n\t"
  28952. "LSR r6, r6, r7\n\t"
  28953. "LDR r4, [%[a], #504]\n\t"
  28954. "STR r6, [%[r], #512]\n\t"
  28955. "LSR r3, r4, #1\n\t"
  28956. "LSL r4, r4, %[n]\n\t"
  28957. "LSR r3, r3, r7\n\t"
  28958. "ORR r5, r5, r3\n\t"
  28959. "LDR r6, [%[a], #500]\n\t"
  28960. "STR r5, [%[r], #508]\n\t"
  28961. "LSR r3, r6, #1\n\t"
  28962. "LSL r6, r6, %[n]\n\t"
  28963. "LSR r3, r3, r7\n\t"
  28964. "ORR r4, r4, r3\n\t"
  28965. "LDR r5, [%[a], #496]\n\t"
  28966. "STR r4, [%[r], #504]\n\t"
  28967. "LSR r3, r5, #1\n\t"
  28968. "LSL r5, r5, %[n]\n\t"
  28969. "LSR r3, r3, r7\n\t"
  28970. "ORR r6, r6, r3\n\t"
  28971. "LDR r4, [%[a], #492]\n\t"
  28972. "STR r6, [%[r], #500]\n\t"
  28973. "LSR r3, r4, #1\n\t"
  28974. "LSL r4, r4, %[n]\n\t"
  28975. "LSR r3, r3, r7\n\t"
  28976. "ORR r5, r5, r3\n\t"
  28977. "LDR r6, [%[a], #488]\n\t"
  28978. "STR r5, [%[r], #496]\n\t"
  28979. "LSR r3, r6, #1\n\t"
  28980. "LSL r6, r6, %[n]\n\t"
  28981. "LSR r3, r3, r7\n\t"
  28982. "ORR r4, r4, r3\n\t"
  28983. "LDR r5, [%[a], #484]\n\t"
  28984. "STR r4, [%[r], #492]\n\t"
  28985. "LSR r3, r5, #1\n\t"
  28986. "LSL r5, r5, %[n]\n\t"
  28987. "LSR r3, r3, r7\n\t"
  28988. "ORR r6, r6, r3\n\t"
  28989. "LDR r4, [%[a], #480]\n\t"
  28990. "STR r6, [%[r], #488]\n\t"
  28991. "LSR r3, r4, #1\n\t"
  28992. "LSL r4, r4, %[n]\n\t"
  28993. "LSR r3, r3, r7\n\t"
  28994. "ORR r5, r5, r3\n\t"
  28995. "LDR r6, [%[a], #476]\n\t"
  28996. "STR r5, [%[r], #484]\n\t"
  28997. "LSR r3, r6, #1\n\t"
  28998. "LSL r6, r6, %[n]\n\t"
  28999. "LSR r3, r3, r7\n\t"
  29000. "ORR r4, r4, r3\n\t"
  29001. "LDR r5, [%[a], #472]\n\t"
  29002. "STR r4, [%[r], #480]\n\t"
  29003. "LSR r3, r5, #1\n\t"
  29004. "LSL r5, r5, %[n]\n\t"
  29005. "LSR r3, r3, r7\n\t"
  29006. "ORR r6, r6, r3\n\t"
  29007. "LDR r4, [%[a], #468]\n\t"
  29008. "STR r6, [%[r], #476]\n\t"
  29009. "LSR r3, r4, #1\n\t"
  29010. "LSL r4, r4, %[n]\n\t"
  29011. "LSR r3, r3, r7\n\t"
  29012. "ORR r5, r5, r3\n\t"
  29013. "LDR r6, [%[a], #464]\n\t"
  29014. "STR r5, [%[r], #472]\n\t"
  29015. "LSR r3, r6, #1\n\t"
  29016. "LSL r6, r6, %[n]\n\t"
  29017. "LSR r3, r3, r7\n\t"
  29018. "ORR r4, r4, r3\n\t"
  29019. "LDR r5, [%[a], #460]\n\t"
  29020. "STR r4, [%[r], #468]\n\t"
  29021. "LSR r3, r5, #1\n\t"
  29022. "LSL r5, r5, %[n]\n\t"
  29023. "LSR r3, r3, r7\n\t"
  29024. "ORR r6, r6, r3\n\t"
  29025. "LDR r4, [%[a], #456]\n\t"
  29026. "STR r6, [%[r], #464]\n\t"
  29027. "LSR r3, r4, #1\n\t"
  29028. "LSL r4, r4, %[n]\n\t"
  29029. "LSR r3, r3, r7\n\t"
  29030. "ORR r5, r5, r3\n\t"
  29031. "LDR r6, [%[a], #452]\n\t"
  29032. "STR r5, [%[r], #460]\n\t"
  29033. "LSR r3, r6, #1\n\t"
  29034. "LSL r6, r6, %[n]\n\t"
  29035. "LSR r3, r3, r7\n\t"
  29036. "ORR r4, r4, r3\n\t"
  29037. "LDR r5, [%[a], #448]\n\t"
  29038. "STR r4, [%[r], #456]\n\t"
  29039. "LSR r3, r5, #1\n\t"
  29040. "LSL r5, r5, %[n]\n\t"
  29041. "LSR r3, r3, r7\n\t"
  29042. "ORR r6, r6, r3\n\t"
  29043. "LDR r4, [%[a], #444]\n\t"
  29044. "STR r6, [%[r], #452]\n\t"
  29045. "LSR r3, r4, #1\n\t"
  29046. "LSL r4, r4, %[n]\n\t"
  29047. "LSR r3, r3, r7\n\t"
  29048. "ORR r5, r5, r3\n\t"
  29049. "LDR r6, [%[a], #440]\n\t"
  29050. "STR r5, [%[r], #448]\n\t"
  29051. "LSR r3, r6, #1\n\t"
  29052. "LSL r6, r6, %[n]\n\t"
  29053. "LSR r3, r3, r7\n\t"
  29054. "ORR r4, r4, r3\n\t"
  29055. "LDR r5, [%[a], #436]\n\t"
  29056. "STR r4, [%[r], #444]\n\t"
  29057. "LSR r3, r5, #1\n\t"
  29058. "LSL r5, r5, %[n]\n\t"
  29059. "LSR r3, r3, r7\n\t"
  29060. "ORR r6, r6, r3\n\t"
  29061. "LDR r4, [%[a], #432]\n\t"
  29062. "STR r6, [%[r], #440]\n\t"
  29063. "LSR r3, r4, #1\n\t"
  29064. "LSL r4, r4, %[n]\n\t"
  29065. "LSR r3, r3, r7\n\t"
  29066. "ORR r5, r5, r3\n\t"
  29067. "LDR r6, [%[a], #428]\n\t"
  29068. "STR r5, [%[r], #436]\n\t"
  29069. "LSR r3, r6, #1\n\t"
  29070. "LSL r6, r6, %[n]\n\t"
  29071. "LSR r3, r3, r7\n\t"
  29072. "ORR r4, r4, r3\n\t"
  29073. "LDR r5, [%[a], #424]\n\t"
  29074. "STR r4, [%[r], #432]\n\t"
  29075. "LSR r3, r5, #1\n\t"
  29076. "LSL r5, r5, %[n]\n\t"
  29077. "LSR r3, r3, r7\n\t"
  29078. "ORR r6, r6, r3\n\t"
  29079. "LDR r4, [%[a], #420]\n\t"
  29080. "STR r6, [%[r], #428]\n\t"
  29081. "LSR r3, r4, #1\n\t"
  29082. "LSL r4, r4, %[n]\n\t"
  29083. "LSR r3, r3, r7\n\t"
  29084. "ORR r5, r5, r3\n\t"
  29085. "LDR r6, [%[a], #416]\n\t"
  29086. "STR r5, [%[r], #424]\n\t"
  29087. "LSR r3, r6, #1\n\t"
  29088. "LSL r6, r6, %[n]\n\t"
  29089. "LSR r3, r3, r7\n\t"
  29090. "ORR r4, r4, r3\n\t"
  29091. "LDR r5, [%[a], #412]\n\t"
  29092. "STR r4, [%[r], #420]\n\t"
  29093. "LSR r3, r5, #1\n\t"
  29094. "LSL r5, r5, %[n]\n\t"
  29095. "LSR r3, r3, r7\n\t"
  29096. "ORR r6, r6, r3\n\t"
  29097. "LDR r4, [%[a], #408]\n\t"
  29098. "STR r6, [%[r], #416]\n\t"
  29099. "LSR r3, r4, #1\n\t"
  29100. "LSL r4, r4, %[n]\n\t"
  29101. "LSR r3, r3, r7\n\t"
  29102. "ORR r5, r5, r3\n\t"
  29103. "LDR r6, [%[a], #404]\n\t"
  29104. "STR r5, [%[r], #412]\n\t"
  29105. "LSR r3, r6, #1\n\t"
  29106. "LSL r6, r6, %[n]\n\t"
  29107. "LSR r3, r3, r7\n\t"
  29108. "ORR r4, r4, r3\n\t"
  29109. "LDR r5, [%[a], #400]\n\t"
  29110. "STR r4, [%[r], #408]\n\t"
  29111. "LSR r3, r5, #1\n\t"
  29112. "LSL r5, r5, %[n]\n\t"
  29113. "LSR r3, r3, r7\n\t"
  29114. "ORR r6, r6, r3\n\t"
  29115. "LDR r4, [%[a], #396]\n\t"
  29116. "STR r6, [%[r], #404]\n\t"
  29117. "LSR r3, r4, #1\n\t"
  29118. "LSL r4, r4, %[n]\n\t"
  29119. "LSR r3, r3, r7\n\t"
  29120. "ORR r5, r5, r3\n\t"
  29121. "LDR r6, [%[a], #392]\n\t"
  29122. "STR r5, [%[r], #400]\n\t"
  29123. "LSR r3, r6, #1\n\t"
  29124. "LSL r6, r6, %[n]\n\t"
  29125. "LSR r3, r3, r7\n\t"
  29126. "ORR r4, r4, r3\n\t"
  29127. "LDR r5, [%[a], #388]\n\t"
  29128. "STR r4, [%[r], #396]\n\t"
  29129. "LSR r3, r5, #1\n\t"
  29130. "LSL r5, r5, %[n]\n\t"
  29131. "LSR r3, r3, r7\n\t"
  29132. "ORR r6, r6, r3\n\t"
  29133. "LDR r4, [%[a], #384]\n\t"
  29134. "STR r6, [%[r], #392]\n\t"
  29135. "LSR r3, r4, #1\n\t"
  29136. "LSL r4, r4, %[n]\n\t"
  29137. "LSR r3, r3, r7\n\t"
  29138. "ORR r5, r5, r3\n\t"
  29139. "LDR r6, [%[a], #380]\n\t"
  29140. "STR r5, [%[r], #388]\n\t"
  29141. "LSR r3, r6, #1\n\t"
  29142. "LSL r6, r6, %[n]\n\t"
  29143. "LSR r3, r3, r7\n\t"
  29144. "ORR r4, r4, r3\n\t"
  29145. "LDR r5, [%[a], #376]\n\t"
  29146. "STR r4, [%[r], #384]\n\t"
  29147. "LSR r3, r5, #1\n\t"
  29148. "LSL r5, r5, %[n]\n\t"
  29149. "LSR r3, r3, r7\n\t"
  29150. "ORR r6, r6, r3\n\t"
  29151. "LDR r4, [%[a], #372]\n\t"
  29152. "STR r6, [%[r], #380]\n\t"
  29153. "LSR r3, r4, #1\n\t"
  29154. "LSL r4, r4, %[n]\n\t"
  29155. "LSR r3, r3, r7\n\t"
  29156. "ORR r5, r5, r3\n\t"
  29157. "LDR r6, [%[a], #368]\n\t"
  29158. "STR r5, [%[r], #376]\n\t"
  29159. "LSR r3, r6, #1\n\t"
  29160. "LSL r6, r6, %[n]\n\t"
  29161. "LSR r3, r3, r7\n\t"
  29162. "ORR r4, r4, r3\n\t"
  29163. "LDR r5, [%[a], #364]\n\t"
  29164. "STR r4, [%[r], #372]\n\t"
  29165. "LSR r3, r5, #1\n\t"
  29166. "LSL r5, r5, %[n]\n\t"
  29167. "LSR r3, r3, r7\n\t"
  29168. "ORR r6, r6, r3\n\t"
  29169. "LDR r4, [%[a], #360]\n\t"
  29170. "STR r6, [%[r], #368]\n\t"
  29171. "LSR r3, r4, #1\n\t"
  29172. "LSL r4, r4, %[n]\n\t"
  29173. "LSR r3, r3, r7\n\t"
  29174. "ORR r5, r5, r3\n\t"
  29175. "LDR r6, [%[a], #356]\n\t"
  29176. "STR r5, [%[r], #364]\n\t"
  29177. "LSR r3, r6, #1\n\t"
  29178. "LSL r6, r6, %[n]\n\t"
  29179. "LSR r3, r3, r7\n\t"
  29180. "ORR r4, r4, r3\n\t"
  29181. "LDR r5, [%[a], #352]\n\t"
  29182. "STR r4, [%[r], #360]\n\t"
  29183. "LSR r3, r5, #1\n\t"
  29184. "LSL r5, r5, %[n]\n\t"
  29185. "LSR r3, r3, r7\n\t"
  29186. "ORR r6, r6, r3\n\t"
  29187. "LDR r4, [%[a], #348]\n\t"
  29188. "STR r6, [%[r], #356]\n\t"
  29189. "LSR r3, r4, #1\n\t"
  29190. "LSL r4, r4, %[n]\n\t"
  29191. "LSR r3, r3, r7\n\t"
  29192. "ORR r5, r5, r3\n\t"
  29193. "LDR r6, [%[a], #344]\n\t"
  29194. "STR r5, [%[r], #352]\n\t"
  29195. "LSR r3, r6, #1\n\t"
  29196. "LSL r6, r6, %[n]\n\t"
  29197. "LSR r3, r3, r7\n\t"
  29198. "ORR r4, r4, r3\n\t"
  29199. "LDR r5, [%[a], #340]\n\t"
  29200. "STR r4, [%[r], #348]\n\t"
  29201. "LSR r3, r5, #1\n\t"
  29202. "LSL r5, r5, %[n]\n\t"
  29203. "LSR r3, r3, r7\n\t"
  29204. "ORR r6, r6, r3\n\t"
  29205. "LDR r4, [%[a], #336]\n\t"
  29206. "STR r6, [%[r], #344]\n\t"
  29207. "LSR r3, r4, #1\n\t"
  29208. "LSL r4, r4, %[n]\n\t"
  29209. "LSR r3, r3, r7\n\t"
  29210. "ORR r5, r5, r3\n\t"
  29211. "LDR r6, [%[a], #332]\n\t"
  29212. "STR r5, [%[r], #340]\n\t"
  29213. "LSR r3, r6, #1\n\t"
  29214. "LSL r6, r6, %[n]\n\t"
  29215. "LSR r3, r3, r7\n\t"
  29216. "ORR r4, r4, r3\n\t"
  29217. "LDR r5, [%[a], #328]\n\t"
  29218. "STR r4, [%[r], #336]\n\t"
  29219. "LSR r3, r5, #1\n\t"
  29220. "LSL r5, r5, %[n]\n\t"
  29221. "LSR r3, r3, r7\n\t"
  29222. "ORR r6, r6, r3\n\t"
  29223. "LDR r4, [%[a], #324]\n\t"
  29224. "STR r6, [%[r], #332]\n\t"
  29225. "LSR r3, r4, #1\n\t"
  29226. "LSL r4, r4, %[n]\n\t"
  29227. "LSR r3, r3, r7\n\t"
  29228. "ORR r5, r5, r3\n\t"
  29229. "LDR r6, [%[a], #320]\n\t"
  29230. "STR r5, [%[r], #328]\n\t"
  29231. "LSR r3, r6, #1\n\t"
  29232. "LSL r6, r6, %[n]\n\t"
  29233. "LSR r3, r3, r7\n\t"
  29234. "ORR r4, r4, r3\n\t"
  29235. "LDR r5, [%[a], #316]\n\t"
  29236. "STR r4, [%[r], #324]\n\t"
  29237. "LSR r3, r5, #1\n\t"
  29238. "LSL r5, r5, %[n]\n\t"
  29239. "LSR r3, r3, r7\n\t"
  29240. "ORR r6, r6, r3\n\t"
  29241. "LDR r4, [%[a], #312]\n\t"
  29242. "STR r6, [%[r], #320]\n\t"
  29243. "LSR r3, r4, #1\n\t"
  29244. "LSL r4, r4, %[n]\n\t"
  29245. "LSR r3, r3, r7\n\t"
  29246. "ORR r5, r5, r3\n\t"
  29247. "LDR r6, [%[a], #308]\n\t"
  29248. "STR r5, [%[r], #316]\n\t"
  29249. "LSR r3, r6, #1\n\t"
  29250. "LSL r6, r6, %[n]\n\t"
  29251. "LSR r3, r3, r7\n\t"
  29252. "ORR r4, r4, r3\n\t"
  29253. "LDR r5, [%[a], #304]\n\t"
  29254. "STR r4, [%[r], #312]\n\t"
  29255. "LSR r3, r5, #1\n\t"
  29256. "LSL r5, r5, %[n]\n\t"
  29257. "LSR r3, r3, r7\n\t"
  29258. "ORR r6, r6, r3\n\t"
  29259. "LDR r4, [%[a], #300]\n\t"
  29260. "STR r6, [%[r], #308]\n\t"
  29261. "LSR r3, r4, #1\n\t"
  29262. "LSL r4, r4, %[n]\n\t"
  29263. "LSR r3, r3, r7\n\t"
  29264. "ORR r5, r5, r3\n\t"
  29265. "LDR r6, [%[a], #296]\n\t"
  29266. "STR r5, [%[r], #304]\n\t"
  29267. "LSR r3, r6, #1\n\t"
  29268. "LSL r6, r6, %[n]\n\t"
  29269. "LSR r3, r3, r7\n\t"
  29270. "ORR r4, r4, r3\n\t"
  29271. "LDR r5, [%[a], #292]\n\t"
  29272. "STR r4, [%[r], #300]\n\t"
  29273. "LSR r3, r5, #1\n\t"
  29274. "LSL r5, r5, %[n]\n\t"
  29275. "LSR r3, r3, r7\n\t"
  29276. "ORR r6, r6, r3\n\t"
  29277. "LDR r4, [%[a], #288]\n\t"
  29278. "STR r6, [%[r], #296]\n\t"
  29279. "LSR r3, r4, #1\n\t"
  29280. "LSL r4, r4, %[n]\n\t"
  29281. "LSR r3, r3, r7\n\t"
  29282. "ORR r5, r5, r3\n\t"
  29283. "LDR r6, [%[a], #284]\n\t"
  29284. "STR r5, [%[r], #292]\n\t"
  29285. "LSR r3, r6, #1\n\t"
  29286. "LSL r6, r6, %[n]\n\t"
  29287. "LSR r3, r3, r7\n\t"
  29288. "ORR r4, r4, r3\n\t"
  29289. "LDR r5, [%[a], #280]\n\t"
  29290. "STR r4, [%[r], #288]\n\t"
  29291. "LSR r3, r5, #1\n\t"
  29292. "LSL r5, r5, %[n]\n\t"
  29293. "LSR r3, r3, r7\n\t"
  29294. "ORR r6, r6, r3\n\t"
  29295. "LDR r4, [%[a], #276]\n\t"
  29296. "STR r6, [%[r], #284]\n\t"
  29297. "LSR r3, r4, #1\n\t"
  29298. "LSL r4, r4, %[n]\n\t"
  29299. "LSR r3, r3, r7\n\t"
  29300. "ORR r5, r5, r3\n\t"
  29301. "LDR r6, [%[a], #272]\n\t"
  29302. "STR r5, [%[r], #280]\n\t"
  29303. "LSR r3, r6, #1\n\t"
  29304. "LSL r6, r6, %[n]\n\t"
  29305. "LSR r3, r3, r7\n\t"
  29306. "ORR r4, r4, r3\n\t"
  29307. "LDR r5, [%[a], #268]\n\t"
  29308. "STR r4, [%[r], #276]\n\t"
  29309. "LSR r3, r5, #1\n\t"
  29310. "LSL r5, r5, %[n]\n\t"
  29311. "LSR r3, r3, r7\n\t"
  29312. "ORR r6, r6, r3\n\t"
  29313. "LDR r4, [%[a], #264]\n\t"
  29314. "STR r6, [%[r], #272]\n\t"
  29315. "LSR r3, r4, #1\n\t"
  29316. "LSL r4, r4, %[n]\n\t"
  29317. "LSR r3, r3, r7\n\t"
  29318. "ORR r5, r5, r3\n\t"
  29319. "LDR r6, [%[a], #260]\n\t"
  29320. "STR r5, [%[r], #268]\n\t"
  29321. "LSR r3, r6, #1\n\t"
  29322. "LSL r6, r6, %[n]\n\t"
  29323. "LSR r3, r3, r7\n\t"
  29324. "ORR r4, r4, r3\n\t"
  29325. "LDR r5, [%[a], #256]\n\t"
  29326. "STR r4, [%[r], #264]\n\t"
  29327. "LSR r3, r5, #1\n\t"
  29328. "LSL r5, r5, %[n]\n\t"
  29329. "LSR r3, r3, r7\n\t"
  29330. "ORR r6, r6, r3\n\t"
  29331. "LDR r4, [%[a], #252]\n\t"
  29332. "STR r6, [%[r], #260]\n\t"
  29333. "LSR r3, r4, #1\n\t"
  29334. "LSL r4, r4, %[n]\n\t"
  29335. "LSR r3, r3, r7\n\t"
  29336. "ORR r5, r5, r3\n\t"
  29337. "LDR r6, [%[a], #248]\n\t"
  29338. "STR r5, [%[r], #256]\n\t"
  29339. "LSR r3, r6, #1\n\t"
  29340. "LSL r6, r6, %[n]\n\t"
  29341. "LSR r3, r3, r7\n\t"
  29342. "ORR r4, r4, r3\n\t"
  29343. "LDR r5, [%[a], #244]\n\t"
  29344. "STR r4, [%[r], #252]\n\t"
  29345. "LSR r3, r5, #1\n\t"
  29346. "LSL r5, r5, %[n]\n\t"
  29347. "LSR r3, r3, r7\n\t"
  29348. "ORR r6, r6, r3\n\t"
  29349. "LDR r4, [%[a], #240]\n\t"
  29350. "STR r6, [%[r], #248]\n\t"
  29351. "LSR r3, r4, #1\n\t"
  29352. "LSL r4, r4, %[n]\n\t"
  29353. "LSR r3, r3, r7\n\t"
  29354. "ORR r5, r5, r3\n\t"
  29355. "LDR r6, [%[a], #236]\n\t"
  29356. "STR r5, [%[r], #244]\n\t"
  29357. "LSR r3, r6, #1\n\t"
  29358. "LSL r6, r6, %[n]\n\t"
  29359. "LSR r3, r3, r7\n\t"
  29360. "ORR r4, r4, r3\n\t"
  29361. "LDR r5, [%[a], #232]\n\t"
  29362. "STR r4, [%[r], #240]\n\t"
  29363. "LSR r3, r5, #1\n\t"
  29364. "LSL r5, r5, %[n]\n\t"
  29365. "LSR r3, r3, r7\n\t"
  29366. "ORR r6, r6, r3\n\t"
  29367. "LDR r4, [%[a], #228]\n\t"
  29368. "STR r6, [%[r], #236]\n\t"
  29369. "LSR r3, r4, #1\n\t"
  29370. "LSL r4, r4, %[n]\n\t"
  29371. "LSR r3, r3, r7\n\t"
  29372. "ORR r5, r5, r3\n\t"
  29373. "LDR r6, [%[a], #224]\n\t"
  29374. "STR r5, [%[r], #232]\n\t"
  29375. "LSR r3, r6, #1\n\t"
  29376. "LSL r6, r6, %[n]\n\t"
  29377. "LSR r3, r3, r7\n\t"
  29378. "ORR r4, r4, r3\n\t"
  29379. "LDR r5, [%[a], #220]\n\t"
  29380. "STR r4, [%[r], #228]\n\t"
  29381. "LSR r3, r5, #1\n\t"
  29382. "LSL r5, r5, %[n]\n\t"
  29383. "LSR r3, r3, r7\n\t"
  29384. "ORR r6, r6, r3\n\t"
  29385. "LDR r4, [%[a], #216]\n\t"
  29386. "STR r6, [%[r], #224]\n\t"
  29387. "LSR r3, r4, #1\n\t"
  29388. "LSL r4, r4, %[n]\n\t"
  29389. "LSR r3, r3, r7\n\t"
  29390. "ORR r5, r5, r3\n\t"
  29391. "LDR r6, [%[a], #212]\n\t"
  29392. "STR r5, [%[r], #220]\n\t"
  29393. "LSR r3, r6, #1\n\t"
  29394. "LSL r6, r6, %[n]\n\t"
  29395. "LSR r3, r3, r7\n\t"
  29396. "ORR r4, r4, r3\n\t"
  29397. "LDR r5, [%[a], #208]\n\t"
  29398. "STR r4, [%[r], #216]\n\t"
  29399. "LSR r3, r5, #1\n\t"
  29400. "LSL r5, r5, %[n]\n\t"
  29401. "LSR r3, r3, r7\n\t"
  29402. "ORR r6, r6, r3\n\t"
  29403. "LDR r4, [%[a], #204]\n\t"
  29404. "STR r6, [%[r], #212]\n\t"
  29405. "LSR r3, r4, #1\n\t"
  29406. "LSL r4, r4, %[n]\n\t"
  29407. "LSR r3, r3, r7\n\t"
  29408. "ORR r5, r5, r3\n\t"
  29409. "LDR r6, [%[a], #200]\n\t"
  29410. "STR r5, [%[r], #208]\n\t"
  29411. "LSR r3, r6, #1\n\t"
  29412. "LSL r6, r6, %[n]\n\t"
  29413. "LSR r3, r3, r7\n\t"
  29414. "ORR r4, r4, r3\n\t"
  29415. "LDR r5, [%[a], #196]\n\t"
  29416. "STR r4, [%[r], #204]\n\t"
  29417. "LSR r3, r5, #1\n\t"
  29418. "LSL r5, r5, %[n]\n\t"
  29419. "LSR r3, r3, r7\n\t"
  29420. "ORR r6, r6, r3\n\t"
  29421. "LDR r4, [%[a], #192]\n\t"
  29422. "STR r6, [%[r], #200]\n\t"
  29423. "LSR r3, r4, #1\n\t"
  29424. "LSL r4, r4, %[n]\n\t"
  29425. "LSR r3, r3, r7\n\t"
  29426. "ORR r5, r5, r3\n\t"
  29427. "LDR r6, [%[a], #188]\n\t"
  29428. "STR r5, [%[r], #196]\n\t"
  29429. "LSR r3, r6, #1\n\t"
  29430. "LSL r6, r6, %[n]\n\t"
  29431. "LSR r3, r3, r7\n\t"
  29432. "ORR r4, r4, r3\n\t"
  29433. "LDR r5, [%[a], #184]\n\t"
  29434. "STR r4, [%[r], #192]\n\t"
  29435. "LSR r3, r5, #1\n\t"
  29436. "LSL r5, r5, %[n]\n\t"
  29437. "LSR r3, r3, r7\n\t"
  29438. "ORR r6, r6, r3\n\t"
  29439. "LDR r4, [%[a], #180]\n\t"
  29440. "STR r6, [%[r], #188]\n\t"
  29441. "LSR r3, r4, #1\n\t"
  29442. "LSL r4, r4, %[n]\n\t"
  29443. "LSR r3, r3, r7\n\t"
  29444. "ORR r5, r5, r3\n\t"
  29445. "LDR r6, [%[a], #176]\n\t"
  29446. "STR r5, [%[r], #184]\n\t"
  29447. "LSR r3, r6, #1\n\t"
  29448. "LSL r6, r6, %[n]\n\t"
  29449. "LSR r3, r3, r7\n\t"
  29450. "ORR r4, r4, r3\n\t"
  29451. "LDR r5, [%[a], #172]\n\t"
  29452. "STR r4, [%[r], #180]\n\t"
  29453. "LSR r3, r5, #1\n\t"
  29454. "LSL r5, r5, %[n]\n\t"
  29455. "LSR r3, r3, r7\n\t"
  29456. "ORR r6, r6, r3\n\t"
  29457. "LDR r4, [%[a], #168]\n\t"
  29458. "STR r6, [%[r], #176]\n\t"
  29459. "LSR r3, r4, #1\n\t"
  29460. "LSL r4, r4, %[n]\n\t"
  29461. "LSR r3, r3, r7\n\t"
  29462. "ORR r5, r5, r3\n\t"
  29463. "LDR r6, [%[a], #164]\n\t"
  29464. "STR r5, [%[r], #172]\n\t"
  29465. "LSR r3, r6, #1\n\t"
  29466. "LSL r6, r6, %[n]\n\t"
  29467. "LSR r3, r3, r7\n\t"
  29468. "ORR r4, r4, r3\n\t"
  29469. "LDR r5, [%[a], #160]\n\t"
  29470. "STR r4, [%[r], #168]\n\t"
  29471. "LSR r3, r5, #1\n\t"
  29472. "LSL r5, r5, %[n]\n\t"
  29473. "LSR r3, r3, r7\n\t"
  29474. "ORR r6, r6, r3\n\t"
  29475. "LDR r4, [%[a], #156]\n\t"
  29476. "STR r6, [%[r], #164]\n\t"
  29477. "LSR r3, r4, #1\n\t"
  29478. "LSL r4, r4, %[n]\n\t"
  29479. "LSR r3, r3, r7\n\t"
  29480. "ORR r5, r5, r3\n\t"
  29481. "LDR r6, [%[a], #152]\n\t"
  29482. "STR r5, [%[r], #160]\n\t"
  29483. "LSR r3, r6, #1\n\t"
  29484. "LSL r6, r6, %[n]\n\t"
  29485. "LSR r3, r3, r7\n\t"
  29486. "ORR r4, r4, r3\n\t"
  29487. "LDR r5, [%[a], #148]\n\t"
  29488. "STR r4, [%[r], #156]\n\t"
  29489. "LSR r3, r5, #1\n\t"
  29490. "LSL r5, r5, %[n]\n\t"
  29491. "LSR r3, r3, r7\n\t"
  29492. "ORR r6, r6, r3\n\t"
  29493. "LDR r4, [%[a], #144]\n\t"
  29494. "STR r6, [%[r], #152]\n\t"
  29495. "LSR r3, r4, #1\n\t"
  29496. "LSL r4, r4, %[n]\n\t"
  29497. "LSR r3, r3, r7\n\t"
  29498. "ORR r5, r5, r3\n\t"
  29499. "LDR r6, [%[a], #140]\n\t"
  29500. "STR r5, [%[r], #148]\n\t"
  29501. "LSR r3, r6, #1\n\t"
  29502. "LSL r6, r6, %[n]\n\t"
  29503. "LSR r3, r3, r7\n\t"
  29504. "ORR r4, r4, r3\n\t"
  29505. "LDR r5, [%[a], #136]\n\t"
  29506. "STR r4, [%[r], #144]\n\t"
  29507. "LSR r3, r5, #1\n\t"
  29508. "LSL r5, r5, %[n]\n\t"
  29509. "LSR r3, r3, r7\n\t"
  29510. "ORR r6, r6, r3\n\t"
  29511. "LDR r4, [%[a], #132]\n\t"
  29512. "STR r6, [%[r], #140]\n\t"
  29513. "LSR r3, r4, #1\n\t"
  29514. "LSL r4, r4, %[n]\n\t"
  29515. "LSR r3, r3, r7\n\t"
  29516. "ORR r5, r5, r3\n\t"
  29517. "LDR r6, [%[a], #128]\n\t"
  29518. "STR r5, [%[r], #136]\n\t"
  29519. "LSR r3, r6, #1\n\t"
  29520. "LSL r6, r6, %[n]\n\t"
  29521. "LSR r3, r3, r7\n\t"
  29522. "ORR r4, r4, r3\n\t"
  29523. "LDR r5, [%[a], #124]\n\t"
  29524. "STR r4, [%[r], #132]\n\t"
  29525. "LSR r3, r5, #1\n\t"
  29526. "LSL r5, r5, %[n]\n\t"
  29527. "LSR r3, r3, r7\n\t"
  29528. "ORR r6, r6, r3\n\t"
  29529. "LDR r4, [%[a], #120]\n\t"
  29530. "STR r6, [%[r], #128]\n\t"
  29531. "LSR r3, r4, #1\n\t"
  29532. "LSL r4, r4, %[n]\n\t"
  29533. "LSR r3, r3, r7\n\t"
  29534. "ORR r5, r5, r3\n\t"
  29535. "LDR r6, [%[a], #116]\n\t"
  29536. "STR r5, [%[r], #124]\n\t"
  29537. "LSR r3, r6, #1\n\t"
  29538. "LSL r6, r6, %[n]\n\t"
  29539. "LSR r3, r3, r7\n\t"
  29540. "ORR r4, r4, r3\n\t"
  29541. "LDR r5, [%[a], #112]\n\t"
  29542. "STR r4, [%[r], #120]\n\t"
  29543. "LSR r3, r5, #1\n\t"
  29544. "LSL r5, r5, %[n]\n\t"
  29545. "LSR r3, r3, r7\n\t"
  29546. "ORR r6, r6, r3\n\t"
  29547. "LDR r4, [%[a], #108]\n\t"
  29548. "STR r6, [%[r], #116]\n\t"
  29549. "LSR r3, r4, #1\n\t"
  29550. "LSL r4, r4, %[n]\n\t"
  29551. "LSR r3, r3, r7\n\t"
  29552. "ORR r5, r5, r3\n\t"
  29553. "LDR r6, [%[a], #104]\n\t"
  29554. "STR r5, [%[r], #112]\n\t"
  29555. "LSR r3, r6, #1\n\t"
  29556. "LSL r6, r6, %[n]\n\t"
  29557. "LSR r3, r3, r7\n\t"
  29558. "ORR r4, r4, r3\n\t"
  29559. "LDR r5, [%[a], #100]\n\t"
  29560. "STR r4, [%[r], #108]\n\t"
  29561. "LSR r3, r5, #1\n\t"
  29562. "LSL r5, r5, %[n]\n\t"
  29563. "LSR r3, r3, r7\n\t"
  29564. "ORR r6, r6, r3\n\t"
  29565. "LDR r4, [%[a], #96]\n\t"
  29566. "STR r6, [%[r], #104]\n\t"
  29567. "LSR r3, r4, #1\n\t"
  29568. "LSL r4, r4, %[n]\n\t"
  29569. "LSR r3, r3, r7\n\t"
  29570. "ORR r5, r5, r3\n\t"
  29571. "LDR r6, [%[a], #92]\n\t"
  29572. "STR r5, [%[r], #100]\n\t"
  29573. "LSR r3, r6, #1\n\t"
  29574. "LSL r6, r6, %[n]\n\t"
  29575. "LSR r3, r3, r7\n\t"
  29576. "ORR r4, r4, r3\n\t"
  29577. "LDR r5, [%[a], #88]\n\t"
  29578. "STR r4, [%[r], #96]\n\t"
  29579. "LSR r3, r5, #1\n\t"
  29580. "LSL r5, r5, %[n]\n\t"
  29581. "LSR r3, r3, r7\n\t"
  29582. "ORR r6, r6, r3\n\t"
  29583. "LDR r4, [%[a], #84]\n\t"
  29584. "STR r6, [%[r], #92]\n\t"
  29585. "LSR r3, r4, #1\n\t"
  29586. "LSL r4, r4, %[n]\n\t"
  29587. "LSR r3, r3, r7\n\t"
  29588. "ORR r5, r5, r3\n\t"
  29589. "LDR r6, [%[a], #80]\n\t"
  29590. "STR r5, [%[r], #88]\n\t"
  29591. "LSR r3, r6, #1\n\t"
  29592. "LSL r6, r6, %[n]\n\t"
  29593. "LSR r3, r3, r7\n\t"
  29594. "ORR r4, r4, r3\n\t"
  29595. "LDR r5, [%[a], #76]\n\t"
  29596. "STR r4, [%[r], #84]\n\t"
  29597. "LSR r3, r5, #1\n\t"
  29598. "LSL r5, r5, %[n]\n\t"
  29599. "LSR r3, r3, r7\n\t"
  29600. "ORR r6, r6, r3\n\t"
  29601. "LDR r4, [%[a], #72]\n\t"
  29602. "STR r6, [%[r], #80]\n\t"
  29603. "LSR r3, r4, #1\n\t"
  29604. "LSL r4, r4, %[n]\n\t"
  29605. "LSR r3, r3, r7\n\t"
  29606. "ORR r5, r5, r3\n\t"
  29607. "LDR r6, [%[a], #68]\n\t"
  29608. "STR r5, [%[r], #76]\n\t"
  29609. "LSR r3, r6, #1\n\t"
  29610. "LSL r6, r6, %[n]\n\t"
  29611. "LSR r3, r3, r7\n\t"
  29612. "ORR r4, r4, r3\n\t"
  29613. "LDR r5, [%[a], #64]\n\t"
  29614. "STR r4, [%[r], #72]\n\t"
  29615. "LSR r3, r5, #1\n\t"
  29616. "LSL r5, r5, %[n]\n\t"
  29617. "LSR r3, r3, r7\n\t"
  29618. "ORR r6, r6, r3\n\t"
  29619. "LDR r4, [%[a], #60]\n\t"
  29620. "STR r6, [%[r], #68]\n\t"
  29621. "LSR r3, r4, #1\n\t"
  29622. "LSL r4, r4, %[n]\n\t"
  29623. "LSR r3, r3, r7\n\t"
  29624. "ORR r5, r5, r3\n\t"
  29625. "LDR r6, [%[a], #56]\n\t"
  29626. "STR r5, [%[r], #64]\n\t"
  29627. "LSR r3, r6, #1\n\t"
  29628. "LSL r6, r6, %[n]\n\t"
  29629. "LSR r3, r3, r7\n\t"
  29630. "ORR r4, r4, r3\n\t"
  29631. "LDR r5, [%[a], #52]\n\t"
  29632. "STR r4, [%[r], #60]\n\t"
  29633. "LSR r3, r5, #1\n\t"
  29634. "LSL r5, r5, %[n]\n\t"
  29635. "LSR r3, r3, r7\n\t"
  29636. "ORR r6, r6, r3\n\t"
  29637. "LDR r4, [%[a], #48]\n\t"
  29638. "STR r6, [%[r], #56]\n\t"
  29639. "LSR r3, r4, #1\n\t"
  29640. "LSL r4, r4, %[n]\n\t"
  29641. "LSR r3, r3, r7\n\t"
  29642. "ORR r5, r5, r3\n\t"
  29643. "LDR r6, [%[a], #44]\n\t"
  29644. "STR r5, [%[r], #52]\n\t"
  29645. "LSR r3, r6, #1\n\t"
  29646. "LSL r6, r6, %[n]\n\t"
  29647. "LSR r3, r3, r7\n\t"
  29648. "ORR r4, r4, r3\n\t"
  29649. "LDR r5, [%[a], #40]\n\t"
  29650. "STR r4, [%[r], #48]\n\t"
  29651. "LSR r3, r5, #1\n\t"
  29652. "LSL r5, r5, %[n]\n\t"
  29653. "LSR r3, r3, r7\n\t"
  29654. "ORR r6, r6, r3\n\t"
  29655. "LDR r4, [%[a], #36]\n\t"
  29656. "STR r6, [%[r], #44]\n\t"
  29657. "LSR r3, r4, #1\n\t"
  29658. "LSL r4, r4, %[n]\n\t"
  29659. "LSR r3, r3, r7\n\t"
  29660. "ORR r5, r5, r3\n\t"
  29661. "LDR r6, [%[a], #32]\n\t"
  29662. "STR r5, [%[r], #40]\n\t"
  29663. "LSR r3, r6, #1\n\t"
  29664. "LSL r6, r6, %[n]\n\t"
  29665. "LSR r3, r3, r7\n\t"
  29666. "ORR r4, r4, r3\n\t"
  29667. "LDR r5, [%[a], #28]\n\t"
  29668. "STR r4, [%[r], #36]\n\t"
  29669. "LSR r3, r5, #1\n\t"
  29670. "LSL r5, r5, %[n]\n\t"
  29671. "LSR r3, r3, r7\n\t"
  29672. "ORR r6, r6, r3\n\t"
  29673. "LDR r4, [%[a], #24]\n\t"
  29674. "STR r6, [%[r], #32]\n\t"
  29675. "LSR r3, r4, #1\n\t"
  29676. "LSL r4, r4, %[n]\n\t"
  29677. "LSR r3, r3, r7\n\t"
  29678. "ORR r5, r5, r3\n\t"
  29679. "LDR r6, [%[a], #20]\n\t"
  29680. "STR r5, [%[r], #28]\n\t"
  29681. "LSR r3, r6, #1\n\t"
  29682. "LSL r6, r6, %[n]\n\t"
  29683. "LSR r3, r3, r7\n\t"
  29684. "ORR r4, r4, r3\n\t"
  29685. "LDR r5, [%[a], #16]\n\t"
  29686. "STR r4, [%[r], #24]\n\t"
  29687. "LSR r3, r5, #1\n\t"
  29688. "LSL r5, r5, %[n]\n\t"
  29689. "LSR r3, r3, r7\n\t"
  29690. "ORR r6, r6, r3\n\t"
  29691. "LDR r4, [%[a], #12]\n\t"
  29692. "STR r6, [%[r], #20]\n\t"
  29693. "LSR r3, r4, #1\n\t"
  29694. "LSL r4, r4, %[n]\n\t"
  29695. "LSR r3, r3, r7\n\t"
  29696. "ORR r5, r5, r3\n\t"
  29697. "LDR r6, [%[a], #8]\n\t"
  29698. "STR r5, [%[r], #16]\n\t"
  29699. "LSR r3, r6, #1\n\t"
  29700. "LSL r6, r6, %[n]\n\t"
  29701. "LSR r3, r3, r7\n\t"
  29702. "ORR r4, r4, r3\n\t"
  29703. "LDR r5, [%[a], #4]\n\t"
  29704. "STR r4, [%[r], #12]\n\t"
  29705. "LSR r3, r5, #1\n\t"
  29706. "LSL r5, r5, %[n]\n\t"
  29707. "LSR r3, r3, r7\n\t"
  29708. "ORR r6, r6, r3\n\t"
  29709. "LDR r4, [%[a]]\n\t"
  29710. "STR r6, [%[r], #8]\n\t"
  29711. "LSR r3, r4, #1\n\t"
  29712. "LSL r4, r4, %[n]\n\t"
  29713. "LSR r3, r3, r7\n\t"
  29714. "ORR r5, r5, r3\n\t"
  29715. "STR r4, [%[r]]\n\t"
  29716. "STR r5, [%[r], #4]\n\t"
  29717. : [r] "+r" (r), [a] "+r" (a), [n] "+r" (n)
  29718. :
  29719. : "memory", "r4", "r5", "r6", "r3", "r7", "cc"
  29720. );
  29721. }
  29722. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  29723. *
  29724. * r A single precision number that is the result of the operation.
  29725. * e A single precision number that is the exponent.
  29726. * bits The number of bits in the exponent.
  29727. * m A single precision number that is the modulus.
  29728. * returns 0 on success.
  29729. * returns MEMORY_E on dynamic memory allocation failure.
  29730. * returns MP_VAL when base is even.
  29731. */
  29732. static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits,
  29733. const sp_digit* m)
  29734. {
  29735. #ifdef WOLFSSL_SP_SMALL_STACK
  29736. sp_digit* td = NULL;
  29737. #else
  29738. sp_digit td[385];
  29739. #endif
  29740. sp_digit* norm = NULL;
  29741. sp_digit* tmp = NULL;
  29742. sp_digit mp = 1;
  29743. sp_digit n;
  29744. sp_digit o;
  29745. sp_digit mask;
  29746. int i;
  29747. int c;
  29748. byte y;
  29749. int err = MP_OKAY;
  29750. if (bits == 0) {
  29751. err = MP_VAL;
  29752. }
  29753. #ifdef WOLFSSL_SP_SMALL_STACK
  29754. if (err == MP_OKAY) {
  29755. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL,
  29756. DYNAMIC_TYPE_TMP_BUFFER);
  29757. if (td == NULL)
  29758. err = MEMORY_E;
  29759. }
  29760. #endif
  29761. if (err == MP_OKAY) {
  29762. norm = td;
  29763. tmp = td + 256;
  29764. sp_4096_mont_setup(m, &mp);
  29765. sp_4096_mont_norm_128(norm, m);
  29766. i = (bits - 1) / 32;
  29767. n = e[i--];
  29768. c = bits & 31;
  29769. if (c == 0) {
  29770. c = 32;
  29771. }
  29772. c -= bits % 5;
  29773. if (c == 32) {
  29774. c = 27;
  29775. }
  29776. if (c < 0) {
  29777. /* Number of bits in top word is less than number needed. */
  29778. c = -c;
  29779. y = (byte)(n << c);
  29780. n = e[i--];
  29781. y |= (byte)(n >> (64 - c));
  29782. n <<= c;
  29783. c = 64 - c;
  29784. }
  29785. else if (c == 0) {
  29786. /* All bits in top word used. */
  29787. y = (byte)n;
  29788. }
  29789. else {
  29790. y = (byte)(n >> c);
  29791. n <<= 32 - c;
  29792. }
  29793. sp_4096_lshift_128(r, norm, y);
  29794. for (; i>=0 || c>=5; ) {
  29795. if (c == 0) {
  29796. n = e[i--];
  29797. y = (byte)(n >> 27);
  29798. n <<= 5;
  29799. c = 27;
  29800. }
  29801. else if (c < 5) {
  29802. y = (byte)(n >> 27);
  29803. n = e[i--];
  29804. c = 5 - c;
  29805. y |= (byte)(n >> (32 - c));
  29806. n <<= c;
  29807. c = 32 - c;
  29808. }
  29809. else {
  29810. y = (byte)((n >> 27) & 0x1f);
  29811. n <<= 5;
  29812. c -= 5;
  29813. }
  29814. sp_4096_mont_sqr_128(r, r, m, mp);
  29815. sp_4096_mont_sqr_128(r, r, m, mp);
  29816. sp_4096_mont_sqr_128(r, r, m, mp);
  29817. sp_4096_mont_sqr_128(r, r, m, mp);
  29818. sp_4096_mont_sqr_128(r, r, m, mp);
  29819. sp_4096_lshift_128(r, r, y);
  29820. sp_4096_mul_d_128(tmp, norm, r[128]);
  29821. r[128] = 0;
  29822. o = sp_4096_add_128(r, r, tmp);
  29823. sp_4096_cond_sub_128(r, r, m, (sp_digit)0 - o);
  29824. }
  29825. XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U);
  29826. sp_4096_mont_reduce_128(r, m, mp);
  29827. mask = 0 - (sp_4096_cmp_128(r, m) >= 0);
  29828. sp_4096_cond_sub_128(r, r, m, mask);
  29829. }
  29830. #ifdef WOLFSSL_SP_SMALL_STACK
  29831. if (td != NULL)
  29832. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  29833. #endif
  29834. return err;
  29835. }
  29836. #endif /* HAVE_FFDHE_4096 */
  29837. /* Perform the modular exponentiation for Diffie-Hellman.
  29838. *
  29839. * base Base.
  29840. * exp Array of bytes that is the exponent.
  29841. * expLen Length of data, in bytes, in exponent.
  29842. * mod Modulus.
  29843. * out Buffer to hold big-endian bytes of exponentiation result.
  29844. * Must be at least 512 bytes long.
  29845. * outLen Length, in bytes, of exponentiation result.
  29846. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  29847. * and MEMORY_E if memory allocation fails.
  29848. */
  29849. int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
  29850. const mp_int* mod, byte* out, word32* outLen)
  29851. {
  29852. int err = MP_OKAY;
  29853. sp_digit b[256];
  29854. sp_digit e[128];
  29855. sp_digit m[128];
  29856. sp_digit* r = b;
  29857. word32 i;
  29858. if (mp_count_bits(base) > 4096) {
  29859. err = MP_READ_E;
  29860. }
  29861. else if (expLen > 512) {
  29862. err = MP_READ_E;
  29863. }
  29864. else if (mp_count_bits(mod) != 4096) {
  29865. err = MP_READ_E;
  29866. }
  29867. else if (mp_iseven(mod)) {
  29868. err = MP_VAL;
  29869. }
  29870. if (err == MP_OKAY) {
  29871. sp_4096_from_mp(b, 128, base);
  29872. sp_4096_from_bin(e, 128, exp, expLen);
  29873. sp_4096_from_mp(m, 128, mod);
  29874. #ifdef HAVE_FFDHE_4096
  29875. if (base->used == 1 && base->dp[0] == 2 && m[127] == (sp_digit)-1)
  29876. err = sp_4096_mod_exp_2_128(r, e, expLen * 8, m);
  29877. else
  29878. #endif
  29879. err = sp_4096_mod_exp_128(r, b, e, expLen * 8, m, 0);
  29880. }
  29881. if (err == MP_OKAY) {
  29882. sp_4096_to_bin_128(r, out);
  29883. *outLen = 512;
  29884. for (i=0; i<512 && out[i] == 0; i++) {
  29885. /* Search for first non-zero. */
  29886. }
  29887. *outLen -= i;
  29888. XMEMMOVE(out, out + i, *outLen);
  29889. }
  29890. XMEMSET(e, 0, sizeof(e));
  29891. return err;
  29892. }
  29893. #endif /* WOLFSSL_HAVE_SP_DH */
  29894. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  29895. #endif /* WOLFSSL_SP_4096 */
  29896. #endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
  29897. #ifdef WOLFSSL_HAVE_SP_ECC
  29898. #ifndef WOLFSSL_SP_NO_256
  29899. /* Point structure to use. */
  29900. typedef struct sp_point_256 {
  29901. /* X ordinate of point. */
  29902. sp_digit x[2 * 8];
  29903. /* Y ordinate of point. */
  29904. sp_digit y[2 * 8];
  29905. /* Z ordinate of point. */
  29906. sp_digit z[2 * 8];
  29907. /* Indicates point is at infinity. */
  29908. int infinity;
  29909. } sp_point_256;
  29910. /* The modulus (prime) of the curve P256. */
  29911. static const sp_digit p256_mod[8] = {
  29912. 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000,
  29913. 0x00000001,0xffffffff
  29914. };
  29915. /* The Montgomery normalizer for modulus of the curve P256. */
  29916. static const sp_digit p256_norm_mod[8] = {
  29917. 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff,
  29918. 0xfffffffe,0x00000000
  29919. };
  29920. /* The Montgomery multiplier for modulus of the curve P256. */
  29921. static const sp_digit p256_mp_mod = 0x00000001;
  29922. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  29923. defined(HAVE_ECC_VERIFY)
  29924. /* The order of the curve P256. */
  29925. static const sp_digit p256_order[8] = {
  29926. 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
  29927. 0x00000000,0xffffffff
  29928. };
  29929. #endif
  29930. /* The order of the curve P256 minus 2. */
  29931. static const sp_digit p256_order2[8] = {
  29932. 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
  29933. 0x00000000,0xffffffff
  29934. };
  29935. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  29936. /* The Montgomery normalizer for order of the curve P256. */
  29937. static const sp_digit p256_norm_order[8] = {
  29938. 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000,
  29939. 0xffffffff,0x00000000
  29940. };
  29941. #endif
  29942. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  29943. /* The Montgomery multiplier for order of the curve P256. */
  29944. static const sp_digit p256_mp_order = 0xee00bc4f;
  29945. #endif
  29946. /* The base point of curve P256. */
  29947. static const sp_point_256 p256_base = {
  29948. /* X ordinate */
  29949. {
  29950. 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5,
  29951. 0xe12c4247,0x6b17d1f2,
  29952. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  29953. (sp_digit)0, (sp_digit)0, (sp_digit)0
  29954. },
  29955. /* Y ordinate */
  29956. {
  29957. 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a,
  29958. 0xfe1a7f9b,0x4fe342e2,
  29959. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  29960. (sp_digit)0, (sp_digit)0, (sp_digit)0
  29961. },
  29962. /* Z ordinate */
  29963. {
  29964. 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  29965. 0x00000000,0x00000000,
  29966. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  29967. (sp_digit)0, (sp_digit)0, (sp_digit)0
  29968. },
  29969. /* infinity */
  29970. 0
  29971. };
  29972. #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
  29973. static const sp_digit p256_b[8] = {
  29974. 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55,
  29975. 0xaa3a93e7,0x5ac635d8
  29976. };
  29977. #endif
  29978. #ifdef WOLFSSL_SP_SMALL
  29979. /* Multiply a and b into r. (r = a * b)
  29980. *
  29981. * r A single precision integer.
  29982. * a A single precision integer.
  29983. * b A single precision integer.
  29984. */
  29985. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  29986. static void sp_256_mul_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  29987. #else
  29988. static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  29989. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  29990. {
  29991. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  29992. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  29993. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  29994. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  29995. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  29996. __asm__ __volatile__ (
  29997. "SUB sp, sp, #0x40\n\t"
  29998. "LDR lr, [%[a]]\n\t"
  29999. "LDR r11, [%[b]]\n\t"
  30000. "UMULL r8, r6, lr, r11\n\t"
  30001. "STR r8, [sp]\n\t"
  30002. "MOV r7, #0x0\n\t"
  30003. "MOV r8, #0x0\n\t"
  30004. "MOV r5, #0x4\n\t"
  30005. "\n"
  30006. "L_sp_256_mul_8_outer:\n\t"
  30007. "SUBS r3, r5, #0x1c\n\t"
  30008. "IT cc\n\t"
  30009. "MOVCC r3, #0x0\n\t"
  30010. "SUB r4, r5, r3\n\t"
  30011. "\n"
  30012. "L_sp_256_mul_8_inner:\n\t"
  30013. "LDR lr, [%[a], r3]\n\t"
  30014. "LDR r11, [%[b], r4]\n\t"
  30015. "UMULL r9, r10, lr, r11\n\t"
  30016. "ADDS r6, r6, r9\n\t"
  30017. "ADCS r7, r7, r10\n\t"
  30018. "ADC r8, r8, #0x0\n\t"
  30019. "LDR lr, [%[a], r4]\n\t"
  30020. "LDR r11, [%[b], r3]\n\t"
  30021. "UMULL r9, r10, lr, r11\n\t"
  30022. "ADDS r6, r6, r9\n\t"
  30023. "ADCS r7, r7, r10\n\t"
  30024. "ADC r8, r8, #0x0\n\t"
  30025. "ADD r3, r3, #0x4\n\t"
  30026. "SUB r4, r4, #0x4\n\t"
  30027. "CMP r3, r4\n\t"
  30028. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30029. "BGT L_sp_256_mul_8_inner_done\n\t"
  30030. #else
  30031. "BGT.N L_sp_256_mul_8_inner_done\n\t"
  30032. #endif
  30033. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30034. "BLT L_sp_256_mul_8_inner\n\t"
  30035. #else
  30036. "BLT.N L_sp_256_mul_8_inner\n\t"
  30037. #endif
  30038. "LDR lr, [%[a], r3]\n\t"
  30039. "LDR r11, [%[b], r3]\n\t"
  30040. "UMULL r9, r10, lr, r11\n\t"
  30041. "ADDS r6, r6, r9\n\t"
  30042. "ADCS r7, r7, r10\n\t"
  30043. "ADC r8, r8, #0x0\n\t"
  30044. "\n"
  30045. "L_sp_256_mul_8_inner_done:\n\t"
  30046. "STR r6, [sp, r5]\n\t"
  30047. "MOV r6, r7\n\t"
  30048. "MOV r7, r8\n\t"
  30049. "MOV r8, #0x0\n\t"
  30050. "ADD r5, r5, #0x4\n\t"
  30051. "CMP r5, #0x34\n\t"
  30052. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30053. "BLE L_sp_256_mul_8_outer\n\t"
  30054. #else
  30055. "BLE.N L_sp_256_mul_8_outer\n\t"
  30056. #endif
  30057. "LDR lr, [%[a], #28]\n\t"
  30058. "LDR r11, [%[b], #28]\n\t"
  30059. "UMLAL r6, r7, lr, r11\n\t"
  30060. "STR r6, [sp, r5]\n\t"
  30061. "ADD r5, r5, #0x4\n\t"
  30062. "STR r7, [sp, r5]\n\t"
  30063. "\n"
  30064. "L_sp_256_mul_8_store:\n\t"
  30065. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  30066. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  30067. "SUBS r5, r5, #0x20\n\t"
  30068. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30069. "BGT L_sp_256_mul_8_store\n\t"
  30070. #else
  30071. "BGT.N L_sp_256_mul_8_store\n\t"
  30072. #endif
  30073. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  30074. :
  30075. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  30076. );
  30077. }
  30078. #else
  30079. #ifdef WOLFSSL_SP_NO_UMAAL
  30080. /* Multiply a and b into r. (r = a * b)
  30081. *
  30082. * r A single precision integer.
  30083. * a A single precision integer.
  30084. * b A single precision integer.
  30085. */
  30086. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30087. SP_NOINLINE static void sp_256_mul_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  30088. #else
  30089. SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  30090. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30091. {
  30092. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30093. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  30094. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  30095. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  30096. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30097. __asm__ __volatile__ (
  30098. "SUB sp, sp, #0x24\n\t"
  30099. "STR %[r], [sp, #32]\n\t"
  30100. "MOV %[r], #0x0\n\t"
  30101. "LDR r12, [%[a]]\n\t"
  30102. /* A[0] * B[0] */
  30103. "LDR lr, [%[b]]\n\t"
  30104. "UMULL r3, r4, r12, lr\n\t"
  30105. /* A[0] * B[2] */
  30106. "LDR lr, [%[b], #8]\n\t"
  30107. "UMULL r5, r6, r12, lr\n\t"
  30108. /* A[0] * B[4] */
  30109. "LDR lr, [%[b], #16]\n\t"
  30110. "UMULL r7, r8, r12, lr\n\t"
  30111. /* A[0] * B[6] */
  30112. "LDR lr, [%[b], #24]\n\t"
  30113. "UMULL r9, r10, r12, lr\n\t"
  30114. "STR r3, [sp]\n\t"
  30115. /* A[0] * B[1] */
  30116. "LDR lr, [%[b], #4]\n\t"
  30117. "MOV r11, %[r]\n\t"
  30118. "UMLAL r4, r11, r12, lr\n\t"
  30119. "ADDS r5, r5, r11\n\t"
  30120. /* A[0] * B[3] */
  30121. "LDR lr, [%[b], #12]\n\t"
  30122. "ADCS r6, r6, #0x0\n\t"
  30123. "ADC r11, %[r], #0x0\n\t"
  30124. "UMLAL r6, r11, r12, lr\n\t"
  30125. "ADDS r7, r7, r11\n\t"
  30126. /* A[0] * B[5] */
  30127. "LDR lr, [%[b], #20]\n\t"
  30128. "ADCS r8, r8, #0x0\n\t"
  30129. "ADC r11, %[r], #0x0\n\t"
  30130. "UMLAL r8, r11, r12, lr\n\t"
  30131. "ADDS r9, r9, r11\n\t"
  30132. /* A[0] * B[7] */
  30133. "LDR lr, [%[b], #28]\n\t"
  30134. "ADCS r10, r10, #0x0\n\t"
  30135. "ADC r3, %[r], #0x0\n\t"
  30136. "UMLAL r10, r3, r12, lr\n\t"
  30137. /* A[1] * B[0] */
  30138. "LDR r12, [%[a], #4]\n\t"
  30139. "LDR lr, [%[b]]\n\t"
  30140. "MOV r11, #0x0\n\t"
  30141. "UMLAL r4, r11, r12, lr\n\t"
  30142. "STR r4, [sp, #4]\n\t"
  30143. "ADDS r5, r5, r11\n\t"
  30144. /* A[1] * B[1] */
  30145. "LDR lr, [%[b], #4]\n\t"
  30146. "ADC r11, %[r], #0x0\n\t"
  30147. "UMLAL r5, r11, r12, lr\n\t"
  30148. "ADDS r6, r6, r11\n\t"
  30149. /* A[1] * B[2] */
  30150. "LDR lr, [%[b], #8]\n\t"
  30151. "ADC r11, %[r], #0x0\n\t"
  30152. "UMLAL r6, r11, r12, lr\n\t"
  30153. "ADDS r7, r7, r11\n\t"
  30154. /* A[1] * B[3] */
  30155. "LDR lr, [%[b], #12]\n\t"
  30156. "ADC r11, %[r], #0x0\n\t"
  30157. "UMLAL r7, r11, r12, lr\n\t"
  30158. "ADDS r8, r8, r11\n\t"
  30159. /* A[1] * B[4] */
  30160. "LDR lr, [%[b], #16]\n\t"
  30161. "ADC r11, %[r], #0x0\n\t"
  30162. "UMLAL r8, r11, r12, lr\n\t"
  30163. "ADDS r9, r9, r11\n\t"
  30164. /* A[1] * B[5] */
  30165. "LDR lr, [%[b], #20]\n\t"
  30166. "ADC r11, %[r], #0x0\n\t"
  30167. "UMLAL r9, r11, r12, lr\n\t"
  30168. "ADDS r10, r10, r11\n\t"
  30169. /* A[1] * B[6] */
  30170. "LDR lr, [%[b], #24]\n\t"
  30171. "ADC r11, %[r], #0x0\n\t"
  30172. "UMLAL r10, r11, r12, lr\n\t"
  30173. "ADDS r3, r3, r11\n\t"
  30174. /* A[1] * B[7] */
  30175. "LDR lr, [%[b], #28]\n\t"
  30176. "ADC r4, %[r], #0x0\n\t"
  30177. "UMLAL r3, r4, r12, lr\n\t"
  30178. /* A[2] * B[0] */
  30179. "LDR r12, [%[a], #8]\n\t"
  30180. "LDR lr, [%[b]]\n\t"
  30181. "MOV r11, #0x0\n\t"
  30182. "UMLAL r5, r11, r12, lr\n\t"
  30183. "STR r5, [sp, #8]\n\t"
  30184. "ADDS r6, r6, r11\n\t"
  30185. /* A[2] * B[1] */
  30186. "LDR lr, [%[b], #4]\n\t"
  30187. "ADC r11, %[r], #0x0\n\t"
  30188. "UMLAL r6, r11, r12, lr\n\t"
  30189. "ADDS r7, r7, r11\n\t"
  30190. /* A[2] * B[2] */
  30191. "LDR lr, [%[b], #8]\n\t"
  30192. "ADC r11, %[r], #0x0\n\t"
  30193. "UMLAL r7, r11, r12, lr\n\t"
  30194. "ADDS r8, r8, r11\n\t"
  30195. /* A[2] * B[3] */
  30196. "LDR lr, [%[b], #12]\n\t"
  30197. "ADC r11, %[r], #0x0\n\t"
  30198. "UMLAL r8, r11, r12, lr\n\t"
  30199. "ADDS r9, r9, r11\n\t"
  30200. /* A[2] * B[4] */
  30201. "LDR lr, [%[b], #16]\n\t"
  30202. "ADC r11, %[r], #0x0\n\t"
  30203. "UMLAL r9, r11, r12, lr\n\t"
  30204. "ADDS r10, r10, r11\n\t"
  30205. /* A[2] * B[5] */
  30206. "LDR lr, [%[b], #20]\n\t"
  30207. "ADC r11, %[r], #0x0\n\t"
  30208. "UMLAL r10, r11, r12, lr\n\t"
  30209. "ADDS r3, r3, r11\n\t"
  30210. /* A[2] * B[6] */
  30211. "LDR lr, [%[b], #24]\n\t"
  30212. "ADC r11, %[r], #0x0\n\t"
  30213. "UMLAL r3, r11, r12, lr\n\t"
  30214. "ADDS r4, r4, r11\n\t"
  30215. /* A[2] * B[7] */
  30216. "LDR lr, [%[b], #28]\n\t"
  30217. "ADC r5, %[r], #0x0\n\t"
  30218. "UMLAL r4, r5, r12, lr\n\t"
  30219. /* A[3] * B[0] */
  30220. "LDR r12, [%[a], #12]\n\t"
  30221. "LDR lr, [%[b]]\n\t"
  30222. "MOV r11, #0x0\n\t"
  30223. "UMLAL r6, r11, r12, lr\n\t"
  30224. "STR r6, [sp, #12]\n\t"
  30225. "ADDS r7, r7, r11\n\t"
  30226. /* A[3] * B[1] */
  30227. "LDR lr, [%[b], #4]\n\t"
  30228. "ADC r11, %[r], #0x0\n\t"
  30229. "UMLAL r7, r11, r12, lr\n\t"
  30230. "ADDS r8, r8, r11\n\t"
  30231. /* A[3] * B[2] */
  30232. "LDR lr, [%[b], #8]\n\t"
  30233. "ADC r11, %[r], #0x0\n\t"
  30234. "UMLAL r8, r11, r12, lr\n\t"
  30235. "ADDS r9, r9, r11\n\t"
  30236. /* A[3] * B[3] */
  30237. "LDR lr, [%[b], #12]\n\t"
  30238. "ADC r11, %[r], #0x0\n\t"
  30239. "UMLAL r9, r11, r12, lr\n\t"
  30240. "ADDS r10, r10, r11\n\t"
  30241. /* A[3] * B[4] */
  30242. "LDR lr, [%[b], #16]\n\t"
  30243. "ADC r11, %[r], #0x0\n\t"
  30244. "UMLAL r10, r11, r12, lr\n\t"
  30245. "ADDS r3, r3, r11\n\t"
  30246. /* A[3] * B[5] */
  30247. "LDR lr, [%[b], #20]\n\t"
  30248. "ADC r11, %[r], #0x0\n\t"
  30249. "UMLAL r3, r11, r12, lr\n\t"
  30250. "ADDS r4, r4, r11\n\t"
  30251. /* A[3] * B[6] */
  30252. "LDR lr, [%[b], #24]\n\t"
  30253. "ADC r11, %[r], #0x0\n\t"
  30254. "UMLAL r4, r11, r12, lr\n\t"
  30255. "ADDS r5, r5, r11\n\t"
  30256. /* A[3] * B[7] */
  30257. "LDR lr, [%[b], #28]\n\t"
  30258. "ADC r6, %[r], #0x0\n\t"
  30259. "UMLAL r5, r6, r12, lr\n\t"
  30260. /* A[4] * B[0] */
  30261. "LDR r12, [%[a], #16]\n\t"
  30262. "LDR lr, [%[b]]\n\t"
  30263. "MOV r11, #0x0\n\t"
  30264. "UMLAL r7, r11, r12, lr\n\t"
  30265. "STR r7, [sp, #16]\n\t"
  30266. "ADDS r8, r8, r11\n\t"
  30267. /* A[4] * B[1] */
  30268. "LDR lr, [%[b], #4]\n\t"
  30269. "ADC r11, %[r], #0x0\n\t"
  30270. "UMLAL r8, r11, r12, lr\n\t"
  30271. "ADDS r9, r9, r11\n\t"
  30272. /* A[4] * B[2] */
  30273. "LDR lr, [%[b], #8]\n\t"
  30274. "ADC r11, %[r], #0x0\n\t"
  30275. "UMLAL r9, r11, r12, lr\n\t"
  30276. "ADDS r10, r10, r11\n\t"
  30277. /* A[4] * B[3] */
  30278. "LDR lr, [%[b], #12]\n\t"
  30279. "ADC r11, %[r], #0x0\n\t"
  30280. "UMLAL r10, r11, r12, lr\n\t"
  30281. "ADDS r3, r3, r11\n\t"
  30282. /* A[4] * B[4] */
  30283. "LDR lr, [%[b], #16]\n\t"
  30284. "ADC r11, %[r], #0x0\n\t"
  30285. "UMLAL r3, r11, r12, lr\n\t"
  30286. "ADDS r4, r4, r11\n\t"
  30287. /* A[4] * B[5] */
  30288. "LDR lr, [%[b], #20]\n\t"
  30289. "ADC r11, %[r], #0x0\n\t"
  30290. "UMLAL r4, r11, r12, lr\n\t"
  30291. "ADDS r5, r5, r11\n\t"
  30292. /* A[4] * B[6] */
  30293. "LDR lr, [%[b], #24]\n\t"
  30294. "ADC r11, %[r], #0x0\n\t"
  30295. "UMLAL r5, r11, r12, lr\n\t"
  30296. "ADDS r6, r6, r11\n\t"
  30297. /* A[4] * B[7] */
  30298. "LDR lr, [%[b], #28]\n\t"
  30299. "ADC r7, %[r], #0x0\n\t"
  30300. "UMLAL r6, r7, r12, lr\n\t"
  30301. /* A[5] * B[0] */
  30302. "LDR r12, [%[a], #20]\n\t"
  30303. "LDR lr, [%[b]]\n\t"
  30304. "MOV r11, #0x0\n\t"
  30305. "UMLAL r8, r11, r12, lr\n\t"
  30306. "STR r8, [sp, #20]\n\t"
  30307. "ADDS r9, r9, r11\n\t"
  30308. /* A[5] * B[1] */
  30309. "LDR lr, [%[b], #4]\n\t"
  30310. "ADC r11, %[r], #0x0\n\t"
  30311. "UMLAL r9, r11, r12, lr\n\t"
  30312. "ADDS r10, r10, r11\n\t"
  30313. /* A[5] * B[2] */
  30314. "LDR lr, [%[b], #8]\n\t"
  30315. "ADC r11, %[r], #0x0\n\t"
  30316. "UMLAL r10, r11, r12, lr\n\t"
  30317. "ADDS r3, r3, r11\n\t"
  30318. /* A[5] * B[3] */
  30319. "LDR lr, [%[b], #12]\n\t"
  30320. "ADC r11, %[r], #0x0\n\t"
  30321. "UMLAL r3, r11, r12, lr\n\t"
  30322. "ADDS r4, r4, r11\n\t"
  30323. /* A[5] * B[4] */
  30324. "LDR lr, [%[b], #16]\n\t"
  30325. "ADC r11, %[r], #0x0\n\t"
  30326. "UMLAL r4, r11, r12, lr\n\t"
  30327. "ADDS r5, r5, r11\n\t"
  30328. /* A[5] * B[5] */
  30329. "LDR lr, [%[b], #20]\n\t"
  30330. "ADC r11, %[r], #0x0\n\t"
  30331. "UMLAL r5, r11, r12, lr\n\t"
  30332. "ADDS r6, r6, r11\n\t"
  30333. /* A[5] * B[6] */
  30334. "LDR lr, [%[b], #24]\n\t"
  30335. "ADC r11, %[r], #0x0\n\t"
  30336. "UMLAL r6, r11, r12, lr\n\t"
  30337. "ADDS r7, r7, r11\n\t"
  30338. /* A[5] * B[7] */
  30339. "LDR lr, [%[b], #28]\n\t"
  30340. "ADC r8, %[r], #0x0\n\t"
  30341. "UMLAL r7, r8, r12, lr\n\t"
  30342. /* A[6] * B[0] */
  30343. "LDR r12, [%[a], #24]\n\t"
  30344. "LDR lr, [%[b]]\n\t"
  30345. "MOV r11, #0x0\n\t"
  30346. "UMLAL r9, r11, r12, lr\n\t"
  30347. "STR r9, [sp, #24]\n\t"
  30348. "ADDS r10, r10, r11\n\t"
  30349. /* A[6] * B[1] */
  30350. "LDR lr, [%[b], #4]\n\t"
  30351. "ADC r11, %[r], #0x0\n\t"
  30352. "UMLAL r10, r11, r12, lr\n\t"
  30353. "ADDS r3, r3, r11\n\t"
  30354. /* A[6] * B[2] */
  30355. "LDR lr, [%[b], #8]\n\t"
  30356. "ADC r11, %[r], #0x0\n\t"
  30357. "UMLAL r3, r11, r12, lr\n\t"
  30358. "ADDS r4, r4, r11\n\t"
  30359. /* A[6] * B[3] */
  30360. "LDR lr, [%[b], #12]\n\t"
  30361. "ADC r11, %[r], #0x0\n\t"
  30362. "UMLAL r4, r11, r12, lr\n\t"
  30363. "ADDS r5, r5, r11\n\t"
  30364. /* A[6] * B[4] */
  30365. "LDR lr, [%[b], #16]\n\t"
  30366. "ADC r11, %[r], #0x0\n\t"
  30367. "UMLAL r5, r11, r12, lr\n\t"
  30368. "ADDS r6, r6, r11\n\t"
  30369. /* A[6] * B[5] */
  30370. "LDR lr, [%[b], #20]\n\t"
  30371. "ADC r11, %[r], #0x0\n\t"
  30372. "UMLAL r6, r11, r12, lr\n\t"
  30373. "ADDS r7, r7, r11\n\t"
  30374. /* A[6] * B[6] */
  30375. "LDR lr, [%[b], #24]\n\t"
  30376. "ADC r11, %[r], #0x0\n\t"
  30377. "UMLAL r7, r11, r12, lr\n\t"
  30378. "ADDS r8, r8, r11\n\t"
  30379. /* A[6] * B[7] */
  30380. "LDR lr, [%[b], #28]\n\t"
  30381. "ADC r9, %[r], #0x0\n\t"
  30382. "UMLAL r8, r9, r12, lr\n\t"
  30383. /* A[7] * B[0] */
  30384. "LDR r12, [%[a], #28]\n\t"
  30385. "LDR lr, [%[b]]\n\t"
  30386. "MOV r11, #0x0\n\t"
  30387. "UMLAL r10, r11, r12, lr\n\t"
  30388. "STR r10, [sp, #28]\n\t"
  30389. "ADDS r3, r3, r11\n\t"
  30390. /* A[7] * B[1] */
  30391. "LDR lr, [%[b], #4]\n\t"
  30392. "ADC r11, %[r], #0x0\n\t"
  30393. "UMLAL r3, r11, r12, lr\n\t"
  30394. "ADDS r4, r4, r11\n\t"
  30395. /* A[7] * B[2] */
  30396. "LDR lr, [%[b], #8]\n\t"
  30397. "ADC r11, %[r], #0x0\n\t"
  30398. "UMLAL r4, r11, r12, lr\n\t"
  30399. "ADDS r5, r5, r11\n\t"
  30400. /* A[7] * B[3] */
  30401. "LDR lr, [%[b], #12]\n\t"
  30402. "ADC r11, %[r], #0x0\n\t"
  30403. "UMLAL r5, r11, r12, lr\n\t"
  30404. "ADDS r6, r6, r11\n\t"
  30405. /* A[7] * B[4] */
  30406. "LDR lr, [%[b], #16]\n\t"
  30407. "ADC r11, %[r], #0x0\n\t"
  30408. "UMLAL r6, r11, r12, lr\n\t"
  30409. "ADDS r7, r7, r11\n\t"
  30410. /* A[7] * B[5] */
  30411. "LDR lr, [%[b], #20]\n\t"
  30412. "ADC r11, %[r], #0x0\n\t"
  30413. "UMLAL r7, r11, r12, lr\n\t"
  30414. "ADDS r8, r8, r11\n\t"
  30415. /* A[7] * B[6] */
  30416. "LDR lr, [%[b], #24]\n\t"
  30417. "ADC r11, %[r], #0x0\n\t"
  30418. "UMLAL r8, r11, r12, lr\n\t"
  30419. "ADDS r9, r9, r11\n\t"
  30420. /* A[7] * B[7] */
  30421. "LDR lr, [%[b], #28]\n\t"
  30422. "ADC r10, %[r], #0x0\n\t"
  30423. "UMLAL r9, r10, r12, lr\n\t"
  30424. "LDR %[r], [sp, #32]\n\t"
  30425. "ADD %[r], %[r], #0x20\n\t"
  30426. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30427. "LDM sp, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30428. "SUB %[r], %[r], #0x20\n\t"
  30429. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30430. "ADD sp, sp, #0x24\n\t"
  30431. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  30432. :
  30433. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  30434. );
  30435. }
  30436. #else
  30437. /* Multiply a and b into r. (r = a * b)
  30438. *
  30439. * r A single precision integer.
  30440. * a A single precision integer.
  30441. * b A single precision integer.
  30442. */
  30443. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30444. SP_NOINLINE static void sp_256_mul_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  30445. #else
  30446. SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  30447. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30448. {
  30449. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30450. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  30451. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  30452. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  30453. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30454. __asm__ __volatile__ (
  30455. "SUB sp, sp, #0x2c\n\t"
  30456. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30457. "STRD %[r], %[a], [sp, #36]\n\t"
  30458. #else
  30459. "STR %[r], [sp, #36]\n\t"
  30460. "STR %[a], [sp, #40]\n\t"
  30461. #endif /* WOLFSSL_NO_VAR_ASSIGN_REG */
  30462. "MOV lr, %[b]\n\t"
  30463. "LDM %[a], {r0, r1, r2, r3}\n\t"
  30464. "LDM lr!, {r4, r5, r6}\n\t"
  30465. "UMULL r10, r11, r0, r4\n\t"
  30466. "UMULL r12, r7, r1, r4\n\t"
  30467. "UMAAL r11, r12, r0, r5\n\t"
  30468. "UMULL r8, r9, r2, r4\n\t"
  30469. "UMAAL r12, r8, r1, r5\n\t"
  30470. "UMAAL r12, r7, r0, r6\n\t"
  30471. "UMAAL r8, r9, r3, r4\n\t"
  30472. "STM sp, {r10, r11, r12}\n\t"
  30473. "UMAAL r7, r8, r2, r5\n\t"
  30474. "LDM lr!, {r4}\n\t"
  30475. "UMULL r10, r11, r1, r6\n\t"
  30476. "UMAAL r8, r9, r2, r6\n\t"
  30477. "UMAAL r7, r10, r0, r4\n\t"
  30478. "UMAAL r8, r11, r3, r5\n\t"
  30479. "STR r7, [sp, #12]\n\t"
  30480. "UMAAL r8, r10, r1, r4\n\t"
  30481. "UMAAL r9, r11, r3, r6\n\t"
  30482. "UMAAL r9, r10, r2, r4\n\t"
  30483. "UMAAL r10, r11, r3, r4\n\t"
  30484. "LDM lr, {r4, r5, r6, r7}\n\t"
  30485. "MOV r12, #0x0\n\t"
  30486. "UMLAL r8, r12, r0, r4\n\t"
  30487. "UMAAL r9, r12, r1, r4\n\t"
  30488. "UMAAL r10, r12, r2, r4\n\t"
  30489. "UMAAL r11, r12, r3, r4\n\t"
  30490. "MOV r4, #0x0\n\t"
  30491. "UMLAL r9, r4, r0, r5\n\t"
  30492. "UMAAL r10, r4, r1, r5\n\t"
  30493. "UMAAL r11, r4, r2, r5\n\t"
  30494. "UMAAL r12, r4, r3, r5\n\t"
  30495. "MOV r5, #0x0\n\t"
  30496. "UMLAL r10, r5, r0, r6\n\t"
  30497. "UMAAL r11, r5, r1, r6\n\t"
  30498. "UMAAL r12, r5, r2, r6\n\t"
  30499. "UMAAL r4, r5, r3, r6\n\t"
  30500. "MOV r6, #0x0\n\t"
  30501. "UMLAL r11, r6, r0, r7\n\t"
  30502. "LDR r0, [sp, #40]\n\t"
  30503. "UMAAL r12, r6, r1, r7\n\t"
  30504. "ADD r0, r0, #0x10\n\t"
  30505. "UMAAL r4, r6, r2, r7\n\t"
  30506. "SUB lr, lr, #0x10\n\t"
  30507. "UMAAL r5, r6, r3, r7\n\t"
  30508. "LDM r0, {r0, r1, r2, r3}\n\t"
  30509. "STR r6, [sp, #32]\n\t"
  30510. "LDM lr!, {r6}\n\t"
  30511. "MOV r7, #0x0\n\t"
  30512. "UMLAL r8, r7, r0, r6\n\t"
  30513. "UMAAL r9, r7, r1, r6\n\t"
  30514. "STR r8, [sp, #16]\n\t"
  30515. "UMAAL r10, r7, r2, r6\n\t"
  30516. "UMAAL r11, r7, r3, r6\n\t"
  30517. "LDM lr!, {r6}\n\t"
  30518. "MOV r8, #0x0\n\t"
  30519. "UMLAL r9, r8, r0, r6\n\t"
  30520. "UMAAL r10, r8, r1, r6\n\t"
  30521. "STR r9, [sp, #20]\n\t"
  30522. "UMAAL r11, r8, r2, r6\n\t"
  30523. "UMAAL r12, r8, r3, r6\n\t"
  30524. "LDM lr!, {r6}\n\t"
  30525. "MOV r9, #0x0\n\t"
  30526. "UMLAL r10, r9, r0, r6\n\t"
  30527. "UMAAL r11, r9, r1, r6\n\t"
  30528. "STR r10, [sp, #24]\n\t"
  30529. "UMAAL r12, r9, r2, r6\n\t"
  30530. "UMAAL r4, r9, r3, r6\n\t"
  30531. "LDM lr!, {r6}\n\t"
  30532. "MOV r10, #0x0\n\t"
  30533. "UMLAL r11, r10, r0, r6\n\t"
  30534. "UMAAL r12, r10, r1, r6\n\t"
  30535. "STR r11, [sp, #28]\n\t"
  30536. "UMAAL r4, r10, r2, r6\n\t"
  30537. "UMAAL r5, r10, r3, r6\n\t"
  30538. "LDM lr!, {r11}\n\t"
  30539. "UMAAL r12, r7, r0, r11\n\t"
  30540. "UMAAL r4, r7, r1, r11\n\t"
  30541. "LDR r6, [sp, #32]\n\t"
  30542. "UMAAL r5, r7, r2, r11\n\t"
  30543. "UMAAL r6, r7, r3, r11\n\t"
  30544. "LDM lr!, {r11}\n\t"
  30545. "UMAAL r4, r8, r0, r11\n\t"
  30546. "UMAAL r5, r8, r1, r11\n\t"
  30547. "UMAAL r6, r8, r2, r11\n\t"
  30548. "UMAAL r7, r8, r3, r11\n\t"
  30549. "LDM lr, {r11, lr}\n\t"
  30550. "UMAAL r5, r9, r0, r11\n\t"
  30551. "UMAAL r6, r10, r0, lr\n\t"
  30552. "UMAAL r6, r9, r1, r11\n\t"
  30553. "UMAAL r7, r10, r1, lr\n\t"
  30554. "UMAAL r7, r9, r2, r11\n\t"
  30555. "UMAAL r8, r10, r2, lr\n\t"
  30556. "UMAAL r8, r9, r3, r11\n\t"
  30557. "UMAAL r9, r10, r3, lr\n\t"
  30558. "MOV r3, r12\n\t"
  30559. "LDR lr, [sp, #36]\n\t"
  30560. "ADD lr, lr, #0x20\n\t"
  30561. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30562. "SUB lr, lr, #0x20\n\t"
  30563. "LDM sp, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30564. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30565. "ADD sp, sp, #0x2c\n\t"
  30566. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  30567. :
  30568. : "memory", "r3", "r4", "r5", "r6", "r10", "r11", "r12", "r7", "r8", "r9", "lr", "cc"
  30569. );
  30570. }
  30571. #endif /* WOLFSSL_SP_NO_UMAAL */
  30572. #endif /* WOLFSSL_SP_SMALL */
  30573. #ifdef WOLFSSL_SP_SMALL
  30574. /* Square a and put result in r. (r = a * a)
  30575. *
  30576. * r A single precision integer.
  30577. * a A single precision integer.
  30578. */
  30579. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30580. static void sp_256_sqr_8(sp_digit* r_p, const sp_digit* a_p)
  30581. #else
  30582. static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
  30583. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30584. {
  30585. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30586. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  30587. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  30588. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30589. __asm__ __volatile__ (
  30590. "SUB sp, sp, #0x40\n\t"
  30591. "LDR lr, [%[a]]\n\t"
  30592. "UMULL r8, r6, lr, lr\n\t"
  30593. "STR r8, [sp]\n\t"
  30594. "MOV r7, #0x0\n\t"
  30595. "MOV r8, #0x0\n\t"
  30596. "MOV r5, #0x4\n\t"
  30597. "\n"
  30598. "L_sp_256_sqr_8_outer:\n\t"
  30599. "SUBS r3, r5, #0x1c\n\t"
  30600. "IT cc\n\t"
  30601. "MOVCC r3, #0x0\n\t"
  30602. "SUB r4, r5, r3\n\t"
  30603. "\n"
  30604. "L_sp_256_sqr_8_inner:\n\t"
  30605. "LDR lr, [%[a], r3]\n\t"
  30606. "LDR r11, [%[a], r4]\n\t"
  30607. "UMULL r9, r10, lr, r11\n\t"
  30608. "ADDS r6, r6, r9\n\t"
  30609. "ADCS r7, r7, r10\n\t"
  30610. "ADC r8, r8, #0x0\n\t"
  30611. "ADDS r6, r6, r9\n\t"
  30612. "ADCS r7, r7, r10\n\t"
  30613. "ADC r8, r8, #0x0\n\t"
  30614. "ADD r3, r3, #0x4\n\t"
  30615. "SUB r4, r4, #0x4\n\t"
  30616. "CMP r3, r4\n\t"
  30617. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30618. "BGT L_sp_256_sqr_8_inner_done\n\t"
  30619. #else
  30620. "BGT.N L_sp_256_sqr_8_inner_done\n\t"
  30621. #endif
  30622. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30623. "BLT L_sp_256_sqr_8_inner\n\t"
  30624. #else
  30625. "BLT.N L_sp_256_sqr_8_inner\n\t"
  30626. #endif
  30627. "LDR lr, [%[a], r3]\n\t"
  30628. "UMULL r9, r10, lr, lr\n\t"
  30629. "ADDS r6, r6, r9\n\t"
  30630. "ADCS r7, r7, r10\n\t"
  30631. "ADC r8, r8, #0x0\n\t"
  30632. "\n"
  30633. "L_sp_256_sqr_8_inner_done:\n\t"
  30634. "STR r6, [sp, r5]\n\t"
  30635. "MOV r6, r7\n\t"
  30636. "MOV r7, r8\n\t"
  30637. "MOV r8, #0x0\n\t"
  30638. "ADD r5, r5, #0x4\n\t"
  30639. "CMP r5, #0x34\n\t"
  30640. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30641. "BLE L_sp_256_sqr_8_outer\n\t"
  30642. #else
  30643. "BLE.N L_sp_256_sqr_8_outer\n\t"
  30644. #endif
  30645. "LDR lr, [%[a], #28]\n\t"
  30646. "UMLAL r6, r7, lr, lr\n\t"
  30647. "STR r6, [sp, r5]\n\t"
  30648. "ADD r5, r5, #0x4\n\t"
  30649. "STR r7, [sp, r5]\n\t"
  30650. "\n"
  30651. "L_sp_256_sqr_8_store:\n\t"
  30652. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  30653. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  30654. "SUBS r5, r5, #0x20\n\t"
  30655. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  30656. "BGT L_sp_256_sqr_8_store\n\t"
  30657. #else
  30658. "BGT.N L_sp_256_sqr_8_store\n\t"
  30659. #endif
  30660. : [r] "+r" (r), [a] "+r" (a)
  30661. :
  30662. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  30663. );
  30664. }
  30665. #else
  30666. #ifdef WOLFSSL_SP_NO_UMAAL
  30667. /* Square a and put result in r. (r = a * a)
  30668. *
  30669. * r A single precision integer.
  30670. * a A single precision integer.
  30671. */
  30672. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30673. SP_NOINLINE static void sp_256_sqr_8(sp_digit* r_p, const sp_digit* a_p)
  30674. #else
  30675. SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
  30676. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30677. {
  30678. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30679. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  30680. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  30681. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30682. __asm__ __volatile__ (
  30683. "SUB sp, sp, #0x44\n\t"
  30684. "STR %[r], [sp, #64]\n\t"
  30685. "MOV %[r], #0x0\n\t"
  30686. "LDR r12, [%[a]]\n\t"
  30687. /* A[0] * A[1] */
  30688. "LDR lr, [%[a], #4]\n\t"
  30689. "UMULL r4, r5, r12, lr\n\t"
  30690. /* A[0] * A[3] */
  30691. "LDR lr, [%[a], #12]\n\t"
  30692. "UMULL r6, r7, r12, lr\n\t"
  30693. /* A[0] * A[5] */
  30694. "LDR lr, [%[a], #20]\n\t"
  30695. "UMULL r8, r9, r12, lr\n\t"
  30696. /* A[0] * A[7] */
  30697. "LDR lr, [%[a], #28]\n\t"
  30698. "UMULL r10, r3, r12, lr\n\t"
  30699. /* A[0] * A[2] */
  30700. "LDR lr, [%[a], #8]\n\t"
  30701. "MOV r11, #0x0\n\t"
  30702. "UMLAL r5, r11, r12, lr\n\t"
  30703. "ADDS r6, r6, r11\n\t"
  30704. /* A[0] * A[4] */
  30705. "LDR lr, [%[a], #16]\n\t"
  30706. "ADCS r7, r7, #0x0\n\t"
  30707. "ADC r11, %[r], #0x0\n\t"
  30708. "UMLAL r7, r11, r12, lr\n\t"
  30709. "ADDS r8, r8, r11\n\t"
  30710. /* A[0] * A[6] */
  30711. "LDR lr, [%[a], #24]\n\t"
  30712. "ADCS r9, r9, #0x0\n\t"
  30713. "ADC r11, %[r], #0x0\n\t"
  30714. "UMLAL r9, r11, r12, lr\n\t"
  30715. "ADDS r10, r10, r11\n\t"
  30716. "ADCS r3, r3, #0x0\n\t"
  30717. "STR r4, [sp, #4]\n\t"
  30718. "STR r5, [sp, #8]\n\t"
  30719. /* A[1] * A[2] */
  30720. "LDR r12, [%[a], #4]\n\t"
  30721. "LDR lr, [%[a], #8]\n\t"
  30722. "MOV r11, #0x0\n\t"
  30723. "UMLAL r6, r11, r12, lr\n\t"
  30724. "STR r6, [sp, #12]\n\t"
  30725. "ADDS r7, r7, r11\n\t"
  30726. /* A[1] * A[3] */
  30727. "LDR lr, [%[a], #12]\n\t"
  30728. "ADC r11, %[r], #0x0\n\t"
  30729. "UMLAL r7, r11, r12, lr\n\t"
  30730. "STR r7, [sp, #16]\n\t"
  30731. "ADDS r8, r8, r11\n\t"
  30732. /* A[1] * A[4] */
  30733. "LDR lr, [%[a], #16]\n\t"
  30734. "ADC r11, %[r], #0x0\n\t"
  30735. "UMLAL r8, r11, r12, lr\n\t"
  30736. "ADDS r9, r9, r11\n\t"
  30737. /* A[1] * A[5] */
  30738. "LDR lr, [%[a], #20]\n\t"
  30739. "ADC r11, %[r], #0x0\n\t"
  30740. "UMLAL r9, r11, r12, lr\n\t"
  30741. "ADDS r10, r10, r11\n\t"
  30742. /* A[1] * A[6] */
  30743. "LDR lr, [%[a], #24]\n\t"
  30744. "ADC r11, %[r], #0x0\n\t"
  30745. "UMLAL r10, r11, r12, lr\n\t"
  30746. "ADDS r3, r3, r11\n\t"
  30747. /* A[1] * A[7] */
  30748. "LDR lr, [%[a], #28]\n\t"
  30749. "ADC r4, %[r], #0x0\n\t"
  30750. "UMLAL r3, r4, r12, lr\n\t"
  30751. /* A[2] * A[3] */
  30752. "LDR r12, [%[a], #8]\n\t"
  30753. "LDR lr, [%[a], #12]\n\t"
  30754. "MOV r11, #0x0\n\t"
  30755. "UMLAL r8, r11, r12, lr\n\t"
  30756. "STR r8, [sp, #20]\n\t"
  30757. "ADDS r9, r9, r11\n\t"
  30758. /* A[2] * A[4] */
  30759. "LDR lr, [%[a], #16]\n\t"
  30760. "ADC r11, %[r], #0x0\n\t"
  30761. "UMLAL r9, r11, r12, lr\n\t"
  30762. "STR r9, [sp, #24]\n\t"
  30763. "ADDS r10, r10, r11\n\t"
  30764. /* A[2] * A[5] */
  30765. "LDR lr, [%[a], #20]\n\t"
  30766. "ADC r11, %[r], #0x0\n\t"
  30767. "UMLAL r10, r11, r12, lr\n\t"
  30768. "ADDS r3, r3, r11\n\t"
  30769. /* A[2] * A[6] */
  30770. "LDR lr, [%[a], #24]\n\t"
  30771. "ADC r11, %[r], #0x0\n\t"
  30772. "UMLAL r3, r11, r12, lr\n\t"
  30773. "ADDS r4, r4, r11\n\t"
  30774. /* A[2] * A[7] */
  30775. "LDR lr, [%[a], #28]\n\t"
  30776. "ADC r5, %[r], #0x0\n\t"
  30777. "UMLAL r4, r5, r12, lr\n\t"
  30778. /* A[3] * A[4] */
  30779. "LDR r12, [%[a], #12]\n\t"
  30780. "LDR lr, [%[a], #16]\n\t"
  30781. "MOV r11, #0x0\n\t"
  30782. "UMLAL r10, r11, r12, lr\n\t"
  30783. "STR r10, [sp, #28]\n\t"
  30784. "ADDS r3, r3, r11\n\t"
  30785. /* A[3] * A[5] */
  30786. "LDR lr, [%[a], #20]\n\t"
  30787. "ADC r11, %[r], #0x0\n\t"
  30788. "UMLAL r3, r11, r12, lr\n\t"
  30789. "ADDS r4, r4, r11\n\t"
  30790. /* A[3] * A[6] */
  30791. "LDR lr, [%[a], #24]\n\t"
  30792. "ADC r11, %[r], #0x0\n\t"
  30793. "UMLAL r4, r11, r12, lr\n\t"
  30794. "ADDS r5, r5, r11\n\t"
  30795. /* A[3] * A[7] */
  30796. "LDR lr, [%[a], #28]\n\t"
  30797. "ADC r6, %[r], #0x0\n\t"
  30798. "UMLAL r5, r6, r12, lr\n\t"
  30799. /* A[4] * A[5] */
  30800. "LDR r12, [%[a], #16]\n\t"
  30801. "LDR lr, [%[a], #20]\n\t"
  30802. "MOV r11, #0x0\n\t"
  30803. "UMLAL r4, r11, r12, lr\n\t"
  30804. "ADDS r5, r5, r11\n\t"
  30805. /* A[4] * A[6] */
  30806. "LDR lr, [%[a], #24]\n\t"
  30807. "ADC r11, %[r], #0x0\n\t"
  30808. "UMLAL r5, r11, r12, lr\n\t"
  30809. "ADDS r6, r6, r11\n\t"
  30810. /* A[4] * A[7] */
  30811. "LDR lr, [%[a], #28]\n\t"
  30812. "ADC r7, %[r], #0x0\n\t"
  30813. "UMLAL r6, r7, r12, lr\n\t"
  30814. /* A[5] * A[6] */
  30815. "LDR r12, [%[a], #20]\n\t"
  30816. "LDR lr, [%[a], #24]\n\t"
  30817. "MOV r11, #0x0\n\t"
  30818. "UMLAL r6, r11, r12, lr\n\t"
  30819. "ADDS r7, r7, r11\n\t"
  30820. /* A[5] * A[7] */
  30821. "LDR lr, [%[a], #28]\n\t"
  30822. "ADC r8, %[r], #0x0\n\t"
  30823. "UMLAL r7, r8, r12, lr\n\t"
  30824. /* A[6] * A[7] */
  30825. "LDR r12, [%[a], #24]\n\t"
  30826. "LDR lr, [%[a], #28]\n\t"
  30827. "MOV r9, #0x0\n\t"
  30828. "UMLAL r8, r9, r12, lr\n\t"
  30829. "ADD lr, sp, #0x20\n\t"
  30830. "STM lr, {r3, r4, r5, r6, r7, r8, r9}\n\t"
  30831. "ADD lr, sp, #0x4\n\t"
  30832. "LDM lr, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  30833. "ADDS r4, r4, r4\n\t"
  30834. "ADCS r5, r5, r5\n\t"
  30835. "ADCS r6, r6, r6\n\t"
  30836. "ADCS r7, r7, r7\n\t"
  30837. "ADCS r8, r8, r8\n\t"
  30838. "ADCS r9, r9, r9\n\t"
  30839. "ADCS r10, r10, r10\n\t"
  30840. "STM lr!, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  30841. "LDM lr, {r3, r4, r5, r6, r7, r8, r9}\n\t"
  30842. "ADCS r3, r3, r3\n\t"
  30843. "ADCS r4, r4, r4\n\t"
  30844. "ADCS r5, r5, r5\n\t"
  30845. "ADCS r6, r6, r6\n\t"
  30846. "ADCS r7, r7, r7\n\t"
  30847. "ADCS r8, r8, r8\n\t"
  30848. "ADCS r9, r9, r9\n\t"
  30849. "ADC r10, %[r], #0x0\n\t"
  30850. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30851. "ADD lr, sp, #0x4\n\t"
  30852. "LDM lr, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  30853. "MOV lr, sp\n\t"
  30854. /* A[0] * A[0] */
  30855. "LDR r12, [%[a]]\n\t"
  30856. "UMULL r3, r11, r12, r12\n\t"
  30857. "ADDS r4, r4, r11\n\t"
  30858. /* A[1] * A[1] */
  30859. "LDR r12, [%[a], #4]\n\t"
  30860. "ADCS r5, r5, #0x0\n\t"
  30861. "ADC r11, %[r], #0x0\n\t"
  30862. "UMLAL r5, r11, r12, r12\n\t"
  30863. "ADDS r6, r6, r11\n\t"
  30864. /* A[2] * A[2] */
  30865. "LDR r12, [%[a], #8]\n\t"
  30866. "ADCS r7, r7, #0x0\n\t"
  30867. "ADC r11, %[r], #0x0\n\t"
  30868. "UMLAL r7, r11, r12, r12\n\t"
  30869. "ADDS r8, r8, r11\n\t"
  30870. /* A[3] * A[3] */
  30871. "LDR r12, [%[a], #12]\n\t"
  30872. "ADCS r9, r9, #0x0\n\t"
  30873. "ADC r11, %[r], #0x0\n\t"
  30874. "UMLAL r9, r11, r12, r12\n\t"
  30875. "ADDS r10, r10, r11\n\t"
  30876. "STM lr!, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30877. "LDM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30878. /* A[4] * A[4] */
  30879. "LDR r12, [%[a], #16]\n\t"
  30880. "ADCS r3, r3, #0x0\n\t"
  30881. "ADC r11, %[r], #0x0\n\t"
  30882. "UMLAL r3, r11, r12, r12\n\t"
  30883. "ADDS r4, r4, r11\n\t"
  30884. /* A[5] * A[5] */
  30885. "LDR r12, [%[a], #20]\n\t"
  30886. "ADCS r5, r5, #0x0\n\t"
  30887. "ADC r11, %[r], #0x0\n\t"
  30888. "UMLAL r5, r11, r12, r12\n\t"
  30889. "ADDS r6, r6, r11\n\t"
  30890. /* A[6] * A[6] */
  30891. "LDR r12, [%[a], #24]\n\t"
  30892. "ADCS r7, r7, #0x0\n\t"
  30893. "ADC r11, %[r], #0x0\n\t"
  30894. "UMLAL r7, r11, r12, r12\n\t"
  30895. "ADDS r8, r8, r11\n\t"
  30896. /* A[7] * A[7] */
  30897. "LDR r12, [%[a], #28]\n\t"
  30898. "ADCS r9, r9, #0x0\n\t"
  30899. "ADC r10, r10, #0x0\n\t"
  30900. "UMLAL r9, r10, r12, r12\n\t"
  30901. "LDR %[r], [sp, #64]\n\t"
  30902. "ADD %[r], %[r], #0x20\n\t"
  30903. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30904. "LDM sp, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30905. "SUB %[r], %[r], #0x20\n\t"
  30906. "STM %[r], {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  30907. "ADD sp, sp, #0x44\n\t"
  30908. : [r] "+r" (r), [a] "+r" (a)
  30909. :
  30910. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  30911. );
  30912. }
  30913. #else
  30914. /* Square a and put result in r. (r = a * a)
  30915. *
  30916. * r A single precision integer.
  30917. * a A single precision integer.
  30918. */
  30919. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30920. SP_NOINLINE static void sp_256_sqr_8(sp_digit* r_p, const sp_digit* a_p)
  30921. #else
  30922. SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
  30923. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30924. {
  30925. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  30926. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  30927. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  30928. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  30929. __asm__ __volatile__ (
  30930. "SUB sp, sp, #0x20\n\t"
  30931. "STR %[r], [sp, #28]\n\t"
  30932. "LDM %[a], {r0, r1, r2, r3, r4, r5, r6, r7}\n\t"
  30933. "UMULL r9, r10, r0, r0\n\t"
  30934. "UMULL r11, r12, r0, r1\n\t"
  30935. "ADDS r11, r11, r11\n\t"
  30936. "MOV lr, #0x0\n\t"
  30937. "UMAAL r10, r11, lr, lr\n\t"
  30938. "STM sp, {r9, r10}\n\t"
  30939. "MOV r8, lr\n\t"
  30940. "UMAAL r8, r12, r0, r2\n\t"
  30941. "ADCS r8, r8, r8\n\t"
  30942. "UMAAL r8, r11, r1, r1\n\t"
  30943. "UMULL r9, r10, r0, r3\n\t"
  30944. "UMAAL r9, r12, r1, r2\n\t"
  30945. "ADCS r9, r9, r9\n\t"
  30946. "UMAAL r9, r11, lr, lr\n\t"
  30947. "STRD r8, r9, [sp, #8]\n\t"
  30948. "MOV r9, lr\n\t"
  30949. "UMAAL r9, r10, r0, r4\n\t"
  30950. "UMAAL r9, r12, r1, r3\n\t"
  30951. "ADCS r9, r9, r9\n\t"
  30952. "UMAAL r9, r11, r2, r2\n\t"
  30953. "STR r9, [sp, #16]\n\t"
  30954. "UMULL r9, r8, r0, r5\n\t"
  30955. "UMAAL r9, r12, r1, r4\n\t"
  30956. "UMAAL r9, r10, r2, r3\n\t"
  30957. "ADCS r9, r9, r9\n\t"
  30958. "UMAAL r9, r11, lr, lr\n\t"
  30959. "STR r9, [sp, #20]\n\t"
  30960. "MOV r9, lr\n\t"
  30961. "UMAAL r9, r8, r0, r6\n\t"
  30962. "UMAAL r9, r12, r1, r5\n\t"
  30963. "UMAAL r9, r10, r2, r4\n\t"
  30964. "ADCS r9, r9, r9\n\t"
  30965. "UMAAL r9, r11, r3, r3\n\t"
  30966. "STR r9, [sp, #24]\n\t"
  30967. "UMULL r0, r9, r0, r7\n\t"
  30968. "UMAAL r0, r8, r1, r6\n\t"
  30969. "UMAAL r0, r12, r2, r5\n\t"
  30970. "UMAAL r0, r10, r3, r4\n\t"
  30971. "ADCS r0, r0, r0\n\t"
  30972. "UMAAL r0, r11, lr, lr\n\t"
  30973. /* R[7] = r0 */
  30974. "UMAAL r9, r8, r1, r7\n\t"
  30975. "UMAAL r9, r10, r2, r6\n\t"
  30976. "UMAAL r12, r9, r3, r5\n\t"
  30977. "ADCS r12, r12, r12\n\t"
  30978. "UMAAL r12, r11, r4, r4\n\t"
  30979. /* R[8] = r12 */
  30980. "UMAAL r9, r8, r2, r7\n\t"
  30981. "UMAAL r10, r9, r3, r6\n\t"
  30982. "MOV r2, lr\n\t"
  30983. "UMAAL r10, r2, r4, r5\n\t"
  30984. "ADCS r10, r10, r10\n\t"
  30985. "UMAAL r11, r10, lr, lr\n\t"
  30986. /* R[9] = r11 */
  30987. "UMAAL r2, r8, r3, r7\n\t"
  30988. "UMAAL r2, r9, r4, r6\n\t"
  30989. "ADCS r3, r2, r2\n\t"
  30990. "UMAAL r10, r3, r5, r5\n\t"
  30991. /* R[10] = r10 */
  30992. "MOV r1, lr\n\t"
  30993. "UMAAL r1, r8, r4, r7\n\t"
  30994. "UMAAL r1, r9, r5, r6\n\t"
  30995. "ADCS r4, r1, r1\n\t"
  30996. "UMAAL r3, r4, lr, lr\n\t"
  30997. /* R[11] = r3 */
  30998. "UMAAL r8, r9, r5, r7\n\t"
  30999. "ADCS r8, r8, r8\n\t"
  31000. "UMAAL r4, r8, r6, r6\n\t"
  31001. /* R[12] = r4 */
  31002. "MOV r5, lr\n\t"
  31003. "UMAAL r5, r9, r6, r7\n\t"
  31004. "ADCS r5, r5, r5\n\t"
  31005. "UMAAL r8, r5, lr, lr\n\t"
  31006. /* R[13] = r8 */
  31007. "ADCS r9, r9, r9\n\t"
  31008. "UMAAL r9, r5, r7, r7\n\t"
  31009. "ADCS r7, r5, lr\n\t"
  31010. /* R[14] = r9 */
  31011. /* R[15] = r7 */
  31012. "LDR lr, [sp, #28]\n\t"
  31013. "ADD lr, lr, #0x1c\n\t"
  31014. "STM lr!, {r0, r12}\n\t"
  31015. "STM lr!, {r11}\n\t"
  31016. "STM lr!, {r10}\n\t"
  31017. "STM lr!, {r3, r4, r8, r9}\n\t"
  31018. "STM lr!, {r7}\n\t"
  31019. "SUB lr, lr, #0x40\n\t"
  31020. "LDM sp, {r0, r1, r2, r3, r4, r5, r6}\n\t"
  31021. "STM lr, {r0, r1, r2, r3, r4, r5, r6}\n\t"
  31022. "ADD sp, sp, #0x20\n\t"
  31023. : [r] "+r" (r), [a] "+r" (a)
  31024. :
  31025. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  31026. );
  31027. }
  31028. #endif /* WOLFSSL_SP_NO_UMAAL */
  31029. #endif /* WOLFSSL_SP_SMALL */
  31030. #ifdef WOLFSSL_SP_SMALL
  31031. /* Add b to a into r. (r = a + b)
  31032. *
  31033. * r A single precision integer.
  31034. * a A single precision integer.
  31035. * b A single precision integer.
  31036. */
  31037. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31038. static sp_digit sp_256_add_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  31039. #else
  31040. static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  31041. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31042. {
  31043. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31044. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  31045. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  31046. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  31047. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31048. __asm__ __volatile__ (
  31049. "MOV r3, #0x0\n\t"
  31050. "ADD r12, %[a], #0x20\n\t"
  31051. "\n"
  31052. "L_sp_256_add_8_word:\n\t"
  31053. "ADDS r3, r3, #0xffffffff\n\t"
  31054. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  31055. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  31056. "ADCS r4, r4, r8\n\t"
  31057. "ADCS r5, r5, r9\n\t"
  31058. "ADCS r6, r6, r10\n\t"
  31059. "ADCS r7, r7, r11\n\t"
  31060. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  31061. "MOV r4, #0x0\n\t"
  31062. "ADC r3, r4, #0x0\n\t"
  31063. "CMP %[a], r12\n\t"
  31064. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  31065. "BNE L_sp_256_add_8_word\n\t"
  31066. #else
  31067. "BNE.N L_sp_256_add_8_word\n\t"
  31068. #endif
  31069. "MOV %[r], r3\n\t"
  31070. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  31071. :
  31072. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  31073. );
  31074. return (uint32_t)(size_t)r;
  31075. }
  31076. #else
  31077. /* Add b to a into r. (r = a + b)
  31078. *
  31079. * r A single precision integer.
  31080. * a A single precision integer.
  31081. * b A single precision integer.
  31082. */
  31083. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31084. static sp_digit sp_256_add_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  31085. #else
  31086. static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  31087. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31088. {
  31089. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31090. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  31091. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  31092. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  31093. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31094. __asm__ __volatile__ (
  31095. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  31096. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  31097. "ADDS r3, r3, r7\n\t"
  31098. "ADCS r4, r4, r8\n\t"
  31099. "ADCS r5, r5, r9\n\t"
  31100. "ADCS r6, r6, r10\n\t"
  31101. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  31102. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  31103. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  31104. "ADCS r3, r3, r7\n\t"
  31105. "ADCS r4, r4, r8\n\t"
  31106. "ADCS r5, r5, r9\n\t"
  31107. "ADCS r6, r6, r10\n\t"
  31108. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  31109. "MOV %[r], #0x0\n\t"
  31110. "ADC %[r], %[r], #0x0\n\t"
  31111. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  31112. :
  31113. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  31114. );
  31115. return (uint32_t)(size_t)r;
  31116. }
  31117. #endif /* WOLFSSL_SP_SMALL */
  31118. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  31119. *
  31120. * r The resulting Montgomery form number.
  31121. * a The number to convert.
  31122. * m The modulus (prime).
  31123. */
  31124. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31125. static int sp_256_mod_mul_norm_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  31126. #else
  31127. static int sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
  31128. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31129. {
  31130. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31131. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  31132. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  31133. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31134. __asm__ __volatile__ (
  31135. "SUB sp, sp, #0x18\n\t"
  31136. "LDM %[a], {r2, r3, r4, r5, r6, r7, r8, r9}\n\t"
  31137. /* Clear overflow and underflow */
  31138. "MOV r11, #0x0\n\t"
  31139. "MOV r12, #0x0\n\t"
  31140. /* t[0] = 1 1 0 -1 -1 -1 -1 0 */
  31141. "ADDS r10, r2, r3\n\t"
  31142. "ADC r11, r11, #0x0\n\t"
  31143. "SUBS r10, r10, r5\n\t"
  31144. "SBC r12, r12, #0x0\n\t"
  31145. "SUBS r10, r10, r6\n\t"
  31146. "SBC r12, r12, #0x0\n\t"
  31147. "SUBS r10, r10, r7\n\t"
  31148. "SBC r12, r12, #0x0\n\t"
  31149. "SUBS r10, r10, r8\n\t"
  31150. "SBC r12, r12, #0x0\n\t"
  31151. /* Store t[0] */
  31152. "STR r10, [sp]\n\t"
  31153. "neg r12, r12\n\t"
  31154. "MOV r10, #0x0\n\t"
  31155. /* t[1] = 0 1 1 0 -1 -1 -1 -1 */
  31156. "ADDS r11, r11, r3\n\t"
  31157. "ADC r10, r10, #0x0\n\t"
  31158. "ADDS r11, r11, r4\n\t"
  31159. "ADC r10, r10, #0x0\n\t"
  31160. "SUBS r11, r11, r12\n\t"
  31161. "SBC r12, r12, r12\n\t"
  31162. "SUBS r11, r11, r6\n\t"
  31163. "SBC r12, r12, #0x0\n\t"
  31164. "SUBS r11, r11, r7\n\t"
  31165. "SBC r12, r12, #0x0\n\t"
  31166. "SUBS r11, r11, r8\n\t"
  31167. "SBC r12, r12, #0x0\n\t"
  31168. "SUBS r11, r11, r9\n\t"
  31169. "SBC r12, r12, #0x0\n\t"
  31170. /* Store t[1] */
  31171. "STR r11, [sp, #4]\n\t"
  31172. "neg r12, r12\n\t"
  31173. "MOV r11, #0x0\n\t"
  31174. /* t[2] = 0 0 1 1 0 -1 -1 -1 */
  31175. "ADDS r10, r10, r4\n\t"
  31176. "ADC r11, r11, #0x0\n\t"
  31177. "ADDS r10, r10, r5\n\t"
  31178. "ADC r11, r11, #0x0\n\t"
  31179. "SUBS r10, r10, r12\n\t"
  31180. "SBC r12, r12, r12\n\t"
  31181. "SUBS r10, r10, r7\n\t"
  31182. "SBC r12, r12, #0x0\n\t"
  31183. "SUBS r10, r10, r8\n\t"
  31184. "SBC r12, r12, #0x0\n\t"
  31185. "SUBS r10, r10, r9\n\t"
  31186. "SBC r12, r12, #0x0\n\t"
  31187. /* Store t[2] */
  31188. "STR r10, [sp, #8]\n\t"
  31189. "neg r12, r12\n\t"
  31190. "MOV r10, #0x0\n\t"
  31191. /* t[3] = -1 -1 0 2 2 1 0 -1 */
  31192. "ADDS r11, r11, r5\n\t"
  31193. "ADC r10, r10, #0x0\n\t"
  31194. "ADDS r11, r11, r5\n\t"
  31195. "ADC r10, r10, #0x0\n\t"
  31196. "ADDS r11, r11, r6\n\t"
  31197. "ADC r10, r10, #0x0\n\t"
  31198. "ADDS r11, r11, r6\n\t"
  31199. "ADC r10, r10, #0x0\n\t"
  31200. "ADDS r11, r11, r7\n\t"
  31201. "ADC r10, r10, #0x0\n\t"
  31202. "SUBS r11, r11, r12\n\t"
  31203. "SBC r12, r12, r12\n\t"
  31204. "SUBS r11, r11, r2\n\t"
  31205. "SBC r12, r12, #0x0\n\t"
  31206. "SUBS r11, r11, r3\n\t"
  31207. "SBC r12, r12, #0x0\n\t"
  31208. "SUBS r11, r11, r9\n\t"
  31209. "SBC r12, r12, #0x0\n\t"
  31210. /* Store t[3] */
  31211. "STR r11, [sp, #12]\n\t"
  31212. "neg r12, r12\n\t"
  31213. "MOV r11, #0x0\n\t"
  31214. /* t[4] = 0 -1 -1 0 2 2 1 0 */
  31215. "ADDS r10, r10, r6\n\t"
  31216. "ADC r11, r11, #0x0\n\t"
  31217. "ADDS r10, r10, r6\n\t"
  31218. "ADC r11, r11, #0x0\n\t"
  31219. "ADDS r10, r10, r7\n\t"
  31220. "ADC r11, r11, #0x0\n\t"
  31221. "ADDS r10, r10, r7\n\t"
  31222. "ADC r11, r11, #0x0\n\t"
  31223. "ADDS r10, r10, r8\n\t"
  31224. "ADC r11, r11, #0x0\n\t"
  31225. "SUBS r10, r10, r12\n\t"
  31226. "SBC r12, r12, r12\n\t"
  31227. "SUBS r10, r10, r3\n\t"
  31228. "SBC r12, r12, #0x0\n\t"
  31229. "SUBS r10, r10, r4\n\t"
  31230. "SBC r12, r12, #0x0\n\t"
  31231. /* Store t[4] */
  31232. "STR r10, [sp, #16]\n\t"
  31233. "neg r12, r12\n\t"
  31234. "MOV r10, #0x0\n\t"
  31235. /* t[5] = 0 0 -1 -1 0 2 2 1 */
  31236. "ADDS r11, r11, r7\n\t"
  31237. "ADC r10, r10, #0x0\n\t"
  31238. "ADDS r11, r11, r7\n\t"
  31239. "ADC r10, r10, #0x0\n\t"
  31240. "ADDS r11, r11, r8\n\t"
  31241. "ADC r10, r10, #0x0\n\t"
  31242. "ADDS r11, r11, r8\n\t"
  31243. "ADC r10, r10, #0x0\n\t"
  31244. "ADDS r11, r11, r9\n\t"
  31245. "ADC r10, r10, #0x0\n\t"
  31246. "SUBS r11, r11, r12\n\t"
  31247. "SBC r12, r12, r12\n\t"
  31248. "SUBS r11, r11, r4\n\t"
  31249. "SBC r12, r12, #0x0\n\t"
  31250. "SUBS r11, r11, r5\n\t"
  31251. "SBC r12, r12, #0x0\n\t"
  31252. /* Store t[5] */
  31253. "STR r11, [sp, #20]\n\t"
  31254. "neg r12, r12\n\t"
  31255. "MOV r11, #0x0\n\t"
  31256. /* t[6] = -1 -1 0 0 0 1 3 2 */
  31257. "ADDS r10, r10, r7\n\t"
  31258. "ADC r11, r11, #0x0\n\t"
  31259. "ADDS r10, r10, r8\n\t"
  31260. "ADC r11, r11, #0x0\n\t"
  31261. "ADDS r10, r10, r8\n\t"
  31262. "ADC r11, r11, #0x0\n\t"
  31263. "ADDS r10, r10, r8\n\t"
  31264. "ADC r11, r11, #0x0\n\t"
  31265. "ADDS r10, r10, r9\n\t"
  31266. "ADC r11, r11, #0x0\n\t"
  31267. "ADDS r10, r10, r9\n\t"
  31268. "ADC r11, r11, #0x0\n\t"
  31269. "SUBS r10, r10, r12\n\t"
  31270. "SBC r12, r12, r12\n\t"
  31271. "SUBS r10, r10, r2\n\t"
  31272. "SBC r12, r12, #0x0\n\t"
  31273. "SUBS r10, r10, r3\n\t"
  31274. "SBC r12, r12, #0x0\n\t"
  31275. /* Store t[6] */
  31276. "MOV r8, r10\n\t"
  31277. "neg r12, r12\n\t"
  31278. "MOV r10, #0x0\n\t"
  31279. /* t[7] = 1 0 -1 -1 -1 -1 0 3 */
  31280. "ADDS r11, r11, r2\n\t"
  31281. "ADC r10, r10, #0x0\n\t"
  31282. "ADDS r11, r11, r9\n\t"
  31283. "ADC r10, r10, #0x0\n\t"
  31284. "ADDS r11, r11, r9\n\t"
  31285. "ADC r10, r10, #0x0\n\t"
  31286. "ADDS r11, r11, r9\n\t"
  31287. "ADC r10, r10, #0x0\n\t"
  31288. "SUBS r11, r11, r12\n\t"
  31289. "SBC r12, r12, r12\n\t"
  31290. "SUBS r11, r11, r4\n\t"
  31291. "SBC r12, r12, #0x0\n\t"
  31292. "SUBS r11, r11, r5\n\t"
  31293. "SBC r12, r12, #0x0\n\t"
  31294. "SUBS r11, r11, r6\n\t"
  31295. "SBC r12, r12, #0x0\n\t"
  31296. "SUBS r11, r11, r7\n\t"
  31297. "SBC r12, r12, #0x0\n\t"
  31298. /* Store t[7] */
  31299. /* Load intermediate */
  31300. "LDM sp, {r2, r3, r4, r5, r6, r7}\n\t"
  31301. "neg r12, r12\n\t"
  31302. /* Add overflow */
  31303. /* Subtract underflow - add neg underflow */
  31304. "ADDS r2, r2, r10\n\t"
  31305. "ADCS r3, r3, #0x0\n\t"
  31306. "ADCS r4, r4, #0x0\n\t"
  31307. "ADCS r5, r5, r12\n\t"
  31308. "ADCS r6, r6, #0x0\n\t"
  31309. "ADCS r7, r7, #0x0\n\t"
  31310. "ADCS r8, r8, r12\n\t"
  31311. "ADCS r11, r11, r10\n\t"
  31312. "MOV r9, #0x0\n\t"
  31313. "ADC r9, r9, #0x0\n\t"
  31314. /* Subtract overflow */
  31315. /* Add underflow - subtract neg underflow */
  31316. "SUBS r2, r2, r12\n\t"
  31317. "SBCS r3, r3, #0x0\n\t"
  31318. "SBCS r4, r4, #0x0\n\t"
  31319. "SBCS r5, r5, r10\n\t"
  31320. "SBCS r6, r6, #0x0\n\t"
  31321. "SBCS r7, r7, #0x0\n\t"
  31322. "SBCS r8, r8, r10\n\t"
  31323. "SBCS r11, r11, r12\n\t"
  31324. "MOV r12, #0x0\n\t"
  31325. "SBC r12, r12, #0x0\n\t"
  31326. "neg r12, r12\n\t"
  31327. /* Add overflow */
  31328. /* Subtract underflow - add neg underflow */
  31329. "ADDS r2, r2, r9\n\t"
  31330. "ADCS r3, r3, #0x0\n\t"
  31331. "ADCS r4, r4, #0x0\n\t"
  31332. "ADCS r5, r5, r12\n\t"
  31333. "ADCS r6, r6, #0x0\n\t"
  31334. "ADCS r7, r7, #0x0\n\t"
  31335. "ADCS r8, r8, r12\n\t"
  31336. "ADC r11, r11, r9\n\t"
  31337. /* Subtract overflow */
  31338. /* Add underflow - subtract neg underflow */
  31339. "SUBS r2, r2, r12\n\t"
  31340. "SBCS r3, r3, #0x0\n\t"
  31341. "SBCS r4, r4, #0x0\n\t"
  31342. "SBCS r5, r5, r9\n\t"
  31343. "SBCS r6, r6, #0x0\n\t"
  31344. "SBCS r7, r7, #0x0\n\t"
  31345. "SBCS r8, r8, r9\n\t"
  31346. "SBC r11, r11, r12\n\t"
  31347. /* Store result */
  31348. "STM %[r], {r2, r3, r4, r5, r6, r7, r8, r11}\n\t"
  31349. "MOV %[r], #0x0\n\t"
  31350. "ADD sp, sp, #0x18\n\t"
  31351. : [r] "+r" (r), [a] "+r" (a)
  31352. :
  31353. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  31354. );
  31355. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31356. (void)m_p;
  31357. #else
  31358. (void)m;
  31359. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31360. return (uint32_t)(size_t)r;
  31361. }
  31362. /* Convert an mp_int to an array of sp_digit.
  31363. *
  31364. * r A single precision integer.
  31365. * size Maximum number of bytes to convert
  31366. * a A multi-precision integer.
  31367. */
  31368. static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
  31369. {
  31370. #if DIGIT_BIT == 32
  31371. int i;
  31372. sp_digit j = (sp_digit)0 - (sp_digit)a->used;
  31373. int o = 0;
  31374. for (i = 0; i < size; i++) {
  31375. sp_digit mask = (sp_digit)0 - (j >> 31);
  31376. r[i] = a->dp[o] & mask;
  31377. j++;
  31378. o += (int)(j >> 31);
  31379. }
  31380. #elif DIGIT_BIT > 32
  31381. unsigned int i;
  31382. int j = 0;
  31383. word32 s = 0;
  31384. r[0] = 0;
  31385. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  31386. r[j] |= ((sp_digit)a->dp[i] << s);
  31387. r[j] &= 0xffffffff;
  31388. s = 32U - s;
  31389. if (j + 1 >= size) {
  31390. break;
  31391. }
  31392. /* lint allow cast of mismatch word32 and mp_digit */
  31393. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  31394. while ((s + 32U) <= (word32)DIGIT_BIT) {
  31395. s += 32U;
  31396. r[j] &= 0xffffffff;
  31397. if (j + 1 >= size) {
  31398. break;
  31399. }
  31400. if (s < (word32)DIGIT_BIT) {
  31401. /* lint allow cast of mismatch word32 and mp_digit */
  31402. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  31403. }
  31404. else {
  31405. r[++j] = (sp_digit)0;
  31406. }
  31407. }
  31408. s = (word32)DIGIT_BIT - s;
  31409. }
  31410. for (j++; j < size; j++) {
  31411. r[j] = 0;
  31412. }
  31413. #else
  31414. unsigned int i;
  31415. int j = 0;
  31416. int s = 0;
  31417. r[0] = 0;
  31418. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  31419. r[j] |= ((sp_digit)a->dp[i]) << s;
  31420. if (s + DIGIT_BIT >= 32) {
  31421. r[j] &= 0xffffffff;
  31422. if (j + 1 >= size) {
  31423. break;
  31424. }
  31425. s = 32 - s;
  31426. if (s == DIGIT_BIT) {
  31427. r[++j] = 0;
  31428. s = 0;
  31429. }
  31430. else {
  31431. r[++j] = a->dp[i] >> s;
  31432. s = DIGIT_BIT - s;
  31433. }
  31434. }
  31435. else {
  31436. s += DIGIT_BIT;
  31437. }
  31438. }
  31439. for (j++; j < size; j++) {
  31440. r[j] = 0;
  31441. }
  31442. #endif
  31443. }
  31444. /* Convert a point of type ecc_point to type sp_point_256.
  31445. *
  31446. * p Point of type sp_point_256 (result).
  31447. * pm Point of type ecc_point.
  31448. */
  31449. static void sp_256_point_from_ecc_point_8(sp_point_256* p,
  31450. const ecc_point* pm)
  31451. {
  31452. XMEMSET(p->x, 0, sizeof(p->x));
  31453. XMEMSET(p->y, 0, sizeof(p->y));
  31454. XMEMSET(p->z, 0, sizeof(p->z));
  31455. sp_256_from_mp(p->x, 8, pm->x);
  31456. sp_256_from_mp(p->y, 8, pm->y);
  31457. sp_256_from_mp(p->z, 8, pm->z);
  31458. p->infinity = 0;
  31459. }
  31460. /* Convert an array of sp_digit to an mp_int.
  31461. *
  31462. * a A single precision integer.
  31463. * r A multi-precision integer.
  31464. */
  31465. static int sp_256_to_mp(const sp_digit* a, mp_int* r)
  31466. {
  31467. int err;
  31468. err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
  31469. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  31470. #if DIGIT_BIT == 32
  31471. XMEMCPY(r->dp, a, sizeof(sp_digit) * 8);
  31472. r->used = 8;
  31473. mp_clamp(r);
  31474. #elif DIGIT_BIT < 32
  31475. int i;
  31476. int j = 0;
  31477. int s = 0;
  31478. r->dp[0] = 0;
  31479. for (i = 0; i < 8; i++) {
  31480. r->dp[j] |= (mp_digit)(a[i] << s);
  31481. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  31482. s = DIGIT_BIT - s;
  31483. r->dp[++j] = (mp_digit)(a[i] >> s);
  31484. while (s + DIGIT_BIT <= 32) {
  31485. s += DIGIT_BIT;
  31486. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  31487. if (s == SP_WORD_SIZE) {
  31488. r->dp[j] = 0;
  31489. }
  31490. else {
  31491. r->dp[j] = (mp_digit)(a[i] >> s);
  31492. }
  31493. }
  31494. s = 32 - s;
  31495. }
  31496. r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
  31497. mp_clamp(r);
  31498. #else
  31499. int i;
  31500. int j = 0;
  31501. int s = 0;
  31502. r->dp[0] = 0;
  31503. for (i = 0; i < 8; i++) {
  31504. r->dp[j] |= ((mp_digit)a[i]) << s;
  31505. if (s + 32 >= DIGIT_BIT) {
  31506. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  31507. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  31508. #endif
  31509. s = DIGIT_BIT - s;
  31510. r->dp[++j] = a[i] >> s;
  31511. s = 32 - s;
  31512. }
  31513. else {
  31514. s += 32;
  31515. }
  31516. }
  31517. r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
  31518. mp_clamp(r);
  31519. #endif
  31520. }
  31521. return err;
  31522. }
  31523. /* Convert a point of type sp_point_256 to type ecc_point.
  31524. *
  31525. * p Point of type sp_point_256.
  31526. * pm Point of type ecc_point (result).
  31527. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  31528. * MP_OKAY.
  31529. */
  31530. static int sp_256_point_to_ecc_point_8(const sp_point_256* p, ecc_point* pm)
  31531. {
  31532. int err;
  31533. err = sp_256_to_mp(p->x, pm->x);
  31534. if (err == MP_OKAY) {
  31535. err = sp_256_to_mp(p->y, pm->y);
  31536. }
  31537. if (err == MP_OKAY) {
  31538. err = sp_256_to_mp(p->z, pm->z);
  31539. }
  31540. return err;
  31541. }
  31542. #ifdef WOLFSSL_SP_NO_UMAAL
  31543. /* Multiply two Montgomery form numbers mod the modulus (prime).
  31544. * (r = a * b mod m)
  31545. *
  31546. * r Result of multiplication.
  31547. * a First number to multiply in Montgomery form.
  31548. * b Second number to multiply in Montgomery form.
  31549. * m Modulus (prime).
  31550. * mp Montgomery multiplier.
  31551. */
  31552. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31553. SP_NOINLINE static void sp_256_mont_mul_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p, sp_digit mp_p)
  31554. #else
  31555. SP_NOINLINE 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)
  31556. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31557. {
  31558. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  31559. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  31560. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  31561. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  31562. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  31563. __asm__ __volatile__ (
  31564. "SUB sp, sp, #0x44\n\t"
  31565. "STR %[r], [sp, #64]\n\t"
  31566. "MOV %[r], #0x0\n\t"
  31567. "LDR r12, [%[a]]\n\t"
  31568. /* A[0] * B[0] */
  31569. "LDR lr, [%[b]]\n\t"
  31570. "UMULL r3, r4, r12, lr\n\t"
  31571. /* A[0] * B[2] */
  31572. "LDR lr, [%[b], #8]\n\t"
  31573. "UMULL r5, r6, r12, lr\n\t"
  31574. /* A[0] * B[4] */
  31575. "LDR lr, [%[b], #16]\n\t"
  31576. "UMULL r7, r8, r12, lr\n\t"
  31577. /* A[0] * B[6] */
  31578. "LDR lr, [%[b], #24]\n\t"
  31579. "UMULL r9, r10, r12, lr\n\t"
  31580. "STR r3, [sp]\n\t"
  31581. /* A[0] * B[1] */
  31582. "LDR lr, [%[b], #4]\n\t"
  31583. "MOV r11, %[r]\n\t"
  31584. "UMLAL r4, r11, r12, lr\n\t"
  31585. "ADDS r5, r5, r11\n\t"
  31586. /* A[0] * B[3] */
  31587. "LDR lr, [%[b], #12]\n\t"
  31588. "ADCS r6, r6, #0x0\n\t"
  31589. "ADC r11, %[r], #0x0\n\t"
  31590. "UMLAL r6, r11, r12, lr\n\t"
  31591. "ADDS r7, r7, r11\n\t"
  31592. /* A[0] * B[5] */
  31593. "LDR lr, [%[b], #20]\n\t"
  31594. "ADCS r8, r8, #0x0\n\t"
  31595. "ADC r11, %[r], #0x0\n\t"
  31596. "UMLAL r8, r11, r12, lr\n\t"
  31597. "ADDS r9, r9, r11\n\t"
  31598. /* A[0] * B[7] */
  31599. "LDR lr, [%[b], #28]\n\t"
  31600. "ADCS r10, r10, #0x0\n\t"
  31601. "ADC r3, %[r], #0x0\n\t"
  31602. "UMLAL r10, r3, r12, lr\n\t"
  31603. /* A[1] * B[0] */
  31604. "LDR r12, [%[a], #4]\n\t"
  31605. "LDR lr, [%[b]]\n\t"
  31606. "MOV r11, #0x0\n\t"
  31607. "UMLAL r4, r11, r12, lr\n\t"
  31608. "STR r4, [sp, #4]\n\t"
  31609. "ADDS r5, r5, r11\n\t"
  31610. /* A[1] * B[1] */
  31611. "LDR lr, [%[b], #4]\n\t"
  31612. "ADC r11, %[r], #0x0\n\t"
  31613. "UMLAL r5, r11, r12, lr\n\t"
  31614. "ADDS r6, r6, r11\n\t"
  31615. /* A[1] * B[2] */
  31616. "LDR lr, [%[b], #8]\n\t"
  31617. "ADC r11, %[r], #0x0\n\t"
  31618. "UMLAL r6, r11, r12, lr\n\t"
  31619. "ADDS r7, r7, r11\n\t"
  31620. /* A[1] * B[3] */
  31621. "LDR lr, [%[b], #12]\n\t"
  31622. "ADC r11, %[r], #0x0\n\t"
  31623. "UMLAL r7, r11, r12, lr\n\t"
  31624. "ADDS r8, r8, r11\n\t"
  31625. /* A[1] * B[4] */
  31626. "LDR lr, [%[b], #16]\n\t"
  31627. "ADC r11, %[r], #0x0\n\t"
  31628. "UMLAL r8, r11, r12, lr\n\t"
  31629. "ADDS r9, r9, r11\n\t"
  31630. /* A[1] * B[5] */
  31631. "LDR lr, [%[b], #20]\n\t"
  31632. "ADC r11, %[r], #0x0\n\t"
  31633. "UMLAL r9, r11, r12, lr\n\t"
  31634. "ADDS r10, r10, r11\n\t"
  31635. /* A[1] * B[6] */
  31636. "LDR lr, [%[b], #24]\n\t"
  31637. "ADC r11, %[r], #0x0\n\t"
  31638. "UMLAL r10, r11, r12, lr\n\t"
  31639. "ADDS r3, r3, r11\n\t"
  31640. /* A[1] * B[7] */
  31641. "LDR lr, [%[b], #28]\n\t"
  31642. "ADC r4, %[r], #0x0\n\t"
  31643. "UMLAL r3, r4, r12, lr\n\t"
  31644. /* A[2] * B[0] */
  31645. "LDR r12, [%[a], #8]\n\t"
  31646. "LDR lr, [%[b]]\n\t"
  31647. "MOV r11, #0x0\n\t"
  31648. "UMLAL r5, r11, r12, lr\n\t"
  31649. "STR r5, [sp, #8]\n\t"
  31650. "ADDS r6, r6, r11\n\t"
  31651. /* A[2] * B[1] */
  31652. "LDR lr, [%[b], #4]\n\t"
  31653. "ADC r11, %[r], #0x0\n\t"
  31654. "UMLAL r6, r11, r12, lr\n\t"
  31655. "ADDS r7, r7, r11\n\t"
  31656. /* A[2] * B[2] */
  31657. "LDR lr, [%[b], #8]\n\t"
  31658. "ADC r11, %[r], #0x0\n\t"
  31659. "UMLAL r7, r11, r12, lr\n\t"
  31660. "ADDS r8, r8, r11\n\t"
  31661. /* A[2] * B[3] */
  31662. "LDR lr, [%[b], #12]\n\t"
  31663. "ADC r11, %[r], #0x0\n\t"
  31664. "UMLAL r8, r11, r12, lr\n\t"
  31665. "ADDS r9, r9, r11\n\t"
  31666. /* A[2] * B[4] */
  31667. "LDR lr, [%[b], #16]\n\t"
  31668. "ADC r11, %[r], #0x0\n\t"
  31669. "UMLAL r9, r11, r12, lr\n\t"
  31670. "ADDS r10, r10, r11\n\t"
  31671. /* A[2] * B[5] */
  31672. "LDR lr, [%[b], #20]\n\t"
  31673. "ADC r11, %[r], #0x0\n\t"
  31674. "UMLAL r10, r11, r12, lr\n\t"
  31675. "ADDS r3, r3, r11\n\t"
  31676. /* A[2] * B[6] */
  31677. "LDR lr, [%[b], #24]\n\t"
  31678. "ADC r11, %[r], #0x0\n\t"
  31679. "UMLAL r3, r11, r12, lr\n\t"
  31680. "ADDS r4, r4, r11\n\t"
  31681. /* A[2] * B[7] */
  31682. "LDR lr, [%[b], #28]\n\t"
  31683. "ADC r5, %[r], #0x0\n\t"
  31684. "UMLAL r4, r5, r12, lr\n\t"
  31685. /* A[3] * B[0] */
  31686. "LDR r12, [%[a], #12]\n\t"
  31687. "LDR lr, [%[b]]\n\t"
  31688. "MOV r11, #0x0\n\t"
  31689. "UMLAL r6, r11, r12, lr\n\t"
  31690. "STR r6, [sp, #12]\n\t"
  31691. "ADDS r7, r7, r11\n\t"
  31692. /* A[3] * B[1] */
  31693. "LDR lr, [%[b], #4]\n\t"
  31694. "ADC r11, %[r], #0x0\n\t"
  31695. "UMLAL r7, r11, r12, lr\n\t"
  31696. "ADDS r8, r8, r11\n\t"
  31697. /* A[3] * B[2] */
  31698. "LDR lr, [%[b], #8]\n\t"
  31699. "ADC r11, %[r], #0x0\n\t"
  31700. "UMLAL r8, r11, r12, lr\n\t"
  31701. "ADDS r9, r9, r11\n\t"
  31702. /* A[3] * B[3] */
  31703. "LDR lr, [%[b], #12]\n\t"
  31704. "ADC r11, %[r], #0x0\n\t"
  31705. "UMLAL r9, r11, r12, lr\n\t"
  31706. "ADDS r10, r10, r11\n\t"
  31707. /* A[3] * B[4] */
  31708. "LDR lr, [%[b], #16]\n\t"
  31709. "ADC r11, %[r], #0x0\n\t"
  31710. "UMLAL r10, r11, r12, lr\n\t"
  31711. "ADDS r3, r3, r11\n\t"
  31712. /* A[3] * B[5] */
  31713. "LDR lr, [%[b], #20]\n\t"
  31714. "ADC r11, %[r], #0x0\n\t"
  31715. "UMLAL r3, r11, r12, lr\n\t"
  31716. "ADDS r4, r4, r11\n\t"
  31717. /* A[3] * B[6] */
  31718. "LDR lr, [%[b], #24]\n\t"
  31719. "ADC r11, %[r], #0x0\n\t"
  31720. "UMLAL r4, r11, r12, lr\n\t"
  31721. "ADDS r5, r5, r11\n\t"
  31722. /* A[3] * B[7] */
  31723. "LDR lr, [%[b], #28]\n\t"
  31724. "ADC r6, %[r], #0x0\n\t"
  31725. "UMLAL r5, r6, r12, lr\n\t"
  31726. /* A[4] * B[0] */
  31727. "LDR r12, [%[a], #16]\n\t"
  31728. "LDR lr, [%[b]]\n\t"
  31729. "MOV r11, #0x0\n\t"
  31730. "UMLAL r7, r11, r12, lr\n\t"
  31731. "STR r7, [sp, #16]\n\t"
  31732. "ADDS r8, r8, r11\n\t"
  31733. /* A[4] * B[1] */
  31734. "LDR lr, [%[b], #4]\n\t"
  31735. "ADC r11, %[r], #0x0\n\t"
  31736. "UMLAL r8, r11, r12, lr\n\t"
  31737. "ADDS r9, r9, r11\n\t"
  31738. /* A[4] * B[2] */
  31739. "LDR lr, [%[b], #8]\n\t"
  31740. "ADC r11, %[r], #0x0\n\t"
  31741. "UMLAL r9, r11, r12, lr\n\t"
  31742. "ADDS r10, r10, r11\n\t"
  31743. /* A[4] * B[3] */
  31744. "LDR lr, [%[b], #12]\n\t"
  31745. "ADC r11, %[r], #0x0\n\t"
  31746. "UMLAL r10, r11, r12, lr\n\t"
  31747. "ADDS r3, r3, r11\n\t"
  31748. /* A[4] * B[4] */
  31749. "LDR lr, [%[b], #16]\n\t"
  31750. "ADC r11, %[r], #0x0\n\t"
  31751. "UMLAL r3, r11, r12, lr\n\t"
  31752. "ADDS r4, r4, r11\n\t"
  31753. /* A[4] * B[5] */
  31754. "LDR lr, [%[b], #20]\n\t"
  31755. "ADC r11, %[r], #0x0\n\t"
  31756. "UMLAL r4, r11, r12, lr\n\t"
  31757. "ADDS r5, r5, r11\n\t"
  31758. /* A[4] * B[6] */
  31759. "LDR lr, [%[b], #24]\n\t"
  31760. "ADC r11, %[r], #0x0\n\t"
  31761. "UMLAL r5, r11, r12, lr\n\t"
  31762. "ADDS r6, r6, r11\n\t"
  31763. /* A[4] * B[7] */
  31764. "LDR lr, [%[b], #28]\n\t"
  31765. "ADC r7, %[r], #0x0\n\t"
  31766. "UMLAL r6, r7, r12, lr\n\t"
  31767. /* A[5] * B[0] */
  31768. "LDR r12, [%[a], #20]\n\t"
  31769. "LDR lr, [%[b]]\n\t"
  31770. "MOV r11, #0x0\n\t"
  31771. "UMLAL r8, r11, r12, lr\n\t"
  31772. "STR r8, [sp, #20]\n\t"
  31773. "ADDS r9, r9, r11\n\t"
  31774. /* A[5] * B[1] */
  31775. "LDR lr, [%[b], #4]\n\t"
  31776. "ADC r11, %[r], #0x0\n\t"
  31777. "UMLAL r9, r11, r12, lr\n\t"
  31778. "ADDS r10, r10, r11\n\t"
  31779. /* A[5] * B[2] */
  31780. "LDR lr, [%[b], #8]\n\t"
  31781. "ADC r11, %[r], #0x0\n\t"
  31782. "UMLAL r10, r11, r12, lr\n\t"
  31783. "ADDS r3, r3, r11\n\t"
  31784. /* A[5] * B[3] */
  31785. "LDR lr, [%[b], #12]\n\t"
  31786. "ADC r11, %[r], #0x0\n\t"
  31787. "UMLAL r3, r11, r12, lr\n\t"
  31788. "ADDS r4, r4, r11\n\t"
  31789. /* A[5] * B[4] */
  31790. "LDR lr, [%[b], #16]\n\t"
  31791. "ADC r11, %[r], #0x0\n\t"
  31792. "UMLAL r4, r11, r12, lr\n\t"
  31793. "ADDS r5, r5, r11\n\t"
  31794. /* A[5] * B[5] */
  31795. "LDR lr, [%[b], #20]\n\t"
  31796. "ADC r11, %[r], #0x0\n\t"
  31797. "UMLAL r5, r11, r12, lr\n\t"
  31798. "ADDS r6, r6, r11\n\t"
  31799. /* A[5] * B[6] */
  31800. "LDR lr, [%[b], #24]\n\t"
  31801. "ADC r11, %[r], #0x0\n\t"
  31802. "UMLAL r6, r11, r12, lr\n\t"
  31803. "ADDS r7, r7, r11\n\t"
  31804. /* A[5] * B[7] */
  31805. "LDR lr, [%[b], #28]\n\t"
  31806. "ADC r8, %[r], #0x0\n\t"
  31807. "UMLAL r7, r8, r12, lr\n\t"
  31808. /* A[6] * B[0] */
  31809. "LDR r12, [%[a], #24]\n\t"
  31810. "LDR lr, [%[b]]\n\t"
  31811. "MOV r11, #0x0\n\t"
  31812. "UMLAL r9, r11, r12, lr\n\t"
  31813. "STR r9, [sp, #24]\n\t"
  31814. "ADDS r10, r10, r11\n\t"
  31815. /* A[6] * B[1] */
  31816. "LDR lr, [%[b], #4]\n\t"
  31817. "ADC r11, %[r], #0x0\n\t"
  31818. "UMLAL r10, r11, r12, lr\n\t"
  31819. "ADDS r3, r3, r11\n\t"
  31820. /* A[6] * B[2] */
  31821. "LDR lr, [%[b], #8]\n\t"
  31822. "ADC r11, %[r], #0x0\n\t"
  31823. "UMLAL r3, r11, r12, lr\n\t"
  31824. "ADDS r4, r4, r11\n\t"
  31825. /* A[6] * B[3] */
  31826. "LDR lr, [%[b], #12]\n\t"
  31827. "ADC r11, %[r], #0x0\n\t"
  31828. "UMLAL r4, r11, r12, lr\n\t"
  31829. "ADDS r5, r5, r11\n\t"
  31830. /* A[6] * B[4] */
  31831. "LDR lr, [%[b], #16]\n\t"
  31832. "ADC r11, %[r], #0x0\n\t"
  31833. "UMLAL r5, r11, r12, lr\n\t"
  31834. "ADDS r6, r6, r11\n\t"
  31835. /* A[6] * B[5] */
  31836. "LDR lr, [%[b], #20]\n\t"
  31837. "ADC r11, %[r], #0x0\n\t"
  31838. "UMLAL r6, r11, r12, lr\n\t"
  31839. "ADDS r7, r7, r11\n\t"
  31840. /* A[6] * B[6] */
  31841. "LDR lr, [%[b], #24]\n\t"
  31842. "ADC r11, %[r], #0x0\n\t"
  31843. "UMLAL r7, r11, r12, lr\n\t"
  31844. "ADDS r8, r8, r11\n\t"
  31845. /* A[6] * B[7] */
  31846. "LDR lr, [%[b], #28]\n\t"
  31847. "ADC r9, %[r], #0x0\n\t"
  31848. "UMLAL r8, r9, r12, lr\n\t"
  31849. /* A[7] * B[0] */
  31850. "LDR r12, [%[a], #28]\n\t"
  31851. "LDR lr, [%[b]]\n\t"
  31852. "MOV r11, #0x0\n\t"
  31853. "UMLAL r10, r11, r12, lr\n\t"
  31854. "STR r10, [sp, #28]\n\t"
  31855. "ADDS r3, r3, r11\n\t"
  31856. /* A[7] * B[1] */
  31857. "LDR lr, [%[b], #4]\n\t"
  31858. "ADC r11, %[r], #0x0\n\t"
  31859. "UMLAL r3, r11, r12, lr\n\t"
  31860. "ADDS r4, r4, r11\n\t"
  31861. /* A[7] * B[2] */
  31862. "LDR lr, [%[b], #8]\n\t"
  31863. "ADC r11, %[r], #0x0\n\t"
  31864. "UMLAL r4, r11, r12, lr\n\t"
  31865. "ADDS r5, r5, r11\n\t"
  31866. /* A[7] * B[3] */
  31867. "LDR lr, [%[b], #12]\n\t"
  31868. "ADC r11, %[r], #0x0\n\t"
  31869. "UMLAL r5, r11, r12, lr\n\t"
  31870. "ADDS r6, r6, r11\n\t"
  31871. /* A[7] * B[4] */
  31872. "LDR lr, [%[b], #16]\n\t"
  31873. "ADC r11, %[r], #0x0\n\t"
  31874. "UMLAL r6, r11, r12, lr\n\t"
  31875. "ADDS r7, r7, r11\n\t"
  31876. /* A[7] * B[5] */
  31877. "LDR lr, [%[b], #20]\n\t"
  31878. "ADC r11, %[r], #0x0\n\t"
  31879. "UMLAL r7, r11, r12, lr\n\t"
  31880. "ADDS r8, r8, r11\n\t"
  31881. /* A[7] * B[6] */
  31882. "LDR lr, [%[b], #24]\n\t"
  31883. "ADC r11, %[r], #0x0\n\t"
  31884. "UMLAL r8, r11, r12, lr\n\t"
  31885. "ADDS r9, r9, r11\n\t"
  31886. /* A[7] * B[7] */
  31887. "LDR lr, [%[b], #28]\n\t"
  31888. "ADC r10, %[r], #0x0\n\t"
  31889. "UMLAL r9, r10, r12, lr\n\t"
  31890. "ADD lr, sp, #0x20\n\t"
  31891. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  31892. /* Start Reduction */
  31893. "LDM sp, {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  31894. "MOV r3, r11\n\t"
  31895. "MOV r4, r12\n\t"
  31896. /* mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192 */
  31897. /* - a[0] << 224 */
  31898. /* + (a[0]-a[1] * 2) << (6 * 32) */
  31899. "ADDS r11, r11, r5\n\t"
  31900. "ADC r12, r12, r6\n\t"
  31901. "ADDS r11, r11, r5\n\t"
  31902. "ADC r12, r12, r6\n\t"
  31903. /* - a[0] << (7 * 32) */
  31904. "SUB r12, r12, r5\n\t"
  31905. /* + a[0]-a[4] << (3 * 32) */
  31906. "MOV r0, r8\n\t"
  31907. "MOV r1, r9\n\t"
  31908. "MOV r2, r10\n\t"
  31909. "ADDS r8, r8, r5\n\t"
  31910. "ADCS r9, r9, r6\n\t"
  31911. "ADCS r10, r10, r7\n\t"
  31912. "ADCS r11, r11, r0\n\t"
  31913. "ADC r12, r12, r1\n\t"
  31914. /* a += mu * m */
  31915. /* += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1) */
  31916. /* a[0] = = t[0] */
  31917. /* a[1] = = t[1] */
  31918. /* a[2] = = t[2] */
  31919. /* a[3] += t[0] = t[3] */
  31920. /* a[4] += t[1] = t[4] */
  31921. /* a[5] += t[2] = t[5] */
  31922. /* a[6] += t[0] + t[3] = t[6] */
  31923. /* a[7] += t[1] + t[4] = t[7] + t[0] */
  31924. "ADDS r0, r0, r5\n\t"
  31925. "ADCS r1, r1, r6\n\t"
  31926. "ADCS r2, r2, r7\n\t"
  31927. "ADCS r3, r3, r8\n\t"
  31928. "ADCS r4, r4, r9\n\t"
  31929. "MOV lr, #0x0\n\t"
  31930. "ADC lr, lr, #0x0\n\t"
  31931. "ADDS r3, r3, r5\n\t"
  31932. "ADCS r4, r4, r6\n\t"
  31933. "ADC lr, lr, #0x0\n\t"
  31934. "STR r4, [sp, #28]\n\t"
  31935. /* a[8] += t[0] + t[2] + t[5] */
  31936. /* a[9] += t[1] + t[3] + t[6] */
  31937. /* a[10] += t[2] + t[4] + t[7] */
  31938. "ADD r0, sp, #0x20\n\t"
  31939. "LDM r0, {r2, r3, r4}\n\t"
  31940. "ADDS r2, r2, lr\n\t"
  31941. "ADCS r3, r3, #0x0\n\t"
  31942. "ADCS r4, r4, #0x0\n\t"
  31943. "MOV lr, #0x0\n\t"
  31944. "ADC lr, lr, #0x0\n\t"
  31945. "ADDS r2, r2, r5\n\t"
  31946. "ADCS r3, r3, r6\n\t"
  31947. "ADCS r4, r4, r7\n\t"
  31948. "ADC lr, lr, #0x0\n\t"
  31949. "ADDS r2, r2, r7\n\t"
  31950. "ADCS r3, r3, r8\n\t"
  31951. "ADCS r4, r4, r9\n\t"
  31952. "ADC lr, lr, #0x0\n\t"
  31953. "ADDS r2, r2, r10\n\t"
  31954. "ADCS r3, r3, r11\n\t"
  31955. "ADCS r4, r4, r12\n\t"
  31956. "ADC lr, lr, #0x0\n\t"
  31957. "STM r0!, {r2, r3, r4}\n\t"
  31958. /* a[11] += t[3] + t[5] + carry */
  31959. /* a[12] += t[4] + t[6] */
  31960. /* a[13] += t[5] + t[7] */
  31961. /* a[14] += t[6] */
  31962. /* a[15] += t[7] */
  31963. "LDM r0, {r0, r1, r2, r3, r4}\n\t"
  31964. "ADDS r0, r0, lr\n\t"
  31965. "ADCS r1, r1, #0x0\n\t"
  31966. "ADCS r2, r2, #0x0\n\t"
  31967. "ADCS r3, r3, #0x0\n\t"
  31968. "ADCS r4, r4, #0x0\n\t"
  31969. "MOV lr, #0x0\n\t"
  31970. "ADC lr, lr, #0x0\n\t"
  31971. "ADDS r0, r0, r8\n\t"
  31972. "ADCS r1, r1, r9\n\t"
  31973. "ADCS r2, r2, r10\n\t"
  31974. "ADCS r3, r3, r11\n\t"
  31975. "ADCS r4, r4, r12\n\t"
  31976. "ADC lr, lr, #0x0\n\t"
  31977. "ADDS r0, r0, r10\n\t"
  31978. "ADCS r1, r1, r11\n\t"
  31979. "ADCS r2, r2, r12\n\t"
  31980. "ADCS r3, r3, #0x0\n\t"
  31981. "ADCS r4, r4, #0x0\n\t"
  31982. "ADC lr, lr, #0x0\n\t"
  31983. "STR r0, [sp, #44]\n\t"
  31984. "STR r1, [sp, #48]\n\t"
  31985. "STR r2, [sp, #52]\n\t"
  31986. "STR r3, [sp, #56]\n\t"
  31987. /* a[7..15] - t[0..7] */
  31988. "ADD r0, sp, #0x1c\n\t"
  31989. "LDM r0, {r0, r1, r2, r3}\n\t"
  31990. "SUBS r0, r0, r5\n\t"
  31991. "SBCS r1, r1, r6\n\t"
  31992. "SBCS r2, r2, r7\n\t"
  31993. "SBCS r3, r3, r8\n\t"
  31994. "ADD r0, sp, #0x2c\n\t"
  31995. "MOV r8, r4\n\t"
  31996. "LDM r0, {r4, r5, r6, r7}\n\t"
  31997. "SBCS r4, r4, r9\n\t"
  31998. "SBCS r5, r5, r10\n\t"
  31999. "SBCS r6, r6, r11\n\t"
  32000. "SBCS r7, r7, r12\n\t"
  32001. "SBCS r8, r8, #0x0\n\t"
  32002. "SBC lr, lr, #0x0\n\t"
  32003. /* mask m and sub from result if overflow */
  32004. "RSB lr, lr, #0x0\n\t"
  32005. "SUBS r1, r1, lr\n\t"
  32006. "SBCS r2, r2, lr\n\t"
  32007. "SBCS r3, r3, lr\n\t"
  32008. "SBCS r4, r4, #0x0\n\t"
  32009. "SBCS r5, r5, #0x0\n\t"
  32010. "SBCS r6, r6, #0x0\n\t"
  32011. "SBCS r7, r7, lr, LSR #31\n\t"
  32012. "SBC r8, r8, lr\n\t"
  32013. "LDR %[r], [sp, #64]\n\t"
  32014. "STM %[r], {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  32015. "ADD sp, sp, #0x44\n\t"
  32016. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  32017. :
  32018. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  32019. );
  32020. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32021. (void)m_p;
  32022. #else
  32023. (void)m;
  32024. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32025. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32026. (void)mp_p;
  32027. #else
  32028. (void)mp;
  32029. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32030. }
  32031. #else
  32032. /* Multiply two Montgomery form numbers mod the modulus (prime).
  32033. * (r = a * b mod m)
  32034. *
  32035. * r Result of multiplication.
  32036. * a First number to multiply in Montgomery form.
  32037. * b Second number to multiply in Montgomery form.
  32038. * m Modulus (prime).
  32039. * mp Montgomery multiplier.
  32040. */
  32041. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32042. SP_NOINLINE static void sp_256_mont_mul_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p, sp_digit mp_p)
  32043. #else
  32044. SP_NOINLINE 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)
  32045. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32046. {
  32047. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32048. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  32049. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  32050. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  32051. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32052. __asm__ __volatile__ (
  32053. "SUB sp, sp, #0x4c\n\t"
  32054. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32055. "STRD %[r], %[a], [sp, #68]\n\t"
  32056. #else
  32057. "STR %[r], [sp, #68]\n\t"
  32058. "STR %[a], [sp, #72]\n\t"
  32059. #endif /* WOLFSSL_NO_VAR_ASSIGN_REG */
  32060. "MOV lr, %[b]\n\t"
  32061. "LDM %[a], {r0, r1, r2, r3}\n\t"
  32062. "LDM lr!, {r4, r5, r6}\n\t"
  32063. "UMULL r10, r11, r0, r4\n\t"
  32064. "UMULL r12, r7, r1, r4\n\t"
  32065. "UMAAL r11, r12, r0, r5\n\t"
  32066. "UMULL r8, r9, r2, r4\n\t"
  32067. "UMAAL r12, r8, r1, r5\n\t"
  32068. "UMAAL r12, r7, r0, r6\n\t"
  32069. "UMAAL r8, r9, r3, r4\n\t"
  32070. "STM sp, {r10, r11, r12}\n\t"
  32071. "UMAAL r7, r8, r2, r5\n\t"
  32072. "LDM lr!, {r4}\n\t"
  32073. "UMULL r10, r11, r1, r6\n\t"
  32074. "UMAAL r8, r9, r2, r6\n\t"
  32075. "UMAAL r7, r10, r0, r4\n\t"
  32076. "UMAAL r8, r11, r3, r5\n\t"
  32077. "STR r7, [sp, #12]\n\t"
  32078. "UMAAL r8, r10, r1, r4\n\t"
  32079. "UMAAL r9, r11, r3, r6\n\t"
  32080. "UMAAL r9, r10, r2, r4\n\t"
  32081. "UMAAL r10, r11, r3, r4\n\t"
  32082. "LDM lr, {r4, r5, r6, r7}\n\t"
  32083. "MOV r12, #0x0\n\t"
  32084. "UMLAL r8, r12, r0, r4\n\t"
  32085. "UMAAL r9, r12, r1, r4\n\t"
  32086. "UMAAL r10, r12, r2, r4\n\t"
  32087. "UMAAL r11, r12, r3, r4\n\t"
  32088. "MOV r4, #0x0\n\t"
  32089. "UMLAL r9, r4, r0, r5\n\t"
  32090. "UMAAL r10, r4, r1, r5\n\t"
  32091. "UMAAL r11, r4, r2, r5\n\t"
  32092. "UMAAL r12, r4, r3, r5\n\t"
  32093. "MOV r5, #0x0\n\t"
  32094. "UMLAL r10, r5, r0, r6\n\t"
  32095. "UMAAL r11, r5, r1, r6\n\t"
  32096. "UMAAL r12, r5, r2, r6\n\t"
  32097. "UMAAL r4, r5, r3, r6\n\t"
  32098. "MOV r6, #0x0\n\t"
  32099. "UMLAL r11, r6, r0, r7\n\t"
  32100. "LDR r0, [sp, #72]\n\t"
  32101. "UMAAL r12, r6, r1, r7\n\t"
  32102. "ADD r0, r0, #0x10\n\t"
  32103. "UMAAL r4, r6, r2, r7\n\t"
  32104. "SUB lr, lr, #0x10\n\t"
  32105. "UMAAL r5, r6, r3, r7\n\t"
  32106. "LDM r0, {r0, r1, r2, r3}\n\t"
  32107. "STR r6, [sp, #64]\n\t"
  32108. "LDM lr!, {r6}\n\t"
  32109. "MOV r7, #0x0\n\t"
  32110. "UMLAL r8, r7, r0, r6\n\t"
  32111. "UMAAL r9, r7, r1, r6\n\t"
  32112. "STR r8, [sp, #16]\n\t"
  32113. "UMAAL r10, r7, r2, r6\n\t"
  32114. "UMAAL r11, r7, r3, r6\n\t"
  32115. "LDM lr!, {r6}\n\t"
  32116. "MOV r8, #0x0\n\t"
  32117. "UMLAL r9, r8, r0, r6\n\t"
  32118. "UMAAL r10, r8, r1, r6\n\t"
  32119. "STR r9, [sp, #20]\n\t"
  32120. "UMAAL r11, r8, r2, r6\n\t"
  32121. "UMAAL r12, r8, r3, r6\n\t"
  32122. "LDM lr!, {r6}\n\t"
  32123. "MOV r9, #0x0\n\t"
  32124. "UMLAL r10, r9, r0, r6\n\t"
  32125. "UMAAL r11, r9, r1, r6\n\t"
  32126. "STR r10, [sp, #24]\n\t"
  32127. "UMAAL r12, r9, r2, r6\n\t"
  32128. "UMAAL r4, r9, r3, r6\n\t"
  32129. "LDM lr!, {r6}\n\t"
  32130. "MOV r10, #0x0\n\t"
  32131. "UMLAL r11, r10, r0, r6\n\t"
  32132. "UMAAL r12, r10, r1, r6\n\t"
  32133. "STR r11, [sp, #28]\n\t"
  32134. "UMAAL r4, r10, r2, r6\n\t"
  32135. "UMAAL r5, r10, r3, r6\n\t"
  32136. "LDM lr!, {r11}\n\t"
  32137. "UMAAL r12, r7, r0, r11\n\t"
  32138. "UMAAL r4, r7, r1, r11\n\t"
  32139. "LDR r6, [sp, #64]\n\t"
  32140. "UMAAL r5, r7, r2, r11\n\t"
  32141. "UMAAL r6, r7, r3, r11\n\t"
  32142. "LDM lr!, {r11}\n\t"
  32143. "UMAAL r4, r8, r0, r11\n\t"
  32144. "UMAAL r5, r8, r1, r11\n\t"
  32145. "UMAAL r6, r8, r2, r11\n\t"
  32146. "UMAAL r7, r8, r3, r11\n\t"
  32147. "LDM lr, {r11, lr}\n\t"
  32148. "UMAAL r5, r9, r0, r11\n\t"
  32149. "UMAAL r6, r10, r0, lr\n\t"
  32150. "UMAAL r6, r9, r1, r11\n\t"
  32151. "UMAAL r7, r10, r1, lr\n\t"
  32152. "UMAAL r7, r9, r2, r11\n\t"
  32153. "UMAAL r8, r10, r2, lr\n\t"
  32154. "UMAAL r8, r9, r3, r11\n\t"
  32155. "UMAAL r9, r10, r3, lr\n\t"
  32156. "MOV r3, r12\n\t"
  32157. "ADD lr, sp, #0x20\n\t"
  32158. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  32159. /* Start Reduction */
  32160. "LDM sp, {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  32161. "MOV r3, r11\n\t"
  32162. "MOV r4, r12\n\t"
  32163. /* mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192 */
  32164. /* - a[0] << 224 */
  32165. /* + (a[0]-a[1] * 2) << (6 * 32) */
  32166. "ADDS r11, r11, r5\n\t"
  32167. "ADC r12, r12, r6\n\t"
  32168. "ADDS r11, r11, r5\n\t"
  32169. "ADC r12, r12, r6\n\t"
  32170. /* - a[0] << (7 * 32) */
  32171. "SUB r12, r12, r5\n\t"
  32172. /* + a[0]-a[4] << (3 * 32) */
  32173. "MOV r0, r8\n\t"
  32174. "MOV r1, r9\n\t"
  32175. "MOV r2, r10\n\t"
  32176. "ADDS r8, r8, r5\n\t"
  32177. "ADCS r9, r9, r6\n\t"
  32178. "ADCS r10, r10, r7\n\t"
  32179. "ADCS r11, r11, r0\n\t"
  32180. "ADC r12, r12, r1\n\t"
  32181. /* a += mu * m */
  32182. /* += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1) */
  32183. /* a[0] = = t[0] */
  32184. /* a[1] = = t[1] */
  32185. /* a[2] = = t[2] */
  32186. /* a[3] += t[0] = t[3] */
  32187. /* a[4] += t[1] = t[4] */
  32188. /* a[5] += t[2] = t[5] */
  32189. /* a[6] += t[0] + t[3] = t[6] */
  32190. /* a[7] += t[1] + t[4] = t[7] + t[0] */
  32191. "ADDS r0, r0, r5\n\t"
  32192. "ADCS r1, r1, r6\n\t"
  32193. "ADCS r2, r2, r7\n\t"
  32194. "ADCS r3, r3, r8\n\t"
  32195. "ADCS r4, r4, r9\n\t"
  32196. "MOV lr, #0x0\n\t"
  32197. "ADC lr, lr, #0x0\n\t"
  32198. "ADDS r3, r3, r5\n\t"
  32199. "ADCS r4, r4, r6\n\t"
  32200. "ADC lr, lr, #0x0\n\t"
  32201. "STR r4, [sp, #28]\n\t"
  32202. /* a[8] += t[0] + t[2] + t[5] */
  32203. /* a[9] += t[1] + t[3] + t[6] */
  32204. /* a[10] += t[2] + t[4] + t[7] */
  32205. "ADD r0, sp, #0x20\n\t"
  32206. "LDM r0, {r2, r3, r4}\n\t"
  32207. "ADDS r2, r2, lr\n\t"
  32208. "ADCS r3, r3, #0x0\n\t"
  32209. "ADCS r4, r4, #0x0\n\t"
  32210. "MOV lr, #0x0\n\t"
  32211. "ADC lr, lr, #0x0\n\t"
  32212. "ADDS r2, r2, r5\n\t"
  32213. "ADCS r3, r3, r6\n\t"
  32214. "ADCS r4, r4, r7\n\t"
  32215. "ADC lr, lr, #0x0\n\t"
  32216. "ADDS r2, r2, r7\n\t"
  32217. "ADCS r3, r3, r8\n\t"
  32218. "ADCS r4, r4, r9\n\t"
  32219. "ADC lr, lr, #0x0\n\t"
  32220. "ADDS r2, r2, r10\n\t"
  32221. "ADCS r3, r3, r11\n\t"
  32222. "ADCS r4, r4, r12\n\t"
  32223. "ADC lr, lr, #0x0\n\t"
  32224. "STM r0!, {r2, r3, r4}\n\t"
  32225. /* a[11] += t[3] + t[5] + carry */
  32226. /* a[12] += t[4] + t[6] */
  32227. /* a[13] += t[5] + t[7] */
  32228. /* a[14] += t[6] */
  32229. /* a[15] += t[7] */
  32230. "LDM r0, {r0, r1, r2, r3, r4}\n\t"
  32231. "ADDS r0, r0, lr\n\t"
  32232. "ADCS r1, r1, #0x0\n\t"
  32233. "ADCS r2, r2, #0x0\n\t"
  32234. "ADCS r3, r3, #0x0\n\t"
  32235. "ADCS r4, r4, #0x0\n\t"
  32236. "MOV lr, #0x0\n\t"
  32237. "ADC lr, lr, #0x0\n\t"
  32238. "ADDS r0, r0, r8\n\t"
  32239. "ADCS r1, r1, r9\n\t"
  32240. "ADCS r2, r2, r10\n\t"
  32241. "ADCS r3, r3, r11\n\t"
  32242. "ADCS r4, r4, r12\n\t"
  32243. "ADC lr, lr, #0x0\n\t"
  32244. "ADDS r0, r0, r10\n\t"
  32245. "ADCS r1, r1, r11\n\t"
  32246. "ADCS r2, r2, r12\n\t"
  32247. "ADCS r3, r3, #0x0\n\t"
  32248. "ADCS r4, r4, #0x0\n\t"
  32249. "ADC lr, lr, #0x0\n\t"
  32250. "STR r0, [sp, #44]\n\t"
  32251. "STR r1, [sp, #48]\n\t"
  32252. "STR r2, [sp, #52]\n\t"
  32253. "STR r3, [sp, #56]\n\t"
  32254. /* a[7..15] - t[0..7] */
  32255. "ADD r0, sp, #0x1c\n\t"
  32256. "LDM r0, {r0, r1, r2, r3}\n\t"
  32257. "SUBS r0, r0, r5\n\t"
  32258. "SBCS r1, r1, r6\n\t"
  32259. "SBCS r2, r2, r7\n\t"
  32260. "SBCS r3, r3, r8\n\t"
  32261. "ADD r0, sp, #0x2c\n\t"
  32262. "MOV r8, r4\n\t"
  32263. "LDM r0, {r4, r5, r6, r7}\n\t"
  32264. "SBCS r4, r4, r9\n\t"
  32265. "SBCS r5, r5, r10\n\t"
  32266. "SBCS r6, r6, r11\n\t"
  32267. "SBCS r7, r7, r12\n\t"
  32268. "SBCS r8, r8, #0x0\n\t"
  32269. "SBC lr, lr, #0x0\n\t"
  32270. /* mask m and sub from result if overflow */
  32271. "RSB lr, lr, #0x0\n\t"
  32272. "SUBS r1, r1, lr\n\t"
  32273. "SBCS r2, r2, lr\n\t"
  32274. "SBCS r3, r3, lr\n\t"
  32275. "SBCS r4, r4, #0x0\n\t"
  32276. "SBCS r5, r5, #0x0\n\t"
  32277. "SBCS r6, r6, #0x0\n\t"
  32278. "SBCS r7, r7, lr, LSR #31\n\t"
  32279. "SBC r8, r8, lr\n\t"
  32280. "LDR %[r], [sp, #68]\n\t"
  32281. "STM %[r], {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  32282. "ADD sp, sp, #0x4c\n\t"
  32283. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  32284. :
  32285. : "memory", "r3", "r4", "r5", "r6", "r10", "r11", "r12", "r7", "r8", "r9", "lr", "cc"
  32286. );
  32287. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32288. (void)m_p;
  32289. #else
  32290. (void)m;
  32291. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32292. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32293. (void)mp_p;
  32294. #else
  32295. (void)mp;
  32296. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32297. }
  32298. #endif
  32299. #ifdef WOLFSSL_SP_NO_UMAAL
  32300. /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
  32301. *
  32302. * r Result of squaring.
  32303. * a Number to square in Montgomery form.
  32304. * m Modulus (prime).
  32305. * mp Montgomery multiplier.
  32306. */
  32307. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32308. SP_NOINLINE static void sp_256_mont_sqr_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  32309. #else
  32310. SP_NOINLINE static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a, const sp_digit* m, sp_digit mp)
  32311. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32312. {
  32313. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32314. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  32315. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  32316. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32317. __asm__ __volatile__ (
  32318. "SUB sp, sp, #0x44\n\t"
  32319. "STR %[r], [sp, #64]\n\t"
  32320. "MOV %[r], #0x0\n\t"
  32321. "LDR r12, [%[a]]\n\t"
  32322. /* A[0] * A[1] */
  32323. "LDR lr, [%[a], #4]\n\t"
  32324. "UMULL r4, r5, r12, lr\n\t"
  32325. /* A[0] * A[3] */
  32326. "LDR lr, [%[a], #12]\n\t"
  32327. "UMULL r6, r7, r12, lr\n\t"
  32328. /* A[0] * A[5] */
  32329. "LDR lr, [%[a], #20]\n\t"
  32330. "UMULL r8, r9, r12, lr\n\t"
  32331. /* A[0] * A[7] */
  32332. "LDR lr, [%[a], #28]\n\t"
  32333. "UMULL r10, r3, r12, lr\n\t"
  32334. /* A[0] * A[2] */
  32335. "LDR lr, [%[a], #8]\n\t"
  32336. "MOV r11, #0x0\n\t"
  32337. "UMLAL r5, r11, r12, lr\n\t"
  32338. "ADDS r6, r6, r11\n\t"
  32339. /* A[0] * A[4] */
  32340. "LDR lr, [%[a], #16]\n\t"
  32341. "ADCS r7, r7, #0x0\n\t"
  32342. "ADC r11, %[r], #0x0\n\t"
  32343. "UMLAL r7, r11, r12, lr\n\t"
  32344. "ADDS r8, r8, r11\n\t"
  32345. /* A[0] * A[6] */
  32346. "LDR lr, [%[a], #24]\n\t"
  32347. "ADCS r9, r9, #0x0\n\t"
  32348. "ADC r11, %[r], #0x0\n\t"
  32349. "UMLAL r9, r11, r12, lr\n\t"
  32350. "ADDS r10, r10, r11\n\t"
  32351. "ADCS r3, r3, #0x0\n\t"
  32352. "STR r4, [sp, #4]\n\t"
  32353. "STR r5, [sp, #8]\n\t"
  32354. /* A[1] * A[2] */
  32355. "LDR r12, [%[a], #4]\n\t"
  32356. "LDR lr, [%[a], #8]\n\t"
  32357. "MOV r11, #0x0\n\t"
  32358. "UMLAL r6, r11, r12, lr\n\t"
  32359. "STR r6, [sp, #12]\n\t"
  32360. "ADDS r7, r7, r11\n\t"
  32361. /* A[1] * A[3] */
  32362. "LDR lr, [%[a], #12]\n\t"
  32363. "ADC r11, %[r], #0x0\n\t"
  32364. "UMLAL r7, r11, r12, lr\n\t"
  32365. "STR r7, [sp, #16]\n\t"
  32366. "ADDS r8, r8, r11\n\t"
  32367. /* A[1] * A[4] */
  32368. "LDR lr, [%[a], #16]\n\t"
  32369. "ADC r11, %[r], #0x0\n\t"
  32370. "UMLAL r8, r11, r12, lr\n\t"
  32371. "ADDS r9, r9, r11\n\t"
  32372. /* A[1] * A[5] */
  32373. "LDR lr, [%[a], #20]\n\t"
  32374. "ADC r11, %[r], #0x0\n\t"
  32375. "UMLAL r9, r11, r12, lr\n\t"
  32376. "ADDS r10, r10, r11\n\t"
  32377. /* A[1] * A[6] */
  32378. "LDR lr, [%[a], #24]\n\t"
  32379. "ADC r11, %[r], #0x0\n\t"
  32380. "UMLAL r10, r11, r12, lr\n\t"
  32381. "ADDS r3, r3, r11\n\t"
  32382. /* A[1] * A[7] */
  32383. "LDR lr, [%[a], #28]\n\t"
  32384. "ADC r4, %[r], #0x0\n\t"
  32385. "UMLAL r3, r4, r12, lr\n\t"
  32386. /* A[2] * A[3] */
  32387. "LDR r12, [%[a], #8]\n\t"
  32388. "LDR lr, [%[a], #12]\n\t"
  32389. "MOV r11, #0x0\n\t"
  32390. "UMLAL r8, r11, r12, lr\n\t"
  32391. "STR r8, [sp, #20]\n\t"
  32392. "ADDS r9, r9, r11\n\t"
  32393. /* A[2] * A[4] */
  32394. "LDR lr, [%[a], #16]\n\t"
  32395. "ADC r11, %[r], #0x0\n\t"
  32396. "UMLAL r9, r11, r12, lr\n\t"
  32397. "STR r9, [sp, #24]\n\t"
  32398. "ADDS r10, r10, r11\n\t"
  32399. /* A[2] * A[5] */
  32400. "LDR lr, [%[a], #20]\n\t"
  32401. "ADC r11, %[r], #0x0\n\t"
  32402. "UMLAL r10, r11, r12, lr\n\t"
  32403. "ADDS r3, r3, r11\n\t"
  32404. /* A[2] * A[6] */
  32405. "LDR lr, [%[a], #24]\n\t"
  32406. "ADC r11, %[r], #0x0\n\t"
  32407. "UMLAL r3, r11, r12, lr\n\t"
  32408. "ADDS r4, r4, r11\n\t"
  32409. /* A[2] * A[7] */
  32410. "LDR lr, [%[a], #28]\n\t"
  32411. "ADC r5, %[r], #0x0\n\t"
  32412. "UMLAL r4, r5, r12, lr\n\t"
  32413. /* A[3] * A[4] */
  32414. "LDR r12, [%[a], #12]\n\t"
  32415. "LDR lr, [%[a], #16]\n\t"
  32416. "MOV r11, #0x0\n\t"
  32417. "UMLAL r10, r11, r12, lr\n\t"
  32418. "STR r10, [sp, #28]\n\t"
  32419. "ADDS r3, r3, r11\n\t"
  32420. /* A[3] * A[5] */
  32421. "LDR lr, [%[a], #20]\n\t"
  32422. "ADC r11, %[r], #0x0\n\t"
  32423. "UMLAL r3, r11, r12, lr\n\t"
  32424. "ADDS r4, r4, r11\n\t"
  32425. /* A[3] * A[6] */
  32426. "LDR lr, [%[a], #24]\n\t"
  32427. "ADC r11, %[r], #0x0\n\t"
  32428. "UMLAL r4, r11, r12, lr\n\t"
  32429. "ADDS r5, r5, r11\n\t"
  32430. /* A[3] * A[7] */
  32431. "LDR lr, [%[a], #28]\n\t"
  32432. "ADC r6, %[r], #0x0\n\t"
  32433. "UMLAL r5, r6, r12, lr\n\t"
  32434. /* A[4] * A[5] */
  32435. "LDR r12, [%[a], #16]\n\t"
  32436. "LDR lr, [%[a], #20]\n\t"
  32437. "MOV r11, #0x0\n\t"
  32438. "UMLAL r4, r11, r12, lr\n\t"
  32439. "ADDS r5, r5, r11\n\t"
  32440. /* A[4] * A[6] */
  32441. "LDR lr, [%[a], #24]\n\t"
  32442. "ADC r11, %[r], #0x0\n\t"
  32443. "UMLAL r5, r11, r12, lr\n\t"
  32444. "ADDS r6, r6, r11\n\t"
  32445. /* A[4] * A[7] */
  32446. "LDR lr, [%[a], #28]\n\t"
  32447. "ADC r7, %[r], #0x0\n\t"
  32448. "UMLAL r6, r7, r12, lr\n\t"
  32449. /* A[5] * A[6] */
  32450. "LDR r12, [%[a], #20]\n\t"
  32451. "LDR lr, [%[a], #24]\n\t"
  32452. "MOV r11, #0x0\n\t"
  32453. "UMLAL r6, r11, r12, lr\n\t"
  32454. "ADDS r7, r7, r11\n\t"
  32455. /* A[5] * A[7] */
  32456. "LDR lr, [%[a], #28]\n\t"
  32457. "ADC r8, %[r], #0x0\n\t"
  32458. "UMLAL r7, r8, r12, lr\n\t"
  32459. /* A[6] * A[7] */
  32460. "LDR r12, [%[a], #24]\n\t"
  32461. "LDR lr, [%[a], #28]\n\t"
  32462. "MOV r9, #0x0\n\t"
  32463. "UMLAL r8, r9, r12, lr\n\t"
  32464. "ADD lr, sp, #0x20\n\t"
  32465. "STM lr, {r3, r4, r5, r6, r7, r8, r9}\n\t"
  32466. "ADD lr, sp, #0x4\n\t"
  32467. "LDM lr, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  32468. "ADDS r4, r4, r4\n\t"
  32469. "ADCS r5, r5, r5\n\t"
  32470. "ADCS r6, r6, r6\n\t"
  32471. "ADCS r7, r7, r7\n\t"
  32472. "ADCS r8, r8, r8\n\t"
  32473. "ADCS r9, r9, r9\n\t"
  32474. "ADCS r10, r10, r10\n\t"
  32475. "STM lr!, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  32476. "LDM lr, {r3, r4, r5, r6, r7, r8, r9}\n\t"
  32477. "ADCS r3, r3, r3\n\t"
  32478. "ADCS r4, r4, r4\n\t"
  32479. "ADCS r5, r5, r5\n\t"
  32480. "ADCS r6, r6, r6\n\t"
  32481. "ADCS r7, r7, r7\n\t"
  32482. "ADCS r8, r8, r8\n\t"
  32483. "ADCS r9, r9, r9\n\t"
  32484. "ADC r10, %[r], #0x0\n\t"
  32485. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  32486. "ADD lr, sp, #0x4\n\t"
  32487. "LDM lr, {r4, r5, r6, r7, r8, r9, r10}\n\t"
  32488. "MOV lr, sp\n\t"
  32489. /* A[0] * A[0] */
  32490. "LDR r12, [%[a]]\n\t"
  32491. "UMULL r3, r11, r12, r12\n\t"
  32492. "ADDS r4, r4, r11\n\t"
  32493. /* A[1] * A[1] */
  32494. "LDR r12, [%[a], #4]\n\t"
  32495. "ADCS r5, r5, #0x0\n\t"
  32496. "ADC r11, %[r], #0x0\n\t"
  32497. "UMLAL r5, r11, r12, r12\n\t"
  32498. "ADDS r6, r6, r11\n\t"
  32499. /* A[2] * A[2] */
  32500. "LDR r12, [%[a], #8]\n\t"
  32501. "ADCS r7, r7, #0x0\n\t"
  32502. "ADC r11, %[r], #0x0\n\t"
  32503. "UMLAL r7, r11, r12, r12\n\t"
  32504. "ADDS r8, r8, r11\n\t"
  32505. /* A[3] * A[3] */
  32506. "LDR r12, [%[a], #12]\n\t"
  32507. "ADCS r9, r9, #0x0\n\t"
  32508. "ADC r11, %[r], #0x0\n\t"
  32509. "UMLAL r9, r11, r12, r12\n\t"
  32510. "ADDS r10, r10, r11\n\t"
  32511. "STM lr!, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  32512. "LDM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  32513. /* A[4] * A[4] */
  32514. "LDR r12, [%[a], #16]\n\t"
  32515. "ADCS r3, r3, #0x0\n\t"
  32516. "ADC r11, %[r], #0x0\n\t"
  32517. "UMLAL r3, r11, r12, r12\n\t"
  32518. "ADDS r4, r4, r11\n\t"
  32519. /* A[5] * A[5] */
  32520. "LDR r12, [%[a], #20]\n\t"
  32521. "ADCS r5, r5, #0x0\n\t"
  32522. "ADC r11, %[r], #0x0\n\t"
  32523. "UMLAL r5, r11, r12, r12\n\t"
  32524. "ADDS r6, r6, r11\n\t"
  32525. /* A[6] * A[6] */
  32526. "LDR r12, [%[a], #24]\n\t"
  32527. "ADCS r7, r7, #0x0\n\t"
  32528. "ADC r11, %[r], #0x0\n\t"
  32529. "UMLAL r7, r11, r12, r12\n\t"
  32530. "ADDS r8, r8, r11\n\t"
  32531. /* A[7] * A[7] */
  32532. "LDR r12, [%[a], #28]\n\t"
  32533. "ADCS r9, r9, #0x0\n\t"
  32534. "ADC r10, r10, #0x0\n\t"
  32535. "UMLAL r9, r10, r12, r12\n\t"
  32536. "ADD lr, sp, #0x20\n\t"
  32537. "STM lr, {r3, r4, r5, r6, r7, r8, r9, r10}\n\t"
  32538. /* Start Reduction */
  32539. "LDM sp, {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  32540. "MOV r3, r11\n\t"
  32541. "MOV r4, r12\n\t"
  32542. /* mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192 */
  32543. /* - a[0] << 224 */
  32544. /* + (a[0]-a[1] * 2) << (6 * 32) */
  32545. "ADDS r11, r11, r5\n\t"
  32546. "ADC r12, r12, r6\n\t"
  32547. "ADDS r11, r11, r5\n\t"
  32548. "ADC r12, r12, r6\n\t"
  32549. /* - a[0] << (7 * 32) */
  32550. "SUB r12, r12, r5\n\t"
  32551. /* + a[0]-a[4] << (3 * 32) */
  32552. "MOV r0, r8\n\t"
  32553. "MOV r1, r9\n\t"
  32554. "MOV r2, r10\n\t"
  32555. "ADDS r8, r8, r5\n\t"
  32556. "ADCS r9, r9, r6\n\t"
  32557. "ADCS r10, r10, r7\n\t"
  32558. "ADCS r11, r11, r0\n\t"
  32559. "ADC r12, r12, r1\n\t"
  32560. /* a += mu * m */
  32561. /* += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1) */
  32562. /* a[0] = = t[0] */
  32563. /* a[1] = = t[1] */
  32564. /* a[2] = = t[2] */
  32565. /* a[3] += t[0] = t[3] */
  32566. /* a[4] += t[1] = t[4] */
  32567. /* a[5] += t[2] = t[5] */
  32568. /* a[6] += t[0] + t[3] = t[6] */
  32569. /* a[7] += t[1] + t[4] = t[7] + t[0] */
  32570. "ADDS r0, r0, r5\n\t"
  32571. "ADCS r1, r1, r6\n\t"
  32572. "ADCS r2, r2, r7\n\t"
  32573. "ADCS r3, r3, r8\n\t"
  32574. "ADCS r4, r4, r9\n\t"
  32575. "MOV lr, #0x0\n\t"
  32576. "ADC lr, lr, #0x0\n\t"
  32577. "ADDS r3, r3, r5\n\t"
  32578. "ADCS r4, r4, r6\n\t"
  32579. "ADC lr, lr, #0x0\n\t"
  32580. "STR r4, [sp, #28]\n\t"
  32581. /* a[8] += t[0] + t[2] + t[5] */
  32582. /* a[9] += t[1] + t[3] + t[6] */
  32583. /* a[10] += t[2] + t[4] + t[7] */
  32584. "ADD r0, sp, #0x20\n\t"
  32585. "LDM r0, {r2, r3, r4}\n\t"
  32586. "ADDS r2, r2, lr\n\t"
  32587. "ADCS r3, r3, #0x0\n\t"
  32588. "ADCS r4, r4, #0x0\n\t"
  32589. "MOV lr, #0x0\n\t"
  32590. "ADC lr, lr, #0x0\n\t"
  32591. "ADDS r2, r2, r5\n\t"
  32592. "ADCS r3, r3, r6\n\t"
  32593. "ADCS r4, r4, r7\n\t"
  32594. "ADC lr, lr, #0x0\n\t"
  32595. "ADDS r2, r2, r7\n\t"
  32596. "ADCS r3, r3, r8\n\t"
  32597. "ADCS r4, r4, r9\n\t"
  32598. "ADC lr, lr, #0x0\n\t"
  32599. "ADDS r2, r2, r10\n\t"
  32600. "ADCS r3, r3, r11\n\t"
  32601. "ADCS r4, r4, r12\n\t"
  32602. "ADC lr, lr, #0x0\n\t"
  32603. "STM r0!, {r2, r3, r4}\n\t"
  32604. /* a[11] += t[3] + t[5] + carry */
  32605. /* a[12] += t[4] + t[6] */
  32606. /* a[13] += t[5] + t[7] */
  32607. /* a[14] += t[6] */
  32608. /* a[15] += t[7] */
  32609. "LDM r0, {r0, r1, r2, r3, r4}\n\t"
  32610. "ADDS r0, r0, lr\n\t"
  32611. "ADCS r1, r1, #0x0\n\t"
  32612. "ADCS r2, r2, #0x0\n\t"
  32613. "ADCS r3, r3, #0x0\n\t"
  32614. "ADCS r4, r4, #0x0\n\t"
  32615. "MOV lr, #0x0\n\t"
  32616. "ADC lr, lr, #0x0\n\t"
  32617. "ADDS r0, r0, r8\n\t"
  32618. "ADCS r1, r1, r9\n\t"
  32619. "ADCS r2, r2, r10\n\t"
  32620. "ADCS r3, r3, r11\n\t"
  32621. "ADCS r4, r4, r12\n\t"
  32622. "ADC lr, lr, #0x0\n\t"
  32623. "ADDS r0, r0, r10\n\t"
  32624. "ADCS r1, r1, r11\n\t"
  32625. "ADCS r2, r2, r12\n\t"
  32626. "ADCS r3, r3, #0x0\n\t"
  32627. "ADCS r4, r4, #0x0\n\t"
  32628. "ADC lr, lr, #0x0\n\t"
  32629. "STR r0, [sp, #44]\n\t"
  32630. "STR r1, [sp, #48]\n\t"
  32631. "STR r2, [sp, #52]\n\t"
  32632. "STR r3, [sp, #56]\n\t"
  32633. /* a[7..15] - t[0..7] */
  32634. "ADD r0, sp, #0x1c\n\t"
  32635. "LDM r0, {r0, r1, r2, r3}\n\t"
  32636. "SUBS r0, r0, r5\n\t"
  32637. "SBCS r1, r1, r6\n\t"
  32638. "SBCS r2, r2, r7\n\t"
  32639. "SBCS r3, r3, r8\n\t"
  32640. "ADD r0, sp, #0x2c\n\t"
  32641. "MOV r8, r4\n\t"
  32642. "LDM r0, {r4, r5, r6, r7}\n\t"
  32643. "SBCS r4, r4, r9\n\t"
  32644. "SBCS r5, r5, r10\n\t"
  32645. "SBCS r6, r6, r11\n\t"
  32646. "SBCS r7, r7, r12\n\t"
  32647. "SBCS r8, r8, #0x0\n\t"
  32648. "SBC lr, lr, #0x0\n\t"
  32649. /* mask m and sub from result if overflow */
  32650. "RSB lr, lr, #0x0\n\t"
  32651. "SUBS r1, r1, lr\n\t"
  32652. "SBCS r2, r2, lr\n\t"
  32653. "SBCS r3, r3, lr\n\t"
  32654. "SBCS r4, r4, #0x0\n\t"
  32655. "SBCS r5, r5, #0x0\n\t"
  32656. "SBCS r6, r6, #0x0\n\t"
  32657. "SBCS r7, r7, lr, LSR #31\n\t"
  32658. "SBC r8, r8, lr\n\t"
  32659. "LDR %[r], [sp, #64]\n\t"
  32660. "STM %[r], {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  32661. "ADD sp, sp, #0x44\n\t"
  32662. : [r] "+r" (r), [a] "+r" (a)
  32663. :
  32664. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  32665. );
  32666. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32667. (void)m_p;
  32668. #else
  32669. (void)m;
  32670. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32671. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32672. (void)mp_p;
  32673. #else
  32674. (void)mp;
  32675. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32676. }
  32677. #else
  32678. /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
  32679. *
  32680. * r Result of squaring.
  32681. * a Number to square in Montgomery form.
  32682. * m Modulus (prime).
  32683. * mp Montgomery multiplier.
  32684. */
  32685. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32686. SP_NOINLINE static void sp_256_mont_sqr_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  32687. #else
  32688. SP_NOINLINE static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a, const sp_digit* m, sp_digit mp)
  32689. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32690. {
  32691. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32692. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  32693. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  32694. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32695. __asm__ __volatile__ (
  32696. "SUB sp, sp, #0x44\n\t"
  32697. "STR %[r], [sp, #64]\n\t"
  32698. "LDM %[a], {r0, r1, r2, r3, r4, r5, r6, r7}\n\t"
  32699. "UMULL r9, r10, r0, r0\n\t"
  32700. "UMULL r11, r12, r0, r1\n\t"
  32701. "ADDS r11, r11, r11\n\t"
  32702. "MOV lr, #0x0\n\t"
  32703. "UMAAL r10, r11, lr, lr\n\t"
  32704. "STM sp, {r9, r10}\n\t"
  32705. "MOV r8, lr\n\t"
  32706. "UMAAL r8, r12, r0, r2\n\t"
  32707. "ADCS r8, r8, r8\n\t"
  32708. "UMAAL r8, r11, r1, r1\n\t"
  32709. "UMULL r9, r10, r0, r3\n\t"
  32710. "UMAAL r9, r12, r1, r2\n\t"
  32711. "ADCS r9, r9, r9\n\t"
  32712. "UMAAL r9, r11, lr, lr\n\t"
  32713. "STRD r8, r9, [sp, #8]\n\t"
  32714. "MOV r9, lr\n\t"
  32715. "UMAAL r9, r10, r0, r4\n\t"
  32716. "UMAAL r9, r12, r1, r3\n\t"
  32717. "ADCS r9, r9, r9\n\t"
  32718. "UMAAL r9, r11, r2, r2\n\t"
  32719. "STR r9, [sp, #16]\n\t"
  32720. "UMULL r9, r8, r0, r5\n\t"
  32721. "UMAAL r9, r12, r1, r4\n\t"
  32722. "UMAAL r9, r10, r2, r3\n\t"
  32723. "ADCS r9, r9, r9\n\t"
  32724. "UMAAL r9, r11, lr, lr\n\t"
  32725. "STR r9, [sp, #20]\n\t"
  32726. "MOV r9, lr\n\t"
  32727. "UMAAL r9, r8, r0, r6\n\t"
  32728. "UMAAL r9, r12, r1, r5\n\t"
  32729. "UMAAL r9, r10, r2, r4\n\t"
  32730. "ADCS r9, r9, r9\n\t"
  32731. "UMAAL r9, r11, r3, r3\n\t"
  32732. "STR r9, [sp, #24]\n\t"
  32733. "UMULL r0, r9, r0, r7\n\t"
  32734. "UMAAL r0, r8, r1, r6\n\t"
  32735. "UMAAL r0, r12, r2, r5\n\t"
  32736. "UMAAL r0, r10, r3, r4\n\t"
  32737. "ADCS r0, r0, r0\n\t"
  32738. "UMAAL r0, r11, lr, lr\n\t"
  32739. /* R[7] = r0 */
  32740. "UMAAL r9, r8, r1, r7\n\t"
  32741. "UMAAL r9, r10, r2, r6\n\t"
  32742. "UMAAL r12, r9, r3, r5\n\t"
  32743. "ADCS r12, r12, r12\n\t"
  32744. "UMAAL r12, r11, r4, r4\n\t"
  32745. /* R[8] = r12 */
  32746. "UMAAL r9, r8, r2, r7\n\t"
  32747. "UMAAL r10, r9, r3, r6\n\t"
  32748. "MOV r2, lr\n\t"
  32749. "UMAAL r10, r2, r4, r5\n\t"
  32750. "ADCS r10, r10, r10\n\t"
  32751. "UMAAL r11, r10, lr, lr\n\t"
  32752. /* R[9] = r11 */
  32753. "UMAAL r2, r8, r3, r7\n\t"
  32754. "UMAAL r2, r9, r4, r6\n\t"
  32755. "ADCS r3, r2, r2\n\t"
  32756. "UMAAL r10, r3, r5, r5\n\t"
  32757. /* R[10] = r10 */
  32758. "MOV r1, lr\n\t"
  32759. "UMAAL r1, r8, r4, r7\n\t"
  32760. "UMAAL r1, r9, r5, r6\n\t"
  32761. "ADCS r4, r1, r1\n\t"
  32762. "UMAAL r3, r4, lr, lr\n\t"
  32763. /* R[11] = r3 */
  32764. "UMAAL r8, r9, r5, r7\n\t"
  32765. "ADCS r8, r8, r8\n\t"
  32766. "UMAAL r4, r8, r6, r6\n\t"
  32767. /* R[12] = r4 */
  32768. "MOV r5, lr\n\t"
  32769. "UMAAL r5, r9, r6, r7\n\t"
  32770. "ADCS r5, r5, r5\n\t"
  32771. "UMAAL r8, r5, lr, lr\n\t"
  32772. /* R[13] = r8 */
  32773. "ADCS r9, r9, r9\n\t"
  32774. "UMAAL r9, r5, r7, r7\n\t"
  32775. "ADCS r7, r5, lr\n\t"
  32776. /* R[14] = r9 */
  32777. /* R[15] = r7 */
  32778. "MOV lr, sp\n\t"
  32779. "ADD lr, lr, #0x1c\n\t"
  32780. "STM lr!, {r0, r12}\n\t"
  32781. "STM lr!, {r11}\n\t"
  32782. "STM lr!, {r10}\n\t"
  32783. "STM lr!, {r3, r4, r8, r9}\n\t"
  32784. "STM lr!, {r7}\n\t"
  32785. /* Start Reduction */
  32786. "LDM sp, {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  32787. "MOV r3, r11\n\t"
  32788. "MOV r4, r12\n\t"
  32789. /* mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192 */
  32790. /* - a[0] << 224 */
  32791. /* + (a[0]-a[1] * 2) << (6 * 32) */
  32792. "ADDS r11, r11, r5\n\t"
  32793. "ADC r12, r12, r6\n\t"
  32794. "ADDS r11, r11, r5\n\t"
  32795. "ADC r12, r12, r6\n\t"
  32796. /* - a[0] << (7 * 32) */
  32797. "SUB r12, r12, r5\n\t"
  32798. /* + a[0]-a[4] << (3 * 32) */
  32799. "MOV r0, r8\n\t"
  32800. "MOV r1, r9\n\t"
  32801. "MOV r2, r10\n\t"
  32802. "ADDS r8, r8, r5\n\t"
  32803. "ADCS r9, r9, r6\n\t"
  32804. "ADCS r10, r10, r7\n\t"
  32805. "ADCS r11, r11, r0\n\t"
  32806. "ADC r12, r12, r1\n\t"
  32807. /* a += mu * m */
  32808. /* += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1) */
  32809. /* a[0] = = t[0] */
  32810. /* a[1] = = t[1] */
  32811. /* a[2] = = t[2] */
  32812. /* a[3] += t[0] = t[3] */
  32813. /* a[4] += t[1] = t[4] */
  32814. /* a[5] += t[2] = t[5] */
  32815. /* a[6] += t[0] + t[3] = t[6] */
  32816. /* a[7] += t[1] + t[4] = t[7] + t[0] */
  32817. "ADDS r0, r0, r5\n\t"
  32818. "ADCS r1, r1, r6\n\t"
  32819. "ADCS r2, r2, r7\n\t"
  32820. "ADCS r3, r3, r8\n\t"
  32821. "ADCS r4, r4, r9\n\t"
  32822. "MOV lr, #0x0\n\t"
  32823. "ADC lr, lr, #0x0\n\t"
  32824. "ADDS r3, r3, r5\n\t"
  32825. "ADCS r4, r4, r6\n\t"
  32826. "ADC lr, lr, #0x0\n\t"
  32827. "STR r4, [sp, #28]\n\t"
  32828. /* a[8] += t[0] + t[2] + t[5] */
  32829. /* a[9] += t[1] + t[3] + t[6] */
  32830. /* a[10] += t[2] + t[4] + t[7] */
  32831. "ADD r0, sp, #0x20\n\t"
  32832. "LDM r0, {r2, r3, r4}\n\t"
  32833. "ADDS r2, r2, lr\n\t"
  32834. "ADCS r3, r3, #0x0\n\t"
  32835. "ADCS r4, r4, #0x0\n\t"
  32836. "MOV lr, #0x0\n\t"
  32837. "ADC lr, lr, #0x0\n\t"
  32838. "ADDS r2, r2, r5\n\t"
  32839. "ADCS r3, r3, r6\n\t"
  32840. "ADCS r4, r4, r7\n\t"
  32841. "ADC lr, lr, #0x0\n\t"
  32842. "ADDS r2, r2, r7\n\t"
  32843. "ADCS r3, r3, r8\n\t"
  32844. "ADCS r4, r4, r9\n\t"
  32845. "ADC lr, lr, #0x0\n\t"
  32846. "ADDS r2, r2, r10\n\t"
  32847. "ADCS r3, r3, r11\n\t"
  32848. "ADCS r4, r4, r12\n\t"
  32849. "ADC lr, lr, #0x0\n\t"
  32850. "STM r0!, {r2, r3, r4}\n\t"
  32851. /* a[11] += t[3] + t[5] + carry */
  32852. /* a[12] += t[4] + t[6] */
  32853. /* a[13] += t[5] + t[7] */
  32854. /* a[14] += t[6] */
  32855. /* a[15] += t[7] */
  32856. "LDM r0, {r0, r1, r2, r3, r4}\n\t"
  32857. "ADDS r0, r0, lr\n\t"
  32858. "ADCS r1, r1, #0x0\n\t"
  32859. "ADCS r2, r2, #0x0\n\t"
  32860. "ADCS r3, r3, #0x0\n\t"
  32861. "ADCS r4, r4, #0x0\n\t"
  32862. "MOV lr, #0x0\n\t"
  32863. "ADC lr, lr, #0x0\n\t"
  32864. "ADDS r0, r0, r8\n\t"
  32865. "ADCS r1, r1, r9\n\t"
  32866. "ADCS r2, r2, r10\n\t"
  32867. "ADCS r3, r3, r11\n\t"
  32868. "ADCS r4, r4, r12\n\t"
  32869. "ADC lr, lr, #0x0\n\t"
  32870. "ADDS r0, r0, r10\n\t"
  32871. "ADCS r1, r1, r11\n\t"
  32872. "ADCS r2, r2, r12\n\t"
  32873. "ADCS r3, r3, #0x0\n\t"
  32874. "ADCS r4, r4, #0x0\n\t"
  32875. "ADC lr, lr, #0x0\n\t"
  32876. "STR r0, [sp, #44]\n\t"
  32877. "STR r1, [sp, #48]\n\t"
  32878. "STR r2, [sp, #52]\n\t"
  32879. "STR r3, [sp, #56]\n\t"
  32880. /* a[7..15] - t[0..7] */
  32881. "ADD r0, sp, #0x1c\n\t"
  32882. "LDM r0, {r0, r1, r2, r3}\n\t"
  32883. "SUBS r0, r0, r5\n\t"
  32884. "SBCS r1, r1, r6\n\t"
  32885. "SBCS r2, r2, r7\n\t"
  32886. "SBCS r3, r3, r8\n\t"
  32887. "ADD r0, sp, #0x2c\n\t"
  32888. "MOV r8, r4\n\t"
  32889. "LDM r0, {r4, r5, r6, r7}\n\t"
  32890. "SBCS r4, r4, r9\n\t"
  32891. "SBCS r5, r5, r10\n\t"
  32892. "SBCS r6, r6, r11\n\t"
  32893. "SBCS r7, r7, r12\n\t"
  32894. "SBCS r8, r8, #0x0\n\t"
  32895. "SBC lr, lr, #0x0\n\t"
  32896. /* mask m and sub from result if overflow */
  32897. "RSB lr, lr, #0x0\n\t"
  32898. "SUBS r1, r1, lr\n\t"
  32899. "SBCS r2, r2, lr\n\t"
  32900. "SBCS r3, r3, lr\n\t"
  32901. "SBCS r4, r4, #0x0\n\t"
  32902. "SBCS r5, r5, #0x0\n\t"
  32903. "SBCS r6, r6, #0x0\n\t"
  32904. "SBCS r7, r7, lr, LSR #31\n\t"
  32905. "SBC r8, r8, lr\n\t"
  32906. "LDR %[r], [sp, #64]\n\t"
  32907. "STM %[r], {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  32908. "ADD sp, sp, #0x44\n\t"
  32909. : [r] "+r" (r), [a] "+r" (a)
  32910. :
  32911. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  32912. );
  32913. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32914. (void)m_p;
  32915. #else
  32916. (void)m;
  32917. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32918. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  32919. (void)mp_p;
  32920. #else
  32921. (void)mp;
  32922. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  32923. }
  32924. #endif
  32925. #if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
  32926. /* Square the Montgomery form number a number of times. (r = a ^ n mod m)
  32927. *
  32928. * r Result of squaring.
  32929. * a Number to square in Montgomery form.
  32930. * n Number of times to square.
  32931. * m Modulus (prime).
  32932. * mp Montgomery multiplier.
  32933. */
  32934. SP_NOINLINE static void sp_256_mont_sqr_n_8(sp_digit* r,
  32935. const sp_digit* a, int n, const sp_digit* m, sp_digit mp)
  32936. {
  32937. sp_256_mont_sqr_8(r, a, m, mp);
  32938. for (; n > 1; n--) {
  32939. sp_256_mont_sqr_8(r, r, m, mp);
  32940. }
  32941. }
  32942. #endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
  32943. #ifdef WOLFSSL_SP_SMALL
  32944. /* Mod-2 for the P256 curve. */
  32945. static const uint32_t p256_mod_minus_2[8] = {
  32946. 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U,
  32947. 0x00000001U,0xffffffffU
  32948. };
  32949. #endif /* !WOLFSSL_SP_SMALL */
  32950. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  32951. * P256 curve. (r = 1 / a mod m)
  32952. *
  32953. * r Inverse result.
  32954. * a Number to invert.
  32955. * td Temporary data.
  32956. */
  32957. static void sp_256_mont_inv_8(sp_digit* r, const sp_digit* a, sp_digit* td)
  32958. {
  32959. #ifdef WOLFSSL_SP_SMALL
  32960. sp_digit* t = td;
  32961. int i;
  32962. XMEMCPY(t, a, sizeof(sp_digit) * 8);
  32963. for (i=254; i>=0; i--) {
  32964. sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod);
  32965. if (p256_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
  32966. sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod);
  32967. }
  32968. XMEMCPY(r, t, sizeof(sp_digit) * 8);
  32969. #else
  32970. sp_digit* t1 = td;
  32971. sp_digit* t2 = td + 2 * 8;
  32972. sp_digit* t3 = td + 4 * 8;
  32973. /* 0x2 */
  32974. sp_256_mont_sqr_8(t1, a, p256_mod, p256_mp_mod);
  32975. /* 0x3 */
  32976. sp_256_mont_mul_8(t2, t1, a, p256_mod, p256_mp_mod);
  32977. /* 0xc */
  32978. sp_256_mont_sqr_n_8(t1, t2, 2, p256_mod, p256_mp_mod);
  32979. /* 0xd */
  32980. sp_256_mont_mul_8(t3, t1, a, p256_mod, p256_mp_mod);
  32981. /* 0xf */
  32982. sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod);
  32983. /* 0xf0 */
  32984. sp_256_mont_sqr_n_8(t1, t2, 4, p256_mod, p256_mp_mod);
  32985. /* 0xfd */
  32986. sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod);
  32987. /* 0xff */
  32988. sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod);
  32989. /* 0xff00 */
  32990. sp_256_mont_sqr_n_8(t1, t2, 8, p256_mod, p256_mp_mod);
  32991. /* 0xfffd */
  32992. sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod);
  32993. /* 0xffff */
  32994. sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod);
  32995. /* 0xffff0000 */
  32996. sp_256_mont_sqr_n_8(t1, t2, 16, p256_mod, p256_mp_mod);
  32997. /* 0xfffffffd */
  32998. sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod);
  32999. /* 0xffffffff */
  33000. sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod);
  33001. /* 0xffffffff00000000 */
  33002. sp_256_mont_sqr_n_8(t1, t2, 32, p256_mod, p256_mp_mod);
  33003. /* 0xffffffffffffffff */
  33004. sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod);
  33005. /* 0xffffffff00000001 */
  33006. sp_256_mont_mul_8(r, t1, a, p256_mod, p256_mp_mod);
  33007. /* 0xffffffff000000010000000000000000000000000000000000000000 */
  33008. sp_256_mont_sqr_n_8(r, r, 160, p256_mod, p256_mp_mod);
  33009. /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */
  33010. sp_256_mont_mul_8(r, r, t2, p256_mod, p256_mp_mod);
  33011. /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */
  33012. sp_256_mont_sqr_n_8(r, r, 32, p256_mod, p256_mp_mod);
  33013. /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */
  33014. sp_256_mont_mul_8(r, r, t3, p256_mod, p256_mp_mod);
  33015. #endif /* WOLFSSL_SP_SMALL */
  33016. }
  33017. /* Compare a with b in constant time.
  33018. *
  33019. * a A single precision integer.
  33020. * b A single precision integer.
  33021. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  33022. * respectively.
  33023. */
  33024. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33025. static sp_int32 sp_256_cmp_8(const sp_digit* a_p, const sp_digit* b_p)
  33026. #else
  33027. static sp_int32 sp_256_cmp_8(const sp_digit* a, const sp_digit* b)
  33028. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33029. {
  33030. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33031. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  33032. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  33033. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33034. __asm__ __volatile__ (
  33035. "MOV r2, #0xffffffff\n\t"
  33036. "MOV r8, #0x1\n\t"
  33037. "MOV r7, #0x0\n\t"
  33038. "MOV r3, #0xffffffff\n\t"
  33039. #ifdef WOLFSSL_SP_SMALL
  33040. "MOV r6, #0x1c\n\t"
  33041. "\n"
  33042. "L_sp_256_cmp_8_words:\n\t"
  33043. "LDR r4, [%[a], r6]\n\t"
  33044. "LDR r5, [%[b], r6]\n\t"
  33045. "AND r4, r4, r3\n\t"
  33046. "AND r5, r5, r3\n\t"
  33047. "SUBS r4, r4, r5\n\t"
  33048. "IT hi\n\t"
  33049. "movhi r2, r8\n\t"
  33050. "IT lo\n\t"
  33051. "movlo r2, r3\n\t"
  33052. "IT ne\n\t"
  33053. "movne r3, r7\n\t"
  33054. "SUBS r6, r6, #0x4\n\t"
  33055. "bcs L_sp_256_cmp_8_words\n\t"
  33056. "EOR r2, r2, r3\n\t"
  33057. #else
  33058. "LDR r4, [%[a], #28]\n\t"
  33059. "LDR r5, [%[b], #28]\n\t"
  33060. "AND r4, r4, r3\n\t"
  33061. "AND r5, r5, r3\n\t"
  33062. "SUBS r4, r4, r5\n\t"
  33063. "IT hi\n\t"
  33064. "movhi r2, r8\n\t"
  33065. "IT lo\n\t"
  33066. "movlo r2, r3\n\t"
  33067. "IT ne\n\t"
  33068. "movne r3, r7\n\t"
  33069. "LDR r4, [%[a], #24]\n\t"
  33070. "LDR r5, [%[b], #24]\n\t"
  33071. "AND r4, r4, r3\n\t"
  33072. "AND r5, r5, r3\n\t"
  33073. "SUBS r4, r4, r5\n\t"
  33074. "IT hi\n\t"
  33075. "movhi r2, r8\n\t"
  33076. "IT lo\n\t"
  33077. "movlo r2, r3\n\t"
  33078. "IT ne\n\t"
  33079. "movne r3, r7\n\t"
  33080. "LDR r4, [%[a], #20]\n\t"
  33081. "LDR r5, [%[b], #20]\n\t"
  33082. "AND r4, r4, r3\n\t"
  33083. "AND r5, r5, r3\n\t"
  33084. "SUBS r4, r4, r5\n\t"
  33085. "IT hi\n\t"
  33086. "movhi r2, r8\n\t"
  33087. "IT lo\n\t"
  33088. "movlo r2, r3\n\t"
  33089. "IT ne\n\t"
  33090. "movne r3, r7\n\t"
  33091. "LDR r4, [%[a], #16]\n\t"
  33092. "LDR r5, [%[b], #16]\n\t"
  33093. "AND r4, r4, r3\n\t"
  33094. "AND r5, r5, r3\n\t"
  33095. "SUBS r4, r4, r5\n\t"
  33096. "IT hi\n\t"
  33097. "movhi r2, r8\n\t"
  33098. "IT lo\n\t"
  33099. "movlo r2, r3\n\t"
  33100. "IT ne\n\t"
  33101. "movne r3, r7\n\t"
  33102. "LDR r4, [%[a], #12]\n\t"
  33103. "LDR r5, [%[b], #12]\n\t"
  33104. "AND r4, r4, r3\n\t"
  33105. "AND r5, r5, r3\n\t"
  33106. "SUBS r4, r4, r5\n\t"
  33107. "IT hi\n\t"
  33108. "movhi r2, r8\n\t"
  33109. "IT lo\n\t"
  33110. "movlo r2, r3\n\t"
  33111. "IT ne\n\t"
  33112. "movne r3, r7\n\t"
  33113. "LDR r4, [%[a], #8]\n\t"
  33114. "LDR r5, [%[b], #8]\n\t"
  33115. "AND r4, r4, r3\n\t"
  33116. "AND r5, r5, r3\n\t"
  33117. "SUBS r4, r4, r5\n\t"
  33118. "IT hi\n\t"
  33119. "movhi r2, r8\n\t"
  33120. "IT lo\n\t"
  33121. "movlo r2, r3\n\t"
  33122. "IT ne\n\t"
  33123. "movne r3, r7\n\t"
  33124. "LDR r4, [%[a], #4]\n\t"
  33125. "LDR r5, [%[b], #4]\n\t"
  33126. "AND r4, r4, r3\n\t"
  33127. "AND r5, r5, r3\n\t"
  33128. "SUBS r4, r4, r5\n\t"
  33129. "IT hi\n\t"
  33130. "movhi r2, r8\n\t"
  33131. "IT lo\n\t"
  33132. "movlo r2, r3\n\t"
  33133. "IT ne\n\t"
  33134. "movne r3, r7\n\t"
  33135. "LDR r4, [%[a]]\n\t"
  33136. "LDR r5, [%[b]]\n\t"
  33137. "AND r4, r4, r3\n\t"
  33138. "AND r5, r5, r3\n\t"
  33139. "SUBS r4, r4, r5\n\t"
  33140. "IT hi\n\t"
  33141. "movhi r2, r8\n\t"
  33142. "IT lo\n\t"
  33143. "movlo r2, r3\n\t"
  33144. "IT ne\n\t"
  33145. "movne r3, r7\n\t"
  33146. "EOR r2, r2, r3\n\t"
  33147. #endif /*WOLFSSL_SP_SMALL */
  33148. "MOV %[a], r2\n\t"
  33149. : [a] "+r" (a), [b] "+r" (b)
  33150. :
  33151. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  33152. );
  33153. return (uint32_t)(size_t)a;
  33154. }
  33155. /* Normalize the values in each word to 32.
  33156. *
  33157. * a Array of sp_digit to normalize.
  33158. */
  33159. #define sp_256_norm_8(a)
  33160. #ifdef WOLFSSL_SP_SMALL
  33161. /* Conditionally subtract b from a using the mask m.
  33162. * m is -1 to subtract and 0 when not copying.
  33163. *
  33164. * r A single precision number representing condition subtract result.
  33165. * a A single precision number to subtract from.
  33166. * b A single precision number to subtract.
  33167. * m Mask value to apply.
  33168. */
  33169. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33170. static sp_digit sp_256_cond_sub_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  33171. #else
  33172. static sp_digit sp_256_cond_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  33173. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33174. {
  33175. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33176. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  33177. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  33178. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  33179. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  33180. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33181. __asm__ __volatile__ (
  33182. "MOV r8, #0x0\n\t"
  33183. "MOV r4, #0x0\n\t"
  33184. "MOV r5, #0x0\n\t"
  33185. "\n"
  33186. "L_sp_256_cond_sub_8_words:\n\t"
  33187. "SUBS r4, r8, r4\n\t"
  33188. "LDR r6, [%[a], r5]\n\t"
  33189. "LDR r7, [%[b], r5]\n\t"
  33190. "AND r7, r7, %[m]\n\t"
  33191. "SBCS r6, r6, r7\n\t"
  33192. "SBC r4, r8, r8\n\t"
  33193. "STR r6, [%[r], r5]\n\t"
  33194. "ADD r5, r5, #0x4\n\t"
  33195. "CMP r5, #0x20\n\t"
  33196. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  33197. "BLT L_sp_256_cond_sub_8_words\n\t"
  33198. #else
  33199. "BLT.N L_sp_256_cond_sub_8_words\n\t"
  33200. #endif
  33201. "MOV %[r], r4\n\t"
  33202. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  33203. :
  33204. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  33205. );
  33206. return (uint32_t)(size_t)r;
  33207. }
  33208. #else
  33209. /* Conditionally subtract b from a using the mask m.
  33210. * m is -1 to subtract and 0 when not copying.
  33211. *
  33212. * r A single precision number representing condition subtract result.
  33213. * a A single precision number to subtract from.
  33214. * b A single precision number to subtract.
  33215. * m Mask value to apply.
  33216. */
  33217. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33218. static sp_digit sp_256_cond_sub_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  33219. #else
  33220. static sp_digit sp_256_cond_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  33221. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33222. {
  33223. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33224. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  33225. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  33226. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  33227. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  33228. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33229. __asm__ __volatile__ (
  33230. "MOV r5, #0x0\n\t"
  33231. "LDM %[a]!, {r6, r7}\n\t"
  33232. "LDM %[b]!, {r8, r9}\n\t"
  33233. "AND r8, r8, %[m]\n\t"
  33234. "AND r9, r9, %[m]\n\t"
  33235. "SUBS r6, r6, r8\n\t"
  33236. "SBCS r7, r7, r9\n\t"
  33237. "STM %[r]!, {r6, r7}\n\t"
  33238. "LDM %[a]!, {r6, r7}\n\t"
  33239. "LDM %[b]!, {r8, r9}\n\t"
  33240. "AND r8, r8, %[m]\n\t"
  33241. "AND r9, r9, %[m]\n\t"
  33242. "SBCS r6, r6, r8\n\t"
  33243. "SBCS r7, r7, r9\n\t"
  33244. "STM %[r]!, {r6, r7}\n\t"
  33245. "LDM %[a]!, {r6, r7}\n\t"
  33246. "LDM %[b]!, {r8, r9}\n\t"
  33247. "AND r8, r8, %[m]\n\t"
  33248. "AND r9, r9, %[m]\n\t"
  33249. "SBCS r6, r6, r8\n\t"
  33250. "SBCS r7, r7, r9\n\t"
  33251. "STM %[r]!, {r6, r7}\n\t"
  33252. "LDM %[a]!, {r6, r7}\n\t"
  33253. "LDM %[b]!, {r8, r9}\n\t"
  33254. "AND r8, r8, %[m]\n\t"
  33255. "AND r9, r9, %[m]\n\t"
  33256. "SBCS r6, r6, r8\n\t"
  33257. "SBCS r7, r7, r9\n\t"
  33258. "STM %[r]!, {r6, r7}\n\t"
  33259. "SBC %[r], r5, r5\n\t"
  33260. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  33261. :
  33262. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  33263. );
  33264. return (uint32_t)(size_t)r;
  33265. }
  33266. #endif /* WOLFSSL_SP_SMALL */
  33267. #ifndef WOLFSSL_SP_SMALL
  33268. #define sp_256_mont_reduce_order_8 sp_256_mont_reduce_8
  33269. #ifdef WOLFSSL_SP_NO_UMAAL
  33270. /* Reduce the number back to 256 bits using Montgomery reduction.
  33271. *
  33272. * a A single precision number to reduce in place.
  33273. * m The single precision number representing the modulus.
  33274. * mp The digit representing the negative inverse of m mod 2^n.
  33275. */
  33276. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33277. SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  33278. #else
  33279. SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_digit mp)
  33280. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33281. {
  33282. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33283. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  33284. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  33285. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  33286. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33287. __asm__ __volatile__ (
  33288. "LDR lr, [%[m]]\n\t"
  33289. /* i = 0 */
  33290. "MOV r11, #0x0\n\t"
  33291. "MOV r3, #0x0\n\t"
  33292. "LDR r4, [%[a]]\n\t"
  33293. "LDR r5, [%[a], #4]\n\t"
  33294. "\n"
  33295. "L_sp_256_mont_reduce_8_word:\n\t"
  33296. /* mu = a[i] * mp */
  33297. "MUL r10, %[mp], r4\n\t"
  33298. /* a[i+0] += m[0] * mu */
  33299. "MOV r7, #0x0\n\t"
  33300. "UMLAL r4, r7, r10, lr\n\t"
  33301. /* a[i+1] += m[1] * mu */
  33302. "LDR r9, [%[m], #4]\n\t"
  33303. "MOV r6, #0x0\n\t"
  33304. "UMLAL r5, r6, r10, r9\n\t"
  33305. "MOV r4, r5\n\t"
  33306. "ADDS r4, r4, r7\n\t"
  33307. "ADC r6, r6, #0x0\n\t"
  33308. /* a[i+2] += m[2] * mu */
  33309. "LDR r9, [%[m], #8]\n\t"
  33310. "LDR r5, [%[a], #8]\n\t"
  33311. "MOV r7, #0x0\n\t"
  33312. "UMLAL r5, r7, r10, r9\n\t"
  33313. "ADDS r5, r5, r6\n\t"
  33314. "ADC r7, r7, #0x0\n\t"
  33315. /* a[i+3] += m[3] * mu */
  33316. "LDR r9, [%[m], #12]\n\t"
  33317. "LDR r12, [%[a], #12]\n\t"
  33318. "MOV r6, #0x0\n\t"
  33319. "UMLAL r12, r6, r10, r9\n\t"
  33320. "ADDS r12, r12, r7\n\t"
  33321. "STR r12, [%[a], #12]\n\t"
  33322. "ADC r6, r6, #0x0\n\t"
  33323. /* a[i+4] += m[4] * mu */
  33324. "LDR r9, [%[m], #16]\n\t"
  33325. "LDR r12, [%[a], #16]\n\t"
  33326. "MOV r7, #0x0\n\t"
  33327. "UMLAL r12, r7, r10, r9\n\t"
  33328. "ADDS r12, r12, r6\n\t"
  33329. "STR r12, [%[a], #16]\n\t"
  33330. "ADC r7, r7, #0x0\n\t"
  33331. /* a[i+5] += m[5] * mu */
  33332. "LDR r9, [%[m], #20]\n\t"
  33333. "LDR r12, [%[a], #20]\n\t"
  33334. "MOV r6, #0x0\n\t"
  33335. "UMLAL r12, r6, r10, r9\n\t"
  33336. "ADDS r12, r12, r7\n\t"
  33337. "STR r12, [%[a], #20]\n\t"
  33338. "ADC r6, r6, #0x0\n\t"
  33339. /* a[i+6] += m[6] * mu */
  33340. "LDR r9, [%[m], #24]\n\t"
  33341. "LDR r12, [%[a], #24]\n\t"
  33342. "MOV r7, #0x0\n\t"
  33343. "UMLAL r12, r7, r10, r9\n\t"
  33344. "ADDS r12, r12, r6\n\t"
  33345. "STR r12, [%[a], #24]\n\t"
  33346. "ADC r7, r7, #0x0\n\t"
  33347. /* a[i+7] += m[7] * mu */
  33348. "LDR r9, [%[m], #28]\n\t"
  33349. "LDR r12, [%[a], #28]\n\t"
  33350. "UMULL r8, r9, r10, r9\n\t"
  33351. "ADDS r7, r7, r8\n\t"
  33352. "ADCS r6, r9, r3\n\t"
  33353. "MOV r3, #0x0\n\t"
  33354. "ADC r3, r3, r3\n\t"
  33355. "ADDS r12, r12, r7\n\t"
  33356. "STR r12, [%[a], #28]\n\t"
  33357. "LDR r12, [%[a], #32]\n\t"
  33358. "ADCS r12, r12, r6\n\t"
  33359. "STR r12, [%[a], #32]\n\t"
  33360. "ADC r3, r3, #0x0\n\t"
  33361. /* i += 1 */
  33362. "ADD r11, r11, #0x4\n\t"
  33363. "ADD %[a], %[a], #0x4\n\t"
  33364. "CMP r11, #0x20\n\t"
  33365. #ifdef __GNUC__
  33366. "BLT L_sp_256_mont_reduce_8_word\n\t"
  33367. #else
  33368. "BLT.W L_sp_256_mont_reduce_8_word\n\t"
  33369. #endif
  33370. /* Loop Done */
  33371. "STR r4, [%[a]]\n\t"
  33372. "STR r5, [%[a], #4]\n\t"
  33373. "MOV %[mp], r3\n\t"
  33374. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  33375. :
  33376. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  33377. );
  33378. sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - mp);
  33379. }
  33380. #else
  33381. /* Reduce the number back to 256 bits using Montgomery reduction.
  33382. *
  33383. * a A single precision number to reduce in place.
  33384. * m The single precision number representing the modulus.
  33385. * mp The digit representing the negative inverse of m mod 2^n.
  33386. */
  33387. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33388. SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  33389. #else
  33390. SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_digit mp)
  33391. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33392. {
  33393. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33394. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  33395. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  33396. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  33397. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33398. __asm__ __volatile__ (
  33399. /* i = 0 */
  33400. "MOV r4, #0x0\n\t"
  33401. "MOV r5, #0x0\n\t"
  33402. "LDR r6, [%[a]]\n\t"
  33403. "LDR r7, [%[a], #4]\n\t"
  33404. "LDR r8, [%[a], #8]\n\t"
  33405. "LDR r9, [%[a], #12]\n\t"
  33406. "LDR r10, [%[a], #16]\n\t"
  33407. "\n"
  33408. "L_sp_256_mont_reduce_8_word:\n\t"
  33409. /* mu = a[i] * mp */
  33410. "MUL lr, %[mp], r6\n\t"
  33411. /* a[i+0] += m[0] * mu */
  33412. "LDR r12, [%[m]]\n\t"
  33413. "MOV r3, #0x0\n\t"
  33414. "UMAAL r6, r3, lr, r12\n\t"
  33415. /* a[i+1] += m[1] * mu */
  33416. "LDR r12, [%[m], #4]\n\t"
  33417. "MOV r6, r7\n\t"
  33418. "UMAAL r6, r3, lr, r12\n\t"
  33419. /* a[i+2] += m[2] * mu */
  33420. "LDR r12, [%[m], #8]\n\t"
  33421. "MOV r7, r8\n\t"
  33422. "UMAAL r7, r3, lr, r12\n\t"
  33423. /* a[i+3] += m[3] * mu */
  33424. "LDR r12, [%[m], #12]\n\t"
  33425. "MOV r8, r9\n\t"
  33426. "UMAAL r8, r3, lr, r12\n\t"
  33427. /* a[i+4] += m[4] * mu */
  33428. "LDR r12, [%[m], #16]\n\t"
  33429. "MOV r9, r10\n\t"
  33430. "UMAAL r9, r3, lr, r12\n\t"
  33431. /* a[i+5] += m[5] * mu */
  33432. "LDR r12, [%[m], #20]\n\t"
  33433. "LDR r10, [%[a], #20]\n\t"
  33434. "UMAAL r10, r3, lr, r12\n\t"
  33435. /* a[i+6] += m[6] * mu */
  33436. "LDR r12, [%[m], #24]\n\t"
  33437. "LDR r11, [%[a], #24]\n\t"
  33438. "UMAAL r11, r3, lr, r12\n\t"
  33439. "STR r11, [%[a], #24]\n\t"
  33440. /* a[i+7] += m[7] * mu */
  33441. "LDR r12, [%[m], #28]\n\t"
  33442. "LDR r11, [%[a], #28]\n\t"
  33443. "UMAAL r11, r3, lr, r12\n\t"
  33444. "LDR lr, [%[a], #32]\n\t"
  33445. "MOV r12, #0x0\n\t"
  33446. "UMAAL r3, lr, r12, r12\n\t"
  33447. "STR r11, [%[a], #28]\n\t"
  33448. "ADDS r3, r3, r5\n\t"
  33449. "ADC r5, lr, #0x0\n\t"
  33450. "STR r3, [%[a], #32]\n\t"
  33451. /* i += 1 */
  33452. "ADD r4, r4, #0x4\n\t"
  33453. "ADD %[a], %[a], #0x4\n\t"
  33454. "CMP r4, #0x20\n\t"
  33455. #ifdef __GNUC__
  33456. "BLT L_sp_256_mont_reduce_8_word\n\t"
  33457. #else
  33458. "BLT.W L_sp_256_mont_reduce_8_word\n\t"
  33459. #endif
  33460. /* Loop Done */
  33461. "STR r6, [%[a]]\n\t"
  33462. "STR r7, [%[a], #4]\n\t"
  33463. "STR r8, [%[a], #8]\n\t"
  33464. "STR r9, [%[a], #12]\n\t"
  33465. "STR r10, [%[a], #16]\n\t"
  33466. "MOV %[mp], r5\n\t"
  33467. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  33468. :
  33469. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  33470. );
  33471. sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - mp);
  33472. }
  33473. #endif
  33474. #else
  33475. /* Reduce the number back to 256 bits using Montgomery reduction.
  33476. *
  33477. * a A single precision number to reduce in place.
  33478. * m The single precision number representing the modulus.
  33479. * mp The digit representing the negative inverse of m mod 2^n.
  33480. */
  33481. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33482. SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  33483. #else
  33484. SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_digit mp)
  33485. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33486. {
  33487. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33488. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  33489. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33490. __asm__ __volatile__ (
  33491. "SUB sp, sp, #0x44\n\t"
  33492. "STR %[a], [sp, #64]\n\t"
  33493. "MOV lr, sp\n\t"
  33494. "LDM %[a]!, {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  33495. "STM lr!, {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  33496. "LDM %[a], {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  33497. "STM lr, {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  33498. /* Start Reduction */
  33499. "LDM sp, {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  33500. "MOV r3, r11\n\t"
  33501. "MOV r4, r12\n\t"
  33502. /* mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192 */
  33503. /* - a[0] << 224 */
  33504. /* + (a[0]-a[1] * 2) << (6 * 32) */
  33505. "ADDS r11, r11, r5\n\t"
  33506. "ADC r12, r12, r6\n\t"
  33507. "ADDS r11, r11, r5\n\t"
  33508. "ADC r12, r12, r6\n\t"
  33509. /* - a[0] << (7 * 32) */
  33510. "SUB r12, r12, r5\n\t"
  33511. /* + a[0]-a[4] << (3 * 32) */
  33512. "MOV r0, r8\n\t"
  33513. "MOV r1, r9\n\t"
  33514. "MOV r2, r10\n\t"
  33515. "ADDS r8, r8, r5\n\t"
  33516. "ADCS r9, r9, r6\n\t"
  33517. "ADCS r10, r10, r7\n\t"
  33518. "ADCS r11, r11, r0\n\t"
  33519. "ADC r12, r12, r1\n\t"
  33520. /* a += mu * m */
  33521. /* += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1) */
  33522. /* a[0] = = t[0] */
  33523. /* a[1] = = t[1] */
  33524. /* a[2] = = t[2] */
  33525. /* a[3] += t[0] = t[3] */
  33526. /* a[4] += t[1] = t[4] */
  33527. /* a[5] += t[2] = t[5] */
  33528. /* a[6] += t[0] + t[3] = t[6] */
  33529. /* a[7] += t[1] + t[4] = t[7] + t[0] */
  33530. "ADDS r0, r0, r5\n\t"
  33531. "ADCS r1, r1, r6\n\t"
  33532. "ADCS r2, r2, r7\n\t"
  33533. "ADCS r3, r3, r8\n\t"
  33534. "ADCS r4, r4, r9\n\t"
  33535. "MOV lr, #0x0\n\t"
  33536. "ADC lr, lr, #0x0\n\t"
  33537. "ADDS r3, r3, r5\n\t"
  33538. "ADCS r4, r4, r6\n\t"
  33539. "ADC lr, lr, #0x0\n\t"
  33540. "STR r4, [sp, #28]\n\t"
  33541. /* a[8] += t[0] + t[2] + t[5] */
  33542. /* a[9] += t[1] + t[3] + t[6] */
  33543. /* a[10] += t[2] + t[4] + t[7] */
  33544. "ADD r0, sp, #0x20\n\t"
  33545. "LDM r0, {r2, r3, r4}\n\t"
  33546. "ADDS r2, r2, lr\n\t"
  33547. "ADCS r3, r3, #0x0\n\t"
  33548. "ADCS r4, r4, #0x0\n\t"
  33549. "MOV lr, #0x0\n\t"
  33550. "ADC lr, lr, #0x0\n\t"
  33551. "ADDS r2, r2, r5\n\t"
  33552. "ADCS r3, r3, r6\n\t"
  33553. "ADCS r4, r4, r7\n\t"
  33554. "ADC lr, lr, #0x0\n\t"
  33555. "ADDS r2, r2, r7\n\t"
  33556. "ADCS r3, r3, r8\n\t"
  33557. "ADCS r4, r4, r9\n\t"
  33558. "ADC lr, lr, #0x0\n\t"
  33559. "ADDS r2, r2, r10\n\t"
  33560. "ADCS r3, r3, r11\n\t"
  33561. "ADCS r4, r4, r12\n\t"
  33562. "ADC lr, lr, #0x0\n\t"
  33563. "STM r0!, {r2, r3, r4}\n\t"
  33564. /* a[11] += t[3] + t[5] + carry */
  33565. /* a[12] += t[4] + t[6] */
  33566. /* a[13] += t[5] + t[7] */
  33567. /* a[14] += t[6] */
  33568. /* a[15] += t[7] */
  33569. "LDM r0, {r0, r1, r2, r3, r4}\n\t"
  33570. "ADDS r0, r0, lr\n\t"
  33571. "ADCS r1, r1, #0x0\n\t"
  33572. "ADCS r2, r2, #0x0\n\t"
  33573. "ADCS r3, r3, #0x0\n\t"
  33574. "ADCS r4, r4, #0x0\n\t"
  33575. "MOV lr, #0x0\n\t"
  33576. "ADC lr, lr, #0x0\n\t"
  33577. "ADDS r0, r0, r8\n\t"
  33578. "ADCS r1, r1, r9\n\t"
  33579. "ADCS r2, r2, r10\n\t"
  33580. "ADCS r3, r3, r11\n\t"
  33581. "ADCS r4, r4, r12\n\t"
  33582. "ADC lr, lr, #0x0\n\t"
  33583. "ADDS r0, r0, r10\n\t"
  33584. "ADCS r1, r1, r11\n\t"
  33585. "ADCS r2, r2, r12\n\t"
  33586. "ADCS r3, r3, #0x0\n\t"
  33587. "ADCS r4, r4, #0x0\n\t"
  33588. "ADC lr, lr, #0x0\n\t"
  33589. "STR r0, [sp, #44]\n\t"
  33590. "STR r1, [sp, #48]\n\t"
  33591. "STR r2, [sp, #52]\n\t"
  33592. "STR r3, [sp, #56]\n\t"
  33593. /* a[7..15] - t[0..7] */
  33594. "ADD r0, sp, #0x1c\n\t"
  33595. "LDM r0, {r0, r1, r2, r3}\n\t"
  33596. "SUBS r0, r0, r5\n\t"
  33597. "SBCS r1, r1, r6\n\t"
  33598. "SBCS r2, r2, r7\n\t"
  33599. "SBCS r3, r3, r8\n\t"
  33600. "ADD r0, sp, #0x2c\n\t"
  33601. "MOV r8, r4\n\t"
  33602. "LDM r0, {r4, r5, r6, r7}\n\t"
  33603. "SBCS r4, r4, r9\n\t"
  33604. "SBCS r5, r5, r10\n\t"
  33605. "SBCS r6, r6, r11\n\t"
  33606. "SBCS r7, r7, r12\n\t"
  33607. "SBCS r8, r8, #0x0\n\t"
  33608. "SBC lr, lr, #0x0\n\t"
  33609. /* mask m and sub from result if overflow */
  33610. "RSB lr, lr, #0x0\n\t"
  33611. "SUBS r1, r1, lr\n\t"
  33612. "SBCS r2, r2, lr\n\t"
  33613. "SBCS r3, r3, lr\n\t"
  33614. "SBCS r4, r4, #0x0\n\t"
  33615. "SBCS r5, r5, #0x0\n\t"
  33616. "SBCS r6, r6, #0x0\n\t"
  33617. "SBCS r7, r7, lr, LSR #31\n\t"
  33618. "SBC r8, r8, lr\n\t"
  33619. "LDR %[a], [sp, #64]\n\t"
  33620. "STM %[a], {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  33621. "ADD sp, sp, #0x44\n\t"
  33622. : [a] "+r" (a)
  33623. :
  33624. : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  33625. );
  33626. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33627. (void)m_p;
  33628. #else
  33629. (void)m;
  33630. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33631. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33632. (void)mp_p;
  33633. #else
  33634. (void)mp;
  33635. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33636. }
  33637. #ifdef WOLFSSL_SP_NO_UMAAL
  33638. /* Reduce the number back to 256 bits using Montgomery reduction.
  33639. *
  33640. * a A single precision number to reduce in place.
  33641. * m The single precision number representing the modulus.
  33642. * mp The digit representing the negative inverse of m mod 2^n.
  33643. */
  33644. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33645. SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  33646. #else
  33647. SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* m, sp_digit mp)
  33648. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33649. {
  33650. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33651. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  33652. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  33653. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  33654. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33655. __asm__ __volatile__ (
  33656. "LDR lr, [%[m]]\n\t"
  33657. /* i = 0 */
  33658. "MOV r11, #0x0\n\t"
  33659. "MOV r3, #0x0\n\t"
  33660. "LDR r4, [%[a]]\n\t"
  33661. "LDR r5, [%[a], #4]\n\t"
  33662. "\n"
  33663. "L_sp_256_mont_reduce_order_8_word:\n\t"
  33664. /* mu = a[i] * mp */
  33665. "MUL r10, %[mp], r4\n\t"
  33666. /* a[i+0] += m[0] * mu */
  33667. "MOV r7, #0x0\n\t"
  33668. "UMLAL r4, r7, r10, lr\n\t"
  33669. /* a[i+1] += m[1] * mu */
  33670. "LDR r9, [%[m], #4]\n\t"
  33671. "MOV r6, #0x0\n\t"
  33672. "UMLAL r5, r6, r10, r9\n\t"
  33673. "MOV r4, r5\n\t"
  33674. "ADDS r4, r4, r7\n\t"
  33675. "ADC r6, r6, #0x0\n\t"
  33676. /* a[i+2] += m[2] * mu */
  33677. "LDR r9, [%[m], #8]\n\t"
  33678. "LDR r5, [%[a], #8]\n\t"
  33679. "MOV r7, #0x0\n\t"
  33680. "UMLAL r5, r7, r10, r9\n\t"
  33681. "ADDS r5, r5, r6\n\t"
  33682. "ADC r7, r7, #0x0\n\t"
  33683. /* a[i+3] += m[3] * mu */
  33684. "LDR r9, [%[m], #12]\n\t"
  33685. "LDR r12, [%[a], #12]\n\t"
  33686. "MOV r6, #0x0\n\t"
  33687. "UMLAL r12, r6, r10, r9\n\t"
  33688. "ADDS r12, r12, r7\n\t"
  33689. "STR r12, [%[a], #12]\n\t"
  33690. "ADC r6, r6, #0x0\n\t"
  33691. /* a[i+4] += m[4] * mu */
  33692. "LDR r9, [%[m], #16]\n\t"
  33693. "LDR r12, [%[a], #16]\n\t"
  33694. "MOV r7, #0x0\n\t"
  33695. "UMLAL r12, r7, r10, r9\n\t"
  33696. "ADDS r12, r12, r6\n\t"
  33697. "STR r12, [%[a], #16]\n\t"
  33698. "ADC r7, r7, #0x0\n\t"
  33699. /* a[i+5] += m[5] * mu */
  33700. "LDR r9, [%[m], #20]\n\t"
  33701. "LDR r12, [%[a], #20]\n\t"
  33702. "MOV r6, #0x0\n\t"
  33703. "UMLAL r12, r6, r10, r9\n\t"
  33704. "ADDS r12, r12, r7\n\t"
  33705. "STR r12, [%[a], #20]\n\t"
  33706. "ADC r6, r6, #0x0\n\t"
  33707. /* a[i+6] += m[6] * mu */
  33708. "LDR r9, [%[m], #24]\n\t"
  33709. "LDR r12, [%[a], #24]\n\t"
  33710. "MOV r7, #0x0\n\t"
  33711. "UMLAL r12, r7, r10, r9\n\t"
  33712. "ADDS r12, r12, r6\n\t"
  33713. "STR r12, [%[a], #24]\n\t"
  33714. "ADC r7, r7, #0x0\n\t"
  33715. /* a[i+7] += m[7] * mu */
  33716. "LDR r9, [%[m], #28]\n\t"
  33717. "LDR r12, [%[a], #28]\n\t"
  33718. "UMULL r8, r9, r10, r9\n\t"
  33719. "ADDS r7, r7, r8\n\t"
  33720. "ADCS r6, r9, r3\n\t"
  33721. "MOV r3, #0x0\n\t"
  33722. "ADC r3, r3, r3\n\t"
  33723. "ADDS r12, r12, r7\n\t"
  33724. "STR r12, [%[a], #28]\n\t"
  33725. "LDR r12, [%[a], #32]\n\t"
  33726. "ADCS r12, r12, r6\n\t"
  33727. "STR r12, [%[a], #32]\n\t"
  33728. "ADC r3, r3, #0x0\n\t"
  33729. /* i += 1 */
  33730. "ADD r11, r11, #0x4\n\t"
  33731. "ADD %[a], %[a], #0x4\n\t"
  33732. "CMP r11, #0x20\n\t"
  33733. #ifdef __GNUC__
  33734. "BLT L_sp_256_mont_reduce_order_8_word\n\t"
  33735. #else
  33736. "BLT.W L_sp_256_mont_reduce_order_8_word\n\t"
  33737. #endif
  33738. /* Loop Done */
  33739. "STR r4, [%[a]]\n\t"
  33740. "STR r5, [%[a], #4]\n\t"
  33741. "MOV %[mp], r3\n\t"
  33742. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  33743. :
  33744. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  33745. );
  33746. sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - mp);
  33747. }
  33748. #else
  33749. /* Reduce the number back to 256 bits using Montgomery reduction.
  33750. *
  33751. * a A single precision number to reduce in place.
  33752. * m The single precision number representing the modulus.
  33753. * mp The digit representing the negative inverse of m mod 2^n.
  33754. */
  33755. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33756. SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  33757. #else
  33758. SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* m, sp_digit mp)
  33759. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33760. {
  33761. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33762. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  33763. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  33764. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  33765. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33766. __asm__ __volatile__ (
  33767. /* i = 0 */
  33768. "MOV r4, #0x0\n\t"
  33769. "MOV r5, #0x0\n\t"
  33770. "LDR r6, [%[a]]\n\t"
  33771. "LDR r7, [%[a], #4]\n\t"
  33772. "LDR r8, [%[a], #8]\n\t"
  33773. "LDR r9, [%[a], #12]\n\t"
  33774. "LDR r10, [%[a], #16]\n\t"
  33775. "\n"
  33776. "L_sp_256_mont_reduce_order_8_word:\n\t"
  33777. /* mu = a[i] * mp */
  33778. "MUL lr, %[mp], r6\n\t"
  33779. /* a[i+0] += m[0] * mu */
  33780. "LDR r12, [%[m]]\n\t"
  33781. "MOV r3, #0x0\n\t"
  33782. "UMAAL r6, r3, lr, r12\n\t"
  33783. /* a[i+1] += m[1] * mu */
  33784. "LDR r12, [%[m], #4]\n\t"
  33785. "MOV r6, r7\n\t"
  33786. "UMAAL r6, r3, lr, r12\n\t"
  33787. /* a[i+2] += m[2] * mu */
  33788. "LDR r12, [%[m], #8]\n\t"
  33789. "MOV r7, r8\n\t"
  33790. "UMAAL r7, r3, lr, r12\n\t"
  33791. /* a[i+3] += m[3] * mu */
  33792. "LDR r12, [%[m], #12]\n\t"
  33793. "MOV r8, r9\n\t"
  33794. "UMAAL r8, r3, lr, r12\n\t"
  33795. /* a[i+4] += m[4] * mu */
  33796. "LDR r12, [%[m], #16]\n\t"
  33797. "MOV r9, r10\n\t"
  33798. "UMAAL r9, r3, lr, r12\n\t"
  33799. /* a[i+5] += m[5] * mu */
  33800. "LDR r12, [%[m], #20]\n\t"
  33801. "LDR r10, [%[a], #20]\n\t"
  33802. "UMAAL r10, r3, lr, r12\n\t"
  33803. /* a[i+6] += m[6] * mu */
  33804. "LDR r12, [%[m], #24]\n\t"
  33805. "LDR r11, [%[a], #24]\n\t"
  33806. "UMAAL r11, r3, lr, r12\n\t"
  33807. "STR r11, [%[a], #24]\n\t"
  33808. /* a[i+7] += m[7] * mu */
  33809. "LDR r12, [%[m], #28]\n\t"
  33810. "LDR r11, [%[a], #28]\n\t"
  33811. "UMAAL r11, r3, lr, r12\n\t"
  33812. "LDR lr, [%[a], #32]\n\t"
  33813. "MOV r12, #0x0\n\t"
  33814. "UMAAL r3, lr, r12, r12\n\t"
  33815. "STR r11, [%[a], #28]\n\t"
  33816. "ADDS r3, r3, r5\n\t"
  33817. "ADC r5, lr, #0x0\n\t"
  33818. "STR r3, [%[a], #32]\n\t"
  33819. /* i += 1 */
  33820. "ADD r4, r4, #0x4\n\t"
  33821. "ADD %[a], %[a], #0x4\n\t"
  33822. "CMP r4, #0x20\n\t"
  33823. #ifdef __GNUC__
  33824. "BLT L_sp_256_mont_reduce_order_8_word\n\t"
  33825. #else
  33826. "BLT.W L_sp_256_mont_reduce_order_8_word\n\t"
  33827. #endif
  33828. /* Loop Done */
  33829. "STR r6, [%[a]]\n\t"
  33830. "STR r7, [%[a], #4]\n\t"
  33831. "STR r8, [%[a], #8]\n\t"
  33832. "STR r9, [%[a], #12]\n\t"
  33833. "STR r10, [%[a], #16]\n\t"
  33834. "MOV %[mp], r5\n\t"
  33835. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  33836. :
  33837. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  33838. );
  33839. sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - mp);
  33840. }
  33841. #endif
  33842. #endif /* WOLFSSL_SP_SMALL */
  33843. /* Map the Montgomery form projective coordinate point to an affine point.
  33844. *
  33845. * r Resulting affine coordinate point.
  33846. * p Montgomery form projective coordinate point.
  33847. * t Temporary ordinate data.
  33848. */
  33849. static void sp_256_map_8(sp_point_256* r, const sp_point_256* p,
  33850. sp_digit* t)
  33851. {
  33852. sp_digit* t1 = t;
  33853. sp_digit* t2 = t + 2*8;
  33854. sp_int32 n;
  33855. sp_256_mont_inv_8(t1, p->z, t + 2*8);
  33856. sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
  33857. sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
  33858. /* x /= z^2 */
  33859. sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod);
  33860. XMEMSET(r->x + 8, 0, sizeof(sp_digit) * 8U);
  33861. sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod);
  33862. /* Reduce x to less than modulus */
  33863. n = sp_256_cmp_8(r->x, p256_mod);
  33864. sp_256_cond_sub_8(r->x, r->x, p256_mod, ~(n >> 31));
  33865. sp_256_norm_8(r->x);
  33866. /* y /= z^3 */
  33867. sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod);
  33868. XMEMSET(r->y + 8, 0, sizeof(sp_digit) * 8U);
  33869. sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod);
  33870. /* Reduce y to less than modulus */
  33871. n = sp_256_cmp_8(r->y, p256_mod);
  33872. sp_256_cond_sub_8(r->y, r->y, p256_mod, ~(n >> 31));
  33873. sp_256_norm_8(r->y);
  33874. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  33875. r->z[0] = 1;
  33876. }
  33877. /* Add two Montgomery form numbers (r = a + b % m).
  33878. *
  33879. * r Result of addition.
  33880. * a First number to add in Montgomery form.
  33881. * b Second number to add in Montgomery form.
  33882. * m Modulus (prime).
  33883. */
  33884. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33885. SP_NOINLINE static void sp_256_mont_add_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  33886. #else
  33887. SP_NOINLINE static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  33888. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33889. {
  33890. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33891. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  33892. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  33893. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  33894. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33895. __asm__ __volatile__ (
  33896. "MOV lr, #0x0\n\t"
  33897. "LDM %[a], {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  33898. "LDM %[b]!, {r3, r4}\n\t"
  33899. "ADDS r5, r5, r3\n\t"
  33900. "ADCS r6, r6, r4\n\t"
  33901. "LDM %[b]!, {r3, r4}\n\t"
  33902. "ADCS r7, r7, r3\n\t"
  33903. "ADCS r8, r8, r4\n\t"
  33904. "LDM %[b]!, {r3, r4}\n\t"
  33905. "ADCS r9, r9, r3\n\t"
  33906. "ADCS r10, r10, r4\n\t"
  33907. "LDM %[b]!, {r3, r4}\n\t"
  33908. "ADCS r11, r11, r3\n\t"
  33909. "ADCS r12, r12, r4\n\t"
  33910. "ADC lr, lr, #0x0\n\t"
  33911. "RSB lr, lr, #0x0\n\t"
  33912. "SUBS r5, r5, lr\n\t"
  33913. "SBCS r6, r6, lr\n\t"
  33914. "SBCS r7, r7, lr\n\t"
  33915. "SBCS r8, r8, #0x0\n\t"
  33916. "SBCS r9, r9, #0x0\n\t"
  33917. "SBCS r10, r10, #0x0\n\t"
  33918. "SBCS r11, r11, lr, LSR #31\n\t"
  33919. "SBCS r12, r12, lr\n\t"
  33920. "SBC %[b], %[b], %[b]\n\t"
  33921. "SUB lr, lr, %[b]\n\t"
  33922. "SUBS r5, r5, lr\n\t"
  33923. "SBCS r6, r6, lr\n\t"
  33924. "SBCS r7, r7, lr\n\t"
  33925. "SBCS r8, r8, #0x0\n\t"
  33926. "SBCS r9, r9, #0x0\n\t"
  33927. "SBCS r10, r10, #0x0\n\t"
  33928. "SBCS r11, r11, lr, LSR #31\n\t"
  33929. "SBC r12, r12, lr\n\t"
  33930. "STM %[r], {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  33931. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  33932. :
  33933. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  33934. );
  33935. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33936. (void)m_p;
  33937. #else
  33938. (void)m;
  33939. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33940. }
  33941. /* Double a Montgomery form number (r = a + a % m).
  33942. *
  33943. * r Result of doubling.
  33944. * a Number to double in Montgomery form.
  33945. * m Modulus (prime).
  33946. */
  33947. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33948. SP_NOINLINE static void sp_256_mont_dbl_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  33949. #else
  33950. SP_NOINLINE static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
  33951. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33952. {
  33953. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33954. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  33955. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  33956. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33957. __asm__ __volatile__ (
  33958. "MOV r2, #0x0\n\t"
  33959. "LDM %[a], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  33960. "ADDS r4, r4, r4\n\t"
  33961. "ADCS r5, r5, r5\n\t"
  33962. "ADCS r6, r6, r6\n\t"
  33963. "ADCS r7, r7, r7\n\t"
  33964. "ADCS r8, r8, r8\n\t"
  33965. "ADCS r9, r9, r9\n\t"
  33966. "ADCS r10, r10, r10\n\t"
  33967. "ADCS r11, r11, r11\n\t"
  33968. "ADC r2, r2, #0x0\n\t"
  33969. "RSB r2, r2, #0x0\n\t"
  33970. "SUBS r4, r4, r2\n\t"
  33971. "SBCS r5, r5, r2\n\t"
  33972. "SBCS r6, r6, r2\n\t"
  33973. "SBCS r7, r7, #0x0\n\t"
  33974. "SBCS r8, r8, #0x0\n\t"
  33975. "SBCS r9, r9, #0x0\n\t"
  33976. "SBCS r10, r10, r2, LSR #31\n\t"
  33977. "SBCS r11, r11, r2\n\t"
  33978. "SBC %[a], %[a], %[a]\n\t"
  33979. "SUB r2, r2, %[a]\n\t"
  33980. "SUBS r4, r4, r2\n\t"
  33981. "SBCS r5, r5, r2\n\t"
  33982. "SBCS r6, r6, r2\n\t"
  33983. "SBCS r7, r7, #0x0\n\t"
  33984. "SBCS r8, r8, #0x0\n\t"
  33985. "SBCS r9, r9, #0x0\n\t"
  33986. "SBCS r10, r10, r2, LSR #31\n\t"
  33987. "SBC r11, r11, r2\n\t"
  33988. "STM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  33989. : [r] "+r" (r), [a] "+r" (a)
  33990. :
  33991. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r2", "cc"
  33992. );
  33993. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  33994. (void)m_p;
  33995. #else
  33996. (void)m;
  33997. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  33998. }
  33999. /* Triple a Montgomery form number (r = a + a + a % m).
  34000. *
  34001. * r Result of Tripling.
  34002. * a Number to triple in Montgomery form.
  34003. * m Modulus (prime).
  34004. */
  34005. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34006. SP_NOINLINE static void sp_256_mont_tpl_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  34007. #else
  34008. SP_NOINLINE static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
  34009. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34010. {
  34011. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34012. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  34013. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  34014. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34015. __asm__ __volatile__ (
  34016. "MOV r12, #0x0\n\t"
  34017. "LDM %[a], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  34018. "ADDS r4, r4, r4\n\t"
  34019. "ADCS r5, r5, r5\n\t"
  34020. "ADCS r6, r6, r6\n\t"
  34021. "ADCS r7, r7, r7\n\t"
  34022. "ADCS r8, r8, r8\n\t"
  34023. "ADCS r9, r9, r9\n\t"
  34024. "ADCS r10, r10, r10\n\t"
  34025. "ADCS r11, r11, r11\n\t"
  34026. "ADC r12, r12, #0x0\n\t"
  34027. "RSB r12, r12, #0x0\n\t"
  34028. "SUBS r4, r4, r12\n\t"
  34029. "SBCS r5, r5, r12\n\t"
  34030. "SBCS r6, r6, r12\n\t"
  34031. "SBCS r7, r7, #0x0\n\t"
  34032. "SBCS r8, r8, #0x0\n\t"
  34033. "SBCS r9, r9, #0x0\n\t"
  34034. "SBCS r10, r10, r12, LSR #31\n\t"
  34035. "SBCS r11, r11, r12\n\t"
  34036. "SBC r2, r2, r2\n\t"
  34037. "SUB r12, r12, r2\n\t"
  34038. "SUBS r4, r4, r12\n\t"
  34039. "SBCS r5, r5, r12\n\t"
  34040. "SBCS r6, r6, r12\n\t"
  34041. "SBCS r7, r7, #0x0\n\t"
  34042. "SBCS r8, r8, #0x0\n\t"
  34043. "SBCS r9, r9, #0x0\n\t"
  34044. "SBCS r10, r10, r12, LSR #31\n\t"
  34045. "SBC r11, r11, r12\n\t"
  34046. "LDM %[a]!, {r2, r3}\n\t"
  34047. "ADDS r4, r4, r2\n\t"
  34048. "ADCS r5, r5, r3\n\t"
  34049. "LDM %[a]!, {r2, r3}\n\t"
  34050. "ADCS r6, r6, r2\n\t"
  34051. "ADCS r7, r7, r3\n\t"
  34052. "LDM %[a]!, {r2, r3}\n\t"
  34053. "ADCS r8, r8, r2\n\t"
  34054. "ADCS r9, r9, r3\n\t"
  34055. "LDM %[a]!, {r2, r3}\n\t"
  34056. "ADCS r10, r10, r2\n\t"
  34057. "ADCS r11, r11, r3\n\t"
  34058. "ADC r12, r12, #0x0\n\t"
  34059. "RSB r12, r12, #0x0\n\t"
  34060. "SUBS r4, r4, r12\n\t"
  34061. "SBCS r5, r5, r12\n\t"
  34062. "SBCS r6, r6, r12\n\t"
  34063. "SBCS r7, r7, #0x0\n\t"
  34064. "SBCS r8, r8, #0x0\n\t"
  34065. "SBCS r9, r9, #0x0\n\t"
  34066. "SBCS r10, r10, r12, LSR #31\n\t"
  34067. "SBCS r11, r11, r12\n\t"
  34068. "SBC r2, r2, r2\n\t"
  34069. "SUB r12, r12, r2\n\t"
  34070. "SUBS r4, r4, r12\n\t"
  34071. "SBCS r5, r5, r12\n\t"
  34072. "SBCS r6, r6, r12\n\t"
  34073. "SBCS r7, r7, #0x0\n\t"
  34074. "SBCS r8, r8, #0x0\n\t"
  34075. "SBCS r9, r9, #0x0\n\t"
  34076. "SBCS r10, r10, r12, LSR #31\n\t"
  34077. "SBC r11, r11, r12\n\t"
  34078. "STM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  34079. : [r] "+r" (r), [a] "+r" (a)
  34080. :
  34081. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r2", "r3", "r12", "cc"
  34082. );
  34083. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34084. (void)m_p;
  34085. #else
  34086. (void)m;
  34087. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34088. }
  34089. /* Subtract two Montgomery form numbers (r = a - b % m).
  34090. *
  34091. * r Result of subtration.
  34092. * a Number to subtract from in Montgomery form.
  34093. * b Number to subtract with in Montgomery form.
  34094. * m Modulus (prime).
  34095. */
  34096. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34097. SP_NOINLINE static void sp_256_mont_sub_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  34098. #else
  34099. SP_NOINLINE static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  34100. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34101. {
  34102. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34103. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  34104. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  34105. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  34106. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34107. __asm__ __volatile__ (
  34108. "MOV lr, #0x0\n\t"
  34109. "LDM %[a], {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  34110. "LDM %[b]!, {r3, r4}\n\t"
  34111. "SUBS r5, r5, r3\n\t"
  34112. "SBCS r6, r6, r4\n\t"
  34113. "LDM %[b]!, {r3, r4}\n\t"
  34114. "SBCS r7, r7, r3\n\t"
  34115. "SBCS r8, r8, r4\n\t"
  34116. "LDM %[b]!, {r3, r4}\n\t"
  34117. "SBCS r9, r9, r3\n\t"
  34118. "SBCS r10, r10, r4\n\t"
  34119. "LDM %[b]!, {r3, r4}\n\t"
  34120. "SBCS r11, r11, r3\n\t"
  34121. "SBCS r12, r12, r4\n\t"
  34122. "SBC lr, lr, #0x0\n\t"
  34123. "ADDS r5, r5, lr\n\t"
  34124. "ADCS r6, r6, lr\n\t"
  34125. "ADCS r7, r7, lr\n\t"
  34126. "ADCS r8, r8, #0x0\n\t"
  34127. "ADCS r9, r9, #0x0\n\t"
  34128. "ADCS r10, r10, #0x0\n\t"
  34129. "ADCS r11, r11, lr, LSR #31\n\t"
  34130. "ADCS r12, r12, lr\n\t"
  34131. "ADC lr, lr, #0x0\n\t"
  34132. "ADDS r5, r5, lr\n\t"
  34133. "ADCS r6, r6, lr\n\t"
  34134. "ADCS r7, r7, lr\n\t"
  34135. "ADCS r8, r8, #0x0\n\t"
  34136. "ADCS r9, r9, #0x0\n\t"
  34137. "ADCS r10, r10, #0x0\n\t"
  34138. "ADCS r11, r11, lr, LSR #31\n\t"
  34139. "ADC r12, r12, lr\n\t"
  34140. "STM %[r], {r5, r6, r7, r8, r9, r10, r11, r12}\n\t"
  34141. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  34142. :
  34143. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  34144. );
  34145. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34146. (void)m_p;
  34147. #else
  34148. (void)m;
  34149. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34150. }
  34151. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  34152. *
  34153. * r Result of division by 2.
  34154. * a Number to divide.
  34155. * m Modulus (prime).
  34156. */
  34157. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34158. SP_NOINLINE static void sp_256_mont_div2_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  34159. #else
  34160. SP_NOINLINE static void sp_256_mont_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
  34161. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34162. {
  34163. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  34164. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  34165. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  34166. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  34167. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  34168. __asm__ __volatile__ (
  34169. "LDM %[a], {r4, r5, r6, r7}\n\t"
  34170. "AND r3, r4, #0x1\n\t"
  34171. "RSB r8, r3, #0x0\n\t"
  34172. "ADDS r4, r4, r8\n\t"
  34173. "ADCS r5, r5, r8\n\t"
  34174. "ADCS r6, r6, r8\n\t"
  34175. "ADCS r7, r7, #0x0\n\t"
  34176. "STM %[r], {r4, r5, r6, r7}\n\t"
  34177. "LDRD r4, r5, [%[a], #16]\n\t"
  34178. "LDRD r6, r7, [%[a], #24]\n\t"
  34179. "ADCS r4, r4, #0x0\n\t"
  34180. "ADCS r5, r5, #0x0\n\t"
  34181. "ADCS r6, r6, r8, LSR #31\n\t"
  34182. "ADCS r7, r7, r8\n\t"
  34183. "MOV r3, #0x0\n\t"
  34184. "ADC r3, r3, #0x0\n\t"
  34185. "LSR r8, r4, #1\n\t"
  34186. "LSR r9, r5, #1\n\t"
  34187. "LSR r10, r6, #1\n\t"
  34188. "LSR r11, r7, #1\n\t"
  34189. "ORR r8, r8, r5, LSL #31\n\t"
  34190. "ORR r9, r9, r6, LSL #31\n\t"
  34191. "ORR r10, r10, r7, LSL #31\n\t"
  34192. "ORR r11, r11, r3, LSL #31\n\t"
  34193. "MOV r3, r4\n\t"
  34194. "STRD r8, r9, [%[r], #16]\n\t"
  34195. "STRD r10, r11, [%[r], #24]\n\t"
  34196. "LDM %[r], {r4, r5, r6, r7}\n\t"
  34197. "LSR r8, r4, #1\n\t"
  34198. "LSR r9, r5, #1\n\t"
  34199. "LSR r10, r6, #1\n\t"
  34200. "LSR r11, r7, #1\n\t"
  34201. "ORR r8, r8, r5, LSL #31\n\t"
  34202. "ORR r9, r9, r6, LSL #31\n\t"
  34203. "ORR r10, r10, r7, LSL #31\n\t"
  34204. "ORR r11, r11, r3, LSL #31\n\t"
  34205. "STM %[r], {r8, r9, r10, r11}\n\t"
  34206. : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
  34207. :
  34208. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "cc"
  34209. );
  34210. }
  34211. /* Double the Montgomery form projective point p.
  34212. *
  34213. * r Result of doubling point.
  34214. * p Point to double.
  34215. * t Temporary ordinate data.
  34216. */
  34217. static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p,
  34218. sp_digit* t)
  34219. {
  34220. sp_digit* t1 = t;
  34221. sp_digit* t2 = t + 2*8;
  34222. sp_digit* x;
  34223. sp_digit* y;
  34224. sp_digit* z;
  34225. x = r->x;
  34226. y = r->y;
  34227. z = r->z;
  34228. /* Put infinity into result. */
  34229. if (r != p) {
  34230. r->infinity = p->infinity;
  34231. }
  34232. /* T1 = Z * Z */
  34233. sp_256_mont_sqr_8(t1, p->z, p256_mod, p256_mp_mod);
  34234. /* Z = Y * Z */
  34235. sp_256_mont_mul_8(z, p->y, p->z, p256_mod, p256_mp_mod);
  34236. /* Z = 2Z */
  34237. sp_256_mont_dbl_8(z, z, p256_mod);
  34238. /* T2 = X - T1 */
  34239. sp_256_mont_sub_8(t2, p->x, t1, p256_mod);
  34240. /* T1 = X + T1 */
  34241. sp_256_mont_add_8(t1, p->x, t1, p256_mod);
  34242. /* T2 = T1 * T2 */
  34243. sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod);
  34244. /* T1 = 3T2 */
  34245. sp_256_mont_tpl_8(t1, t2, p256_mod);
  34246. /* Y = 2Y */
  34247. sp_256_mont_dbl_8(y, p->y, p256_mod);
  34248. /* Y = Y * Y */
  34249. sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod);
  34250. /* T2 = Y * Y */
  34251. sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
  34252. /* T2 = T2/2 */
  34253. sp_256_mont_div2_8(t2, t2, p256_mod);
  34254. /* Y = Y * X */
  34255. sp_256_mont_mul_8(y, y, p->x, p256_mod, p256_mp_mod);
  34256. /* X = T1 * T1 */
  34257. sp_256_mont_sqr_8(x, t1, p256_mod, p256_mp_mod);
  34258. /* X = X - Y */
  34259. sp_256_mont_sub_8(x, x, y, p256_mod);
  34260. /* X = X - Y */
  34261. sp_256_mont_sub_8(x, x, y, p256_mod);
  34262. /* Y = Y - X */
  34263. sp_256_mont_sub_8(y, y, x, p256_mod);
  34264. /* Y = Y * T1 */
  34265. sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod);
  34266. /* Y = Y - T2 */
  34267. sp_256_mont_sub_8(y, y, t2, p256_mod);
  34268. }
  34269. #ifdef WOLFSSL_SP_NONBLOCK
  34270. typedef struct sp_256_proj_point_dbl_8_ctx {
  34271. int state;
  34272. sp_digit* t1;
  34273. sp_digit* t2;
  34274. sp_digit* x;
  34275. sp_digit* y;
  34276. sp_digit* z;
  34277. } sp_256_proj_point_dbl_8_ctx;
  34278. /* Double the Montgomery form projective point p.
  34279. *
  34280. * r Result of doubling point.
  34281. * p Point to double.
  34282. * t Temporary ordinate data.
  34283. */
  34284. static int sp_256_proj_point_dbl_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
  34285. const sp_point_256* p, sp_digit* t)
  34286. {
  34287. int err = FP_WOULDBLOCK;
  34288. sp_256_proj_point_dbl_8_ctx* ctx = (sp_256_proj_point_dbl_8_ctx*)sp_ctx->data;
  34289. typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  34290. (void)sizeof(ctx_size_test);
  34291. switch (ctx->state) {
  34292. case 0:
  34293. ctx->t1 = t;
  34294. ctx->t2 = t + 2*8;
  34295. ctx->x = r->x;
  34296. ctx->y = r->y;
  34297. ctx->z = r->z;
  34298. /* Put infinity into result. */
  34299. if (r != p) {
  34300. r->infinity = p->infinity;
  34301. }
  34302. ctx->state = 1;
  34303. break;
  34304. case 1:
  34305. /* T1 = Z * Z */
  34306. sp_256_mont_sqr_8(ctx->t1, p->z, p256_mod, p256_mp_mod);
  34307. ctx->state = 2;
  34308. break;
  34309. case 2:
  34310. /* Z = Y * Z */
  34311. sp_256_mont_mul_8(ctx->z, p->y, p->z, p256_mod, p256_mp_mod);
  34312. ctx->state = 3;
  34313. break;
  34314. case 3:
  34315. /* Z = 2Z */
  34316. sp_256_mont_dbl_8(ctx->z, ctx->z, p256_mod);
  34317. ctx->state = 4;
  34318. break;
  34319. case 4:
  34320. /* T2 = X - T1 */
  34321. sp_256_mont_sub_8(ctx->t2, p->x, ctx->t1, p256_mod);
  34322. ctx->state = 5;
  34323. break;
  34324. case 5:
  34325. /* T1 = X + T1 */
  34326. sp_256_mont_add_8(ctx->t1, p->x, ctx->t1, p256_mod);
  34327. ctx->state = 6;
  34328. break;
  34329. case 6:
  34330. /* T2 = T1 * T2 */
  34331. sp_256_mont_mul_8(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod);
  34332. ctx->state = 7;
  34333. break;
  34334. case 7:
  34335. /* T1 = 3T2 */
  34336. sp_256_mont_tpl_8(ctx->t1, ctx->t2, p256_mod);
  34337. ctx->state = 8;
  34338. break;
  34339. case 8:
  34340. /* Y = 2Y */
  34341. sp_256_mont_dbl_8(ctx->y, p->y, p256_mod);
  34342. ctx->state = 9;
  34343. break;
  34344. case 9:
  34345. /* Y = Y * Y */
  34346. sp_256_mont_sqr_8(ctx->y, ctx->y, p256_mod, p256_mp_mod);
  34347. ctx->state = 10;
  34348. break;
  34349. case 10:
  34350. /* T2 = Y * Y */
  34351. sp_256_mont_sqr_8(ctx->t2, ctx->y, p256_mod, p256_mp_mod);
  34352. ctx->state = 11;
  34353. break;
  34354. case 11:
  34355. /* T2 = T2/2 */
  34356. sp_256_mont_div2_8(ctx->t2, ctx->t2, p256_mod);
  34357. ctx->state = 12;
  34358. break;
  34359. case 12:
  34360. /* Y = Y * X */
  34361. sp_256_mont_mul_8(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod);
  34362. ctx->state = 13;
  34363. break;
  34364. case 13:
  34365. /* X = T1 * T1 */
  34366. sp_256_mont_sqr_8(ctx->x, ctx->t1, p256_mod, p256_mp_mod);
  34367. ctx->state = 14;
  34368. break;
  34369. case 14:
  34370. /* X = X - Y */
  34371. sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod);
  34372. ctx->state = 15;
  34373. break;
  34374. case 15:
  34375. /* X = X - Y */
  34376. sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod);
  34377. ctx->state = 16;
  34378. break;
  34379. case 16:
  34380. /* Y = Y - X */
  34381. sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod);
  34382. ctx->state = 17;
  34383. break;
  34384. case 17:
  34385. /* Y = Y * T1 */
  34386. sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod);
  34387. ctx->state = 18;
  34388. break;
  34389. case 18:
  34390. /* Y = Y - T2 */
  34391. sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t2, p256_mod);
  34392. ctx->state = 19;
  34393. /* fall-through */
  34394. case 19:
  34395. err = MP_OKAY;
  34396. break;
  34397. }
  34398. if (err == MP_OKAY && ctx->state != 19) {
  34399. err = FP_WOULDBLOCK;
  34400. }
  34401. return err;
  34402. }
  34403. #endif /* WOLFSSL_SP_NONBLOCK */
  34404. /* Compare two numbers to determine if they are equal.
  34405. * Constant time implementation.
  34406. *
  34407. * a First number to compare.
  34408. * b Second number to compare.
  34409. * returns 1 when equal and 0 otherwise.
  34410. */
  34411. static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b)
  34412. {
  34413. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  34414. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  34415. (a[6] ^ b[6]) | (a[7] ^ b[7])) == 0;
  34416. }
  34417. /* Returns 1 if the number of zero.
  34418. * Implementation is constant time.
  34419. *
  34420. * a Number to check.
  34421. * returns 1 if the number is zero and 0 otherwise.
  34422. */
  34423. static int sp_256_iszero_8(const sp_digit* a)
  34424. {
  34425. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0;
  34426. }
  34427. /* Add two Montgomery form projective points.
  34428. *
  34429. * r Result of addition.
  34430. * p First point to add.
  34431. * q Second point to add.
  34432. * t Temporary ordinate data.
  34433. */
  34434. static void sp_256_proj_point_add_8(sp_point_256* r,
  34435. const sp_point_256* p, const sp_point_256* q, sp_digit* t)
  34436. {
  34437. sp_digit* t6 = t;
  34438. sp_digit* t1 = t + 2*8;
  34439. sp_digit* t2 = t + 4*8;
  34440. sp_digit* t3 = t + 6*8;
  34441. sp_digit* t4 = t + 8*8;
  34442. sp_digit* t5 = t + 10*8;
  34443. /* U1 = X1*Z2^2 */
  34444. sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod);
  34445. sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod);
  34446. sp_256_mont_mul_8(t1, t1, p->x, p256_mod, p256_mp_mod);
  34447. /* U2 = X2*Z1^2 */
  34448. sp_256_mont_sqr_8(t2, p->z, p256_mod, p256_mp_mod);
  34449. sp_256_mont_mul_8(t4, t2, p->z, p256_mod, p256_mp_mod);
  34450. sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod);
  34451. /* S1 = Y1*Z2^3 */
  34452. sp_256_mont_mul_8(t3, t3, p->y, p256_mod, p256_mp_mod);
  34453. /* S2 = Y2*Z1^3 */
  34454. sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod);
  34455. /* Check double */
  34456. if ((~p->infinity) & (~q->infinity) &
  34457. sp_256_cmp_equal_8(t2, t1) &
  34458. sp_256_cmp_equal_8(t4, t3)) {
  34459. sp_256_proj_point_dbl_8(r, p, t);
  34460. }
  34461. else {
  34462. sp_digit* x = t6;
  34463. sp_digit* y = t1;
  34464. sp_digit* z = t2;
  34465. /* H = U2 - U1 */
  34466. sp_256_mont_sub_8(t2, t2, t1, p256_mod);
  34467. /* R = S2 - S1 */
  34468. sp_256_mont_sub_8(t4, t4, t3, p256_mod);
  34469. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  34470. sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod);
  34471. sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod);
  34472. sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod);
  34473. /* Z3 = H*Z1*Z2 */
  34474. sp_256_mont_mul_8(z, p->z, t2, p256_mod, p256_mp_mod);
  34475. sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod);
  34476. sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod);
  34477. sp_256_mont_sub_8(x, x, t5, p256_mod);
  34478. sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod);
  34479. sp_256_mont_dbl_8(t3, y, p256_mod);
  34480. sp_256_mont_sub_8(x, x, t3, p256_mod);
  34481. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  34482. sp_256_mont_sub_8(y, y, x, p256_mod);
  34483. sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod);
  34484. sp_256_mont_sub_8(y, y, t5, p256_mod);
  34485. {
  34486. int i;
  34487. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  34488. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  34489. sp_digit maskt = ~(maskp | maskq);
  34490. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  34491. for (i = 0; i < 8; i++) {
  34492. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  34493. (x[i] & maskt);
  34494. }
  34495. for (i = 0; i < 8; i++) {
  34496. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  34497. (y[i] & maskt);
  34498. }
  34499. for (i = 0; i < 8; i++) {
  34500. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  34501. (z[i] & maskt);
  34502. }
  34503. r->z[0] |= inf;
  34504. r->infinity = (word32)inf;
  34505. }
  34506. }
  34507. }
  34508. #ifdef WOLFSSL_SP_NONBLOCK
  34509. typedef struct sp_256_proj_point_add_8_ctx {
  34510. int state;
  34511. sp_256_proj_point_dbl_8_ctx dbl_ctx;
  34512. const sp_point_256* ap[2];
  34513. sp_point_256* rp[2];
  34514. sp_digit* t1;
  34515. sp_digit* t2;
  34516. sp_digit* t3;
  34517. sp_digit* t4;
  34518. sp_digit* t5;
  34519. sp_digit* t6;
  34520. sp_digit* x;
  34521. sp_digit* y;
  34522. sp_digit* z;
  34523. } sp_256_proj_point_add_8_ctx;
  34524. /* Add two Montgomery form projective points.
  34525. *
  34526. * r Result of addition.
  34527. * p First point to add.
  34528. * q Second point to add.
  34529. * t Temporary ordinate data.
  34530. */
  34531. static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
  34532. const sp_point_256* p, const sp_point_256* q, sp_digit* t)
  34533. {
  34534. int err = FP_WOULDBLOCK;
  34535. sp_256_proj_point_add_8_ctx* ctx = (sp_256_proj_point_add_8_ctx*)sp_ctx->data;
  34536. /* Ensure only the first point is the same as the result. */
  34537. if (q == r) {
  34538. const sp_point_256* a = p;
  34539. p = q;
  34540. q = a;
  34541. }
  34542. typedef char ctx_size_test[sizeof(sp_256_proj_point_add_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  34543. (void)sizeof(ctx_size_test);
  34544. switch (ctx->state) {
  34545. case 0: /* INIT */
  34546. ctx->t6 = t;
  34547. ctx->t1 = t + 2*8;
  34548. ctx->t2 = t + 4*8;
  34549. ctx->t3 = t + 6*8;
  34550. ctx->t4 = t + 8*8;
  34551. ctx->t5 = t + 10*8;
  34552. ctx->x = ctx->t6;
  34553. ctx->y = ctx->t1;
  34554. ctx->z = ctx->t2;
  34555. ctx->state = 1;
  34556. break;
  34557. case 1:
  34558. /* U1 = X1*Z2^2 */
  34559. sp_256_mont_sqr_8(ctx->t1, q->z, p256_mod, p256_mp_mod);
  34560. ctx->state = 2;
  34561. break;
  34562. case 2:
  34563. sp_256_mont_mul_8(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod);
  34564. ctx->state = 3;
  34565. break;
  34566. case 3:
  34567. sp_256_mont_mul_8(ctx->t1, ctx->t1, p->x, p256_mod, p256_mp_mod);
  34568. ctx->state = 4;
  34569. break;
  34570. case 4:
  34571. /* U2 = X2*Z1^2 */
  34572. sp_256_mont_sqr_8(ctx->t2, p->z, p256_mod, p256_mp_mod);
  34573. ctx->state = 5;
  34574. break;
  34575. case 5:
  34576. sp_256_mont_mul_8(ctx->t4, ctx->t2, p->z, p256_mod, p256_mp_mod);
  34577. ctx->state = 6;
  34578. break;
  34579. case 6:
  34580. sp_256_mont_mul_8(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod);
  34581. ctx->state = 7;
  34582. break;
  34583. case 7:
  34584. /* S1 = Y1*Z2^3 */
  34585. sp_256_mont_mul_8(ctx->t3, ctx->t3, p->y, p256_mod, p256_mp_mod);
  34586. ctx->state = 8;
  34587. break;
  34588. case 8:
  34589. /* S2 = Y2*Z1^3 */
  34590. sp_256_mont_mul_8(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod);
  34591. ctx->state = 9;
  34592. break;
  34593. case 9:
  34594. /* Check double */
  34595. if ((~p->infinity) & (~q->infinity) &
  34596. sp_256_cmp_equal_8(ctx->t2, ctx->t1) &
  34597. sp_256_cmp_equal_8(ctx->t4, ctx->t3)) {
  34598. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  34599. sp_256_proj_point_dbl_8(r, p, t);
  34600. ctx->state = 25;
  34601. }
  34602. else {
  34603. ctx->state = 10;
  34604. }
  34605. break;
  34606. case 10:
  34607. /* H = U2 - U1 */
  34608. sp_256_mont_sub_8(ctx->t2, ctx->t2, ctx->t1, p256_mod);
  34609. ctx->state = 11;
  34610. break;
  34611. case 11:
  34612. /* R = S2 - S1 */
  34613. sp_256_mont_sub_8(ctx->t4, ctx->t4, ctx->t3, p256_mod);
  34614. ctx->state = 12;
  34615. break;
  34616. case 12:
  34617. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  34618. sp_256_mont_sqr_8(ctx->t5, ctx->t2, p256_mod, p256_mp_mod);
  34619. ctx->state = 13;
  34620. break;
  34621. case 13:
  34622. sp_256_mont_mul_8(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod);
  34623. ctx->state = 14;
  34624. break;
  34625. case 14:
  34626. sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod);
  34627. ctx->state = 15;
  34628. break;
  34629. case 15:
  34630. /* Z3 = H*Z1*Z2 */
  34631. sp_256_mont_mul_8(ctx->z, p->z, ctx->t2, p256_mod, p256_mp_mod);
  34632. ctx->state = 16;
  34633. break;
  34634. case 16:
  34635. sp_256_mont_mul_8(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod);
  34636. ctx->state = 17;
  34637. break;
  34638. case 17:
  34639. sp_256_mont_sqr_8(ctx->x, ctx->t4, p256_mod, p256_mp_mod);
  34640. ctx->state = 18;
  34641. break;
  34642. case 18:
  34643. sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t5, p256_mod);
  34644. ctx->state = 19;
  34645. break;
  34646. case 19:
  34647. sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod);
  34648. ctx->state = 20;
  34649. break;
  34650. case 20:
  34651. sp_256_mont_dbl_8(ctx->t3, ctx->y, p256_mod);
  34652. sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t3, p256_mod);
  34653. ctx->state = 21;
  34654. break;
  34655. case 21:
  34656. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  34657. sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod);
  34658. ctx->state = 22;
  34659. break;
  34660. case 22:
  34661. sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod);
  34662. ctx->state = 23;
  34663. break;
  34664. case 23:
  34665. sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t5, p256_mod);
  34666. ctx->state = 24;
  34667. break;
  34668. case 24:
  34669. {
  34670. {
  34671. int i;
  34672. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  34673. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  34674. sp_digit maskt = ~(maskp | maskq);
  34675. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  34676. for (i = 0; i < 8; i++) {
  34677. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  34678. (ctx->x[i] & maskt);
  34679. }
  34680. for (i = 0; i < 8; i++) {
  34681. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  34682. (ctx->y[i] & maskt);
  34683. }
  34684. for (i = 0; i < 8; i++) {
  34685. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  34686. (ctx->z[i] & maskt);
  34687. }
  34688. r->z[0] |= inf;
  34689. r->infinity = (word32)inf;
  34690. }
  34691. ctx->state = 25;
  34692. break;
  34693. }
  34694. case 25:
  34695. err = MP_OKAY;
  34696. break;
  34697. }
  34698. if (err == MP_OKAY && ctx->state != 25) {
  34699. err = FP_WOULDBLOCK;
  34700. }
  34701. return err;
  34702. }
  34703. #endif /* WOLFSSL_SP_NONBLOCK */
  34704. #ifndef WC_NO_CACHE_RESISTANT
  34705. /* Touch each possible point that could be being copied.
  34706. *
  34707. * r Point to copy into.
  34708. * table Table - start of the entries to access
  34709. * idx Index of entry to retrieve.
  34710. */
  34711. static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table,
  34712. int idx)
  34713. {
  34714. int i;
  34715. sp_digit mask;
  34716. r->x[0] = 0;
  34717. r->x[1] = 0;
  34718. r->x[2] = 0;
  34719. r->x[3] = 0;
  34720. r->x[4] = 0;
  34721. r->x[5] = 0;
  34722. r->x[6] = 0;
  34723. r->x[7] = 0;
  34724. r->y[0] = 0;
  34725. r->y[1] = 0;
  34726. r->y[2] = 0;
  34727. r->y[3] = 0;
  34728. r->y[4] = 0;
  34729. r->y[5] = 0;
  34730. r->y[6] = 0;
  34731. r->y[7] = 0;
  34732. r->z[0] = 0;
  34733. r->z[1] = 0;
  34734. r->z[2] = 0;
  34735. r->z[3] = 0;
  34736. r->z[4] = 0;
  34737. r->z[5] = 0;
  34738. r->z[6] = 0;
  34739. r->z[7] = 0;
  34740. for (i = 1; i < 16; i++) {
  34741. mask = 0 - (i == idx);
  34742. r->x[0] |= mask & table[i].x[0];
  34743. r->x[1] |= mask & table[i].x[1];
  34744. r->x[2] |= mask & table[i].x[2];
  34745. r->x[3] |= mask & table[i].x[3];
  34746. r->x[4] |= mask & table[i].x[4];
  34747. r->x[5] |= mask & table[i].x[5];
  34748. r->x[6] |= mask & table[i].x[6];
  34749. r->x[7] |= mask & table[i].x[7];
  34750. r->y[0] |= mask & table[i].y[0];
  34751. r->y[1] |= mask & table[i].y[1];
  34752. r->y[2] |= mask & table[i].y[2];
  34753. r->y[3] |= mask & table[i].y[3];
  34754. r->y[4] |= mask & table[i].y[4];
  34755. r->y[5] |= mask & table[i].y[5];
  34756. r->y[6] |= mask & table[i].y[6];
  34757. r->y[7] |= mask & table[i].y[7];
  34758. r->z[0] |= mask & table[i].z[0];
  34759. r->z[1] |= mask & table[i].z[1];
  34760. r->z[2] |= mask & table[i].z[2];
  34761. r->z[3] |= mask & table[i].z[3];
  34762. r->z[4] |= mask & table[i].z[4];
  34763. r->z[5] |= mask & table[i].z[5];
  34764. r->z[6] |= mask & table[i].z[6];
  34765. r->z[7] |= mask & table[i].z[7];
  34766. }
  34767. }
  34768. #endif /* !WC_NO_CACHE_RESISTANT */
  34769. /* Multiply the point by the scalar and return the result.
  34770. * If map is true then convert result to affine coordinates.
  34771. *
  34772. * Fast implementation that generates a pre-computation table.
  34773. * 4 bits of window (no sliding!).
  34774. * Uses add and double for calculating table.
  34775. * 256 doubles.
  34776. * 76 adds.
  34777. *
  34778. * r Resulting point.
  34779. * g Point to multiply.
  34780. * k Scalar to multiply by.
  34781. * map Indicates whether to convert result to affine.
  34782. * ct Constant time required.
  34783. * heap Heap to use for allocation.
  34784. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  34785. */
  34786. static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k,
  34787. int map, int ct, void* heap)
  34788. {
  34789. #ifdef WOLFSSL_SP_SMALL_STACK
  34790. sp_point_256* t = NULL;
  34791. sp_digit* tmp = NULL;
  34792. #else
  34793. sp_point_256 t[16 + 1];
  34794. sp_digit tmp[2 * 8 * 6];
  34795. #endif
  34796. sp_point_256* rt = NULL;
  34797. #ifndef WC_NO_CACHE_RESISTANT
  34798. #ifdef WOLFSSL_SP_SMALL_STACK
  34799. sp_point_256* p = NULL;
  34800. #else
  34801. sp_point_256 p[1];
  34802. #endif
  34803. #endif /* !WC_NO_CACHE_RESISTANT */
  34804. sp_digit n;
  34805. int i;
  34806. int c;
  34807. int y;
  34808. int err = MP_OKAY;
  34809. /* Constant time used for cache attack resistance implementation. */
  34810. (void)ct;
  34811. (void)heap;
  34812. #ifdef WOLFSSL_SP_SMALL_STACK
  34813. t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * (16 + 1),
  34814. heap, DYNAMIC_TYPE_ECC);
  34815. if (t == NULL)
  34816. err = MEMORY_E;
  34817. #ifndef WC_NO_CACHE_RESISTANT
  34818. if (err == MP_OKAY) {
  34819. p = (sp_point_256*)XMALLOC(sizeof(sp_point_256),
  34820. heap, DYNAMIC_TYPE_ECC);
  34821. if (p == NULL)
  34822. err = MEMORY_E;
  34823. }
  34824. #endif
  34825. if (err == MP_OKAY) {
  34826. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 6, heap,
  34827. DYNAMIC_TYPE_ECC);
  34828. if (tmp == NULL)
  34829. err = MEMORY_E;
  34830. }
  34831. #endif
  34832. if (err == MP_OKAY) {
  34833. rt = t + 16;
  34834. /* t[0] = {0, 0, 1} * norm */
  34835. XMEMSET(&t[0], 0, sizeof(t[0]));
  34836. t[0].infinity = 1;
  34837. /* t[1] = {g->x, g->y, g->z} * norm */
  34838. (void)sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod);
  34839. (void)sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod);
  34840. (void)sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod);
  34841. t[1].infinity = 0;
  34842. sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp);
  34843. t[ 2].infinity = 0;
  34844. sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp);
  34845. t[ 3].infinity = 0;
  34846. sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp);
  34847. t[ 4].infinity = 0;
  34848. sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp);
  34849. t[ 5].infinity = 0;
  34850. sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp);
  34851. t[ 6].infinity = 0;
  34852. sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp);
  34853. t[ 7].infinity = 0;
  34854. sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp);
  34855. t[ 8].infinity = 0;
  34856. sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp);
  34857. t[ 9].infinity = 0;
  34858. sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp);
  34859. t[10].infinity = 0;
  34860. sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp);
  34861. t[11].infinity = 0;
  34862. sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp);
  34863. t[12].infinity = 0;
  34864. sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp);
  34865. t[13].infinity = 0;
  34866. sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp);
  34867. t[14].infinity = 0;
  34868. sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp);
  34869. t[15].infinity = 0;
  34870. i = 6;
  34871. n = k[i+1] << 0;
  34872. c = 28;
  34873. y = (int)(n >> 28);
  34874. #ifndef WC_NO_CACHE_RESISTANT
  34875. if (ct) {
  34876. sp_256_get_point_16_8(rt, t, y);
  34877. rt->infinity = !y;
  34878. }
  34879. else
  34880. #endif
  34881. {
  34882. XMEMCPY(rt, &t[y], sizeof(sp_point_256));
  34883. }
  34884. n <<= 4;
  34885. for (; i>=0 || c>=4; ) {
  34886. if (c < 4) {
  34887. n |= k[i--];
  34888. c += 32;
  34889. }
  34890. y = (n >> 28) & 0xf;
  34891. n <<= 4;
  34892. c -= 4;
  34893. sp_256_proj_point_dbl_8(rt, rt, tmp);
  34894. sp_256_proj_point_dbl_8(rt, rt, tmp);
  34895. sp_256_proj_point_dbl_8(rt, rt, tmp);
  34896. sp_256_proj_point_dbl_8(rt, rt, tmp);
  34897. #ifndef WC_NO_CACHE_RESISTANT
  34898. if (ct) {
  34899. sp_256_get_point_16_8(p, t, y);
  34900. p->infinity = !y;
  34901. sp_256_proj_point_add_8(rt, rt, p, tmp);
  34902. }
  34903. else
  34904. #endif
  34905. {
  34906. sp_256_proj_point_add_8(rt, rt, &t[y], tmp);
  34907. }
  34908. }
  34909. if (map != 0) {
  34910. sp_256_map_8(r, rt, tmp);
  34911. }
  34912. else {
  34913. XMEMCPY(r, rt, sizeof(sp_point_256));
  34914. }
  34915. }
  34916. #ifdef WOLFSSL_SP_SMALL_STACK
  34917. if (tmp != NULL)
  34918. #endif
  34919. {
  34920. ForceZero(tmp, sizeof(sp_digit) * 2 * 8 * 6);
  34921. #ifdef WOLFSSL_SP_SMALL_STACK
  34922. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  34923. #endif
  34924. }
  34925. #ifndef WC_NO_CACHE_RESISTANT
  34926. #ifdef WOLFSSL_SP_SMALL_STACK
  34927. if (p != NULL)
  34928. #endif
  34929. {
  34930. ForceZero(p, sizeof(sp_point_256));
  34931. #ifdef WOLFSSL_SP_SMALL_STACK
  34932. XFREE(p, heap, DYNAMIC_TYPE_ECC);
  34933. #endif
  34934. }
  34935. #endif /* !WC_NO_CACHE_RESISTANT */
  34936. #ifdef WOLFSSL_SP_SMALL_STACK
  34937. if (t != NULL)
  34938. #endif
  34939. {
  34940. ForceZero(t, sizeof(sp_point_256) * 17);
  34941. #ifdef WOLFSSL_SP_SMALL_STACK
  34942. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  34943. #endif
  34944. }
  34945. return err;
  34946. }
  34947. #ifdef FP_ECC
  34948. /* Double the Montgomery form projective point p a number of times.
  34949. *
  34950. * r Result of repeated doubling of point.
  34951. * p Point to double.
  34952. * n Number of times to double
  34953. * t Temporary ordinate data.
  34954. */
  34955. static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int i,
  34956. sp_digit* t)
  34957. {
  34958. sp_digit* w = t;
  34959. sp_digit* a = t + 2*8;
  34960. sp_digit* b = t + 4*8;
  34961. sp_digit* t1 = t + 6*8;
  34962. sp_digit* t2 = t + 8*8;
  34963. sp_digit* x;
  34964. sp_digit* y;
  34965. sp_digit* z;
  34966. volatile int n = i;
  34967. x = p->x;
  34968. y = p->y;
  34969. z = p->z;
  34970. /* Y = 2*Y */
  34971. sp_256_mont_dbl_8(y, y, p256_mod);
  34972. /* W = Z^4 */
  34973. sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod);
  34974. sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod);
  34975. #ifndef WOLFSSL_SP_SMALL
  34976. while (--n > 0)
  34977. #else
  34978. while (--n >= 0)
  34979. #endif
  34980. {
  34981. /* A = 3*(X^2 - W) */
  34982. sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod);
  34983. sp_256_mont_sub_8(t1, t1, w, p256_mod);
  34984. sp_256_mont_tpl_8(a, t1, p256_mod);
  34985. /* B = X*Y^2 */
  34986. sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod);
  34987. sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod);
  34988. /* X = A^2 - 2B */
  34989. sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod);
  34990. sp_256_mont_dbl_8(t2, b, p256_mod);
  34991. sp_256_mont_sub_8(x, x, t2, p256_mod);
  34992. /* B = 2.(B - X) */
  34993. sp_256_mont_sub_8(t2, b, x, p256_mod);
  34994. sp_256_mont_dbl_8(b, t2, p256_mod);
  34995. /* Z = Z*Y */
  34996. sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod);
  34997. /* t1 = Y^4 */
  34998. sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod);
  34999. #ifdef WOLFSSL_SP_SMALL
  35000. if (n != 0)
  35001. #endif
  35002. {
  35003. /* W = W*Y^4 */
  35004. sp_256_mont_mul_8(w, w, t1, p256_mod, p256_mp_mod);
  35005. }
  35006. /* y = 2*A*(B - X) - Y^4 */
  35007. sp_256_mont_mul_8(y, b, a, p256_mod, p256_mp_mod);
  35008. sp_256_mont_sub_8(y, y, t1, p256_mod);
  35009. }
  35010. #ifndef WOLFSSL_SP_SMALL
  35011. /* A = 3*(X^2 - W) */
  35012. sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod);
  35013. sp_256_mont_sub_8(t1, t1, w, p256_mod);
  35014. sp_256_mont_tpl_8(a, t1, p256_mod);
  35015. /* B = X*Y^2 */
  35016. sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod);
  35017. sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod);
  35018. /* X = A^2 - 2B */
  35019. sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod);
  35020. sp_256_mont_dbl_8(t2, b, p256_mod);
  35021. sp_256_mont_sub_8(x, x, t2, p256_mod);
  35022. /* B = 2.(B - X) */
  35023. sp_256_mont_sub_8(t2, b, x, p256_mod);
  35024. sp_256_mont_dbl_8(b, t2, p256_mod);
  35025. /* Z = Z*Y */
  35026. sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod);
  35027. /* t1 = Y^4 */
  35028. sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod);
  35029. /* y = 2*A*(B - X) - Y^4 */
  35030. sp_256_mont_mul_8(y, b, a, p256_mod, p256_mp_mod);
  35031. sp_256_mont_sub_8(y, y, t1, p256_mod);
  35032. #endif /* WOLFSSL_SP_SMALL */
  35033. /* Y = Y/2 */
  35034. sp_256_mont_div2_8(y, y, p256_mod);
  35035. }
  35036. /* Convert the projective point to affine.
  35037. * Ordinates are in Montgomery form.
  35038. *
  35039. * a Point to convert.
  35040. * t Temporary data.
  35041. */
  35042. static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t)
  35043. {
  35044. sp_digit* t1 = t;
  35045. sp_digit* t2 = t + 2 * 8;
  35046. sp_digit* tmp = t + 4 * 8;
  35047. sp_256_mont_inv_8(t1, a->z, tmp);
  35048. sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
  35049. sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
  35050. sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod);
  35051. sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod);
  35052. XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
  35053. }
  35054. #endif /* FP_ECC */
  35055. /* A table entry for pre-computed points. */
  35056. typedef struct sp_table_entry_256 {
  35057. sp_digit x[8];
  35058. sp_digit y[8];
  35059. } sp_table_entry_256;
  35060. #ifdef FP_ECC
  35061. #endif /* FP_ECC */
  35062. /* Add two Montgomery form projective points. The second point has a q value of
  35063. * one.
  35064. * Only the first point can be the same pointer as the result point.
  35065. *
  35066. * r Result of addition.
  35067. * p First point to add.
  35068. * q Second point to add.
  35069. * t Temporary ordinate data.
  35070. */
  35071. static void sp_256_proj_point_add_qz1_8(sp_point_256* r,
  35072. const sp_point_256* p, const sp_point_256* q, sp_digit* t)
  35073. {
  35074. sp_digit* t2 = t;
  35075. sp_digit* t3 = t + 2*8;
  35076. sp_digit* t6 = t + 4*8;
  35077. sp_digit* t1 = t + 6*8;
  35078. sp_digit* t4 = t + 8*8;
  35079. sp_digit* t5 = t + 10*8;
  35080. /* Calculate values to subtract from P->x and P->y. */
  35081. /* U2 = X2*Z1^2 */
  35082. sp_256_mont_sqr_8(t2, p->z, p256_mod, p256_mp_mod);
  35083. sp_256_mont_mul_8(t4, t2, p->z, p256_mod, p256_mp_mod);
  35084. sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod);
  35085. /* S2 = Y2*Z1^3 */
  35086. sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod);
  35087. if ((~p->infinity) & (~q->infinity) &
  35088. sp_256_cmp_equal_8(p->x, t2) &
  35089. sp_256_cmp_equal_8(p->y, t4)) {
  35090. sp_256_proj_point_dbl_8(r, p, t);
  35091. }
  35092. else {
  35093. sp_digit* x = t2;
  35094. sp_digit* y = t3;
  35095. sp_digit* z = t6;
  35096. /* H = U2 - X1 */
  35097. sp_256_mont_sub_8(t2, t2, p->x, p256_mod);
  35098. /* R = S2 - Y1 */
  35099. sp_256_mont_sub_8(t4, t4, p->y, p256_mod);
  35100. /* Z3 = H*Z1 */
  35101. sp_256_mont_mul_8(z, p->z, t2, p256_mod, p256_mp_mod);
  35102. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  35103. sp_256_mont_sqr_8(t1, t2, p256_mod, p256_mp_mod);
  35104. sp_256_mont_mul_8(t3, p->x, t1, p256_mod, p256_mp_mod);
  35105. sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
  35106. sp_256_mont_sqr_8(t2, t4, p256_mod, p256_mp_mod);
  35107. sp_256_mont_sub_8(t2, t2, t1, p256_mod);
  35108. sp_256_mont_dbl_8(t5, t3, p256_mod);
  35109. sp_256_mont_sub_8(x, t2, t5, p256_mod);
  35110. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  35111. sp_256_mont_sub_8(t3, t3, x, p256_mod);
  35112. sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod);
  35113. sp_256_mont_mul_8(t1, t1, p->y, p256_mod, p256_mp_mod);
  35114. sp_256_mont_sub_8(y, t3, t1, p256_mod);
  35115. {
  35116. int i;
  35117. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  35118. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  35119. sp_digit maskt = ~(maskp | maskq);
  35120. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  35121. for (i = 0; i < 8; i++) {
  35122. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  35123. (x[i] & maskt);
  35124. }
  35125. for (i = 0; i < 8; i++) {
  35126. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  35127. (y[i] & maskt);
  35128. }
  35129. for (i = 0; i < 8; i++) {
  35130. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  35131. (z[i] & maskt);
  35132. }
  35133. r->z[0] |= inf;
  35134. r->infinity = (word32)inf;
  35135. }
  35136. }
  35137. }
  35138. #ifdef WOLFSSL_SP_SMALL
  35139. #ifdef FP_ECC
  35140. /* Generate the pre-computed table of points for the base point.
  35141. *
  35142. * width = 4
  35143. * 16 entries
  35144. * 64 bits between
  35145. *
  35146. * a The base point.
  35147. * table Place to store generated point data.
  35148. * tmp Temporary data.
  35149. * heap Heap to use for allocation.
  35150. */
  35151. static int sp_256_gen_stripe_table_8(const sp_point_256* a,
  35152. sp_table_entry_256* table, sp_digit* tmp, void* heap)
  35153. {
  35154. #ifdef WOLFSSL_SP_SMALL_STACK
  35155. sp_point_256* t = NULL;
  35156. #else
  35157. sp_point_256 t[3];
  35158. #endif
  35159. sp_point_256* s1 = NULL;
  35160. sp_point_256* s2 = NULL;
  35161. int i;
  35162. int j;
  35163. int err = MP_OKAY;
  35164. (void)heap;
  35165. #ifdef WOLFSSL_SP_SMALL_STACK
  35166. t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap,
  35167. DYNAMIC_TYPE_ECC);
  35168. if (t == NULL)
  35169. err = MEMORY_E;
  35170. #endif
  35171. if (err == MP_OKAY) {
  35172. s1 = t + 1;
  35173. s2 = t + 2;
  35174. err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod);
  35175. }
  35176. if (err == MP_OKAY) {
  35177. err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod);
  35178. }
  35179. if (err == MP_OKAY) {
  35180. err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod);
  35181. }
  35182. if (err == MP_OKAY) {
  35183. t->infinity = 0;
  35184. sp_256_proj_to_affine_8(t, tmp);
  35185. XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
  35186. s1->infinity = 0;
  35187. XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
  35188. s2->infinity = 0;
  35189. /* table[0] = {0, 0, infinity} */
  35190. XMEMSET(&table[0], 0, sizeof(sp_table_entry_256));
  35191. /* table[1] = Affine version of 'a' in Montgomery form */
  35192. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  35193. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  35194. for (i=1; i<4; i++) {
  35195. sp_256_proj_point_dbl_n_8(t, 64, tmp);
  35196. sp_256_proj_to_affine_8(t, tmp);
  35197. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  35198. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  35199. }
  35200. for (i=1; i<4; i++) {
  35201. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  35202. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  35203. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  35204. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  35205. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  35206. sp_256_proj_point_add_qz1_8(t, s1, s2, tmp);
  35207. sp_256_proj_to_affine_8(t, tmp);
  35208. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  35209. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  35210. }
  35211. }
  35212. }
  35213. #ifdef WOLFSSL_SP_SMALL_STACK
  35214. if (t != NULL)
  35215. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  35216. #endif
  35217. return err;
  35218. }
  35219. #endif /* FP_ECC */
  35220. #ifndef WC_NO_CACHE_RESISTANT
  35221. /* Touch each possible entry that could be being copied.
  35222. *
  35223. * r Point to copy into.
  35224. * table Table - start of the entries to access
  35225. * idx Index of entry to retrieve.
  35226. */
  35227. static void sp_256_get_entry_16_8(sp_point_256* r,
  35228. const sp_table_entry_256* table, int idx)
  35229. {
  35230. int i;
  35231. sp_digit mask;
  35232. r->x[0] = 0;
  35233. r->x[1] = 0;
  35234. r->x[2] = 0;
  35235. r->x[3] = 0;
  35236. r->x[4] = 0;
  35237. r->x[5] = 0;
  35238. r->x[6] = 0;
  35239. r->x[7] = 0;
  35240. r->y[0] = 0;
  35241. r->y[1] = 0;
  35242. r->y[2] = 0;
  35243. r->y[3] = 0;
  35244. r->y[4] = 0;
  35245. r->y[5] = 0;
  35246. r->y[6] = 0;
  35247. r->y[7] = 0;
  35248. for (i = 1; i < 16; i++) {
  35249. mask = 0 - (i == idx);
  35250. r->x[0] |= mask & table[i].x[0];
  35251. r->x[1] |= mask & table[i].x[1];
  35252. r->x[2] |= mask & table[i].x[2];
  35253. r->x[3] |= mask & table[i].x[3];
  35254. r->x[4] |= mask & table[i].x[4];
  35255. r->x[5] |= mask & table[i].x[5];
  35256. r->x[6] |= mask & table[i].x[6];
  35257. r->x[7] |= mask & table[i].x[7];
  35258. r->y[0] |= mask & table[i].y[0];
  35259. r->y[1] |= mask & table[i].y[1];
  35260. r->y[2] |= mask & table[i].y[2];
  35261. r->y[3] |= mask & table[i].y[3];
  35262. r->y[4] |= mask & table[i].y[4];
  35263. r->y[5] |= mask & table[i].y[5];
  35264. r->y[6] |= mask & table[i].y[6];
  35265. r->y[7] |= mask & table[i].y[7];
  35266. }
  35267. }
  35268. #endif /* !WC_NO_CACHE_RESISTANT */
  35269. /* Multiply the point by the scalar and return the result.
  35270. * If map is true then convert result to affine coordinates.
  35271. *
  35272. * Stripe implementation.
  35273. * Pre-generated: 2^0, 2^64, ...
  35274. * Pre-generated: products of all combinations of above.
  35275. * 4 doubles and adds (with qz=1)
  35276. *
  35277. * r Resulting point.
  35278. * k Scalar to multiply by.
  35279. * table Pre-computed table.
  35280. * map Indicates whether to convert result to affine.
  35281. * ct Constant time required.
  35282. * heap Heap to use for allocation.
  35283. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35284. */
  35285. static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
  35286. const sp_table_entry_256* table, const sp_digit* k, int map,
  35287. int ct, void* heap)
  35288. {
  35289. #ifdef WOLFSSL_SP_SMALL_STACK
  35290. sp_point_256* rt = NULL;
  35291. sp_digit* t = NULL;
  35292. #else
  35293. sp_point_256 rt[2];
  35294. sp_digit t[2 * 8 * 6];
  35295. #endif
  35296. sp_point_256* p = NULL;
  35297. int i;
  35298. int j;
  35299. int y;
  35300. int x;
  35301. int err = MP_OKAY;
  35302. (void)g;
  35303. /* Constant time used for cache attack resistance implementation. */
  35304. (void)ct;
  35305. (void)heap;
  35306. #ifdef WOLFSSL_SP_SMALL_STACK
  35307. rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  35308. DYNAMIC_TYPE_ECC);
  35309. if (rt == NULL)
  35310. err = MEMORY_E;
  35311. if (err == MP_OKAY) {
  35312. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 6, heap,
  35313. DYNAMIC_TYPE_ECC);
  35314. if (t == NULL)
  35315. err = MEMORY_E;
  35316. }
  35317. #endif
  35318. if (err == MP_OKAY) {
  35319. p = rt + 1;
  35320. XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
  35321. XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
  35322. y = 0;
  35323. x = 63;
  35324. for (j=0; j<4; j++) {
  35325. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  35326. x += 64;
  35327. }
  35328. #ifndef WC_NO_CACHE_RESISTANT
  35329. if (ct) {
  35330. sp_256_get_entry_16_8(rt, table, y);
  35331. } else
  35332. #endif
  35333. {
  35334. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  35335. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  35336. }
  35337. rt->infinity = !y;
  35338. for (i=62; i>=0; i--) {
  35339. y = 0;
  35340. x = i;
  35341. for (j=0; j<4; j++) {
  35342. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  35343. x += 64;
  35344. }
  35345. sp_256_proj_point_dbl_8(rt, rt, t);
  35346. #ifndef WC_NO_CACHE_RESISTANT
  35347. if (ct) {
  35348. sp_256_get_entry_16_8(p, table, y);
  35349. }
  35350. else
  35351. #endif
  35352. {
  35353. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  35354. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  35355. }
  35356. p->infinity = !y;
  35357. sp_256_proj_point_add_qz1_8(rt, rt, p, t);
  35358. }
  35359. if (map != 0) {
  35360. sp_256_map_8(r, rt, t);
  35361. }
  35362. else {
  35363. XMEMCPY(r, rt, sizeof(sp_point_256));
  35364. }
  35365. }
  35366. #ifdef WOLFSSL_SP_SMALL_STACK
  35367. if (t != NULL)
  35368. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  35369. if (rt != NULL)
  35370. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  35371. #endif
  35372. return err;
  35373. }
  35374. #ifdef FP_ECC
  35375. #ifndef FP_ENTRIES
  35376. #define FP_ENTRIES 16
  35377. #endif
  35378. /* Cache entry - holds precomputation tables for a point. */
  35379. typedef struct sp_cache_256_t {
  35380. /* X ordinate of point that table was generated from. */
  35381. sp_digit x[8];
  35382. /* Y ordinate of point that table was generated from. */
  35383. sp_digit y[8];
  35384. /* Precomputation table for point. */
  35385. sp_table_entry_256 table[16];
  35386. /* Count of entries in table. */
  35387. uint32_t cnt;
  35388. /* Point and table set in entry. */
  35389. int set;
  35390. } sp_cache_256_t;
  35391. /* Cache of tables. */
  35392. static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
  35393. /* Index of last entry in cache. */
  35394. static THREAD_LS_T int sp_cache_256_last = -1;
  35395. /* Cache has been initialized. */
  35396. static THREAD_LS_T int sp_cache_256_inited = 0;
  35397. #ifndef HAVE_THREAD_LS
  35398. static volatile int initCacheMutex_256 = 0;
  35399. static wolfSSL_Mutex sp_cache_256_lock;
  35400. #endif
  35401. /* Get the cache entry for the point.
  35402. *
  35403. * g [in] Point scalar multiplying.
  35404. * cache [out] Cache table to use.
  35405. */
  35406. static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
  35407. {
  35408. int i;
  35409. int j;
  35410. uint32_t least;
  35411. if (sp_cache_256_inited == 0) {
  35412. for (i=0; i<FP_ENTRIES; i++) {
  35413. sp_cache_256[i].set = 0;
  35414. }
  35415. sp_cache_256_inited = 1;
  35416. }
  35417. /* Compare point with those in cache. */
  35418. for (i=0; i<FP_ENTRIES; i++) {
  35419. if (!sp_cache_256[i].set)
  35420. continue;
  35421. if (sp_256_cmp_equal_8(g->x, sp_cache_256[i].x) &
  35422. sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) {
  35423. sp_cache_256[i].cnt++;
  35424. break;
  35425. }
  35426. }
  35427. /* No match. */
  35428. if (i == FP_ENTRIES) {
  35429. /* Find empty entry. */
  35430. i = (sp_cache_256_last + 1) % FP_ENTRIES;
  35431. for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) {
  35432. if (!sp_cache_256[i].set) {
  35433. break;
  35434. }
  35435. }
  35436. /* Evict least used. */
  35437. if (i == sp_cache_256_last) {
  35438. least = sp_cache_256[0].cnt;
  35439. for (j=1; j<FP_ENTRIES; j++) {
  35440. if (sp_cache_256[j].cnt < least) {
  35441. i = j;
  35442. least = sp_cache_256[i].cnt;
  35443. }
  35444. }
  35445. }
  35446. XMEMCPY(sp_cache_256[i].x, g->x, sizeof(sp_cache_256[i].x));
  35447. XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y));
  35448. sp_cache_256[i].set = 1;
  35449. sp_cache_256[i].cnt = 1;
  35450. }
  35451. *cache = &sp_cache_256[i];
  35452. sp_cache_256_last = i;
  35453. }
  35454. #endif /* FP_ECC */
  35455. /* Multiply the base point of P256 by the scalar and return the result.
  35456. * If map is true then convert result to affine coordinates.
  35457. *
  35458. * r Resulting point.
  35459. * g Point to multiply.
  35460. * k Scalar to multiply by.
  35461. * map Indicates whether to convert result to affine.
  35462. * ct Constant time required.
  35463. * heap Heap to use for allocation.
  35464. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35465. */
  35466. static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g,
  35467. const sp_digit* k, int map, int ct, void* heap)
  35468. {
  35469. #ifndef FP_ECC
  35470. return sp_256_ecc_mulmod_fast_8(r, g, k, map, ct, heap);
  35471. #else
  35472. #ifdef WOLFSSL_SP_SMALL_STACK
  35473. sp_digit* tmp;
  35474. #else
  35475. sp_digit tmp[2 * 8 * 6];
  35476. #endif
  35477. sp_cache_256_t* cache;
  35478. int err = MP_OKAY;
  35479. #ifdef WOLFSSL_SP_SMALL_STACK
  35480. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 6, heap, DYNAMIC_TYPE_ECC);
  35481. if (tmp == NULL) {
  35482. err = MEMORY_E;
  35483. }
  35484. #endif
  35485. #ifndef HAVE_THREAD_LS
  35486. if (err == MP_OKAY) {
  35487. if (initCacheMutex_256 == 0) {
  35488. wc_InitMutex(&sp_cache_256_lock);
  35489. initCacheMutex_256 = 1;
  35490. }
  35491. if (wc_LockMutex(&sp_cache_256_lock) != 0) {
  35492. err = BAD_MUTEX_E;
  35493. }
  35494. }
  35495. #endif /* HAVE_THREAD_LS */
  35496. if (err == MP_OKAY) {
  35497. sp_ecc_get_cache_256(g, &cache);
  35498. if (cache->cnt == 2)
  35499. sp_256_gen_stripe_table_8(g, cache->table, tmp, heap);
  35500. #ifndef HAVE_THREAD_LS
  35501. wc_UnLockMutex(&sp_cache_256_lock);
  35502. #endif /* HAVE_THREAD_LS */
  35503. if (cache->cnt < 2) {
  35504. err = sp_256_ecc_mulmod_fast_8(r, g, k, map, ct, heap);
  35505. }
  35506. else {
  35507. err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k,
  35508. map, ct, heap);
  35509. }
  35510. }
  35511. #ifdef WOLFSSL_SP_SMALL_STACK
  35512. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  35513. #endif
  35514. return err;
  35515. #endif
  35516. }
  35517. #else
  35518. #ifdef FP_ECC
  35519. /* Generate the pre-computed table of points for the base point.
  35520. *
  35521. * width = 8
  35522. * 256 entries
  35523. * 32 bits between
  35524. *
  35525. * a The base point.
  35526. * table Place to store generated point data.
  35527. * tmp Temporary data.
  35528. * heap Heap to use for allocation.
  35529. */
  35530. static int sp_256_gen_stripe_table_8(const sp_point_256* a,
  35531. sp_table_entry_256* table, sp_digit* tmp, void* heap)
  35532. {
  35533. #ifdef WOLFSSL_SP_SMALL_STACK
  35534. sp_point_256* t = NULL;
  35535. #else
  35536. sp_point_256 t[3];
  35537. #endif
  35538. sp_point_256* s1 = NULL;
  35539. sp_point_256* s2 = NULL;
  35540. int i;
  35541. int j;
  35542. int err = MP_OKAY;
  35543. (void)heap;
  35544. #ifdef WOLFSSL_SP_SMALL_STACK
  35545. t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap,
  35546. DYNAMIC_TYPE_ECC);
  35547. if (t == NULL)
  35548. err = MEMORY_E;
  35549. #endif
  35550. if (err == MP_OKAY) {
  35551. s1 = t + 1;
  35552. s2 = t + 2;
  35553. err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod);
  35554. }
  35555. if (err == MP_OKAY) {
  35556. err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod);
  35557. }
  35558. if (err == MP_OKAY) {
  35559. err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod);
  35560. }
  35561. if (err == MP_OKAY) {
  35562. t->infinity = 0;
  35563. sp_256_proj_to_affine_8(t, tmp);
  35564. XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
  35565. s1->infinity = 0;
  35566. XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
  35567. s2->infinity = 0;
  35568. /* table[0] = {0, 0, infinity} */
  35569. XMEMSET(&table[0], 0, sizeof(sp_table_entry_256));
  35570. /* table[1] = Affine version of 'a' in Montgomery form */
  35571. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  35572. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  35573. for (i=1; i<8; i++) {
  35574. sp_256_proj_point_dbl_n_8(t, 32, tmp);
  35575. sp_256_proj_to_affine_8(t, tmp);
  35576. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  35577. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  35578. }
  35579. for (i=1; i<8; i++) {
  35580. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  35581. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  35582. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  35583. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  35584. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  35585. sp_256_proj_point_add_qz1_8(t, s1, s2, tmp);
  35586. sp_256_proj_to_affine_8(t, tmp);
  35587. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  35588. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  35589. }
  35590. }
  35591. }
  35592. #ifdef WOLFSSL_SP_SMALL_STACK
  35593. if (t != NULL)
  35594. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  35595. #endif
  35596. return err;
  35597. }
  35598. #endif /* FP_ECC */
  35599. #ifndef WC_NO_CACHE_RESISTANT
  35600. /* Touch each possible entry that could be being copied.
  35601. *
  35602. * r Point to copy into.
  35603. * table Table - start of the entries to access
  35604. * idx Index of entry to retrieve.
  35605. */
  35606. static void sp_256_get_entry_256_8(sp_point_256* r,
  35607. const sp_table_entry_256* table, int idx)
  35608. {
  35609. int i;
  35610. sp_digit mask;
  35611. r->x[0] = 0;
  35612. r->x[1] = 0;
  35613. r->x[2] = 0;
  35614. r->x[3] = 0;
  35615. r->x[4] = 0;
  35616. r->x[5] = 0;
  35617. r->x[6] = 0;
  35618. r->x[7] = 0;
  35619. r->y[0] = 0;
  35620. r->y[1] = 0;
  35621. r->y[2] = 0;
  35622. r->y[3] = 0;
  35623. r->y[4] = 0;
  35624. r->y[5] = 0;
  35625. r->y[6] = 0;
  35626. r->y[7] = 0;
  35627. for (i = 1; i < 256; i++) {
  35628. mask = 0 - (i == idx);
  35629. r->x[0] |= mask & table[i].x[0];
  35630. r->x[1] |= mask & table[i].x[1];
  35631. r->x[2] |= mask & table[i].x[2];
  35632. r->x[3] |= mask & table[i].x[3];
  35633. r->x[4] |= mask & table[i].x[4];
  35634. r->x[5] |= mask & table[i].x[5];
  35635. r->x[6] |= mask & table[i].x[6];
  35636. r->x[7] |= mask & table[i].x[7];
  35637. r->y[0] |= mask & table[i].y[0];
  35638. r->y[1] |= mask & table[i].y[1];
  35639. r->y[2] |= mask & table[i].y[2];
  35640. r->y[3] |= mask & table[i].y[3];
  35641. r->y[4] |= mask & table[i].y[4];
  35642. r->y[5] |= mask & table[i].y[5];
  35643. r->y[6] |= mask & table[i].y[6];
  35644. r->y[7] |= mask & table[i].y[7];
  35645. }
  35646. }
  35647. #endif /* !WC_NO_CACHE_RESISTANT */
  35648. /* Multiply the point by the scalar and return the result.
  35649. * If map is true then convert result to affine coordinates.
  35650. *
  35651. * Stripe implementation.
  35652. * Pre-generated: 2^0, 2^32, ...
  35653. * Pre-generated: products of all combinations of above.
  35654. * 8 doubles and adds (with qz=1)
  35655. *
  35656. * r Resulting point.
  35657. * k Scalar to multiply by.
  35658. * table Pre-computed table.
  35659. * map Indicates whether to convert result to affine.
  35660. * ct Constant time required.
  35661. * heap Heap to use for allocation.
  35662. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35663. */
  35664. static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g,
  35665. const sp_table_entry_256* table, const sp_digit* k, int map,
  35666. int ct, void* heap)
  35667. {
  35668. #ifdef WOLFSSL_SP_SMALL_STACK
  35669. sp_point_256* rt = NULL;
  35670. sp_digit* t = NULL;
  35671. #else
  35672. sp_point_256 rt[2];
  35673. sp_digit t[2 * 8 * 6];
  35674. #endif
  35675. sp_point_256* p = NULL;
  35676. int i;
  35677. int j;
  35678. int y;
  35679. int x;
  35680. int err = MP_OKAY;
  35681. (void)g;
  35682. /* Constant time used for cache attack resistance implementation. */
  35683. (void)ct;
  35684. (void)heap;
  35685. #ifdef WOLFSSL_SP_SMALL_STACK
  35686. rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  35687. DYNAMIC_TYPE_ECC);
  35688. if (rt == NULL)
  35689. err = MEMORY_E;
  35690. if (err == MP_OKAY) {
  35691. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 6, heap,
  35692. DYNAMIC_TYPE_ECC);
  35693. if (t == NULL)
  35694. err = MEMORY_E;
  35695. }
  35696. #endif
  35697. if (err == MP_OKAY) {
  35698. p = rt + 1;
  35699. XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
  35700. XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
  35701. y = 0;
  35702. x = 31;
  35703. for (j=0; j<8; j++) {
  35704. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  35705. x += 32;
  35706. }
  35707. #ifndef WC_NO_CACHE_RESISTANT
  35708. if (ct) {
  35709. sp_256_get_entry_256_8(rt, table, y);
  35710. } else
  35711. #endif
  35712. {
  35713. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  35714. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  35715. }
  35716. rt->infinity = !y;
  35717. for (i=30; i>=0; i--) {
  35718. y = 0;
  35719. x = i;
  35720. for (j=0; j<8; j++) {
  35721. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  35722. x += 32;
  35723. }
  35724. sp_256_proj_point_dbl_8(rt, rt, t);
  35725. #ifndef WC_NO_CACHE_RESISTANT
  35726. if (ct) {
  35727. sp_256_get_entry_256_8(p, table, y);
  35728. }
  35729. else
  35730. #endif
  35731. {
  35732. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  35733. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  35734. }
  35735. p->infinity = !y;
  35736. sp_256_proj_point_add_qz1_8(rt, rt, p, t);
  35737. }
  35738. if (map != 0) {
  35739. sp_256_map_8(r, rt, t);
  35740. }
  35741. else {
  35742. XMEMCPY(r, rt, sizeof(sp_point_256));
  35743. }
  35744. }
  35745. #ifdef WOLFSSL_SP_SMALL_STACK
  35746. if (t != NULL)
  35747. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  35748. if (rt != NULL)
  35749. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  35750. #endif
  35751. return err;
  35752. }
  35753. #ifdef FP_ECC
  35754. #ifndef FP_ENTRIES
  35755. #define FP_ENTRIES 16
  35756. #endif
  35757. /* Cache entry - holds precomputation tables for a point. */
  35758. typedef struct sp_cache_256_t {
  35759. /* X ordinate of point that table was generated from. */
  35760. sp_digit x[8];
  35761. /* Y ordinate of point that table was generated from. */
  35762. sp_digit y[8];
  35763. /* Precomputation table for point. */
  35764. sp_table_entry_256 table[256];
  35765. /* Count of entries in table. */
  35766. uint32_t cnt;
  35767. /* Point and table set in entry. */
  35768. int set;
  35769. } sp_cache_256_t;
  35770. /* Cache of tables. */
  35771. static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
  35772. /* Index of last entry in cache. */
  35773. static THREAD_LS_T int sp_cache_256_last = -1;
  35774. /* Cache has been initialized. */
  35775. static THREAD_LS_T int sp_cache_256_inited = 0;
  35776. #ifndef HAVE_THREAD_LS
  35777. static volatile int initCacheMutex_256 = 0;
  35778. static wolfSSL_Mutex sp_cache_256_lock;
  35779. #endif
  35780. /* Get the cache entry for the point.
  35781. *
  35782. * g [in] Point scalar multiplying.
  35783. * cache [out] Cache table to use.
  35784. */
  35785. static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
  35786. {
  35787. int i;
  35788. int j;
  35789. uint32_t least;
  35790. if (sp_cache_256_inited == 0) {
  35791. for (i=0; i<FP_ENTRIES; i++) {
  35792. sp_cache_256[i].set = 0;
  35793. }
  35794. sp_cache_256_inited = 1;
  35795. }
  35796. /* Compare point with those in cache. */
  35797. for (i=0; i<FP_ENTRIES; i++) {
  35798. if (!sp_cache_256[i].set)
  35799. continue;
  35800. if (sp_256_cmp_equal_8(g->x, sp_cache_256[i].x) &
  35801. sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) {
  35802. sp_cache_256[i].cnt++;
  35803. break;
  35804. }
  35805. }
  35806. /* No match. */
  35807. if (i == FP_ENTRIES) {
  35808. /* Find empty entry. */
  35809. i = (sp_cache_256_last + 1) % FP_ENTRIES;
  35810. for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) {
  35811. if (!sp_cache_256[i].set) {
  35812. break;
  35813. }
  35814. }
  35815. /* Evict least used. */
  35816. if (i == sp_cache_256_last) {
  35817. least = sp_cache_256[0].cnt;
  35818. for (j=1; j<FP_ENTRIES; j++) {
  35819. if (sp_cache_256[j].cnt < least) {
  35820. i = j;
  35821. least = sp_cache_256[i].cnt;
  35822. }
  35823. }
  35824. }
  35825. XMEMCPY(sp_cache_256[i].x, g->x, sizeof(sp_cache_256[i].x));
  35826. XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y));
  35827. sp_cache_256[i].set = 1;
  35828. sp_cache_256[i].cnt = 1;
  35829. }
  35830. *cache = &sp_cache_256[i];
  35831. sp_cache_256_last = i;
  35832. }
  35833. #endif /* FP_ECC */
  35834. /* Multiply the base point of P256 by the scalar and return the result.
  35835. * If map is true then convert result to affine coordinates.
  35836. *
  35837. * r Resulting point.
  35838. * g Point to multiply.
  35839. * k Scalar to multiply by.
  35840. * map Indicates whether to convert result to affine.
  35841. * ct Constant time required.
  35842. * heap Heap to use for allocation.
  35843. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35844. */
  35845. static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g,
  35846. const sp_digit* k, int map, int ct, void* heap)
  35847. {
  35848. #ifndef FP_ECC
  35849. return sp_256_ecc_mulmod_fast_8(r, g, k, map, ct, heap);
  35850. #else
  35851. #ifdef WOLFSSL_SP_SMALL_STACK
  35852. sp_digit* tmp;
  35853. #else
  35854. sp_digit tmp[2 * 8 * 6];
  35855. #endif
  35856. sp_cache_256_t* cache;
  35857. int err = MP_OKAY;
  35858. #ifdef WOLFSSL_SP_SMALL_STACK
  35859. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 6, heap, DYNAMIC_TYPE_ECC);
  35860. if (tmp == NULL) {
  35861. err = MEMORY_E;
  35862. }
  35863. #endif
  35864. #ifndef HAVE_THREAD_LS
  35865. if (err == MP_OKAY) {
  35866. if (initCacheMutex_256 == 0) {
  35867. wc_InitMutex(&sp_cache_256_lock);
  35868. initCacheMutex_256 = 1;
  35869. }
  35870. if (wc_LockMutex(&sp_cache_256_lock) != 0) {
  35871. err = BAD_MUTEX_E;
  35872. }
  35873. }
  35874. #endif /* HAVE_THREAD_LS */
  35875. if (err == MP_OKAY) {
  35876. sp_ecc_get_cache_256(g, &cache);
  35877. if (cache->cnt == 2)
  35878. sp_256_gen_stripe_table_8(g, cache->table, tmp, heap);
  35879. #ifndef HAVE_THREAD_LS
  35880. wc_UnLockMutex(&sp_cache_256_lock);
  35881. #endif /* HAVE_THREAD_LS */
  35882. if (cache->cnt < 2) {
  35883. err = sp_256_ecc_mulmod_fast_8(r, g, k, map, ct, heap);
  35884. }
  35885. else {
  35886. err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k,
  35887. map, ct, heap);
  35888. }
  35889. }
  35890. #ifdef WOLFSSL_SP_SMALL_STACK
  35891. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  35892. #endif
  35893. return err;
  35894. #endif
  35895. }
  35896. #endif /* WOLFSSL_SP_SMALL */
  35897. /* Multiply the point by the scalar and return the result.
  35898. * If map is true then convert result to affine coordinates.
  35899. *
  35900. * km Scalar to multiply by.
  35901. * p Point to multiply.
  35902. * r Resulting point.
  35903. * map Indicates whether to convert result to affine.
  35904. * heap Heap to use for allocation.
  35905. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35906. */
  35907. int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r,
  35908. int map, void* heap)
  35909. {
  35910. #ifdef WOLFSSL_SP_SMALL_STACK
  35911. sp_point_256* point = NULL;
  35912. sp_digit* k = NULL;
  35913. #else
  35914. sp_point_256 point[1];
  35915. sp_digit k[8];
  35916. #endif
  35917. int err = MP_OKAY;
  35918. #ifdef WOLFSSL_SP_SMALL_STACK
  35919. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  35920. DYNAMIC_TYPE_ECC);
  35921. if (point == NULL)
  35922. err = MEMORY_E;
  35923. if (err == MP_OKAY) {
  35924. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
  35925. DYNAMIC_TYPE_ECC);
  35926. if (k == NULL)
  35927. err = MEMORY_E;
  35928. }
  35929. #endif
  35930. if (err == MP_OKAY) {
  35931. sp_256_from_mp(k, 8, km);
  35932. sp_256_point_from_ecc_point_8(point, gm);
  35933. err = sp_256_ecc_mulmod_8(point, point, k, map, 1, heap);
  35934. }
  35935. if (err == MP_OKAY) {
  35936. err = sp_256_point_to_ecc_point_8(point, r);
  35937. }
  35938. #ifdef WOLFSSL_SP_SMALL_STACK
  35939. if (k != NULL)
  35940. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  35941. if (point != NULL)
  35942. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  35943. #endif
  35944. return err;
  35945. }
  35946. /* Multiply the point by the scalar, add point a and return the result.
  35947. * If map is true then convert result to affine coordinates.
  35948. *
  35949. * km Scalar to multiply by.
  35950. * p Point to multiply.
  35951. * am Point to add to scalar multiply result.
  35952. * inMont Point to add is in montgomery form.
  35953. * r Resulting point.
  35954. * map Indicates whether to convert result to affine.
  35955. * heap Heap to use for allocation.
  35956. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35957. */
  35958. int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm,
  35959. const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
  35960. {
  35961. #ifdef WOLFSSL_SP_SMALL_STACK
  35962. sp_point_256* point = NULL;
  35963. sp_digit* k = NULL;
  35964. #else
  35965. sp_point_256 point[2];
  35966. sp_digit k[8 + 8 * 2 * 6];
  35967. #endif
  35968. sp_point_256* addP = NULL;
  35969. sp_digit* tmp = NULL;
  35970. int err = MP_OKAY;
  35971. #ifdef WOLFSSL_SP_SMALL_STACK
  35972. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  35973. DYNAMIC_TYPE_ECC);
  35974. if (point == NULL)
  35975. err = MEMORY_E;
  35976. if (err == MP_OKAY) {
  35977. k = (sp_digit*)XMALLOC(
  35978. sizeof(sp_digit) * (8 + 8 * 2 * 6), heap,
  35979. DYNAMIC_TYPE_ECC);
  35980. if (k == NULL)
  35981. err = MEMORY_E;
  35982. }
  35983. #endif
  35984. if (err == MP_OKAY) {
  35985. addP = point + 1;
  35986. tmp = k + 8;
  35987. sp_256_from_mp(k, 8, km);
  35988. sp_256_point_from_ecc_point_8(point, gm);
  35989. sp_256_point_from_ecc_point_8(addP, am);
  35990. }
  35991. if ((err == MP_OKAY) && (!inMont)) {
  35992. err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
  35993. }
  35994. if ((err == MP_OKAY) && (!inMont)) {
  35995. err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
  35996. }
  35997. if ((err == MP_OKAY) && (!inMont)) {
  35998. err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
  35999. }
  36000. if (err == MP_OKAY) {
  36001. err = sp_256_ecc_mulmod_8(point, point, k, 0, 0, heap);
  36002. }
  36003. if (err == MP_OKAY) {
  36004. sp_256_proj_point_add_8(point, point, addP, tmp);
  36005. if (map) {
  36006. sp_256_map_8(point, point, tmp);
  36007. }
  36008. err = sp_256_point_to_ecc_point_8(point, r);
  36009. }
  36010. #ifdef WOLFSSL_SP_SMALL_STACK
  36011. if (k != NULL)
  36012. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  36013. if (point != NULL)
  36014. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  36015. #endif
  36016. return err;
  36017. }
  36018. #ifdef WOLFSSL_SP_SMALL
  36019. /* Striping precomputation table.
  36020. * 4 points combined into a table of 16 points.
  36021. * Distance of 64 between points.
  36022. */
  36023. static const sp_table_entry_256 p256_table[16] = {
  36024. /* 0 */
  36025. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  36026. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  36027. /* 1 */
  36028. { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b,
  36029. 0xa53755c6,0x18905f76 },
  36030. { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688,
  36031. 0x25885d85,0x8571ff18 } },
  36032. /* 2 */
  36033. { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a,
  36034. 0xfd1b667f,0x2f5e6961 },
  36035. { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37,
  36036. 0x8d6f0f7b,0xf648f916 } },
  36037. /* 3 */
  36038. { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761,
  36039. 0x133d0015,0x5abe0285 },
  36040. { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562,
  36041. 0x6b6f7383,0x94bb725b } },
  36042. /* 4 */
  36043. { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5,
  36044. 0x21d324f6,0x61d587d4 },
  36045. { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e,
  36046. 0x4621efbe,0xfa11fe12 } },
  36047. /* 5 */
  36048. { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67,
  36049. 0x1f13bedc,0x586eb04c },
  36050. { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0,
  36051. 0x70864f11,0x19d5ac08 } },
  36052. /* 6 */
  36053. { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a,
  36054. 0xc3b266b1,0xbb6de651 },
  36055. { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1,
  36056. 0x5d18b99b,0x60b4619a } },
  36057. /* 7 */
  36058. { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014,
  36059. 0xaeebffcd,0x9d0f27b2 },
  36060. { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0,
  36061. 0x356ec48d,0x244a566d } },
  36062. /* 8 */
  36063. { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e,
  36064. 0xcd42ab1b,0x803f3e02 },
  36065. { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273,
  36066. 0x5067adc1,0xc097440e } },
  36067. /* 9 */
  36068. { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459,
  36069. 0x915f1f30,0xf1af32d5 },
  36070. { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418,
  36071. 0xe2d41c8b,0x23d0f130 } },
  36072. /* 10 */
  36073. { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926,
  36074. 0x7990216a,0x50bbb4d9 },
  36075. { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b,
  36076. 0x01fe49c3,0x2b100118 } },
  36077. /* 11 */
  36078. { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa,
  36079. 0x83fbae0c,0xdd558999 },
  36080. { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf,
  36081. 0x149d6041,0xe6e4c551 } },
  36082. /* 12 */
  36083. { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07,
  36084. 0xdb7e63af,0xfad27148 },
  36085. { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875,
  36086. 0x9f0e1a84,0x77387de3 } },
  36087. /* 13 */
  36088. { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408,
  36089. 0xbef0c47e,0xb37b85c0 },
  36090. { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa,
  36091. 0xf9f628d5,0x9c135ac8 } },
  36092. /* 14 */
  36093. { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403,
  36094. 0x91ece900,0xc109f9cb },
  36095. { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d,
  36096. 0x2eee1ee1,0x9bc3344f } },
  36097. /* 15 */
  36098. { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665,
  36099. 0x5f1a4cc1,0x29591d52 },
  36100. { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496,
  36101. 0x18ef332c,0x6376551f } },
  36102. };
  36103. /* Multiply the base point of P256 by the scalar and return the result.
  36104. * If map is true then convert result to affine coordinates.
  36105. *
  36106. * Stripe implementation.
  36107. * Pre-generated: 2^0, 2^64, ...
  36108. * Pre-generated: products of all combinations of above.
  36109. * 4 doubles and adds (with qz=1)
  36110. *
  36111. * r Resulting point.
  36112. * k Scalar to multiply by.
  36113. * map Indicates whether to convert result to affine.
  36114. * ct Constant time required.
  36115. * heap Heap to use for allocation.
  36116. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  36117. */
  36118. static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
  36119. int map, int ct, void* heap)
  36120. {
  36121. return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table,
  36122. k, map, ct, heap);
  36123. }
  36124. #else
  36125. /* Striping precomputation table.
  36126. * 8 points combined into a table of 256 points.
  36127. * Distance of 32 between points.
  36128. */
  36129. static const sp_table_entry_256 p256_table[256] = {
  36130. /* 0 */
  36131. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  36132. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  36133. /* 1 */
  36134. { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b,
  36135. 0xa53755c6,0x18905f76 },
  36136. { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688,
  36137. 0x25885d85,0x8571ff18 } },
  36138. /* 2 */
  36139. { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca,
  36140. 0xdbdf58e9,0xd953c50d },
  36141. { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110,
  36142. 0x9eb288f3,0x863ebb7e } },
  36143. /* 3 */
  36144. { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954,
  36145. 0xb5ff80a0,0x00076055 },
  36146. { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39,
  36147. 0x34373ee0,0x83087761 } },
  36148. /* 4 */
  36149. { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a,
  36150. 0xfd1b667f,0x2f5e6961 },
  36151. { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37,
  36152. 0x8d6f0f7b,0xf648f916 } },
  36153. /* 5 */
  36154. { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761,
  36155. 0x133d0015,0x5abe0285 },
  36156. { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562,
  36157. 0x6b6f7383,0x94bb725b } },
  36158. /* 6 */
  36159. { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129,
  36160. 0x2f7dc4ef,0xcdd6bbcb },
  36161. { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792,
  36162. 0x4bdae5f6,0xa361bebd } },
  36163. /* 7 */
  36164. { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec,
  36165. 0xc4b5292c,0xba12ca09 },
  36166. { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089,
  36167. 0x701fef4b,0x53ebb99d } },
  36168. /* 8 */
  36169. { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334,
  36170. 0x06d54831,0x8589fb92 },
  36171. { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507,
  36172. 0x02541c4f,0xebb0696d } },
  36173. /* 9 */
  36174. { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3,
  36175. 0xd1b27da3,0xeb2820cb },
  36176. { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42,
  36177. 0x55a7da1d,0x1f28289b } },
  36178. /* 10 */
  36179. { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862,
  36180. 0x05e54d63,0x337a4b59 },
  36181. { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781,
  36182. 0xf4c2fbd6,0x0d65e0d5 } },
  36183. /* 11 */
  36184. { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4,
  36185. 0x52f4a232,0xc23da242 },
  36186. { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86,
  36187. 0xc790cff1,0x19de3b8c } },
  36188. /* 12 */
  36189. { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586,
  36190. 0x91fccbfd,0xe34dcbd4 },
  36191. { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127,
  36192. 0x7b4e0f7f,0xe7641f44 } },
  36193. /* 13 */
  36194. { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6,
  36195. 0x052a57bf,0x4a12df57 },
  36196. { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa,
  36197. 0xbb5bea46,0x6af5aa93 } },
  36198. /* 14 */
  36199. { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4,
  36200. 0x66a44013,0x5fe3475a },
  36201. { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae,
  36202. 0xecfea916,0xb544e308 } },
  36203. /* 15 */
  36204. { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76,
  36205. 0xa6b0c20b,0xe0b6b2bd },
  36206. { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad,
  36207. 0x25a63774,0x71c023de } },
  36208. /* 16 */
  36209. { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5,
  36210. 0x21d324f6,0x61d587d4 },
  36211. { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e,
  36212. 0x4621efbe,0xfa11fe12 } },
  36213. /* 17 */
  36214. { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67,
  36215. 0x1f13bedc,0x586eb04c },
  36216. { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0,
  36217. 0x70864f11,0x19d5ac08 } },
  36218. /* 18 */
  36219. { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b,
  36220. 0x7f9c563f,0xe7c0073f },
  36221. { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a,
  36222. 0xc65b3c0a,0xe08504fe } },
  36223. /* 19 */
  36224. { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa,
  36225. 0x5b0996b4,0x78f01882 },
  36226. { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877,
  36227. 0x7e94747a,0x43a773b8 } },
  36228. /* 20 */
  36229. { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a,
  36230. 0xc3b266b1,0xbb6de651 },
  36231. { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1,
  36232. 0x5d18b99b,0x60b4619a } },
  36233. /* 21 */
  36234. { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014,
  36235. 0xaeebffcd,0x9d0f27b2 },
  36236. { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0,
  36237. 0x356ec48d,0x244a566d } },
  36238. /* 22 */
  36239. { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b,
  36240. 0x3581ef69,0x45e58c87 },
  36241. { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2,
  36242. 0xc1e4b7a4,0xc040e21c } },
  36243. /* 23 */
  36244. { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576,
  36245. 0x682c6ec7,0x1cdf5c97 },
  36246. { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1,
  36247. 0xa92dff3d,0x046755f8 } },
  36248. /* 24 */
  36249. { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172,
  36250. 0x3b83a5f3,0x046e5e11 },
  36251. { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6,
  36252. 0x303d005b,0x6e0106c3 } },
  36253. /* 25 */
  36254. { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8,
  36255. 0xe901cf1f,0x442594ed },
  36256. { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1,
  36257. 0x4c2ee68e,0xa796fa51 } },
  36258. /* 26 */
  36259. { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e,
  36260. 0xc69766e9,0xe4ad2da9 },
  36261. { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4,
  36262. 0xc37b5143,0xc5e94046 } },
  36263. /* 27 */
  36264. { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0,
  36265. 0xdb464747,0x63283daf },
  36266. { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad,
  36267. 0x1981a938,0x68bd19ab } },
  36268. /* 28 */
  36269. { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981,
  36270. 0x3c6fdfd6,0x495292f5 },
  36271. { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2,
  36272. 0x26036837,0x0ec7530d } },
  36273. /* 29 */
  36274. { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5,
  36275. 0x64863f0b,0x0f6207a6 },
  36276. { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407,
  36277. 0x08ed6dcf,0xff0db072 } },
  36278. /* 30 */
  36279. { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317,
  36280. 0x88740ea3,0x313b513c },
  36281. { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd,
  36282. 0x86f19f81,0x2d3abcf9 } },
  36283. /* 31 */
  36284. { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f,
  36285. 0xded98cdf,0xc036fa10 },
  36286. { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277,
  36287. 0xb6d40194,0xa6b2a2c4 } },
  36288. /* 32 */
  36289. { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac,
  36290. 0xaf7c9860,0x810ee252 },
  36291. { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74,
  36292. 0x92731745,0xd485717a } },
  36293. /* 33 */
  36294. { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb,
  36295. 0x2f9a604e,0x6a6045a7 },
  36296. { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73,
  36297. 0xf9e15790,0xd3e45cfa } },
  36298. /* 34 */
  36299. { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54,
  36300. 0xe3c2c19c,0x207755de },
  36301. { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6,
  36302. 0x7154b00d,0x48dc5ee5 } },
  36303. /* 35 */
  36304. { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe,
  36305. 0xdff6f445,0xf2fb0aed },
  36306. { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad,
  36307. 0xdb28d525,0xa13e9015 } },
  36308. /* 36 */
  36309. { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241,
  36310. 0x1497526f,0x2bf0d6b0 },
  36311. { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f,
  36312. 0x162fe89f,0x42a94a5a } },
  36313. /* 37 */
  36314. { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050,
  36315. 0xc65ede3d,0x2c2dd969 },
  36316. { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706,
  36317. 0x42c56dbc,0xf437fa1f } },
  36318. /* 38 */
  36319. { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050,
  36320. 0x54707aa8,0xaaf45b33 },
  36321. { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681,
  36322. 0xf4f272bc,0xcdf6310d } },
  36323. /* 39 */
  36324. { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772,
  36325. 0xda9e2ff2,0xf0d008ba },
  36326. { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d,
  36327. 0xca887b8b,0x5bd5c2f5 } },
  36328. /* 40 */
  36329. { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e,
  36330. 0xa09e4719,0xaa12dfc8 },
  36331. { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73,
  36332. 0xe48ca901,0x6c036e73 } },
  36333. /* 41 */
  36334. { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b,
  36335. 0x96afbe24,0x292ff658 },
  36336. { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f,
  36337. 0x311b7276,0x644e0c90 } },
  36338. /* 42 */
  36339. { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87,
  36340. 0xcab79a77,0xf25ae793 },
  36341. { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3,
  36342. 0x13db0a3e,0x39b8e653 } },
  36343. /* 43 */
  36344. { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a,
  36345. 0x0f19db06,0x39122f2f },
  36346. { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2,
  36347. 0xce80ff8d,0x8de80af8 } },
  36348. /* 44 */
  36349. { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b,
  36350. 0x2e368c04,0x87194906 },
  36351. { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a,
  36352. 0x5b74fde1,0xfc315e6a } },
  36353. /* 45 */
  36354. { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b,
  36355. 0xee389088,0xe6d4a7ad },
  36356. { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93,
  36357. 0x9be2ae57,0x35dfaf9a } },
  36358. /* 46 */
  36359. { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41,
  36360. 0x1c830d2b,0x1da5c7d7 },
  36361. { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7,
  36362. 0xdbf4b9d6,0x7077c0fd } },
  36363. /* 47 */
  36364. { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140,
  36365. 0xe50efe44,0x53a8632e },
  36366. { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3,
  36367. 0x34e1fcc1,0x028ca76d } },
  36368. /* 48 */
  36369. { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117,
  36370. 0x6962f046,0x04c17cd8 },
  36371. { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6,
  36372. 0xfed97474,0xf7ba4de9 } },
  36373. /* 49 */
  36374. { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553,
  36375. 0x52131c41,0xe31f9600 },
  36376. { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac,
  36377. 0xce34d47b,0xaa3a6259 } },
  36378. /* 50 */
  36379. { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa,
  36380. 0x7e79daee,0x2398dd62 },
  36381. { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377,
  36382. 0x1c046210,0x5717f5b2 } },
  36383. /* 51 */
  36384. { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239,
  36385. 0x0e3c28de,0x660a2c56 },
  36386. { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481,
  36387. 0x4f522453,0x624ee54c } },
  36388. /* 52 */
  36389. { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423,
  36390. 0x92bdfbc0,0x4f392afb },
  36391. { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803,
  36392. 0xccdb399c,0x8a3e7977 } },
  36393. /* 53 */
  36394. { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de,
  36395. 0x70c24404,0x3888d023 },
  36396. { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8,
  36397. 0x18102336,0xa5e62e47 } },
  36398. /* 54 */
  36399. { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7,
  36400. 0x466a5adc,0x2c4768e6 },
  36401. { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064,
  36402. 0xf9e652a0,0x7b5e6441 } },
  36403. /* 55 */
  36404. { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5,
  36405. 0x0c8d744a,0xb8af73cb },
  36406. { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f,
  36407. 0x7f3f0895,0xa036395f } },
  36408. /* 56 */
  36409. { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682,
  36410. 0x875fb533,0x4be36b01 },
  36411. { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05,
  36412. 0x1bdc00c0,0x8cbc9a87 } },
  36413. /* 57 */
  36414. { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c,
  36415. 0x0c0835f8,0x44e7553e },
  36416. { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276,
  36417. 0x5eb8fc18,0x470a683a } },
  36418. /* 58 */
  36419. { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee,
  36420. 0xc63dc6ef,0x16410690 },
  36421. { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72,
  36422. 0x7abcbb4f,0xd73479fd } },
  36423. /* 59 */
  36424. { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1,
  36425. 0x0771666b,0x816469e3 },
  36426. { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb,
  36427. 0xf0dd3f9c,0x0a36dd23 } },
  36428. /* 60 */
  36429. { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad,
  36430. 0xfdbab118,0xe331dfd6 },
  36431. { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7,
  36432. 0x492e3389,0xd3b4782a } },
  36433. /* 61 */
  36434. { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953,
  36435. 0x4c86a5bd,0x7281275a },
  36436. { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a,
  36437. 0xce145059,0x2c062e7e } },
  36438. /* 62 */
  36439. { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288,
  36440. 0x2c4e7ef1,0x282a35f9 },
  36441. { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38,
  36442. 0x554d2abd,0xc71cd513 } },
  36443. /* 63 */
  36444. { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7,
  36445. 0xcf47f3a3,0xc50f6740 },
  36446. { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222,
  36447. 0x212958dc,0xb9ecb3a7 } },
  36448. /* 64 */
  36449. { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e,
  36450. 0xcd42ab1b,0x803f3e02 },
  36451. { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273,
  36452. 0x5067adc1,0xc097440e } },
  36453. /* 65 */
  36454. { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459,
  36455. 0x915f1f30,0xf1af32d5 },
  36456. { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418,
  36457. 0xe2d41c8b,0x23d0f130 } },
  36458. /* 66 */
  36459. { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648,
  36460. 0xc0a3fadd,0xb0288dd6 },
  36461. { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7,
  36462. 0xf408c8d2,0xffd3724f } },
  36463. /* 67 */
  36464. { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b,
  36465. 0xd78c26df,0xf5590f4a },
  36466. { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f,
  36467. 0xf6f74a20,0x18d6da54 } },
  36468. /* 68 */
  36469. { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926,
  36470. 0x7990216a,0x50bbb4d9 },
  36471. { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b,
  36472. 0x01fe49c3,0x2b100118 } },
  36473. /* 69 */
  36474. { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa,
  36475. 0x83fbae0c,0xdd558999 },
  36476. { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf,
  36477. 0x149d6041,0xe6e4c551 } },
  36478. /* 70 */
  36479. { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b,
  36480. 0x07ed56ff,0x51e00db1 },
  36481. { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5,
  36482. 0x49829177,0xe22f4241 } },
  36483. /* 71 */
  36484. { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f,
  36485. 0x52dc48c9,0xf709373d },
  36486. { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a,
  36487. 0xe7275b11,0xbd52d288 } },
  36488. /* 72 */
  36489. { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e,
  36490. 0xc8aa77a6,0xa0d0f8e4 },
  36491. { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8,
  36492. 0x946d6a00,0xa56c78c7 } },
  36493. /* 73 */
  36494. { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f,
  36495. 0x731a367a,0xd8befdf8 },
  36496. { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40,
  36497. 0xce9f6478,0x854a68a5 } },
  36498. /* 74 */
  36499. { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b,
  36500. 0x98846a95,0x5cacea0b },
  36501. { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8,
  36502. 0x35e4efa9,0xe4982d12 } },
  36503. /* 75 */
  36504. { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa,
  36505. 0x16b20499,0x8046b7f6 },
  36506. { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea,
  36507. 0x9082af55,0xeb17ca7b } },
  36508. /* 76 */
  36509. { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565,
  36510. 0xfab5e131,0x097b00ba },
  36511. { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11,
  36512. 0xafdbcc9e,0xf95c747b } },
  36513. /* 77 */
  36514. { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1,
  36515. 0x566ed837,0x3512601e },
  36516. { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2,
  36517. 0x6068ab6b,0x0ef97123 } },
  36518. /* 78 */
  36519. { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74,
  36520. 0x3b4fbc95,0xfc16d933 },
  36521. { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497,
  36522. 0xb95d7a17,0x14ca4af1 } },
  36523. /* 79 */
  36524. { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7,
  36525. 0xf59c231d,0x4057b063 },
  36526. { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae,
  36527. 0xf1330b13,0x1c3b5d64 } },
  36528. /* 80 */
  36529. { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07,
  36530. 0xdb7e63af,0xfad27148 },
  36531. { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875,
  36532. 0x9f0e1a84,0x77387de3 } },
  36533. /* 81 */
  36534. { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408,
  36535. 0xbef0c47e,0xb37b85c0 },
  36536. { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa,
  36537. 0xf9f628d5,0x9c135ac8 } },
  36538. /* 82 */
  36539. { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176,
  36540. 0xc433851f,0x5721361f },
  36541. { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e,
  36542. 0xe6bb11bd,0xdcbac3c9 } },
  36543. /* 83 */
  36544. { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7,
  36545. 0x2d626862,0xb8c1c89e },
  36546. { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9,
  36547. 0x2f9422d4,0x5d23bbda } },
  36548. /* 84 */
  36549. { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403,
  36550. 0x91ece900,0xc109f9cb },
  36551. { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d,
  36552. 0x2eee1ee1,0x9bc3344f } },
  36553. /* 85 */
  36554. { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665,
  36555. 0x5f1a4cc1,0x29591d52 },
  36556. { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496,
  36557. 0x18ef332c,0x6376551f } },
  36558. /* 86 */
  36559. { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064,
  36560. 0x08e2987a,0xbdb79dc8 },
  36561. { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022,
  36562. 0xadd3c14a,0x8ee86001 } },
  36563. /* 87 */
  36564. { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899,
  36565. 0x6f77aa4b,0x92e51d7a },
  36566. { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3,
  36567. 0x0a56aaaa,0x5182f86f } },
  36568. /* 88 */
  36569. { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb,
  36570. 0x4073a6f2,0x91dcab5d },
  36571. { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c,
  36572. 0x97974f2b,0x17a0cedb } },
  36573. /* 89 */
  36574. { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4,
  36575. 0x7f4cdf41,0x2e8ce36c },
  36576. { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388,
  36577. 0x34f668f3,0xf4ccc6cb } },
  36578. /* 90 */
  36579. { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741,
  36580. 0x9a0df3c9,0xac0db488 },
  36581. { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f,
  36582. 0x94c974a2,0x95a64a61 } },
  36583. /* 91 */
  36584. { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c,
  36585. 0x29210677,0x231e54ba },
  36586. { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b,
  36587. 0xd8a731e1,0xab0be032 } },
  36588. /* 92 */
  36589. { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196,
  36590. 0x2cf6a679,0xf1bcc880 },
  36591. { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc,
  36592. 0x5aebb271,0x85169469 } },
  36593. /* 93 */
  36594. { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2,
  36595. 0xdaad55d8,0x8f67d9d2 },
  36596. { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4,
  36597. 0xc0728b5d,0xf84572b9 } },
  36598. /* 94 */
  36599. { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07,
  36600. 0x616b2c19,0xedee2710 },
  36601. { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3,
  36602. 0x44ebd7f4,0x9fd27e9b } },
  36603. /* 95 */
  36604. { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816,
  36605. 0x958ff387,0xa40c2fb6 },
  36606. { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704,
  36607. 0x7dc6decf,0x99bc9bb8 } },
  36608. /* 96 */
  36609. { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0,
  36610. 0xa16d7e64,0x9abe210b },
  36611. { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987,
  36612. 0x87f344b0,0x7881c257 } },
  36613. /* 97 */
  36614. { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2,
  36615. 0xa30e8940,0x15e6e319 },
  36616. { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1,
  36617. 0x191172ce,0x0e55facf } },
  36618. /* 98 */
  36619. { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca,
  36620. 0x6fe96577,0xd73d0976 },
  36621. { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859,
  36622. 0x8f15a50b,0x9250a374 } },
  36623. /* 99 */
  36624. { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289,
  36625. 0xc1cc8c0b,0x77414082 },
  36626. { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7,
  36627. 0x12eb20b9,0x8cb04f4d } },
  36628. /* 100 */
  36629. { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f,
  36630. 0x47123b51,0xe4e429ef },
  36631. { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07,
  36632. 0x3c6e6552,0x37bca2ff } },
  36633. /* 101 */
  36634. { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9,
  36635. 0x3002b22a,0x59913edc },
  36636. { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375,
  36637. 0xb013e226,0x43786e4a } },
  36638. /* 102 */
  36639. { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845,
  36640. 0xb7e79e7a,0x8638ca98 },
  36641. { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0,
  36642. 0x7b3aa6f0,0x1ecdd36a } },
  36643. /* 103 */
  36644. { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa,
  36645. 0xd459f32d,0xd85d0f85 },
  36646. { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4,
  36647. 0xb4ed3c62,0xa04f19c3 } },
  36648. /* 104 */
  36649. { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a,
  36650. 0x5c0950b0,0x92b2eeea },
  36651. { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3,
  36652. 0x5834276c,0x1ee78221 } },
  36653. /* 105 */
  36654. { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a,
  36655. 0x57a6e150,0xf3f2ced8 },
  36656. { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7,
  36657. 0x3da3e210,0x0f56a454 } },
  36658. /* 106 */
  36659. { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0,
  36660. 0x1969e263,0xbd8f1741 },
  36661. { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7,
  36662. 0x30ccfa09,0x2d1a1c35 } },
  36663. /* 107 */
  36664. { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949,
  36665. 0xb91fba46,0xa107a65e },
  36666. { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584,
  36667. 0xf87a9af2,0x183d760a } },
  36668. /* 108 */
  36669. { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963,
  36670. 0xc269d754,0x1d44179d },
  36671. { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5,
  36672. 0x9606d262,0x771f9cc2 } },
  36673. /* 109 */
  36674. { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2,
  36675. 0x0362718e,0x64427a31 },
  36676. { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d,
  36677. 0x6ae90d6d,0x49d9b749 } },
  36678. /* 110 */
  36679. { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0,
  36680. 0x3f605445,0x9037d81b },
  36681. { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96,
  36682. 0x7cc0639c,0x08c3de6a } },
  36683. /* 111 */
  36684. { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e,
  36685. 0x45796b2f,0xc6909442 },
  36686. { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab,
  36687. 0xcafe3ac0,0x3fa3db02 } },
  36688. /* 112 */
  36689. { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c,
  36690. 0xfdb808ff,0xc5c4bdb0 },
  36691. { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d,
  36692. 0x46c2b6b5,0x2d56db94 } },
  36693. /* 113 */
  36694. { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4,
  36695. 0xe503ba42,0x0f56bd9d },
  36696. { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a,
  36697. 0x1173b5f1,0x4003bb9d } },
  36698. /* 114 */
  36699. { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d,
  36700. 0xa07f2f9e,0x53765522 },
  36701. { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e,
  36702. 0x6c5d4549,0x7a056f58 } },
  36703. /* 115 */
  36704. { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e,
  36705. 0x7a1a2675,0x77d482f1 },
  36706. { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057,
  36707. 0x2b38b0e4,0x4115012b } },
  36708. /* 116 */
  36709. { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e,
  36710. 0xfbea0946,0xcdf04572 },
  36711. { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1,
  36712. 0x97383109,0xee703dda } },
  36713. /* 117 */
  36714. { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff,
  36715. 0xa162ce21,0x2a0ad89d },
  36716. { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c,
  36717. 0xac2b4659,0xd62d0b67 } },
  36718. /* 118 */
  36719. { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3,
  36720. 0x991c2426,0xb39a23f2 },
  36721. { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137,
  36722. 0xc0674cc5,0x04ed0092 } },
  36723. /* 119 */
  36724. { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6,
  36725. 0x0177c387,0xa0a91fc1 },
  36726. { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1,
  36727. 0x9ed20c41,0x084cf988 } },
  36728. /* 120 */
  36729. { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4,
  36730. 0x73abf77e,0xd57955b2 },
  36731. { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089,
  36732. 0x02d141f1,0x8e14ea42 } },
  36733. /* 121 */
  36734. { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194,
  36735. 0x2aa4d158,0x597e1a37 },
  36736. { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a,
  36737. 0x199b4dea,0xca3f0236 } },
  36738. /* 122 */
  36739. { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1,
  36740. 0x309c07e4,0xbde7fd7e },
  36741. { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f,
  36742. 0x0a7dd198,0xb623ad0e } },
  36743. /* 123 */
  36744. { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0,
  36745. 0x58ec137b,0xd6aa2e46 },
  36746. { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b,
  36747. 0x2dcc513a,0x111662e0 } },
  36748. /* 124 */
  36749. { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7,
  36750. 0x94b750f8,0xdb3ee1cb },
  36751. { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93,
  36752. 0x52206a59,0x886a6442 } },
  36753. /* 125 */
  36754. { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d,
  36755. 0x018a17bc,0xa70cf4eb },
  36756. { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e,
  36757. 0xd1747b77,0xaa4772ab } },
  36758. /* 126 */
  36759. { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4,
  36760. 0x30faf974,0x611a6ddc },
  36761. { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf,
  36762. 0x16429c88,0x5cfffaf8 } },
  36763. /* 127 */
  36764. { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f,
  36765. 0x7dc1994c,0x6e5a6b23 },
  36766. { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6,
  36767. 0x242dabcc,0x481a238d } },
  36768. /* 128 */
  36769. { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d,
  36770. 0xe0cdf943,0x2c41114c },
  36771. { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2,
  36772. 0x42ff9297,0x20477abf } },
  36773. /* 129 */
  36774. { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b,
  36775. 0xc77396b6,0xac66409a },
  36776. { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba,
  36777. 0xcc122f85,0xce8e6975 } },
  36778. /* 130 */
  36779. { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d,
  36780. 0x250bb4a8,0x08fde365 },
  36781. { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc,
  36782. 0x565d6cd7,0x2f7e2fd2 } },
  36783. /* 131 */
  36784. { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d,
  36785. 0x907702ae,0xc65be92e },
  36786. { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585,
  36787. 0xd1193b3a,0x4bff8e47 } },
  36788. /* 132 */
  36789. { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef,
  36790. 0x5772967d,0x3e4e4ae6 },
  36791. { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26,
  36792. 0x58ec6028,0x5388aefd } },
  36793. /* 133 */
  36794. { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f,
  36795. 0x4f75be0e,0x5cf908d1 },
  36796. { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f,
  36797. 0x60f00ce2,0xa698ba40 } },
  36798. /* 134 */
  36799. { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544,
  36800. 0x7aebad8d,0xb142ef8a },
  36801. { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b,
  36802. 0x58515075,0xd1896a96 } },
  36803. /* 135 */
  36804. { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73,
  36805. 0x7981da39,0x267b0e0b },
  36806. { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0,
  36807. 0xa1119393,0xb54e287a } },
  36808. /* 136 */
  36809. { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab,
  36810. 0x5f87d4e6,0x84abb28b },
  36811. { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b,
  36812. 0x17655640,0xe5436f67 } },
  36813. /* 137 */
  36814. { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd,
  36815. 0x5b9ce99e,0x0404f68b },
  36816. { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960,
  36817. 0x0ac1c701,0x3a4263df } },
  36818. /* 138 */
  36819. { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6,
  36820. 0x905ea367,0x0ca8fd3f },
  36821. { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be,
  36822. 0x4ddb0c33,0x96dca264 } },
  36823. /* 139 */
  36824. { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770,
  36825. 0x3aad59dc,0x4363e212 },
  36826. { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604,
  36827. 0xd8bb98c4,0x840e115c } },
  36828. /* 140 */
  36829. { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272,
  36830. 0x30ded6d4,0x5e0d6abd },
  36831. { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9,
  36832. 0x2945a25a,0x7dea48f4 } },
  36833. /* 141 */
  36834. { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54,
  36835. 0xebfd16d1,0xabc2a2be },
  36836. { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377,
  36837. 0x6c7eefc1,0x4ea35394 } },
  36838. /* 142 */
  36839. { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a,
  36840. 0x1c94ffc3,0x3a76e689 },
  36841. { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72,
  36842. 0x465e6464,0x8212a10a } },
  36843. /* 143 */
  36844. { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67,
  36845. 0x599cb164,0xaa7cab71 },
  36846. { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292,
  36847. 0xfe0617c3,0x40e38073 } },
  36848. /* 144 */
  36849. { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320,
  36850. 0xb3055526,0xe3604700 },
  36851. { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434,
  36852. 0xa3dee15f,0x6542d677 } },
  36853. /* 145 */
  36854. { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8,
  36855. 0x09bb6f21,0xa6534aee },
  36856. { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1,
  36857. 0xdc9aef22,0xf3cb672f } },
  36858. /* 146 */
  36859. { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9,
  36860. 0xaae870e7,0x7cafaa2e },
  36861. { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108,
  36862. 0xb9bd522e,0x0aab13c1 } },
  36863. /* 147 */
  36864. { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173,
  36865. 0x847012e9,0x4b91a602 },
  36866. { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a,
  36867. 0x72321cab,0x49534c53 } },
  36868. /* 148 */
  36869. { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b,
  36870. 0xd65ac5ee,0xcaf46c4f },
  36871. { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168,
  36872. 0x04c6770f,0x14ce9e57 } },
  36873. /* 149 */
  36874. { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f,
  36875. 0x3e4c9a71,0x1bb708a5 },
  36876. { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71,
  36877. 0xda300102,0xf9d126f2 } },
  36878. /* 150 */
  36879. { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311,
  36880. 0x729ecc69,0x807afcb9 },
  36881. { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59,
  36882. 0x6568cd8c,0x751adcd1 } },
  36883. /* 151 */
  36884. { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14,
  36885. 0x2537743f,0x29ec4468 },
  36886. { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a,
  36887. 0x92a4077d,0xff9370e3 } },
  36888. /* 152 */
  36889. { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e,
  36890. 0xa2a9d01a,0x9776478b },
  36891. { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5,
  36892. 0xac2f82fa,0x74a6313f } },
  36893. /* 153 */
  36894. { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0,
  36895. 0x0ff4863d,0xab75be15 },
  36896. { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03,
  36897. 0x0b4459f6,0x4ebeac2e } },
  36898. /* 154 */
  36899. { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633,
  36900. 0x2c1baffc,0xdf99887b },
  36901. { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511,
  36902. 0x779f4058,0x27b040a7 } },
  36903. /* 155 */
  36904. { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152,
  36905. 0xe4cfa3f5,0xb393dd37 },
  36906. { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be,
  36907. 0xd0463419,0x09588c12 } },
  36908. /* 156 */
  36909. { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280,
  36910. 0xdb9f648b,0x81c879a9 },
  36911. { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41,
  36912. 0x5fc11bc4,0xfa0d48f5 } },
  36913. /* 157 */
  36914. { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1,
  36915. 0xb6a367d6,0x8ea0e156 },
  36916. { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b,
  36917. 0xfa00b5ac,0x3f5ab924 } },
  36918. /* 158 */
  36919. { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6,
  36920. 0x2b74256e,0x8bc76887 },
  36921. { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168,
  36922. 0x60fcf34f,0xb386f190 } },
  36923. /* 159 */
  36924. { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea,
  36925. 0x1b069c4d,0x4cb460f7 },
  36926. { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66,
  36927. 0x95ef5223,0x52c0d508 } },
  36928. /* 160 */
  36929. { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661,
  36930. 0x2bb09c0b,0x4ac3c938 },
  36931. { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765,
  36932. 0xe39705f4,0x380d94c7 } },
  36933. /* 161 */
  36934. { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977,
  36935. 0xde2637af,0x2ce3e171 },
  36936. { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f,
  36937. 0x0b624e4d,0x2e6cd852 } },
  36938. /* 162 */
  36939. { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e,
  36940. 0x42c69d54,0xca177547 },
  36941. { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793,
  36942. 0x9cab2ce6,0xa976a713 } },
  36943. /* 163 */
  36944. { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7,
  36945. 0x0a1f4999,0x8720a717 },
  36946. { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a,
  36947. 0xc769893c,0x9719ef29 } },
  36948. /* 164 */
  36949. { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0,
  36950. 0xe15704c1,0xa5072976 },
  36951. { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18,
  36952. 0xf7b77725,0x99389c9d } },
  36953. /* 165 */
  36954. { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89,
  36955. 0x202c82e4,0xa88806aa },
  36956. { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0,
  36957. 0x4738dcfe,0x0043bffb } },
  36958. /* 166 */
  36959. { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a,
  36960. 0xba6c4866,0x52f3ef01 },
  36961. { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa,
  36962. 0x9ef27e75,0x3296bd89 } },
  36963. /* 167 */
  36964. { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd,
  36965. 0xaee571e9,0x3b90febf },
  36966. { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48,
  36967. 0x9f810b18,0x6e88069d } },
  36968. /* 168 */
  36969. { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221,
  36970. 0xdefaad13,0xa7222bea },
  36971. { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5,
  36972. 0xbc2ac690,0xbe94d523 } },
  36973. /* 169 */
  36974. { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1,
  36975. 0x9be8c766,0x7782defe },
  36976. { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc,
  36977. 0xa2892e4b,0x03838567 } },
  36978. /* 170 */
  36979. { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc,
  36980. 0xadf7b420,0xdbd986c4 },
  36981. { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d,
  36982. 0x6860bbd0,0x8e24d3c4 } },
  36983. /* 171 */
  36984. { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4,
  36985. 0x407bafc8,0x541a99c4 },
  36986. { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4,
  36987. 0xf57d35d1,0xc0092c49 } },
  36988. /* 172 */
  36989. { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1,
  36990. 0x7286944d,0x75e40634 },
  36991. { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16,
  36992. 0xc7848586,0x5b7cb658 } },
  36993. /* 173 */
  36994. { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1,
  36995. 0x8df097a1,0x7ae13eba },
  36996. { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878,
  36997. 0xe2a8e3fd,0x787d8074 } },
  36998. /* 174 */
  36999. { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3,
  37000. 0x9ef28484,0x5c222819 },
  37001. { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1,
  37002. 0xbaf0f2b0,0xe45d37ab } },
  37003. /* 175 */
  37004. { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7,
  37005. 0x84dfb9d3,0xed7bc122 },
  37006. { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140,
  37007. 0x45ca6d27,0xaac97cc9 } },
  37008. /* 176 */
  37009. { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1,
  37010. 0x1163dc4e,0x318f97b3 },
  37011. { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f,
  37012. 0x9a84ff4d,0xfa41faa1 } },
  37013. /* 177 */
  37014. { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4,
  37015. 0x1d26e9e2,0x38bb6b2c },
  37016. { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf,
  37017. 0xce7601a5,0x94dd0905 } },
  37018. /* 178 */
  37019. { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9,
  37020. 0xd25c2ae9,0x92077867 },
  37021. { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3,
  37022. 0xd29beb51,0x81e8428b } },
  37023. /* 179 */
  37024. { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f,
  37025. 0xdbbfa4b1,0x1b94ab62 },
  37026. { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f,
  37027. 0x055590ee,0x06a38e28 } },
  37028. /* 180 */
  37029. { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b,
  37030. 0x83d9d4f8,0xa7b36c20 },
  37031. { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2,
  37032. 0xa2822a20,0xbe54c6b4 } },
  37033. /* 181 */
  37034. { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f,
  37035. 0xeae022bb,0xbf30a5ab },
  37036. { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb,
  37037. 0x2732d13a,0xd1c820de } },
  37038. /* 182 */
  37039. { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe,
  37040. 0x68a18da3,0xb7d17bed },
  37041. { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af,
  37042. 0x6412cc64,0x3997fd5e } },
  37043. /* 183 */
  37044. { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0,
  37045. 0x3c6c13e8,0x0eeb8929 },
  37046. { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6,
  37047. 0xc922b6ef,0x228916f8 } },
  37048. /* 184 */
  37049. { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e,
  37050. 0x6e93097e,0xec05ad1d },
  37051. { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237,
  37052. 0x7ff11b37,0x7d314156 } },
  37053. /* 185 */
  37054. { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97,
  37055. 0x9bc1d7a3,0xe9ce66fc },
  37056. { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34,
  37057. 0x72280651,0xd9650b01 } },
  37058. /* 186 */
  37059. { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208,
  37060. 0x804eb7a2,0x14d6699a },
  37061. { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90,
  37062. 0x0d43598a,0x6f4c6841 } },
  37063. /* 187 */
  37064. { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2,
  37065. 0x61189abb,0x4c4350fd },
  37066. { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413,
  37067. 0x5a3118b5,0xa726d242 } },
  37068. /* 188 */
  37069. { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f,
  37070. 0xcc6cf392,0x13639e82 },
  37071. { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e,
  37072. 0xc1a335a3,0xca9365e1 } },
  37073. /* 189 */
  37074. { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4,
  37075. 0x970b72a5,0x9ce29c34 },
  37076. { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a,
  37077. 0xab42af98,0x48c4abd7 } },
  37078. /* 190 */
  37079. { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698,
  37080. 0xf67b33cb,0x78017c32 },
  37081. { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55,
  37082. 0xde5c1c04,0x53cd0454 } },
  37083. /* 191 */
  37084. { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1,
  37085. 0xd3d7fa8f,0xeea465c1 },
  37086. { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770,
  37087. 0x7ae69193,0x1b6e42a4 } },
  37088. /* 192 */
  37089. { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887,
  37090. 0x187fbd3d,0x0224da14 },
  37091. { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf,
  37092. 0x42bfff33,0x60838ef0 } },
  37093. /* 193 */
  37094. { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a,
  37095. 0x2d331643,0x636eb202 },
  37096. { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2,
  37097. 0x39218bac,0x8844eeb6 } },
  37098. /* 194 */
  37099. { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f,
  37100. 0x51fb789e,0x27ba83dc },
  37101. { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35,
  37102. 0x87f3a4ab,0xadb62d34 } },
  37103. /* 195 */
  37104. { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7,
  37105. 0x75e7c8b2,0xb990fd76 },
  37106. { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a,
  37107. 0x4d10d18d,0x81707ef9 } },
  37108. /* 196 */
  37109. { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4,
  37110. 0xd5a8aa5c,0x3792daea },
  37111. { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527,
  37112. 0x94b001ba,0x5abd635e } },
  37113. /* 197 */
  37114. { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea,
  37115. 0x846ab610,0x5995bf21 },
  37116. { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44,
  37117. 0xd483411e,0x44c32ca2 } },
  37118. /* 198 */
  37119. { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b,
  37120. 0x8082a54c,0x1f2162fb },
  37121. { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e,
  37122. 0xc3e907c9,0x8f1d402b } },
  37123. /* 199 */
  37124. { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37,
  37125. 0x926edbf9,0xb1980f43 },
  37126. { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4,
  37127. 0x37448e45,0x2828ad9b } },
  37128. /* 200 */
  37129. { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2,
  37130. 0x5a14b390,0x4973f127 },
  37131. { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f,
  37132. 0xdb168ac7,0x6dac8ed0 } },
  37133. /* 201 */
  37134. { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0,
  37135. 0x20b9de4c,0x4b23ef59 },
  37136. { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863,
  37137. 0xddf49a4e,0x4dd71534 } },
  37138. /* 202 */
  37139. { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8,
  37140. 0x2f4a4dbb,0xfd317000 },
  37141. { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976,
  37142. 0x9569f365,0x14fac58c } },
  37143. /* 203 */
  37144. { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240,
  37145. 0x36abda50,0xed7c7651 },
  37146. { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075,
  37147. 0x4d2e9f53,0xfefcb7f7 } },
  37148. /* 204 */
  37149. { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de,
  37150. 0x87e0d80b,0x1801a57e },
  37151. { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b,
  37152. 0x1ead1064,0x9f8fc11e } },
  37153. /* 205 */
  37154. { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd,
  37155. 0x3d3a69a9,0xa9d3809d },
  37156. { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e,
  37157. 0xe1178ef7,0x3006b9ae } },
  37158. /* 206 */
  37159. { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd,
  37160. 0x45f8f761,0x0ab85fd7 },
  37161. { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274,
  37162. 0x11e942c2,0xb122d675 } },
  37163. /* 207 */
  37164. { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301,
  37165. 0x097dbaec,0x9f599dc1 },
  37166. { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4,
  37167. 0x8a294b78,0x7d5528e0 } },
  37168. /* 208 */
  37169. { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b,
  37170. 0x303f1730,0x28ccea01 },
  37171. { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc,
  37172. 0xa1d013bf,0xc18baf48 } },
  37173. /* 209 */
  37174. { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171,
  37175. 0xb7a9596b,0x9def809d },
  37176. { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d,
  37177. 0x68808ce5,0x0357f8b0 } },
  37178. /* 210 */
  37179. { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874,
  37180. 0x1b489887,0xe4a01add },
  37181. { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71,
  37182. 0xce10cc30,0x466d7d79 } },
  37183. /* 211 */
  37184. { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28,
  37185. 0x451ead1a,0xc672a522 },
  37186. { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680,
  37187. 0xf2a67513,0x5e3d64fa } },
  37188. /* 212 */
  37189. { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a,
  37190. 0xeb8e42fc,0x6c8a7a95 },
  37191. { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738,
  37192. 0xad82ca91,0x348ae422 } },
  37193. /* 213 */
  37194. { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782,
  37195. 0xd9ef2d2e,0xc1074de0 },
  37196. { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50,
  37197. 0xc9e54ffc,0xfbadfbdb } },
  37198. /* 214 */
  37199. { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd,
  37200. 0x83716fcd,0xb7f976b4 },
  37201. { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760,
  37202. 0xcafcc805,0xf4d41b2e } },
  37203. /* 215 */
  37204. { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974,
  37205. 0xe0160f10,0x180824ea },
  37206. { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34,
  37207. 0x83cf6d25,0x67e5f639 } },
  37208. /* 216 */
  37209. { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276,
  37210. 0x04c11fc6,0x9fef789a },
  37211. { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0,
  37212. 0xa99c4e20,0xbc80c181 } },
  37213. /* 217 */
  37214. { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171,
  37215. 0x9f8cdf10,0x49270e62 },
  37216. { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17,
  37217. 0x61372f7f,0xd2ee52f9 } },
  37218. /* 218 */
  37219. { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5,
  37220. 0xe5abb733,0xdfb478be },
  37221. { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf,
  37222. 0x08df473a,0xd9a140b4 } },
  37223. /* 219 */
  37224. { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391,
  37225. 0x623f4b1a,0x760c058d },
  37226. { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110,
  37227. 0x8f190409,0x7141982d } },
  37228. /* 220 */
  37229. { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6,
  37230. 0x89d54e47,0x3af9d1ce },
  37231. { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc,
  37232. 0x73957dd6,0xb1f815c3 } },
  37233. /* 221 */
  37234. { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d,
  37235. 0x1543f052,0xa41aed14 },
  37236. { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be,
  37237. 0x86fb60ef,0xd6e9c1dd } },
  37238. /* 222 */
  37239. { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7,
  37240. 0xae9bf8c2,0x9c9c6e10 },
  37241. { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23,
  37242. 0x40fa61b6,0x566bd596 } },
  37243. /* 223 */
  37244. { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0,
  37245. 0xf525345e,0xcf2c7390 },
  37246. { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a,
  37247. 0x8aa20979,0x02f51755 } },
  37248. /* 224 */
  37249. { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac,
  37250. 0xe8d4d97d,0x14e9ada5 },
  37251. { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d,
  37252. 0x8e9d9ae8,0xa0ad4fab } },
  37253. /* 225 */
  37254. { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737,
  37255. 0x6e56ed1e,0xbcd530b8 },
  37256. { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761,
  37257. 0x6979341d,0x909283cf } },
  37258. /* 226 */
  37259. { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b,
  37260. 0xace1549a,0x35eeb7c9 },
  37261. { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c,
  37262. 0x448ae864,0x9a8b2cf4 } },
  37263. /* 227 */
  37264. { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168,
  37265. 0xd4491379,0x6bdb60f4 },
  37266. { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741,
  37267. 0x94ba08a9,0x01ec3cfd } },
  37268. /* 228 */
  37269. { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f,
  37270. 0x475464f6,0xd1acb1c0 },
  37271. { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813,
  37272. 0x405626c2,0x7dcd079d } },
  37273. /* 229 */
  37274. { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971,
  37275. 0x377d19b8,0x0bf53589 },
  37276. { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6,
  37277. 0xe16686fc,0xd28be4d9 } },
  37278. /* 230 */
  37279. { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa,
  37280. 0x510f88ce,0xd76007aa },
  37281. { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082,
  37282. 0xb303bb01,0xf2b52f68 } },
  37283. /* 231 */
  37284. { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680,
  37285. 0xcc5aed3a,0xd8dbe98e },
  37286. { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd,
  37287. 0xee559705,0xe01593a3 } },
  37288. /* 232 */
  37289. { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f,
  37290. 0xaeb8ef06,0xafec07b1 },
  37291. { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a,
  37292. 0x6e2dbfdd,0xa71b9354 } },
  37293. /* 233 */
  37294. { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db,
  37295. 0x628523d9,0x53a2005c },
  37296. { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7,
  37297. 0x3d588e3d,0xbf47d19b } },
  37298. /* 234 */
  37299. { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae,
  37300. 0x39c9a1b6,0x001c2c7f },
  37301. { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b,
  37302. 0x86ffb99b,0xfdadf8e7 } },
  37303. /* 235 */
  37304. { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055,
  37305. 0x5aa43c94,0x3a838e4d },
  37306. { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6,
  37307. 0x873e1da3,0x3cdb8257 } },
  37308. /* 236 */
  37309. { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2,
  37310. 0xf1f57fba,0x5a60cc89 },
  37311. { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8,
  37312. 0xdbfd8fc0,0x922ff56f } },
  37313. /* 237 */
  37314. { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46,
  37315. 0xf6c5cd62,0x72919a7d },
  37316. { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77,
  37317. 0x3624089a,0x5e791780 } },
  37318. /* 238 */
  37319. { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea,
  37320. 0xe24c2fab,0x4e0a5371 },
  37321. { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae,
  37322. 0xd56604ee,0xf5ff7818 } },
  37323. /* 239 */
  37324. { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a,
  37325. 0x533f5e64,0xe41df0e9 },
  37326. { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192,
  37327. 0xac4f155f,0x8edd7d6e } },
  37328. /* 240 */
  37329. { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c,
  37330. 0xed8aee96,0x1432c1ca },
  37331. { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5,
  37332. 0x5ac8d2c6,0xcaef480b } },
  37333. /* 241 */
  37334. { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0,
  37335. 0x8efae236,0xd0ba177e },
  37336. { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605,
  37337. 0x1c54ae16,0xf31c957c } },
  37338. /* 242 */
  37339. { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55,
  37340. 0x96e17c3a,0x013404cb },
  37341. { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682,
  37342. 0x91933e6c,0x6f377c4b } },
  37343. /* 243 */
  37344. { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037,
  37345. 0xd2d09506,0x6dba3e4e },
  37346. { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752,
  37347. 0x3becf4a7,0xf13cf342 } },
  37348. /* 244 */
  37349. { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6,
  37350. 0x274bbad3,0xc83fa9a9 },
  37351. { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e,
  37352. 0x5d702683,0xb49d70f4 } },
  37353. /* 245 */
  37354. { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418,
  37355. 0x0c30f1cf,0x59cfadbb },
  37356. { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c,
  37357. 0x354a4b67,0x5babf362 } },
  37358. /* 246 */
  37359. { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1,
  37360. 0x9026c8f0,0x6188c6a7 },
  37361. { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b,
  37362. 0xdf50b9d9,0x993fe475 } },
  37363. /* 247 */
  37364. { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a,
  37365. 0x4c80616b,0x81f76466 },
  37366. { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04,
  37367. 0x5fe9060d,0x564a812a } },
  37368. /* 248 */
  37369. { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f,
  37370. 0x00e51d6c,0x226bf3cf },
  37371. { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49,
  37372. 0xff257836,0x68779f47 } },
  37373. /* 249 */
  37374. { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28,
  37375. 0xeb092e0b,0x97bcb0d1 },
  37376. { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3,
  37377. 0x0a784655,0xa872ffe8 } },
  37378. /* 250 */
  37379. { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91,
  37380. 0xb732a36a,0x02812bfc },
  37381. { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398,
  37382. 0xfe5396af,0x07391cc9 } },
  37383. /* 251 */
  37384. { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8,
  37385. 0x7e6d2a08,0x355d2adc },
  37386. { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd,
  37387. 0x7c2a3a79,0x3dc2b1e3 } },
  37388. /* 252 */
  37389. { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590,
  37390. 0x3ccd846b,0xc4786910 },
  37391. { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5,
  37392. 0xd5bb4d32,0xccc42968 } },
  37393. /* 253 */
  37394. { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640,
  37395. 0xaa4871cf,0xe147eb42 },
  37396. { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47,
  37397. 0x080e96e3,0x239ac047 } },
  37398. /* 254 */
  37399. { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e,
  37400. 0xf5f7e59d,0xc55fa1a3 },
  37401. { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998,
  37402. 0xd4f4b699,0x094cd99c } },
  37403. /* 255 */
  37404. { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9,
  37405. 0x42abad33,0xb90a30b6 },
  37406. { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc,
  37407. 0x1b7924f7,0x019f8b9a } },
  37408. };
  37409. /* Multiply the base point of P256 by the scalar and return the result.
  37410. * If map is true then convert result to affine coordinates.
  37411. *
  37412. * Stripe implementation.
  37413. * Pre-generated: 2^0, 2^32, ...
  37414. * Pre-generated: products of all combinations of above.
  37415. * 8 doubles and adds (with qz=1)
  37416. *
  37417. * r Resulting point.
  37418. * k Scalar to multiply by.
  37419. * map Indicates whether to convert result to affine.
  37420. * ct Constant time required.
  37421. * heap Heap to use for allocation.
  37422. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  37423. */
  37424. static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k,
  37425. int map, int ct, void* heap)
  37426. {
  37427. return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table,
  37428. k, map, ct, heap);
  37429. }
  37430. #endif
  37431. /* Multiply the base point of P256 by the scalar and return the result.
  37432. * If map is true then convert result to affine coordinates.
  37433. *
  37434. * km Scalar to multiply by.
  37435. * r Resulting point.
  37436. * map Indicates whether to convert result to affine.
  37437. * heap Heap to use for allocation.
  37438. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  37439. */
  37440. int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap)
  37441. {
  37442. #ifdef WOLFSSL_SP_SMALL_STACK
  37443. sp_point_256* point = NULL;
  37444. sp_digit* k = NULL;
  37445. #else
  37446. sp_point_256 point[1];
  37447. sp_digit k[8];
  37448. #endif
  37449. int err = MP_OKAY;
  37450. #ifdef WOLFSSL_SP_SMALL_STACK
  37451. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  37452. DYNAMIC_TYPE_ECC);
  37453. if (point == NULL)
  37454. err = MEMORY_E;
  37455. if (err == MP_OKAY) {
  37456. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
  37457. DYNAMIC_TYPE_ECC);
  37458. if (k == NULL)
  37459. err = MEMORY_E;
  37460. }
  37461. #endif
  37462. if (err == MP_OKAY) {
  37463. sp_256_from_mp(k, 8, km);
  37464. err = sp_256_ecc_mulmod_base_8(point, k, map, 1, heap);
  37465. }
  37466. if (err == MP_OKAY) {
  37467. err = sp_256_point_to_ecc_point_8(point, r);
  37468. }
  37469. #ifdef WOLFSSL_SP_SMALL_STACK
  37470. if (k != NULL)
  37471. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37472. if (point != NULL)
  37473. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37474. #endif
  37475. return err;
  37476. }
  37477. /* Multiply the base point of P256 by the scalar, add point a and return
  37478. * the result. If map is true then convert result to affine coordinates.
  37479. *
  37480. * km Scalar to multiply by.
  37481. * am Point to add to scalar multiply result.
  37482. * inMont Point to add is in montgomery form.
  37483. * r Resulting point.
  37484. * map Indicates whether to convert result to affine.
  37485. * heap Heap to use for allocation.
  37486. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  37487. */
  37488. int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am,
  37489. int inMont, ecc_point* r, int map, void* heap)
  37490. {
  37491. #ifdef WOLFSSL_SP_SMALL_STACK
  37492. sp_point_256* point = NULL;
  37493. sp_digit* k = NULL;
  37494. #else
  37495. sp_point_256 point[2];
  37496. sp_digit k[8 + 8 * 2 * 6];
  37497. #endif
  37498. sp_point_256* addP = NULL;
  37499. sp_digit* tmp = NULL;
  37500. int err = MP_OKAY;
  37501. #ifdef WOLFSSL_SP_SMALL_STACK
  37502. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  37503. DYNAMIC_TYPE_ECC);
  37504. if (point == NULL)
  37505. err = MEMORY_E;
  37506. if (err == MP_OKAY) {
  37507. k = (sp_digit*)XMALLOC(
  37508. sizeof(sp_digit) * (8 + 8 * 2 * 6),
  37509. heap, DYNAMIC_TYPE_ECC);
  37510. if (k == NULL)
  37511. err = MEMORY_E;
  37512. }
  37513. #endif
  37514. if (err == MP_OKAY) {
  37515. addP = point + 1;
  37516. tmp = k + 8;
  37517. sp_256_from_mp(k, 8, km);
  37518. sp_256_point_from_ecc_point_8(addP, am);
  37519. }
  37520. if ((err == MP_OKAY) && (!inMont)) {
  37521. err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod);
  37522. }
  37523. if ((err == MP_OKAY) && (!inMont)) {
  37524. err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod);
  37525. }
  37526. if ((err == MP_OKAY) && (!inMont)) {
  37527. err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod);
  37528. }
  37529. if (err == MP_OKAY) {
  37530. err = sp_256_ecc_mulmod_base_8(point, k, 0, 0, heap);
  37531. }
  37532. if (err == MP_OKAY) {
  37533. sp_256_proj_point_add_8(point, point, addP, tmp);
  37534. if (map) {
  37535. sp_256_map_8(point, point, tmp);
  37536. }
  37537. err = sp_256_point_to_ecc_point_8(point, r);
  37538. }
  37539. #ifdef WOLFSSL_SP_SMALL_STACK
  37540. if (k != NULL)
  37541. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37542. if (point)
  37543. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37544. #endif
  37545. return err;
  37546. }
  37547. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  37548. defined(HAVE_ECC_VERIFY)
  37549. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  37550. /* Add 1 to a. (a = a + 1)
  37551. *
  37552. * a A single precision integer.
  37553. */
  37554. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  37555. static void sp_256_add_one_8(sp_digit* a_p)
  37556. #else
  37557. static void sp_256_add_one_8(sp_digit* a)
  37558. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  37559. {
  37560. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  37561. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  37562. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  37563. __asm__ __volatile__ (
  37564. "LDM %[a], {r1, r2, r3, r4}\n\t"
  37565. "ADDS r1, r1, #0x1\n\t"
  37566. "ADCS r2, r2, #0x0\n\t"
  37567. "ADCS r3, r3, #0x0\n\t"
  37568. "ADCS r4, r4, #0x0\n\t"
  37569. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  37570. "LDM %[a], {r1, r2, r3, r4}\n\t"
  37571. "ADCS r1, r1, #0x0\n\t"
  37572. "ADCS r2, r2, #0x0\n\t"
  37573. "ADCS r3, r3, #0x0\n\t"
  37574. "ADCS r4, r4, #0x0\n\t"
  37575. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  37576. : [a] "+r" (a)
  37577. :
  37578. : "memory", "r1", "r2", "r3", "r4", "cc"
  37579. );
  37580. }
  37581. /* Read big endian unsigned byte array into r.
  37582. *
  37583. * r A single precision integer.
  37584. * size Maximum number of bytes to convert
  37585. * a Byte array.
  37586. * n Number of bytes in array to read.
  37587. */
  37588. static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n)
  37589. {
  37590. int i;
  37591. int j;
  37592. byte* d;
  37593. for (i = n - 1,j = 0; i >= 3; i -= 4) {
  37594. r[j] = ((sp_digit)a[i - 0] << 0) |
  37595. ((sp_digit)a[i - 1] << 8) |
  37596. ((sp_digit)a[i - 2] << 16) |
  37597. ((sp_digit)a[i - 3] << 24);
  37598. j++;
  37599. }
  37600. if (i >= 0) {
  37601. r[j] = 0;
  37602. d = (byte*)r;
  37603. switch (i) {
  37604. case 2: d[n - 1 - 2] = a[2]; //fallthrough
  37605. case 1: d[n - 1 - 1] = a[1]; //fallthrough
  37606. case 0: d[n - 1 - 0] = a[0]; //fallthrough
  37607. }
  37608. j++;
  37609. }
  37610. for (; j < size; j++) {
  37611. r[j] = 0;
  37612. }
  37613. }
  37614. /* Generates a scalar that is in the range 1..order-1.
  37615. *
  37616. * rng Random number generator.
  37617. * k Scalar value.
  37618. * returns RNG failures, MEMORY_E when memory allocation fails and
  37619. * MP_OKAY on success.
  37620. */
  37621. static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k)
  37622. {
  37623. int err;
  37624. byte buf[32];
  37625. do {
  37626. err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
  37627. if (err == 0) {
  37628. sp_256_from_bin(k, 8, buf, (int)sizeof(buf));
  37629. if (sp_256_cmp_8(k, p256_order2) <= 0) {
  37630. sp_256_add_one_8(k);
  37631. break;
  37632. }
  37633. }
  37634. }
  37635. while (err == 0);
  37636. return err;
  37637. }
  37638. /* Makes a random EC key pair.
  37639. *
  37640. * rng Random number generator.
  37641. * priv Generated private value.
  37642. * pub Generated public point.
  37643. * heap Heap to use for allocation.
  37644. * returns ECC_INF_E when the point does not have the correct order, RNG
  37645. * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
  37646. */
  37647. int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
  37648. {
  37649. #ifdef WOLFSSL_SP_SMALL_STACK
  37650. sp_point_256* point = NULL;
  37651. sp_digit* k = NULL;
  37652. #else
  37653. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37654. sp_point_256 point[2];
  37655. #else
  37656. sp_point_256 point[1];
  37657. #endif
  37658. sp_digit k[8];
  37659. #endif
  37660. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37661. sp_point_256* infinity = NULL;
  37662. #endif
  37663. int err = MP_OKAY;
  37664. (void)heap;
  37665. #ifdef WOLFSSL_SP_SMALL_STACK
  37666. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37667. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC);
  37668. #else
  37669. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
  37670. #endif
  37671. if (point == NULL)
  37672. err = MEMORY_E;
  37673. if (err == MP_OKAY) {
  37674. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
  37675. DYNAMIC_TYPE_ECC);
  37676. if (k == NULL)
  37677. err = MEMORY_E;
  37678. }
  37679. #endif
  37680. if (err == MP_OKAY) {
  37681. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37682. infinity = point + 1;
  37683. #endif
  37684. err = sp_256_ecc_gen_k_8(rng, k);
  37685. }
  37686. if (err == MP_OKAY) {
  37687. err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, NULL);
  37688. }
  37689. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37690. if (err == MP_OKAY) {
  37691. err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, 1, NULL);
  37692. }
  37693. if (err == MP_OKAY) {
  37694. if (sp_256_iszero_8(point->x) || sp_256_iszero_8(point->y)) {
  37695. err = ECC_INF_E;
  37696. }
  37697. }
  37698. #endif
  37699. if (err == MP_OKAY) {
  37700. err = sp_256_to_mp(k, priv);
  37701. }
  37702. if (err == MP_OKAY) {
  37703. err = sp_256_point_to_ecc_point_8(point, pub);
  37704. }
  37705. #ifdef WOLFSSL_SP_SMALL_STACK
  37706. if (k != NULL)
  37707. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37708. if (point != NULL) {
  37709. /* point is not sensitive, so no need to zeroize */
  37710. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37711. }
  37712. #endif
  37713. return err;
  37714. }
  37715. #ifdef WOLFSSL_SP_NONBLOCK
  37716. typedef struct sp_ecc_key_gen_256_ctx {
  37717. int state;
  37718. sp_256_ecc_mulmod_8_ctx mulmod_ctx;
  37719. sp_digit k[8];
  37720. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37721. sp_point_256 point[2];
  37722. #else
  37723. sp_point_256 point[1];
  37724. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  37725. } sp_ecc_key_gen_256_ctx;
  37726. int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv,
  37727. ecc_point* pub, void* heap)
  37728. {
  37729. int err = FP_WOULDBLOCK;
  37730. sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data;
  37731. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37732. sp_point_256* infinity = ctx->point + 1;
  37733. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  37734. typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx)
  37735. >= sizeof(*sp_ctx) ? -1 : 1];
  37736. (void)sizeof(ctx_size_test);
  37737. switch (ctx->state) {
  37738. case 0:
  37739. err = sp_256_ecc_gen_k_8(rng, ctx->k);
  37740. if (err == MP_OKAY) {
  37741. err = FP_WOULDBLOCK;
  37742. ctx->state = 1;
  37743. }
  37744. break;
  37745. case 1:
  37746. err = sp_256_ecc_mulmod_base_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  37747. ctx->point, ctx->k, 1, 1, heap);
  37748. if (err == MP_OKAY) {
  37749. err = FP_WOULDBLOCK;
  37750. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37751. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  37752. ctx->state = 2;
  37753. #else
  37754. ctx->state = 3;
  37755. #endif
  37756. }
  37757. break;
  37758. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37759. case 2:
  37760. err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  37761. infinity, ctx->point, p256_order, 1, 1);
  37762. if (err == MP_OKAY) {
  37763. if (sp_256_iszero_8(ctx->point->x) ||
  37764. sp_256_iszero_8(ctx->point->y)) {
  37765. err = ECC_INF_E;
  37766. }
  37767. else {
  37768. err = FP_WOULDBLOCK;
  37769. ctx->state = 3;
  37770. }
  37771. }
  37772. break;
  37773. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  37774. case 3:
  37775. err = sp_256_to_mp(ctx->k, priv);
  37776. if (err == MP_OKAY) {
  37777. err = sp_256_point_to_ecc_point_8(ctx->point, pub);
  37778. }
  37779. break;
  37780. }
  37781. if (err != FP_WOULDBLOCK) {
  37782. XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx));
  37783. }
  37784. return err;
  37785. }
  37786. #endif /* WOLFSSL_SP_NONBLOCK */
  37787. #ifdef HAVE_ECC_DHE
  37788. /* Write r as big endian to byte array.
  37789. * Fixed length number of bytes written: 32
  37790. *
  37791. * r A single precision integer.
  37792. * a Byte array.
  37793. */
  37794. static void sp_256_to_bin_8(sp_digit* r, byte* a)
  37795. {
  37796. int i;
  37797. int j = 0;
  37798. for (i = 7; i >= 0; i--) {
  37799. a[j++] = r[i] >> 24;
  37800. a[j++] = r[i] >> 16;
  37801. a[j++] = r[i] >> 8;
  37802. a[j++] = r[i] >> 0;
  37803. }
  37804. }
  37805. /* Multiply the point by the scalar and serialize the X ordinate.
  37806. * The number is 0 padded to maximum size on output.
  37807. *
  37808. * priv Scalar to multiply the point by.
  37809. * pub Point to multiply.
  37810. * out Buffer to hold X ordinate.
  37811. * outLen On entry, size of the buffer in bytes.
  37812. * On exit, length of data in buffer in bytes.
  37813. * heap Heap to use for allocation.
  37814. * returns BUFFER_E if the buffer is to small for output size,
  37815. * MEMORY_E when memory allocation fails and MP_OKAY on success.
  37816. */
  37817. int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out,
  37818. word32* outLen, void* heap)
  37819. {
  37820. #ifdef WOLFSSL_SP_SMALL_STACK
  37821. sp_point_256* point = NULL;
  37822. sp_digit* k = NULL;
  37823. #else
  37824. sp_point_256 point[1];
  37825. sp_digit k[8];
  37826. #endif
  37827. int err = MP_OKAY;
  37828. if (*outLen < 32U) {
  37829. err = BUFFER_E;
  37830. }
  37831. #ifdef WOLFSSL_SP_SMALL_STACK
  37832. if (err == MP_OKAY) {
  37833. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  37834. DYNAMIC_TYPE_ECC);
  37835. if (point == NULL)
  37836. err = MEMORY_E;
  37837. }
  37838. if (err == MP_OKAY) {
  37839. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
  37840. DYNAMIC_TYPE_ECC);
  37841. if (k == NULL)
  37842. err = MEMORY_E;
  37843. }
  37844. #endif
  37845. if (err == MP_OKAY) {
  37846. sp_256_from_mp(k, 8, priv);
  37847. sp_256_point_from_ecc_point_8(point, pub);
  37848. err = sp_256_ecc_mulmod_8(point, point, k, 1, 1, heap);
  37849. }
  37850. if (err == MP_OKAY) {
  37851. sp_256_to_bin_8(point->x, out);
  37852. *outLen = 32;
  37853. }
  37854. #ifdef WOLFSSL_SP_SMALL_STACK
  37855. if (k != NULL)
  37856. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37857. if (point != NULL)
  37858. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37859. #endif
  37860. return err;
  37861. }
  37862. #ifdef WOLFSSL_SP_NONBLOCK
  37863. typedef struct sp_ecc_sec_gen_256_ctx {
  37864. int state;
  37865. union {
  37866. sp_256_ecc_mulmod_8_ctx mulmod_ctx;
  37867. };
  37868. sp_digit k[8];
  37869. sp_point_256 point;
  37870. } sp_ecc_sec_gen_256_ctx;
  37871. int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
  37872. const ecc_point* pub, byte* out, word32* outLen, void* heap)
  37873. {
  37874. int err = FP_WOULDBLOCK;
  37875. sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data;
  37876. typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  37877. (void)sizeof(ctx_size_test);
  37878. if (*outLen < 32U) {
  37879. err = BUFFER_E;
  37880. }
  37881. switch (ctx->state) {
  37882. case 0:
  37883. sp_256_from_mp(ctx->k, 8, priv);
  37884. sp_256_point_from_ecc_point_8(&ctx->point, pub);
  37885. ctx->state = 1;
  37886. break;
  37887. case 1:
  37888. err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  37889. &ctx->point, &ctx->point, ctx->k, 1, 1, heap);
  37890. if (err == MP_OKAY) {
  37891. sp_256_to_bin_8(ctx->point.x, out);
  37892. *outLen = 32;
  37893. }
  37894. break;
  37895. }
  37896. if (err == MP_OKAY && ctx->state != 1) {
  37897. err = FP_WOULDBLOCK;
  37898. }
  37899. if (err != FP_WOULDBLOCK) {
  37900. XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx));
  37901. }
  37902. return err;
  37903. }
  37904. #endif /* WOLFSSL_SP_NONBLOCK */
  37905. #endif /* HAVE_ECC_DHE */
  37906. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  37907. #endif
  37908. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  37909. #endif
  37910. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  37911. #ifdef WOLFSSL_SP_SMALL
  37912. /* Sub b from a into a. (a -= b)
  37913. *
  37914. * a A single precision integer.
  37915. * b A single precision integer.
  37916. */
  37917. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  37918. static sp_digit sp_256_sub_in_place_8(sp_digit* a_p, const sp_digit* b_p)
  37919. #else
  37920. static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b)
  37921. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  37922. {
  37923. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  37924. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  37925. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  37926. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  37927. __asm__ __volatile__ (
  37928. "MOV r10, #0x0\n\t"
  37929. "ADD r11, %[a], #0x20\n\t"
  37930. "\n"
  37931. "L_sp_256_sub_in_pkace_8_word:\n\t"
  37932. "RSBS r10, r10, #0x0\n\t"
  37933. "LDM %[a], {r2, r3, r4, r5}\n\t"
  37934. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  37935. "SBCS r2, r2, r6\n\t"
  37936. "SBCS r3, r3, r7\n\t"
  37937. "SBCS r4, r4, r8\n\t"
  37938. "SBCS r5, r5, r9\n\t"
  37939. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  37940. "SBC r10, r10, r10\n\t"
  37941. "CMP %[a], r11\n\t"
  37942. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  37943. "BNE L_sp_256_sub_in_pkace_8_word\n\t"
  37944. #else
  37945. "BNE.N L_sp_256_sub_in_pkace_8_word\n\t"
  37946. #endif
  37947. "MOV %[a], r10\n\t"
  37948. : [a] "+r" (a), [b] "+r" (b)
  37949. :
  37950. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  37951. );
  37952. return (uint32_t)(size_t)a;
  37953. }
  37954. #else
  37955. /* Sub b from a into a. (a -= b)
  37956. *
  37957. * a A single precision integer and result.
  37958. * b A single precision integer.
  37959. */
  37960. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  37961. static sp_digit sp_256_sub_in_place_8(sp_digit* a_p, const sp_digit* b_p)
  37962. #else
  37963. static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b)
  37964. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  37965. {
  37966. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  37967. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  37968. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  37969. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  37970. __asm__ __volatile__ (
  37971. "LDM %[a], {r2, r3, r4, r5}\n\t"
  37972. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  37973. "SUBS r2, r2, r6\n\t"
  37974. "SBCS r3, r3, r7\n\t"
  37975. "SBCS r4, r4, r8\n\t"
  37976. "SBCS r5, r5, r9\n\t"
  37977. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  37978. "LDM %[a], {r2, r3, r4, r5}\n\t"
  37979. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  37980. "SBCS r2, r2, r6\n\t"
  37981. "SBCS r3, r3, r7\n\t"
  37982. "SBCS r4, r4, r8\n\t"
  37983. "SBCS r5, r5, r9\n\t"
  37984. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  37985. "SBC %[a], r9, r9\n\t"
  37986. : [a] "+r" (a), [b] "+r" (b)
  37987. :
  37988. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  37989. );
  37990. return (uint32_t)(size_t)a;
  37991. }
  37992. #endif /* WOLFSSL_SP_SMALL */
  37993. #ifdef WOLFSSL_SP_SMALL
  37994. /* Mul a by digit b into r. (r = a * b)
  37995. *
  37996. * r A single precision integer.
  37997. * a A single precision integer.
  37998. * b A single precision digit.
  37999. */
  38000. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38001. static void sp_256_mul_d_8(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  38002. #else
  38003. static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, sp_digit b)
  38004. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38005. {
  38006. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38007. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  38008. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  38009. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  38010. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38011. __asm__ __volatile__ (
  38012. /* A[0] * B */
  38013. "LDR r8, [%[a]]\n\t"
  38014. "UMULL r5, r3, %[b], r8\n\t"
  38015. "MOV r4, #0x0\n\t"
  38016. "STR r5, [%[r]]\n\t"
  38017. "MOV r5, #0x0\n\t"
  38018. "MOV r9, #0x4\n\t"
  38019. "\n"
  38020. "L_sp_256_mul_d_8_word:\n\t"
  38021. /* A[i] * B */
  38022. "LDR r8, [%[a], r9]\n\t"
  38023. "UMULL r6, r7, %[b], r8\n\t"
  38024. "ADDS r3, r3, r6\n\t"
  38025. "ADCS r4, r4, r7\n\t"
  38026. "ADC r5, r5, #0x0\n\t"
  38027. "STR r3, [%[r], r9]\n\t"
  38028. "MOV r3, r4\n\t"
  38029. "MOV r4, r5\n\t"
  38030. "MOV r5, #0x0\n\t"
  38031. "ADD r9, r9, #0x4\n\t"
  38032. "CMP r9, #0x20\n\t"
  38033. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  38034. "BLT L_sp_256_mul_d_8_word\n\t"
  38035. #else
  38036. "BLT.N L_sp_256_mul_d_8_word\n\t"
  38037. #endif
  38038. "STR r3, [%[r], #32]\n\t"
  38039. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  38040. :
  38041. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  38042. );
  38043. }
  38044. #else
  38045. /* Mul a by digit b into r. (r = a * b)
  38046. *
  38047. * r A single precision integer.
  38048. * a A single precision integer.
  38049. * b A single precision digit.
  38050. */
  38051. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38052. static void sp_256_mul_d_8(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  38053. #else
  38054. static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, sp_digit b)
  38055. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38056. {
  38057. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38058. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  38059. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  38060. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  38061. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38062. __asm__ __volatile__ (
  38063. /* A[0] * B */
  38064. "LDM %[a]!, {r8}\n\t"
  38065. "UMULL r3, r4, %[b], r8\n\t"
  38066. "STM %[r]!, {r3}\n\t"
  38067. "MOV r5, #0x0\n\t"
  38068. /* A[1] * B */
  38069. "LDM %[a]!, {r8}\n\t"
  38070. "UMLAL r4, r5, %[b], r8\n\t"
  38071. "STM %[r]!, {r4}\n\t"
  38072. "MOV r3, #0x0\n\t"
  38073. /* A[2] * B */
  38074. "LDM %[a]!, {r8}\n\t"
  38075. "UMLAL r5, r3, %[b], r8\n\t"
  38076. "STM %[r]!, {r5}\n\t"
  38077. "MOV r4, #0x0\n\t"
  38078. /* A[3] * B */
  38079. "LDM %[a]!, {r8}\n\t"
  38080. "UMLAL r3, r4, %[b], r8\n\t"
  38081. "STM %[r]!, {r3}\n\t"
  38082. "MOV r5, #0x0\n\t"
  38083. /* A[4] * B */
  38084. "LDM %[a]!, {r8}\n\t"
  38085. "UMLAL r4, r5, %[b], r8\n\t"
  38086. "STM %[r]!, {r4}\n\t"
  38087. "MOV r3, #0x0\n\t"
  38088. /* A[5] * B */
  38089. "LDM %[a]!, {r8}\n\t"
  38090. "UMLAL r5, r3, %[b], r8\n\t"
  38091. "STM %[r]!, {r5}\n\t"
  38092. "MOV r4, #0x0\n\t"
  38093. /* A[6] * B */
  38094. "LDM %[a]!, {r8}\n\t"
  38095. "UMLAL r3, r4, %[b], r8\n\t"
  38096. "STM %[r]!, {r3}\n\t"
  38097. "MOV r5, #0x0\n\t"
  38098. /* A[7] * B */
  38099. "LDM %[a]!, {r8}\n\t"
  38100. "UMLAL r4, r5, %[b], r8\n\t"
  38101. "STM %[r]!, {r4}\n\t"
  38102. "STR r5, [%[r]]\n\t"
  38103. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  38104. :
  38105. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  38106. );
  38107. }
  38108. #endif /* WOLFSSL_SP_SMALL */
  38109. #ifdef WOLFSSL_SP_USE_UDIV
  38110. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  38111. *
  38112. * d1 The high order half of the number to divide.
  38113. * d0 The low order half of the number to divide.
  38114. * div The divisor.
  38115. * returns the result of the division.
  38116. *
  38117. * Note that this is an approximate div. It may give an answer 1 larger.
  38118. */
  38119. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38120. SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  38121. #else
  38122. SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, sp_digit div)
  38123. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38124. {
  38125. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38126. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  38127. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  38128. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  38129. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38130. __asm__ __volatile__ (
  38131. "LSR r8, %[div], #16\n\t"
  38132. "ADD r5, r8, #0x1\n\t"
  38133. "UDIV r6, %[d1], r5\n\t"
  38134. "LSL r7, %[div], #16\n\t"
  38135. "LSL r6, r6, #16\n\t"
  38136. "UMULL r3, r4, %[div], r6\n\t"
  38137. "SUBS %[d0], %[d0], r3\n\t"
  38138. "SBC %[d1], %[d1], r4\n\t"
  38139. "SUBS r3, %[d1], r5\n\t"
  38140. "SBC r9, r9, r9\n\t"
  38141. "ADD r9, r9, #0x1\n\t"
  38142. "RSB r10, r9, #0x0\n\t"
  38143. "LSL r9, r9, #16\n\t"
  38144. "AND r7, r7, r10\n\t"
  38145. "AND r8, r8, r10\n\t"
  38146. "SUBS %[d0], %[d0], r7\n\t"
  38147. "ADD r6, r6, r9\n\t"
  38148. "SBC %[d1], %[d1], r8\n\t"
  38149. "LSL r4, %[d1], #16\n\t"
  38150. "LSR r3, %[d0], #16\n\t"
  38151. "ORR r3, r3, r4\n\t"
  38152. "UDIV r3, r3, r5\n\t"
  38153. "ADD r6, r6, r3\n\t"
  38154. "UMULL r3, r4, %[div], r3\n\t"
  38155. "SUBS %[d0], %[d0], r3\n\t"
  38156. "SBC %[d1], %[d1], r4\n\t"
  38157. "LSL r4, %[d1], #16\n\t"
  38158. "LSR r3, %[d0], #16\n\t"
  38159. "ORR r3, r3, r4\n\t"
  38160. "UDIV r3, r3, r5\n\t"
  38161. "ADD r6, r6, r3\n\t"
  38162. "MUL r3, %[div], r3\n\t"
  38163. "SUB %[d0], %[d0], r3\n\t"
  38164. "UDIV r3, %[d0], %[div]\n\t"
  38165. "ADD %[d1], r6, r3\n\t"
  38166. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  38167. :
  38168. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  38169. );
  38170. return (uint32_t)(size_t)d1;
  38171. }
  38172. #else
  38173. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  38174. *
  38175. * d1 The high order half of the number to divide.
  38176. * d0 The low order half of the number to divide.
  38177. * div The divisor.
  38178. * returns the result of the division.
  38179. *
  38180. * Note that this is an approximate div. It may give an answer 1 larger.
  38181. */
  38182. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38183. SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  38184. #else
  38185. SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, sp_digit div)
  38186. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38187. {
  38188. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38189. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  38190. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  38191. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  38192. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38193. __asm__ __volatile__ (
  38194. "LSR r5, %[div], #1\n\t"
  38195. "ADD r5, r5, #0x1\n\t"
  38196. "MOV r6, %[d0]\n\t"
  38197. "MOV r7, %[d1]\n\t"
  38198. /* Do top 32 */
  38199. "SUBS r8, r5, r7\n\t"
  38200. "SBC r8, r8, r8\n\t"
  38201. "MOV r3, #0x0\n\t"
  38202. "SUB r3, r3, r8\n\t"
  38203. "AND r8, r8, r5\n\t"
  38204. "SUBS r7, r7, r8\n\t"
  38205. /* Next 30 bits */
  38206. "MOV r4, #0x1d\n\t"
  38207. "\n"
  38208. "L_div_256_word_8_bit:\n\t"
  38209. "LSLS r6, r6, #1\n\t"
  38210. "ADC r7, r7, r7\n\t"
  38211. "SUBS r8, r5, r7\n\t"
  38212. "SBC r8, r8, r8\n\t"
  38213. "ADD r3, r3, r3\n\t"
  38214. "SUB r3, r3, r8\n\t"
  38215. "AND r8, r8, r5\n\t"
  38216. "SUBS r7, r7, r8\n\t"
  38217. "SUBS r4, r4, #0x1\n\t"
  38218. "bpl L_div_256_word_8_bit\n\t"
  38219. "ADD r3, r3, r3\n\t"
  38220. "ADD r3, r3, #0x1\n\t"
  38221. "UMULL r6, r7, r3, %[div]\n\t"
  38222. "SUBS r9, %[d0], r6\n\t"
  38223. "SBC r10, %[d1], r7\n\t"
  38224. "ADD r3, r3, r10\n\t"
  38225. "UMULL r6, r7, r3, %[div]\n\t"
  38226. "SUBS r9, %[d0], r6\n\t"
  38227. "SBC r10, %[d1], r7\n\t"
  38228. "ADD r3, r3, r10\n\t"
  38229. "UMULL r6, r7, r3, %[div]\n\t"
  38230. "SUBS r9, %[d0], r6\n\t"
  38231. "SBC r10, %[d1], r7\n\t"
  38232. "ADD r3, r3, r10\n\t"
  38233. "SUBS r8, %[div], r9\n\t"
  38234. "SBC r8, r8, r8\n\t"
  38235. "SUB %[d1], r3, r8\n\t"
  38236. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  38237. :
  38238. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  38239. );
  38240. return (uint32_t)(size_t)d1;
  38241. }
  38242. #endif
  38243. /* AND m into each word of a and store in r.
  38244. *
  38245. * r A single precision integer.
  38246. * a A single precision integer.
  38247. * m Mask to AND against each digit.
  38248. */
  38249. static void sp_256_mask_8(sp_digit* r, const sp_digit* a, sp_digit m)
  38250. {
  38251. #ifdef WOLFSSL_SP_SMALL
  38252. int i;
  38253. for (i=0; i<8; i++) {
  38254. r[i] = a[i] & m;
  38255. }
  38256. #else
  38257. r[0] = a[0] & m;
  38258. r[1] = a[1] & m;
  38259. r[2] = a[2] & m;
  38260. r[3] = a[3] & m;
  38261. r[4] = a[4] & m;
  38262. r[5] = a[5] & m;
  38263. r[6] = a[6] & m;
  38264. r[7] = a[7] & m;
  38265. #endif
  38266. }
  38267. /* Divide d in a and put remainder into r (m*d + r = a)
  38268. * m is not calculated as it is not needed at this time.
  38269. *
  38270. * a Number to be divided.
  38271. * d Number to divide with.
  38272. * m Multiplier result.
  38273. * r Remainder from the division.
  38274. * returns MP_OKAY indicating success.
  38275. */
  38276. static WC_INLINE int sp_256_div_8(const sp_digit* a, const sp_digit* d,
  38277. sp_digit* m, sp_digit* r)
  38278. {
  38279. sp_digit t1[16], t2[9];
  38280. sp_digit div, r1;
  38281. int i;
  38282. (void)m;
  38283. div = d[7];
  38284. XMEMCPY(t1, a, sizeof(*t1) * 2 * 8);
  38285. r1 = sp_256_cmp_8(&t1[8], d) >= 0;
  38286. sp_256_cond_sub_8(&t1[8], &t1[8], d, (sp_digit)0 - r1);
  38287. for (i = 7; i >= 0; i--) {
  38288. volatile sp_digit mask = (sp_digit)0 - (t1[8 + i] == div);
  38289. sp_digit hi = t1[8 + i] + mask;
  38290. r1 = div_256_word_8(hi, t1[8 + i - 1], div);
  38291. r1 |= mask;
  38292. sp_256_mul_d_8(t2, d, r1);
  38293. t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2);
  38294. t1[8 + i] -= t2[8];
  38295. sp_256_mask_8(t2, d, t1[8 + i]);
  38296. t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2);
  38297. sp_256_mask_8(t2, d, t1[8 + i]);
  38298. t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2);
  38299. }
  38300. r1 = sp_256_cmp_8(t1, d) >= 0;
  38301. sp_256_cond_sub_8(r, t1, d, (sp_digit)0 - r1);
  38302. return MP_OKAY;
  38303. }
  38304. /* Reduce a modulo m into r. (r = a mod m)
  38305. *
  38306. * r A single precision number that is the reduced result.
  38307. * a A single precision number that is to be reduced.
  38308. * m A single precision number that is the modulus to reduce with.
  38309. * returns MP_OKAY indicating success.
  38310. */
  38311. static WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
  38312. {
  38313. return sp_256_div_8(a, m, NULL, r);
  38314. }
  38315. #endif
  38316. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  38317. /* Multiply two number mod the order of P256 curve. (r = a * b mod order)
  38318. *
  38319. * r Result of the multiplication.
  38320. * a First operand of the multiplication.
  38321. * b Second operand of the multiplication.
  38322. */
  38323. static void sp_256_mont_mul_order_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  38324. {
  38325. sp_256_mul_8(r, a, b);
  38326. sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order);
  38327. }
  38328. #if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
  38329. #ifdef WOLFSSL_SP_SMALL
  38330. /* Order-2 for the P256 curve. */
  38331. static const uint32_t p256_order_minus_2[8] = {
  38332. 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU,
  38333. 0x00000000U,0xffffffffU
  38334. };
  38335. #else
  38336. /* The low half of the order-2 of the P256 curve. */
  38337. static const sp_int_digit p256_order_low[4] = {
  38338. 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU
  38339. };
  38340. #endif /* WOLFSSL_SP_SMALL */
  38341. /* Square number mod the order of P256 curve. (r = a * a mod order)
  38342. *
  38343. * r Result of the squaring.
  38344. * a Number to square.
  38345. */
  38346. static void sp_256_mont_sqr_order_8(sp_digit* r, const sp_digit* a)
  38347. {
  38348. sp_256_sqr_8(r, a);
  38349. sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order);
  38350. }
  38351. #ifndef WOLFSSL_SP_SMALL
  38352. /* Square number mod the order of P256 curve a number of times.
  38353. * (r = a ^ n mod order)
  38354. *
  38355. * r Result of the squaring.
  38356. * a Number to square.
  38357. */
  38358. static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n)
  38359. {
  38360. int i;
  38361. sp_256_mont_sqr_order_8(r, a);
  38362. for (i=1; i<n; i++) {
  38363. sp_256_mont_sqr_order_8(r, r);
  38364. }
  38365. }
  38366. #endif /* !WOLFSSL_SP_SMALL */
  38367. /* Invert the number, in Montgomery form, modulo the order of the P256 curve.
  38368. * (r = 1 / a mod order)
  38369. *
  38370. * r Inverse result.
  38371. * a Number to invert.
  38372. * td Temporary data.
  38373. */
  38374. #ifdef WOLFSSL_SP_NONBLOCK
  38375. typedef struct sp_256_mont_inv_order_8_ctx {
  38376. int state;
  38377. int i;
  38378. } sp_256_mont_inv_order_8_ctx;
  38379. static int sp_256_mont_inv_order_8_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
  38380. sp_digit* t)
  38381. {
  38382. int err = FP_WOULDBLOCK;
  38383. sp_256_mont_inv_order_8_ctx* ctx = (sp_256_mont_inv_order_8_ctx*)sp_ctx;
  38384. typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  38385. (void)sizeof(ctx_size_test);
  38386. switch (ctx->state) {
  38387. case 0:
  38388. XMEMCPY(t, a, sizeof(sp_digit) * 8);
  38389. ctx->i = 254;
  38390. ctx->state = 1;
  38391. break;
  38392. case 1:
  38393. sp_256_mont_sqr_order_8(t, t);
  38394. ctx->state = 2;
  38395. break;
  38396. case 2:
  38397. if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
  38398. sp_256_mont_mul_order_8(t, t, a);
  38399. }
  38400. ctx->i--;
  38401. ctx->state = (ctx->i == 0) ? 3 : 1;
  38402. break;
  38403. case 3:
  38404. XMEMCPY(r, t, sizeof(sp_digit) * 8U);
  38405. err = MP_OKAY;
  38406. break;
  38407. }
  38408. return err;
  38409. }
  38410. #endif /* WOLFSSL_SP_NONBLOCK */
  38411. static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
  38412. sp_digit* td)
  38413. {
  38414. #ifdef WOLFSSL_SP_SMALL
  38415. sp_digit* t = td;
  38416. int i;
  38417. XMEMCPY(t, a, sizeof(sp_digit) * 8);
  38418. for (i=254; i>=0; i--) {
  38419. sp_256_mont_sqr_order_8(t, t);
  38420. if ((p256_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  38421. sp_256_mont_mul_order_8(t, t, a);
  38422. }
  38423. }
  38424. XMEMCPY(r, t, sizeof(sp_digit) * 8U);
  38425. #else
  38426. sp_digit* t = td;
  38427. sp_digit* t2 = td + 2 * 8;
  38428. sp_digit* t3 = td + 4 * 8;
  38429. int i;
  38430. /* t = a^2 */
  38431. sp_256_mont_sqr_order_8(t, a);
  38432. /* t = a^3 = t * a */
  38433. sp_256_mont_mul_order_8(t, t, a);
  38434. /* t2= a^c = t ^ 2 ^ 2 */
  38435. sp_256_mont_sqr_n_order_8(t2, t, 2);
  38436. /* t3= a^f = t2 * t */
  38437. sp_256_mont_mul_order_8(t3, t2, t);
  38438. /* t2= a^f0 = t3 ^ 2 ^ 4 */
  38439. sp_256_mont_sqr_n_order_8(t2, t3, 4);
  38440. /* t = a^ff = t2 * t3 */
  38441. sp_256_mont_mul_order_8(t, t2, t3);
  38442. /* t2= a^ff00 = t ^ 2 ^ 8 */
  38443. sp_256_mont_sqr_n_order_8(t2, t, 8);
  38444. /* t = a^ffff = t2 * t */
  38445. sp_256_mont_mul_order_8(t, t2, t);
  38446. /* t2= a^ffff0000 = t ^ 2 ^ 16 */
  38447. sp_256_mont_sqr_n_order_8(t2, t, 16);
  38448. /* t = a^ffffffff = t2 * t */
  38449. sp_256_mont_mul_order_8(t, t2, t);
  38450. /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */
  38451. sp_256_mont_sqr_n_order_8(t2, t, 64);
  38452. /* t2= a^ffffffff00000000ffffffff = t2 * t */
  38453. sp_256_mont_mul_order_8(t2, t2, t);
  38454. /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */
  38455. sp_256_mont_sqr_n_order_8(t2, t2, 32);
  38456. /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
  38457. sp_256_mont_mul_order_8(t2, t2, t);
  38458. /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
  38459. sp_256_mont_sqr_order_8(t2, t2);
  38460. sp_256_mont_mul_order_8(t2, t2, a);
  38461. sp_256_mont_sqr_n_order_8(t2, t2, 5);
  38462. sp_256_mont_mul_order_8(t2, t2, t3);
  38463. for (i=121; i>=112; i--) {
  38464. sp_256_mont_sqr_order_8(t2, t2);
  38465. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  38466. sp_256_mont_mul_order_8(t2, t2, a);
  38467. }
  38468. }
  38469. /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
  38470. sp_256_mont_sqr_n_order_8(t2, t2, 4);
  38471. sp_256_mont_mul_order_8(t2, t2, t3);
  38472. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
  38473. for (i=107; i>=64; i--) {
  38474. sp_256_mont_sqr_order_8(t2, t2);
  38475. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  38476. sp_256_mont_mul_order_8(t2, t2, a);
  38477. }
  38478. }
  38479. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
  38480. sp_256_mont_sqr_n_order_8(t2, t2, 4);
  38481. sp_256_mont_mul_order_8(t2, t2, t3);
  38482. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
  38483. for (i=59; i>=32; i--) {
  38484. sp_256_mont_sqr_order_8(t2, t2);
  38485. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  38486. sp_256_mont_mul_order_8(t2, t2, a);
  38487. }
  38488. }
  38489. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
  38490. sp_256_mont_sqr_n_order_8(t2, t2, 4);
  38491. sp_256_mont_mul_order_8(t2, t2, t3);
  38492. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
  38493. for (i=27; i>=0; i--) {
  38494. sp_256_mont_sqr_order_8(t2, t2);
  38495. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  38496. sp_256_mont_mul_order_8(t2, t2, a);
  38497. }
  38498. }
  38499. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
  38500. sp_256_mont_sqr_n_order_8(t2, t2, 4);
  38501. /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
  38502. sp_256_mont_mul_order_8(r, t2, t3);
  38503. #endif /* WOLFSSL_SP_SMALL */
  38504. }
  38505. #endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
  38506. #endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  38507. #ifdef HAVE_ECC_SIGN
  38508. #ifndef SP_ECC_MAX_SIG_GEN
  38509. #define SP_ECC_MAX_SIG_GEN 64
  38510. #endif
  38511. /* Calculate second signature value S from R, k and private value.
  38512. *
  38513. * s = (r * x + e) / k
  38514. *
  38515. * s Signature value.
  38516. * r First signature value.
  38517. * k Ephemeral private key.
  38518. * x Private key as a number.
  38519. * e Hash of message as a number.
  38520. * tmp Temporary storage for intermediate numbers.
  38521. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  38522. */
  38523. static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k,
  38524. sp_digit* x, const sp_digit* e, sp_digit* tmp)
  38525. {
  38526. int err;
  38527. sp_digit carry;
  38528. sp_int32 c;
  38529. sp_digit* kInv = k;
  38530. /* Conv k to Montgomery form (mod order) */
  38531. sp_256_mul_8(k, k, p256_norm_order);
  38532. err = sp_256_mod_8(k, k, p256_order);
  38533. if (err == MP_OKAY) {
  38534. sp_256_norm_8(k);
  38535. /* kInv = 1/k mod order */
  38536. sp_256_mont_inv_order_8(kInv, k, tmp);
  38537. sp_256_norm_8(kInv);
  38538. /* s = r * x + e */
  38539. sp_256_mul_8(x, x, r);
  38540. err = sp_256_mod_8(x, x, p256_order);
  38541. }
  38542. if (err == MP_OKAY) {
  38543. sp_256_norm_8(x);
  38544. carry = sp_256_add_8(s, e, x);
  38545. sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
  38546. sp_256_norm_8(s);
  38547. c = sp_256_cmp_8(s, p256_order);
  38548. sp_256_cond_sub_8(s, s, p256_order,
  38549. (sp_digit)0 - (sp_digit)(c >= 0));
  38550. sp_256_norm_8(s);
  38551. /* s = s * k^-1 mod order */
  38552. sp_256_mont_mul_order_8(s, s, kInv);
  38553. sp_256_norm_8(s);
  38554. }
  38555. return err;
  38556. }
  38557. /* Sign the hash using the private key.
  38558. * e = [hash, 256 bits] from binary
  38559. * r = (k.G)->x mod order
  38560. * s = (r * x + e) / k mod order
  38561. * The hash is truncated to the first 256 bits.
  38562. *
  38563. * hash Hash to sign.
  38564. * hashLen Length of the hash data.
  38565. * rng Random number generator.
  38566. * priv Private part of key - scalar.
  38567. * rm First part of result as an mp_int.
  38568. * sm Sirst part of result as an mp_int.
  38569. * heap Heap to use for allocation.
  38570. * returns RNG failures, MEMORY_E when memory allocation fails and
  38571. * MP_OKAY on success.
  38572. */
  38573. int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng,
  38574. const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  38575. {
  38576. #ifdef WOLFSSL_SP_SMALL_STACK
  38577. sp_digit* e = NULL;
  38578. sp_point_256* point = NULL;
  38579. #else
  38580. sp_digit e[7 * 2 * 8];
  38581. sp_point_256 point[1];
  38582. #endif
  38583. sp_digit* x = NULL;
  38584. sp_digit* k = NULL;
  38585. sp_digit* r = NULL;
  38586. sp_digit* tmp = NULL;
  38587. sp_digit* s = NULL;
  38588. sp_int32 c;
  38589. int err = MP_OKAY;
  38590. int i;
  38591. (void)heap;
  38592. #ifdef WOLFSSL_SP_SMALL_STACK
  38593. if (err == MP_OKAY) {
  38594. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  38595. DYNAMIC_TYPE_ECC);
  38596. if (point == NULL)
  38597. err = MEMORY_E;
  38598. }
  38599. if (err == MP_OKAY) {
  38600. e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap,
  38601. DYNAMIC_TYPE_ECC);
  38602. if (e == NULL)
  38603. err = MEMORY_E;
  38604. }
  38605. #endif
  38606. if (err == MP_OKAY) {
  38607. x = e + 2 * 8;
  38608. k = e + 4 * 8;
  38609. r = e + 6 * 8;
  38610. tmp = e + 8 * 8;
  38611. s = e;
  38612. if (hashLen > 32U) {
  38613. hashLen = 32U;
  38614. }
  38615. }
  38616. for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
  38617. /* New random point. */
  38618. if (km == NULL || mp_iszero(km)) {
  38619. err = sp_256_ecc_gen_k_8(rng, k);
  38620. }
  38621. else {
  38622. sp_256_from_mp(k, 8, km);
  38623. mp_zero(km);
  38624. }
  38625. if (err == MP_OKAY) {
  38626. err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap);
  38627. }
  38628. if (err == MP_OKAY) {
  38629. /* r = point->x mod order */
  38630. XMEMCPY(r, point->x, sizeof(sp_digit) * 8U);
  38631. sp_256_norm_8(r);
  38632. c = sp_256_cmp_8(r, p256_order);
  38633. sp_256_cond_sub_8(r, r, p256_order,
  38634. (sp_digit)0 - (sp_digit)(c >= 0));
  38635. sp_256_norm_8(r);
  38636. if (!sp_256_iszero_8(r)) {
  38637. /* x is modified in calculation of s. */
  38638. sp_256_from_mp(x, 8, priv);
  38639. /* s ptr == e ptr, e is modified in calculation of s. */
  38640. sp_256_from_bin(e, 8, hash, (int)hashLen);
  38641. err = sp_256_calc_s_8(s, r, k, x, e, tmp);
  38642. /* Check that signature is usable. */
  38643. if ((err == MP_OKAY) && (!sp_256_iszero_8(s))) {
  38644. break;
  38645. }
  38646. }
  38647. }
  38648. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  38649. i = 1;
  38650. #endif
  38651. }
  38652. if (i == 0) {
  38653. err = RNG_FAILURE_E;
  38654. }
  38655. if (err == MP_OKAY) {
  38656. err = sp_256_to_mp(r, rm);
  38657. }
  38658. if (err == MP_OKAY) {
  38659. err = sp_256_to_mp(s, sm);
  38660. }
  38661. #ifdef WOLFSSL_SP_SMALL_STACK
  38662. if (e != NULL)
  38663. #endif
  38664. {
  38665. ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8);
  38666. #ifdef WOLFSSL_SP_SMALL_STACK
  38667. XFREE(e, heap, DYNAMIC_TYPE_ECC);
  38668. #endif
  38669. }
  38670. #ifdef WOLFSSL_SP_SMALL_STACK
  38671. if (point != NULL)
  38672. #endif
  38673. {
  38674. ForceZero(point, sizeof(sp_point_256));
  38675. #ifdef WOLFSSL_SP_SMALL_STACK
  38676. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  38677. #endif
  38678. }
  38679. return err;
  38680. }
  38681. #ifdef WOLFSSL_SP_NONBLOCK
  38682. typedef struct sp_ecc_sign_256_ctx {
  38683. int state;
  38684. union {
  38685. sp_256_ecc_mulmod_8_ctx mulmod_ctx;
  38686. sp_256_mont_inv_order_8_ctx mont_inv_order_ctx;
  38687. };
  38688. sp_digit e[2*8];
  38689. sp_digit x[2*8];
  38690. sp_digit k[2*8];
  38691. sp_digit r[2*8];
  38692. sp_digit tmp[3 * 2*8];
  38693. sp_point_256 point;
  38694. sp_digit* s;
  38695. sp_digit* kInv;
  38696. int i;
  38697. } sp_ecc_sign_256_ctx;
  38698. int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
  38699. mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  38700. {
  38701. int err = FP_WOULDBLOCK;
  38702. sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data;
  38703. typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  38704. (void)sizeof(ctx_size_test);
  38705. switch (ctx->state) {
  38706. case 0: /* INIT */
  38707. ctx->s = ctx->e;
  38708. ctx->kInv = ctx->k;
  38709. ctx->i = SP_ECC_MAX_SIG_GEN;
  38710. ctx->state = 1;
  38711. break;
  38712. case 1: /* GEN */
  38713. /* New random point. */
  38714. if (km == NULL || mp_iszero(km)) {
  38715. err = sp_256_ecc_gen_k_8(rng, ctx->k);
  38716. }
  38717. else {
  38718. sp_256_from_mp(ctx->k, 8, km);
  38719. mp_zero(km);
  38720. }
  38721. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  38722. ctx->state = 2;
  38723. break;
  38724. case 2: /* MULMOD */
  38725. err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  38726. &ctx->point, &p256_base, ctx->k, 1, 1, heap);
  38727. if (err == MP_OKAY) {
  38728. ctx->state = 3;
  38729. }
  38730. break;
  38731. case 3: /* MODORDER */
  38732. {
  38733. sp_int32 c;
  38734. /* r = point->x mod order */
  38735. XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 8U);
  38736. sp_256_norm_8(ctx->r);
  38737. c = sp_256_cmp_8(ctx->r, p256_order);
  38738. sp_256_cond_sub_8(ctx->r, ctx->r, p256_order,
  38739. (sp_digit)0 - (sp_digit)(c >= 0));
  38740. sp_256_norm_8(ctx->r);
  38741. if (hashLen > 32U) {
  38742. hashLen = 32U;
  38743. }
  38744. sp_256_from_mp(ctx->x, 8, priv);
  38745. sp_256_from_bin(ctx->e, 8, hash, (int)hashLen);
  38746. ctx->state = 4;
  38747. break;
  38748. }
  38749. case 4: /* KMODORDER */
  38750. /* Conv k to Montgomery form (mod order) */
  38751. sp_256_mul_8(ctx->k, ctx->k, p256_norm_order);
  38752. err = sp_256_mod_8(ctx->k, ctx->k, p256_order);
  38753. if (err == MP_OKAY) {
  38754. sp_256_norm_8(ctx->k);
  38755. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  38756. ctx->state = 5;
  38757. }
  38758. break;
  38759. case 5: /* KINV */
  38760. /* kInv = 1/k mod order */
  38761. err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
  38762. if (err == MP_OKAY) {
  38763. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  38764. ctx->state = 6;
  38765. }
  38766. break;
  38767. case 6: /* KINVNORM */
  38768. sp_256_norm_8(ctx->kInv);
  38769. ctx->state = 7;
  38770. break;
  38771. case 7: /* R */
  38772. /* s = r * x + e */
  38773. sp_256_mul_8(ctx->x, ctx->x, ctx->r);
  38774. ctx->state = 8;
  38775. break;
  38776. case 8: /* S1 */
  38777. err = sp_256_mod_8(ctx->x, ctx->x, p256_order);
  38778. if (err == MP_OKAY)
  38779. ctx->state = 9;
  38780. break;
  38781. case 9: /* S2 */
  38782. {
  38783. sp_digit carry;
  38784. sp_int32 c;
  38785. sp_256_norm_8(ctx->x);
  38786. carry = sp_256_add_8(ctx->s, ctx->e, ctx->x);
  38787. sp_256_cond_sub_8(ctx->s, ctx->s,
  38788. p256_order, 0 - carry);
  38789. sp_256_norm_8(ctx->s);
  38790. c = sp_256_cmp_8(ctx->s, p256_order);
  38791. sp_256_cond_sub_8(ctx->s, ctx->s, p256_order,
  38792. (sp_digit)0 - (sp_digit)(c >= 0));
  38793. sp_256_norm_8(ctx->s);
  38794. /* s = s * k^-1 mod order */
  38795. sp_256_mont_mul_order_8(ctx->s, ctx->s, ctx->kInv);
  38796. sp_256_norm_8(ctx->s);
  38797. /* Check that signature is usable. */
  38798. if (sp_256_iszero_8(ctx->s) == 0) {
  38799. ctx->state = 10;
  38800. break;
  38801. }
  38802. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  38803. ctx->i = 1;
  38804. #endif
  38805. /* not usable gen, try again */
  38806. ctx->i--;
  38807. if (ctx->i == 0) {
  38808. err = RNG_FAILURE_E;
  38809. }
  38810. ctx->state = 1;
  38811. break;
  38812. }
  38813. case 10: /* RES */
  38814. err = sp_256_to_mp(ctx->r, rm);
  38815. if (err == MP_OKAY) {
  38816. err = sp_256_to_mp(ctx->s, sm);
  38817. }
  38818. break;
  38819. }
  38820. if (err == MP_OKAY && ctx->state != 10) {
  38821. err = FP_WOULDBLOCK;
  38822. }
  38823. if (err != FP_WOULDBLOCK) {
  38824. XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 8U);
  38825. XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 8U);
  38826. XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 8U);
  38827. XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 8U);
  38828. XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U);
  38829. }
  38830. return err;
  38831. }
  38832. #endif /* WOLFSSL_SP_NONBLOCK */
  38833. #endif /* HAVE_ECC_SIGN */
  38834. #ifndef WOLFSSL_SP_SMALL
  38835. #ifdef WOLFSSL_SP_SMALL
  38836. /* Sub b from a into r. (r = a - b)
  38837. *
  38838. * r A single precision integer.
  38839. * a A single precision integer.
  38840. * b A single precision integer.
  38841. */
  38842. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38843. static sp_digit sp_256_sub_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  38844. #else
  38845. static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  38846. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38847. {
  38848. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38849. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  38850. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  38851. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  38852. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38853. __asm__ __volatile__ (
  38854. "MOV r11, #0x0\n\t"
  38855. "ADD r12, %[a], #0x20\n\t"
  38856. "\n"
  38857. "L_sp_256_sub_8_word:\n\t"
  38858. "RSBS r11, r11, #0x0\n\t"
  38859. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  38860. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  38861. "SBCS r3, r3, r7\n\t"
  38862. "SBCS r4, r4, r8\n\t"
  38863. "SBCS r5, r5, r9\n\t"
  38864. "SBCS r6, r6, r10\n\t"
  38865. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  38866. "SBC r11, r3, r3\n\t"
  38867. "CMP %[a], r12\n\t"
  38868. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  38869. "BNE L_sp_256_sub_8_word\n\t"
  38870. #else
  38871. "BNE.N L_sp_256_sub_8_word\n\t"
  38872. #endif
  38873. "MOV %[r], r11\n\t"
  38874. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  38875. :
  38876. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  38877. );
  38878. return (uint32_t)(size_t)r;
  38879. }
  38880. #else
  38881. /* Sub b from a into r. (r = a - b)
  38882. *
  38883. * r A single precision integer.
  38884. * a A single precision integer.
  38885. * b A single precision integer.
  38886. */
  38887. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38888. static sp_digit sp_256_sub_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  38889. #else
  38890. static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
  38891. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38892. {
  38893. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38894. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  38895. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  38896. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  38897. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38898. __asm__ __volatile__ (
  38899. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  38900. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  38901. "SUBS r3, r3, r7\n\t"
  38902. "SBCS r4, r4, r8\n\t"
  38903. "SBCS r5, r5, r9\n\t"
  38904. "SBCS r6, r6, r10\n\t"
  38905. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  38906. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  38907. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  38908. "SBCS r3, r3, r7\n\t"
  38909. "SBCS r4, r4, r8\n\t"
  38910. "SBCS r5, r5, r9\n\t"
  38911. "SBCS r6, r6, r10\n\t"
  38912. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  38913. "SBC %[r], r6, r6\n\t"
  38914. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  38915. :
  38916. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  38917. );
  38918. return (uint32_t)(size_t)r;
  38919. }
  38920. #endif /* WOLFSSL_SP_SMALL */
  38921. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38922. static void sp_256_rshift1_8(sp_digit* r_p, const sp_digit* a_p)
  38923. #else
  38924. static void sp_256_rshift1_8(sp_digit* r, const sp_digit* a)
  38925. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38926. {
  38927. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38928. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  38929. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  38930. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38931. __asm__ __volatile__ (
  38932. "MOV r10, #0x0\n\t"
  38933. "LDRD r2, r3, [%[a], #16]\n\t"
  38934. "LDRD r4, r5, [%[a], #24]\n\t"
  38935. "LSR r6, r2, #1\n\t"
  38936. "LSR r7, r3, #1\n\t"
  38937. "LSR r8, r4, #1\n\t"
  38938. "LSR r9, r5, #1\n\t"
  38939. "ORR r6, r6, r3, lsl #31\n\t"
  38940. "ORR r7, r7, r4, lsl #31\n\t"
  38941. "ORR r8, r8, r5, lsl #31\n\t"
  38942. "ORR r9, r9, r10, lsl #31\n\t"
  38943. "MOV r10, r2\n\t"
  38944. "STRD r6, r7, [%[r], #16]\n\t"
  38945. "STRD r8, r9, [%[r], #24]\n\t"
  38946. "LDRD r2, r3, [%[a]]\n\t"
  38947. "LDRD r4, r5, [%[a], #8]\n\t"
  38948. "LSR r6, r2, #1\n\t"
  38949. "LSR r7, r3, #1\n\t"
  38950. "LSR r8, r4, #1\n\t"
  38951. "LSR r9, r5, #1\n\t"
  38952. "ORR r6, r6, r3, lsl #31\n\t"
  38953. "ORR r7, r7, r4, lsl #31\n\t"
  38954. "ORR r8, r8, r5, lsl #31\n\t"
  38955. "ORR r9, r9, r10, lsl #31\n\t"
  38956. "STRD r6, r7, [%[r]]\n\t"
  38957. "STRD r8, r9, [%[r], #8]\n\t"
  38958. : [r] "+r" (r), [a] "+r" (a)
  38959. :
  38960. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  38961. );
  38962. }
  38963. /* Divide the number by 2 mod the modulus. (r = a / 2 % m)
  38964. *
  38965. * r Result of division by 2.
  38966. * a Number to divide.
  38967. * m Modulus.
  38968. */
  38969. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38970. static void sp_256_div2_mod_8(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  38971. #else
  38972. static void sp_256_div2_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
  38973. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38974. {
  38975. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  38976. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  38977. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  38978. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  38979. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  38980. __asm__ __volatile__ (
  38981. "MOV r12, #0x0\n\t"
  38982. "LDM %[a]!, {r4}\n\t"
  38983. "ANDS r3, r4, #0x1\n\t"
  38984. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  38985. "BEQ L_sp_256_div2_mod_8_even\n\t"
  38986. #else
  38987. "BEQ.N L_sp_256_div2_mod_8_even\n\t"
  38988. #endif
  38989. "LDM %[a]!, {r5, r6, r7}\n\t"
  38990. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  38991. "ADDS r4, r4, r8\n\t"
  38992. "ADCS r5, r5, r9\n\t"
  38993. "ADCS r6, r6, r10\n\t"
  38994. "ADCS r7, r7, r11\n\t"
  38995. "STM %[r], {r4, r5, r6, r7}\n\t"
  38996. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  38997. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  38998. "ADCS r4, r4, r8\n\t"
  38999. "ADCS r5, r5, r9\n\t"
  39000. "ADCS r6, r6, r10\n\t"
  39001. "ADCS r7, r7, r11\n\t"
  39002. "ADC r3, r12, r12\n\t"
  39003. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39004. "B L_sp_256_div2_mod_8_div2\n\t"
  39005. #else
  39006. "B.N L_sp_256_div2_mod_8_div2\n\t"
  39007. #endif
  39008. "\n"
  39009. "L_sp_256_div2_mod_8_even:\n\t"
  39010. "LDRD r4, r5, [%[a], #12]\n\t"
  39011. "LDRD r6, r7, [%[a], #20]\n\t"
  39012. "\n"
  39013. "L_sp_256_div2_mod_8_div2:\n\t"
  39014. "LSR r8, r4, #1\n\t"
  39015. "AND r4, r4, #0x1\n\t"
  39016. "LSR r9, r5, #1\n\t"
  39017. "LSR r10, r6, #1\n\t"
  39018. "LSR r11, r7, #1\n\t"
  39019. "ORR r8, r8, r5, lsl #31\n\t"
  39020. "ORR r9, r9, r6, lsl #31\n\t"
  39021. "ORR r10, r10, r7, lsl #31\n\t"
  39022. "ORR r11, r11, r3, lsl #31\n\t"
  39023. "MOV r3, r4\n\t"
  39024. "STRD r8, r9, [%[r], #16]\n\t"
  39025. "STRD r10, r11, [%[r], #24]\n\t"
  39026. "LDM %[r], {r4, r5, r6, r7}\n\t"
  39027. "LSR r8, r4, #1\n\t"
  39028. "LSR r9, r5, #1\n\t"
  39029. "LSR r10, r6, #1\n\t"
  39030. "LSR r11, r7, #1\n\t"
  39031. "ORR r8, r8, r5, lsl #31\n\t"
  39032. "ORR r9, r9, r6, lsl #31\n\t"
  39033. "ORR r10, r10, r7, lsl #31\n\t"
  39034. "ORR r11, r11, r3, lsl #31\n\t"
  39035. "STM %[r], {r8, r9, r10, r11}\n\t"
  39036. : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
  39037. :
  39038. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  39039. );
  39040. }
  39041. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  39042. static int sp_256_num_bits_8(const sp_digit* a_p)
  39043. #else
  39044. static int sp_256_num_bits_8(const sp_digit* a)
  39045. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  39046. {
  39047. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  39048. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  39049. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  39050. __asm__ __volatile__ (
  39051. "LDR r1, [%[a], #28]\n\t"
  39052. "CMP r1, #0x0\n\t"
  39053. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39054. "BEQ L_sp_256_num_bits_8_7\n\t"
  39055. #else
  39056. "BEQ.N L_sp_256_num_bits_8_7\n\t"
  39057. #endif
  39058. "MOV r2, #0x100\n\t"
  39059. "CLZ r4, r1\n\t"
  39060. "SUB r4, r2, r4\n\t"
  39061. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39062. "B L_sp_256_num_bits_8_9\n\t"
  39063. #else
  39064. "B.N L_sp_256_num_bits_8_9\n\t"
  39065. #endif
  39066. "\n"
  39067. "L_sp_256_num_bits_8_7:\n\t"
  39068. "LDR r1, [%[a], #24]\n\t"
  39069. "CMP r1, #0x0\n\t"
  39070. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39071. "BEQ L_sp_256_num_bits_8_6\n\t"
  39072. #else
  39073. "BEQ.N L_sp_256_num_bits_8_6\n\t"
  39074. #endif
  39075. "MOV r2, #0xe0\n\t"
  39076. "CLZ r4, r1\n\t"
  39077. "SUB r4, r2, r4\n\t"
  39078. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39079. "B L_sp_256_num_bits_8_9\n\t"
  39080. #else
  39081. "B.N L_sp_256_num_bits_8_9\n\t"
  39082. #endif
  39083. "\n"
  39084. "L_sp_256_num_bits_8_6:\n\t"
  39085. "LDR r1, [%[a], #20]\n\t"
  39086. "CMP r1, #0x0\n\t"
  39087. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39088. "BEQ L_sp_256_num_bits_8_5\n\t"
  39089. #else
  39090. "BEQ.N L_sp_256_num_bits_8_5\n\t"
  39091. #endif
  39092. "MOV r2, #0xc0\n\t"
  39093. "CLZ r4, r1\n\t"
  39094. "SUB r4, r2, r4\n\t"
  39095. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39096. "B L_sp_256_num_bits_8_9\n\t"
  39097. #else
  39098. "B.N L_sp_256_num_bits_8_9\n\t"
  39099. #endif
  39100. "\n"
  39101. "L_sp_256_num_bits_8_5:\n\t"
  39102. "LDR r1, [%[a], #16]\n\t"
  39103. "CMP r1, #0x0\n\t"
  39104. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39105. "BEQ L_sp_256_num_bits_8_4\n\t"
  39106. #else
  39107. "BEQ.N L_sp_256_num_bits_8_4\n\t"
  39108. #endif
  39109. "MOV r2, #0xa0\n\t"
  39110. "CLZ r4, r1\n\t"
  39111. "SUB r4, r2, r4\n\t"
  39112. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39113. "B L_sp_256_num_bits_8_9\n\t"
  39114. #else
  39115. "B.N L_sp_256_num_bits_8_9\n\t"
  39116. #endif
  39117. "\n"
  39118. "L_sp_256_num_bits_8_4:\n\t"
  39119. "LDR r1, [%[a], #12]\n\t"
  39120. "CMP r1, #0x0\n\t"
  39121. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39122. "BEQ L_sp_256_num_bits_8_3\n\t"
  39123. #else
  39124. "BEQ.N L_sp_256_num_bits_8_3\n\t"
  39125. #endif
  39126. "MOV r2, #0x80\n\t"
  39127. "CLZ r4, r1\n\t"
  39128. "SUB r4, r2, r4\n\t"
  39129. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39130. "B L_sp_256_num_bits_8_9\n\t"
  39131. #else
  39132. "B.N L_sp_256_num_bits_8_9\n\t"
  39133. #endif
  39134. "\n"
  39135. "L_sp_256_num_bits_8_3:\n\t"
  39136. "LDR r1, [%[a], #8]\n\t"
  39137. "CMP r1, #0x0\n\t"
  39138. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39139. "BEQ L_sp_256_num_bits_8_2\n\t"
  39140. #else
  39141. "BEQ.N L_sp_256_num_bits_8_2\n\t"
  39142. #endif
  39143. "MOV r2, #0x60\n\t"
  39144. "CLZ r4, r1\n\t"
  39145. "SUB r4, r2, r4\n\t"
  39146. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39147. "B L_sp_256_num_bits_8_9\n\t"
  39148. #else
  39149. "B.N L_sp_256_num_bits_8_9\n\t"
  39150. #endif
  39151. "\n"
  39152. "L_sp_256_num_bits_8_2:\n\t"
  39153. "LDR r1, [%[a], #4]\n\t"
  39154. "CMP r1, #0x0\n\t"
  39155. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39156. "BEQ L_sp_256_num_bits_8_1\n\t"
  39157. #else
  39158. "BEQ.N L_sp_256_num_bits_8_1\n\t"
  39159. #endif
  39160. "MOV r2, #0x40\n\t"
  39161. "CLZ r4, r1\n\t"
  39162. "SUB r4, r2, r4\n\t"
  39163. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  39164. "B L_sp_256_num_bits_8_9\n\t"
  39165. #else
  39166. "B.N L_sp_256_num_bits_8_9\n\t"
  39167. #endif
  39168. "\n"
  39169. "L_sp_256_num_bits_8_1:\n\t"
  39170. "LDR r1, [%[a]]\n\t"
  39171. "MOV r2, #0x20\n\t"
  39172. "CLZ r4, r1\n\t"
  39173. "SUB r4, r2, r4\n\t"
  39174. "\n"
  39175. "L_sp_256_num_bits_8_9:\n\t"
  39176. "MOV %[a], r4\n\t"
  39177. : [a] "+r" (a)
  39178. :
  39179. : "memory", "r1", "r2", "r3", "r4", "r5", "cc"
  39180. );
  39181. return (uint32_t)(size_t)a;
  39182. }
  39183. /* Non-constant time modular inversion.
  39184. *
  39185. * @param [out] r Resulting number.
  39186. * @param [in] a Number to invert.
  39187. * @param [in] m Modulus.
  39188. * @return MP_OKAY on success.
  39189. */
  39190. static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
  39191. {
  39192. sp_digit u[8];
  39193. sp_digit v[8];
  39194. sp_digit b[8];
  39195. sp_digit d[8];
  39196. int ut, vt;
  39197. sp_digit o;
  39198. XMEMCPY(u, m, sizeof(u));
  39199. XMEMCPY(v, a, sizeof(v));
  39200. ut = sp_256_num_bits_8(u);
  39201. vt = sp_256_num_bits_8(v);
  39202. XMEMSET(b, 0, sizeof(b));
  39203. if ((v[0] & 1) == 0) {
  39204. sp_256_rshift1_8(v, v);
  39205. XMEMCPY(d, m, sizeof(u));
  39206. d[0] += 1;
  39207. sp_256_rshift1_8(d, d);
  39208. vt--;
  39209. while ((v[0] & 1) == 0) {
  39210. sp_256_rshift1_8(v, v);
  39211. sp_256_div2_mod_8(d, d, m);
  39212. vt--;
  39213. }
  39214. }
  39215. else {
  39216. XMEMSET(d+1, 0, sizeof(d)-sizeof(sp_digit));
  39217. d[0] = 1;
  39218. }
  39219. while (ut > 1 && vt > 1) {
  39220. if ((ut > vt) || ((ut == vt) && (sp_256_cmp_8(u, v) >= 0))) {
  39221. sp_256_sub_8(u, u, v);
  39222. o = sp_256_sub_8(b, b, d);
  39223. if (o != 0)
  39224. sp_256_add_8(b, b, m);
  39225. ut = sp_256_num_bits_8(u);
  39226. do {
  39227. sp_256_rshift1_8(u, u);
  39228. sp_256_div2_mod_8(b, b, m);
  39229. ut--;
  39230. }
  39231. while (ut > 0 && (u[0] & 1) == 0);
  39232. }
  39233. else {
  39234. sp_256_sub_8(v, v, u);
  39235. o = sp_256_sub_8(d, d, b);
  39236. if (o != 0)
  39237. sp_256_add_8(d, d, m);
  39238. vt = sp_256_num_bits_8(v);
  39239. do {
  39240. sp_256_rshift1_8(v, v);
  39241. sp_256_div2_mod_8(d, d, m);
  39242. vt--;
  39243. }
  39244. while (vt > 0 && (v[0] & 1) == 0);
  39245. }
  39246. }
  39247. if (ut == 1)
  39248. XMEMCPY(r, b, sizeof(b));
  39249. else
  39250. XMEMCPY(r, d, sizeof(d));
  39251. return MP_OKAY;
  39252. }
  39253. #endif /* WOLFSSL_SP_SMALL */
  39254. /* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
  39255. *
  39256. * p1 First point to add and holds result.
  39257. * p2 Second point to add.
  39258. * tmp Temporary storage for intermediate numbers.
  39259. */
  39260. static void sp_256_add_points_8(sp_point_256* p1, const sp_point_256* p2,
  39261. sp_digit* tmp)
  39262. {
  39263. sp_256_proj_point_add_8(p1, p1, p2, tmp);
  39264. if (sp_256_iszero_8(p1->z)) {
  39265. if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
  39266. sp_256_proj_point_dbl_8(p1, p2, tmp);
  39267. }
  39268. else {
  39269. /* Y ordinate is not used from here - don't set. */
  39270. p1->x[0] = 0;
  39271. p1->x[1] = 0;
  39272. p1->x[2] = 0;
  39273. p1->x[3] = 0;
  39274. p1->x[4] = 0;
  39275. p1->x[5] = 0;
  39276. p1->x[6] = 0;
  39277. p1->x[7] = 0;
  39278. XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
  39279. }
  39280. }
  39281. }
  39282. /* Calculate the verification point: [e/s]G + [r/s]Q
  39283. *
  39284. * p1 Calculated point.
  39285. * p2 Public point and temporary.
  39286. * s Second part of signature as a number.
  39287. * u1 Temporary number.
  39288. * u2 Temporary number.
  39289. * heap Heap to use for allocation.
  39290. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  39291. */
  39292. static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2,
  39293. sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
  39294. {
  39295. int err;
  39296. #ifndef WOLFSSL_SP_SMALL
  39297. err = sp_256_mod_inv_8(s, s, p256_order);
  39298. if (err == MP_OKAY)
  39299. #endif /* !WOLFSSL_SP_SMALL */
  39300. {
  39301. sp_256_mul_8(s, s, p256_norm_order);
  39302. err = sp_256_mod_8(s, s, p256_order);
  39303. }
  39304. if (err == MP_OKAY) {
  39305. sp_256_norm_8(s);
  39306. #ifdef WOLFSSL_SP_SMALL
  39307. {
  39308. sp_256_mont_inv_order_8(s, s, tmp);
  39309. sp_256_mont_mul_order_8(u1, u1, s);
  39310. sp_256_mont_mul_order_8(u2, u2, s);
  39311. }
  39312. #else
  39313. {
  39314. sp_256_mont_mul_order_8(u1, u1, s);
  39315. sp_256_mont_mul_order_8(u2, u2, s);
  39316. }
  39317. #endif /* WOLFSSL_SP_SMALL */
  39318. {
  39319. err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap);
  39320. }
  39321. }
  39322. if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) {
  39323. p1->infinity = 1;
  39324. }
  39325. if (err == MP_OKAY) {
  39326. err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap);
  39327. }
  39328. if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) {
  39329. p2->infinity = 1;
  39330. }
  39331. if (err == MP_OKAY) {
  39332. sp_256_add_points_8(p1, p2, tmp);
  39333. }
  39334. return err;
  39335. }
  39336. #ifdef HAVE_ECC_VERIFY
  39337. /* Verify the signature values with the hash and public key.
  39338. * e = Truncate(hash, 256)
  39339. * u1 = e/s mod order
  39340. * u2 = r/s mod order
  39341. * r == (u1.G + u2.Q)->x mod order
  39342. * Optimization: Leave point in projective form.
  39343. * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
  39344. * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
  39345. * The hash is truncated to the first 256 bits.
  39346. *
  39347. * hash Hash to sign.
  39348. * hashLen Length of the hash data.
  39349. * rng Random number generator.
  39350. * priv Private part of key - scalar.
  39351. * rm First part of result as an mp_int.
  39352. * sm Sirst part of result as an mp_int.
  39353. * heap Heap to use for allocation.
  39354. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  39355. */
  39356. int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX,
  39357. const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
  39358. int* res, void* heap)
  39359. {
  39360. #ifdef WOLFSSL_SP_SMALL_STACK
  39361. sp_digit* u1 = NULL;
  39362. sp_point_256* p1 = NULL;
  39363. #else
  39364. sp_digit u1[18 * 8];
  39365. sp_point_256 p1[2];
  39366. #endif
  39367. sp_digit* u2 = NULL;
  39368. sp_digit* s = NULL;
  39369. sp_digit* tmp = NULL;
  39370. sp_point_256* p2 = NULL;
  39371. sp_digit carry;
  39372. sp_int32 c = 0;
  39373. int err = MP_OKAY;
  39374. #ifdef WOLFSSL_SP_SMALL_STACK
  39375. if (err == MP_OKAY) {
  39376. p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  39377. DYNAMIC_TYPE_ECC);
  39378. if (p1 == NULL)
  39379. err = MEMORY_E;
  39380. }
  39381. if (err == MP_OKAY) {
  39382. u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 8, heap,
  39383. DYNAMIC_TYPE_ECC);
  39384. if (u1 == NULL)
  39385. err = MEMORY_E;
  39386. }
  39387. #endif
  39388. if (err == MP_OKAY) {
  39389. u2 = u1 + 2 * 8;
  39390. s = u1 + 4 * 8;
  39391. tmp = u1 + 6 * 8;
  39392. p2 = p1 + 1;
  39393. if (hashLen > 32U) {
  39394. hashLen = 32U;
  39395. }
  39396. sp_256_from_bin(u1, 8, hash, (int)hashLen);
  39397. sp_256_from_mp(u2, 8, rm);
  39398. sp_256_from_mp(s, 8, sm);
  39399. sp_256_from_mp(p2->x, 8, pX);
  39400. sp_256_from_mp(p2->y, 8, pY);
  39401. sp_256_from_mp(p2->z, 8, pZ);
  39402. err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap);
  39403. }
  39404. if (err == MP_OKAY) {
  39405. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  39406. /* Reload r and convert to Montgomery form. */
  39407. sp_256_from_mp(u2, 8, rm);
  39408. err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
  39409. }
  39410. if (err == MP_OKAY) {
  39411. /* u1 = r.z'.z' mod prime */
  39412. sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod);
  39413. sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod);
  39414. *res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
  39415. if (*res == 0) {
  39416. /* Reload r and add order. */
  39417. sp_256_from_mp(u2, 8, rm);
  39418. carry = sp_256_add_8(u2, u2, p256_order);
  39419. /* Carry means result is greater than mod and is not valid. */
  39420. if (carry == 0) {
  39421. sp_256_norm_8(u2);
  39422. /* Compare with mod and if greater or equal then not valid. */
  39423. c = sp_256_cmp_8(u2, p256_mod);
  39424. }
  39425. }
  39426. if ((*res == 0) && (c < 0)) {
  39427. /* Convert to Montogomery form */
  39428. err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
  39429. if (err == MP_OKAY) {
  39430. /* u1 = (r + 1*order).z'.z' mod prime */
  39431. {
  39432. sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod);
  39433. }
  39434. *res = (sp_256_cmp_8(p1->x, u1) == 0);
  39435. }
  39436. }
  39437. }
  39438. #ifdef WOLFSSL_SP_SMALL_STACK
  39439. if (u1 != NULL)
  39440. XFREE(u1, heap, DYNAMIC_TYPE_ECC);
  39441. if (p1 != NULL)
  39442. XFREE(p1, heap, DYNAMIC_TYPE_ECC);
  39443. #endif
  39444. return err;
  39445. }
  39446. #ifdef WOLFSSL_SP_NONBLOCK
  39447. typedef struct sp_ecc_verify_256_ctx {
  39448. int state;
  39449. union {
  39450. sp_256_ecc_mulmod_8_ctx mulmod_ctx;
  39451. sp_256_mont_inv_order_8_ctx mont_inv_order_ctx;
  39452. sp_256_proj_point_dbl_8_ctx dbl_ctx;
  39453. sp_256_proj_point_add_8_ctx add_ctx;
  39454. };
  39455. sp_digit u1[2*8];
  39456. sp_digit u2[2*8];
  39457. sp_digit s[2*8];
  39458. sp_digit tmp[2*8 * 6];
  39459. sp_point_256 p1;
  39460. sp_point_256 p2;
  39461. } sp_ecc_verify_256_ctx;
  39462. int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
  39463. word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
  39464. const mp_int* rm, const mp_int* sm, int* res, void* heap)
  39465. {
  39466. int err = FP_WOULDBLOCK;
  39467. sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data;
  39468. typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  39469. (void)sizeof(ctx_size_test);
  39470. switch (ctx->state) {
  39471. case 0: /* INIT */
  39472. if (hashLen > 32U) {
  39473. hashLen = 32U;
  39474. }
  39475. sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen);
  39476. sp_256_from_mp(ctx->u2, 8, rm);
  39477. sp_256_from_mp(ctx->s, 8, sm);
  39478. sp_256_from_mp(ctx->p2.x, 8, pX);
  39479. sp_256_from_mp(ctx->p2.y, 8, pY);
  39480. sp_256_from_mp(ctx->p2.z, 8, pZ);
  39481. ctx->state = 1;
  39482. break;
  39483. case 1: /* NORMS0 */
  39484. sp_256_mul_8(ctx->s, ctx->s, p256_norm_order);
  39485. err = sp_256_mod_8(ctx->s, ctx->s, p256_order);
  39486. if (err == MP_OKAY)
  39487. ctx->state = 2;
  39488. break;
  39489. case 2: /* NORMS1 */
  39490. sp_256_norm_8(ctx->s);
  39491. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  39492. ctx->state = 3;
  39493. break;
  39494. case 3: /* NORMS2 */
  39495. err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
  39496. if (err == MP_OKAY) {
  39497. ctx->state = 4;
  39498. }
  39499. break;
  39500. case 4: /* NORMS3 */
  39501. sp_256_mont_mul_order_8(ctx->u1, ctx->u1, ctx->s);
  39502. ctx->state = 5;
  39503. break;
  39504. case 5: /* NORMS4 */
  39505. sp_256_mont_mul_order_8(ctx->u2, ctx->u2, ctx->s);
  39506. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  39507. ctx->state = 6;
  39508. break;
  39509. case 6: /* MULBASE */
  39510. err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, 0, heap);
  39511. if (err == MP_OKAY) {
  39512. if (sp_256_iszero_8(ctx->p1.z)) {
  39513. ctx->p1.infinity = 1;
  39514. }
  39515. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  39516. ctx->state = 7;
  39517. }
  39518. break;
  39519. case 7: /* MULMOD */
  39520. err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
  39521. if (err == MP_OKAY) {
  39522. if (sp_256_iszero_8(ctx->p2.z)) {
  39523. ctx->p2.infinity = 1;
  39524. }
  39525. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  39526. ctx->state = 8;
  39527. }
  39528. break;
  39529. case 8: /* ADD */
  39530. err = sp_256_proj_point_add_8_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
  39531. if (err == MP_OKAY)
  39532. ctx->state = 9;
  39533. break;
  39534. case 9: /* MONT */
  39535. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  39536. /* Reload r and convert to Montgomery form. */
  39537. sp_256_from_mp(ctx->u2, 8, rm);
  39538. err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod);
  39539. if (err == MP_OKAY)
  39540. ctx->state = 10;
  39541. break;
  39542. case 10: /* SQR */
  39543. /* u1 = r.z'.z' mod prime */
  39544. sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod);
  39545. ctx->state = 11;
  39546. break;
  39547. case 11: /* MUL */
  39548. sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod);
  39549. ctx->state = 12;
  39550. break;
  39551. case 12: /* RES */
  39552. {
  39553. sp_int32 c = 0;
  39554. err = MP_OKAY; /* math okay, now check result */
  39555. *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0);
  39556. if (*res == 0) {
  39557. sp_digit carry;
  39558. /* Reload r and add order. */
  39559. sp_256_from_mp(ctx->u2, 8, rm);
  39560. carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order);
  39561. /* Carry means result is greater than mod and is not valid. */
  39562. if (carry == 0) {
  39563. sp_256_norm_8(ctx->u2);
  39564. /* Compare with mod and if greater or equal then not valid. */
  39565. c = sp_256_cmp_8(ctx->u2, p256_mod);
  39566. }
  39567. }
  39568. if ((*res == 0) && (c < 0)) {
  39569. /* Convert to Montogomery form */
  39570. err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod);
  39571. if (err == MP_OKAY) {
  39572. /* u1 = (r + 1*order).z'.z' mod prime */
  39573. sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod,
  39574. p256_mp_mod);
  39575. *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0);
  39576. }
  39577. }
  39578. break;
  39579. }
  39580. } /* switch */
  39581. if (err == MP_OKAY && ctx->state != 12) {
  39582. err = FP_WOULDBLOCK;
  39583. }
  39584. return err;
  39585. }
  39586. #endif /* WOLFSSL_SP_NONBLOCK */
  39587. #endif /* HAVE_ECC_VERIFY */
  39588. #ifdef HAVE_ECC_CHECK_KEY
  39589. /* Check that the x and y ordinates are a valid point on the curve.
  39590. *
  39591. * point EC point.
  39592. * heap Heap to use if dynamically allocating.
  39593. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  39594. * not on the curve and MP_OKAY otherwise.
  39595. */
  39596. static int sp_256_ecc_is_point_8(const sp_point_256* point,
  39597. void* heap)
  39598. {
  39599. #ifdef WOLFSSL_SP_SMALL_STACK
  39600. sp_digit* t1 = NULL;
  39601. #else
  39602. sp_digit t1[8 * 4];
  39603. #endif
  39604. sp_digit* t2 = NULL;
  39605. int err = MP_OKAY;
  39606. #ifdef WOLFSSL_SP_SMALL_STACK
  39607. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC);
  39608. if (t1 == NULL)
  39609. err = MEMORY_E;
  39610. #endif
  39611. (void)heap;
  39612. if (err == MP_OKAY) {
  39613. t2 = t1 + 2 * 8;
  39614. /* y^2 - x^3 - a.x = b */
  39615. sp_256_sqr_8(t1, point->y);
  39616. (void)sp_256_mod_8(t1, t1, p256_mod);
  39617. sp_256_sqr_8(t2, point->x);
  39618. (void)sp_256_mod_8(t2, t2, p256_mod);
  39619. sp_256_mul_8(t2, t2, point->x);
  39620. (void)sp_256_mod_8(t2, t2, p256_mod);
  39621. sp_256_mont_sub_8(t1, t1, t2, p256_mod);
  39622. /* y^2 - x^3 + 3.x = b, when a = -3 */
  39623. sp_256_mont_add_8(t1, t1, point->x, p256_mod);
  39624. sp_256_mont_add_8(t1, t1, point->x, p256_mod);
  39625. sp_256_mont_add_8(t1, t1, point->x, p256_mod);
  39626. if (sp_256_cmp_8(t1, p256_b) != 0) {
  39627. err = MP_VAL;
  39628. }
  39629. }
  39630. #ifdef WOLFSSL_SP_SMALL_STACK
  39631. if (t1 != NULL)
  39632. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  39633. #endif
  39634. return err;
  39635. }
  39636. /* Check that the x and y ordinates are a valid point on the curve.
  39637. *
  39638. * pX X ordinate of EC point.
  39639. * pY Y ordinate of EC point.
  39640. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  39641. * not on the curve and MP_OKAY otherwise.
  39642. */
  39643. int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY)
  39644. {
  39645. #ifdef WOLFSSL_SP_SMALL_STACK
  39646. sp_point_256* pub = NULL;
  39647. #else
  39648. sp_point_256 pub[1];
  39649. #endif
  39650. const byte one[1] = { 1 };
  39651. int err = MP_OKAY;
  39652. #ifdef WOLFSSL_SP_SMALL_STACK
  39653. pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
  39654. DYNAMIC_TYPE_ECC);
  39655. if (pub == NULL)
  39656. err = MEMORY_E;
  39657. #endif
  39658. if (err == MP_OKAY) {
  39659. sp_256_from_mp(pub->x, 8, pX);
  39660. sp_256_from_mp(pub->y, 8, pY);
  39661. sp_256_from_bin(pub->z, 8, one, (int)sizeof(one));
  39662. err = sp_256_ecc_is_point_8(pub, NULL);
  39663. }
  39664. #ifdef WOLFSSL_SP_SMALL_STACK
  39665. if (pub != NULL)
  39666. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  39667. #endif
  39668. return err;
  39669. }
  39670. /* Check that the private scalar generates the EC point (px, py), the point is
  39671. * on the curve and the point has the correct order.
  39672. *
  39673. * pX X ordinate of EC point.
  39674. * pY Y ordinate of EC point.
  39675. * privm Private scalar that generates EC point.
  39676. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  39677. * not on the curve, ECC_INF_E if the point does not have the correct order,
  39678. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  39679. * MP_OKAY otherwise.
  39680. */
  39681. int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY,
  39682. const mp_int* privm, void* heap)
  39683. {
  39684. #ifdef WOLFSSL_SP_SMALL_STACK
  39685. sp_digit* priv = NULL;
  39686. sp_point_256* pub = NULL;
  39687. #else
  39688. sp_digit priv[8];
  39689. sp_point_256 pub[2];
  39690. #endif
  39691. sp_point_256* p = NULL;
  39692. const byte one[1] = { 1 };
  39693. int err = MP_OKAY;
  39694. /* Quick check the lengs of public key ordinates and private key are in
  39695. * range. Proper check later.
  39696. */
  39697. if (((mp_count_bits(pX) > 256) ||
  39698. (mp_count_bits(pY) > 256) ||
  39699. ((privm != NULL) && (mp_count_bits(privm) > 256)))) {
  39700. err = ECC_OUT_OF_RANGE_E;
  39701. }
  39702. #ifdef WOLFSSL_SP_SMALL_STACK
  39703. if (err == MP_OKAY) {
  39704. pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  39705. DYNAMIC_TYPE_ECC);
  39706. if (pub == NULL)
  39707. err = MEMORY_E;
  39708. }
  39709. if (err == MP_OKAY && privm) {
  39710. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap,
  39711. DYNAMIC_TYPE_ECC);
  39712. if (priv == NULL)
  39713. err = MEMORY_E;
  39714. }
  39715. #endif
  39716. if (err == MP_OKAY) {
  39717. p = pub + 1;
  39718. sp_256_from_mp(pub->x, 8, pX);
  39719. sp_256_from_mp(pub->y, 8, pY);
  39720. sp_256_from_bin(pub->z, 8, one, (int)sizeof(one));
  39721. if (privm)
  39722. sp_256_from_mp(priv, 8, privm);
  39723. /* Check point at infinitiy. */
  39724. if ((sp_256_iszero_8(pub->x) != 0) &&
  39725. (sp_256_iszero_8(pub->y) != 0)) {
  39726. err = ECC_INF_E;
  39727. }
  39728. }
  39729. /* Check range of X and Y */
  39730. if ((err == MP_OKAY) &&
  39731. ((sp_256_cmp_8(pub->x, p256_mod) >= 0) ||
  39732. (sp_256_cmp_8(pub->y, p256_mod) >= 0))) {
  39733. err = ECC_OUT_OF_RANGE_E;
  39734. }
  39735. if (err == MP_OKAY) {
  39736. /* Check point is on curve */
  39737. err = sp_256_ecc_is_point_8(pub, heap);
  39738. }
  39739. if (err == MP_OKAY) {
  39740. /* Point * order = infinity */
  39741. err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, 1, heap);
  39742. }
  39743. /* Check result is infinity */
  39744. if ((err == MP_OKAY) && ((sp_256_iszero_8(p->x) == 0) ||
  39745. (sp_256_iszero_8(p->y) == 0))) {
  39746. err = ECC_INF_E;
  39747. }
  39748. if (privm) {
  39749. if (err == MP_OKAY) {
  39750. /* Base * private = point */
  39751. err = sp_256_ecc_mulmod_base_8(p, priv, 1, 1, heap);
  39752. }
  39753. /* Check result is public key */
  39754. if ((err == MP_OKAY) &&
  39755. ((sp_256_cmp_8(p->x, pub->x) != 0) ||
  39756. (sp_256_cmp_8(p->y, pub->y) != 0))) {
  39757. err = ECC_PRIV_KEY_E;
  39758. }
  39759. }
  39760. #ifdef WOLFSSL_SP_SMALL_STACK
  39761. if (pub != NULL)
  39762. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  39763. if (priv != NULL)
  39764. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  39765. #endif
  39766. return err;
  39767. }
  39768. #endif
  39769. #ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
  39770. /* Add two projective EC points together.
  39771. * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
  39772. *
  39773. * pX First EC point's X ordinate.
  39774. * pY First EC point's Y ordinate.
  39775. * pZ First EC point's Z ordinate.
  39776. * qX Second EC point's X ordinate.
  39777. * qY Second EC point's Y ordinate.
  39778. * qZ Second EC point's Z ordinate.
  39779. * rX Resultant EC point's X ordinate.
  39780. * rY Resultant EC point's Y ordinate.
  39781. * rZ Resultant EC point's Z ordinate.
  39782. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39783. */
  39784. int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
  39785. mp_int* qX, mp_int* qY, mp_int* qZ,
  39786. mp_int* rX, mp_int* rY, mp_int* rZ)
  39787. {
  39788. #ifdef WOLFSSL_SP_SMALL_STACK
  39789. sp_digit* tmp = NULL;
  39790. sp_point_256* p = NULL;
  39791. #else
  39792. sp_digit tmp[2 * 8 * 6];
  39793. sp_point_256 p[2];
  39794. #endif
  39795. sp_point_256* q = NULL;
  39796. int err = MP_OKAY;
  39797. #ifdef WOLFSSL_SP_SMALL_STACK
  39798. if (err == MP_OKAY) {
  39799. p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL,
  39800. DYNAMIC_TYPE_ECC);
  39801. if (p == NULL)
  39802. err = MEMORY_E;
  39803. }
  39804. if (err == MP_OKAY) {
  39805. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 6, NULL,
  39806. DYNAMIC_TYPE_ECC);
  39807. if (tmp == NULL) {
  39808. err = MEMORY_E;
  39809. }
  39810. }
  39811. #endif
  39812. if (err == MP_OKAY) {
  39813. q = p + 1;
  39814. sp_256_from_mp(p->x, 8, pX);
  39815. sp_256_from_mp(p->y, 8, pY);
  39816. sp_256_from_mp(p->z, 8, pZ);
  39817. sp_256_from_mp(q->x, 8, qX);
  39818. sp_256_from_mp(q->y, 8, qY);
  39819. sp_256_from_mp(q->z, 8, qZ);
  39820. p->infinity = sp_256_iszero_8(p->x) &
  39821. sp_256_iszero_8(p->y);
  39822. q->infinity = sp_256_iszero_8(q->x) &
  39823. sp_256_iszero_8(q->y);
  39824. sp_256_proj_point_add_8(p, p, q, tmp);
  39825. }
  39826. if (err == MP_OKAY) {
  39827. err = sp_256_to_mp(p->x, rX);
  39828. }
  39829. if (err == MP_OKAY) {
  39830. err = sp_256_to_mp(p->y, rY);
  39831. }
  39832. if (err == MP_OKAY) {
  39833. err = sp_256_to_mp(p->z, rZ);
  39834. }
  39835. #ifdef WOLFSSL_SP_SMALL_STACK
  39836. if (tmp != NULL)
  39837. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  39838. if (p != NULL)
  39839. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  39840. #endif
  39841. return err;
  39842. }
  39843. /* Double a projective EC point.
  39844. * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
  39845. *
  39846. * pX EC point's X ordinate.
  39847. * pY EC point's Y ordinate.
  39848. * pZ EC point's Z ordinate.
  39849. * rX Resultant EC point's X ordinate.
  39850. * rY Resultant EC point's Y ordinate.
  39851. * rZ Resultant EC point's Z ordinate.
  39852. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39853. */
  39854. int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
  39855. mp_int* rX, mp_int* rY, mp_int* rZ)
  39856. {
  39857. #ifdef WOLFSSL_SP_SMALL_STACK
  39858. sp_digit* tmp = NULL;
  39859. sp_point_256* p = NULL;
  39860. #else
  39861. sp_digit tmp[2 * 8 * 2];
  39862. sp_point_256 p[1];
  39863. #endif
  39864. int err = MP_OKAY;
  39865. #ifdef WOLFSSL_SP_SMALL_STACK
  39866. if (err == MP_OKAY) {
  39867. p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
  39868. DYNAMIC_TYPE_ECC);
  39869. if (p == NULL)
  39870. err = MEMORY_E;
  39871. }
  39872. if (err == MP_OKAY) {
  39873. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL,
  39874. DYNAMIC_TYPE_ECC);
  39875. if (tmp == NULL)
  39876. err = MEMORY_E;
  39877. }
  39878. #endif
  39879. if (err == MP_OKAY) {
  39880. sp_256_from_mp(p->x, 8, pX);
  39881. sp_256_from_mp(p->y, 8, pY);
  39882. sp_256_from_mp(p->z, 8, pZ);
  39883. p->infinity = sp_256_iszero_8(p->x) &
  39884. sp_256_iszero_8(p->y);
  39885. sp_256_proj_point_dbl_8(p, p, tmp);
  39886. }
  39887. if (err == MP_OKAY) {
  39888. err = sp_256_to_mp(p->x, rX);
  39889. }
  39890. if (err == MP_OKAY) {
  39891. err = sp_256_to_mp(p->y, rY);
  39892. }
  39893. if (err == MP_OKAY) {
  39894. err = sp_256_to_mp(p->z, rZ);
  39895. }
  39896. #ifdef WOLFSSL_SP_SMALL_STACK
  39897. if (tmp != NULL)
  39898. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  39899. if (p != NULL)
  39900. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  39901. #endif
  39902. return err;
  39903. }
  39904. /* Map a projective EC point to affine in place.
  39905. * pZ will be one.
  39906. *
  39907. * pX EC point's X ordinate.
  39908. * pY EC point's Y ordinate.
  39909. * pZ EC point's Z ordinate.
  39910. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39911. */
  39912. int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
  39913. {
  39914. #ifdef WOLFSSL_SP_SMALL_STACK
  39915. sp_digit* tmp = NULL;
  39916. sp_point_256* p = NULL;
  39917. #else
  39918. sp_digit tmp[2 * 8 * 4];
  39919. sp_point_256 p[1];
  39920. #endif
  39921. int err = MP_OKAY;
  39922. #ifdef WOLFSSL_SP_SMALL_STACK
  39923. if (err == MP_OKAY) {
  39924. p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
  39925. DYNAMIC_TYPE_ECC);
  39926. if (p == NULL)
  39927. err = MEMORY_E;
  39928. }
  39929. if (err == MP_OKAY) {
  39930. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL,
  39931. DYNAMIC_TYPE_ECC);
  39932. if (tmp == NULL)
  39933. err = MEMORY_E;
  39934. }
  39935. #endif
  39936. if (err == MP_OKAY) {
  39937. sp_256_from_mp(p->x, 8, pX);
  39938. sp_256_from_mp(p->y, 8, pY);
  39939. sp_256_from_mp(p->z, 8, pZ);
  39940. p->infinity = sp_256_iszero_8(p->x) &
  39941. sp_256_iszero_8(p->y);
  39942. sp_256_map_8(p, p, tmp);
  39943. }
  39944. if (err == MP_OKAY) {
  39945. err = sp_256_to_mp(p->x, pX);
  39946. }
  39947. if (err == MP_OKAY) {
  39948. err = sp_256_to_mp(p->y, pY);
  39949. }
  39950. if (err == MP_OKAY) {
  39951. err = sp_256_to_mp(p->z, pZ);
  39952. }
  39953. #ifdef WOLFSSL_SP_SMALL_STACK
  39954. if (tmp != NULL)
  39955. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  39956. if (p != NULL)
  39957. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  39958. #endif
  39959. return err;
  39960. }
  39961. #endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
  39962. #ifdef HAVE_COMP_KEY
  39963. /* Find the square root of a number mod the prime of the curve.
  39964. *
  39965. * y The number to operate on and the result.
  39966. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39967. */
  39968. static int sp_256_mont_sqrt_8(sp_digit* y)
  39969. {
  39970. #ifdef WOLFSSL_SP_SMALL_STACK
  39971. sp_digit* t1 = NULL;
  39972. #else
  39973. sp_digit t1[4 * 8];
  39974. #endif
  39975. sp_digit* t2 = NULL;
  39976. int err = MP_OKAY;
  39977. #ifdef WOLFSSL_SP_SMALL_STACK
  39978. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC);
  39979. if (t1 == NULL) {
  39980. err = MEMORY_E;
  39981. }
  39982. #endif
  39983. if (err == MP_OKAY) {
  39984. t2 = t1 + 2 * 8;
  39985. {
  39986. /* t2 = y ^ 0x2 */
  39987. sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
  39988. /* t1 = y ^ 0x3 */
  39989. sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod);
  39990. /* t2 = y ^ 0xc */
  39991. sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod);
  39992. /* t1 = y ^ 0xf */
  39993. sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
  39994. /* t2 = y ^ 0xf0 */
  39995. sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod);
  39996. /* t1 = y ^ 0xff */
  39997. sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
  39998. /* t2 = y ^ 0xff00 */
  39999. sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod);
  40000. /* t1 = y ^ 0xffff */
  40001. sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
  40002. /* t2 = y ^ 0xffff0000 */
  40003. sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod);
  40004. /* t1 = y ^ 0xffffffff */
  40005. sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
  40006. /* t1 = y ^ 0xffffffff00000000 */
  40007. sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod);
  40008. /* t1 = y ^ 0xffffffff00000001 */
  40009. sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod);
  40010. /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
  40011. sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod);
  40012. /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
  40013. sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod);
  40014. sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod);
  40015. }
  40016. }
  40017. #ifdef WOLFSSL_SP_SMALL_STACK
  40018. if (t1 != NULL)
  40019. XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
  40020. #endif
  40021. return err;
  40022. }
  40023. /* Uncompress the point given the X ordinate.
  40024. *
  40025. * xm X ordinate.
  40026. * odd Whether the Y ordinate is odd.
  40027. * ym Calculated Y ordinate.
  40028. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  40029. */
  40030. int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
  40031. {
  40032. #ifdef WOLFSSL_SP_SMALL_STACK
  40033. sp_digit* x = NULL;
  40034. #else
  40035. sp_digit x[4 * 8];
  40036. #endif
  40037. sp_digit* y = NULL;
  40038. int err = MP_OKAY;
  40039. #ifdef WOLFSSL_SP_SMALL_STACK
  40040. x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC);
  40041. if (x == NULL)
  40042. err = MEMORY_E;
  40043. #endif
  40044. if (err == MP_OKAY) {
  40045. y = x + 2 * 8;
  40046. sp_256_from_mp(x, 8, xm);
  40047. err = sp_256_mod_mul_norm_8(x, x, p256_mod);
  40048. }
  40049. if (err == MP_OKAY) {
  40050. /* y = x^3 */
  40051. {
  40052. sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod);
  40053. sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod);
  40054. }
  40055. /* y = x^3 - 3x */
  40056. sp_256_mont_sub_8(y, y, x, p256_mod);
  40057. sp_256_mont_sub_8(y, y, x, p256_mod);
  40058. sp_256_mont_sub_8(y, y, x, p256_mod);
  40059. /* y = x^3 - 3x + b */
  40060. err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod);
  40061. }
  40062. if (err == MP_OKAY) {
  40063. sp_256_mont_add_8(y, y, x, p256_mod);
  40064. /* y = sqrt(x^3 - 3x + b) */
  40065. err = sp_256_mont_sqrt_8(y);
  40066. }
  40067. if (err == MP_OKAY) {
  40068. XMEMSET(y + 8, 0, 8U * sizeof(sp_digit));
  40069. sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod);
  40070. if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
  40071. sp_256_mont_sub_8(y, p256_mod, y, p256_mod);
  40072. }
  40073. err = sp_256_to_mp(y, ym);
  40074. }
  40075. #ifdef WOLFSSL_SP_SMALL_STACK
  40076. if (x != NULL)
  40077. XFREE(x, NULL, DYNAMIC_TYPE_ECC);
  40078. #endif
  40079. return err;
  40080. }
  40081. #endif
  40082. #endif /* !WOLFSSL_SP_NO_256 */
  40083. #ifdef WOLFSSL_SP_384
  40084. /* Point structure to use. */
  40085. typedef struct sp_point_384 {
  40086. /* X ordinate of point. */
  40087. sp_digit x[2 * 12];
  40088. /* Y ordinate of point. */
  40089. sp_digit y[2 * 12];
  40090. /* Z ordinate of point. */
  40091. sp_digit z[2 * 12];
  40092. /* Indicates point is at infinity. */
  40093. int infinity;
  40094. } sp_point_384;
  40095. /* The modulus (prime) of the curve P384. */
  40096. static const sp_digit p384_mod[12] = {
  40097. 0xffffffff,0x00000000,0x00000000,0xffffffff,0xfffffffe,0xffffffff,
  40098. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
  40099. };
  40100. /* The Montgomery normalizer for modulus of the curve P384. */
  40101. static const sp_digit p384_norm_mod[12] = {
  40102. 0x00000001,0xffffffff,0xffffffff,0x00000000,0x00000001,0x00000000,
  40103. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
  40104. };
  40105. /* The Montgomery multiplier for modulus of the curve P384. */
  40106. static sp_digit p384_mp_mod = 0x00000001;
  40107. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  40108. defined(HAVE_ECC_VERIFY)
  40109. /* The order of the curve P384. */
  40110. static const sp_digit p384_order[12] = {
  40111. 0xccc52973,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81,
  40112. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
  40113. };
  40114. #endif
  40115. /* The order of the curve P384 minus 2. */
  40116. static const sp_digit p384_order2[12] = {
  40117. 0xccc52971,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81,
  40118. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
  40119. };
  40120. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  40121. /* The Montgomery normalizer for order of the curve P384. */
  40122. static const sp_digit p384_norm_order[12] = {
  40123. 0x333ad68d,0x1313e695,0xb74f5885,0xa7e5f24d,0x0bc8d220,0x389cb27e,
  40124. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
  40125. };
  40126. #endif
  40127. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  40128. /* The Montgomery multiplier for order of the curve P384. */
  40129. static sp_digit p384_mp_order = 0xe88fdc45;
  40130. #endif
  40131. /* The base point of curve P384. */
  40132. static const sp_point_384 p384_base = {
  40133. /* X ordinate */
  40134. {
  40135. 0x72760ab7,0x3a545e38,0xbf55296c,0x5502f25d,0x82542a38,0x59f741e0,
  40136. 0x8ba79b98,0x6e1d3b62,0xf320ad74,0x8eb1c71e,0xbe8b0537,0xaa87ca22,
  40137. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40138. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40139. (sp_digit)0, (sp_digit)0
  40140. },
  40141. /* Y ordinate */
  40142. {
  40143. 0x90ea0e5f,0x7a431d7c,0x1d7e819d,0x0a60b1ce,0xb5f0b8c0,0xe9da3113,
  40144. 0x289a147c,0xf8f41dbd,0x9292dc29,0x5d9e98bf,0x96262c6f,0x3617de4a,
  40145. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40146. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40147. (sp_digit)0, (sp_digit)0
  40148. },
  40149. /* Z ordinate */
  40150. {
  40151. 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  40152. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  40153. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40154. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40155. (sp_digit)0, (sp_digit)0
  40156. },
  40157. /* infinity */
  40158. 0
  40159. };
  40160. #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
  40161. static const sp_digit p384_b[12] = {
  40162. 0xd3ec2aef,0x2a85c8ed,0x8a2ed19d,0xc656398d,0x5013875a,0x0314088f,
  40163. 0xfe814112,0x181d9c6e,0xe3f82d19,0x988e056b,0xe23ee7e4,0xb3312fa7
  40164. };
  40165. #endif
  40166. #ifdef WOLFSSL_SP_SMALL
  40167. /* Multiply a and b into r. (r = a * b)
  40168. *
  40169. * r A single precision integer.
  40170. * a A single precision integer.
  40171. * b A single precision integer.
  40172. */
  40173. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  40174. static void sp_384_mul_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  40175. #else
  40176. static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  40177. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  40178. {
  40179. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  40180. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  40181. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  40182. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  40183. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  40184. __asm__ __volatile__ (
  40185. "SUB sp, sp, #0x60\n\t"
  40186. "LDR lr, [%[a]]\n\t"
  40187. "LDR r11, [%[b]]\n\t"
  40188. "UMULL r8, r6, lr, r11\n\t"
  40189. "STR r8, [sp]\n\t"
  40190. "MOV r7, #0x0\n\t"
  40191. "MOV r8, #0x0\n\t"
  40192. "MOV r5, #0x4\n\t"
  40193. "\n"
  40194. "L_sp_384_mul_12_outer:\n\t"
  40195. "SUBS r3, r5, #0x2c\n\t"
  40196. "IT cc\n\t"
  40197. "MOVCC r3, #0x0\n\t"
  40198. "SUB r4, r5, r3\n\t"
  40199. "\n"
  40200. "L_sp_384_mul_12_inner:\n\t"
  40201. "LDR lr, [%[a], r3]\n\t"
  40202. "LDR r11, [%[b], r4]\n\t"
  40203. "UMULL r9, r10, lr, r11\n\t"
  40204. "ADDS r6, r6, r9\n\t"
  40205. "ADCS r7, r7, r10\n\t"
  40206. "ADC r8, r8, #0x0\n\t"
  40207. "LDR lr, [%[a], r4]\n\t"
  40208. "LDR r11, [%[b], r3]\n\t"
  40209. "UMULL r9, r10, lr, r11\n\t"
  40210. "ADDS r6, r6, r9\n\t"
  40211. "ADCS r7, r7, r10\n\t"
  40212. "ADC r8, r8, #0x0\n\t"
  40213. "ADD r3, r3, #0x4\n\t"
  40214. "SUB r4, r4, #0x4\n\t"
  40215. "CMP r3, r4\n\t"
  40216. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  40217. "BGT L_sp_384_mul_12_inner_done\n\t"
  40218. #else
  40219. "BGT.N L_sp_384_mul_12_inner_done\n\t"
  40220. #endif
  40221. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  40222. "BLT L_sp_384_mul_12_inner\n\t"
  40223. #else
  40224. "BLT.N L_sp_384_mul_12_inner\n\t"
  40225. #endif
  40226. "LDR lr, [%[a], r3]\n\t"
  40227. "LDR r11, [%[b], r3]\n\t"
  40228. "UMULL r9, r10, lr, r11\n\t"
  40229. "ADDS r6, r6, r9\n\t"
  40230. "ADCS r7, r7, r10\n\t"
  40231. "ADC r8, r8, #0x0\n\t"
  40232. "\n"
  40233. "L_sp_384_mul_12_inner_done:\n\t"
  40234. "STR r6, [sp, r5]\n\t"
  40235. "MOV r6, r7\n\t"
  40236. "MOV r7, r8\n\t"
  40237. "MOV r8, #0x0\n\t"
  40238. "ADD r5, r5, #0x4\n\t"
  40239. "CMP r5, #0x54\n\t"
  40240. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  40241. "BLE L_sp_384_mul_12_outer\n\t"
  40242. #else
  40243. "BLE.N L_sp_384_mul_12_outer\n\t"
  40244. #endif
  40245. "LDR lr, [%[a], #44]\n\t"
  40246. "LDR r11, [%[b], #44]\n\t"
  40247. "UMLAL r6, r7, lr, r11\n\t"
  40248. "STR r6, [sp, r5]\n\t"
  40249. "ADD r5, r5, #0x4\n\t"
  40250. "STR r7, [sp, r5]\n\t"
  40251. "\n"
  40252. "L_sp_384_mul_12_store:\n\t"
  40253. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  40254. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  40255. "SUBS r5, r5, #0x20\n\t"
  40256. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  40257. "BGT L_sp_384_mul_12_store\n\t"
  40258. #else
  40259. "BGT.N L_sp_384_mul_12_store\n\t"
  40260. #endif
  40261. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  40262. :
  40263. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  40264. );
  40265. }
  40266. #else
  40267. /* Multiply a and b into r. (r = a * b)
  40268. *
  40269. * r A single precision integer.
  40270. * a A single precision integer.
  40271. * b A single precision integer.
  40272. */
  40273. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  40274. static void sp_384_mul_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  40275. #else
  40276. static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  40277. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  40278. {
  40279. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  40280. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  40281. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  40282. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  40283. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  40284. __asm__ __volatile__ (
  40285. "SUB sp, sp, #0x30\n\t"
  40286. /* A[0] * B[0] */
  40287. "LDR r11, [%[a]]\n\t"
  40288. "LDR r12, [%[b]]\n\t"
  40289. "UMULL r3, r4, r11, r12\n\t"
  40290. "MOV r5, #0x0\n\t"
  40291. "STR r3, [sp]\n\t"
  40292. /* A[0] * B[1] */
  40293. "LDR r9, [%[b], #4]\n\t"
  40294. "UMULL r6, r7, r11, r9\n\t"
  40295. "ADDS r4, r4, r6\n\t"
  40296. "ADCS r5, r5, r7\n\t"
  40297. "MOV r3, #0x0\n\t"
  40298. "ADC r3, r3, #0x0\n\t"
  40299. /* A[1] * B[0] */
  40300. "LDR r8, [%[a], #4]\n\t"
  40301. "UMULL r6, r7, r8, r12\n\t"
  40302. "ADDS r4, r4, r6\n\t"
  40303. "ADCS r5, r5, r7\n\t"
  40304. "ADC r3, r3, #0x0\n\t"
  40305. "STR r4, [sp, #4]\n\t"
  40306. /* A[2] * B[0] */
  40307. "LDR r8, [%[a], #8]\n\t"
  40308. "UMULL r6, r7, r8, r12\n\t"
  40309. "ADDS r5, r5, r6\n\t"
  40310. "ADCS r3, r3, r7\n\t"
  40311. "MOV r4, #0x0\n\t"
  40312. "ADC r4, r4, #0x0\n\t"
  40313. /* A[1] * B[1] */
  40314. "LDR r11, [%[a], #4]\n\t"
  40315. "LDR r12, [%[b], #4]\n\t"
  40316. "UMULL r6, r7, r11, r12\n\t"
  40317. "ADDS r5, r5, r6\n\t"
  40318. "ADCS r3, r3, r7\n\t"
  40319. "ADC r4, r4, #0x0\n\t"
  40320. /* A[0] * B[2] */
  40321. "LDR r8, [%[a]]\n\t"
  40322. "LDR r9, [%[b], #8]\n\t"
  40323. "UMULL r6, r7, r8, r9\n\t"
  40324. "ADDS r5, r5, r6\n\t"
  40325. "ADCS r3, r3, r7\n\t"
  40326. "ADC r4, r4, #0x0\n\t"
  40327. "STR r5, [sp, #8]\n\t"
  40328. /* A[0] * B[3] */
  40329. "LDR r9, [%[b], #12]\n\t"
  40330. "UMULL r6, r7, r8, r9\n\t"
  40331. "ADDS r3, r3, r6\n\t"
  40332. "ADCS r4, r4, r7\n\t"
  40333. "MOV r5, #0x0\n\t"
  40334. "ADC r5, r5, #0x0\n\t"
  40335. /* A[1] * B[2] */
  40336. "LDR r9, [%[b], #8]\n\t"
  40337. "UMULL r6, r7, r11, r9\n\t"
  40338. "ADDS r3, r3, r6\n\t"
  40339. "ADCS r4, r4, r7\n\t"
  40340. "ADC r5, r5, #0x0\n\t"
  40341. /* A[2] * B[1] */
  40342. "LDR r8, [%[a], #8]\n\t"
  40343. "UMULL r6, r7, r8, r12\n\t"
  40344. "ADDS r3, r3, r6\n\t"
  40345. "ADCS r4, r4, r7\n\t"
  40346. "ADC r5, r5, #0x0\n\t"
  40347. /* A[3] * B[0] */
  40348. "LDR r8, [%[a], #12]\n\t"
  40349. "LDR r9, [%[b]]\n\t"
  40350. "UMULL r6, r7, r8, r9\n\t"
  40351. "ADDS r3, r3, r6\n\t"
  40352. "ADCS r4, r4, r7\n\t"
  40353. "ADC r5, r5, #0x0\n\t"
  40354. "STR r3, [sp, #12]\n\t"
  40355. /* A[4] * B[0] */
  40356. "LDR r8, [%[a], #16]\n\t"
  40357. "UMULL r6, r7, r8, r9\n\t"
  40358. "ADDS r4, r4, r6\n\t"
  40359. "ADCS r5, r5, r7\n\t"
  40360. "MOV r3, #0x0\n\t"
  40361. "ADC r3, r3, #0x0\n\t"
  40362. /* A[3] * B[1] */
  40363. "LDR r8, [%[a], #12]\n\t"
  40364. "UMULL r6, r7, r8, r12\n\t"
  40365. "ADDS r4, r4, r6\n\t"
  40366. "ADCS r5, r5, r7\n\t"
  40367. "ADC r3, r3, #0x0\n\t"
  40368. /* A[2] * B[2] */
  40369. "LDR r11, [%[a], #8]\n\t"
  40370. "LDR r12, [%[b], #8]\n\t"
  40371. "UMULL r6, r7, r11, r12\n\t"
  40372. "ADDS r4, r4, r6\n\t"
  40373. "ADCS r5, r5, r7\n\t"
  40374. "ADC r3, r3, #0x0\n\t"
  40375. /* A[1] * B[3] */
  40376. "LDR r8, [%[a], #4]\n\t"
  40377. "LDR r9, [%[b], #12]\n\t"
  40378. "UMULL r6, r7, r8, r9\n\t"
  40379. "ADDS r4, r4, r6\n\t"
  40380. "ADCS r5, r5, r7\n\t"
  40381. "ADC r3, r3, #0x0\n\t"
  40382. /* A[0] * B[4] */
  40383. "LDR r8, [%[a]]\n\t"
  40384. "LDR r9, [%[b], #16]\n\t"
  40385. "UMULL r6, r7, r8, r9\n\t"
  40386. "ADDS r4, r4, r6\n\t"
  40387. "ADCS r5, r5, r7\n\t"
  40388. "ADC r3, r3, #0x0\n\t"
  40389. "STR r4, [sp, #16]\n\t"
  40390. /* A[0] * B[5] */
  40391. "LDR r9, [%[b], #20]\n\t"
  40392. "UMULL r6, r7, r8, r9\n\t"
  40393. "ADDS r5, r5, r6\n\t"
  40394. "ADCS r3, r3, r7\n\t"
  40395. "MOV r4, #0x0\n\t"
  40396. "ADC r4, r4, #0x0\n\t"
  40397. /* A[1] * B[4] */
  40398. "LDR r8, [%[a], #4]\n\t"
  40399. "LDR r9, [%[b], #16]\n\t"
  40400. "UMULL r6, r7, r8, r9\n\t"
  40401. "ADDS r5, r5, r6\n\t"
  40402. "ADCS r3, r3, r7\n\t"
  40403. "ADC r4, r4, #0x0\n\t"
  40404. /* A[2] * B[3] */
  40405. "LDR r9, [%[b], #12]\n\t"
  40406. "UMULL r6, r7, r11, r9\n\t"
  40407. "ADDS r5, r5, r6\n\t"
  40408. "ADCS r3, r3, r7\n\t"
  40409. "ADC r4, r4, #0x0\n\t"
  40410. /* A[3] * B[2] */
  40411. "LDR r8, [%[a], #12]\n\t"
  40412. "UMULL r6, r7, r8, r12\n\t"
  40413. "ADDS r5, r5, r6\n\t"
  40414. "ADCS r3, r3, r7\n\t"
  40415. "ADC r4, r4, #0x0\n\t"
  40416. /* A[4] * B[1] */
  40417. "LDR r8, [%[a], #16]\n\t"
  40418. "LDR r9, [%[b], #4]\n\t"
  40419. "UMULL r6, r7, r8, r9\n\t"
  40420. "ADDS r5, r5, r6\n\t"
  40421. "ADCS r3, r3, r7\n\t"
  40422. "ADC r4, r4, #0x0\n\t"
  40423. /* A[5] * B[0] */
  40424. "LDR r8, [%[a], #20]\n\t"
  40425. "LDR r9, [%[b]]\n\t"
  40426. "UMULL r6, r7, r8, r9\n\t"
  40427. "ADDS r5, r5, r6\n\t"
  40428. "ADCS r3, r3, r7\n\t"
  40429. "ADC r4, r4, #0x0\n\t"
  40430. "STR r5, [sp, #20]\n\t"
  40431. /* A[6] * B[0] */
  40432. "LDR r8, [%[a], #24]\n\t"
  40433. "UMULL r6, r7, r8, r9\n\t"
  40434. "ADDS r3, r3, r6\n\t"
  40435. "ADCS r4, r4, r7\n\t"
  40436. "MOV r5, #0x0\n\t"
  40437. "ADC r5, r5, #0x0\n\t"
  40438. /* A[5] * B[1] */
  40439. "LDR r8, [%[a], #20]\n\t"
  40440. "LDR r9, [%[b], #4]\n\t"
  40441. "UMULL r6, r7, r8, r9\n\t"
  40442. "ADDS r3, r3, r6\n\t"
  40443. "ADCS r4, r4, r7\n\t"
  40444. "ADC r5, r5, #0x0\n\t"
  40445. /* A[4] * B[2] */
  40446. "LDR r8, [%[a], #16]\n\t"
  40447. "UMULL r6, r7, r8, r12\n\t"
  40448. "ADDS r3, r3, r6\n\t"
  40449. "ADCS r4, r4, r7\n\t"
  40450. "ADC r5, r5, #0x0\n\t"
  40451. /* A[3] * B[3] */
  40452. "LDR r11, [%[a], #12]\n\t"
  40453. "LDR r12, [%[b], #12]\n\t"
  40454. "UMULL r6, r7, r11, r12\n\t"
  40455. "ADDS r3, r3, r6\n\t"
  40456. "ADCS r4, r4, r7\n\t"
  40457. "ADC r5, r5, #0x0\n\t"
  40458. /* A[2] * B[4] */
  40459. "LDR r8, [%[a], #8]\n\t"
  40460. "LDR r9, [%[b], #16]\n\t"
  40461. "UMULL r6, r7, r8, r9\n\t"
  40462. "ADDS r3, r3, r6\n\t"
  40463. "ADCS r4, r4, r7\n\t"
  40464. "ADC r5, r5, #0x0\n\t"
  40465. /* A[1] * B[5] */
  40466. "LDR r8, [%[a], #4]\n\t"
  40467. "LDR r9, [%[b], #20]\n\t"
  40468. "UMULL r6, r7, r8, r9\n\t"
  40469. "ADDS r3, r3, r6\n\t"
  40470. "ADCS r4, r4, r7\n\t"
  40471. "ADC r5, r5, #0x0\n\t"
  40472. /* A[0] * B[6] */
  40473. "LDR r8, [%[a]]\n\t"
  40474. "LDR r9, [%[b], #24]\n\t"
  40475. "UMULL r6, r7, r8, r9\n\t"
  40476. "ADDS r3, r3, r6\n\t"
  40477. "ADCS r4, r4, r7\n\t"
  40478. "ADC r5, r5, #0x0\n\t"
  40479. "STR r3, [sp, #24]\n\t"
  40480. /* A[0] * B[7] */
  40481. "LDR r9, [%[b], #28]\n\t"
  40482. "UMULL r6, r7, r8, r9\n\t"
  40483. "ADDS r4, r4, r6\n\t"
  40484. "ADCS r5, r5, r7\n\t"
  40485. "MOV r3, #0x0\n\t"
  40486. "ADC r3, r3, #0x0\n\t"
  40487. /* A[1] * B[6] */
  40488. "LDR r8, [%[a], #4]\n\t"
  40489. "LDR r9, [%[b], #24]\n\t"
  40490. "UMULL r6, r7, r8, r9\n\t"
  40491. "ADDS r4, r4, r6\n\t"
  40492. "ADCS r5, r5, r7\n\t"
  40493. "ADC r3, r3, #0x0\n\t"
  40494. /* A[2] * B[5] */
  40495. "LDR r8, [%[a], #8]\n\t"
  40496. "LDR r9, [%[b], #20]\n\t"
  40497. "UMULL r6, r7, r8, r9\n\t"
  40498. "ADDS r4, r4, r6\n\t"
  40499. "ADCS r5, r5, r7\n\t"
  40500. "ADC r3, r3, #0x0\n\t"
  40501. /* A[3] * B[4] */
  40502. "LDR r9, [%[b], #16]\n\t"
  40503. "UMULL r6, r7, r11, r9\n\t"
  40504. "ADDS r4, r4, r6\n\t"
  40505. "ADCS r5, r5, r7\n\t"
  40506. "ADC r3, r3, #0x0\n\t"
  40507. /* A[4] * B[3] */
  40508. "LDR r8, [%[a], #16]\n\t"
  40509. "UMULL r6, r7, r8, r12\n\t"
  40510. "ADDS r4, r4, r6\n\t"
  40511. "ADCS r5, r5, r7\n\t"
  40512. "ADC r3, r3, #0x0\n\t"
  40513. /* A[5] * B[2] */
  40514. "LDR r8, [%[a], #20]\n\t"
  40515. "LDR r9, [%[b], #8]\n\t"
  40516. "UMULL r6, r7, r8, r9\n\t"
  40517. "ADDS r4, r4, r6\n\t"
  40518. "ADCS r5, r5, r7\n\t"
  40519. "ADC r3, r3, #0x0\n\t"
  40520. /* A[6] * B[1] */
  40521. "LDR r8, [%[a], #24]\n\t"
  40522. "LDR r9, [%[b], #4]\n\t"
  40523. "UMULL r6, r7, r8, r9\n\t"
  40524. "ADDS r4, r4, r6\n\t"
  40525. "ADCS r5, r5, r7\n\t"
  40526. "ADC r3, r3, #0x0\n\t"
  40527. /* A[7] * B[0] */
  40528. "LDR r8, [%[a], #28]\n\t"
  40529. "LDR r9, [%[b]]\n\t"
  40530. "UMULL r6, r7, r8, r9\n\t"
  40531. "ADDS r4, r4, r6\n\t"
  40532. "ADCS r5, r5, r7\n\t"
  40533. "ADC r3, r3, #0x0\n\t"
  40534. "STR r4, [sp, #28]\n\t"
  40535. /* A[8] * B[0] */
  40536. "LDR r8, [%[a], #32]\n\t"
  40537. "UMULL r6, r7, r8, r9\n\t"
  40538. "ADDS r5, r5, r6\n\t"
  40539. "ADCS r3, r3, r7\n\t"
  40540. "MOV r4, #0x0\n\t"
  40541. "ADC r4, r4, #0x0\n\t"
  40542. /* A[7] * B[1] */
  40543. "LDR r8, [%[a], #28]\n\t"
  40544. "LDR r9, [%[b], #4]\n\t"
  40545. "UMULL r6, r7, r8, r9\n\t"
  40546. "ADDS r5, r5, r6\n\t"
  40547. "ADCS r3, r3, r7\n\t"
  40548. "ADC r4, r4, #0x0\n\t"
  40549. /* A[6] * B[2] */
  40550. "LDR r8, [%[a], #24]\n\t"
  40551. "LDR r9, [%[b], #8]\n\t"
  40552. "UMULL r6, r7, r8, r9\n\t"
  40553. "ADDS r5, r5, r6\n\t"
  40554. "ADCS r3, r3, r7\n\t"
  40555. "ADC r4, r4, #0x0\n\t"
  40556. /* A[5] * B[3] */
  40557. "LDR r8, [%[a], #20]\n\t"
  40558. "UMULL r6, r7, r8, r12\n\t"
  40559. "ADDS r5, r5, r6\n\t"
  40560. "ADCS r3, r3, r7\n\t"
  40561. "ADC r4, r4, #0x0\n\t"
  40562. /* A[4] * B[4] */
  40563. "LDR r11, [%[a], #16]\n\t"
  40564. "LDR r12, [%[b], #16]\n\t"
  40565. "UMULL r6, r7, r11, r12\n\t"
  40566. "ADDS r5, r5, r6\n\t"
  40567. "ADCS r3, r3, r7\n\t"
  40568. "ADC r4, r4, #0x0\n\t"
  40569. /* A[3] * B[5] */
  40570. "LDR r8, [%[a], #12]\n\t"
  40571. "LDR r9, [%[b], #20]\n\t"
  40572. "UMULL r6, r7, r8, r9\n\t"
  40573. "ADDS r5, r5, r6\n\t"
  40574. "ADCS r3, r3, r7\n\t"
  40575. "ADC r4, r4, #0x0\n\t"
  40576. /* A[2] * B[6] */
  40577. "LDR r8, [%[a], #8]\n\t"
  40578. "LDR r9, [%[b], #24]\n\t"
  40579. "UMULL r6, r7, r8, r9\n\t"
  40580. "ADDS r5, r5, r6\n\t"
  40581. "ADCS r3, r3, r7\n\t"
  40582. "ADC r4, r4, #0x0\n\t"
  40583. /* A[1] * B[7] */
  40584. "LDR r8, [%[a], #4]\n\t"
  40585. "LDR r9, [%[b], #28]\n\t"
  40586. "UMULL r6, r7, r8, r9\n\t"
  40587. "ADDS r5, r5, r6\n\t"
  40588. "ADCS r3, r3, r7\n\t"
  40589. "ADC r4, r4, #0x0\n\t"
  40590. /* A[0] * B[8] */
  40591. "LDR r8, [%[a]]\n\t"
  40592. "LDR r9, [%[b], #32]\n\t"
  40593. "UMULL r6, r7, r8, r9\n\t"
  40594. "ADDS r5, r5, r6\n\t"
  40595. "ADCS r3, r3, r7\n\t"
  40596. "ADC r4, r4, #0x0\n\t"
  40597. "STR r5, [sp, #32]\n\t"
  40598. /* A[0] * B[9] */
  40599. "LDR r9, [%[b], #36]\n\t"
  40600. "UMULL r6, r7, r8, r9\n\t"
  40601. "ADDS r3, r3, r6\n\t"
  40602. "ADCS r4, r4, r7\n\t"
  40603. "MOV r5, #0x0\n\t"
  40604. "ADC r5, r5, #0x0\n\t"
  40605. /* A[1] * B[8] */
  40606. "LDR r8, [%[a], #4]\n\t"
  40607. "LDR r9, [%[b], #32]\n\t"
  40608. "UMULL r6, r7, r8, r9\n\t"
  40609. "ADDS r3, r3, r6\n\t"
  40610. "ADCS r4, r4, r7\n\t"
  40611. "ADC r5, r5, #0x0\n\t"
  40612. /* A[2] * B[7] */
  40613. "LDR r8, [%[a], #8]\n\t"
  40614. "LDR r9, [%[b], #28]\n\t"
  40615. "UMULL r6, r7, r8, r9\n\t"
  40616. "ADDS r3, r3, r6\n\t"
  40617. "ADCS r4, r4, r7\n\t"
  40618. "ADC r5, r5, #0x0\n\t"
  40619. /* A[3] * B[6] */
  40620. "LDR r8, [%[a], #12]\n\t"
  40621. "LDR r9, [%[b], #24]\n\t"
  40622. "UMULL r6, r7, r8, r9\n\t"
  40623. "ADDS r3, r3, r6\n\t"
  40624. "ADCS r4, r4, r7\n\t"
  40625. "ADC r5, r5, #0x0\n\t"
  40626. /* A[4] * B[5] */
  40627. "LDR r9, [%[b], #20]\n\t"
  40628. "UMULL r6, r7, r11, r9\n\t"
  40629. "ADDS r3, r3, r6\n\t"
  40630. "ADCS r4, r4, r7\n\t"
  40631. "ADC r5, r5, #0x0\n\t"
  40632. /* A[5] * B[4] */
  40633. "LDR r8, [%[a], #20]\n\t"
  40634. "UMULL r6, r7, r8, r12\n\t"
  40635. "ADDS r3, r3, r6\n\t"
  40636. "ADCS r4, r4, r7\n\t"
  40637. "ADC r5, r5, #0x0\n\t"
  40638. /* A[6] * B[3] */
  40639. "LDR r8, [%[a], #24]\n\t"
  40640. "LDR r9, [%[b], #12]\n\t"
  40641. "UMULL r6, r7, r8, r9\n\t"
  40642. "ADDS r3, r3, r6\n\t"
  40643. "ADCS r4, r4, r7\n\t"
  40644. "ADC r5, r5, #0x0\n\t"
  40645. /* A[7] * B[2] */
  40646. "LDR r8, [%[a], #28]\n\t"
  40647. "LDR r9, [%[b], #8]\n\t"
  40648. "UMULL r6, r7, r8, r9\n\t"
  40649. "ADDS r3, r3, r6\n\t"
  40650. "ADCS r4, r4, r7\n\t"
  40651. "ADC r5, r5, #0x0\n\t"
  40652. /* A[8] * B[1] */
  40653. "LDR r8, [%[a], #32]\n\t"
  40654. "LDR r9, [%[b], #4]\n\t"
  40655. "UMULL r6, r7, r8, r9\n\t"
  40656. "ADDS r3, r3, r6\n\t"
  40657. "ADCS r4, r4, r7\n\t"
  40658. "ADC r5, r5, #0x0\n\t"
  40659. /* A[9] * B[0] */
  40660. "LDR r8, [%[a], #36]\n\t"
  40661. "LDR r9, [%[b]]\n\t"
  40662. "UMULL r6, r7, r8, r9\n\t"
  40663. "ADDS r3, r3, r6\n\t"
  40664. "ADCS r4, r4, r7\n\t"
  40665. "ADC r5, r5, #0x0\n\t"
  40666. "STR r3, [sp, #36]\n\t"
  40667. /* A[10] * B[0] */
  40668. "LDR r8, [%[a], #40]\n\t"
  40669. "UMULL r6, r7, r8, r9\n\t"
  40670. "ADDS r4, r4, r6\n\t"
  40671. "ADCS r5, r5, r7\n\t"
  40672. "MOV r3, #0x0\n\t"
  40673. "ADC r3, r3, #0x0\n\t"
  40674. /* A[9] * B[1] */
  40675. "LDR r8, [%[a], #36]\n\t"
  40676. "LDR r9, [%[b], #4]\n\t"
  40677. "UMULL r6, r7, r8, r9\n\t"
  40678. "ADDS r4, r4, r6\n\t"
  40679. "ADCS r5, r5, r7\n\t"
  40680. "ADC r3, r3, #0x0\n\t"
  40681. /* A[8] * B[2] */
  40682. "LDR r8, [%[a], #32]\n\t"
  40683. "LDR r9, [%[b], #8]\n\t"
  40684. "UMULL r6, r7, r8, r9\n\t"
  40685. "ADDS r4, r4, r6\n\t"
  40686. "ADCS r5, r5, r7\n\t"
  40687. "ADC r3, r3, #0x0\n\t"
  40688. /* A[7] * B[3] */
  40689. "LDR r8, [%[a], #28]\n\t"
  40690. "LDR r9, [%[b], #12]\n\t"
  40691. "UMULL r6, r7, r8, r9\n\t"
  40692. "ADDS r4, r4, r6\n\t"
  40693. "ADCS r5, r5, r7\n\t"
  40694. "ADC r3, r3, #0x0\n\t"
  40695. /* A[6] * B[4] */
  40696. "LDR r8, [%[a], #24]\n\t"
  40697. "UMULL r6, r7, r8, r12\n\t"
  40698. "ADDS r4, r4, r6\n\t"
  40699. "ADCS r5, r5, r7\n\t"
  40700. "ADC r3, r3, #0x0\n\t"
  40701. /* A[5] * B[5] */
  40702. "LDR r11, [%[a], #20]\n\t"
  40703. "LDR r12, [%[b], #20]\n\t"
  40704. "UMULL r6, r7, r11, r12\n\t"
  40705. "ADDS r4, r4, r6\n\t"
  40706. "ADCS r5, r5, r7\n\t"
  40707. "ADC r3, r3, #0x0\n\t"
  40708. /* A[4] * B[6] */
  40709. "LDR r8, [%[a], #16]\n\t"
  40710. "LDR r9, [%[b], #24]\n\t"
  40711. "UMULL r6, r7, r8, r9\n\t"
  40712. "ADDS r4, r4, r6\n\t"
  40713. "ADCS r5, r5, r7\n\t"
  40714. "ADC r3, r3, #0x0\n\t"
  40715. /* A[3] * B[7] */
  40716. "LDR r8, [%[a], #12]\n\t"
  40717. "LDR r9, [%[b], #28]\n\t"
  40718. "UMULL r6, r7, r8, r9\n\t"
  40719. "ADDS r4, r4, r6\n\t"
  40720. "ADCS r5, r5, r7\n\t"
  40721. "ADC r3, r3, #0x0\n\t"
  40722. /* A[2] * B[8] */
  40723. "LDR r8, [%[a], #8]\n\t"
  40724. "LDR r9, [%[b], #32]\n\t"
  40725. "UMULL r6, r7, r8, r9\n\t"
  40726. "ADDS r4, r4, r6\n\t"
  40727. "ADCS r5, r5, r7\n\t"
  40728. "ADC r3, r3, #0x0\n\t"
  40729. /* A[1] * B[9] */
  40730. "LDR r8, [%[a], #4]\n\t"
  40731. "LDR r9, [%[b], #36]\n\t"
  40732. "UMULL r6, r7, r8, r9\n\t"
  40733. "ADDS r4, r4, r6\n\t"
  40734. "ADCS r5, r5, r7\n\t"
  40735. "ADC r3, r3, #0x0\n\t"
  40736. /* A[0] * B[10] */
  40737. "LDR r8, [%[a]]\n\t"
  40738. "LDR r9, [%[b], #40]\n\t"
  40739. "UMULL r6, r7, r8, r9\n\t"
  40740. "ADDS r4, r4, r6\n\t"
  40741. "ADCS r5, r5, r7\n\t"
  40742. "ADC r3, r3, #0x0\n\t"
  40743. "STR r4, [sp, #40]\n\t"
  40744. /* A[0] * B[11] */
  40745. "LDR r9, [%[b], #44]\n\t"
  40746. "UMULL r6, r7, r8, r9\n\t"
  40747. "ADDS r5, r5, r6\n\t"
  40748. "ADCS r3, r3, r7\n\t"
  40749. "MOV r4, #0x0\n\t"
  40750. "ADC r4, r4, #0x0\n\t"
  40751. /* A[1] * B[10] */
  40752. "LDR r8, [%[a], #4]\n\t"
  40753. "LDR r9, [%[b], #40]\n\t"
  40754. "UMULL r6, r7, r8, r9\n\t"
  40755. "ADDS r5, r5, r6\n\t"
  40756. "ADCS r3, r3, r7\n\t"
  40757. "ADC r4, r4, #0x0\n\t"
  40758. /* A[2] * B[9] */
  40759. "LDR r8, [%[a], #8]\n\t"
  40760. "LDR r9, [%[b], #36]\n\t"
  40761. "UMULL r6, r7, r8, r9\n\t"
  40762. "ADDS r5, r5, r6\n\t"
  40763. "ADCS r3, r3, r7\n\t"
  40764. "ADC r4, r4, #0x0\n\t"
  40765. /* A[3] * B[8] */
  40766. "LDR r8, [%[a], #12]\n\t"
  40767. "LDR r9, [%[b], #32]\n\t"
  40768. "UMULL r6, r7, r8, r9\n\t"
  40769. "ADDS r5, r5, r6\n\t"
  40770. "ADCS r3, r3, r7\n\t"
  40771. "ADC r4, r4, #0x0\n\t"
  40772. /* A[4] * B[7] */
  40773. "LDR r8, [%[a], #16]\n\t"
  40774. "LDR r9, [%[b], #28]\n\t"
  40775. "UMULL r6, r7, r8, r9\n\t"
  40776. "ADDS r5, r5, r6\n\t"
  40777. "ADCS r3, r3, r7\n\t"
  40778. "ADC r4, r4, #0x0\n\t"
  40779. /* A[5] * B[6] */
  40780. "LDR r9, [%[b], #24]\n\t"
  40781. "UMULL r6, r7, r11, r9\n\t"
  40782. "ADDS r5, r5, r6\n\t"
  40783. "ADCS r3, r3, r7\n\t"
  40784. "ADC r4, r4, #0x0\n\t"
  40785. /* A[6] * B[5] */
  40786. "LDR r8, [%[a], #24]\n\t"
  40787. "UMULL r6, r7, r8, r12\n\t"
  40788. "ADDS r5, r5, r6\n\t"
  40789. "ADCS r3, r3, r7\n\t"
  40790. "ADC r4, r4, #0x0\n\t"
  40791. /* A[7] * B[4] */
  40792. "LDR r8, [%[a], #28]\n\t"
  40793. "LDR r9, [%[b], #16]\n\t"
  40794. "UMULL r6, r7, r8, r9\n\t"
  40795. "ADDS r5, r5, r6\n\t"
  40796. "ADCS r3, r3, r7\n\t"
  40797. "ADC r4, r4, #0x0\n\t"
  40798. /* A[8] * B[3] */
  40799. "LDR r8, [%[a], #32]\n\t"
  40800. "LDR r9, [%[b], #12]\n\t"
  40801. "UMULL r6, r7, r8, r9\n\t"
  40802. "ADDS r5, r5, r6\n\t"
  40803. "ADCS r3, r3, r7\n\t"
  40804. "ADC r4, r4, #0x0\n\t"
  40805. /* A[9] * B[2] */
  40806. "LDR r8, [%[a], #36]\n\t"
  40807. "LDR r9, [%[b], #8]\n\t"
  40808. "UMULL r6, r7, r8, r9\n\t"
  40809. "ADDS r5, r5, r6\n\t"
  40810. "ADCS r3, r3, r7\n\t"
  40811. "ADC r4, r4, #0x0\n\t"
  40812. /* A[10] * B[1] */
  40813. "LDR r8, [%[a], #40]\n\t"
  40814. "LDR r9, [%[b], #4]\n\t"
  40815. "UMULL r6, r7, r8, r9\n\t"
  40816. "ADDS r5, r5, r6\n\t"
  40817. "ADCS r3, r3, r7\n\t"
  40818. "ADC r4, r4, #0x0\n\t"
  40819. /* A[11] * B[0] */
  40820. "LDR r8, [%[a], #44]\n\t"
  40821. "LDR r9, [%[b]]\n\t"
  40822. "UMULL r6, r7, r8, r9\n\t"
  40823. "ADDS r5, r5, r6\n\t"
  40824. "ADCS r3, r3, r7\n\t"
  40825. "ADC r4, r4, #0x0\n\t"
  40826. "STR r5, [sp, #44]\n\t"
  40827. /* A[11] * B[1] */
  40828. "LDR r9, [%[b], #4]\n\t"
  40829. "UMULL r6, r7, r8, r9\n\t"
  40830. "ADDS r3, r3, r6\n\t"
  40831. "ADCS r4, r4, r7\n\t"
  40832. "MOV r5, #0x0\n\t"
  40833. "ADC r5, r5, #0x0\n\t"
  40834. /* A[10] * B[2] */
  40835. "LDR r8, [%[a], #40]\n\t"
  40836. "LDR r9, [%[b], #8]\n\t"
  40837. "UMULL r6, r7, r8, r9\n\t"
  40838. "ADDS r3, r3, r6\n\t"
  40839. "ADCS r4, r4, r7\n\t"
  40840. "ADC r5, r5, #0x0\n\t"
  40841. /* A[9] * B[3] */
  40842. "LDR r8, [%[a], #36]\n\t"
  40843. "LDR r9, [%[b], #12]\n\t"
  40844. "UMULL r6, r7, r8, r9\n\t"
  40845. "ADDS r3, r3, r6\n\t"
  40846. "ADCS r4, r4, r7\n\t"
  40847. "ADC r5, r5, #0x0\n\t"
  40848. /* A[8] * B[4] */
  40849. "LDR r8, [%[a], #32]\n\t"
  40850. "LDR r9, [%[b], #16]\n\t"
  40851. "UMULL r6, r7, r8, r9\n\t"
  40852. "ADDS r3, r3, r6\n\t"
  40853. "ADCS r4, r4, r7\n\t"
  40854. "ADC r5, r5, #0x0\n\t"
  40855. /* A[7] * B[5] */
  40856. "LDR r8, [%[a], #28]\n\t"
  40857. "UMULL r6, r7, r8, r12\n\t"
  40858. "ADDS r3, r3, r6\n\t"
  40859. "ADCS r4, r4, r7\n\t"
  40860. "ADC r5, r5, #0x0\n\t"
  40861. /* A[6] * B[6] */
  40862. "LDR r11, [%[a], #24]\n\t"
  40863. "LDR r12, [%[b], #24]\n\t"
  40864. "UMULL r6, r7, r11, r12\n\t"
  40865. "ADDS r3, r3, r6\n\t"
  40866. "ADCS r4, r4, r7\n\t"
  40867. "ADC r5, r5, #0x0\n\t"
  40868. /* A[5] * B[7] */
  40869. "LDR r8, [%[a], #20]\n\t"
  40870. "LDR r9, [%[b], #28]\n\t"
  40871. "UMULL r6, r7, r8, r9\n\t"
  40872. "ADDS r3, r3, r6\n\t"
  40873. "ADCS r4, r4, r7\n\t"
  40874. "ADC r5, r5, #0x0\n\t"
  40875. /* A[4] * B[8] */
  40876. "LDR r8, [%[a], #16]\n\t"
  40877. "LDR r9, [%[b], #32]\n\t"
  40878. "UMULL r6, r7, r8, r9\n\t"
  40879. "ADDS r3, r3, r6\n\t"
  40880. "ADCS r4, r4, r7\n\t"
  40881. "ADC r5, r5, #0x0\n\t"
  40882. /* A[3] * B[9] */
  40883. "LDR r8, [%[a], #12]\n\t"
  40884. "LDR r9, [%[b], #36]\n\t"
  40885. "UMULL r6, r7, r8, r9\n\t"
  40886. "ADDS r3, r3, r6\n\t"
  40887. "ADCS r4, r4, r7\n\t"
  40888. "ADC r5, r5, #0x0\n\t"
  40889. /* A[2] * B[10] */
  40890. "LDR r8, [%[a], #8]\n\t"
  40891. "LDR r9, [%[b], #40]\n\t"
  40892. "UMULL r6, r7, r8, r9\n\t"
  40893. "ADDS r3, r3, r6\n\t"
  40894. "ADCS r4, r4, r7\n\t"
  40895. "ADC r5, r5, #0x0\n\t"
  40896. /* A[1] * B[11] */
  40897. "LDR r8, [%[a], #4]\n\t"
  40898. "LDR r9, [%[b], #44]\n\t"
  40899. "UMULL r6, r7, r8, r9\n\t"
  40900. "ADDS r3, r3, r6\n\t"
  40901. "ADCS r4, r4, r7\n\t"
  40902. "ADC r5, r5, #0x0\n\t"
  40903. "STR r3, [%[r], #48]\n\t"
  40904. /* A[2] * B[11] */
  40905. "LDR r8, [%[a], #8]\n\t"
  40906. "UMULL r6, r7, r8, r9\n\t"
  40907. "ADDS r4, r4, r6\n\t"
  40908. "ADCS r5, r5, r7\n\t"
  40909. "MOV r3, #0x0\n\t"
  40910. "ADC r3, r3, #0x0\n\t"
  40911. /* A[3] * B[10] */
  40912. "LDR r8, [%[a], #12]\n\t"
  40913. "LDR r9, [%[b], #40]\n\t"
  40914. "UMULL r6, r7, r8, r9\n\t"
  40915. "ADDS r4, r4, r6\n\t"
  40916. "ADCS r5, r5, r7\n\t"
  40917. "ADC r3, r3, #0x0\n\t"
  40918. /* A[4] * B[9] */
  40919. "LDR r8, [%[a], #16]\n\t"
  40920. "LDR r9, [%[b], #36]\n\t"
  40921. "UMULL r6, r7, r8, r9\n\t"
  40922. "ADDS r4, r4, r6\n\t"
  40923. "ADCS r5, r5, r7\n\t"
  40924. "ADC r3, r3, #0x0\n\t"
  40925. /* A[5] * B[8] */
  40926. "LDR r8, [%[a], #20]\n\t"
  40927. "LDR r9, [%[b], #32]\n\t"
  40928. "UMULL r6, r7, r8, r9\n\t"
  40929. "ADDS r4, r4, r6\n\t"
  40930. "ADCS r5, r5, r7\n\t"
  40931. "ADC r3, r3, #0x0\n\t"
  40932. /* A[6] * B[7] */
  40933. "LDR r9, [%[b], #28]\n\t"
  40934. "UMULL r6, r7, r11, r9\n\t"
  40935. "ADDS r4, r4, r6\n\t"
  40936. "ADCS r5, r5, r7\n\t"
  40937. "ADC r3, r3, #0x0\n\t"
  40938. /* A[7] * B[6] */
  40939. "LDR r8, [%[a], #28]\n\t"
  40940. "UMULL r6, r7, r8, r12\n\t"
  40941. "ADDS r4, r4, r6\n\t"
  40942. "ADCS r5, r5, r7\n\t"
  40943. "ADC r3, r3, #0x0\n\t"
  40944. /* A[8] * B[5] */
  40945. "LDR r8, [%[a], #32]\n\t"
  40946. "LDR r9, [%[b], #20]\n\t"
  40947. "UMULL r6, r7, r8, r9\n\t"
  40948. "ADDS r4, r4, r6\n\t"
  40949. "ADCS r5, r5, r7\n\t"
  40950. "ADC r3, r3, #0x0\n\t"
  40951. /* A[9] * B[4] */
  40952. "LDR r8, [%[a], #36]\n\t"
  40953. "LDR r9, [%[b], #16]\n\t"
  40954. "UMULL r6, r7, r8, r9\n\t"
  40955. "ADDS r4, r4, r6\n\t"
  40956. "ADCS r5, r5, r7\n\t"
  40957. "ADC r3, r3, #0x0\n\t"
  40958. /* A[10] * B[3] */
  40959. "LDR r8, [%[a], #40]\n\t"
  40960. "LDR r9, [%[b], #12]\n\t"
  40961. "UMULL r6, r7, r8, r9\n\t"
  40962. "ADDS r4, r4, r6\n\t"
  40963. "ADCS r5, r5, r7\n\t"
  40964. "ADC r3, r3, #0x0\n\t"
  40965. /* A[11] * B[2] */
  40966. "LDR r8, [%[a], #44]\n\t"
  40967. "LDR r9, [%[b], #8]\n\t"
  40968. "UMULL r6, r7, r8, r9\n\t"
  40969. "ADDS r4, r4, r6\n\t"
  40970. "ADCS r5, r5, r7\n\t"
  40971. "ADC r3, r3, #0x0\n\t"
  40972. "STR r4, [%[r], #52]\n\t"
  40973. /* A[11] * B[3] */
  40974. "LDR r9, [%[b], #12]\n\t"
  40975. "UMULL r6, r7, r8, r9\n\t"
  40976. "ADDS r5, r5, r6\n\t"
  40977. "ADCS r3, r3, r7\n\t"
  40978. "MOV r4, #0x0\n\t"
  40979. "ADC r4, r4, #0x0\n\t"
  40980. /* A[10] * B[4] */
  40981. "LDR r8, [%[a], #40]\n\t"
  40982. "LDR r9, [%[b], #16]\n\t"
  40983. "UMULL r6, r7, r8, r9\n\t"
  40984. "ADDS r5, r5, r6\n\t"
  40985. "ADCS r3, r3, r7\n\t"
  40986. "ADC r4, r4, #0x0\n\t"
  40987. /* A[9] * B[5] */
  40988. "LDR r8, [%[a], #36]\n\t"
  40989. "LDR r9, [%[b], #20]\n\t"
  40990. "UMULL r6, r7, r8, r9\n\t"
  40991. "ADDS r5, r5, r6\n\t"
  40992. "ADCS r3, r3, r7\n\t"
  40993. "ADC r4, r4, #0x0\n\t"
  40994. /* A[8] * B[6] */
  40995. "LDR r8, [%[a], #32]\n\t"
  40996. "UMULL r6, r7, r8, r12\n\t"
  40997. "ADDS r5, r5, r6\n\t"
  40998. "ADCS r3, r3, r7\n\t"
  40999. "ADC r4, r4, #0x0\n\t"
  41000. /* A[7] * B[7] */
  41001. "LDR r11, [%[a], #28]\n\t"
  41002. "LDR r12, [%[b], #28]\n\t"
  41003. "UMULL r6, r7, r11, r12\n\t"
  41004. "ADDS r5, r5, r6\n\t"
  41005. "ADCS r3, r3, r7\n\t"
  41006. "ADC r4, r4, #0x0\n\t"
  41007. /* A[6] * B[8] */
  41008. "LDR r8, [%[a], #24]\n\t"
  41009. "LDR r9, [%[b], #32]\n\t"
  41010. "UMULL r6, r7, r8, r9\n\t"
  41011. "ADDS r5, r5, r6\n\t"
  41012. "ADCS r3, r3, r7\n\t"
  41013. "ADC r4, r4, #0x0\n\t"
  41014. /* A[5] * B[9] */
  41015. "LDR r8, [%[a], #20]\n\t"
  41016. "LDR r9, [%[b], #36]\n\t"
  41017. "UMULL r6, r7, r8, r9\n\t"
  41018. "ADDS r5, r5, r6\n\t"
  41019. "ADCS r3, r3, r7\n\t"
  41020. "ADC r4, r4, #0x0\n\t"
  41021. /* A[4] * B[10] */
  41022. "LDR r8, [%[a], #16]\n\t"
  41023. "LDR r9, [%[b], #40]\n\t"
  41024. "UMULL r6, r7, r8, r9\n\t"
  41025. "ADDS r5, r5, r6\n\t"
  41026. "ADCS r3, r3, r7\n\t"
  41027. "ADC r4, r4, #0x0\n\t"
  41028. /* A[3] * B[11] */
  41029. "LDR r8, [%[a], #12]\n\t"
  41030. "LDR r9, [%[b], #44]\n\t"
  41031. "UMULL r6, r7, r8, r9\n\t"
  41032. "ADDS r5, r5, r6\n\t"
  41033. "ADCS r3, r3, r7\n\t"
  41034. "ADC r4, r4, #0x0\n\t"
  41035. "STR r5, [%[r], #56]\n\t"
  41036. /* A[4] * B[11] */
  41037. "LDR r8, [%[a], #16]\n\t"
  41038. "UMULL r6, r7, r8, r9\n\t"
  41039. "ADDS r3, r3, r6\n\t"
  41040. "ADCS r4, r4, r7\n\t"
  41041. "MOV r5, #0x0\n\t"
  41042. "ADC r5, r5, #0x0\n\t"
  41043. /* A[5] * B[10] */
  41044. "LDR r8, [%[a], #20]\n\t"
  41045. "LDR r9, [%[b], #40]\n\t"
  41046. "UMULL r6, r7, r8, r9\n\t"
  41047. "ADDS r3, r3, r6\n\t"
  41048. "ADCS r4, r4, r7\n\t"
  41049. "ADC r5, r5, #0x0\n\t"
  41050. /* A[6] * B[9] */
  41051. "LDR r8, [%[a], #24]\n\t"
  41052. "LDR r9, [%[b], #36]\n\t"
  41053. "UMULL r6, r7, r8, r9\n\t"
  41054. "ADDS r3, r3, r6\n\t"
  41055. "ADCS r4, r4, r7\n\t"
  41056. "ADC r5, r5, #0x0\n\t"
  41057. /* A[7] * B[8] */
  41058. "LDR r9, [%[b], #32]\n\t"
  41059. "UMULL r6, r7, r11, r9\n\t"
  41060. "ADDS r3, r3, r6\n\t"
  41061. "ADCS r4, r4, r7\n\t"
  41062. "ADC r5, r5, #0x0\n\t"
  41063. /* A[8] * B[7] */
  41064. "LDR r8, [%[a], #32]\n\t"
  41065. "UMULL r6, r7, r8, r12\n\t"
  41066. "ADDS r3, r3, r6\n\t"
  41067. "ADCS r4, r4, r7\n\t"
  41068. "ADC r5, r5, #0x0\n\t"
  41069. /* A[9] * B[6] */
  41070. "LDR r8, [%[a], #36]\n\t"
  41071. "LDR r9, [%[b], #24]\n\t"
  41072. "UMULL r6, r7, r8, r9\n\t"
  41073. "ADDS r3, r3, r6\n\t"
  41074. "ADCS r4, r4, r7\n\t"
  41075. "ADC r5, r5, #0x0\n\t"
  41076. /* A[10] * B[5] */
  41077. "LDR r8, [%[a], #40]\n\t"
  41078. "LDR r9, [%[b], #20]\n\t"
  41079. "UMULL r6, r7, r8, r9\n\t"
  41080. "ADDS r3, r3, r6\n\t"
  41081. "ADCS r4, r4, r7\n\t"
  41082. "ADC r5, r5, #0x0\n\t"
  41083. /* A[11] * B[4] */
  41084. "LDR r8, [%[a], #44]\n\t"
  41085. "LDR r9, [%[b], #16]\n\t"
  41086. "UMULL r6, r7, r8, r9\n\t"
  41087. "ADDS r3, r3, r6\n\t"
  41088. "ADCS r4, r4, r7\n\t"
  41089. "ADC r5, r5, #0x0\n\t"
  41090. "STR r3, [%[r], #60]\n\t"
  41091. /* A[11] * B[5] */
  41092. "LDR r9, [%[b], #20]\n\t"
  41093. "UMULL r6, r7, r8, r9\n\t"
  41094. "ADDS r4, r4, r6\n\t"
  41095. "ADCS r5, r5, r7\n\t"
  41096. "MOV r3, #0x0\n\t"
  41097. "ADC r3, r3, #0x0\n\t"
  41098. /* A[10] * B[6] */
  41099. "LDR r8, [%[a], #40]\n\t"
  41100. "LDR r9, [%[b], #24]\n\t"
  41101. "UMULL r6, r7, r8, r9\n\t"
  41102. "ADDS r4, r4, r6\n\t"
  41103. "ADCS r5, r5, r7\n\t"
  41104. "ADC r3, r3, #0x0\n\t"
  41105. /* A[9] * B[7] */
  41106. "LDR r8, [%[a], #36]\n\t"
  41107. "UMULL r6, r7, r8, r12\n\t"
  41108. "ADDS r4, r4, r6\n\t"
  41109. "ADCS r5, r5, r7\n\t"
  41110. "ADC r3, r3, #0x0\n\t"
  41111. /* A[8] * B[8] */
  41112. "LDR r11, [%[a], #32]\n\t"
  41113. "LDR r12, [%[b], #32]\n\t"
  41114. "UMULL r6, r7, r11, r12\n\t"
  41115. "ADDS r4, r4, r6\n\t"
  41116. "ADCS r5, r5, r7\n\t"
  41117. "ADC r3, r3, #0x0\n\t"
  41118. /* A[7] * B[9] */
  41119. "LDR r8, [%[a], #28]\n\t"
  41120. "LDR r9, [%[b], #36]\n\t"
  41121. "UMULL r6, r7, r8, r9\n\t"
  41122. "ADDS r4, r4, r6\n\t"
  41123. "ADCS r5, r5, r7\n\t"
  41124. "ADC r3, r3, #0x0\n\t"
  41125. /* A[6] * B[10] */
  41126. "LDR r8, [%[a], #24]\n\t"
  41127. "LDR r9, [%[b], #40]\n\t"
  41128. "UMULL r6, r7, r8, r9\n\t"
  41129. "ADDS r4, r4, r6\n\t"
  41130. "ADCS r5, r5, r7\n\t"
  41131. "ADC r3, r3, #0x0\n\t"
  41132. /* A[5] * B[11] */
  41133. "LDR r8, [%[a], #20]\n\t"
  41134. "LDR r9, [%[b], #44]\n\t"
  41135. "UMULL r6, r7, r8, r9\n\t"
  41136. "ADDS r4, r4, r6\n\t"
  41137. "ADCS r5, r5, r7\n\t"
  41138. "ADC r3, r3, #0x0\n\t"
  41139. "STR r4, [%[r], #64]\n\t"
  41140. /* A[6] * B[11] */
  41141. "LDR r8, [%[a], #24]\n\t"
  41142. "UMULL r6, r7, r8, r9\n\t"
  41143. "ADDS r5, r5, r6\n\t"
  41144. "ADCS r3, r3, r7\n\t"
  41145. "MOV r4, #0x0\n\t"
  41146. "ADC r4, r4, #0x0\n\t"
  41147. /* A[7] * B[10] */
  41148. "LDR r8, [%[a], #28]\n\t"
  41149. "LDR r9, [%[b], #40]\n\t"
  41150. "UMULL r6, r7, r8, r9\n\t"
  41151. "ADDS r5, r5, r6\n\t"
  41152. "ADCS r3, r3, r7\n\t"
  41153. "ADC r4, r4, #0x0\n\t"
  41154. /* A[8] * B[9] */
  41155. "LDR r9, [%[b], #36]\n\t"
  41156. "UMULL r6, r7, r11, r9\n\t"
  41157. "ADDS r5, r5, r6\n\t"
  41158. "ADCS r3, r3, r7\n\t"
  41159. "ADC r4, r4, #0x0\n\t"
  41160. /* A[9] * B[8] */
  41161. "LDR r8, [%[a], #36]\n\t"
  41162. "UMULL r6, r7, r8, r12\n\t"
  41163. "ADDS r5, r5, r6\n\t"
  41164. "ADCS r3, r3, r7\n\t"
  41165. "ADC r4, r4, #0x0\n\t"
  41166. /* A[10] * B[7] */
  41167. "LDR r8, [%[a], #40]\n\t"
  41168. "LDR r9, [%[b], #28]\n\t"
  41169. "UMULL r6, r7, r8, r9\n\t"
  41170. "ADDS r5, r5, r6\n\t"
  41171. "ADCS r3, r3, r7\n\t"
  41172. "ADC r4, r4, #0x0\n\t"
  41173. /* A[11] * B[6] */
  41174. "LDR r8, [%[a], #44]\n\t"
  41175. "LDR r9, [%[b], #24]\n\t"
  41176. "UMULL r6, r7, r8, r9\n\t"
  41177. "ADDS r5, r5, r6\n\t"
  41178. "ADCS r3, r3, r7\n\t"
  41179. "ADC r4, r4, #0x0\n\t"
  41180. "STR r5, [%[r], #68]\n\t"
  41181. /* A[11] * B[7] */
  41182. "LDR r9, [%[b], #28]\n\t"
  41183. "UMULL r6, r7, r8, r9\n\t"
  41184. "ADDS r3, r3, r6\n\t"
  41185. "ADCS r4, r4, r7\n\t"
  41186. "MOV r5, #0x0\n\t"
  41187. "ADC r5, r5, #0x0\n\t"
  41188. /* A[10] * B[8] */
  41189. "LDR r8, [%[a], #40]\n\t"
  41190. "UMULL r6, r7, r8, r12\n\t"
  41191. "ADDS r3, r3, r6\n\t"
  41192. "ADCS r4, r4, r7\n\t"
  41193. "ADC r5, r5, #0x0\n\t"
  41194. /* A[9] * B[9] */
  41195. "LDR r11, [%[a], #36]\n\t"
  41196. "LDR r12, [%[b], #36]\n\t"
  41197. "UMULL r6, r7, r11, r12\n\t"
  41198. "ADDS r3, r3, r6\n\t"
  41199. "ADCS r4, r4, r7\n\t"
  41200. "ADC r5, r5, #0x0\n\t"
  41201. /* A[8] * B[10] */
  41202. "LDR r8, [%[a], #32]\n\t"
  41203. "LDR r9, [%[b], #40]\n\t"
  41204. "UMULL r6, r7, r8, r9\n\t"
  41205. "ADDS r3, r3, r6\n\t"
  41206. "ADCS r4, r4, r7\n\t"
  41207. "ADC r5, r5, #0x0\n\t"
  41208. /* A[7] * B[11] */
  41209. "LDR r8, [%[a], #28]\n\t"
  41210. "LDR r9, [%[b], #44]\n\t"
  41211. "UMULL r6, r7, r8, r9\n\t"
  41212. "ADDS r3, r3, r6\n\t"
  41213. "ADCS r4, r4, r7\n\t"
  41214. "ADC r5, r5, #0x0\n\t"
  41215. "STR r3, [%[r], #72]\n\t"
  41216. /* A[8] * B[11] */
  41217. "LDR r8, [%[a], #32]\n\t"
  41218. "UMULL r6, r7, r8, r9\n\t"
  41219. "ADDS r4, r4, r6\n\t"
  41220. "ADCS r5, r5, r7\n\t"
  41221. "MOV r3, #0x0\n\t"
  41222. "ADC r3, r3, #0x0\n\t"
  41223. /* A[9] * B[10] */
  41224. "LDR r9, [%[b], #40]\n\t"
  41225. "UMULL r6, r7, r11, r9\n\t"
  41226. "ADDS r4, r4, r6\n\t"
  41227. "ADCS r5, r5, r7\n\t"
  41228. "ADC r3, r3, #0x0\n\t"
  41229. /* A[10] * B[9] */
  41230. "LDR r8, [%[a], #40]\n\t"
  41231. "UMULL r6, r7, r8, r12\n\t"
  41232. "ADDS r4, r4, r6\n\t"
  41233. "ADCS r5, r5, r7\n\t"
  41234. "ADC r3, r3, #0x0\n\t"
  41235. /* A[11] * B[8] */
  41236. "LDR r8, [%[a], #44]\n\t"
  41237. "LDR r9, [%[b], #32]\n\t"
  41238. "UMULL r6, r7, r8, r9\n\t"
  41239. "ADDS r4, r4, r6\n\t"
  41240. "ADCS r5, r5, r7\n\t"
  41241. "ADC r3, r3, #0x0\n\t"
  41242. "STR r4, [%[r], #76]\n\t"
  41243. /* A[11] * B[9] */
  41244. "UMULL r6, r7, r8, r12\n\t"
  41245. "ADDS r5, r5, r6\n\t"
  41246. "ADCS r3, r3, r7\n\t"
  41247. "MOV r4, #0x0\n\t"
  41248. "ADC r4, r4, #0x0\n\t"
  41249. /* A[10] * B[10] */
  41250. "LDR r11, [%[a], #40]\n\t"
  41251. "LDR r12, [%[b], #40]\n\t"
  41252. "UMULL r6, r7, r11, r12\n\t"
  41253. "ADDS r5, r5, r6\n\t"
  41254. "ADCS r3, r3, r7\n\t"
  41255. "ADC r4, r4, #0x0\n\t"
  41256. /* A[9] * B[11] */
  41257. "LDR r8, [%[a], #36]\n\t"
  41258. "LDR r9, [%[b], #44]\n\t"
  41259. "UMULL r6, r7, r8, r9\n\t"
  41260. "ADDS r5, r5, r6\n\t"
  41261. "ADCS r3, r3, r7\n\t"
  41262. "ADC r4, r4, #0x0\n\t"
  41263. "STR r5, [%[r], #80]\n\t"
  41264. /* A[10] * B[11] */
  41265. "UMULL r6, r7, r11, r9\n\t"
  41266. "ADDS r3, r3, r6\n\t"
  41267. "ADCS r4, r4, r7\n\t"
  41268. "MOV r5, #0x0\n\t"
  41269. "ADC r5, r5, #0x0\n\t"
  41270. /* A[11] * B[10] */
  41271. "LDR r8, [%[a], #44]\n\t"
  41272. "UMULL r6, r7, r8, r12\n\t"
  41273. "ADDS r3, r3, r6\n\t"
  41274. "ADCS r4, r4, r7\n\t"
  41275. "ADC r5, r5, #0x0\n\t"
  41276. "STR r3, [%[r], #84]\n\t"
  41277. /* A[11] * B[11] */
  41278. "UMLAL r4, r5, r8, r9\n\t"
  41279. "STR r4, [%[r], #88]\n\t"
  41280. "STR r5, [%[r], #92]\n\t"
  41281. "LDM sp!, {r3, r4, r5, r6}\n\t"
  41282. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  41283. "LDM sp!, {r3, r4, r5, r6}\n\t"
  41284. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  41285. "LDM sp!, {r3, r4, r5, r6}\n\t"
  41286. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  41287. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  41288. :
  41289. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r11", "r12", "cc"
  41290. );
  41291. }
  41292. #endif /* WOLFSSL_SP_SMALL */
  41293. #ifdef WOLFSSL_SP_SMALL
  41294. /* Square a and put result in r. (r = a * a)
  41295. *
  41296. * r A single precision integer.
  41297. * a A single precision integer.
  41298. */
  41299. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  41300. static void sp_384_sqr_12(sp_digit* r_p, const sp_digit* a_p)
  41301. #else
  41302. static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
  41303. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  41304. {
  41305. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  41306. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  41307. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  41308. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  41309. __asm__ __volatile__ (
  41310. "SUB sp, sp, #0x60\n\t"
  41311. "LDR lr, [%[a]]\n\t"
  41312. "UMULL r8, r6, lr, lr\n\t"
  41313. "STR r8, [sp]\n\t"
  41314. "MOV r7, #0x0\n\t"
  41315. "MOV r8, #0x0\n\t"
  41316. "MOV r5, #0x4\n\t"
  41317. "\n"
  41318. "L_sp_384_sqr_12_outer:\n\t"
  41319. "SUBS r3, r5, #0x2c\n\t"
  41320. "IT cc\n\t"
  41321. "MOVCC r3, #0x0\n\t"
  41322. "SUB r4, r5, r3\n\t"
  41323. "\n"
  41324. "L_sp_384_sqr_12_inner:\n\t"
  41325. "LDR lr, [%[a], r3]\n\t"
  41326. "LDR r11, [%[a], r4]\n\t"
  41327. "UMULL r9, r10, lr, r11\n\t"
  41328. "ADDS r6, r6, r9\n\t"
  41329. "ADCS r7, r7, r10\n\t"
  41330. "ADC r8, r8, #0x0\n\t"
  41331. "ADDS r6, r6, r9\n\t"
  41332. "ADCS r7, r7, r10\n\t"
  41333. "ADC r8, r8, #0x0\n\t"
  41334. "ADD r3, r3, #0x4\n\t"
  41335. "SUB r4, r4, #0x4\n\t"
  41336. "CMP r3, r4\n\t"
  41337. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  41338. "BGT L_sp_384_sqr_12_inner_done\n\t"
  41339. #else
  41340. "BGT.N L_sp_384_sqr_12_inner_done\n\t"
  41341. #endif
  41342. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  41343. "BLT L_sp_384_sqr_12_inner\n\t"
  41344. #else
  41345. "BLT.N L_sp_384_sqr_12_inner\n\t"
  41346. #endif
  41347. "LDR lr, [%[a], r3]\n\t"
  41348. "UMULL r9, r10, lr, lr\n\t"
  41349. "ADDS r6, r6, r9\n\t"
  41350. "ADCS r7, r7, r10\n\t"
  41351. "ADC r8, r8, #0x0\n\t"
  41352. "\n"
  41353. "L_sp_384_sqr_12_inner_done:\n\t"
  41354. "STR r6, [sp, r5]\n\t"
  41355. "MOV r6, r7\n\t"
  41356. "MOV r7, r8\n\t"
  41357. "MOV r8, #0x0\n\t"
  41358. "ADD r5, r5, #0x4\n\t"
  41359. "CMP r5, #0x54\n\t"
  41360. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  41361. "BLE L_sp_384_sqr_12_outer\n\t"
  41362. #else
  41363. "BLE.N L_sp_384_sqr_12_outer\n\t"
  41364. #endif
  41365. "LDR lr, [%[a], #44]\n\t"
  41366. "UMLAL r6, r7, lr, lr\n\t"
  41367. "STR r6, [sp, r5]\n\t"
  41368. "ADD r5, r5, #0x4\n\t"
  41369. "STR r7, [sp, r5]\n\t"
  41370. "\n"
  41371. "L_sp_384_sqr_12_store:\n\t"
  41372. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  41373. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  41374. "SUBS r5, r5, #0x20\n\t"
  41375. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  41376. "BGT L_sp_384_sqr_12_store\n\t"
  41377. #else
  41378. "BGT.N L_sp_384_sqr_12_store\n\t"
  41379. #endif
  41380. : [r] "+r" (r), [a] "+r" (a)
  41381. :
  41382. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  41383. );
  41384. }
  41385. #else
  41386. /* Square a and put result in r. (r = a * a)
  41387. *
  41388. * r A single precision integer.
  41389. * a A single precision integer.
  41390. */
  41391. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  41392. static void sp_384_sqr_12(sp_digit* r_p, const sp_digit* a_p)
  41393. #else
  41394. static void sp_384_sqr_12(sp_digit* r, const sp_digit* a)
  41395. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  41396. {
  41397. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  41398. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  41399. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  41400. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  41401. __asm__ __volatile__ (
  41402. "SUB sp, sp, #0x30\n\t"
  41403. /* A[0] * A[0] */
  41404. "LDR r10, [%[a]]\n\t"
  41405. "UMULL r8, r3, r10, r10\n\t"
  41406. "MOV r4, #0x0\n\t"
  41407. "STR r8, [sp]\n\t"
  41408. /* A[0] * A[1] */
  41409. "LDR r10, [%[a], #4]\n\t"
  41410. "LDR r12, [%[a]]\n\t"
  41411. "UMULL r8, r9, r10, r12\n\t"
  41412. "ADDS r3, r3, r8\n\t"
  41413. "ADCS r4, r4, r9\n\t"
  41414. "MOV r2, #0x0\n\t"
  41415. "ADC r2, r2, #0x0\n\t"
  41416. "ADDS r3, r3, r8\n\t"
  41417. "ADCS r4, r4, r9\n\t"
  41418. "MOV r2, #0x0\n\t"
  41419. "ADC r2, r2, #0x0\n\t"
  41420. "STR r3, [sp, #4]\n\t"
  41421. /* A[0] * A[2] */
  41422. "LDR r10, [%[a], #8]\n\t"
  41423. "LDR r12, [%[a]]\n\t"
  41424. "UMULL r8, r9, r10, r12\n\t"
  41425. "ADDS r4, r4, r8\n\t"
  41426. "ADCS r2, r2, r9\n\t"
  41427. "MOV r3, #0x0\n\t"
  41428. "ADC r3, r3, #0x0\n\t"
  41429. "ADDS r4, r4, r8\n\t"
  41430. "ADCS r2, r2, r9\n\t"
  41431. "MOV r3, #0x0\n\t"
  41432. "ADC r3, r3, #0x0\n\t"
  41433. /* A[1] * A[1] */
  41434. "LDR r10, [%[a], #4]\n\t"
  41435. "UMULL r8, r9, r10, r10\n\t"
  41436. "ADDS r4, r4, r8\n\t"
  41437. "ADCS r2, r2, r9\n\t"
  41438. "ADC r3, r3, #0x0\n\t"
  41439. "STR r4, [sp, #8]\n\t"
  41440. /* A[0] * A[3] */
  41441. "LDR r10, [%[a], #12]\n\t"
  41442. "LDR r12, [%[a]]\n\t"
  41443. "UMULL r8, r9, r10, r12\n\t"
  41444. "ADDS r2, r2, r8\n\t"
  41445. "ADCS r3, r3, r9\n\t"
  41446. "MOV r4, #0x0\n\t"
  41447. "ADC r4, r4, #0x0\n\t"
  41448. "ADDS r2, r2, r8\n\t"
  41449. "ADCS r3, r3, r9\n\t"
  41450. "MOV r4, #0x0\n\t"
  41451. "ADC r4, r4, #0x0\n\t"
  41452. /* A[1] * A[2] */
  41453. "LDR r10, [%[a], #8]\n\t"
  41454. "LDR r12, [%[a], #4]\n\t"
  41455. "UMULL r8, r9, r10, r12\n\t"
  41456. "ADDS r2, r2, r8\n\t"
  41457. "ADCS r3, r3, r9\n\t"
  41458. "ADC r4, r4, #0x0\n\t"
  41459. "ADDS r2, r2, r8\n\t"
  41460. "ADCS r3, r3, r9\n\t"
  41461. "ADC r4, r4, #0x0\n\t"
  41462. "STR r2, [sp, #12]\n\t"
  41463. /* A[0] * A[4] */
  41464. "LDR r10, [%[a], #16]\n\t"
  41465. "LDR r12, [%[a]]\n\t"
  41466. "UMULL r8, r9, r10, r12\n\t"
  41467. "ADDS r3, r3, r8\n\t"
  41468. "ADCS r4, r4, r9\n\t"
  41469. "MOV r2, #0x0\n\t"
  41470. "ADC r2, r2, #0x0\n\t"
  41471. "ADDS r3, r3, r8\n\t"
  41472. "ADCS r4, r4, r9\n\t"
  41473. "MOV r2, #0x0\n\t"
  41474. "ADC r2, r2, #0x0\n\t"
  41475. /* A[1] * A[3] */
  41476. "LDR r10, [%[a], #12]\n\t"
  41477. "LDR r12, [%[a], #4]\n\t"
  41478. "UMULL r8, r9, r10, r12\n\t"
  41479. "ADDS r3, r3, r8\n\t"
  41480. "ADCS r4, r4, r9\n\t"
  41481. "ADC r2, r2, #0x0\n\t"
  41482. "ADDS r3, r3, r8\n\t"
  41483. "ADCS r4, r4, r9\n\t"
  41484. "ADC r2, r2, #0x0\n\t"
  41485. /* A[2] * A[2] */
  41486. "LDR r10, [%[a], #8]\n\t"
  41487. "UMULL r8, r9, r10, r10\n\t"
  41488. "ADDS r3, r3, r8\n\t"
  41489. "ADCS r4, r4, r9\n\t"
  41490. "ADC r2, r2, #0x0\n\t"
  41491. "STR r3, [sp, #16]\n\t"
  41492. /* A[0] * A[5] */
  41493. "LDR r10, [%[a], #20]\n\t"
  41494. "LDR r12, [%[a]]\n\t"
  41495. "UMULL r5, r6, r10, r12\n\t"
  41496. "MOV r3, #0x0\n\t"
  41497. "MOV r7, #0x0\n\t"
  41498. /* A[1] * A[4] */
  41499. "LDR r10, [%[a], #16]\n\t"
  41500. "LDR r12, [%[a], #4]\n\t"
  41501. "UMULL r8, r9, r10, r12\n\t"
  41502. "ADDS r5, r5, r8\n\t"
  41503. "ADCS r6, r6, r9\n\t"
  41504. "ADC r7, r7, #0x0\n\t"
  41505. /* A[2] * A[3] */
  41506. "LDR r10, [%[a], #12]\n\t"
  41507. "LDR r12, [%[a], #8]\n\t"
  41508. "UMULL r8, r9, r10, r12\n\t"
  41509. "ADDS r5, r5, r8\n\t"
  41510. "ADCS r6, r6, r9\n\t"
  41511. "ADC r7, r7, #0x0\n\t"
  41512. "ADDS r5, r5, r5\n\t"
  41513. "ADCS r6, r6, r6\n\t"
  41514. "ADC r7, r7, r7\n\t"
  41515. "ADDS r4, r4, r5\n\t"
  41516. "ADCS r2, r2, r6\n\t"
  41517. "ADC r3, r3, r7\n\t"
  41518. "STR r4, [sp, #20]\n\t"
  41519. /* A[0] * A[6] */
  41520. "LDR r10, [%[a], #24]\n\t"
  41521. "LDR r12, [%[a]]\n\t"
  41522. "UMULL r5, r6, r10, r12\n\t"
  41523. "MOV r4, #0x0\n\t"
  41524. "MOV r7, #0x0\n\t"
  41525. /* A[1] * A[5] */
  41526. "LDR r10, [%[a], #20]\n\t"
  41527. "LDR r12, [%[a], #4]\n\t"
  41528. "UMULL r8, r9, r10, r12\n\t"
  41529. "ADDS r5, r5, r8\n\t"
  41530. "ADCS r6, r6, r9\n\t"
  41531. "ADC r7, r7, #0x0\n\t"
  41532. /* A[2] * A[4] */
  41533. "LDR r10, [%[a], #16]\n\t"
  41534. "LDR r12, [%[a], #8]\n\t"
  41535. "UMULL r8, r9, r10, r12\n\t"
  41536. "ADDS r5, r5, r8\n\t"
  41537. "ADCS r6, r6, r9\n\t"
  41538. "ADC r7, r7, #0x0\n\t"
  41539. /* A[3] * A[3] */
  41540. "LDR r10, [%[a], #12]\n\t"
  41541. "UMULL r8, r9, r10, r10\n\t"
  41542. "ADDS r5, r5, r5\n\t"
  41543. "ADCS r6, r6, r6\n\t"
  41544. "ADC r7, r7, r7\n\t"
  41545. "ADDS r2, r2, r8\n\t"
  41546. "ADCS r3, r3, r9\n\t"
  41547. "ADC r4, r4, #0x0\n\t"
  41548. "ADDS r2, r2, r5\n\t"
  41549. "ADCS r3, r3, r6\n\t"
  41550. "ADC r4, r4, r7\n\t"
  41551. "STR r2, [sp, #24]\n\t"
  41552. /* A[0] * A[7] */
  41553. "LDR r10, [%[a], #28]\n\t"
  41554. "LDR r12, [%[a]]\n\t"
  41555. "UMULL r5, r6, r10, r12\n\t"
  41556. "MOV r2, #0x0\n\t"
  41557. "MOV r7, #0x0\n\t"
  41558. /* A[1] * A[6] */
  41559. "LDR r10, [%[a], #24]\n\t"
  41560. "LDR r12, [%[a], #4]\n\t"
  41561. "UMULL r8, r9, r10, r12\n\t"
  41562. "ADDS r5, r5, r8\n\t"
  41563. "ADCS r6, r6, r9\n\t"
  41564. "ADC r7, r7, #0x0\n\t"
  41565. /* A[2] * A[5] */
  41566. "LDR r10, [%[a], #20]\n\t"
  41567. "LDR r12, [%[a], #8]\n\t"
  41568. "UMULL r8, r9, r10, r12\n\t"
  41569. "ADDS r5, r5, r8\n\t"
  41570. "ADCS r6, r6, r9\n\t"
  41571. "ADC r7, r7, #0x0\n\t"
  41572. /* A[3] * A[4] */
  41573. "LDR r10, [%[a], #16]\n\t"
  41574. "LDR r12, [%[a], #12]\n\t"
  41575. "UMULL r8, r9, r10, r12\n\t"
  41576. "ADDS r5, r5, r8\n\t"
  41577. "ADCS r6, r6, r9\n\t"
  41578. "ADC r7, r7, #0x0\n\t"
  41579. "ADDS r5, r5, r5\n\t"
  41580. "ADCS r6, r6, r6\n\t"
  41581. "ADC r7, r7, r7\n\t"
  41582. "ADDS r3, r3, r5\n\t"
  41583. "ADCS r4, r4, r6\n\t"
  41584. "ADC r2, r2, r7\n\t"
  41585. "STR r3, [sp, #28]\n\t"
  41586. /* A[0] * A[8] */
  41587. "LDR r10, [%[a], #32]\n\t"
  41588. "LDR r12, [%[a]]\n\t"
  41589. "UMULL r5, r6, r10, r12\n\t"
  41590. "MOV r3, #0x0\n\t"
  41591. "MOV r7, #0x0\n\t"
  41592. /* A[1] * A[7] */
  41593. "LDR r10, [%[a], #28]\n\t"
  41594. "LDR r12, [%[a], #4]\n\t"
  41595. "UMULL r8, r9, r10, r12\n\t"
  41596. "ADDS r5, r5, r8\n\t"
  41597. "ADCS r6, r6, r9\n\t"
  41598. "ADC r7, r7, #0x0\n\t"
  41599. /* A[2] * A[6] */
  41600. "LDR r10, [%[a], #24]\n\t"
  41601. "LDR r12, [%[a], #8]\n\t"
  41602. "UMULL r8, r9, r10, r12\n\t"
  41603. "ADDS r5, r5, r8\n\t"
  41604. "ADCS r6, r6, r9\n\t"
  41605. "ADC r7, r7, #0x0\n\t"
  41606. /* A[3] * A[5] */
  41607. "LDR r10, [%[a], #20]\n\t"
  41608. "LDR r12, [%[a], #12]\n\t"
  41609. "UMULL r8, r9, r10, r12\n\t"
  41610. "ADDS r5, r5, r8\n\t"
  41611. "ADCS r6, r6, r9\n\t"
  41612. "ADC r7, r7, #0x0\n\t"
  41613. /* A[4] * A[4] */
  41614. "LDR r10, [%[a], #16]\n\t"
  41615. "UMULL r8, r9, r10, r10\n\t"
  41616. "ADDS r5, r5, r5\n\t"
  41617. "ADCS r6, r6, r6\n\t"
  41618. "ADC r7, r7, r7\n\t"
  41619. "ADDS r4, r4, r8\n\t"
  41620. "ADCS r2, r2, r9\n\t"
  41621. "ADC r3, r3, #0x0\n\t"
  41622. "ADDS r4, r4, r5\n\t"
  41623. "ADCS r2, r2, r6\n\t"
  41624. "ADC r3, r3, r7\n\t"
  41625. "STR r4, [sp, #32]\n\t"
  41626. /* A[0] * A[9] */
  41627. "LDR r10, [%[a], #36]\n\t"
  41628. "LDR r12, [%[a]]\n\t"
  41629. "UMULL r5, r6, r10, r12\n\t"
  41630. "MOV r4, #0x0\n\t"
  41631. "MOV r7, #0x0\n\t"
  41632. /* A[1] * A[8] */
  41633. "LDR r10, [%[a], #32]\n\t"
  41634. "LDR r12, [%[a], #4]\n\t"
  41635. "UMULL r8, r9, r10, r12\n\t"
  41636. "ADDS r5, r5, r8\n\t"
  41637. "ADCS r6, r6, r9\n\t"
  41638. "ADC r7, r7, #0x0\n\t"
  41639. /* A[2] * A[7] */
  41640. "LDR r10, [%[a], #28]\n\t"
  41641. "LDR r12, [%[a], #8]\n\t"
  41642. "UMULL r8, r9, r10, r12\n\t"
  41643. "ADDS r5, r5, r8\n\t"
  41644. "ADCS r6, r6, r9\n\t"
  41645. "ADC r7, r7, #0x0\n\t"
  41646. /* A[3] * A[6] */
  41647. "LDR r10, [%[a], #24]\n\t"
  41648. "LDR r12, [%[a], #12]\n\t"
  41649. "UMULL r8, r9, r10, r12\n\t"
  41650. "ADDS r5, r5, r8\n\t"
  41651. "ADCS r6, r6, r9\n\t"
  41652. "ADC r7, r7, #0x0\n\t"
  41653. /* A[4] * A[5] */
  41654. "LDR r10, [%[a], #20]\n\t"
  41655. "LDR r12, [%[a], #16]\n\t"
  41656. "UMULL r8, r9, r10, r12\n\t"
  41657. "ADDS r5, r5, r8\n\t"
  41658. "ADCS r6, r6, r9\n\t"
  41659. "ADC r7, r7, #0x0\n\t"
  41660. "ADDS r5, r5, r5\n\t"
  41661. "ADCS r6, r6, r6\n\t"
  41662. "ADC r7, r7, r7\n\t"
  41663. "ADDS r2, r2, r5\n\t"
  41664. "ADCS r3, r3, r6\n\t"
  41665. "ADC r4, r4, r7\n\t"
  41666. "STR r2, [sp, #36]\n\t"
  41667. /* A[0] * A[10] */
  41668. "LDR r10, [%[a], #40]\n\t"
  41669. "LDR r12, [%[a]]\n\t"
  41670. "UMULL r5, r6, r10, r12\n\t"
  41671. "MOV r2, #0x0\n\t"
  41672. "MOV r7, #0x0\n\t"
  41673. /* A[1] * A[9] */
  41674. "LDR r10, [%[a], #36]\n\t"
  41675. "LDR r12, [%[a], #4]\n\t"
  41676. "UMULL r8, r9, r10, r12\n\t"
  41677. "ADDS r5, r5, r8\n\t"
  41678. "ADCS r6, r6, r9\n\t"
  41679. "ADC r7, r7, #0x0\n\t"
  41680. /* A[2] * A[8] */
  41681. "LDR r10, [%[a], #32]\n\t"
  41682. "LDR r12, [%[a], #8]\n\t"
  41683. "UMULL r8, r9, r10, r12\n\t"
  41684. "ADDS r5, r5, r8\n\t"
  41685. "ADCS r6, r6, r9\n\t"
  41686. "ADC r7, r7, #0x0\n\t"
  41687. /* A[3] * A[7] */
  41688. "LDR r10, [%[a], #28]\n\t"
  41689. "LDR r12, [%[a], #12]\n\t"
  41690. "UMULL r8, r9, r10, r12\n\t"
  41691. "ADDS r5, r5, r8\n\t"
  41692. "ADCS r6, r6, r9\n\t"
  41693. "ADC r7, r7, #0x0\n\t"
  41694. /* A[4] * A[6] */
  41695. "LDR r10, [%[a], #24]\n\t"
  41696. "LDR r12, [%[a], #16]\n\t"
  41697. "UMULL r8, r9, r10, r12\n\t"
  41698. "ADDS r5, r5, r8\n\t"
  41699. "ADCS r6, r6, r9\n\t"
  41700. "ADC r7, r7, #0x0\n\t"
  41701. /* A[5] * A[5] */
  41702. "LDR r10, [%[a], #20]\n\t"
  41703. "UMULL r8, r9, r10, r10\n\t"
  41704. "ADDS r5, r5, r5\n\t"
  41705. "ADCS r6, r6, r6\n\t"
  41706. "ADC r7, r7, r7\n\t"
  41707. "ADDS r3, r3, r8\n\t"
  41708. "ADCS r4, r4, r9\n\t"
  41709. "ADC r2, r2, #0x0\n\t"
  41710. "ADDS r3, r3, r5\n\t"
  41711. "ADCS r4, r4, r6\n\t"
  41712. "ADC r2, r2, r7\n\t"
  41713. "STR r3, [sp, #40]\n\t"
  41714. /* A[0] * A[11] */
  41715. "LDR r10, [%[a], #44]\n\t"
  41716. "LDR r12, [%[a]]\n\t"
  41717. "UMULL r5, r6, r10, r12\n\t"
  41718. "MOV r3, #0x0\n\t"
  41719. "MOV r7, #0x0\n\t"
  41720. /* A[1] * A[10] */
  41721. "LDR r10, [%[a], #40]\n\t"
  41722. "LDR r12, [%[a], #4]\n\t"
  41723. "UMULL r8, r9, r10, r12\n\t"
  41724. "ADDS r5, r5, r8\n\t"
  41725. "ADCS r6, r6, r9\n\t"
  41726. "ADC r7, r7, #0x0\n\t"
  41727. /* A[2] * A[9] */
  41728. "LDR r10, [%[a], #36]\n\t"
  41729. "LDR r12, [%[a], #8]\n\t"
  41730. "UMULL r8, r9, r10, r12\n\t"
  41731. "ADDS r5, r5, r8\n\t"
  41732. "ADCS r6, r6, r9\n\t"
  41733. "ADC r7, r7, #0x0\n\t"
  41734. /* A[3] * A[8] */
  41735. "LDR r10, [%[a], #32]\n\t"
  41736. "LDR r12, [%[a], #12]\n\t"
  41737. "UMULL r8, r9, r10, r12\n\t"
  41738. "ADDS r5, r5, r8\n\t"
  41739. "ADCS r6, r6, r9\n\t"
  41740. "ADC r7, r7, #0x0\n\t"
  41741. /* A[4] * A[7] */
  41742. "LDR r10, [%[a], #28]\n\t"
  41743. "LDR r12, [%[a], #16]\n\t"
  41744. "UMULL r8, r9, r10, r12\n\t"
  41745. "ADDS r5, r5, r8\n\t"
  41746. "ADCS r6, r6, r9\n\t"
  41747. "ADC r7, r7, #0x0\n\t"
  41748. /* A[5] * A[6] */
  41749. "LDR r10, [%[a], #24]\n\t"
  41750. "LDR r12, [%[a], #20]\n\t"
  41751. "UMULL r8, r9, r10, r12\n\t"
  41752. "ADDS r5, r5, r8\n\t"
  41753. "ADCS r6, r6, r9\n\t"
  41754. "ADC r7, r7, #0x0\n\t"
  41755. "ADDS r5, r5, r5\n\t"
  41756. "ADCS r6, r6, r6\n\t"
  41757. "ADC r7, r7, r7\n\t"
  41758. "ADDS r4, r4, r5\n\t"
  41759. "ADCS r2, r2, r6\n\t"
  41760. "ADC r3, r3, r7\n\t"
  41761. "STR r4, [sp, #44]\n\t"
  41762. /* A[1] * A[11] */
  41763. "LDR r10, [%[a], #44]\n\t"
  41764. "LDR r12, [%[a], #4]\n\t"
  41765. "UMULL r5, r6, r10, r12\n\t"
  41766. "MOV r4, #0x0\n\t"
  41767. "MOV r7, #0x0\n\t"
  41768. /* A[2] * A[10] */
  41769. "LDR r10, [%[a], #40]\n\t"
  41770. "LDR r12, [%[a], #8]\n\t"
  41771. "UMULL r8, r9, r10, r12\n\t"
  41772. "ADDS r5, r5, r8\n\t"
  41773. "ADCS r6, r6, r9\n\t"
  41774. "ADC r7, r7, #0x0\n\t"
  41775. /* A[3] * A[9] */
  41776. "LDR r10, [%[a], #36]\n\t"
  41777. "LDR r12, [%[a], #12]\n\t"
  41778. "UMULL r8, r9, r10, r12\n\t"
  41779. "ADDS r5, r5, r8\n\t"
  41780. "ADCS r6, r6, r9\n\t"
  41781. "ADC r7, r7, #0x0\n\t"
  41782. /* A[4] * A[8] */
  41783. "LDR r10, [%[a], #32]\n\t"
  41784. "LDR r12, [%[a], #16]\n\t"
  41785. "UMULL r8, r9, r10, r12\n\t"
  41786. "ADDS r5, r5, r8\n\t"
  41787. "ADCS r6, r6, r9\n\t"
  41788. "ADC r7, r7, #0x0\n\t"
  41789. /* A[5] * A[7] */
  41790. "LDR r10, [%[a], #28]\n\t"
  41791. "LDR r12, [%[a], #20]\n\t"
  41792. "UMULL r8, r9, r10, r12\n\t"
  41793. "ADDS r5, r5, r8\n\t"
  41794. "ADCS r6, r6, r9\n\t"
  41795. "ADC r7, r7, #0x0\n\t"
  41796. /* A[6] * A[6] */
  41797. "LDR r10, [%[a], #24]\n\t"
  41798. "UMULL r8, r9, r10, r10\n\t"
  41799. "ADDS r5, r5, r5\n\t"
  41800. "ADCS r6, r6, r6\n\t"
  41801. "ADC r7, r7, r7\n\t"
  41802. "ADDS r2, r2, r8\n\t"
  41803. "ADCS r3, r3, r9\n\t"
  41804. "ADC r4, r4, #0x0\n\t"
  41805. "ADDS r2, r2, r5\n\t"
  41806. "ADCS r3, r3, r6\n\t"
  41807. "ADC r4, r4, r7\n\t"
  41808. "STR r2, [%[r], #48]\n\t"
  41809. /* A[2] * A[11] */
  41810. "LDR r10, [%[a], #44]\n\t"
  41811. "LDR r12, [%[a], #8]\n\t"
  41812. "UMULL r5, r6, r10, r12\n\t"
  41813. "MOV r2, #0x0\n\t"
  41814. "MOV r7, #0x0\n\t"
  41815. /* A[3] * A[10] */
  41816. "LDR r10, [%[a], #40]\n\t"
  41817. "LDR r12, [%[a], #12]\n\t"
  41818. "UMULL r8, r9, r10, r12\n\t"
  41819. "ADDS r5, r5, r8\n\t"
  41820. "ADCS r6, r6, r9\n\t"
  41821. "ADC r7, r7, #0x0\n\t"
  41822. /* A[4] * A[9] */
  41823. "LDR r10, [%[a], #36]\n\t"
  41824. "LDR r12, [%[a], #16]\n\t"
  41825. "UMULL r8, r9, r10, r12\n\t"
  41826. "ADDS r5, r5, r8\n\t"
  41827. "ADCS r6, r6, r9\n\t"
  41828. "ADC r7, r7, #0x0\n\t"
  41829. /* A[5] * A[8] */
  41830. "LDR r10, [%[a], #32]\n\t"
  41831. "LDR r12, [%[a], #20]\n\t"
  41832. "UMULL r8, r9, r10, r12\n\t"
  41833. "ADDS r5, r5, r8\n\t"
  41834. "ADCS r6, r6, r9\n\t"
  41835. "ADC r7, r7, #0x0\n\t"
  41836. /* A[6] * A[7] */
  41837. "LDR r10, [%[a], #28]\n\t"
  41838. "LDR r12, [%[a], #24]\n\t"
  41839. "UMULL r8, r9, r10, r12\n\t"
  41840. "ADDS r5, r5, r8\n\t"
  41841. "ADCS r6, r6, r9\n\t"
  41842. "ADC r7, r7, #0x0\n\t"
  41843. "ADDS r5, r5, r5\n\t"
  41844. "ADCS r6, r6, r6\n\t"
  41845. "ADC r7, r7, r7\n\t"
  41846. "ADDS r3, r3, r5\n\t"
  41847. "ADCS r4, r4, r6\n\t"
  41848. "ADC r2, r2, r7\n\t"
  41849. "STR r3, [%[r], #52]\n\t"
  41850. /* A[3] * A[11] */
  41851. "LDR r10, [%[a], #44]\n\t"
  41852. "LDR r12, [%[a], #12]\n\t"
  41853. "UMULL r5, r6, r10, r12\n\t"
  41854. "MOV r3, #0x0\n\t"
  41855. "MOV r7, #0x0\n\t"
  41856. /* A[4] * A[10] */
  41857. "LDR r10, [%[a], #40]\n\t"
  41858. "LDR r12, [%[a], #16]\n\t"
  41859. "UMULL r8, r9, r10, r12\n\t"
  41860. "ADDS r5, r5, r8\n\t"
  41861. "ADCS r6, r6, r9\n\t"
  41862. "ADC r7, r7, #0x0\n\t"
  41863. /* A[5] * A[9] */
  41864. "LDR r10, [%[a], #36]\n\t"
  41865. "LDR r12, [%[a], #20]\n\t"
  41866. "UMULL r8, r9, r10, r12\n\t"
  41867. "ADDS r5, r5, r8\n\t"
  41868. "ADCS r6, r6, r9\n\t"
  41869. "ADC r7, r7, #0x0\n\t"
  41870. /* A[6] * A[8] */
  41871. "LDR r10, [%[a], #32]\n\t"
  41872. "LDR r12, [%[a], #24]\n\t"
  41873. "UMULL r8, r9, r10, r12\n\t"
  41874. "ADDS r5, r5, r8\n\t"
  41875. "ADCS r6, r6, r9\n\t"
  41876. "ADC r7, r7, #0x0\n\t"
  41877. /* A[7] * A[7] */
  41878. "LDR r10, [%[a], #28]\n\t"
  41879. "UMULL r8, r9, r10, r10\n\t"
  41880. "ADDS r5, r5, r5\n\t"
  41881. "ADCS r6, r6, r6\n\t"
  41882. "ADC r7, r7, r7\n\t"
  41883. "ADDS r4, r4, r8\n\t"
  41884. "ADCS r2, r2, r9\n\t"
  41885. "ADC r3, r3, #0x0\n\t"
  41886. "ADDS r4, r4, r5\n\t"
  41887. "ADCS r2, r2, r6\n\t"
  41888. "ADC r3, r3, r7\n\t"
  41889. "STR r4, [%[r], #56]\n\t"
  41890. /* A[4] * A[11] */
  41891. "LDR r10, [%[a], #44]\n\t"
  41892. "LDR r12, [%[a], #16]\n\t"
  41893. "UMULL r5, r6, r10, r12\n\t"
  41894. "MOV r4, #0x0\n\t"
  41895. "MOV r7, #0x0\n\t"
  41896. /* A[5] * A[10] */
  41897. "LDR r10, [%[a], #40]\n\t"
  41898. "LDR r12, [%[a], #20]\n\t"
  41899. "UMULL r8, r9, r10, r12\n\t"
  41900. "ADDS r5, r5, r8\n\t"
  41901. "ADCS r6, r6, r9\n\t"
  41902. "ADC r7, r7, #0x0\n\t"
  41903. /* A[6] * A[9] */
  41904. "LDR r10, [%[a], #36]\n\t"
  41905. "LDR r12, [%[a], #24]\n\t"
  41906. "UMULL r8, r9, r10, r12\n\t"
  41907. "ADDS r5, r5, r8\n\t"
  41908. "ADCS r6, r6, r9\n\t"
  41909. "ADC r7, r7, #0x0\n\t"
  41910. /* A[7] * A[8] */
  41911. "LDR r10, [%[a], #32]\n\t"
  41912. "LDR r12, [%[a], #28]\n\t"
  41913. "UMULL r8, r9, r10, r12\n\t"
  41914. "ADDS r5, r5, r8\n\t"
  41915. "ADCS r6, r6, r9\n\t"
  41916. "ADC r7, r7, #0x0\n\t"
  41917. "ADDS r5, r5, r5\n\t"
  41918. "ADCS r6, r6, r6\n\t"
  41919. "ADC r7, r7, r7\n\t"
  41920. "ADDS r2, r2, r5\n\t"
  41921. "ADCS r3, r3, r6\n\t"
  41922. "ADC r4, r4, r7\n\t"
  41923. "STR r2, [%[r], #60]\n\t"
  41924. /* A[5] * A[11] */
  41925. "LDR r10, [%[a], #44]\n\t"
  41926. "LDR r12, [%[a], #20]\n\t"
  41927. "UMULL r5, r6, r10, r12\n\t"
  41928. "MOV r2, #0x0\n\t"
  41929. "MOV r7, #0x0\n\t"
  41930. /* A[6] * A[10] */
  41931. "LDR r10, [%[a], #40]\n\t"
  41932. "LDR r12, [%[a], #24]\n\t"
  41933. "UMULL r8, r9, r10, r12\n\t"
  41934. "ADDS r5, r5, r8\n\t"
  41935. "ADCS r6, r6, r9\n\t"
  41936. "ADC r7, r7, #0x0\n\t"
  41937. /* A[7] * A[9] */
  41938. "LDR r10, [%[a], #36]\n\t"
  41939. "LDR r12, [%[a], #28]\n\t"
  41940. "UMULL r8, r9, r10, r12\n\t"
  41941. "ADDS r5, r5, r8\n\t"
  41942. "ADCS r6, r6, r9\n\t"
  41943. "ADC r7, r7, #0x0\n\t"
  41944. /* A[8] * A[8] */
  41945. "LDR r10, [%[a], #32]\n\t"
  41946. "UMULL r8, r9, r10, r10\n\t"
  41947. "ADDS r5, r5, r5\n\t"
  41948. "ADCS r6, r6, r6\n\t"
  41949. "ADC r7, r7, r7\n\t"
  41950. "ADDS r3, r3, r8\n\t"
  41951. "ADCS r4, r4, r9\n\t"
  41952. "ADC r2, r2, #0x0\n\t"
  41953. "ADDS r3, r3, r5\n\t"
  41954. "ADCS r4, r4, r6\n\t"
  41955. "ADC r2, r2, r7\n\t"
  41956. "STR r3, [%[r], #64]\n\t"
  41957. /* A[6] * A[11] */
  41958. "LDR r10, [%[a], #44]\n\t"
  41959. "LDR r12, [%[a], #24]\n\t"
  41960. "UMULL r5, r6, r10, r12\n\t"
  41961. "MOV r3, #0x0\n\t"
  41962. "MOV r7, #0x0\n\t"
  41963. /* A[7] * A[10] */
  41964. "LDR r10, [%[a], #40]\n\t"
  41965. "LDR r12, [%[a], #28]\n\t"
  41966. "UMULL r8, r9, r10, r12\n\t"
  41967. "ADDS r5, r5, r8\n\t"
  41968. "ADCS r6, r6, r9\n\t"
  41969. "ADC r7, r7, #0x0\n\t"
  41970. /* A[8] * A[9] */
  41971. "LDR r10, [%[a], #36]\n\t"
  41972. "LDR r12, [%[a], #32]\n\t"
  41973. "UMULL r8, r9, r10, r12\n\t"
  41974. "ADDS r5, r5, r8\n\t"
  41975. "ADCS r6, r6, r9\n\t"
  41976. "ADC r7, r7, #0x0\n\t"
  41977. "ADDS r5, r5, r5\n\t"
  41978. "ADCS r6, r6, r6\n\t"
  41979. "ADC r7, r7, r7\n\t"
  41980. "ADDS r4, r4, r5\n\t"
  41981. "ADCS r2, r2, r6\n\t"
  41982. "ADC r3, r3, r7\n\t"
  41983. "STR r4, [%[r], #68]\n\t"
  41984. /* A[7] * A[11] */
  41985. "LDR r10, [%[a], #44]\n\t"
  41986. "LDR r12, [%[a], #28]\n\t"
  41987. "UMULL r8, r9, r10, r12\n\t"
  41988. "ADDS r2, r2, r8\n\t"
  41989. "ADCS r3, r3, r9\n\t"
  41990. "MOV r4, #0x0\n\t"
  41991. "ADC r4, r4, #0x0\n\t"
  41992. "ADDS r2, r2, r8\n\t"
  41993. "ADCS r3, r3, r9\n\t"
  41994. "MOV r4, #0x0\n\t"
  41995. "ADC r4, r4, #0x0\n\t"
  41996. /* A[8] * A[10] */
  41997. "LDR r10, [%[a], #40]\n\t"
  41998. "LDR r12, [%[a], #32]\n\t"
  41999. "UMULL r8, r9, r10, r12\n\t"
  42000. "ADDS r2, r2, r8\n\t"
  42001. "ADCS r3, r3, r9\n\t"
  42002. "ADC r4, r4, #0x0\n\t"
  42003. "ADDS r2, r2, r8\n\t"
  42004. "ADCS r3, r3, r9\n\t"
  42005. "ADC r4, r4, #0x0\n\t"
  42006. /* A[9] * A[9] */
  42007. "LDR r10, [%[a], #36]\n\t"
  42008. "UMULL r8, r9, r10, r10\n\t"
  42009. "ADDS r2, r2, r8\n\t"
  42010. "ADCS r3, r3, r9\n\t"
  42011. "ADC r4, r4, #0x0\n\t"
  42012. "STR r2, [%[r], #72]\n\t"
  42013. /* A[8] * A[11] */
  42014. "LDR r10, [%[a], #44]\n\t"
  42015. "LDR r12, [%[a], #32]\n\t"
  42016. "UMULL r8, r9, r10, r12\n\t"
  42017. "ADDS r3, r3, r8\n\t"
  42018. "ADCS r4, r4, r9\n\t"
  42019. "MOV r2, #0x0\n\t"
  42020. "ADC r2, r2, #0x0\n\t"
  42021. "ADDS r3, r3, r8\n\t"
  42022. "ADCS r4, r4, r9\n\t"
  42023. "MOV r2, #0x0\n\t"
  42024. "ADC r2, r2, #0x0\n\t"
  42025. /* A[9] * A[10] */
  42026. "LDR r10, [%[a], #40]\n\t"
  42027. "LDR r12, [%[a], #36]\n\t"
  42028. "UMULL r8, r9, r10, r12\n\t"
  42029. "ADDS r3, r3, r8\n\t"
  42030. "ADCS r4, r4, r9\n\t"
  42031. "ADC r2, r2, #0x0\n\t"
  42032. "ADDS r3, r3, r8\n\t"
  42033. "ADCS r4, r4, r9\n\t"
  42034. "ADC r2, r2, #0x0\n\t"
  42035. "STR r3, [%[r], #76]\n\t"
  42036. /* A[9] * A[11] */
  42037. "LDR r10, [%[a], #44]\n\t"
  42038. "LDR r12, [%[a], #36]\n\t"
  42039. "UMULL r8, r9, r10, r12\n\t"
  42040. "ADDS r4, r4, r8\n\t"
  42041. "ADCS r2, r2, r9\n\t"
  42042. "MOV r3, #0x0\n\t"
  42043. "ADC r3, r3, #0x0\n\t"
  42044. "ADDS r4, r4, r8\n\t"
  42045. "ADCS r2, r2, r9\n\t"
  42046. "MOV r3, #0x0\n\t"
  42047. "ADC r3, r3, #0x0\n\t"
  42048. /* A[10] * A[10] */
  42049. "LDR r10, [%[a], #40]\n\t"
  42050. "UMULL r8, r9, r10, r10\n\t"
  42051. "ADDS r4, r4, r8\n\t"
  42052. "ADCS r2, r2, r9\n\t"
  42053. "ADC r3, r3, #0x0\n\t"
  42054. "STR r4, [%[r], #80]\n\t"
  42055. /* A[10] * A[11] */
  42056. "LDR r10, [%[a], #44]\n\t"
  42057. "LDR r12, [%[a], #40]\n\t"
  42058. "UMULL r8, r9, r10, r12\n\t"
  42059. "ADDS r2, r2, r8\n\t"
  42060. "ADCS r3, r3, r9\n\t"
  42061. "MOV r4, #0x0\n\t"
  42062. "ADC r4, r4, #0x0\n\t"
  42063. "ADDS r2, r2, r8\n\t"
  42064. "ADCS r3, r3, r9\n\t"
  42065. "MOV r4, #0x0\n\t"
  42066. "ADC r4, r4, #0x0\n\t"
  42067. "STR r2, [%[r], #84]\n\t"
  42068. /* A[11] * A[11] */
  42069. "LDR r10, [%[a], #44]\n\t"
  42070. "UMLAL r3, r4, r10, r10\n\t"
  42071. "STR r3, [%[r], #88]\n\t"
  42072. "STR r4, [%[r], #92]\n\t"
  42073. "LDM sp!, {r2, r3, r4, r8}\n\t"
  42074. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  42075. "LDM sp!, {r2, r3, r4, r8}\n\t"
  42076. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  42077. "LDM sp!, {r2, r3, r4, r8}\n\t"
  42078. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  42079. : [r] "+r" (r), [a] "+r" (a)
  42080. :
  42081. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "cc"
  42082. );
  42083. }
  42084. #endif /* WOLFSSL_SP_SMALL */
  42085. #ifdef WOLFSSL_SP_SMALL
  42086. /* Add b to a into r. (r = a + b)
  42087. *
  42088. * r A single precision integer.
  42089. * a A single precision integer.
  42090. * b A single precision integer.
  42091. */
  42092. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42093. static sp_digit sp_384_add_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  42094. #else
  42095. static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  42096. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42097. {
  42098. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42099. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  42100. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  42101. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  42102. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42103. __asm__ __volatile__ (
  42104. "MOV r3, #0x0\n\t"
  42105. "ADD r12, %[a], #0x30\n\t"
  42106. "\n"
  42107. "L_sp_384_add_12_word:\n\t"
  42108. "ADDS r3, r3, #0xffffffff\n\t"
  42109. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  42110. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  42111. "ADCS r4, r4, r8\n\t"
  42112. "ADCS r5, r5, r9\n\t"
  42113. "ADCS r6, r6, r10\n\t"
  42114. "ADCS r7, r7, r11\n\t"
  42115. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  42116. "MOV r4, #0x0\n\t"
  42117. "ADC r3, r4, #0x0\n\t"
  42118. "CMP %[a], r12\n\t"
  42119. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  42120. "BNE L_sp_384_add_12_word\n\t"
  42121. #else
  42122. "BNE.N L_sp_384_add_12_word\n\t"
  42123. #endif
  42124. "MOV %[r], r3\n\t"
  42125. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  42126. :
  42127. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  42128. );
  42129. return (uint32_t)(size_t)r;
  42130. }
  42131. #else
  42132. /* Add b to a into r. (r = a + b)
  42133. *
  42134. * r A single precision integer.
  42135. * a A single precision integer.
  42136. * b A single precision integer.
  42137. */
  42138. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42139. static sp_digit sp_384_add_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  42140. #else
  42141. static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  42142. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42143. {
  42144. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42145. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  42146. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  42147. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  42148. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42149. __asm__ __volatile__ (
  42150. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  42151. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  42152. "ADDS r3, r3, r7\n\t"
  42153. "ADCS r4, r4, r8\n\t"
  42154. "ADCS r5, r5, r9\n\t"
  42155. "ADCS r6, r6, r10\n\t"
  42156. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  42157. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  42158. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  42159. "ADCS r3, r3, r7\n\t"
  42160. "ADCS r4, r4, r8\n\t"
  42161. "ADCS r5, r5, r9\n\t"
  42162. "ADCS r6, r6, r10\n\t"
  42163. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  42164. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  42165. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  42166. "ADCS r3, r3, r7\n\t"
  42167. "ADCS r4, r4, r8\n\t"
  42168. "ADCS r5, r5, r9\n\t"
  42169. "ADCS r6, r6, r10\n\t"
  42170. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  42171. "MOV %[r], #0x0\n\t"
  42172. "ADC %[r], %[r], #0x0\n\t"
  42173. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  42174. :
  42175. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  42176. );
  42177. return (uint32_t)(size_t)r;
  42178. }
  42179. #endif /* WOLFSSL_SP_SMALL */
  42180. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  42181. *
  42182. * r The resulting Montgomery form number.
  42183. * a The number to convert.
  42184. * m The modulus (prime).
  42185. * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
  42186. */
  42187. static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
  42188. {
  42189. #ifdef WOLFSSL_SP_SMALL_STACK
  42190. int64_t* t = NULL;
  42191. #else
  42192. int64_t t[12];
  42193. #endif
  42194. int64_t o;
  42195. int err = MP_OKAY;
  42196. (void)m;
  42197. #ifdef WOLFSSL_SP_SMALL_STACK
  42198. t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC);
  42199. if (t == NULL) {
  42200. err = MEMORY_E;
  42201. }
  42202. #endif
  42203. if (err == MP_OKAY) {
  42204. /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
  42205. t[0] = 0 + (int64_t)a[0] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[11];
  42206. /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
  42207. t[1] = 0 - (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[8] + (int64_t)a[10] + (int64_t)a[11];
  42208. /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
  42209. t[2] = 0 - (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[9] + (int64_t)a[11];
  42210. /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
  42211. t[3] = 0 + (int64_t)a[0] - (int64_t)a[2] + (int64_t)a[3] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[10] - (int64_t)a[11];
  42212. /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
  42213. t[4] = 0 + (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[3] + (int64_t)a[4] + (int64_t)a[8] + 2 * (int64_t)a[9] + (int64_t)a[10] - 2 * (int64_t)a[11];
  42214. /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
  42215. t[5] = 0 + (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[4] + (int64_t)a[5] + (int64_t)a[9] + 2 * (int64_t)a[10] + (int64_t)a[11];
  42216. /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
  42217. t[6] = 0 + (int64_t)a[2] + (int64_t)a[3] - (int64_t)a[5] + (int64_t)a[6] + (int64_t)a[10] + 2 * (int64_t)a[11];
  42218. /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
  42219. t[7] = 0 + (int64_t)a[3] + (int64_t)a[4] - (int64_t)a[6] + (int64_t)a[7] + (int64_t)a[11];
  42220. /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
  42221. t[8] = 0 + (int64_t)a[4] + (int64_t)a[5] - (int64_t)a[7] + (int64_t)a[8];
  42222. /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
  42223. t[9] = 0 + (int64_t)a[5] + (int64_t)a[6] - (int64_t)a[8] + (int64_t)a[9];
  42224. /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
  42225. t[10] = 0 + (int64_t)a[6] + (int64_t)a[7] - (int64_t)a[9] + (int64_t)a[10];
  42226. /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
  42227. t[11] = 0 + (int64_t)a[7] + (int64_t)a[8] - (int64_t)a[10] + (int64_t)a[11];
  42228. t[1] += t[0] >> 32; t[0] &= 0xffffffff;
  42229. t[2] += t[1] >> 32; t[1] &= 0xffffffff;
  42230. t[3] += t[2] >> 32; t[2] &= 0xffffffff;
  42231. t[4] += t[3] >> 32; t[3] &= 0xffffffff;
  42232. t[5] += t[4] >> 32; t[4] &= 0xffffffff;
  42233. t[6] += t[5] >> 32; t[5] &= 0xffffffff;
  42234. t[7] += t[6] >> 32; t[6] &= 0xffffffff;
  42235. t[8] += t[7] >> 32; t[7] &= 0xffffffff;
  42236. t[9] += t[8] >> 32; t[8] &= 0xffffffff;
  42237. t[10] += t[9] >> 32; t[9] &= 0xffffffff;
  42238. t[11] += t[10] >> 32; t[10] &= 0xffffffff;
  42239. o = t[11] >> 32; t[11] &= 0xffffffff;
  42240. t[0] += o;
  42241. t[1] -= o;
  42242. t[3] += o;
  42243. t[4] += o;
  42244. t[1] += t[0] >> 32; t[0] &= 0xffffffff;
  42245. t[2] += t[1] >> 32; t[1] &= 0xffffffff;
  42246. t[3] += t[2] >> 32; t[2] &= 0xffffffff;
  42247. t[4] += t[3] >> 32; t[3] &= 0xffffffff;
  42248. t[5] += t[4] >> 32; t[4] &= 0xffffffff;
  42249. t[6] += t[5] >> 32; t[5] &= 0xffffffff;
  42250. t[7] += t[6] >> 32; t[6] &= 0xffffffff;
  42251. t[8] += t[7] >> 32; t[7] &= 0xffffffff;
  42252. t[9] += t[8] >> 32; t[8] &= 0xffffffff;
  42253. t[10] += t[9] >> 32; t[9] &= 0xffffffff;
  42254. t[11] += t[10] >> 32; t[10] &= 0xffffffff;
  42255. r[0] = t[0];
  42256. r[1] = t[1];
  42257. r[2] = t[2];
  42258. r[3] = t[3];
  42259. r[4] = t[4];
  42260. r[5] = t[5];
  42261. r[6] = t[6];
  42262. r[7] = t[7];
  42263. r[8] = t[8];
  42264. r[9] = t[9];
  42265. r[10] = t[10];
  42266. r[11] = t[11];
  42267. }
  42268. #ifdef WOLFSSL_SP_SMALL_STACK
  42269. if (t != NULL)
  42270. XFREE(t, NULL, DYNAMIC_TYPE_ECC);
  42271. #endif
  42272. return err;
  42273. }
  42274. /* Convert an mp_int to an array of sp_digit.
  42275. *
  42276. * r A single precision integer.
  42277. * size Maximum number of bytes to convert
  42278. * a A multi-precision integer.
  42279. */
  42280. static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
  42281. {
  42282. #if DIGIT_BIT == 32
  42283. int i;
  42284. sp_digit j = (sp_digit)0 - (sp_digit)a->used;
  42285. int o = 0;
  42286. for (i = 0; i < size; i++) {
  42287. sp_digit mask = (sp_digit)0 - (j >> 31);
  42288. r[i] = a->dp[o] & mask;
  42289. j++;
  42290. o += (int)(j >> 31);
  42291. }
  42292. #elif DIGIT_BIT > 32
  42293. unsigned int i;
  42294. int j = 0;
  42295. word32 s = 0;
  42296. r[0] = 0;
  42297. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  42298. r[j] |= ((sp_digit)a->dp[i] << s);
  42299. r[j] &= 0xffffffff;
  42300. s = 32U - s;
  42301. if (j + 1 >= size) {
  42302. break;
  42303. }
  42304. /* lint allow cast of mismatch word32 and mp_digit */
  42305. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  42306. while ((s + 32U) <= (word32)DIGIT_BIT) {
  42307. s += 32U;
  42308. r[j] &= 0xffffffff;
  42309. if (j + 1 >= size) {
  42310. break;
  42311. }
  42312. if (s < (word32)DIGIT_BIT) {
  42313. /* lint allow cast of mismatch word32 and mp_digit */
  42314. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  42315. }
  42316. else {
  42317. r[++j] = (sp_digit)0;
  42318. }
  42319. }
  42320. s = (word32)DIGIT_BIT - s;
  42321. }
  42322. for (j++; j < size; j++) {
  42323. r[j] = 0;
  42324. }
  42325. #else
  42326. unsigned int i;
  42327. int j = 0;
  42328. int s = 0;
  42329. r[0] = 0;
  42330. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  42331. r[j] |= ((sp_digit)a->dp[i]) << s;
  42332. if (s + DIGIT_BIT >= 32) {
  42333. r[j] &= 0xffffffff;
  42334. if (j + 1 >= size) {
  42335. break;
  42336. }
  42337. s = 32 - s;
  42338. if (s == DIGIT_BIT) {
  42339. r[++j] = 0;
  42340. s = 0;
  42341. }
  42342. else {
  42343. r[++j] = a->dp[i] >> s;
  42344. s = DIGIT_BIT - s;
  42345. }
  42346. }
  42347. else {
  42348. s += DIGIT_BIT;
  42349. }
  42350. }
  42351. for (j++; j < size; j++) {
  42352. r[j] = 0;
  42353. }
  42354. #endif
  42355. }
  42356. /* Convert a point of type ecc_point to type sp_point_384.
  42357. *
  42358. * p Point of type sp_point_384 (result).
  42359. * pm Point of type ecc_point.
  42360. */
  42361. static void sp_384_point_from_ecc_point_12(sp_point_384* p,
  42362. const ecc_point* pm)
  42363. {
  42364. XMEMSET(p->x, 0, sizeof(p->x));
  42365. XMEMSET(p->y, 0, sizeof(p->y));
  42366. XMEMSET(p->z, 0, sizeof(p->z));
  42367. sp_384_from_mp(p->x, 12, pm->x);
  42368. sp_384_from_mp(p->y, 12, pm->y);
  42369. sp_384_from_mp(p->z, 12, pm->z);
  42370. p->infinity = 0;
  42371. }
  42372. /* Convert an array of sp_digit to an mp_int.
  42373. *
  42374. * a A single precision integer.
  42375. * r A multi-precision integer.
  42376. */
  42377. static int sp_384_to_mp(const sp_digit* a, mp_int* r)
  42378. {
  42379. int err;
  42380. err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
  42381. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  42382. #if DIGIT_BIT == 32
  42383. XMEMCPY(r->dp, a, sizeof(sp_digit) * 12);
  42384. r->used = 12;
  42385. mp_clamp(r);
  42386. #elif DIGIT_BIT < 32
  42387. int i;
  42388. int j = 0;
  42389. int s = 0;
  42390. r->dp[0] = 0;
  42391. for (i = 0; i < 12; i++) {
  42392. r->dp[j] |= (mp_digit)(a[i] << s);
  42393. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  42394. s = DIGIT_BIT - s;
  42395. r->dp[++j] = (mp_digit)(a[i] >> s);
  42396. while (s + DIGIT_BIT <= 32) {
  42397. s += DIGIT_BIT;
  42398. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  42399. if (s == SP_WORD_SIZE) {
  42400. r->dp[j] = 0;
  42401. }
  42402. else {
  42403. r->dp[j] = (mp_digit)(a[i] >> s);
  42404. }
  42405. }
  42406. s = 32 - s;
  42407. }
  42408. r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
  42409. mp_clamp(r);
  42410. #else
  42411. int i;
  42412. int j = 0;
  42413. int s = 0;
  42414. r->dp[0] = 0;
  42415. for (i = 0; i < 12; i++) {
  42416. r->dp[j] |= ((mp_digit)a[i]) << s;
  42417. if (s + 32 >= DIGIT_BIT) {
  42418. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  42419. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  42420. #endif
  42421. s = DIGIT_BIT - s;
  42422. r->dp[++j] = a[i] >> s;
  42423. s = 32 - s;
  42424. }
  42425. else {
  42426. s += 32;
  42427. }
  42428. }
  42429. r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
  42430. mp_clamp(r);
  42431. #endif
  42432. }
  42433. return err;
  42434. }
  42435. /* Convert a point of type sp_point_384 to type ecc_point.
  42436. *
  42437. * p Point of type sp_point_384.
  42438. * pm Point of type ecc_point (result).
  42439. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  42440. * MP_OKAY.
  42441. */
  42442. static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm)
  42443. {
  42444. int err;
  42445. err = sp_384_to_mp(p->x, pm->x);
  42446. if (err == MP_OKAY) {
  42447. err = sp_384_to_mp(p->y, pm->y);
  42448. }
  42449. if (err == MP_OKAY) {
  42450. err = sp_384_to_mp(p->z, pm->z);
  42451. }
  42452. return err;
  42453. }
  42454. #ifdef WOLFSSL_SP_SMALL
  42455. /* Conditionally subtract b from a using the mask m.
  42456. * m is -1 to subtract and 0 when not copying.
  42457. *
  42458. * r A single precision number representing condition subtract result.
  42459. * a A single precision number to subtract from.
  42460. * b A single precision number to subtract.
  42461. * m Mask value to apply.
  42462. */
  42463. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42464. static sp_digit sp_384_cond_sub_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  42465. #else
  42466. static sp_digit sp_384_cond_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  42467. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42468. {
  42469. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42470. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  42471. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  42472. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  42473. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  42474. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42475. __asm__ __volatile__ (
  42476. "MOV r8, #0x0\n\t"
  42477. "MOV r4, #0x0\n\t"
  42478. "MOV r5, #0x0\n\t"
  42479. "\n"
  42480. "L_sp_384_cond_sub_12_words:\n\t"
  42481. "SUBS r4, r8, r4\n\t"
  42482. "LDR r6, [%[a], r5]\n\t"
  42483. "LDR r7, [%[b], r5]\n\t"
  42484. "AND r7, r7, %[m]\n\t"
  42485. "SBCS r6, r6, r7\n\t"
  42486. "SBC r4, r8, r8\n\t"
  42487. "STR r6, [%[r], r5]\n\t"
  42488. "ADD r5, r5, #0x4\n\t"
  42489. "CMP r5, #0x30\n\t"
  42490. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  42491. "BLT L_sp_384_cond_sub_12_words\n\t"
  42492. #else
  42493. "BLT.N L_sp_384_cond_sub_12_words\n\t"
  42494. #endif
  42495. "MOV %[r], r4\n\t"
  42496. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  42497. :
  42498. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  42499. );
  42500. return (uint32_t)(size_t)r;
  42501. }
  42502. #else
  42503. /* Conditionally subtract b from a using the mask m.
  42504. * m is -1 to subtract and 0 when not copying.
  42505. *
  42506. * r A single precision number representing condition subtract result.
  42507. * a A single precision number to subtract from.
  42508. * b A single precision number to subtract.
  42509. * m Mask value to apply.
  42510. */
  42511. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42512. static sp_digit sp_384_cond_sub_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  42513. #else
  42514. static sp_digit sp_384_cond_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  42515. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42516. {
  42517. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42518. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  42519. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  42520. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  42521. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  42522. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42523. __asm__ __volatile__ (
  42524. "MOV r5, #0x0\n\t"
  42525. "LDM %[a]!, {r6, r7}\n\t"
  42526. "LDM %[b]!, {r8, r9}\n\t"
  42527. "AND r8, r8, %[m]\n\t"
  42528. "AND r9, r9, %[m]\n\t"
  42529. "SUBS r6, r6, r8\n\t"
  42530. "SBCS r7, r7, r9\n\t"
  42531. "STM %[r]!, {r6, r7}\n\t"
  42532. "LDM %[a]!, {r6, r7}\n\t"
  42533. "LDM %[b]!, {r8, r9}\n\t"
  42534. "AND r8, r8, %[m]\n\t"
  42535. "AND r9, r9, %[m]\n\t"
  42536. "SBCS r6, r6, r8\n\t"
  42537. "SBCS r7, r7, r9\n\t"
  42538. "STM %[r]!, {r6, r7}\n\t"
  42539. "LDM %[a]!, {r6, r7}\n\t"
  42540. "LDM %[b]!, {r8, r9}\n\t"
  42541. "AND r8, r8, %[m]\n\t"
  42542. "AND r9, r9, %[m]\n\t"
  42543. "SBCS r6, r6, r8\n\t"
  42544. "SBCS r7, r7, r9\n\t"
  42545. "STM %[r]!, {r6, r7}\n\t"
  42546. "LDM %[a]!, {r6, r7}\n\t"
  42547. "LDM %[b]!, {r8, r9}\n\t"
  42548. "AND r8, r8, %[m]\n\t"
  42549. "AND r9, r9, %[m]\n\t"
  42550. "SBCS r6, r6, r8\n\t"
  42551. "SBCS r7, r7, r9\n\t"
  42552. "STM %[r]!, {r6, r7}\n\t"
  42553. "LDM %[a]!, {r6, r7}\n\t"
  42554. "LDM %[b]!, {r8, r9}\n\t"
  42555. "AND r8, r8, %[m]\n\t"
  42556. "AND r9, r9, %[m]\n\t"
  42557. "SBCS r6, r6, r8\n\t"
  42558. "SBCS r7, r7, r9\n\t"
  42559. "STM %[r]!, {r6, r7}\n\t"
  42560. "LDM %[a]!, {r6, r7}\n\t"
  42561. "LDM %[b]!, {r8, r9}\n\t"
  42562. "AND r8, r8, %[m]\n\t"
  42563. "AND r9, r9, %[m]\n\t"
  42564. "SBCS r6, r6, r8\n\t"
  42565. "SBCS r7, r7, r9\n\t"
  42566. "STM %[r]!, {r6, r7}\n\t"
  42567. "SBC %[r], r5, r5\n\t"
  42568. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  42569. :
  42570. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  42571. );
  42572. return (uint32_t)(size_t)r;
  42573. }
  42574. #endif /* WOLFSSL_SP_SMALL */
  42575. #define sp_384_mont_reduce_order_12 sp_384_mont_reduce_12
  42576. #ifdef WOLFSSL_SP_NO_UMAAL
  42577. /* Reduce the number back to 384 bits using Montgomery reduction.
  42578. *
  42579. * a A single precision number to reduce in place.
  42580. * m The single precision number representing the modulus.
  42581. * mp The digit representing the negative inverse of m mod 2^n.
  42582. */
  42583. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42584. SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  42585. #else
  42586. SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, sp_digit mp)
  42587. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42588. {
  42589. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42590. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  42591. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  42592. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  42593. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42594. __asm__ __volatile__ (
  42595. "LDR lr, [%[m]]\n\t"
  42596. /* i = 0 */
  42597. "MOV r11, #0x0\n\t"
  42598. "MOV r3, #0x0\n\t"
  42599. "LDR r4, [%[a]]\n\t"
  42600. "LDR r5, [%[a], #4]\n\t"
  42601. "\n"
  42602. "L_sp_384_mont_reduce_12_word:\n\t"
  42603. /* mu = a[i] * mp */
  42604. "MUL r10, %[mp], r4\n\t"
  42605. /* a[i+0] += m[0] * mu */
  42606. "MOV r7, #0x0\n\t"
  42607. "UMLAL r4, r7, r10, lr\n\t"
  42608. /* a[i+1] += m[1] * mu */
  42609. "LDR r9, [%[m], #4]\n\t"
  42610. "MOV r6, #0x0\n\t"
  42611. "UMLAL r5, r6, r10, r9\n\t"
  42612. "MOV r4, r5\n\t"
  42613. "ADDS r4, r4, r7\n\t"
  42614. "ADC r6, r6, #0x0\n\t"
  42615. /* a[i+2] += m[2] * mu */
  42616. "LDR r9, [%[m], #8]\n\t"
  42617. "LDR r5, [%[a], #8]\n\t"
  42618. "MOV r7, #0x0\n\t"
  42619. "UMLAL r5, r7, r10, r9\n\t"
  42620. "ADDS r5, r5, r6\n\t"
  42621. "ADC r7, r7, #0x0\n\t"
  42622. /* a[i+3] += m[3] * mu */
  42623. "LDR r9, [%[m], #12]\n\t"
  42624. "LDR r12, [%[a], #12]\n\t"
  42625. "MOV r6, #0x0\n\t"
  42626. "UMLAL r12, r6, r10, r9\n\t"
  42627. "ADDS r12, r12, r7\n\t"
  42628. "STR r12, [%[a], #12]\n\t"
  42629. "ADC r6, r6, #0x0\n\t"
  42630. /* a[i+4] += m[4] * mu */
  42631. "LDR r9, [%[m], #16]\n\t"
  42632. "LDR r12, [%[a], #16]\n\t"
  42633. "MOV r7, #0x0\n\t"
  42634. "UMLAL r12, r7, r10, r9\n\t"
  42635. "ADDS r12, r12, r6\n\t"
  42636. "STR r12, [%[a], #16]\n\t"
  42637. "ADC r7, r7, #0x0\n\t"
  42638. /* a[i+5] += m[5] * mu */
  42639. "LDR r9, [%[m], #20]\n\t"
  42640. "LDR r12, [%[a], #20]\n\t"
  42641. "MOV r6, #0x0\n\t"
  42642. "UMLAL r12, r6, r10, r9\n\t"
  42643. "ADDS r12, r12, r7\n\t"
  42644. "STR r12, [%[a], #20]\n\t"
  42645. "ADC r6, r6, #0x0\n\t"
  42646. /* a[i+6] += m[6] * mu */
  42647. "LDR r9, [%[m], #24]\n\t"
  42648. "LDR r12, [%[a], #24]\n\t"
  42649. "MOV r7, #0x0\n\t"
  42650. "UMLAL r12, r7, r10, r9\n\t"
  42651. "ADDS r12, r12, r6\n\t"
  42652. "STR r12, [%[a], #24]\n\t"
  42653. "ADC r7, r7, #0x0\n\t"
  42654. /* a[i+7] += m[7] * mu */
  42655. "LDR r9, [%[m], #28]\n\t"
  42656. "LDR r12, [%[a], #28]\n\t"
  42657. "MOV r6, #0x0\n\t"
  42658. "UMLAL r12, r6, r10, r9\n\t"
  42659. "ADDS r12, r12, r7\n\t"
  42660. "STR r12, [%[a], #28]\n\t"
  42661. "ADC r6, r6, #0x0\n\t"
  42662. /* a[i+8] += m[8] * mu */
  42663. "LDR r9, [%[m], #32]\n\t"
  42664. "LDR r12, [%[a], #32]\n\t"
  42665. "MOV r7, #0x0\n\t"
  42666. "UMLAL r12, r7, r10, r9\n\t"
  42667. "ADDS r12, r12, r6\n\t"
  42668. "STR r12, [%[a], #32]\n\t"
  42669. "ADC r7, r7, #0x0\n\t"
  42670. /* a[i+9] += m[9] * mu */
  42671. "LDR r9, [%[m], #36]\n\t"
  42672. "LDR r12, [%[a], #36]\n\t"
  42673. "MOV r6, #0x0\n\t"
  42674. "UMLAL r12, r6, r10, r9\n\t"
  42675. "ADDS r12, r12, r7\n\t"
  42676. "STR r12, [%[a], #36]\n\t"
  42677. "ADC r6, r6, #0x0\n\t"
  42678. /* a[i+10] += m[10] * mu */
  42679. "LDR r9, [%[m], #40]\n\t"
  42680. "LDR r12, [%[a], #40]\n\t"
  42681. "MOV r7, #0x0\n\t"
  42682. "UMLAL r12, r7, r10, r9\n\t"
  42683. "ADDS r12, r12, r6\n\t"
  42684. "STR r12, [%[a], #40]\n\t"
  42685. "ADC r7, r7, #0x0\n\t"
  42686. /* a[i+11] += m[11] * mu */
  42687. "LDR r9, [%[m], #44]\n\t"
  42688. "LDR r12, [%[a], #44]\n\t"
  42689. "UMULL r8, r9, r10, r9\n\t"
  42690. "ADDS r7, r7, r8\n\t"
  42691. "ADCS r6, r9, r3\n\t"
  42692. "MOV r3, #0x0\n\t"
  42693. "ADC r3, r3, r3\n\t"
  42694. "ADDS r12, r12, r7\n\t"
  42695. "STR r12, [%[a], #44]\n\t"
  42696. "LDR r12, [%[a], #48]\n\t"
  42697. "ADCS r12, r12, r6\n\t"
  42698. "STR r12, [%[a], #48]\n\t"
  42699. "ADC r3, r3, #0x0\n\t"
  42700. /* i += 1 */
  42701. "ADD r11, r11, #0x4\n\t"
  42702. "ADD %[a], %[a], #0x4\n\t"
  42703. "CMP r11, #0x30\n\t"
  42704. #ifdef __GNUC__
  42705. "BLT L_sp_384_mont_reduce_12_word\n\t"
  42706. #else
  42707. "BLT.W L_sp_384_mont_reduce_12_word\n\t"
  42708. #endif
  42709. /* Loop Done */
  42710. "STR r4, [%[a]]\n\t"
  42711. "STR r5, [%[a], #4]\n\t"
  42712. "MOV %[mp], r3\n\t"
  42713. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  42714. :
  42715. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  42716. );
  42717. sp_384_cond_sub_12(a - 12, a, m, (sp_digit)0 - mp);
  42718. }
  42719. #else
  42720. /* Reduce the number back to 384 bits using Montgomery reduction.
  42721. *
  42722. * a A single precision number to reduce in place.
  42723. * m The single precision number representing the modulus.
  42724. * mp The digit representing the negative inverse of m mod 2^n.
  42725. */
  42726. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42727. SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  42728. #else
  42729. SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, sp_digit mp)
  42730. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42731. {
  42732. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42733. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  42734. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  42735. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  42736. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42737. __asm__ __volatile__ (
  42738. /* i = 0 */
  42739. "MOV r4, #0x0\n\t"
  42740. "MOV r5, #0x0\n\t"
  42741. "LDR r6, [%[a]]\n\t"
  42742. "LDR r7, [%[a], #4]\n\t"
  42743. "LDR r8, [%[a], #8]\n\t"
  42744. "LDR r9, [%[a], #12]\n\t"
  42745. "LDR r10, [%[a], #16]\n\t"
  42746. "\n"
  42747. "L_sp_384_mont_reduce_12_word:\n\t"
  42748. /* mu = a[i] * mp */
  42749. "MUL lr, %[mp], r6\n\t"
  42750. /* a[i+0] += m[0] * mu */
  42751. "LDR r12, [%[m]]\n\t"
  42752. "MOV r3, #0x0\n\t"
  42753. "UMAAL r6, r3, lr, r12\n\t"
  42754. /* a[i+1] += m[1] * mu */
  42755. "LDR r12, [%[m], #4]\n\t"
  42756. "MOV r6, r7\n\t"
  42757. "UMAAL r6, r3, lr, r12\n\t"
  42758. /* a[i+2] += m[2] * mu */
  42759. "LDR r12, [%[m], #8]\n\t"
  42760. "MOV r7, r8\n\t"
  42761. "UMAAL r7, r3, lr, r12\n\t"
  42762. /* a[i+3] += m[3] * mu */
  42763. "LDR r12, [%[m], #12]\n\t"
  42764. "MOV r8, r9\n\t"
  42765. "UMAAL r8, r3, lr, r12\n\t"
  42766. /* a[i+4] += m[4] * mu */
  42767. "LDR r12, [%[m], #16]\n\t"
  42768. "MOV r9, r10\n\t"
  42769. "UMAAL r9, r3, lr, r12\n\t"
  42770. /* a[i+5] += m[5] * mu */
  42771. "LDR r12, [%[m], #20]\n\t"
  42772. "LDR r10, [%[a], #20]\n\t"
  42773. "UMAAL r10, r3, lr, r12\n\t"
  42774. /* a[i+6] += m[6] * mu */
  42775. "LDR r12, [%[m], #24]\n\t"
  42776. "LDR r11, [%[a], #24]\n\t"
  42777. "UMAAL r11, r3, lr, r12\n\t"
  42778. "STR r11, [%[a], #24]\n\t"
  42779. /* a[i+7] += m[7] * mu */
  42780. "LDR r12, [%[m], #28]\n\t"
  42781. "LDR r11, [%[a], #28]\n\t"
  42782. "UMAAL r11, r3, lr, r12\n\t"
  42783. "STR r11, [%[a], #28]\n\t"
  42784. /* a[i+8] += m[8] * mu */
  42785. "LDR r12, [%[m], #32]\n\t"
  42786. "LDR r11, [%[a], #32]\n\t"
  42787. "UMAAL r11, r3, lr, r12\n\t"
  42788. "STR r11, [%[a], #32]\n\t"
  42789. /* a[i+9] += m[9] * mu */
  42790. "LDR r12, [%[m], #36]\n\t"
  42791. "LDR r11, [%[a], #36]\n\t"
  42792. "UMAAL r11, r3, lr, r12\n\t"
  42793. "STR r11, [%[a], #36]\n\t"
  42794. /* a[i+10] += m[10] * mu */
  42795. "LDR r12, [%[m], #40]\n\t"
  42796. "LDR r11, [%[a], #40]\n\t"
  42797. "UMAAL r11, r3, lr, r12\n\t"
  42798. "STR r11, [%[a], #40]\n\t"
  42799. /* a[i+11] += m[11] * mu */
  42800. "LDR r12, [%[m], #44]\n\t"
  42801. "LDR r11, [%[a], #44]\n\t"
  42802. "UMAAL r11, r3, lr, r12\n\t"
  42803. "LDR lr, [%[a], #48]\n\t"
  42804. "MOV r12, #0x0\n\t"
  42805. "UMAAL r3, lr, r12, r12\n\t"
  42806. "STR r11, [%[a], #44]\n\t"
  42807. "ADDS r3, r3, r5\n\t"
  42808. "ADC r5, lr, #0x0\n\t"
  42809. "STR r3, [%[a], #48]\n\t"
  42810. /* i += 1 */
  42811. "ADD r4, r4, #0x4\n\t"
  42812. "ADD %[a], %[a], #0x4\n\t"
  42813. "CMP r4, #0x30\n\t"
  42814. #ifdef __GNUC__
  42815. "BLT L_sp_384_mont_reduce_12_word\n\t"
  42816. #else
  42817. "BLT.W L_sp_384_mont_reduce_12_word\n\t"
  42818. #endif
  42819. /* Loop Done */
  42820. "STR r6, [%[a]]\n\t"
  42821. "STR r7, [%[a], #4]\n\t"
  42822. "STR r8, [%[a], #8]\n\t"
  42823. "STR r9, [%[a], #12]\n\t"
  42824. "STR r10, [%[a], #16]\n\t"
  42825. "MOV %[mp], r5\n\t"
  42826. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  42827. :
  42828. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  42829. );
  42830. sp_384_cond_sub_12(a - 12, a, m, (sp_digit)0 - mp);
  42831. }
  42832. #endif
  42833. /* Multiply two Montgomery form numbers mod the modulus (prime).
  42834. * (r = a * b mod m)
  42835. *
  42836. * r Result of multiplication.
  42837. * a First number to multiply in Montgomery form.
  42838. * b Second number to multiply in Montgomery form.
  42839. * m Modulus (prime).
  42840. * mp Montgomery multiplier.
  42841. */
  42842. SP_NOINLINE static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a,
  42843. const sp_digit* b, const sp_digit* m, sp_digit mp)
  42844. {
  42845. sp_384_mul_12(r, a, b);
  42846. sp_384_mont_reduce_12(r, m, mp);
  42847. }
  42848. /* Square the Montgomery form number. (r = a * a mod m)
  42849. *
  42850. * r Result of squaring.
  42851. * a Number to square in Montgomery form.
  42852. * m Modulus (prime).
  42853. * mp Montgomery multiplier.
  42854. */
  42855. SP_NOINLINE static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a,
  42856. const sp_digit* m, sp_digit mp)
  42857. {
  42858. sp_384_sqr_12(r, a);
  42859. sp_384_mont_reduce_12(r, m, mp);
  42860. }
  42861. #if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
  42862. /* Square the Montgomery form number a number of times. (r = a ^ n mod m)
  42863. *
  42864. * r Result of squaring.
  42865. * a Number to square in Montgomery form.
  42866. * n Number of times to square.
  42867. * m Modulus (prime).
  42868. * mp Montgomery multiplier.
  42869. */
  42870. SP_NOINLINE static void sp_384_mont_sqr_n_12(sp_digit* r,
  42871. const sp_digit* a, int n, const sp_digit* m, sp_digit mp)
  42872. {
  42873. sp_384_mont_sqr_12(r, a, m, mp);
  42874. for (; n > 1; n--) {
  42875. sp_384_mont_sqr_12(r, r, m, mp);
  42876. }
  42877. }
  42878. #endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
  42879. #ifdef WOLFSSL_SP_SMALL
  42880. /* Mod-2 for the P384 curve. */
  42881. static const uint32_t p384_mod_minus_2[12] = {
  42882. 0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU,
  42883. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU
  42884. };
  42885. #endif /* !WOLFSSL_SP_SMALL */
  42886. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  42887. * P384 curve. (r = 1 / a mod m)
  42888. *
  42889. * r Inverse result.
  42890. * a Number to invert.
  42891. * td Temporary data.
  42892. */
  42893. static void sp_384_mont_inv_12(sp_digit* r, const sp_digit* a, sp_digit* td)
  42894. {
  42895. #ifdef WOLFSSL_SP_SMALL
  42896. sp_digit* t = td;
  42897. int i;
  42898. XMEMCPY(t, a, sizeof(sp_digit) * 12);
  42899. for (i=382; i>=0; i--) {
  42900. sp_384_mont_sqr_12(t, t, p384_mod, p384_mp_mod);
  42901. if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
  42902. sp_384_mont_mul_12(t, t, a, p384_mod, p384_mp_mod);
  42903. }
  42904. XMEMCPY(r, t, sizeof(sp_digit) * 12);
  42905. #else
  42906. sp_digit* t1 = td;
  42907. sp_digit* t2 = td + 2 * 12;
  42908. sp_digit* t3 = td + 4 * 12;
  42909. sp_digit* t4 = td + 6 * 12;
  42910. sp_digit* t5 = td + 8 * 12;
  42911. /* 0x2 */
  42912. sp_384_mont_sqr_12(t1, a, p384_mod, p384_mp_mod);
  42913. /* 0x3 */
  42914. sp_384_mont_mul_12(t5, t1, a, p384_mod, p384_mp_mod);
  42915. /* 0xc */
  42916. sp_384_mont_sqr_n_12(t1, t5, 2, p384_mod, p384_mp_mod);
  42917. /* 0xf */
  42918. sp_384_mont_mul_12(t2, t5, t1, p384_mod, p384_mp_mod);
  42919. /* 0x1e */
  42920. sp_384_mont_sqr_12(t1, t2, p384_mod, p384_mp_mod);
  42921. /* 0x1f */
  42922. sp_384_mont_mul_12(t4, t1, a, p384_mod, p384_mp_mod);
  42923. /* 0x3e0 */
  42924. sp_384_mont_sqr_n_12(t1, t4, 5, p384_mod, p384_mp_mod);
  42925. /* 0x3ff */
  42926. sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod);
  42927. /* 0x7fe0 */
  42928. sp_384_mont_sqr_n_12(t1, t2, 5, p384_mod, p384_mp_mod);
  42929. /* 0x7fff */
  42930. sp_384_mont_mul_12(t4, t4, t1, p384_mod, p384_mp_mod);
  42931. /* 0x3fff8000 */
  42932. sp_384_mont_sqr_n_12(t1, t4, 15, p384_mod, p384_mp_mod);
  42933. /* 0x3fffffff */
  42934. sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod);
  42935. /* 0xfffffffc */
  42936. sp_384_mont_sqr_n_12(t3, t2, 2, p384_mod, p384_mp_mod);
  42937. /* 0xfffffffd */
  42938. sp_384_mont_mul_12(r, t3, a, p384_mod, p384_mp_mod);
  42939. /* 0xffffffff */
  42940. sp_384_mont_mul_12(t3, t5, t3, p384_mod, p384_mp_mod);
  42941. /* 0xfffffffc0000000 */
  42942. sp_384_mont_sqr_n_12(t1, t2, 30, p384_mod, p384_mp_mod);
  42943. /* 0xfffffffffffffff */
  42944. sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod);
  42945. /* 0xfffffffffffffff000000000000000 */
  42946. sp_384_mont_sqr_n_12(t1, t2, 60, p384_mod, p384_mp_mod);
  42947. /* 0xffffffffffffffffffffffffffffff */
  42948. sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod);
  42949. /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */
  42950. sp_384_mont_sqr_n_12(t1, t2, 120, p384_mod, p384_mp_mod);
  42951. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  42952. sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod);
  42953. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */
  42954. sp_384_mont_sqr_n_12(t1, t2, 15, p384_mod, p384_mp_mod);
  42955. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  42956. sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod);
  42957. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */
  42958. sp_384_mont_sqr_n_12(t1, t2, 33, p384_mod, p384_mp_mod);
  42959. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */
  42960. sp_384_mont_mul_12(t2, t3, t1, p384_mod, p384_mp_mod);
  42961. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */
  42962. sp_384_mont_sqr_n_12(t1, t2, 96, p384_mod, p384_mp_mod);
  42963. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */
  42964. sp_384_mont_mul_12(r, r, t1, p384_mod, p384_mp_mod);
  42965. #endif /* WOLFSSL_SP_SMALL */
  42966. }
  42967. /* Compare a with b in constant time.
  42968. *
  42969. * a A single precision integer.
  42970. * b A single precision integer.
  42971. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  42972. * respectively.
  42973. */
  42974. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42975. static sp_int32 sp_384_cmp_12(const sp_digit* a_p, const sp_digit* b_p)
  42976. #else
  42977. static sp_int32 sp_384_cmp_12(const sp_digit* a, const sp_digit* b)
  42978. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42979. {
  42980. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  42981. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  42982. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  42983. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  42984. __asm__ __volatile__ (
  42985. "MOV r2, #0xffffffff\n\t"
  42986. "MOV r8, #0x1\n\t"
  42987. "MOV r7, #0x0\n\t"
  42988. "MOV r3, #0xffffffff\n\t"
  42989. #ifdef WOLFSSL_SP_SMALL
  42990. "MOV r6, #0x2c\n\t"
  42991. "\n"
  42992. "L_sp_384_cmp_12_words:\n\t"
  42993. "LDR r4, [%[a], r6]\n\t"
  42994. "LDR r5, [%[b], r6]\n\t"
  42995. "AND r4, r4, r3\n\t"
  42996. "AND r5, r5, r3\n\t"
  42997. "SUBS r4, r4, r5\n\t"
  42998. "IT hi\n\t"
  42999. "movhi r2, r8\n\t"
  43000. "IT lo\n\t"
  43001. "movlo r2, r3\n\t"
  43002. "IT ne\n\t"
  43003. "movne r3, r7\n\t"
  43004. "SUBS r6, r6, #0x4\n\t"
  43005. "bcs L_sp_384_cmp_12_words\n\t"
  43006. "EOR r2, r2, r3\n\t"
  43007. #else
  43008. "LDR r4, [%[a], #44]\n\t"
  43009. "LDR r5, [%[b], #44]\n\t"
  43010. "AND r4, r4, r3\n\t"
  43011. "AND r5, r5, r3\n\t"
  43012. "SUBS r4, r4, r5\n\t"
  43013. "IT hi\n\t"
  43014. "movhi r2, r8\n\t"
  43015. "IT lo\n\t"
  43016. "movlo r2, r3\n\t"
  43017. "IT ne\n\t"
  43018. "movne r3, r7\n\t"
  43019. "LDR r4, [%[a], #40]\n\t"
  43020. "LDR r5, [%[b], #40]\n\t"
  43021. "AND r4, r4, r3\n\t"
  43022. "AND r5, r5, r3\n\t"
  43023. "SUBS r4, r4, r5\n\t"
  43024. "IT hi\n\t"
  43025. "movhi r2, r8\n\t"
  43026. "IT lo\n\t"
  43027. "movlo r2, r3\n\t"
  43028. "IT ne\n\t"
  43029. "movne r3, r7\n\t"
  43030. "LDR r4, [%[a], #36]\n\t"
  43031. "LDR r5, [%[b], #36]\n\t"
  43032. "AND r4, r4, r3\n\t"
  43033. "AND r5, r5, r3\n\t"
  43034. "SUBS r4, r4, r5\n\t"
  43035. "IT hi\n\t"
  43036. "movhi r2, r8\n\t"
  43037. "IT lo\n\t"
  43038. "movlo r2, r3\n\t"
  43039. "IT ne\n\t"
  43040. "movne r3, r7\n\t"
  43041. "LDR r4, [%[a], #32]\n\t"
  43042. "LDR r5, [%[b], #32]\n\t"
  43043. "AND r4, r4, r3\n\t"
  43044. "AND r5, r5, r3\n\t"
  43045. "SUBS r4, r4, r5\n\t"
  43046. "IT hi\n\t"
  43047. "movhi r2, r8\n\t"
  43048. "IT lo\n\t"
  43049. "movlo r2, r3\n\t"
  43050. "IT ne\n\t"
  43051. "movne r3, r7\n\t"
  43052. "LDR r4, [%[a], #28]\n\t"
  43053. "LDR r5, [%[b], #28]\n\t"
  43054. "AND r4, r4, r3\n\t"
  43055. "AND r5, r5, r3\n\t"
  43056. "SUBS r4, r4, r5\n\t"
  43057. "IT hi\n\t"
  43058. "movhi r2, r8\n\t"
  43059. "IT lo\n\t"
  43060. "movlo r2, r3\n\t"
  43061. "IT ne\n\t"
  43062. "movne r3, r7\n\t"
  43063. "LDR r4, [%[a], #24]\n\t"
  43064. "LDR r5, [%[b], #24]\n\t"
  43065. "AND r4, r4, r3\n\t"
  43066. "AND r5, r5, r3\n\t"
  43067. "SUBS r4, r4, r5\n\t"
  43068. "IT hi\n\t"
  43069. "movhi r2, r8\n\t"
  43070. "IT lo\n\t"
  43071. "movlo r2, r3\n\t"
  43072. "IT ne\n\t"
  43073. "movne r3, r7\n\t"
  43074. "LDR r4, [%[a], #20]\n\t"
  43075. "LDR r5, [%[b], #20]\n\t"
  43076. "AND r4, r4, r3\n\t"
  43077. "AND r5, r5, r3\n\t"
  43078. "SUBS r4, r4, r5\n\t"
  43079. "IT hi\n\t"
  43080. "movhi r2, r8\n\t"
  43081. "IT lo\n\t"
  43082. "movlo r2, r3\n\t"
  43083. "IT ne\n\t"
  43084. "movne r3, r7\n\t"
  43085. "LDR r4, [%[a], #16]\n\t"
  43086. "LDR r5, [%[b], #16]\n\t"
  43087. "AND r4, r4, r3\n\t"
  43088. "AND r5, r5, r3\n\t"
  43089. "SUBS r4, r4, r5\n\t"
  43090. "IT hi\n\t"
  43091. "movhi r2, r8\n\t"
  43092. "IT lo\n\t"
  43093. "movlo r2, r3\n\t"
  43094. "IT ne\n\t"
  43095. "movne r3, r7\n\t"
  43096. "LDR r4, [%[a], #12]\n\t"
  43097. "LDR r5, [%[b], #12]\n\t"
  43098. "AND r4, r4, r3\n\t"
  43099. "AND r5, r5, r3\n\t"
  43100. "SUBS r4, r4, r5\n\t"
  43101. "IT hi\n\t"
  43102. "movhi r2, r8\n\t"
  43103. "IT lo\n\t"
  43104. "movlo r2, r3\n\t"
  43105. "IT ne\n\t"
  43106. "movne r3, r7\n\t"
  43107. "LDR r4, [%[a], #8]\n\t"
  43108. "LDR r5, [%[b], #8]\n\t"
  43109. "AND r4, r4, r3\n\t"
  43110. "AND r5, r5, r3\n\t"
  43111. "SUBS r4, r4, r5\n\t"
  43112. "IT hi\n\t"
  43113. "movhi r2, r8\n\t"
  43114. "IT lo\n\t"
  43115. "movlo r2, r3\n\t"
  43116. "IT ne\n\t"
  43117. "movne r3, r7\n\t"
  43118. "LDR r4, [%[a], #4]\n\t"
  43119. "LDR r5, [%[b], #4]\n\t"
  43120. "AND r4, r4, r3\n\t"
  43121. "AND r5, r5, r3\n\t"
  43122. "SUBS r4, r4, r5\n\t"
  43123. "IT hi\n\t"
  43124. "movhi r2, r8\n\t"
  43125. "IT lo\n\t"
  43126. "movlo r2, r3\n\t"
  43127. "IT ne\n\t"
  43128. "movne r3, r7\n\t"
  43129. "LDR r4, [%[a]]\n\t"
  43130. "LDR r5, [%[b]]\n\t"
  43131. "AND r4, r4, r3\n\t"
  43132. "AND r5, r5, r3\n\t"
  43133. "SUBS r4, r4, r5\n\t"
  43134. "IT hi\n\t"
  43135. "movhi r2, r8\n\t"
  43136. "IT lo\n\t"
  43137. "movlo r2, r3\n\t"
  43138. "IT ne\n\t"
  43139. "movne r3, r7\n\t"
  43140. "EOR r2, r2, r3\n\t"
  43141. #endif /*WOLFSSL_SP_SMALL */
  43142. "MOV %[a], r2\n\t"
  43143. : [a] "+r" (a), [b] "+r" (b)
  43144. :
  43145. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  43146. );
  43147. return (uint32_t)(size_t)a;
  43148. }
  43149. /* Normalize the values in each word to 32.
  43150. *
  43151. * a Array of sp_digit to normalize.
  43152. */
  43153. #define sp_384_norm_12(a)
  43154. /* Map the Montgomery form projective coordinate point to an affine point.
  43155. *
  43156. * r Resulting affine coordinate point.
  43157. * p Montgomery form projective coordinate point.
  43158. * t Temporary ordinate data.
  43159. */
  43160. static void sp_384_map_12(sp_point_384* r, const sp_point_384* p,
  43161. sp_digit* t)
  43162. {
  43163. sp_digit* t1 = t;
  43164. sp_digit* t2 = t + 2*12;
  43165. sp_int32 n;
  43166. sp_384_mont_inv_12(t1, p->z, t + 2*12);
  43167. sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod);
  43168. sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod);
  43169. /* x /= z^2 */
  43170. sp_384_mont_mul_12(r->x, p->x, t2, p384_mod, p384_mp_mod);
  43171. XMEMSET(r->x + 12, 0, sizeof(sp_digit) * 12U);
  43172. sp_384_mont_reduce_12(r->x, p384_mod, p384_mp_mod);
  43173. /* Reduce x to less than modulus */
  43174. n = sp_384_cmp_12(r->x, p384_mod);
  43175. sp_384_cond_sub_12(r->x, r->x, p384_mod, ~(n >> 31));
  43176. sp_384_norm_12(r->x);
  43177. /* y /= z^3 */
  43178. sp_384_mont_mul_12(r->y, p->y, t1, p384_mod, p384_mp_mod);
  43179. XMEMSET(r->y + 12, 0, sizeof(sp_digit) * 12U);
  43180. sp_384_mont_reduce_12(r->y, p384_mod, p384_mp_mod);
  43181. /* Reduce y to less than modulus */
  43182. n = sp_384_cmp_12(r->y, p384_mod);
  43183. sp_384_cond_sub_12(r->y, r->y, p384_mod, ~(n >> 31));
  43184. sp_384_norm_12(r->y);
  43185. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  43186. r->z[0] = 1;
  43187. }
  43188. /* Add two Montgomery form numbers (r = a + b % m).
  43189. *
  43190. * r Result of addition.
  43191. * a First number to add in Montgomery form.
  43192. * b Second number to add in Montgomery form.
  43193. * m Modulus (prime).
  43194. */
  43195. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43196. SP_NOINLINE static void sp_384_mont_add_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  43197. #else
  43198. SP_NOINLINE static void sp_384_mont_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  43199. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43200. {
  43201. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43202. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43203. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43204. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  43205. register const sp_digit* m __asm__ ("r3") = (const sp_digit*)m_p;
  43206. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43207. sp_digit o;
  43208. o = sp_384_add_12(r, a, b);
  43209. sp_384_cond_sub_12(r, r, m, 0 - o);
  43210. }
  43211. /* Double a Montgomery form number (r = a + a % m).
  43212. *
  43213. * r Result of doubling.
  43214. * a Number to double in Montgomery form.
  43215. * m Modulus (prime).
  43216. */
  43217. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43218. SP_NOINLINE static void sp_384_mont_dbl_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  43219. #else
  43220. SP_NOINLINE static void sp_384_mont_dbl_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
  43221. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43222. {
  43223. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43224. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43225. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43226. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  43227. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43228. sp_digit o;
  43229. o = sp_384_add_12(r, a, a);
  43230. sp_384_cond_sub_12(r, r, m, 0 - o);
  43231. }
  43232. /* Triple a Montgomery form number (r = a + a + a % m).
  43233. *
  43234. * r Result of Tripling.
  43235. * a Number to triple in Montgomery form.
  43236. * m Modulus (prime).
  43237. */
  43238. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43239. SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  43240. #else
  43241. SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
  43242. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43243. {
  43244. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43245. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43246. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43247. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  43248. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43249. sp_digit o;
  43250. o = sp_384_add_12(r, a, a);
  43251. sp_384_cond_sub_12(r, r, m, 0 - o);
  43252. o = sp_384_add_12(r, r, a);
  43253. sp_384_cond_sub_12(r, r, m, 0 - o);
  43254. }
  43255. #ifdef WOLFSSL_SP_SMALL
  43256. /* Sub b from a into r. (r = a - b)
  43257. *
  43258. * r A single precision integer.
  43259. * a A single precision integer.
  43260. * b A single precision integer.
  43261. */
  43262. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43263. static sp_digit sp_384_sub_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  43264. #else
  43265. static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  43266. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43267. {
  43268. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43269. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43270. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43271. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  43272. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43273. __asm__ __volatile__ (
  43274. "MOV r11, #0x0\n\t"
  43275. "ADD r12, %[a], #0x30\n\t"
  43276. "\n"
  43277. "L_sp_384_sub_12_word:\n\t"
  43278. "RSBS r11, r11, #0x0\n\t"
  43279. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  43280. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  43281. "SBCS r3, r3, r7\n\t"
  43282. "SBCS r4, r4, r8\n\t"
  43283. "SBCS r5, r5, r9\n\t"
  43284. "SBCS r6, r6, r10\n\t"
  43285. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  43286. "SBC r11, r3, r3\n\t"
  43287. "CMP %[a], r12\n\t"
  43288. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  43289. "BNE L_sp_384_sub_12_word\n\t"
  43290. #else
  43291. "BNE.N L_sp_384_sub_12_word\n\t"
  43292. #endif
  43293. "MOV %[r], r11\n\t"
  43294. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  43295. :
  43296. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  43297. );
  43298. return (uint32_t)(size_t)r;
  43299. }
  43300. #else
  43301. /* Sub b from a into r. (r = a - b)
  43302. *
  43303. * r A single precision integer.
  43304. * a A single precision integer.
  43305. * b A single precision integer.
  43306. */
  43307. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43308. static sp_digit sp_384_sub_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  43309. #else
  43310. static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  43311. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43312. {
  43313. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43314. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43315. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43316. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  43317. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43318. __asm__ __volatile__ (
  43319. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  43320. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  43321. "SUBS r3, r3, r7\n\t"
  43322. "SBCS r4, r4, r8\n\t"
  43323. "SBCS r5, r5, r9\n\t"
  43324. "SBCS r6, r6, r10\n\t"
  43325. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  43326. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  43327. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  43328. "SBCS r3, r3, r7\n\t"
  43329. "SBCS r4, r4, r8\n\t"
  43330. "SBCS r5, r5, r9\n\t"
  43331. "SBCS r6, r6, r10\n\t"
  43332. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  43333. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  43334. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  43335. "SBCS r3, r3, r7\n\t"
  43336. "SBCS r4, r4, r8\n\t"
  43337. "SBCS r5, r5, r9\n\t"
  43338. "SBCS r6, r6, r10\n\t"
  43339. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  43340. "SBC %[r], r6, r6\n\t"
  43341. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  43342. :
  43343. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  43344. );
  43345. return (uint32_t)(size_t)r;
  43346. }
  43347. #endif /* WOLFSSL_SP_SMALL */
  43348. #ifdef WOLFSSL_SP_SMALL
  43349. /* Conditionally add a and b using the mask m.
  43350. * m is -1 to add and 0 when not.
  43351. *
  43352. * r A single precision number representing conditional add result.
  43353. * a A single precision number to add with.
  43354. * b A single precision number to add.
  43355. * m Mask value to apply.
  43356. */
  43357. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43358. static sp_digit sp_384_cond_add_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  43359. #else
  43360. static sp_digit sp_384_cond_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  43361. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43362. {
  43363. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43364. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43365. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43366. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  43367. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  43368. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43369. __asm__ __volatile__ (
  43370. "MOV r5, #0x0\n\t"
  43371. "MOV r8, #0x0\n\t"
  43372. "MOV r4, #0x0\n\t"
  43373. "\n"
  43374. "L_sp_384_cond_add_12_words:\n\t"
  43375. "ADDS r5, r5, #0xffffffff\n\t"
  43376. "LDR r6, [%[a], r4]\n\t"
  43377. "LDR r7, [%[b], r4]\n\t"
  43378. "AND r7, r7, %[m]\n\t"
  43379. "ADCS r6, r6, r7\n\t"
  43380. "ADC r5, r8, r8\n\t"
  43381. "STR r6, [%[r], r4]\n\t"
  43382. "ADD r4, r4, #0x4\n\t"
  43383. "CMP r4, #0x30\n\t"
  43384. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  43385. "BLT L_sp_384_cond_add_12_words\n\t"
  43386. #else
  43387. "BLT.N L_sp_384_cond_add_12_words\n\t"
  43388. #endif
  43389. "MOV %[r], r5\n\t"
  43390. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  43391. :
  43392. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  43393. );
  43394. return (uint32_t)(size_t)r;
  43395. }
  43396. #else
  43397. /* Conditionally add a and b using the mask m.
  43398. * m is -1 to add and 0 when not.
  43399. *
  43400. * r A single precision number representing conditional add result.
  43401. * a A single precision number to add with.
  43402. * b A single precision number to add.
  43403. * m Mask value to apply.
  43404. */
  43405. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43406. static sp_digit sp_384_cond_add_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  43407. #else
  43408. static sp_digit sp_384_cond_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  43409. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43410. {
  43411. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43412. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43413. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43414. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  43415. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  43416. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43417. __asm__ __volatile__ (
  43418. "MOV r10, #0x0\n\t"
  43419. "LDM %[a]!, {r6, r7}\n\t"
  43420. "LDM %[b]!, {r8, r9}\n\t"
  43421. "AND r8, r8, %[m]\n\t"
  43422. "AND r9, r9, %[m]\n\t"
  43423. "ADDS r6, r6, r8\n\t"
  43424. "ADCS r7, r7, r9\n\t"
  43425. "STM %[r]!, {r6, r7}\n\t"
  43426. "LDM %[a]!, {r6, r7}\n\t"
  43427. "LDM %[b]!, {r8, r9}\n\t"
  43428. "AND r8, r8, %[m]\n\t"
  43429. "AND r9, r9, %[m]\n\t"
  43430. "ADCS r6, r6, r8\n\t"
  43431. "ADCS r7, r7, r9\n\t"
  43432. "STM %[r]!, {r6, r7}\n\t"
  43433. "LDM %[a]!, {r6, r7}\n\t"
  43434. "LDM %[b]!, {r8, r9}\n\t"
  43435. "AND r8, r8, %[m]\n\t"
  43436. "AND r9, r9, %[m]\n\t"
  43437. "ADCS r6, r6, r8\n\t"
  43438. "ADCS r7, r7, r9\n\t"
  43439. "STM %[r]!, {r6, r7}\n\t"
  43440. "LDM %[a]!, {r6, r7}\n\t"
  43441. "LDM %[b]!, {r8, r9}\n\t"
  43442. "AND r8, r8, %[m]\n\t"
  43443. "AND r9, r9, %[m]\n\t"
  43444. "ADCS r6, r6, r8\n\t"
  43445. "ADCS r7, r7, r9\n\t"
  43446. "STM %[r]!, {r6, r7}\n\t"
  43447. "LDM %[a]!, {r6, r7}\n\t"
  43448. "LDM %[b]!, {r8, r9}\n\t"
  43449. "AND r8, r8, %[m]\n\t"
  43450. "AND r9, r9, %[m]\n\t"
  43451. "ADCS r6, r6, r8\n\t"
  43452. "ADCS r7, r7, r9\n\t"
  43453. "STM %[r]!, {r6, r7}\n\t"
  43454. "LDM %[a]!, {r6, r7}\n\t"
  43455. "LDM %[b]!, {r8, r9}\n\t"
  43456. "AND r8, r8, %[m]\n\t"
  43457. "AND r9, r9, %[m]\n\t"
  43458. "ADCS r6, r6, r8\n\t"
  43459. "ADCS r7, r7, r9\n\t"
  43460. "STM %[r]!, {r6, r7}\n\t"
  43461. "ADC %[r], r10, r10\n\t"
  43462. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  43463. :
  43464. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  43465. );
  43466. return (uint32_t)(size_t)r;
  43467. }
  43468. #endif /* WOLFSSL_SP_SMALL */
  43469. /* Subtract two Montgomery form numbers (r = a - b % m).
  43470. *
  43471. * r Result of subtration.
  43472. * a Number to subtract from in Montgomery form.
  43473. * b Number to subtract with in Montgomery form.
  43474. * m Modulus (prime).
  43475. */
  43476. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43477. SP_NOINLINE static void sp_384_mont_sub_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  43478. #else
  43479. SP_NOINLINE static void sp_384_mont_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  43480. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43481. {
  43482. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43483. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43484. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43485. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  43486. register const sp_digit* m __asm__ ("r3") = (const sp_digit*)m_p;
  43487. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43488. sp_digit o;
  43489. o = sp_384_sub_12(r, a, b);
  43490. sp_384_cond_add_12(r, r, m, o);
  43491. }
  43492. #ifdef WOLFSSL_SP_SMALL
  43493. #else
  43494. #endif /* WOLFSSL_SP_SMALL */
  43495. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43496. static void sp_384_rshift1_12(sp_digit* r_p, const sp_digit* a_p)
  43497. #else
  43498. static void sp_384_rshift1_12(sp_digit* r, const sp_digit* a)
  43499. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43500. {
  43501. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  43502. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  43503. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  43504. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  43505. __asm__ __volatile__ (
  43506. "LDM %[a], {r2, r3}\n\t"
  43507. "LSR r2, r2, #1\n\t"
  43508. "ORR r2, r2, r3, lsl #31\n\t"
  43509. "LSR r3, r3, #1\n\t"
  43510. "LDR r4, [%[a], #8]\n\t"
  43511. "STR r2, [%[r]]\n\t"
  43512. "ORR r3, r3, r4, lsl #31\n\t"
  43513. "LSR r4, r4, #1\n\t"
  43514. "LDR r2, [%[a], #12]\n\t"
  43515. "STR r3, [%[r], #4]\n\t"
  43516. "ORR r4, r4, r2, lsl #31\n\t"
  43517. "LSR r2, r2, #1\n\t"
  43518. "LDR r3, [%[a], #16]\n\t"
  43519. "STR r4, [%[r], #8]\n\t"
  43520. "ORR r2, r2, r3, lsl #31\n\t"
  43521. "LSR r3, r3, #1\n\t"
  43522. "LDR r4, [%[a], #20]\n\t"
  43523. "STR r2, [%[r], #12]\n\t"
  43524. "ORR r3, r3, r4, lsl #31\n\t"
  43525. "LSR r4, r4, #1\n\t"
  43526. "LDR r2, [%[a], #24]\n\t"
  43527. "STR r3, [%[r], #16]\n\t"
  43528. "ORR r4, r4, r2, lsl #31\n\t"
  43529. "LSR r2, r2, #1\n\t"
  43530. "LDR r3, [%[a], #28]\n\t"
  43531. "STR r4, [%[r], #20]\n\t"
  43532. "ORR r2, r2, r3, lsl #31\n\t"
  43533. "LSR r3, r3, #1\n\t"
  43534. "LDR r4, [%[a], #32]\n\t"
  43535. "STR r2, [%[r], #24]\n\t"
  43536. "ORR r3, r3, r4, lsl #31\n\t"
  43537. "LSR r4, r4, #1\n\t"
  43538. "LDR r2, [%[a], #36]\n\t"
  43539. "STR r3, [%[r], #28]\n\t"
  43540. "ORR r4, r4, r2, lsl #31\n\t"
  43541. "LSR r2, r2, #1\n\t"
  43542. "LDR r3, [%[a], #40]\n\t"
  43543. "STR r4, [%[r], #32]\n\t"
  43544. "ORR r2, r2, r3, lsl #31\n\t"
  43545. "LSR r3, r3, #1\n\t"
  43546. "LDR r4, [%[a], #44]\n\t"
  43547. "STR r2, [%[r], #36]\n\t"
  43548. "ORR r3, r3, r4, lsl #31\n\t"
  43549. "LSR r4, r4, #1\n\t"
  43550. "STR r3, [%[r], #40]\n\t"
  43551. "STR r4, [%[r], #44]\n\t"
  43552. : [r] "+r" (r), [a] "+r" (a)
  43553. :
  43554. : "memory", "r2", "r3", "r4", "cc"
  43555. );
  43556. }
  43557. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  43558. *
  43559. * r Result of division by 2.
  43560. * a Number to divide.
  43561. * m Modulus (prime).
  43562. */
  43563. static void sp_384_mont_div2_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
  43564. {
  43565. sp_digit o;
  43566. o = sp_384_cond_add_12(r, a, m, 0 - (a[0] & 1));
  43567. sp_384_rshift1_12(r, r);
  43568. r[11] |= o << 31;
  43569. }
  43570. /* Double the Montgomery form projective point p.
  43571. *
  43572. * r Result of doubling point.
  43573. * p Point to double.
  43574. * t Temporary ordinate data.
  43575. */
  43576. static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p,
  43577. sp_digit* t)
  43578. {
  43579. sp_digit* t1 = t;
  43580. sp_digit* t2 = t + 2*12;
  43581. sp_digit* x;
  43582. sp_digit* y;
  43583. sp_digit* z;
  43584. x = r->x;
  43585. y = r->y;
  43586. z = r->z;
  43587. /* Put infinity into result. */
  43588. if (r != p) {
  43589. r->infinity = p->infinity;
  43590. }
  43591. /* T1 = Z * Z */
  43592. sp_384_mont_sqr_12(t1, p->z, p384_mod, p384_mp_mod);
  43593. /* Z = Y * Z */
  43594. sp_384_mont_mul_12(z, p->y, p->z, p384_mod, p384_mp_mod);
  43595. /* Z = 2Z */
  43596. sp_384_mont_dbl_12(z, z, p384_mod);
  43597. /* T2 = X - T1 */
  43598. sp_384_mont_sub_12(t2, p->x, t1, p384_mod);
  43599. /* T1 = X + T1 */
  43600. sp_384_mont_add_12(t1, p->x, t1, p384_mod);
  43601. /* T2 = T1 * T2 */
  43602. sp_384_mont_mul_12(t2, t1, t2, p384_mod, p384_mp_mod);
  43603. /* T1 = 3T2 */
  43604. sp_384_mont_tpl_12(t1, t2, p384_mod);
  43605. /* Y = 2Y */
  43606. sp_384_mont_dbl_12(y, p->y, p384_mod);
  43607. /* Y = Y * Y */
  43608. sp_384_mont_sqr_12(y, y, p384_mod, p384_mp_mod);
  43609. /* T2 = Y * Y */
  43610. sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod);
  43611. /* T2 = T2/2 */
  43612. sp_384_mont_div2_12(t2, t2, p384_mod);
  43613. /* Y = Y * X */
  43614. sp_384_mont_mul_12(y, y, p->x, p384_mod, p384_mp_mod);
  43615. /* X = T1 * T1 */
  43616. sp_384_mont_sqr_12(x, t1, p384_mod, p384_mp_mod);
  43617. /* X = X - Y */
  43618. sp_384_mont_sub_12(x, x, y, p384_mod);
  43619. /* X = X - Y */
  43620. sp_384_mont_sub_12(x, x, y, p384_mod);
  43621. /* Y = Y - X */
  43622. sp_384_mont_sub_12(y, y, x, p384_mod);
  43623. /* Y = Y * T1 */
  43624. sp_384_mont_mul_12(y, y, t1, p384_mod, p384_mp_mod);
  43625. /* Y = Y - T2 */
  43626. sp_384_mont_sub_12(y, y, t2, p384_mod);
  43627. }
  43628. #ifdef WOLFSSL_SP_NONBLOCK
  43629. typedef struct sp_384_proj_point_dbl_12_ctx {
  43630. int state;
  43631. sp_digit* t1;
  43632. sp_digit* t2;
  43633. sp_digit* x;
  43634. sp_digit* y;
  43635. sp_digit* z;
  43636. } sp_384_proj_point_dbl_12_ctx;
  43637. /* Double the Montgomery form projective point p.
  43638. *
  43639. * r Result of doubling point.
  43640. * p Point to double.
  43641. * t Temporary ordinate data.
  43642. */
  43643. static int sp_384_proj_point_dbl_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
  43644. const sp_point_384* p, sp_digit* t)
  43645. {
  43646. int err = FP_WOULDBLOCK;
  43647. sp_384_proj_point_dbl_12_ctx* ctx = (sp_384_proj_point_dbl_12_ctx*)sp_ctx->data;
  43648. typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  43649. (void)sizeof(ctx_size_test);
  43650. switch (ctx->state) {
  43651. case 0:
  43652. ctx->t1 = t;
  43653. ctx->t2 = t + 2*12;
  43654. ctx->x = r->x;
  43655. ctx->y = r->y;
  43656. ctx->z = r->z;
  43657. /* Put infinity into result. */
  43658. if (r != p) {
  43659. r->infinity = p->infinity;
  43660. }
  43661. ctx->state = 1;
  43662. break;
  43663. case 1:
  43664. /* T1 = Z * Z */
  43665. sp_384_mont_sqr_12(ctx->t1, p->z, p384_mod, p384_mp_mod);
  43666. ctx->state = 2;
  43667. break;
  43668. case 2:
  43669. /* Z = Y * Z */
  43670. sp_384_mont_mul_12(ctx->z, p->y, p->z, p384_mod, p384_mp_mod);
  43671. ctx->state = 3;
  43672. break;
  43673. case 3:
  43674. /* Z = 2Z */
  43675. sp_384_mont_dbl_12(ctx->z, ctx->z, p384_mod);
  43676. ctx->state = 4;
  43677. break;
  43678. case 4:
  43679. /* T2 = X - T1 */
  43680. sp_384_mont_sub_12(ctx->t2, p->x, ctx->t1, p384_mod);
  43681. ctx->state = 5;
  43682. break;
  43683. case 5:
  43684. /* T1 = X + T1 */
  43685. sp_384_mont_add_12(ctx->t1, p->x, ctx->t1, p384_mod);
  43686. ctx->state = 6;
  43687. break;
  43688. case 6:
  43689. /* T2 = T1 * T2 */
  43690. sp_384_mont_mul_12(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod);
  43691. ctx->state = 7;
  43692. break;
  43693. case 7:
  43694. /* T1 = 3T2 */
  43695. sp_384_mont_tpl_12(ctx->t1, ctx->t2, p384_mod);
  43696. ctx->state = 8;
  43697. break;
  43698. case 8:
  43699. /* Y = 2Y */
  43700. sp_384_mont_dbl_12(ctx->y, p->y, p384_mod);
  43701. ctx->state = 9;
  43702. break;
  43703. case 9:
  43704. /* Y = Y * Y */
  43705. sp_384_mont_sqr_12(ctx->y, ctx->y, p384_mod, p384_mp_mod);
  43706. ctx->state = 10;
  43707. break;
  43708. case 10:
  43709. /* T2 = Y * Y */
  43710. sp_384_mont_sqr_12(ctx->t2, ctx->y, p384_mod, p384_mp_mod);
  43711. ctx->state = 11;
  43712. break;
  43713. case 11:
  43714. /* T2 = T2/2 */
  43715. sp_384_mont_div2_12(ctx->t2, ctx->t2, p384_mod);
  43716. ctx->state = 12;
  43717. break;
  43718. case 12:
  43719. /* Y = Y * X */
  43720. sp_384_mont_mul_12(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod);
  43721. ctx->state = 13;
  43722. break;
  43723. case 13:
  43724. /* X = T1 * T1 */
  43725. sp_384_mont_sqr_12(ctx->x, ctx->t1, p384_mod, p384_mp_mod);
  43726. ctx->state = 14;
  43727. break;
  43728. case 14:
  43729. /* X = X - Y */
  43730. sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod);
  43731. ctx->state = 15;
  43732. break;
  43733. case 15:
  43734. /* X = X - Y */
  43735. sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod);
  43736. ctx->state = 16;
  43737. break;
  43738. case 16:
  43739. /* Y = Y - X */
  43740. sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod);
  43741. ctx->state = 17;
  43742. break;
  43743. case 17:
  43744. /* Y = Y * T1 */
  43745. sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod);
  43746. ctx->state = 18;
  43747. break;
  43748. case 18:
  43749. /* Y = Y - T2 */
  43750. sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t2, p384_mod);
  43751. ctx->state = 19;
  43752. /* fall-through */
  43753. case 19:
  43754. err = MP_OKAY;
  43755. break;
  43756. }
  43757. if (err == MP_OKAY && ctx->state != 19) {
  43758. err = FP_WOULDBLOCK;
  43759. }
  43760. return err;
  43761. }
  43762. #endif /* WOLFSSL_SP_NONBLOCK */
  43763. /* Compare two numbers to determine if they are equal.
  43764. * Constant time implementation.
  43765. *
  43766. * a First number to compare.
  43767. * b Second number to compare.
  43768. * returns 1 when equal and 0 otherwise.
  43769. */
  43770. static int sp_384_cmp_equal_12(const sp_digit* a, const sp_digit* b)
  43771. {
  43772. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  43773. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  43774. (a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
  43775. (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11])) == 0;
  43776. }
  43777. /* Returns 1 if the number of zero.
  43778. * Implementation is constant time.
  43779. *
  43780. * a Number to check.
  43781. * returns 1 if the number is zero and 0 otherwise.
  43782. */
  43783. static int sp_384_iszero_12(const sp_digit* a)
  43784. {
  43785. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
  43786. a[8] | a[9] | a[10] | a[11]) == 0;
  43787. }
  43788. /* Add two Montgomery form projective points.
  43789. *
  43790. * r Result of addition.
  43791. * p First point to add.
  43792. * q Second point to add.
  43793. * t Temporary ordinate data.
  43794. */
  43795. static void sp_384_proj_point_add_12(sp_point_384* r,
  43796. const sp_point_384* p, const sp_point_384* q, sp_digit* t)
  43797. {
  43798. sp_digit* t6 = t;
  43799. sp_digit* t1 = t + 2*12;
  43800. sp_digit* t2 = t + 4*12;
  43801. sp_digit* t3 = t + 6*12;
  43802. sp_digit* t4 = t + 8*12;
  43803. sp_digit* t5 = t + 10*12;
  43804. /* U1 = X1*Z2^2 */
  43805. sp_384_mont_sqr_12(t1, q->z, p384_mod, p384_mp_mod);
  43806. sp_384_mont_mul_12(t3, t1, q->z, p384_mod, p384_mp_mod);
  43807. sp_384_mont_mul_12(t1, t1, p->x, p384_mod, p384_mp_mod);
  43808. /* U2 = X2*Z1^2 */
  43809. sp_384_mont_sqr_12(t2, p->z, p384_mod, p384_mp_mod);
  43810. sp_384_mont_mul_12(t4, t2, p->z, p384_mod, p384_mp_mod);
  43811. sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod);
  43812. /* S1 = Y1*Z2^3 */
  43813. sp_384_mont_mul_12(t3, t3, p->y, p384_mod, p384_mp_mod);
  43814. /* S2 = Y2*Z1^3 */
  43815. sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod);
  43816. /* Check double */
  43817. if ((~p->infinity) & (~q->infinity) &
  43818. sp_384_cmp_equal_12(t2, t1) &
  43819. sp_384_cmp_equal_12(t4, t3)) {
  43820. sp_384_proj_point_dbl_12(r, p, t);
  43821. }
  43822. else {
  43823. sp_digit* x = t6;
  43824. sp_digit* y = t1;
  43825. sp_digit* z = t2;
  43826. /* H = U2 - U1 */
  43827. sp_384_mont_sub_12(t2, t2, t1, p384_mod);
  43828. /* R = S2 - S1 */
  43829. sp_384_mont_sub_12(t4, t4, t3, p384_mod);
  43830. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  43831. sp_384_mont_sqr_12(t5, t2, p384_mod, p384_mp_mod);
  43832. sp_384_mont_mul_12(y, t1, t5, p384_mod, p384_mp_mod);
  43833. sp_384_mont_mul_12(t5, t5, t2, p384_mod, p384_mp_mod);
  43834. /* Z3 = H*Z1*Z2 */
  43835. sp_384_mont_mul_12(z, p->z, t2, p384_mod, p384_mp_mod);
  43836. sp_384_mont_mul_12(z, z, q->z, p384_mod, p384_mp_mod);
  43837. sp_384_mont_sqr_12(x, t4, p384_mod, p384_mp_mod);
  43838. sp_384_mont_sub_12(x, x, t5, p384_mod);
  43839. sp_384_mont_mul_12(t5, t5, t3, p384_mod, p384_mp_mod);
  43840. sp_384_mont_dbl_12(t3, y, p384_mod);
  43841. sp_384_mont_sub_12(x, x, t3, p384_mod);
  43842. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  43843. sp_384_mont_sub_12(y, y, x, p384_mod);
  43844. sp_384_mont_mul_12(y, y, t4, p384_mod, p384_mp_mod);
  43845. sp_384_mont_sub_12(y, y, t5, p384_mod);
  43846. {
  43847. int i;
  43848. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  43849. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  43850. sp_digit maskt = ~(maskp | maskq);
  43851. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  43852. for (i = 0; i < 12; i++) {
  43853. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  43854. (x[i] & maskt);
  43855. }
  43856. for (i = 0; i < 12; i++) {
  43857. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  43858. (y[i] & maskt);
  43859. }
  43860. for (i = 0; i < 12; i++) {
  43861. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  43862. (z[i] & maskt);
  43863. }
  43864. r->z[0] |= inf;
  43865. r->infinity = (word32)inf;
  43866. }
  43867. }
  43868. }
  43869. #ifdef WOLFSSL_SP_NONBLOCK
  43870. typedef struct sp_384_proj_point_add_12_ctx {
  43871. int state;
  43872. sp_384_proj_point_dbl_12_ctx dbl_ctx;
  43873. const sp_point_384* ap[2];
  43874. sp_point_384* rp[2];
  43875. sp_digit* t1;
  43876. sp_digit* t2;
  43877. sp_digit* t3;
  43878. sp_digit* t4;
  43879. sp_digit* t5;
  43880. sp_digit* t6;
  43881. sp_digit* x;
  43882. sp_digit* y;
  43883. sp_digit* z;
  43884. } sp_384_proj_point_add_12_ctx;
  43885. /* Add two Montgomery form projective points.
  43886. *
  43887. * r Result of addition.
  43888. * p First point to add.
  43889. * q Second point to add.
  43890. * t Temporary ordinate data.
  43891. */
  43892. static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
  43893. const sp_point_384* p, const sp_point_384* q, sp_digit* t)
  43894. {
  43895. int err = FP_WOULDBLOCK;
  43896. sp_384_proj_point_add_12_ctx* ctx = (sp_384_proj_point_add_12_ctx*)sp_ctx->data;
  43897. /* Ensure only the first point is the same as the result. */
  43898. if (q == r) {
  43899. const sp_point_384* a = p;
  43900. p = q;
  43901. q = a;
  43902. }
  43903. typedef char ctx_size_test[sizeof(sp_384_proj_point_add_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  43904. (void)sizeof(ctx_size_test);
  43905. switch (ctx->state) {
  43906. case 0: /* INIT */
  43907. ctx->t6 = t;
  43908. ctx->t1 = t + 2*12;
  43909. ctx->t2 = t + 4*12;
  43910. ctx->t3 = t + 6*12;
  43911. ctx->t4 = t + 8*12;
  43912. ctx->t5 = t + 10*12;
  43913. ctx->x = ctx->t6;
  43914. ctx->y = ctx->t1;
  43915. ctx->z = ctx->t2;
  43916. ctx->state = 1;
  43917. break;
  43918. case 1:
  43919. /* U1 = X1*Z2^2 */
  43920. sp_384_mont_sqr_12(ctx->t1, q->z, p384_mod, p384_mp_mod);
  43921. ctx->state = 2;
  43922. break;
  43923. case 2:
  43924. sp_384_mont_mul_12(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod);
  43925. ctx->state = 3;
  43926. break;
  43927. case 3:
  43928. sp_384_mont_mul_12(ctx->t1, ctx->t1, p->x, p384_mod, p384_mp_mod);
  43929. ctx->state = 4;
  43930. break;
  43931. case 4:
  43932. /* U2 = X2*Z1^2 */
  43933. sp_384_mont_sqr_12(ctx->t2, p->z, p384_mod, p384_mp_mod);
  43934. ctx->state = 5;
  43935. break;
  43936. case 5:
  43937. sp_384_mont_mul_12(ctx->t4, ctx->t2, p->z, p384_mod, p384_mp_mod);
  43938. ctx->state = 6;
  43939. break;
  43940. case 6:
  43941. sp_384_mont_mul_12(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod);
  43942. ctx->state = 7;
  43943. break;
  43944. case 7:
  43945. /* S1 = Y1*Z2^3 */
  43946. sp_384_mont_mul_12(ctx->t3, ctx->t3, p->y, p384_mod, p384_mp_mod);
  43947. ctx->state = 8;
  43948. break;
  43949. case 8:
  43950. /* S2 = Y2*Z1^3 */
  43951. sp_384_mont_mul_12(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod);
  43952. ctx->state = 9;
  43953. break;
  43954. case 9:
  43955. /* Check double */
  43956. if ((~p->infinity) & (~q->infinity) &
  43957. sp_384_cmp_equal_12(ctx->t2, ctx->t1) &
  43958. sp_384_cmp_equal_12(ctx->t4, ctx->t3)) {
  43959. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  43960. sp_384_proj_point_dbl_12(r, p, t);
  43961. ctx->state = 25;
  43962. }
  43963. else {
  43964. ctx->state = 10;
  43965. }
  43966. break;
  43967. case 10:
  43968. /* H = U2 - U1 */
  43969. sp_384_mont_sub_12(ctx->t2, ctx->t2, ctx->t1, p384_mod);
  43970. ctx->state = 11;
  43971. break;
  43972. case 11:
  43973. /* R = S2 - S1 */
  43974. sp_384_mont_sub_12(ctx->t4, ctx->t4, ctx->t3, p384_mod);
  43975. ctx->state = 12;
  43976. break;
  43977. case 12:
  43978. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  43979. sp_384_mont_sqr_12(ctx->t5, ctx->t2, p384_mod, p384_mp_mod);
  43980. ctx->state = 13;
  43981. break;
  43982. case 13:
  43983. sp_384_mont_mul_12(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod);
  43984. ctx->state = 14;
  43985. break;
  43986. case 14:
  43987. sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod);
  43988. ctx->state = 15;
  43989. break;
  43990. case 15:
  43991. /* Z3 = H*Z1*Z2 */
  43992. sp_384_mont_mul_12(ctx->z, p->z, ctx->t2, p384_mod, p384_mp_mod);
  43993. ctx->state = 16;
  43994. break;
  43995. case 16:
  43996. sp_384_mont_mul_12(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod);
  43997. ctx->state = 17;
  43998. break;
  43999. case 17:
  44000. sp_384_mont_sqr_12(ctx->x, ctx->t4, p384_mod, p384_mp_mod);
  44001. ctx->state = 18;
  44002. break;
  44003. case 18:
  44004. sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t5, p384_mod);
  44005. ctx->state = 19;
  44006. break;
  44007. case 19:
  44008. sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod);
  44009. ctx->state = 20;
  44010. break;
  44011. case 20:
  44012. sp_384_mont_dbl_12(ctx->t3, ctx->y, p384_mod);
  44013. sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t3, p384_mod);
  44014. ctx->state = 21;
  44015. break;
  44016. case 21:
  44017. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  44018. sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod);
  44019. ctx->state = 22;
  44020. break;
  44021. case 22:
  44022. sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod);
  44023. ctx->state = 23;
  44024. break;
  44025. case 23:
  44026. sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t5, p384_mod);
  44027. ctx->state = 24;
  44028. break;
  44029. case 24:
  44030. {
  44031. {
  44032. int i;
  44033. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  44034. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  44035. sp_digit maskt = ~(maskp | maskq);
  44036. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  44037. for (i = 0; i < 12; i++) {
  44038. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  44039. (ctx->x[i] & maskt);
  44040. }
  44041. for (i = 0; i < 12; i++) {
  44042. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  44043. (ctx->y[i] & maskt);
  44044. }
  44045. for (i = 0; i < 12; i++) {
  44046. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  44047. (ctx->z[i] & maskt);
  44048. }
  44049. r->z[0] |= inf;
  44050. r->infinity = (word32)inf;
  44051. }
  44052. ctx->state = 25;
  44053. break;
  44054. }
  44055. case 25:
  44056. err = MP_OKAY;
  44057. break;
  44058. }
  44059. if (err == MP_OKAY && ctx->state != 25) {
  44060. err = FP_WOULDBLOCK;
  44061. }
  44062. return err;
  44063. }
  44064. #endif /* WOLFSSL_SP_NONBLOCK */
  44065. #ifndef WC_NO_CACHE_RESISTANT
  44066. /* Touch each possible point that could be being copied.
  44067. *
  44068. * r Point to copy into.
  44069. * table Table - start of the entries to access
  44070. * idx Index of entry to retrieve.
  44071. */
  44072. static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table,
  44073. int idx)
  44074. {
  44075. int i;
  44076. sp_digit mask;
  44077. r->x[0] = 0;
  44078. r->x[1] = 0;
  44079. r->x[2] = 0;
  44080. r->x[3] = 0;
  44081. r->x[4] = 0;
  44082. r->x[5] = 0;
  44083. r->x[6] = 0;
  44084. r->x[7] = 0;
  44085. r->x[8] = 0;
  44086. r->x[9] = 0;
  44087. r->x[10] = 0;
  44088. r->x[11] = 0;
  44089. r->y[0] = 0;
  44090. r->y[1] = 0;
  44091. r->y[2] = 0;
  44092. r->y[3] = 0;
  44093. r->y[4] = 0;
  44094. r->y[5] = 0;
  44095. r->y[6] = 0;
  44096. r->y[7] = 0;
  44097. r->y[8] = 0;
  44098. r->y[9] = 0;
  44099. r->y[10] = 0;
  44100. r->y[11] = 0;
  44101. r->z[0] = 0;
  44102. r->z[1] = 0;
  44103. r->z[2] = 0;
  44104. r->z[3] = 0;
  44105. r->z[4] = 0;
  44106. r->z[5] = 0;
  44107. r->z[6] = 0;
  44108. r->z[7] = 0;
  44109. r->z[8] = 0;
  44110. r->z[9] = 0;
  44111. r->z[10] = 0;
  44112. r->z[11] = 0;
  44113. for (i = 1; i < 16; i++) {
  44114. mask = 0 - (i == idx);
  44115. r->x[0] |= mask & table[i].x[0];
  44116. r->x[1] |= mask & table[i].x[1];
  44117. r->x[2] |= mask & table[i].x[2];
  44118. r->x[3] |= mask & table[i].x[3];
  44119. r->x[4] |= mask & table[i].x[4];
  44120. r->x[5] |= mask & table[i].x[5];
  44121. r->x[6] |= mask & table[i].x[6];
  44122. r->x[7] |= mask & table[i].x[7];
  44123. r->x[8] |= mask & table[i].x[8];
  44124. r->x[9] |= mask & table[i].x[9];
  44125. r->x[10] |= mask & table[i].x[10];
  44126. r->x[11] |= mask & table[i].x[11];
  44127. r->y[0] |= mask & table[i].y[0];
  44128. r->y[1] |= mask & table[i].y[1];
  44129. r->y[2] |= mask & table[i].y[2];
  44130. r->y[3] |= mask & table[i].y[3];
  44131. r->y[4] |= mask & table[i].y[4];
  44132. r->y[5] |= mask & table[i].y[5];
  44133. r->y[6] |= mask & table[i].y[6];
  44134. r->y[7] |= mask & table[i].y[7];
  44135. r->y[8] |= mask & table[i].y[8];
  44136. r->y[9] |= mask & table[i].y[9];
  44137. r->y[10] |= mask & table[i].y[10];
  44138. r->y[11] |= mask & table[i].y[11];
  44139. r->z[0] |= mask & table[i].z[0];
  44140. r->z[1] |= mask & table[i].z[1];
  44141. r->z[2] |= mask & table[i].z[2];
  44142. r->z[3] |= mask & table[i].z[3];
  44143. r->z[4] |= mask & table[i].z[4];
  44144. r->z[5] |= mask & table[i].z[5];
  44145. r->z[6] |= mask & table[i].z[6];
  44146. r->z[7] |= mask & table[i].z[7];
  44147. r->z[8] |= mask & table[i].z[8];
  44148. r->z[9] |= mask & table[i].z[9];
  44149. r->z[10] |= mask & table[i].z[10];
  44150. r->z[11] |= mask & table[i].z[11];
  44151. }
  44152. }
  44153. #endif /* !WC_NO_CACHE_RESISTANT */
  44154. /* Multiply the point by the scalar and return the result.
  44155. * If map is true then convert result to affine coordinates.
  44156. *
  44157. * Fast implementation that generates a pre-computation table.
  44158. * 4 bits of window (no sliding!).
  44159. * Uses add and double for calculating table.
  44160. * 384 doubles.
  44161. * 108 adds.
  44162. *
  44163. * r Resulting point.
  44164. * g Point to multiply.
  44165. * k Scalar to multiply by.
  44166. * map Indicates whether to convert result to affine.
  44167. * ct Constant time required.
  44168. * heap Heap to use for allocation.
  44169. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  44170. */
  44171. static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k,
  44172. int map, int ct, void* heap)
  44173. {
  44174. #ifdef WOLFSSL_SP_SMALL_STACK
  44175. sp_point_384* t = NULL;
  44176. sp_digit* tmp = NULL;
  44177. #else
  44178. sp_point_384 t[16 + 1];
  44179. sp_digit tmp[2 * 12 * 6];
  44180. #endif
  44181. sp_point_384* rt = NULL;
  44182. #ifndef WC_NO_CACHE_RESISTANT
  44183. #ifdef WOLFSSL_SP_SMALL_STACK
  44184. sp_point_384* p = NULL;
  44185. #else
  44186. sp_point_384 p[1];
  44187. #endif
  44188. #endif /* !WC_NO_CACHE_RESISTANT */
  44189. sp_digit n;
  44190. int i;
  44191. int c;
  44192. int y;
  44193. int err = MP_OKAY;
  44194. /* Constant time used for cache attack resistance implementation. */
  44195. (void)ct;
  44196. (void)heap;
  44197. #ifdef WOLFSSL_SP_SMALL_STACK
  44198. t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * (16 + 1),
  44199. heap, DYNAMIC_TYPE_ECC);
  44200. if (t == NULL)
  44201. err = MEMORY_E;
  44202. #ifndef WC_NO_CACHE_RESISTANT
  44203. if (err == MP_OKAY) {
  44204. p = (sp_point_384*)XMALLOC(sizeof(sp_point_384),
  44205. heap, DYNAMIC_TYPE_ECC);
  44206. if (p == NULL)
  44207. err = MEMORY_E;
  44208. }
  44209. #endif
  44210. if (err == MP_OKAY) {
  44211. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap,
  44212. DYNAMIC_TYPE_ECC);
  44213. if (tmp == NULL)
  44214. err = MEMORY_E;
  44215. }
  44216. #endif
  44217. if (err == MP_OKAY) {
  44218. rt = t + 16;
  44219. /* t[0] = {0, 0, 1} * norm */
  44220. XMEMSET(&t[0], 0, sizeof(t[0]));
  44221. t[0].infinity = 1;
  44222. /* t[1] = {g->x, g->y, g->z} * norm */
  44223. (void)sp_384_mod_mul_norm_12(t[1].x, g->x, p384_mod);
  44224. (void)sp_384_mod_mul_norm_12(t[1].y, g->y, p384_mod);
  44225. (void)sp_384_mod_mul_norm_12(t[1].z, g->z, p384_mod);
  44226. t[1].infinity = 0;
  44227. sp_384_proj_point_dbl_12(&t[ 2], &t[ 1], tmp);
  44228. t[ 2].infinity = 0;
  44229. sp_384_proj_point_add_12(&t[ 3], &t[ 2], &t[ 1], tmp);
  44230. t[ 3].infinity = 0;
  44231. sp_384_proj_point_dbl_12(&t[ 4], &t[ 2], tmp);
  44232. t[ 4].infinity = 0;
  44233. sp_384_proj_point_add_12(&t[ 5], &t[ 3], &t[ 2], tmp);
  44234. t[ 5].infinity = 0;
  44235. sp_384_proj_point_dbl_12(&t[ 6], &t[ 3], tmp);
  44236. t[ 6].infinity = 0;
  44237. sp_384_proj_point_add_12(&t[ 7], &t[ 4], &t[ 3], tmp);
  44238. t[ 7].infinity = 0;
  44239. sp_384_proj_point_dbl_12(&t[ 8], &t[ 4], tmp);
  44240. t[ 8].infinity = 0;
  44241. sp_384_proj_point_add_12(&t[ 9], &t[ 5], &t[ 4], tmp);
  44242. t[ 9].infinity = 0;
  44243. sp_384_proj_point_dbl_12(&t[10], &t[ 5], tmp);
  44244. t[10].infinity = 0;
  44245. sp_384_proj_point_add_12(&t[11], &t[ 6], &t[ 5], tmp);
  44246. t[11].infinity = 0;
  44247. sp_384_proj_point_dbl_12(&t[12], &t[ 6], tmp);
  44248. t[12].infinity = 0;
  44249. sp_384_proj_point_add_12(&t[13], &t[ 7], &t[ 6], tmp);
  44250. t[13].infinity = 0;
  44251. sp_384_proj_point_dbl_12(&t[14], &t[ 7], tmp);
  44252. t[14].infinity = 0;
  44253. sp_384_proj_point_add_12(&t[15], &t[ 8], &t[ 7], tmp);
  44254. t[15].infinity = 0;
  44255. i = 10;
  44256. n = k[i+1] << 0;
  44257. c = 28;
  44258. y = (int)(n >> 28);
  44259. #ifndef WC_NO_CACHE_RESISTANT
  44260. if (ct) {
  44261. sp_384_get_point_16_12(rt, t, y);
  44262. rt->infinity = !y;
  44263. }
  44264. else
  44265. #endif
  44266. {
  44267. XMEMCPY(rt, &t[y], sizeof(sp_point_384));
  44268. }
  44269. n <<= 4;
  44270. for (; i>=0 || c>=4; ) {
  44271. if (c < 4) {
  44272. n |= k[i--];
  44273. c += 32;
  44274. }
  44275. y = (n >> 28) & 0xf;
  44276. n <<= 4;
  44277. c -= 4;
  44278. sp_384_proj_point_dbl_12(rt, rt, tmp);
  44279. sp_384_proj_point_dbl_12(rt, rt, tmp);
  44280. sp_384_proj_point_dbl_12(rt, rt, tmp);
  44281. sp_384_proj_point_dbl_12(rt, rt, tmp);
  44282. #ifndef WC_NO_CACHE_RESISTANT
  44283. if (ct) {
  44284. sp_384_get_point_16_12(p, t, y);
  44285. p->infinity = !y;
  44286. sp_384_proj_point_add_12(rt, rt, p, tmp);
  44287. }
  44288. else
  44289. #endif
  44290. {
  44291. sp_384_proj_point_add_12(rt, rt, &t[y], tmp);
  44292. }
  44293. }
  44294. if (map != 0) {
  44295. sp_384_map_12(r, rt, tmp);
  44296. }
  44297. else {
  44298. XMEMCPY(r, rt, sizeof(sp_point_384));
  44299. }
  44300. }
  44301. #ifdef WOLFSSL_SP_SMALL_STACK
  44302. if (tmp != NULL)
  44303. #endif
  44304. {
  44305. ForceZero(tmp, sizeof(sp_digit) * 2 * 12 * 6);
  44306. #ifdef WOLFSSL_SP_SMALL_STACK
  44307. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  44308. #endif
  44309. }
  44310. #ifndef WC_NO_CACHE_RESISTANT
  44311. #ifdef WOLFSSL_SP_SMALL_STACK
  44312. if (p != NULL)
  44313. #endif
  44314. {
  44315. ForceZero(p, sizeof(sp_point_384));
  44316. #ifdef WOLFSSL_SP_SMALL_STACK
  44317. XFREE(p, heap, DYNAMIC_TYPE_ECC);
  44318. #endif
  44319. }
  44320. #endif /* !WC_NO_CACHE_RESISTANT */
  44321. #ifdef WOLFSSL_SP_SMALL_STACK
  44322. if (t != NULL)
  44323. #endif
  44324. {
  44325. ForceZero(t, sizeof(sp_point_384) * 17);
  44326. #ifdef WOLFSSL_SP_SMALL_STACK
  44327. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  44328. #endif
  44329. }
  44330. return err;
  44331. }
  44332. #ifdef FP_ECC
  44333. /* Double the Montgomery form projective point p a number of times.
  44334. *
  44335. * r Result of repeated doubling of point.
  44336. * p Point to double.
  44337. * n Number of times to double
  44338. * t Temporary ordinate data.
  44339. */
  44340. static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int i,
  44341. sp_digit* t)
  44342. {
  44343. sp_digit* w = t;
  44344. sp_digit* a = t + 2*12;
  44345. sp_digit* b = t + 4*12;
  44346. sp_digit* t1 = t + 6*12;
  44347. sp_digit* t2 = t + 8*12;
  44348. sp_digit* x;
  44349. sp_digit* y;
  44350. sp_digit* z;
  44351. volatile int n = i;
  44352. x = p->x;
  44353. y = p->y;
  44354. z = p->z;
  44355. /* Y = 2*Y */
  44356. sp_384_mont_dbl_12(y, y, p384_mod);
  44357. /* W = Z^4 */
  44358. sp_384_mont_sqr_12(w, z, p384_mod, p384_mp_mod);
  44359. sp_384_mont_sqr_12(w, w, p384_mod, p384_mp_mod);
  44360. #ifndef WOLFSSL_SP_SMALL
  44361. while (--n > 0)
  44362. #else
  44363. while (--n >= 0)
  44364. #endif
  44365. {
  44366. /* A = 3*(X^2 - W) */
  44367. sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod);
  44368. sp_384_mont_sub_12(t1, t1, w, p384_mod);
  44369. sp_384_mont_tpl_12(a, t1, p384_mod);
  44370. /* B = X*Y^2 */
  44371. sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod);
  44372. sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod);
  44373. /* X = A^2 - 2B */
  44374. sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod);
  44375. sp_384_mont_dbl_12(t2, b, p384_mod);
  44376. sp_384_mont_sub_12(x, x, t2, p384_mod);
  44377. /* B = 2.(B - X) */
  44378. sp_384_mont_sub_12(t2, b, x, p384_mod);
  44379. sp_384_mont_dbl_12(b, t2, p384_mod);
  44380. /* Z = Z*Y */
  44381. sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod);
  44382. /* t1 = Y^4 */
  44383. sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod);
  44384. #ifdef WOLFSSL_SP_SMALL
  44385. if (n != 0)
  44386. #endif
  44387. {
  44388. /* W = W*Y^4 */
  44389. sp_384_mont_mul_12(w, w, t1, p384_mod, p384_mp_mod);
  44390. }
  44391. /* y = 2*A*(B - X) - Y^4 */
  44392. sp_384_mont_mul_12(y, b, a, p384_mod, p384_mp_mod);
  44393. sp_384_mont_sub_12(y, y, t1, p384_mod);
  44394. }
  44395. #ifndef WOLFSSL_SP_SMALL
  44396. /* A = 3*(X^2 - W) */
  44397. sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod);
  44398. sp_384_mont_sub_12(t1, t1, w, p384_mod);
  44399. sp_384_mont_tpl_12(a, t1, p384_mod);
  44400. /* B = X*Y^2 */
  44401. sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod);
  44402. sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod);
  44403. /* X = A^2 - 2B */
  44404. sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod);
  44405. sp_384_mont_dbl_12(t2, b, p384_mod);
  44406. sp_384_mont_sub_12(x, x, t2, p384_mod);
  44407. /* B = 2.(B - X) */
  44408. sp_384_mont_sub_12(t2, b, x, p384_mod);
  44409. sp_384_mont_dbl_12(b, t2, p384_mod);
  44410. /* Z = Z*Y */
  44411. sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod);
  44412. /* t1 = Y^4 */
  44413. sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod);
  44414. /* y = 2*A*(B - X) - Y^4 */
  44415. sp_384_mont_mul_12(y, b, a, p384_mod, p384_mp_mod);
  44416. sp_384_mont_sub_12(y, y, t1, p384_mod);
  44417. #endif /* WOLFSSL_SP_SMALL */
  44418. /* Y = Y/2 */
  44419. sp_384_mont_div2_12(y, y, p384_mod);
  44420. }
  44421. /* Convert the projective point to affine.
  44422. * Ordinates are in Montgomery form.
  44423. *
  44424. * a Point to convert.
  44425. * t Temporary data.
  44426. */
  44427. static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t)
  44428. {
  44429. sp_digit* t1 = t;
  44430. sp_digit* t2 = t + 2 * 12;
  44431. sp_digit* tmp = t + 4 * 12;
  44432. sp_384_mont_inv_12(t1, a->z, tmp);
  44433. sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod);
  44434. sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod);
  44435. sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod);
  44436. sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod);
  44437. XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
  44438. }
  44439. #endif /* FP_ECC */
  44440. /* A table entry for pre-computed points. */
  44441. typedef struct sp_table_entry_384 {
  44442. sp_digit x[12];
  44443. sp_digit y[12];
  44444. } sp_table_entry_384;
  44445. #ifdef FP_ECC
  44446. #endif /* FP_ECC */
  44447. /* Add two Montgomery form projective points. The second point has a q value of
  44448. * one.
  44449. * Only the first point can be the same pointer as the result point.
  44450. *
  44451. * r Result of addition.
  44452. * p First point to add.
  44453. * q Second point to add.
  44454. * t Temporary ordinate data.
  44455. */
  44456. static void sp_384_proj_point_add_qz1_12(sp_point_384* r,
  44457. const sp_point_384* p, const sp_point_384* q, sp_digit* t)
  44458. {
  44459. sp_digit* t2 = t;
  44460. sp_digit* t3 = t + 2*12;
  44461. sp_digit* t6 = t + 4*12;
  44462. sp_digit* t1 = t + 6*12;
  44463. sp_digit* t4 = t + 8*12;
  44464. sp_digit* t5 = t + 10*12;
  44465. /* Calculate values to subtract from P->x and P->y. */
  44466. /* U2 = X2*Z1^2 */
  44467. sp_384_mont_sqr_12(t2, p->z, p384_mod, p384_mp_mod);
  44468. sp_384_mont_mul_12(t4, t2, p->z, p384_mod, p384_mp_mod);
  44469. sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod);
  44470. /* S2 = Y2*Z1^3 */
  44471. sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod);
  44472. if ((~p->infinity) & (~q->infinity) &
  44473. sp_384_cmp_equal_12(p->x, t2) &
  44474. sp_384_cmp_equal_12(p->y, t4)) {
  44475. sp_384_proj_point_dbl_12(r, p, t);
  44476. }
  44477. else {
  44478. sp_digit* x = t2;
  44479. sp_digit* y = t3;
  44480. sp_digit* z = t6;
  44481. /* H = U2 - X1 */
  44482. sp_384_mont_sub_12(t2, t2, p->x, p384_mod);
  44483. /* R = S2 - Y1 */
  44484. sp_384_mont_sub_12(t4, t4, p->y, p384_mod);
  44485. /* Z3 = H*Z1 */
  44486. sp_384_mont_mul_12(z, p->z, t2, p384_mod, p384_mp_mod);
  44487. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  44488. sp_384_mont_sqr_12(t1, t2, p384_mod, p384_mp_mod);
  44489. sp_384_mont_mul_12(t3, p->x, t1, p384_mod, p384_mp_mod);
  44490. sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod);
  44491. sp_384_mont_sqr_12(t2, t4, p384_mod, p384_mp_mod);
  44492. sp_384_mont_sub_12(t2, t2, t1, p384_mod);
  44493. sp_384_mont_dbl_12(t5, t3, p384_mod);
  44494. sp_384_mont_sub_12(x, t2, t5, p384_mod);
  44495. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  44496. sp_384_mont_sub_12(t3, t3, x, p384_mod);
  44497. sp_384_mont_mul_12(t3, t3, t4, p384_mod, p384_mp_mod);
  44498. sp_384_mont_mul_12(t1, t1, p->y, p384_mod, p384_mp_mod);
  44499. sp_384_mont_sub_12(y, t3, t1, p384_mod);
  44500. {
  44501. int i;
  44502. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  44503. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  44504. sp_digit maskt = ~(maskp | maskq);
  44505. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  44506. for (i = 0; i < 12; i++) {
  44507. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  44508. (x[i] & maskt);
  44509. }
  44510. for (i = 0; i < 12; i++) {
  44511. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  44512. (y[i] & maskt);
  44513. }
  44514. for (i = 0; i < 12; i++) {
  44515. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  44516. (z[i] & maskt);
  44517. }
  44518. r->z[0] |= inf;
  44519. r->infinity = (word32)inf;
  44520. }
  44521. }
  44522. }
  44523. #ifdef WOLFSSL_SP_SMALL
  44524. #ifdef FP_ECC
  44525. /* Generate the pre-computed table of points for the base point.
  44526. *
  44527. * width = 4
  44528. * 16 entries
  44529. * 96 bits between
  44530. *
  44531. * a The base point.
  44532. * table Place to store generated point data.
  44533. * tmp Temporary data.
  44534. * heap Heap to use for allocation.
  44535. */
  44536. static int sp_384_gen_stripe_table_12(const sp_point_384* a,
  44537. sp_table_entry_384* table, sp_digit* tmp, void* heap)
  44538. {
  44539. #ifdef WOLFSSL_SP_SMALL_STACK
  44540. sp_point_384* t = NULL;
  44541. #else
  44542. sp_point_384 t[3];
  44543. #endif
  44544. sp_point_384* s1 = NULL;
  44545. sp_point_384* s2 = NULL;
  44546. int i;
  44547. int j;
  44548. int err = MP_OKAY;
  44549. (void)heap;
  44550. #ifdef WOLFSSL_SP_SMALL_STACK
  44551. t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap,
  44552. DYNAMIC_TYPE_ECC);
  44553. if (t == NULL)
  44554. err = MEMORY_E;
  44555. #endif
  44556. if (err == MP_OKAY) {
  44557. s1 = t + 1;
  44558. s2 = t + 2;
  44559. err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod);
  44560. }
  44561. if (err == MP_OKAY) {
  44562. err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod);
  44563. }
  44564. if (err == MP_OKAY) {
  44565. err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod);
  44566. }
  44567. if (err == MP_OKAY) {
  44568. t->infinity = 0;
  44569. sp_384_proj_to_affine_12(t, tmp);
  44570. XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod));
  44571. s1->infinity = 0;
  44572. XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod));
  44573. s2->infinity = 0;
  44574. /* table[0] = {0, 0, infinity} */
  44575. XMEMSET(&table[0], 0, sizeof(sp_table_entry_384));
  44576. /* table[1] = Affine version of 'a' in Montgomery form */
  44577. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  44578. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  44579. for (i=1; i<4; i++) {
  44580. sp_384_proj_point_dbl_n_12(t, 96, tmp);
  44581. sp_384_proj_to_affine_12(t, tmp);
  44582. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  44583. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  44584. }
  44585. for (i=1; i<4; i++) {
  44586. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  44587. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  44588. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  44589. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  44590. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  44591. sp_384_proj_point_add_qz1_12(t, s1, s2, tmp);
  44592. sp_384_proj_to_affine_12(t, tmp);
  44593. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  44594. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  44595. }
  44596. }
  44597. }
  44598. #ifdef WOLFSSL_SP_SMALL_STACK
  44599. if (t != NULL)
  44600. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  44601. #endif
  44602. return err;
  44603. }
  44604. #endif /* FP_ECC */
  44605. #ifndef WC_NO_CACHE_RESISTANT
  44606. /* Touch each possible entry that could be being copied.
  44607. *
  44608. * r Point to copy into.
  44609. * table Table - start of the entries to access
  44610. * idx Index of entry to retrieve.
  44611. */
  44612. static void sp_384_get_entry_16_12(sp_point_384* r,
  44613. const sp_table_entry_384* table, int idx)
  44614. {
  44615. int i;
  44616. sp_digit mask;
  44617. r->x[0] = 0;
  44618. r->x[1] = 0;
  44619. r->x[2] = 0;
  44620. r->x[3] = 0;
  44621. r->x[4] = 0;
  44622. r->x[5] = 0;
  44623. r->x[6] = 0;
  44624. r->x[7] = 0;
  44625. r->x[8] = 0;
  44626. r->x[9] = 0;
  44627. r->x[10] = 0;
  44628. r->x[11] = 0;
  44629. r->y[0] = 0;
  44630. r->y[1] = 0;
  44631. r->y[2] = 0;
  44632. r->y[3] = 0;
  44633. r->y[4] = 0;
  44634. r->y[5] = 0;
  44635. r->y[6] = 0;
  44636. r->y[7] = 0;
  44637. r->y[8] = 0;
  44638. r->y[9] = 0;
  44639. r->y[10] = 0;
  44640. r->y[11] = 0;
  44641. for (i = 1; i < 16; i++) {
  44642. mask = 0 - (i == idx);
  44643. r->x[0] |= mask & table[i].x[0];
  44644. r->x[1] |= mask & table[i].x[1];
  44645. r->x[2] |= mask & table[i].x[2];
  44646. r->x[3] |= mask & table[i].x[3];
  44647. r->x[4] |= mask & table[i].x[4];
  44648. r->x[5] |= mask & table[i].x[5];
  44649. r->x[6] |= mask & table[i].x[6];
  44650. r->x[7] |= mask & table[i].x[7];
  44651. r->x[8] |= mask & table[i].x[8];
  44652. r->x[9] |= mask & table[i].x[9];
  44653. r->x[10] |= mask & table[i].x[10];
  44654. r->x[11] |= mask & table[i].x[11];
  44655. r->y[0] |= mask & table[i].y[0];
  44656. r->y[1] |= mask & table[i].y[1];
  44657. r->y[2] |= mask & table[i].y[2];
  44658. r->y[3] |= mask & table[i].y[3];
  44659. r->y[4] |= mask & table[i].y[4];
  44660. r->y[5] |= mask & table[i].y[5];
  44661. r->y[6] |= mask & table[i].y[6];
  44662. r->y[7] |= mask & table[i].y[7];
  44663. r->y[8] |= mask & table[i].y[8];
  44664. r->y[9] |= mask & table[i].y[9];
  44665. r->y[10] |= mask & table[i].y[10];
  44666. r->y[11] |= mask & table[i].y[11];
  44667. }
  44668. }
  44669. #endif /* !WC_NO_CACHE_RESISTANT */
  44670. /* Multiply the point by the scalar and return the result.
  44671. * If map is true then convert result to affine coordinates.
  44672. *
  44673. * Stripe implementation.
  44674. * Pre-generated: 2^0, 2^96, ...
  44675. * Pre-generated: products of all combinations of above.
  44676. * 4 doubles and adds (with qz=1)
  44677. *
  44678. * r Resulting point.
  44679. * k Scalar to multiply by.
  44680. * table Pre-computed table.
  44681. * map Indicates whether to convert result to affine.
  44682. * ct Constant time required.
  44683. * heap Heap to use for allocation.
  44684. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  44685. */
  44686. static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
  44687. const sp_table_entry_384* table, const sp_digit* k, int map,
  44688. int ct, void* heap)
  44689. {
  44690. #ifdef WOLFSSL_SP_SMALL_STACK
  44691. sp_point_384* rt = NULL;
  44692. sp_digit* t = NULL;
  44693. #else
  44694. sp_point_384 rt[2];
  44695. sp_digit t[2 * 12 * 6];
  44696. #endif
  44697. sp_point_384* p = NULL;
  44698. int i;
  44699. int j;
  44700. int y;
  44701. int x;
  44702. int err = MP_OKAY;
  44703. (void)g;
  44704. /* Constant time used for cache attack resistance implementation. */
  44705. (void)ct;
  44706. (void)heap;
  44707. #ifdef WOLFSSL_SP_SMALL_STACK
  44708. rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  44709. DYNAMIC_TYPE_ECC);
  44710. if (rt == NULL)
  44711. err = MEMORY_E;
  44712. if (err == MP_OKAY) {
  44713. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap,
  44714. DYNAMIC_TYPE_ECC);
  44715. if (t == NULL)
  44716. err = MEMORY_E;
  44717. }
  44718. #endif
  44719. if (err == MP_OKAY) {
  44720. p = rt + 1;
  44721. XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod));
  44722. XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
  44723. y = 0;
  44724. x = 95;
  44725. for (j=0; j<4; j++) {
  44726. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  44727. x += 96;
  44728. }
  44729. #ifndef WC_NO_CACHE_RESISTANT
  44730. if (ct) {
  44731. sp_384_get_entry_16_12(rt, table, y);
  44732. } else
  44733. #endif
  44734. {
  44735. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  44736. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  44737. }
  44738. rt->infinity = !y;
  44739. for (i=94; i>=0; i--) {
  44740. y = 0;
  44741. x = i;
  44742. for (j=0; j<4; j++) {
  44743. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  44744. x += 96;
  44745. }
  44746. sp_384_proj_point_dbl_12(rt, rt, t);
  44747. #ifndef WC_NO_CACHE_RESISTANT
  44748. if (ct) {
  44749. sp_384_get_entry_16_12(p, table, y);
  44750. }
  44751. else
  44752. #endif
  44753. {
  44754. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  44755. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  44756. }
  44757. p->infinity = !y;
  44758. sp_384_proj_point_add_qz1_12(rt, rt, p, t);
  44759. }
  44760. if (map != 0) {
  44761. sp_384_map_12(r, rt, t);
  44762. }
  44763. else {
  44764. XMEMCPY(r, rt, sizeof(sp_point_384));
  44765. }
  44766. }
  44767. #ifdef WOLFSSL_SP_SMALL_STACK
  44768. if (t != NULL)
  44769. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  44770. if (rt != NULL)
  44771. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  44772. #endif
  44773. return err;
  44774. }
  44775. #ifdef FP_ECC
  44776. #ifndef FP_ENTRIES
  44777. #define FP_ENTRIES 16
  44778. #endif
  44779. /* Cache entry - holds precomputation tables for a point. */
  44780. typedef struct sp_cache_384_t {
  44781. /* X ordinate of point that table was generated from. */
  44782. sp_digit x[12];
  44783. /* Y ordinate of point that table was generated from. */
  44784. sp_digit y[12];
  44785. /* Precomputation table for point. */
  44786. sp_table_entry_384 table[16];
  44787. /* Count of entries in table. */
  44788. uint32_t cnt;
  44789. /* Point and table set in entry. */
  44790. int set;
  44791. } sp_cache_384_t;
  44792. /* Cache of tables. */
  44793. static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
  44794. /* Index of last entry in cache. */
  44795. static THREAD_LS_T int sp_cache_384_last = -1;
  44796. /* Cache has been initialized. */
  44797. static THREAD_LS_T int sp_cache_384_inited = 0;
  44798. #ifndef HAVE_THREAD_LS
  44799. static volatile int initCacheMutex_384 = 0;
  44800. static wolfSSL_Mutex sp_cache_384_lock;
  44801. #endif
  44802. /* Get the cache entry for the point.
  44803. *
  44804. * g [in] Point scalar multiplying.
  44805. * cache [out] Cache table to use.
  44806. */
  44807. static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
  44808. {
  44809. int i;
  44810. int j;
  44811. uint32_t least;
  44812. if (sp_cache_384_inited == 0) {
  44813. for (i=0; i<FP_ENTRIES; i++) {
  44814. sp_cache_384[i].set = 0;
  44815. }
  44816. sp_cache_384_inited = 1;
  44817. }
  44818. /* Compare point with those in cache. */
  44819. for (i=0; i<FP_ENTRIES; i++) {
  44820. if (!sp_cache_384[i].set)
  44821. continue;
  44822. if (sp_384_cmp_equal_12(g->x, sp_cache_384[i].x) &
  44823. sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) {
  44824. sp_cache_384[i].cnt++;
  44825. break;
  44826. }
  44827. }
  44828. /* No match. */
  44829. if (i == FP_ENTRIES) {
  44830. /* Find empty entry. */
  44831. i = (sp_cache_384_last + 1) % FP_ENTRIES;
  44832. for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) {
  44833. if (!sp_cache_384[i].set) {
  44834. break;
  44835. }
  44836. }
  44837. /* Evict least used. */
  44838. if (i == sp_cache_384_last) {
  44839. least = sp_cache_384[0].cnt;
  44840. for (j=1; j<FP_ENTRIES; j++) {
  44841. if (sp_cache_384[j].cnt < least) {
  44842. i = j;
  44843. least = sp_cache_384[i].cnt;
  44844. }
  44845. }
  44846. }
  44847. XMEMCPY(sp_cache_384[i].x, g->x, sizeof(sp_cache_384[i].x));
  44848. XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y));
  44849. sp_cache_384[i].set = 1;
  44850. sp_cache_384[i].cnt = 1;
  44851. }
  44852. *cache = &sp_cache_384[i];
  44853. sp_cache_384_last = i;
  44854. }
  44855. #endif /* FP_ECC */
  44856. /* Multiply the base point of P384 by the scalar and return the result.
  44857. * If map is true then convert result to affine coordinates.
  44858. *
  44859. * r Resulting point.
  44860. * g Point to multiply.
  44861. * k Scalar to multiply by.
  44862. * map Indicates whether to convert result to affine.
  44863. * ct Constant time required.
  44864. * heap Heap to use for allocation.
  44865. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  44866. */
  44867. static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g,
  44868. const sp_digit* k, int map, int ct, void* heap)
  44869. {
  44870. #ifndef FP_ECC
  44871. return sp_384_ecc_mulmod_fast_12(r, g, k, map, ct, heap);
  44872. #else
  44873. #ifdef WOLFSSL_SP_SMALL_STACK
  44874. sp_digit* tmp;
  44875. #else
  44876. sp_digit tmp[2 * 12 * 7];
  44877. #endif
  44878. sp_cache_384_t* cache;
  44879. int err = MP_OKAY;
  44880. #ifdef WOLFSSL_SP_SMALL_STACK
  44881. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 7, heap, DYNAMIC_TYPE_ECC);
  44882. if (tmp == NULL) {
  44883. err = MEMORY_E;
  44884. }
  44885. #endif
  44886. #ifndef HAVE_THREAD_LS
  44887. if (err == MP_OKAY) {
  44888. if (initCacheMutex_384 == 0) {
  44889. wc_InitMutex(&sp_cache_384_lock);
  44890. initCacheMutex_384 = 1;
  44891. }
  44892. if (wc_LockMutex(&sp_cache_384_lock) != 0) {
  44893. err = BAD_MUTEX_E;
  44894. }
  44895. }
  44896. #endif /* HAVE_THREAD_LS */
  44897. if (err == MP_OKAY) {
  44898. sp_ecc_get_cache_384(g, &cache);
  44899. if (cache->cnt == 2)
  44900. sp_384_gen_stripe_table_12(g, cache->table, tmp, heap);
  44901. #ifndef HAVE_THREAD_LS
  44902. wc_UnLockMutex(&sp_cache_384_lock);
  44903. #endif /* HAVE_THREAD_LS */
  44904. if (cache->cnt < 2) {
  44905. err = sp_384_ecc_mulmod_fast_12(r, g, k, map, ct, heap);
  44906. }
  44907. else {
  44908. err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k,
  44909. map, ct, heap);
  44910. }
  44911. }
  44912. #ifdef WOLFSSL_SP_SMALL_STACK
  44913. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  44914. #endif
  44915. return err;
  44916. #endif
  44917. }
  44918. #else
  44919. #ifdef FP_ECC
  44920. /* Generate the pre-computed table of points for the base point.
  44921. *
  44922. * width = 8
  44923. * 256 entries
  44924. * 48 bits between
  44925. *
  44926. * a The base point.
  44927. * table Place to store generated point data.
  44928. * tmp Temporary data.
  44929. * heap Heap to use for allocation.
  44930. */
  44931. static int sp_384_gen_stripe_table_12(const sp_point_384* a,
  44932. sp_table_entry_384* table, sp_digit* tmp, void* heap)
  44933. {
  44934. #ifdef WOLFSSL_SP_SMALL_STACK
  44935. sp_point_384* t = NULL;
  44936. #else
  44937. sp_point_384 t[3];
  44938. #endif
  44939. sp_point_384* s1 = NULL;
  44940. sp_point_384* s2 = NULL;
  44941. int i;
  44942. int j;
  44943. int err = MP_OKAY;
  44944. (void)heap;
  44945. #ifdef WOLFSSL_SP_SMALL_STACK
  44946. t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap,
  44947. DYNAMIC_TYPE_ECC);
  44948. if (t == NULL)
  44949. err = MEMORY_E;
  44950. #endif
  44951. if (err == MP_OKAY) {
  44952. s1 = t + 1;
  44953. s2 = t + 2;
  44954. err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod);
  44955. }
  44956. if (err == MP_OKAY) {
  44957. err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod);
  44958. }
  44959. if (err == MP_OKAY) {
  44960. err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod);
  44961. }
  44962. if (err == MP_OKAY) {
  44963. t->infinity = 0;
  44964. sp_384_proj_to_affine_12(t, tmp);
  44965. XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod));
  44966. s1->infinity = 0;
  44967. XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod));
  44968. s2->infinity = 0;
  44969. /* table[0] = {0, 0, infinity} */
  44970. XMEMSET(&table[0], 0, sizeof(sp_table_entry_384));
  44971. /* table[1] = Affine version of 'a' in Montgomery form */
  44972. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  44973. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  44974. for (i=1; i<8; i++) {
  44975. sp_384_proj_point_dbl_n_12(t, 48, tmp);
  44976. sp_384_proj_to_affine_12(t, tmp);
  44977. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  44978. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  44979. }
  44980. for (i=1; i<8; i++) {
  44981. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  44982. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  44983. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  44984. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  44985. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  44986. sp_384_proj_point_add_qz1_12(t, s1, s2, tmp);
  44987. sp_384_proj_to_affine_12(t, tmp);
  44988. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  44989. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  44990. }
  44991. }
  44992. }
  44993. #ifdef WOLFSSL_SP_SMALL_STACK
  44994. if (t != NULL)
  44995. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  44996. #endif
  44997. return err;
  44998. }
  44999. #endif /* FP_ECC */
  45000. #ifndef WC_NO_CACHE_RESISTANT
  45001. /* Touch each possible entry that could be being copied.
  45002. *
  45003. * r Point to copy into.
  45004. * table Table - start of the entries to access
  45005. * idx Index of entry to retrieve.
  45006. */
  45007. static void sp_384_get_entry_256_12(sp_point_384* r,
  45008. const sp_table_entry_384* table, int idx)
  45009. {
  45010. int i;
  45011. sp_digit mask;
  45012. r->x[0] = 0;
  45013. r->x[1] = 0;
  45014. r->x[2] = 0;
  45015. r->x[3] = 0;
  45016. r->x[4] = 0;
  45017. r->x[5] = 0;
  45018. r->x[6] = 0;
  45019. r->x[7] = 0;
  45020. r->x[8] = 0;
  45021. r->x[9] = 0;
  45022. r->x[10] = 0;
  45023. r->x[11] = 0;
  45024. r->y[0] = 0;
  45025. r->y[1] = 0;
  45026. r->y[2] = 0;
  45027. r->y[3] = 0;
  45028. r->y[4] = 0;
  45029. r->y[5] = 0;
  45030. r->y[6] = 0;
  45031. r->y[7] = 0;
  45032. r->y[8] = 0;
  45033. r->y[9] = 0;
  45034. r->y[10] = 0;
  45035. r->y[11] = 0;
  45036. for (i = 1; i < 256; i++) {
  45037. mask = 0 - (i == idx);
  45038. r->x[0] |= mask & table[i].x[0];
  45039. r->x[1] |= mask & table[i].x[1];
  45040. r->x[2] |= mask & table[i].x[2];
  45041. r->x[3] |= mask & table[i].x[3];
  45042. r->x[4] |= mask & table[i].x[4];
  45043. r->x[5] |= mask & table[i].x[5];
  45044. r->x[6] |= mask & table[i].x[6];
  45045. r->x[7] |= mask & table[i].x[7];
  45046. r->x[8] |= mask & table[i].x[8];
  45047. r->x[9] |= mask & table[i].x[9];
  45048. r->x[10] |= mask & table[i].x[10];
  45049. r->x[11] |= mask & table[i].x[11];
  45050. r->y[0] |= mask & table[i].y[0];
  45051. r->y[1] |= mask & table[i].y[1];
  45052. r->y[2] |= mask & table[i].y[2];
  45053. r->y[3] |= mask & table[i].y[3];
  45054. r->y[4] |= mask & table[i].y[4];
  45055. r->y[5] |= mask & table[i].y[5];
  45056. r->y[6] |= mask & table[i].y[6];
  45057. r->y[7] |= mask & table[i].y[7];
  45058. r->y[8] |= mask & table[i].y[8];
  45059. r->y[9] |= mask & table[i].y[9];
  45060. r->y[10] |= mask & table[i].y[10];
  45061. r->y[11] |= mask & table[i].y[11];
  45062. }
  45063. }
  45064. #endif /* !WC_NO_CACHE_RESISTANT */
  45065. /* Multiply the point by the scalar and return the result.
  45066. * If map is true then convert result to affine coordinates.
  45067. *
  45068. * Stripe implementation.
  45069. * Pre-generated: 2^0, 2^48, ...
  45070. * Pre-generated: products of all combinations of above.
  45071. * 8 doubles and adds (with qz=1)
  45072. *
  45073. * r Resulting point.
  45074. * k Scalar to multiply by.
  45075. * table Pre-computed table.
  45076. * map Indicates whether to convert result to affine.
  45077. * ct Constant time required.
  45078. * heap Heap to use for allocation.
  45079. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  45080. */
  45081. static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g,
  45082. const sp_table_entry_384* table, const sp_digit* k, int map,
  45083. int ct, void* heap)
  45084. {
  45085. #ifdef WOLFSSL_SP_SMALL_STACK
  45086. sp_point_384* rt = NULL;
  45087. sp_digit* t = NULL;
  45088. #else
  45089. sp_point_384 rt[2];
  45090. sp_digit t[2 * 12 * 6];
  45091. #endif
  45092. sp_point_384* p = NULL;
  45093. int i;
  45094. int j;
  45095. int y;
  45096. int x;
  45097. int err = MP_OKAY;
  45098. (void)g;
  45099. /* Constant time used for cache attack resistance implementation. */
  45100. (void)ct;
  45101. (void)heap;
  45102. #ifdef WOLFSSL_SP_SMALL_STACK
  45103. rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  45104. DYNAMIC_TYPE_ECC);
  45105. if (rt == NULL)
  45106. err = MEMORY_E;
  45107. if (err == MP_OKAY) {
  45108. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap,
  45109. DYNAMIC_TYPE_ECC);
  45110. if (t == NULL)
  45111. err = MEMORY_E;
  45112. }
  45113. #endif
  45114. if (err == MP_OKAY) {
  45115. p = rt + 1;
  45116. XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod));
  45117. XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
  45118. y = 0;
  45119. x = 47;
  45120. for (j=0; j<8; j++) {
  45121. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  45122. x += 48;
  45123. }
  45124. #ifndef WC_NO_CACHE_RESISTANT
  45125. if (ct) {
  45126. sp_384_get_entry_256_12(rt, table, y);
  45127. } else
  45128. #endif
  45129. {
  45130. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  45131. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  45132. }
  45133. rt->infinity = !y;
  45134. for (i=46; i>=0; i--) {
  45135. y = 0;
  45136. x = i;
  45137. for (j=0; j<8; j++) {
  45138. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  45139. x += 48;
  45140. }
  45141. sp_384_proj_point_dbl_12(rt, rt, t);
  45142. #ifndef WC_NO_CACHE_RESISTANT
  45143. if (ct) {
  45144. sp_384_get_entry_256_12(p, table, y);
  45145. }
  45146. else
  45147. #endif
  45148. {
  45149. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  45150. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  45151. }
  45152. p->infinity = !y;
  45153. sp_384_proj_point_add_qz1_12(rt, rt, p, t);
  45154. }
  45155. if (map != 0) {
  45156. sp_384_map_12(r, rt, t);
  45157. }
  45158. else {
  45159. XMEMCPY(r, rt, sizeof(sp_point_384));
  45160. }
  45161. }
  45162. #ifdef WOLFSSL_SP_SMALL_STACK
  45163. if (t != NULL)
  45164. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  45165. if (rt != NULL)
  45166. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  45167. #endif
  45168. return err;
  45169. }
  45170. #ifdef FP_ECC
  45171. #ifndef FP_ENTRIES
  45172. #define FP_ENTRIES 16
  45173. #endif
  45174. /* Cache entry - holds precomputation tables for a point. */
  45175. typedef struct sp_cache_384_t {
  45176. /* X ordinate of point that table was generated from. */
  45177. sp_digit x[12];
  45178. /* Y ordinate of point that table was generated from. */
  45179. sp_digit y[12];
  45180. /* Precomputation table for point. */
  45181. sp_table_entry_384 table[256];
  45182. /* Count of entries in table. */
  45183. uint32_t cnt;
  45184. /* Point and table set in entry. */
  45185. int set;
  45186. } sp_cache_384_t;
  45187. /* Cache of tables. */
  45188. static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
  45189. /* Index of last entry in cache. */
  45190. static THREAD_LS_T int sp_cache_384_last = -1;
  45191. /* Cache has been initialized. */
  45192. static THREAD_LS_T int sp_cache_384_inited = 0;
  45193. #ifndef HAVE_THREAD_LS
  45194. static volatile int initCacheMutex_384 = 0;
  45195. static wolfSSL_Mutex sp_cache_384_lock;
  45196. #endif
  45197. /* Get the cache entry for the point.
  45198. *
  45199. * g [in] Point scalar multiplying.
  45200. * cache [out] Cache table to use.
  45201. */
  45202. static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
  45203. {
  45204. int i;
  45205. int j;
  45206. uint32_t least;
  45207. if (sp_cache_384_inited == 0) {
  45208. for (i=0; i<FP_ENTRIES; i++) {
  45209. sp_cache_384[i].set = 0;
  45210. }
  45211. sp_cache_384_inited = 1;
  45212. }
  45213. /* Compare point with those in cache. */
  45214. for (i=0; i<FP_ENTRIES; i++) {
  45215. if (!sp_cache_384[i].set)
  45216. continue;
  45217. if (sp_384_cmp_equal_12(g->x, sp_cache_384[i].x) &
  45218. sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) {
  45219. sp_cache_384[i].cnt++;
  45220. break;
  45221. }
  45222. }
  45223. /* No match. */
  45224. if (i == FP_ENTRIES) {
  45225. /* Find empty entry. */
  45226. i = (sp_cache_384_last + 1) % FP_ENTRIES;
  45227. for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) {
  45228. if (!sp_cache_384[i].set) {
  45229. break;
  45230. }
  45231. }
  45232. /* Evict least used. */
  45233. if (i == sp_cache_384_last) {
  45234. least = sp_cache_384[0].cnt;
  45235. for (j=1; j<FP_ENTRIES; j++) {
  45236. if (sp_cache_384[j].cnt < least) {
  45237. i = j;
  45238. least = sp_cache_384[i].cnt;
  45239. }
  45240. }
  45241. }
  45242. XMEMCPY(sp_cache_384[i].x, g->x, sizeof(sp_cache_384[i].x));
  45243. XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y));
  45244. sp_cache_384[i].set = 1;
  45245. sp_cache_384[i].cnt = 1;
  45246. }
  45247. *cache = &sp_cache_384[i];
  45248. sp_cache_384_last = i;
  45249. }
  45250. #endif /* FP_ECC */
  45251. /* Multiply the base point of P384 by the scalar and return the result.
  45252. * If map is true then convert result to affine coordinates.
  45253. *
  45254. * r Resulting point.
  45255. * g Point to multiply.
  45256. * k Scalar to multiply by.
  45257. * map Indicates whether to convert result to affine.
  45258. * ct Constant time required.
  45259. * heap Heap to use for allocation.
  45260. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  45261. */
  45262. static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g,
  45263. const sp_digit* k, int map, int ct, void* heap)
  45264. {
  45265. #ifndef FP_ECC
  45266. return sp_384_ecc_mulmod_fast_12(r, g, k, map, ct, heap);
  45267. #else
  45268. #ifdef WOLFSSL_SP_SMALL_STACK
  45269. sp_digit* tmp;
  45270. #else
  45271. sp_digit tmp[2 * 12 * 7];
  45272. #endif
  45273. sp_cache_384_t* cache;
  45274. int err = MP_OKAY;
  45275. #ifdef WOLFSSL_SP_SMALL_STACK
  45276. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 7, heap, DYNAMIC_TYPE_ECC);
  45277. if (tmp == NULL) {
  45278. err = MEMORY_E;
  45279. }
  45280. #endif
  45281. #ifndef HAVE_THREAD_LS
  45282. if (err == MP_OKAY) {
  45283. if (initCacheMutex_384 == 0) {
  45284. wc_InitMutex(&sp_cache_384_lock);
  45285. initCacheMutex_384 = 1;
  45286. }
  45287. if (wc_LockMutex(&sp_cache_384_lock) != 0) {
  45288. err = BAD_MUTEX_E;
  45289. }
  45290. }
  45291. #endif /* HAVE_THREAD_LS */
  45292. if (err == MP_OKAY) {
  45293. sp_ecc_get_cache_384(g, &cache);
  45294. if (cache->cnt == 2)
  45295. sp_384_gen_stripe_table_12(g, cache->table, tmp, heap);
  45296. #ifndef HAVE_THREAD_LS
  45297. wc_UnLockMutex(&sp_cache_384_lock);
  45298. #endif /* HAVE_THREAD_LS */
  45299. if (cache->cnt < 2) {
  45300. err = sp_384_ecc_mulmod_fast_12(r, g, k, map, ct, heap);
  45301. }
  45302. else {
  45303. err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k,
  45304. map, ct, heap);
  45305. }
  45306. }
  45307. #ifdef WOLFSSL_SP_SMALL_STACK
  45308. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  45309. #endif
  45310. return err;
  45311. #endif
  45312. }
  45313. #endif /* WOLFSSL_SP_SMALL */
  45314. /* Multiply the point by the scalar and return the result.
  45315. * If map is true then convert result to affine coordinates.
  45316. *
  45317. * km Scalar to multiply by.
  45318. * p Point to multiply.
  45319. * r Resulting point.
  45320. * map Indicates whether to convert result to affine.
  45321. * heap Heap to use for allocation.
  45322. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  45323. */
  45324. int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r,
  45325. int map, void* heap)
  45326. {
  45327. #ifdef WOLFSSL_SP_SMALL_STACK
  45328. sp_point_384* point = NULL;
  45329. sp_digit* k = NULL;
  45330. #else
  45331. sp_point_384 point[1];
  45332. sp_digit k[12];
  45333. #endif
  45334. int err = MP_OKAY;
  45335. #ifdef WOLFSSL_SP_SMALL_STACK
  45336. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  45337. DYNAMIC_TYPE_ECC);
  45338. if (point == NULL)
  45339. err = MEMORY_E;
  45340. if (err == MP_OKAY) {
  45341. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap,
  45342. DYNAMIC_TYPE_ECC);
  45343. if (k == NULL)
  45344. err = MEMORY_E;
  45345. }
  45346. #endif
  45347. if (err == MP_OKAY) {
  45348. sp_384_from_mp(k, 12, km);
  45349. sp_384_point_from_ecc_point_12(point, gm);
  45350. err = sp_384_ecc_mulmod_12(point, point, k, map, 1, heap);
  45351. }
  45352. if (err == MP_OKAY) {
  45353. err = sp_384_point_to_ecc_point_12(point, r);
  45354. }
  45355. #ifdef WOLFSSL_SP_SMALL_STACK
  45356. if (k != NULL)
  45357. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  45358. if (point != NULL)
  45359. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  45360. #endif
  45361. return err;
  45362. }
  45363. /* Multiply the point by the scalar, add point a and return the result.
  45364. * If map is true then convert result to affine coordinates.
  45365. *
  45366. * km Scalar to multiply by.
  45367. * p Point to multiply.
  45368. * am Point to add to scalar multiply result.
  45369. * inMont Point to add is in montgomery form.
  45370. * r Resulting point.
  45371. * map Indicates whether to convert result to affine.
  45372. * heap Heap to use for allocation.
  45373. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  45374. */
  45375. int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm,
  45376. const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
  45377. {
  45378. #ifdef WOLFSSL_SP_SMALL_STACK
  45379. sp_point_384* point = NULL;
  45380. sp_digit* k = NULL;
  45381. #else
  45382. sp_point_384 point[2];
  45383. sp_digit k[12 + 12 * 2 * 6];
  45384. #endif
  45385. sp_point_384* addP = NULL;
  45386. sp_digit* tmp = NULL;
  45387. int err = MP_OKAY;
  45388. #ifdef WOLFSSL_SP_SMALL_STACK
  45389. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  45390. DYNAMIC_TYPE_ECC);
  45391. if (point == NULL)
  45392. err = MEMORY_E;
  45393. if (err == MP_OKAY) {
  45394. k = (sp_digit*)XMALLOC(
  45395. sizeof(sp_digit) * (12 + 12 * 2 * 6), heap,
  45396. DYNAMIC_TYPE_ECC);
  45397. if (k == NULL)
  45398. err = MEMORY_E;
  45399. }
  45400. #endif
  45401. if (err == MP_OKAY) {
  45402. addP = point + 1;
  45403. tmp = k + 12;
  45404. sp_384_from_mp(k, 12, km);
  45405. sp_384_point_from_ecc_point_12(point, gm);
  45406. sp_384_point_from_ecc_point_12(addP, am);
  45407. }
  45408. if ((err == MP_OKAY) && (!inMont)) {
  45409. err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
  45410. }
  45411. if ((err == MP_OKAY) && (!inMont)) {
  45412. err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
  45413. }
  45414. if ((err == MP_OKAY) && (!inMont)) {
  45415. err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
  45416. }
  45417. if (err == MP_OKAY) {
  45418. err = sp_384_ecc_mulmod_12(point, point, k, 0, 0, heap);
  45419. }
  45420. if (err == MP_OKAY) {
  45421. sp_384_proj_point_add_12(point, point, addP, tmp);
  45422. if (map) {
  45423. sp_384_map_12(point, point, tmp);
  45424. }
  45425. err = sp_384_point_to_ecc_point_12(point, r);
  45426. }
  45427. #ifdef WOLFSSL_SP_SMALL_STACK
  45428. if (k != NULL)
  45429. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  45430. if (point != NULL)
  45431. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  45432. #endif
  45433. return err;
  45434. }
  45435. #ifdef WOLFSSL_SP_SMALL
  45436. /* Striping precomputation table.
  45437. * 4 points combined into a table of 16 points.
  45438. * Distance of 96 between points.
  45439. */
  45440. static const sp_table_entry_384 p384_table[16] = {
  45441. /* 0 */
  45442. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  45443. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  45444. /* 1 */
  45445. { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc,
  45446. 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 },
  45447. { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756,
  45448. 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } },
  45449. /* 2 */
  45450. { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3,
  45451. 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 },
  45452. { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc,
  45453. 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } },
  45454. /* 3 */
  45455. { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480,
  45456. 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 },
  45457. { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047,
  45458. 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } },
  45459. /* 4 */
  45460. { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c,
  45461. 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 },
  45462. { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc,
  45463. 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } },
  45464. /* 5 */
  45465. { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98,
  45466. 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c },
  45467. { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28,
  45468. 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } },
  45469. /* 6 */
  45470. { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e,
  45471. 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 },
  45472. { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec,
  45473. 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } },
  45474. /* 7 */
  45475. { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b,
  45476. 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b },
  45477. { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b,
  45478. 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } },
  45479. /* 8 */
  45480. { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9,
  45481. 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 },
  45482. { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1,
  45483. 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } },
  45484. /* 9 */
  45485. { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc,
  45486. 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a },
  45487. { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18,
  45488. 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } },
  45489. /* 10 */
  45490. { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247,
  45491. 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 },
  45492. { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d,
  45493. 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } },
  45494. /* 11 */
  45495. { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12,
  45496. 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e },
  45497. { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f,
  45498. 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } },
  45499. /* 12 */
  45500. { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe,
  45501. 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 },
  45502. { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6,
  45503. 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } },
  45504. /* 13 */
  45505. { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6,
  45506. 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 },
  45507. { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf,
  45508. 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } },
  45509. /* 14 */
  45510. { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53,
  45511. 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 },
  45512. { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370,
  45513. 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } },
  45514. /* 15 */
  45515. { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f,
  45516. 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc },
  45517. { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2,
  45518. 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } },
  45519. };
  45520. /* Multiply the base point of P384 by the scalar and return the result.
  45521. * If map is true then convert result to affine coordinates.
  45522. *
  45523. * Stripe implementation.
  45524. * Pre-generated: 2^0, 2^96, ...
  45525. * Pre-generated: products of all combinations of above.
  45526. * 4 doubles and adds (with qz=1)
  45527. *
  45528. * r Resulting point.
  45529. * k Scalar to multiply by.
  45530. * map Indicates whether to convert result to affine.
  45531. * ct Constant time required.
  45532. * heap Heap to use for allocation.
  45533. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  45534. */
  45535. static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
  45536. int map, int ct, void* heap)
  45537. {
  45538. return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table,
  45539. k, map, ct, heap);
  45540. }
  45541. #else
  45542. /* Striping precomputation table.
  45543. * 8 points combined into a table of 256 points.
  45544. * Distance of 48 between points.
  45545. */
  45546. static const sp_table_entry_384 p384_table[256] = {
  45547. /* 0 */
  45548. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  45549. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  45550. /* 1 */
  45551. { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc,
  45552. 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 },
  45553. { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756,
  45554. 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } },
  45555. /* 2 */
  45556. { { 0x2b0c535b,0x29864753,0x70506296,0x90dd6953,0x216ab9ac,0x038cd6b4,
  45557. 0xbe12d76a,0x3df9b7b7,0x5f347bdb,0x13f4d978,0x13e94489,0x222c5c9c },
  45558. { 0x2680dc64,0x5f8e796f,0x58352417,0x120e7cb7,0xd10740b8,0x254b5d8a,
  45559. 0x5337dee6,0xc38b8efb,0x94f02247,0xf688c2e1,0x6c25bc4c,0x7b5c75f3 } },
  45560. /* 3 */
  45561. { { 0x9edffea5,0xe26a3cc3,0x37d7e9fc,0x35bbfd1c,0x9bde3ef6,0xf0e7700d,
  45562. 0x1a538f5a,0x0380eb47,0x05bf9eb3,0x2e9da8bb,0x1a460c3e,0xdbb93c73 },
  45563. { 0xf526b605,0x37dba260,0xfd785537,0x95d4978e,0xed72a04a,0x24ed793a,
  45564. 0x76005b1a,0x26948377,0x9e681f82,0x99f557b9,0xd64954ef,0xae5f9557 } },
  45565. /* 4 */
  45566. { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3,
  45567. 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 },
  45568. { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc,
  45569. 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } },
  45570. /* 5 */
  45571. { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480,
  45572. 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 },
  45573. { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047,
  45574. 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } },
  45575. /* 6 */
  45576. { { 0x4fc52870,0x28f9c07a,0x1a53a961,0xce0b3748,0x0e1828d9,0xd550fa18,
  45577. 0x6adb225a,0xa24abaf7,0x6e58a348,0xd11ed0a5,0x948acb62,0xf3d811e6 },
  45578. { 0x4c61ed22,0x8618dd77,0x80b47c9d,0x0bb747f9,0xde6b8559,0x22bf796f,
  45579. 0x680a21e9,0xfdfd1c6d,0x2af2c9dd,0xc0db1577,0xc1e90f3d,0xa09379e6 } },
  45580. /* 7 */
  45581. { { 0xe085c629,0x386c66ef,0x095bc89a,0x5fc2a461,0x203f4b41,0x1353d631,
  45582. 0x7e4bd8f5,0x7ca1972b,0xa7df8ce9,0xb077380a,0xee7e4ea3,0xd8a90389 },
  45583. { 0xe7b14461,0x1bc74dc7,0x0c9c4f78,0xdc2cb014,0x84ef0a10,0x52b4b3a6,
  45584. 0x20327fe2,0xbde6ea5d,0x660f9615,0xb71ec435,0xb8ad8173,0xeede5a04 } },
  45585. /* 8 */
  45586. { { 0x893b9a2d,0x5584cbb3,0x00850c5d,0x820c660b,0x7df2d43d,0x4126d826,
  45587. 0x0109e801,0xdd5bbbf0,0x38172f1c,0x85b92ee3,0xf31430d9,0x609d4f93 },
  45588. { 0xeadaf9d6,0x1e059a07,0x0f125fb0,0x70e6536c,0x560f20e7,0xd6220751,
  45589. 0x7aaf3a9a,0xa59489ae,0x64bae14e,0x7b70e2f6,0x76d08249,0x0dd03701 } },
  45590. /* 9 */
  45591. { { 0x8510521f,0x4cc13be8,0xf724cc17,0x87315ba9,0x353dc263,0xb49d83bb,
  45592. 0x0c279257,0x8b677efe,0xc93c9537,0x510a1c1c,0xa4702c99,0x33e30cd8 },
  45593. { 0x2208353f,0xf0ffc89d,0xced42b2b,0x0170fa8d,0x26e2a5f5,0x090851ed,
  45594. 0xecb52c96,0x81276455,0x7fe1adf4,0x0646c4e1,0xb0868eab,0x513f047e } },
  45595. /* 10 */
  45596. { { 0xdf5bdf53,0xc07611f4,0x58b11a6d,0x45d331a7,0x1c4ee394,0x58965daf,
  45597. 0x5a5878d1,0xba8bebe7,0x82dd3025,0xaecc0a18,0xa923eb8b,0xcf2a3899 },
  45598. { 0xd24fd048,0xf98c9281,0x8bbb025d,0x841bfb59,0xc9ab9d53,0xb8ddf8ce,
  45599. 0x7fef044e,0x538a4cb6,0x23236662,0x092ac21f,0x0b66f065,0xa919d385 } },
  45600. /* 11 */
  45601. { { 0x85d480d8,0x3db03b40,0x1b287a7d,0x8cd9f479,0x4a8f3bae,0x8f24dc75,
  45602. 0x3db41892,0x482eb800,0x9c56e0f5,0x38bf9eb3,0x9a91dc6f,0x8b977320 },
  45603. { 0x7209cfc2,0xa31b05b2,0x05b2db70,0x4c49bf85,0xd619527b,0x56462498,
  45604. 0x1fac51ba,0x3fe51039,0xab4b8342,0xfb04f55e,0x04c6eabf,0xc07c10dc } },
  45605. /* 12 */
  45606. { { 0xdb32f048,0xad22fe4c,0x475ed6df,0x5f23bf91,0xaa66b6cb,0xa50ce0c0,
  45607. 0xf03405c0,0xdf627a89,0xf95e2d6a,0x3674837d,0xba42e64e,0x081c95b6 },
  45608. { 0xe71d6ceb,0xeba3e036,0x6c6b0271,0xb45bcccf,0x0684701d,0x67b47e63,
  45609. 0xe712523f,0x60f8f942,0x5cd47adc,0x82423472,0x87649cbb,0x83027d79 } },
  45610. /* 13 */
  45611. { { 0x3615b0b8,0xb3929ea6,0xa54dac41,0xb41441fd,0xb5b6a368,0x8995d556,
  45612. 0x167ef05e,0xa80d4529,0x6d25a27f,0xf6bcb4a1,0x7bd55b68,0x210d6a4c },
  45613. { 0x25351130,0xf3804abb,0x903e37eb,0x1d2df699,0x084c25c8,0x5f201efc,
  45614. 0xa1c68e91,0x31a28c87,0x563f62a5,0x81dad253,0xd6c415d4,0x5dd6de70 } },
  45615. /* 14 */
  45616. { { 0x846612ce,0x29f470fd,0xda18d997,0x986f3eec,0x2f34af86,0x6b84c161,
  45617. 0x46ddaf8b,0x5ef0a408,0xe49e795f,0x14405a00,0xaa2f7a37,0x5f491b16 },
  45618. { 0xdb41b38d,0xc7f07ae4,0x18fbfcaa,0xef7d119e,0x14443b19,0x3a18e076,
  45619. 0x79a19926,0x4356841a,0xe2226fbe,0x91f4a91c,0x3cc88721,0xdc77248c } },
  45620. /* 15 */
  45621. { { 0xe4b1ec9d,0xd570ff1a,0xe7eef706,0x21d23e0e,0xca19e086,0x3cde40f4,
  45622. 0xcd4bb270,0x7d6523c4,0xbf13aa6c,0x16c1f06c,0xd14c4b60,0x5aa7245a },
  45623. { 0x44b74de8,0x37f81467,0x620a934e,0x839e7a17,0xde8b1aa1,0xf74d14e8,
  45624. 0xf30d75e2,0x8789fa51,0xc81c261e,0x09b24052,0x33c565ee,0x654e2678 } },
  45625. /* 16 */
  45626. { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c,
  45627. 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 },
  45628. { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc,
  45629. 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } },
  45630. /* 17 */
  45631. { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98,
  45632. 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c },
  45633. { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28,
  45634. 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } },
  45635. /* 18 */
  45636. { { 0x7d8c1bba,0x7ecbac01,0x90b0f3d5,0x6058f9c3,0xf6197d0f,0xaee116e3,
  45637. 0x4033b128,0xc4dd7068,0xc209b983,0xf084dba6,0x831dbc4a,0x97c7c2cf },
  45638. { 0xf96010e8,0x2f4e61dd,0x529faa17,0xd97e4e20,0x69d37f20,0x4ee66660,
  45639. 0x3d366d72,0xccc139ed,0x13488e0f,0x690b6ee2,0xf3a6d533,0x7cad1dc5 } },
  45640. /* 19 */
  45641. { { 0xda57a41f,0x660a9a81,0xec0039b6,0xe74a0412,0x5e1dad15,0x42343c6b,
  45642. 0x46681d4c,0x284f3ff5,0x63749e89,0xb51087f1,0x6f9f2f13,0x070f23cc },
  45643. { 0x5d186e14,0x542211da,0xfddb0dff,0x84748f37,0xdb1f4180,0x41a3aab4,
  45644. 0xa6402d0e,0x25ed667b,0x02f58355,0x2f2924a9,0xfa44a689,0x5844ee7c } },
  45645. /* 20 */
  45646. { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e,
  45647. 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 },
  45648. { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec,
  45649. 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } },
  45650. /* 21 */
  45651. { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b,
  45652. 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b },
  45653. { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b,
  45654. 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } },
  45655. /* 22 */
  45656. { { 0x104cbba5,0xc023780d,0xfa35dd4c,0x6207e747,0x1ca9b6a3,0x35c23928,
  45657. 0x97987b10,0x4ff19be8,0x8022eee8,0xb8476bbf,0xd3bbe74d,0xaa0a4a14 },
  45658. { 0x187d4543,0x20f94331,0x79f6e066,0x32153870,0xac7e82e1,0x83b0f74e,
  45659. 0x828f06ab,0xa7748ba2,0xc26ef35f,0xc5f0298a,0x8e9a7dbd,0x0f0c5070 } },
  45660. /* 23 */
  45661. { { 0xdef029dd,0x0c5c244c,0x850661b8,0x3dabc687,0xfe11d981,0x9992b865,
  45662. 0x6274dbad,0xe9801b8f,0x098da242,0xe54e6319,0x91a53d08,0x9929a91a },
  45663. { 0x35285887,0x37bffd72,0xf1418102,0xbc759425,0xfd2e6e20,0x9280cc35,
  45664. 0xfbc42ee5,0x735c600c,0x8837619a,0xb7ad2864,0xa778c57b,0xa3627231 } },
  45665. /* 24 */
  45666. { { 0x91361ed8,0xae799b5c,0x6c63366c,0x47d71b75,0x1b265a6a,0x54cdd521,
  45667. 0x98d77b74,0xe0215a59,0xbab29db0,0x4424d9b7,0x7fd9e536,0x8b0ffacc },
  45668. { 0x37b5d9ef,0x46d85d12,0xbfa91747,0x5b106d62,0x5f99ba2d,0xed0479f8,
  45669. 0x1d104de4,0x0e6f3923,0x25e8983f,0x83a84c84,0xf8105a70,0xa9507e0a } },
  45670. /* 25 */
  45671. { { 0x14cf381c,0xf6c68a6e,0xc22e31cc,0xaf9d27bd,0xaa8a5ccb,0x23568d4d,
  45672. 0xe338e4d2,0xe431eec0,0x8f52ad1f,0xf1a828fe,0xe86acd80,0xdb6a0579 },
  45673. { 0x4507832a,0x2885672e,0x887e5289,0x73fc275f,0x05610d08,0x65f80278,
  45674. 0x075ff5b0,0x8d9b4554,0x09f712b5,0x3a8e8fb1,0x2ebe9cf2,0x39f0ac86 } },
  45675. /* 26 */
  45676. { { 0x4c52edf5,0xd8fabf78,0xa589ae53,0xdcd737e5,0xd791ab17,0x94918bf0,
  45677. 0xbcff06c9,0xb5fbd956,0xdca46d45,0xf6d3032e,0x41a3e486,0x2cdff7e1 },
  45678. { 0x61f47ec8,0x6674b3ba,0xeef84608,0x8a882163,0x4c687f90,0xa257c705,
  45679. 0xf6cdf227,0xe30cb2ed,0x7f6ea846,0x2c4c64ca,0xcc6bcd3c,0x186fa17c } },
  45680. /* 27 */
  45681. { { 0x1dfcb91e,0x48a3f536,0x646d358a,0x83595e13,0x91128798,0xbd15827b,
  45682. 0x2187757a,0x3ce612b8,0x61bd7372,0x873150a1,0xb662f568,0xf4684530 },
  45683. { 0x401896f6,0x8833950b,0x77f3e090,0xe11cb89a,0x48e7f4a5,0xb2f12cac,
  45684. 0xf606677e,0x313dd769,0x16579f93,0xfdcf08b3,0x46b8f22b,0x6429cec9 } },
  45685. /* 28 */
  45686. { { 0xbb75f9a4,0x4984dd54,0x29d3b570,0x4aef06b9,0x3d6e4c1e,0xb5f84ca2,
  45687. 0xb083ef35,0x24c61c11,0x392ca9ff,0xce4a7392,0x6730a800,0x865d6517 },
  45688. { 0x722b4a2b,0xca3dfe76,0x7b083e0e,0x12c04bf9,0x1b86b8a5,0x803ce5b5,
  45689. 0x6a7e3e0c,0x3fc7632d,0xc81adbe4,0xc89970c2,0x120e16b1,0x3cbcd3ad } },
  45690. /* 29 */
  45691. { { 0xec30ce93,0xfbfb4cc7,0xb72720a2,0x10ed6c7d,0x47b55500,0xec675bf7,
  45692. 0x333ff7c3,0x90725903,0x5075bfc0,0xc7c3973e,0x07acf31b,0xb049ecb0 },
  45693. { 0x4f58839c,0xb4076eaf,0xa2b05e4f,0x101896da,0xab40c66e,0x3f6033b0,
  45694. 0xc8d864ba,0x19ee9eeb,0x47bf6d2a,0xeb6cf155,0xf826477d,0x8e5a9663 } },
  45695. /* 30 */
  45696. { { 0xf7fbd5e1,0x69e62fdd,0x76912b1d,0x38ecfe54,0xd1da3bfb,0x845a3d56,
  45697. 0x1c86f0d4,0x0494950e,0x3bc36ce8,0x83cadbf9,0x4fccc8d1,0x41fce572 },
  45698. { 0x8332c144,0x05f939c2,0x0871e46e,0xb17f248b,0x66e8aff6,0x3d8534e2,
  45699. 0x3b85c629,0x1d06f1dc,0xa3131b73,0xdb06a32e,0x8b3f64e5,0xf295184d } },
  45700. /* 31 */
  45701. { { 0x36ddc103,0xd9653ff7,0x95ef606f,0x25f43e37,0xfe06dce8,0x09e301fc,
  45702. 0x30b6eebf,0x85af2341,0x0ff56b20,0x79b12b53,0xfe9a3c6b,0x9b4fb499 },
  45703. { 0x51d27ac2,0x0154f892,0x56ca5389,0xd33167e3,0xafc065a6,0x7828ec1f,
  45704. 0x7f746c9b,0x0959a258,0x0c44f837,0xb18f1be3,0xc4132fdb,0xa7946117 } },
  45705. /* 32 */
  45706. { { 0x5e3c647b,0xc0426b77,0x8cf05348,0xbfcbd939,0x172c0d3d,0x31d312e3,
  45707. 0xee754737,0x5f49fde6,0x6da7ee61,0x895530f0,0xe8b3a5fb,0xcf281b0a },
  45708. { 0x41b8a543,0xfd149735,0x3080dd30,0x41a625a7,0x653908cf,0xe2baae07,
  45709. 0xba02a278,0xc3d01436,0x7b21b8f8,0xa0d0222e,0xd7ec1297,0xfdc270e9 } },
  45710. /* 33 */
  45711. { { 0xbc7f41d6,0x00873c0c,0x1b7ad641,0xd976113e,0x238443fb,0x2a536ff4,
  45712. 0x41e62e45,0x030d00e2,0x5f545fc6,0x532e9867,0x8e91208c,0xcd033108 },
  45713. { 0x9797612c,0xd1a04c99,0xeea674e2,0xd4393e02,0xe19742a1,0xd56fa69e,
  45714. 0x85f0590e,0xdd2ab480,0x48a2243d,0xa5cefc52,0x54383f41,0x48cc67b6 } },
  45715. /* 34 */
  45716. { { 0xfc14ab48,0x4e50430e,0x26706a74,0x195b7f4f,0xcc881ff6,0x2fe8a228,
  45717. 0xd945013d,0xb1b968e2,0x4b92162b,0x936aa579,0x364e754a,0x4fb766b7 },
  45718. { 0x31e1ff7f,0x13f93bca,0xce4f2691,0x696eb5ca,0xa2b09e02,0xff754bf8,
  45719. 0xe58e3ff8,0x58f13c9c,0x1678c0b0,0xb757346f,0xa86692b3,0xd54200db } },
  45720. /* 35 */
  45721. { { 0x6dda1265,0x9a030bbd,0xe89718dd,0xf7b4f3fc,0x936065b8,0xa6a4931f,
  45722. 0x5f72241c,0xbce72d87,0x65775857,0x6cbb51cb,0x4e993675,0xc7161815 },
  45723. { 0x2ee32189,0xe81a0f79,0x277dc0b2,0xef2fab26,0xb71f469f,0x9e64f6fe,
  45724. 0xdfdaf859,0xb448ce33,0xbe6b5df1,0x3f5c1c4c,0x1de45f7b,0xfb8dfb00 } },
  45725. /* 36 */
  45726. { { 0x4d5bb921,0xc7345fa7,0x4d2b667e,0x5c7e04be,0x282d7a3e,0x47ed3a80,
  45727. 0x7e47b2a4,0x5c2777f8,0x08488e2e,0x89b3b100,0xb2eb5b45,0x9aad77c2 },
  45728. { 0xdaac34ae,0xd681bca7,0x26afb326,0x2452e4e5,0x41a1ee14,0x0c887924,
  45729. 0xc2407ade,0x743b04d4,0xfc17a2ac,0xcb5e999b,0x4a701a06,0x4dca2f82 } },
  45730. /* 37 */
  45731. { { 0x1127bc1a,0x68e31ca6,0x17ead3be,0xa3edd59b,0xe25f5a15,0x67b6b645,
  45732. 0xa420e15e,0x76221794,0x4b1e872e,0x794fd83b,0xb2dece1b,0x7cab3f03 },
  45733. { 0xca9b3586,0x7119bf15,0x4d250bd7,0xa5545924,0xcc6bcf24,0x173633ea,
  45734. 0xb1b6f884,0x9bd308c2,0x447d38c3,0x3bae06f5,0xf341fe1c,0x54dcc135 } },
  45735. /* 38 */
  45736. { { 0x943caf0d,0x56d3598d,0x225ff133,0xce044ea9,0x563fadea,0x9edf6a7c,
  45737. 0x73e8dc27,0x632eb944,0x3190dcab,0x814b467e,0x6dbb1e31,0x2d4f4f31 },
  45738. { 0xa143b7ca,0x8d69811c,0xde7cf950,0x4ec1ac32,0x37b5fe82,0x223ab5fd,
  45739. 0x9390f1d9,0xe82616e4,0x75804610,0xabff4b20,0x875b08f0,0x11b9be15 } },
  45740. /* 39 */
  45741. { { 0x3bbe682c,0x4ae31a3d,0x74eef2dd,0xbc7c5d26,0x3c47dd40,0x92afd10a,
  45742. 0xc14ab9e1,0xec7e0a3b,0xb2e495e4,0x6a6c3dd1,0x309bcd85,0x085ee5e9 },
  45743. { 0x8c2e67fd,0xf381a908,0xe261eaf2,0x32083a80,0x96deee15,0x0fcd6a49,
  45744. 0x5e524c79,0xe3b8fb03,0x1d5b08b9,0x8dc360d9,0x7f26719f,0x3a06e2c8 } },
  45745. /* 40 */
  45746. { { 0x7237cac0,0x5cd9f5a8,0x43586794,0x93f0b59d,0xe94f6c4e,0x4384a764,
  45747. 0xb62782d3,0x8304ed2b,0xcde06015,0x0b8db8b3,0x5dbe190f,0x4336dd53 },
  45748. { 0x92ab473a,0x57443553,0xbe5ed046,0x031c7275,0x21909aa4,0x3e78678c,
  45749. 0x99202ddb,0x4ab7e04f,0x6977e635,0x2648d206,0x093198be,0xd427d184 } },
  45750. /* 41 */
  45751. { { 0x0f9b5a31,0x822848f5,0xbaadb62a,0xbb003468,0x3357559c,0x233a0472,
  45752. 0x79aee843,0x49ef6880,0xaeb9e1e3,0xa89867a0,0x1f6f9a55,0xc151931b },
  45753. { 0xad74251e,0xd264eb0b,0x4abf295e,0x37b9b263,0x04960d10,0xb600921b,
  45754. 0x4da77dc0,0x0de53dbc,0xd2b18697,0x01d9bab3,0xf7156ddf,0xad54ec7a } },
  45755. /* 42 */
  45756. { { 0x79efdc58,0x8e74dc35,0x4ff68ddb,0x456bd369,0xd32096a5,0x724e74cc,
  45757. 0x386783d0,0xe41cff42,0x7c70d8a4,0xa04c7f21,0xe61a19a2,0x41199d2f },
  45758. { 0x29c05dd2,0xd389a3e0,0xe7e3fda9,0x535f2a6b,0x7c2b4df8,0x26ecf72d,
  45759. 0xfe745294,0x678275f4,0x9d23f519,0x6319c9cc,0x88048fc4,0x1e05a02d } },
  45760. /* 43 */
  45761. { { 0xd4d5ffe8,0x75cc8e2e,0xdbea17f2,0xf8bb4896,0xcee3cb4a,0x35059790,
  45762. 0xa47c6165,0x4c06ee85,0x92935d2f,0xf98fff25,0x32ffd7c7,0x34c4a572 },
  45763. { 0xea0376a2,0xc4b14806,0x4f115e02,0x2ea5e750,0x1e55d7c0,0x532d76e2,
  45764. 0xf31044da,0x68dc9411,0x71b77993,0x9272e465,0x93a8cfd5,0xadaa38bb } },
  45765. /* 44 */
  45766. { { 0x7d4ed72a,0x4bf0c712,0xba1f79a3,0xda0e9264,0xf4c39ea4,0x48c0258b,
  45767. 0x2a715138,0xa5394ed8,0xbf06c660,0x4af511ce,0xec5c37cd,0xfcebceef },
  45768. { 0x779ae8c1,0xf23b75aa,0xad1e606e,0xdeff59cc,0x22755c82,0xf3f526fd,
  45769. 0xbb32cefd,0x64c5ab44,0x915bdefd,0xa96e11a2,0x1143813e,0xab19746a } },
  45770. /* 45 */
  45771. { { 0xec837d7d,0x43c78585,0xb8ee0ba4,0xca5b6fbc,0xd5dbb5ee,0x34e924d9,
  45772. 0xbb4f1ca5,0x3f4fa104,0x398640f7,0x15458b72,0xd7f407ea,0x4231faa9 },
  45773. { 0xf96e6896,0x53e0661e,0xd03b0f9d,0x554e4c69,0x9c7858d1,0xd4fcb07b,
  45774. 0x52cb04fa,0x7e952793,0x8974e7f7,0x5f5f1574,0x6b6d57c8,0x2e3fa558 } },
  45775. /* 46 */
  45776. { { 0x6a9951a8,0x42cd4803,0x42792ad0,0xa8b15b88,0xabb29a73,0x18e8bcf9,
  45777. 0x409933e8,0xbfd9a092,0xefb88dc4,0x760a3594,0x40724458,0x14418863 },
  45778. { 0x99caedc7,0x162a56ee,0x91d101c9,0x8fb12ecd,0x393202da,0xea671967,
  45779. 0xa4ccd796,0x1aac8c4a,0x1cf185a8,0x7db05036,0x8cfd095a,0x0c9f86cd } },
  45780. /* 47 */
  45781. { { 0x10b2a556,0x9a728147,0x327b70b2,0x767ca964,0x5e3799b7,0x04ed9e12,
  45782. 0x22a3eb2a,0x6781d2dc,0x0d9450ac,0x5bd116eb,0xa7ebe08a,0xeccac1fc },
  45783. { 0xdc2d6e94,0xde68444f,0x35ecf21b,0x3621f429,0x29e03a2c,0x14e2d543,
  45784. 0x7d3e7f0a,0x53e42cd5,0x73ed00b9,0xbba26c09,0xc57d2272,0x00297c39 } },
  45785. /* 48 */
  45786. { { 0xb8243a7d,0x3aaaab10,0x8fa58c5b,0x6eeef93e,0x9ae7f764,0xf866fca3,
  45787. 0x61ab04d3,0x64105a26,0x03945d66,0xa3578d8a,0x791b848c,0xb08cd3e4 },
  45788. { 0x756d2411,0x45edc5f8,0xa755128c,0xd4a790d9,0x49e5f6a0,0xc2cf0963,
  45789. 0xf649beaa,0xc66d267d,0x8467039e,0x3ce6d968,0x42f7816f,0x50046c6b } },
  45790. /* 49 */
  45791. { { 0x66425043,0x92ae1602,0xf08db890,0x1ff66afd,0x8f162ce5,0x386f5a7f,
  45792. 0xfcf5598f,0x18d2dea0,0x1a8ca18e,0x78372b3a,0x8cd0e6f7,0xdf0d20eb },
  45793. { 0x75bb4045,0x7edd5e1d,0xb96d94b7,0x252a47ce,0x2c626776,0xbdb29358,
  45794. 0x40dd1031,0x853c3943,0x7d5f47fd,0x9dc9becf,0xbae4044a,0x27c2302f } },
  45795. /* 50 */
  45796. { { 0x8f2d49ce,0x2d1d208a,0x162df0a2,0x0d91aa02,0x09a07f65,0x9c5cce87,
  45797. 0x84339012,0xdf07238b,0x419442cd,0x5028e2c8,0x72062aba,0x2dcbd358 },
  45798. { 0xe4680967,0xb5fbc3cb,0x9f92d72c,0x2a7bc645,0x116c369d,0x806c76e1,
  45799. 0x3177e8d8,0x5c50677a,0x4569df57,0x753739eb,0x36c3f40b,0x2d481ef6 } },
  45800. /* 51 */
  45801. { { 0xfea1103e,0x1a2d39fd,0x95f81b17,0xeaae5592,0xf59b264a,0xdbd0aa18,
  45802. 0xcb592ee0,0x90c39c1a,0x9750cca3,0xdf62f80d,0xdf97cc6c,0xda4d8283 },
  45803. { 0x1e201067,0x0a6dd346,0x69fb1f6b,0x1531f859,0x1d60121f,0x4895e552,
  45804. 0x4c041c91,0x0b21aab0,0xbcc1ccf8,0x9d896c46,0x3141bde7,0xd24da3b3 } },
  45805. /* 52 */
  45806. { { 0x53b0a354,0x575a0537,0x0c6ddcd8,0x392ff2f4,0x56157b94,0x0b8e8cff,
  45807. 0x3b1b80d1,0x073e57bd,0x3fedee15,0x2a75e0f0,0xaa8e6f19,0x752380e4 },
  45808. { 0x6558ffe9,0x1f4e227c,0x19ec5415,0x3a348618,0xf7997085,0xab382d5e,
  45809. 0xddc46ac2,0x5e6deaff,0xfc8d094c,0xe5144078,0xf60e37c6,0xf674fe51 } },
  45810. /* 53 */
  45811. { { 0xaf63408f,0x6fb87ae5,0xcd75a737,0xa39c36a9,0xcf4c618d,0x7833313f,
  45812. 0xf034c88d,0xfbcd4482,0x39b35288,0x4469a761,0x66b5d9c9,0x77a711c5 },
  45813. { 0x944f8d65,0x4a695dc7,0x161aaba8,0xe6da5f65,0x24601669,0x8654e9c3,
  45814. 0x28ae7491,0xbc8b93f5,0x8f5580d8,0x5f1d1e83,0xcea32cc8,0x8ccf9a1a } },
  45815. /* 54 */
  45816. { { 0x7196fee2,0x28ab110c,0x874c8945,0x75799d63,0x29aedadd,0xa2629348,
  45817. 0x2be88ff4,0x9714cc7b,0xd58d60d6,0xf71293cf,0x32a564e9,0xda6b6cb3 },
  45818. { 0x3dd821c2,0xf43fddb1,0x90dd323d,0xf2f2785f,0x048489f8,0x91246419,
  45819. 0xd24c6749,0x61660f26,0xc803c15c,0x961d9e8c,0xfaadc4c9,0x631c6158 } },
  45820. /* 55 */
  45821. { { 0xfd752366,0xacf2ebe0,0x139be88b,0xb93c340e,0x0f20179e,0x98f66485,
  45822. 0xff1da785,0x14820254,0x4f85c16e,0x5278e276,0x7aab1913,0xa246ee45 },
  45823. { 0x53763b33,0x43861eb4,0x45c0bc0d,0xc49f03fc,0xad6b1ea1,0xafff16bc,
  45824. 0x6fd49c99,0xce33908b,0xf7fde8c3,0x5c51e9bf,0xff142c5e,0x076a7a39 } },
  45825. /* 56 */
  45826. { { 0x9e338d10,0x04639dfe,0xf42b411b,0x8ee6996f,0xa875cef2,0x960461d1,
  45827. 0x95b4d0ba,0x1057b6d6,0xa906e0bc,0x27639252,0xe1c20f8a,0x2c19f09a },
  45828. { 0xeef4c43d,0x5b8fc3f0,0x07a84aa9,0xe2e1b1a8,0x835d2bdb,0x5f455528,
  45829. 0x207132dd,0x0f4aee4d,0x3907f675,0xe9f8338c,0x0e0531f0,0x7a874dc9 } },
  45830. /* 57 */
  45831. { { 0x97c27050,0x84b22d45,0x59e70bf8,0xbd0b8df7,0x79738b9b,0xb4d67405,
  45832. 0xcd917c4f,0x47f4d5f5,0x13ce6e33,0x9099c4ce,0x521d0f8b,0x942bfd39 },
  45833. { 0xa43b566d,0x5028f0f6,0x21bff7de,0xaf6e8669,0xc44232cd,0x83f6f856,
  45834. 0xf915069a,0x65680579,0xecfecb85,0xd12095a2,0xdb01ba16,0xcf7f06ae } },
  45835. /* 58 */
  45836. { { 0x8ef96c80,0x0f56e3c4,0x3ddb609c,0xd521f2b3,0x7dc1450d,0x2be94102,
  45837. 0x02a91fe2,0x2d21a071,0x1efa37de,0x2e6f74fa,0x156c28a1,0x9a9a90b8 },
  45838. { 0x9dc7dfcb,0xc54ea9ea,0x2c2c1d62,0xc74e66fc,0x49d3e067,0x9f23f967,
  45839. 0x54dd38ad,0x1c7c3a46,0x5946cee3,0xc7005884,0x45cc045d,0x89856368 } },
  45840. /* 59 */
  45841. { { 0xfce73946,0x29da7cd4,0x23168563,0x8f697db5,0xcba92ec6,0x8e235e9c,
  45842. 0x9f91d3ea,0x55d4655f,0xaa50a6cd,0xf3689f23,0x21e6a1a0,0xdcf21c26 },
  45843. { 0x61b818bf,0xcffbc82e,0xda47a243,0xc74a2f96,0x8bc1a0cf,0x234e980a,
  45844. 0x7929cb6d,0xf35fd6b5,0xefe17d6c,0x81468e12,0x58b2dafb,0xddea6ae5 } },
  45845. /* 60 */
  45846. { { 0x7e787b2e,0x294de887,0x39a9310d,0x258acc1f,0xac14265d,0x92d9714a,
  45847. 0x708b48a0,0x18b5591c,0xe1abbf71,0x27cc6bb0,0x568307b9,0xc0581fa3 },
  45848. { 0xf24d4d58,0x9e0f58a3,0xe0ce2327,0xfebe9bb8,0x9d1be702,0x91fd6a41,
  45849. 0xfacac993,0x9a7d8a45,0x9e50d66d,0xabc0a08c,0x06498201,0x02c342f7 } },
  45850. /* 61 */
  45851. { { 0x157bdbc2,0xccd71407,0xad0e1605,0x72fa89c6,0xb92a015f,0xb1d3da2b,
  45852. 0xa0a3fe56,0x8ad9e7cd,0x24f06737,0x160edcbd,0x61275be6,0x79d4db33 },
  45853. { 0x5f3497c4,0xd3d31fd9,0x04192fb0,0x8cafeaee,0x13a50af3,0xe13ca745,
  45854. 0x8c85aae5,0x18826167,0x9eb556ff,0xce06cea8,0xbdb549f3,0x2eef1995 } },
  45855. /* 62 */
  45856. { { 0x50596edc,0x8ed7d3eb,0x905243a2,0xaa359362,0xa4b6d02b,0xa212c2c2,
  45857. 0xc4fbec68,0x611fd727,0xb84f733d,0x8a0b8ff7,0x5f0daf0e,0xd85a6b90 },
  45858. { 0xd4091cf7,0x60e899f5,0x2eff2768,0x4fef2b67,0x10c33964,0xc1f195cb,
  45859. 0x93626a8f,0x8275d369,0x0d6c840a,0xc77904f4,0x7a868acd,0x88d8b7fd } },
  45860. /* 63 */
  45861. { { 0x7bd98425,0x85f23723,0xc70b154e,0xd4463992,0x96687a2e,0xcbb00ee2,
  45862. 0xc83214fd,0x905fdbf7,0x13593684,0x2019d293,0xef51218e,0x0428c393 },
  45863. { 0x981e909a,0x40c7623f,0x7be192da,0x92513385,0x4010907e,0x48fe480f,
  45864. 0x3120b459,0xdd7a187c,0xa1fd8f3c,0xc9d7702d,0xe358efc5,0x66e4753b } },
  45865. /* 64 */
  45866. { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9,
  45867. 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 },
  45868. { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1,
  45869. 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } },
  45870. /* 65 */
  45871. { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc,
  45872. 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a },
  45873. { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18,
  45874. 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } },
  45875. /* 66 */
  45876. { { 0xc6a2123f,0xb1a358f5,0xfe28df6d,0x927b2d95,0xf199d2f9,0x89702753,
  45877. 0x1a3f82dc,0x0a73754c,0x777affe1,0x063d029d,0xdae6d34d,0x5439817e },
  45878. { 0x6b8b83c4,0xf7979eef,0x9d945682,0x615cb214,0xc5e57eae,0x8f0e4fac,
  45879. 0x113047dd,0x042b89b8,0x93f36508,0x888356dc,0x5fd1f32f,0xbf008d18 } },
  45880. /* 67 */
  45881. { { 0x4e8068db,0x8012aa24,0xa5729a47,0xc72cc641,0x43f0691d,0x3c33df2c,
  45882. 0x1d92145f,0xfa057347,0xb97f7946,0xaefc0f2f,0x2f8121bf,0x813d75cb },
  45883. { 0x4383bba6,0x05613c72,0xa4224b3f,0xa924ce70,0x5f2179a6,0xe59cecbe,
  45884. 0x79f62b61,0x78e2e8aa,0x53ad8079,0x3ac2cc3b,0xd8f4fa96,0x55518d71 } },
  45885. /* 68 */
  45886. { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247,
  45887. 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 },
  45888. { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d,
  45889. 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } },
  45890. /* 69 */
  45891. { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12,
  45892. 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e },
  45893. { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f,
  45894. 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } },
  45895. /* 70 */
  45896. { { 0xb0ab9645,0xb5e405d3,0xd5f1f711,0xaeec7f98,0x585c2a6e,0x8ad42311,
  45897. 0x512c6944,0x045acb9e,0xa90db1c6,0xae106c4e,0x898e6563,0xb89f33d5 },
  45898. { 0x7fed2ce4,0x43b07cd9,0xdd815b20,0xf9934e17,0x0a81a349,0x6778d4d5,
  45899. 0x52918061,0x9e616ade,0xd7e67112,0xfa06db06,0x88488091,0x1da23cf1 } },
  45900. /* 71 */
  45901. { { 0x42f2c4b5,0x821c46b3,0x66059e47,0x931513ef,0x66f50cd1,0x7030ae43,
  45902. 0x43e7b127,0x43b536c9,0x5fca5360,0x006258cf,0x6b557abf,0xe4e3ee79 },
  45903. { 0x24c8b22f,0xbb6b3900,0xfcbf1054,0x2eb5e2c1,0x567492af,0x937b18c9,
  45904. 0xacf53957,0xf09432e4,0x1dbf3a56,0x585f5a9d,0xbe0887cf,0xf86751fd } },
  45905. /* 72 */
  45906. { { 0x9d10e0b2,0x157399cb,0x60dc51b7,0x1c0d5956,0x1f583090,0x1d496b8a,
  45907. 0x88590484,0x6658bc26,0x03213f28,0x88c08ab7,0x7ae58de4,0x8d2e0f73 },
  45908. { 0x486cfee6,0x9b79bc95,0xe9e5bc57,0x036a26c7,0xcd8ae97a,0x1ad03601,
  45909. 0xff3a0494,0x06907f87,0x2c7eb584,0x078f4bbf,0x7e8d0a5a,0xe3731bf5 } },
  45910. /* 73 */
  45911. { { 0xe1cd0abe,0x72f2282b,0x87efefa2,0xd4f9015e,0x6c3834bd,0x9d189806,
  45912. 0xb8a29ced,0x9c8cdcc1,0xfee82ebc,0x0601b9f4,0x7206a756,0x371052bc },
  45913. { 0x46f32562,0x76fa1092,0x17351bb4,0xdaad534c,0xb3636bb5,0xc3d64c37,
  45914. 0x45d54e00,0x038a8c51,0x32c09e7c,0x301e6180,0x95735151,0x9764eae7 } },
  45915. /* 74 */
  45916. { { 0xcbd5256a,0x8791b19f,0x6ca13a3b,0x4007e0f2,0x4cf06904,0x03b79460,
  45917. 0xb6c17589,0xb18a9c22,0x81d45908,0xa1cb7d7d,0x21bb68f1,0x6e13fa9d },
  45918. { 0xa71e6e16,0x47183c62,0xe18749ed,0x5cf0ef8e,0x2e5ed409,0x2c9c7f9b,
  45919. 0xe6e117e1,0x042eeacc,0x13fb5a7f,0xb86d4816,0xc9e5feb1,0xea1cf0ed } },
  45920. /* 75 */
  45921. { { 0xcea4cc9b,0x6e6573c9,0xafcec8f3,0x5417961d,0xa438b6f6,0x804bf02a,
  45922. 0xdcd4ea88,0xb894b03c,0x3799571f,0xd0f807e9,0x862156e8,0x3466a7f5 },
  45923. { 0x56515664,0x51e59acd,0xa3c5eb0b,0x55b0f93c,0x6a4279db,0x84a06b02,
  45924. 0xc5fae08e,0x5c850579,0xa663a1a2,0xcf07b8db,0xf46ffc8d,0x49a36bbc } },
  45925. /* 76 */
  45926. { { 0x46d93106,0xe47f5acc,0xaa897c9c,0x65b7ade0,0x12d7e4be,0x37cf4c94,
  45927. 0xd4b2caa9,0xa2ae9b80,0xe60357a3,0x5e7ce09c,0xc8ecd5f9,0x29f77667 },
  45928. { 0xa8a0b1c5,0xdf6868f5,0x62978ad8,0x240858cf,0xdc0002a1,0x0f7ac101,
  45929. 0xffe9aa05,0x1d28a9d7,0x5b962c97,0x744984d6,0x3d28c8b2,0xa8a7c00b } },
  45930. /* 77 */
  45931. { { 0xae11a338,0x7c58a852,0xd1af96e7,0xa78613f1,0x5355cc73,0x7e9767d2,
  45932. 0x792a2de6,0x6ba37009,0x124386b2,0x7d60f618,0x11157674,0xab09b531 },
  45933. { 0x98eb9dd0,0x95a04841,0x15070328,0xe6c17acc,0x489c6e49,0xafc6da45,
  45934. 0xbb211530,0xab45a60a,0x7d7ea933,0xc58d6592,0x095642c6,0xa3ef3c65 } },
  45935. /* 78 */
  45936. { { 0xdf010879,0x89d420e9,0x39576179,0x9d25255d,0xe39513b6,0x9cdefd50,
  45937. 0xd5d1c313,0xe4efe45b,0x3f7af771,0xc0149de7,0x340ab06b,0x55a6b4f4 },
  45938. { 0xebeaf771,0xf1325251,0x878d4288,0x2ab44128,0x18e05afe,0xfcd5832e,
  45939. 0xcc1fb62b,0xef52a348,0xc1c4792a,0x2bd08274,0x877c6dc7,0x345c5846 } },
  45940. /* 79 */
  45941. { { 0xbea65e90,0xde15ceb0,0x2416d99c,0x0987f72b,0xfd863dec,0x44db578d,
  45942. 0xac6a3578,0xf617b74b,0xdb48e999,0x9e62bd7a,0xeab1a1be,0x877cae61 },
  45943. { 0x3a358610,0x23adddaa,0x325e2b07,0x2fc4d6d1,0x1585754e,0x897198f5,
  45944. 0xb392b584,0xf741852c,0xb55f7de1,0x9927804c,0x1aa8efae,0xe9e6c4ed } },
  45945. /* 80 */
  45946. { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe,
  45947. 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 },
  45948. { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6,
  45949. 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } },
  45950. /* 81 */
  45951. { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6,
  45952. 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 },
  45953. { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf,
  45954. 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } },
  45955. /* 82 */
  45956. { { 0xf8e60f5b,0x511188b4,0x48aa2ada,0x7fe67015,0x381abca2,0xdb333cb8,
  45957. 0xdaf3fc97,0xb15e6d9d,0x36aabc03,0x4b24f6eb,0x72a748b4,0xc59789df },
  45958. { 0x29cf5279,0x26fcb8a5,0x01ad9a6c,0x7a3c6bfc,0x4b8bac9b,0x866cf88d,
  45959. 0x9c80d041,0xf4c89989,0x70add148,0xf0a04241,0x45d81a41,0x5a02f479 } },
  45960. /* 83 */
  45961. { { 0xc1c90202,0xfa5c877c,0xf8ac7570,0xd099d440,0xd17881f7,0x428a5b1b,
  45962. 0x5b2501d7,0x61e267db,0xf2e4465b,0xf889bf04,0x76aa4cb8,0x4da3ae08 },
  45963. { 0xe3e66861,0x3ef0fe26,0x3318b86d,0x5e772953,0x747396df,0xc3c35fbc,
  45964. 0x439ffd37,0x5115a29c,0xb2d70374,0xbfc4bd97,0x56246b9d,0x088630ea } },
  45965. /* 84 */
  45966. { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53,
  45967. 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 },
  45968. { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370,
  45969. 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } },
  45970. /* 85 */
  45971. { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f,
  45972. 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc },
  45973. { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2,
  45974. 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } },
  45975. /* 86 */
  45976. { { 0xfecf5b9b,0x34e0f9d1,0xf206966a,0xa115b12b,0x1eaa0534,0x5591cf3b,
  45977. 0xfb1558f9,0x5f0293cb,0x1bc703a5,0x1c8507a4,0x862c1f81,0x92e6b81c },
  45978. { 0xcdaf24e3,0xcc9ebc66,0x72fcfc70,0x68917ecd,0x8157ba48,0x6dc9a930,
  45979. 0xb06ab2b2,0x5d425c08,0x36e929c4,0x362f8ce7,0x62e89324,0x09f6f57c } },
  45980. /* 87 */
  45981. { { 0xd29375fb,0x1c7d6b78,0xe35d1157,0xfabd851e,0x4243ea47,0xf6f62dcd,
  45982. 0x8fe30b0f,0x1dd92460,0xffc6e709,0x08166dfa,0x0881e6a7,0xc6c4c693 },
  45983. { 0xd6a53fb0,0x20368f87,0x9eb4d1f9,0x38718e9f,0xafd7e790,0x03f08acd,
  45984. 0x72fe2a1c,0x0835eb44,0x88076e5d,0x7e050903,0xa638e731,0x538f765e } },
  45985. /* 88 */
  45986. { { 0xc2663b4b,0x0e0249d9,0x47cd38dd,0xe700ab5b,0x2c46559f,0xb192559d,
  45987. 0x4bcde66d,0x8f9f74a8,0x3e2aced5,0xad161523,0x3dd03a5b,0xc155c047 },
  45988. { 0x3be454eb,0x346a8799,0x83b7dccd,0x66ee94db,0xab9d2abe,0x1f6d8378,
  45989. 0x7733f355,0x4a396dd2,0xf53553c2,0x419bd40a,0x731dd943,0xd0ead98d } },
  45990. /* 89 */
  45991. { { 0xec142408,0x908e0b0e,0x4114b310,0x98943cb9,0x1742b1d7,0x03dbf7d8,
  45992. 0x693412f4,0xd270df6b,0x8f69e20c,0xc5065494,0x697e43a1,0xa76a90c3 },
  45993. { 0x4624825a,0xe0fa3384,0x8acc34c2,0x82e48c0b,0xe9a14f2b,0x7b24bd14,
  45994. 0x4db30803,0x4f5dd5e2,0x932da0a3,0x0c77a9e7,0x74c653dc,0x20db90f2 } },
  45995. /* 90 */
  45996. { { 0x0e6c5fd9,0x261179b7,0x6c982eea,0xf8bec123,0xd4957b7e,0x47683338,
  45997. 0x0a72f66a,0xcc47e664,0x1bad9350,0xbd54bf6a,0xf454e95a,0xdfbf4c6a },
  45998. { 0x6907f4fa,0x3f7a7afa,0x865ca735,0x7311fae0,0x2a496ada,0x24737ab8,
  45999. 0x15feb79b,0x13e425f1,0xa1b93c21,0xe9e97c50,0x4ddd3eb5,0xb26b6eac } },
  46000. /* 91 */
  46001. { { 0x2a2e5f2b,0x81cab9f5,0xbf385ac4,0xf93caf29,0xc909963a,0xf4bf35c3,
  46002. 0x74c9143c,0x081e7300,0xc281b4c5,0x3ea57fa8,0x9b340741,0xe497905c },
  46003. { 0x55ab3cfb,0xf556dd8a,0x518db6ad,0xd444b96b,0x5ef4b955,0x34f5425a,
  46004. 0xecd26aa3,0xdda7a3ac,0xda655e97,0xb57da11b,0xc2024c70,0x02da3eff } },
  46005. /* 92 */
  46006. { { 0x6481d0d9,0xe24b0036,0x818fdfe2,0x3740dbe5,0x190fda00,0xc1fc1f45,
  46007. 0x3cf27fde,0x329c9280,0x6934f43e,0x7435cb53,0x7884e8fe,0x2b505a5d },
  46008. { 0x711adcc9,0x6cfcc6a6,0x531e21e1,0xf034325c,0x9b2a8a99,0xa2f4a967,
  46009. 0x3c21bdff,0x9d5f3842,0x31b57d66,0xb25c7811,0x0b8093b9,0xdb5344d8 } },
  46010. /* 93 */
  46011. { { 0xae50a2f5,0x0d72e667,0xe4a861d1,0x9b7f8d8a,0x330df1cb,0xa129f70f,
  46012. 0xe04fefc3,0xe90aa5d7,0xe72c3ae1,0xff561ecb,0xcdb955fa,0x0d8fb428 },
  46013. { 0xd7663784,0xd2235f73,0x7e2c456a,0xc05baec6,0x2adbfccc,0xe5c292e4,
  46014. 0xefb110d5,0x4fd17988,0xd19d49f3,0x27e57734,0x84f679fe,0x188ac4ce } },
  46015. /* 94 */
  46016. { { 0xa796c53e,0x7ee344cf,0x0868009b,0xbbf6074d,0x474a1295,0x1f1594f7,
  46017. 0xac11632d,0x66776edc,0x04e2fa5a,0x1862278b,0xc854a89a,0x52665cf2 },
  46018. { 0x8104ab58,0x7e376464,0x7204fd6d,0x16775913,0x44ea1199,0x86ca06a5,
  46019. 0x1c9240dd,0xaa3f765b,0x24746149,0x5f8501a9,0xdcd251d7,0x7b982e30 } },
  46020. /* 95 */
  46021. { { 0xc15f3060,0xe44e9efc,0xa87ebbe6,0x5ad62f2e,0xc79500d4,0x36499d41,
  46022. 0x336fa9d1,0xa66d6dc0,0x5afd3b1f,0xf8afc495,0xe5c9822b,0x1d8ccb24 },
  46023. { 0x79d7584b,0x4031422b,0xea3f20dd,0xc54a0580,0x958468c5,0x3f837c8f,
  46024. 0xfbea7735,0x3d82f110,0x7dffe2fc,0x679a8778,0x20704803,0x48eba63b } },
  46025. /* 96 */
  46026. { { 0xdf46e2f6,0x89b10d41,0x19514367,0x13ab57f8,0x1d469c87,0x067372b9,
  46027. 0x4f6c5798,0x0c195afa,0x272c9acf,0xea43a12a,0x678abdac,0x9dadd8cb },
  46028. { 0xe182579a,0xcce56c6b,0x2d26c2d8,0x86febadb,0x2a44745c,0x1c668ee1,
  46029. 0x98dc047a,0x580acd86,0x51b9ec2d,0x5a2b79cc,0x4054f6a0,0x007da608 } },
  46030. /* 97 */
  46031. { { 0x17b00dd0,0x9e3ca352,0x0e81a7a6,0x046779cb,0xd482d871,0xb999fef3,
  46032. 0xd9233fbc,0xe6f38134,0xf48cd0e0,0x112c3001,0x3c6c66ae,0x934e7576 },
  46033. { 0xd73234dc,0xb44d4fc3,0x864eafc1,0xfcae2062,0x26bef21a,0x843afe25,
  46034. 0xf3b75fdf,0x61355107,0x794c2e6b,0x8367a5aa,0x8548a372,0x3d2629b1 } },
  46035. /* 98 */
  46036. { { 0x437cfaf8,0x6230618f,0x2032c299,0x5b8742cb,0x2293643a,0x949f7247,
  46037. 0x09464f79,0xb8040f1a,0x4f254143,0x049462d2,0x366c7e76,0xabd6b522 },
  46038. { 0xd5338f55,0x119b392b,0x01495a0c,0x1a80a9ce,0xf8d7537e,0xf3118ca7,
  46039. 0x6bf4b762,0xb715adc2,0xa8482b6c,0x24506165,0x96a7c84d,0xd958d7c6 } },
  46040. /* 99 */
  46041. { { 0xbdc21f31,0x9ad8aa87,0x8063e58c,0xadb3cab4,0xb07dd7b8,0xefd86283,
  46042. 0x1be7c6b4,0xc7b9b762,0x015582de,0x2ef58741,0x299addf3,0xc970c52e },
  46043. { 0x22f24d66,0x78f02e2a,0x74cc100a,0xefec1d10,0x09316e1a,0xaf2a6a39,
  46044. 0x5849dd49,0xce7c2205,0x96bffc4c,0x9c1fe75c,0x7ba06ec0,0xcad98fd2 } },
  46045. /* 100 */
  46046. { { 0xb648b73e,0xed76e2d0,0x1cfd285e,0xa9f92ce5,0x2ed13de1,0xa8c86c06,
  46047. 0xa5191a93,0x1d3a574e,0x1ad1b8bf,0x385cdf8b,0x47d2cfe3,0xbbecc28a },
  46048. { 0x69cec548,0x98d326c0,0xf240a0b2,0x4f5bc1dd,0x29057236,0x241a7062,
  46049. 0xc68294a4,0x0fc6e9c5,0xa319f17a,0x4d04838b,0x9ffc1c6f,0x8b612cf1 } },
  46050. /* 101 */
  46051. { { 0x4c3830eb,0x9bb0b501,0x8ee0d0c5,0x3d08f83c,0x79ba9389,0xa4a62642,
  46052. 0x9cbc2914,0x5d5d4044,0x074c46f0,0xae9eb83e,0x74ead7d6,0x63bb758f },
  46053. { 0xc6bb29e0,0x1c40d2ea,0x4b02f41e,0x95aa2d87,0x53cb199a,0x92989175,
  46054. 0x51584f6d,0xdd91bafe,0x31a1aaec,0x3715efb9,0x46780f9e,0xc1b6ae5b } },
  46055. /* 102 */
  46056. { { 0x42772f41,0xcded3e4b,0x3bcb79d1,0x3a700d5d,0x80feee60,0x4430d50e,
  46057. 0xf5e5d4bb,0x444ef1fc,0xe6e358ff,0xc660194f,0x6a91b43c,0xe68a2f32 },
  46058. { 0x977fe4d2,0x5842775c,0x7e2a41eb,0x78fdef5c,0xff8df00e,0x5f3bec02,
  46059. 0x5852525d,0xf4b840cd,0x4e6988bd,0x0870483a,0xcc64b837,0x39499e39 } },
  46060. /* 103 */
  46061. { { 0xb08df5fe,0xfc05de80,0x63ba0362,0x0c12957c,0xd5cf1428,0xea379414,
  46062. 0x54ef6216,0xc559132a,0xb9e65cf8,0x33d5f12f,0x1695d663,0x09c60278 },
  46063. { 0x61f7a2fb,0x3ac1ced4,0xd4f5eeb8,0xdd838444,0x8318fcad,0x82a38c6c,
  46064. 0xe9f1a864,0x315be2e5,0x442daf47,0x317b5771,0x95aa5f9e,0x81b5904a } },
  46065. /* 104 */
  46066. { { 0x8b21d232,0x6b6b1c50,0x8c2cba75,0x87f3dbc0,0xae9f0faf,0xa7e74b46,
  46067. 0xbb7b8079,0x036a0985,0x8d974a25,0x4f185b90,0xd9af5ec9,0x5aa7cef0 },
  46068. { 0x57dcfffc,0xe0566a70,0xb8453225,0x6ea311da,0x23368aa9,0x72ea1a8d,
  46069. 0x48cd552d,0xed9b2083,0xc80ea435,0xb987967c,0x6c104173,0xad735c75 } },
  46070. /* 105 */
  46071. { { 0xcee76ef4,0xaea85ab3,0xaf1d2b93,0x44997444,0xeacb923f,0x0851929b,
  46072. 0x51e3bc0c,0xb080b590,0x59be68a2,0xc4ee1d86,0x64b26cda,0xf00de219 },
  46073. { 0xf2e90d4d,0x8d7fb5c0,0x77d9ec64,0x00e219a7,0x5d1c491c,0xc4e6febd,
  46074. 0x1a8f4585,0x080e3754,0x48d2af9c,0x4a9b86c8,0xb6679851,0x2ed70db6 } },
  46075. /* 106 */
  46076. { { 0x586f25cb,0xaee44116,0xa0fcf70f,0xf7b6861f,0x18a350e8,0x55d2cd20,
  46077. 0x92dc286f,0x861bf3e5,0x6226aba7,0x9ab18ffa,0xa9857b03,0xd15827be },
  46078. { 0x92e6acef,0x26c1f547,0xac1fbac3,0x422c63c8,0xfcbfd71d,0xa2d8760d,
  46079. 0xb2511224,0x35f6a539,0x048d1a21,0xbaa88fa1,0xebf999db,0x49f1abe9 } },
  46080. /* 107 */
  46081. { { 0xf7492b73,0x16f9f4f4,0xcb392b1a,0xcf28ec1e,0x69ca6ffc,0x45b130d4,
  46082. 0xb72efa58,0x28ba8d40,0x5ca066f5,0xace987c7,0x4ad022eb,0x3e399246 },
  46083. { 0x752555bb,0x63a2d84e,0x9c2ae394,0xaaa93b4a,0xc89539ca,0xcd80424e,
  46084. 0xaa119a99,0x6d6b5a6d,0x379f2629,0xbd50334c,0xef3cc7d3,0x899e925e } },
  46085. /* 108 */
  46086. { { 0xbf825dc4,0xb7ff3651,0x40b9c462,0x0f741cc4,0x5cc4fb5b,0x771ff5a9,
  46087. 0x47fd56fe,0xcb9e9c9b,0x5626c0d3,0xbdf053db,0xf7e14098,0xa97ce675 },
  46088. { 0x6c934f5e,0x68afe5a3,0xccefc46f,0x6cd5e148,0xd7a88586,0xc7758570,
  46089. 0xdd558d40,0x49978f5e,0x64ae00c1,0xa1d5088a,0xf1d65bb2,0x58f2a720 } },
  46090. /* 109 */
  46091. { { 0x3e4daedb,0x66fdda4a,0x65d1b052,0x38318c12,0x4c4bbf5c,0x28d910a2,
  46092. 0x78a9cd14,0x762fe5c4,0xd2cc0aee,0x08e5ebaa,0xca0c654c,0xd2cdf257 },
  46093. { 0x08b717d2,0x48f7c58b,0x386cd07a,0x3807184a,0xae7d0112,0x3240f626,
  46094. 0xc43917b0,0x03e9361b,0x20aea018,0xf261a876,0x7e1e6372,0x53f556a4 } },
  46095. /* 110 */
  46096. { { 0x2f512a90,0xc84cee56,0x1b0ea9f1,0x24b3c004,0xe26cc1ea,0x0ee15d2d,
  46097. 0xf0c9ef7d,0xd848762c,0xd5341435,0x1026e9c5,0xfdb16b31,0x8f5b73dc },
  46098. { 0xd2c75d95,0x1f69bef2,0xbe064dda,0x8d33d581,0x57ed35e6,0x8c024c12,
  46099. 0xc309c281,0xf8d435f9,0xd6960193,0xfd295061,0xe9e49541,0x66618d78 } },
  46100. /* 111 */
  46101. { { 0x8ce382de,0x571cfd45,0xde900dde,0x175806ee,0x34aba3b5,0x61849965,
  46102. 0xde7aec95,0xe899778a,0xff4aa97f,0xe8f00f6e,0x010b0c6d,0xae971cb5 },
  46103. { 0x3af788f1,0x1827eebc,0xe413fe2d,0xd46229ff,0x4741c9b4,0x8a15455b,
  46104. 0xf8e424eb,0x5f02e690,0xdae87712,0x40a1202e,0x64944f6d,0x49b3bda2 } },
  46105. /* 112 */
  46106. { { 0x035b2d69,0xd63c6067,0x6bed91b0,0xb507150d,0x7afb39b2,0x1f35f82f,
  46107. 0x16012b66,0xb9bd9c01,0xed0a5f50,0x00d97960,0x2716f7c9,0xed705451 },
  46108. { 0x127abdb4,0x1576eff4,0xf01e701c,0x6850d698,0x3fc87e2f,0x9fa7d749,
  46109. 0xb0ce3e48,0x0b6bcc6f,0xf7d8c1c0,0xf4fbe1f5,0x02719cc6,0xcf75230e } },
  46110. /* 113 */
  46111. { { 0x722d94ed,0x6761d6c2,0x3718820e,0xd1ec3f21,0x25d0e7c6,0x65a40b70,
  46112. 0xbaf3cf31,0xd67f830e,0xb93ea430,0x633b3807,0x0bc96c69,0x17faa0ea },
  46113. { 0xdf866b98,0xe6bf3482,0xa9db52d4,0x205c1ee9,0xff9ab869,0x51ef9bbd,
  46114. 0x75eeb985,0x3863dad1,0xd3cf442a,0xef216c3b,0xf9c8e321,0x3fb228e3 } },
  46115. /* 114 */
  46116. { { 0x0760ac07,0x94f9b70c,0x9d79bf4d,0xf3c9ccae,0xc5ffc83d,0x73cea084,
  46117. 0xdc49c38e,0xef50f943,0xbc9e7330,0xf467a2ae,0x44ea7fba,0x5ee534b6 },
  46118. { 0x03609e7f,0x20cb6272,0x62fdc9f0,0x09844355,0x0f1457f7,0xaf5c8e58,
  46119. 0xb4b25941,0xd1f50a6c,0x2ec82395,0x77cb247c,0xda3dca33,0xa5f3e1e5 } },
  46120. /* 115 */
  46121. { { 0x7d85fa94,0x023489d6,0x2db9ce47,0x0ba40537,0xaed7aad1,0x0fdf7a1f,
  46122. 0x9a4ccb40,0xa57b0d73,0x5b18967c,0x48fcec99,0xb7274d24,0xf30b5b6e },
  46123. { 0xc81c5338,0x7ccb4773,0xa3ed6bd0,0xb85639e6,0x1d56eada,0x7d9df95f,
  46124. 0x0a1607ad,0xe256d57f,0x957574d6,0x6da7ffdc,0x01c7a8c4,0x65f84046 } },
  46125. /* 116 */
  46126. { { 0xcba1e7f1,0x8d45d0cb,0x02b55f64,0xef0a08c0,0x17e19892,0x771ca31b,
  46127. 0x4885907e,0xe1843ecb,0x364ce16a,0x67797ebc,0x8df4b338,0x816d2b2d },
  46128. { 0x39aa8671,0xe870b0e5,0xc102b5f5,0x9f0db3e4,0x1720c697,0x34296659,
  46129. 0x613c0d2a,0x0ad4c89e,0x418ddd61,0x1af900b2,0xd336e20e,0xe087ca72 } },
  46130. /* 117 */
  46131. { { 0xaba10079,0x222831ff,0x6d64fff2,0x0dc5f87b,0x3e8cb330,0x44547907,
  46132. 0x702a33fb,0xe815aaa2,0x5fba3215,0x338d6b2e,0x79f549c8,0x0f7535cb },
  46133. { 0x2ee95923,0x471ecd97,0xc6d1c09f,0x1e868b37,0xc666ef4e,0x2bc7b8ec,
  46134. 0x808a4bfc,0xf5416589,0x3fbc4d2e,0xf23e9ee2,0x2d75125b,0x4357236c } },
  46135. /* 118 */
  46136. { { 0xba9cdb1b,0xfe176d95,0x2f82791e,0x45a1ca01,0x4de4cca2,0x97654af2,
  46137. 0x5cc4bcb9,0xbdbf9d0e,0xad97ac0a,0xf6a7df50,0x61359fd6,0xc52112b0 },
  46138. { 0x4f05eae3,0x696d9ce3,0xe943ac2b,0x903adc02,0x0848be17,0xa9075347,
  46139. 0x2a3973e5,0x1e20f170,0x6feb67e9,0xe1aacc1c,0xe16bc6b9,0x2ca0ac32 } },
  46140. /* 119 */
  46141. { { 0xef871eb5,0xffea12e4,0xa8bf0a7a,0x94c2f25d,0x78134eaa,0x4d1e4c2a,
  46142. 0x0360fb10,0x11ed16fb,0x85fc11be,0x4029b6db,0xf4d390fa,0x5e9f7ab7 },
  46143. { 0x30646612,0x5076d72f,0xdda1d0d8,0xa0afed1d,0x85a1d103,0x29022257,
  46144. 0x4e276bcd,0xcb499e17,0x51246c3d,0x16d1da71,0x589a0443,0xc72d56d3 } },
  46145. /* 120 */
  46146. { { 0xdae5bb45,0xdf5ffc74,0x261bd6dc,0x99068c4a,0xaa98ec7b,0xdc0afa7a,
  46147. 0xf121e96d,0xedd2ee00,0x1414045c,0x163cc7be,0x335af50e,0xb0b1bbce },
  46148. { 0x01a06293,0xd440d785,0x6552e644,0xcdebab7c,0x8c757e46,0x48cb8dbc,
  46149. 0x3cabe3cb,0x81f9cf78,0xb123f59a,0xddd02611,0xeeb3784d,0x3dc7b88e } },
  46150. /* 121 */
  46151. { { 0xc4741456,0xe1b8d398,0x6032a121,0xa9dfa902,0x1263245b,0x1cbfc86d,
  46152. 0x5244718c,0xf411c762,0x05b0fc54,0x96521d54,0xdbaa4985,0x1afab46e },
  46153. { 0x8674b4ad,0xa75902ba,0x5ad87d12,0x486b43ad,0x36e0d099,0x72b1c736,
  46154. 0xbb6cd6d6,0x39890e07,0x59bace4e,0x8128999c,0x7b535e33,0xd8da430b } },
  46155. /* 122 */
  46156. { { 0xc6b75791,0x39f65642,0x21806bfb,0x050947a6,0x1362ef84,0x0ca3e370,
  46157. 0x8c3d2391,0x9bc60aed,0x732e1ddc,0x9b488671,0xa98ee077,0x12d10d9e },
  46158. { 0x3651b7dc,0xb6f2822d,0x80abd138,0x6345a5ba,0x472d3c84,0x62033262,
  46159. 0xacc57527,0xd54a1d40,0x424447cb,0x6ea46b3a,0x2fb1a496,0x5bc41057 } },
  46160. /* 123 */
  46161. { { 0xa751cd0e,0xe70c57a3,0xeba3c7d6,0x190d8419,0x9d47d55a,0xb1c3bee7,
  46162. 0xf912c6d8,0xda941266,0x407a6ad6,0x12e9aacc,0x6e838911,0xd6ce5f11 },
  46163. { 0x70e1f2ce,0x063ca97b,0x8213d434,0xa3e47c72,0x84df810a,0xa016e241,
  46164. 0xdfd881a4,0x688ad7b0,0xa89bf0ad,0xa37d99fc,0xa23c2d23,0xd8e3f339 } },
  46165. /* 124 */
  46166. { { 0x750bed6f,0xbdf53163,0x83e68b0a,0x808abc32,0x5bb08a33,0x85a36627,
  46167. 0x6b0e4abe,0xf72a3a0f,0xfaf0c6ad,0xf7716d19,0x5379b25f,0x22dcc020 },
  46168. { 0xf9a56e11,0x7400bf8d,0x56a47f21,0x6cb8bad7,0x7a6eb644,0x7c97176f,
  46169. 0xd1f5b646,0xe8fd84f7,0x44ddb054,0x98320a94,0x1dde86f5,0x07071ba3 } },
  46170. /* 125 */
  46171. { { 0x98f8fcb9,0x6fdfa0e5,0x94d0d70c,0x89cec8e0,0x106d20a8,0xa0899397,
  46172. 0xba8acc9c,0x915bfb9a,0x5507e01c,0x1370c94b,0x8a821ffb,0x83246a60 },
  46173. { 0xbe3c378f,0xa8273a9f,0x35a25be9,0x7e544789,0x4dd929d7,0x6cfa4972,
  46174. 0x365bd878,0x987fed9d,0x5c29a7ae,0x4982ac94,0x5ddd7ec5,0x4589a5d7 } },
  46175. /* 126 */
  46176. { { 0xa95540a9,0x9fabb174,0x0162c5b0,0x7cfb886f,0xea3dee18,0x17be766b,
  46177. 0xe88e624c,0xff7da41f,0x8b919c38,0xad0b71eb,0xf31ff9a9,0x86a522e0 },
  46178. { 0x868bc259,0xbc8e6f72,0x3ccef9e4,0x6130c638,0x9a466555,0x09f1f454,
  46179. 0x19b2bfb4,0x8e6c0f09,0x0ca7bb22,0x945c46c9,0x4dafb67b,0xacd87168 } },
  46180. /* 127 */
  46181. { { 0x10c53841,0x090c72ca,0x55a4fced,0xc20ae01b,0xe10234ad,0x03f7ebd5,
  46182. 0x85892064,0xb3f42a6a,0xb4a14722,0xbdbc30c0,0x8ca124cc,0x971bc437 },
  46183. { 0x517ff2ff,0x6f79f46d,0xecba947b,0x6a9c96e2,0x62925122,0x5e79f2f4,
  46184. 0x6a4e91f1,0x30a96bb1,0x2d4c72da,0x1147c923,0x5811e4df,0x65bc311f } },
  46185. /* 128 */
  46186. { { 0x139b3239,0x87c7dd7d,0x4d833bae,0x8b57824e,0x9fff0015,0xbcbc4878,
  46187. 0x909eaf1a,0x8ffcef8b,0xf1443a78,0x9905f4ee,0xe15cbfed,0x020dd4a2 },
  46188. { 0xa306d695,0xca2969ec,0xb93caf60,0xdf940cad,0x87ea6e39,0x67f7fab7,
  46189. 0xf98c4fe5,0x0d0ee10f,0xc19cb91e,0xc646879a,0x7d1d7ab4,0x4b4ea50c } },
  46190. /* 129 */
  46191. { { 0x7a0db57e,0x19e40945,0x9a8c9702,0xe6017cad,0x1be5cff9,0xdbf739e5,
  46192. 0xa7a938a2,0x3646b3cd,0x68350dfc,0x04511085,0x56e098b5,0xad3bd6f3 },
  46193. { 0xee2e3e3e,0x935ebabf,0x473926cb,0xfbd01702,0x9e9fb5aa,0x7c735b02,
  46194. 0x2e3feff0,0xc52a1b85,0x046b405a,0x9199abd3,0x39039971,0xe306fcec } },
  46195. /* 130 */
  46196. { { 0x23e4712c,0xd6d9aec8,0xc3c198ee,0x7ca8376c,0x31bebd8a,0xe6d83187,
  46197. 0xd88bfef3,0xed57aff3,0xcf44edc7,0x72a645ee,0x5cbb1517,0xd4e63d0b },
  46198. { 0xceee0ecf,0x98ce7a1c,0x5383ee8e,0x8f012633,0xa6b455e8,0x3b879078,
  46199. 0xc7658c06,0xcbcd3d96,0x0783336a,0x721d6fe7,0x5a677136,0xf21a7263 } },
  46200. /* 131 */
  46201. { { 0x9586ba11,0x19d8b3cd,0x8a5c0480,0xd9e0aeb2,0x2230ef5c,0xe4261dbf,
  46202. 0x02e6bf09,0x095a9dee,0x80dc7784,0x8963723c,0x145157b1,0x5c97dbaf },
  46203. { 0x4bc4503e,0x97e74434,0x85a6b370,0x0fb1cb31,0xcd205d4b,0x3e8df2be,
  46204. 0xf8f765da,0x497dd1bc,0x6c988a1a,0x92ef95c7,0x64dc4cfa,0x3f924baa } },
  46205. /* 132 */
  46206. { { 0x7268b448,0x6bf1b8dd,0xefd79b94,0xd4c28ba1,0xe4e3551f,0x2fa1f8c8,
  46207. 0x5c9187a9,0x769e3ad4,0x40326c0d,0x28843b4d,0x50d5d669,0xfefc8094 },
  46208. { 0x90339366,0x30c85bfd,0x5ccf6c3a,0x4eeb56f1,0x28ccd1dc,0x0e72b149,
  46209. 0xf2ce978e,0x73ee85b5,0x3165bb23,0xcdeb2bf3,0x4e410abf,0x8106c923 } },
  46210. /* 133 */
  46211. { { 0x7d02f4ee,0xc8df0161,0x18e21225,0x8a781547,0x6acf9e40,0x4ea895eb,
  46212. 0x6e5a633d,0x8b000cb5,0x7e981ffb,0xf31d86d5,0x4475bc32,0xf5c8029c },
  46213. { 0x1b568973,0x764561ce,0xa62996ec,0x2f809b81,0xda085408,0x9e513d64,
  46214. 0xe61ce309,0xc27d815d,0x272999e0,0x0da6ff99,0xfead73f7,0xbd284779 } },
  46215. /* 134 */
  46216. { { 0x9b1cdf2b,0x6033c2f9,0xbc5fa151,0x2a99cf06,0x12177b3b,0x7d27d259,
  46217. 0xc4485483,0xb1f15273,0x102e2297,0x5fd57d81,0xc7f6acb7,0x3d43e017 },
  46218. { 0x3a70eb28,0x41a8bb0b,0x3e80b06b,0x67de2d8e,0x70c28de5,0x09245a41,
  46219. 0xa7b26023,0xad7dbcb1,0x2cbc6c1e,0x70b08a35,0x9b33041f,0xb504fb66 } },
  46220. /* 135 */
  46221. { { 0xf97a27c2,0xa8e85ab5,0xc10a011b,0x6ac5ec8b,0xffbcf161,0x55745533,
  46222. 0x65790a60,0x01780e85,0x99ee75b0,0xe451bf85,0x39c29881,0x8907a63b },
  46223. { 0x260189ed,0x76d46738,0x47bd35cb,0x284a4436,0x20cab61e,0xd74e8c40,
  46224. 0x416cf20a,0x6264bf8c,0x5fd820ce,0xfa5a6c95,0xf24bb5fc,0xfa7154d0 } },
  46225. /* 136 */
  46226. { { 0x9b3f5034,0x18482cec,0xcd9e68fd,0x962d445a,0x95746f23,0x266fb1d6,
  46227. 0x58c94a4b,0xc66ade5a,0xed68a5b6,0xdbbda826,0x7ab0d6ae,0x05664a4d },
  46228. { 0x025e32fc,0xbcd4fe51,0xa96df252,0x61a5aebf,0x31592a31,0xd88a07e2,
  46229. 0x98905517,0x5d9d94de,0x5fd440e7,0x96bb4010,0xe807db4c,0x1b0c47a2 } },
  46230. /* 137 */
  46231. { { 0x08223878,0x5c2a6ac8,0xe65a5558,0xba08c269,0x9bbc27fd,0xd22b1b9b,
  46232. 0x72b9607d,0x919171bf,0xe588dc58,0x9ab455f9,0x23662d93,0x6d54916e },
  46233. { 0x3b1de0c1,0x8da8e938,0x804f278f,0xa84d186a,0xd3461695,0xbf4988cc,
  46234. 0xe10eb0cb,0xf5eae3be,0xbf2a66ed,0x1ff8b68f,0xc305b570,0xa68daf67 } },
  46235. /* 138 */
  46236. { { 0x44b2e045,0xc1004cff,0x4b1c05d4,0x91b5e136,0x88a48a07,0x53ae4090,
  46237. 0xea11bb1a,0x73fb2995,0x3d93a4ea,0x32048570,0x3bfc8a5f,0xcce45de8 },
  46238. { 0xc2b3106e,0xaff4a97e,0xb6848b4f,0x9069c630,0xed76241c,0xeda837a6,
  46239. 0x6cc3f6cf,0x8a0daf13,0x3da018a8,0x199d049d,0xd9093ba3,0xf867c6b1 } },
  46240. /* 139 */
  46241. { { 0x56527296,0xe4d42a56,0xce71178d,0xae26c73d,0x6c251664,0x70a0adac,
  46242. 0x5dc0ae1d,0x813483ae,0xdaab2daf,0x7574eacd,0xc2d55f4f,0xc56b52dc },
  46243. { 0x95f32923,0x872bc167,0x5bdd2a89,0x4be17581,0xa7699f00,0x9b57f1e7,
  46244. 0x3ac2de02,0x5fcd9c72,0x92377739,0x83af3ba1,0xfc50b97f,0xa64d4e2b } },
  46245. /* 140 */
  46246. { { 0x0e552b40,0x2172dae2,0xd34d52e8,0x62f49725,0x07958f98,0x7930ee40,
  46247. 0x751fdd74,0x56da2a90,0xf53e48c3,0xf1192834,0x8e53c343,0x34d2ac26 },
  46248. { 0x13111286,0x1073c218,0xda9d9827,0x201dac14,0xee95d378,0xec2c29db,
  46249. 0x1f3ee0b1,0x9316f119,0x544ce71c,0x7890c9f0,0x27612127,0xd77138af } },
  46250. /* 141 */
  46251. { { 0x3b4ad1cd,0x78045e6d,0x4aa49bc1,0xcd86b94e,0xfd677a16,0x57e51f1d,
  46252. 0xfa613697,0xd9290935,0x34f4d893,0x7a3f9593,0x5d5fcf9b,0x8c9c248b },
  46253. { 0x6f70d4e9,0x9f23a482,0x63190ae9,0x17273454,0x5b081a48,0x4bdd7c13,
  46254. 0x28d65271,0x1e2de389,0xe5841d1f,0x0bbaaa25,0x746772e5,0xc4c18a79 } },
  46255. /* 142 */
  46256. { { 0x593375ac,0x10ee2681,0x7dd5e113,0x4f3288be,0x240f3538,0x9a97b2fb,
  46257. 0x1de6b1e2,0xfa11089f,0x1351bc58,0x516da562,0x2dfa85b5,0x573b6119 },
  46258. { 0x6cba7df5,0x89e96683,0x8c28ab40,0xf299be15,0xad43fcbf,0xe91c9348,
  46259. 0x9a1cefb3,0xe9bbc7cc,0x738b2775,0xc8add876,0x775eaa01,0x6e3b1f2e } },
  46260. /* 143 */
  46261. { { 0xb677788b,0x0365a888,0x3fd6173c,0x634ae8c4,0x9e498dbe,0x30498761,
  46262. 0xc8f779ab,0x08c43e6d,0x4c09aca9,0x068ae384,0x2018d170,0x2380c70b },
  46263. { 0xa297c5ec,0xcf77fbc3,0xca457948,0xdacbc853,0x336bec7e,0x3690de04,
  46264. 0x14eec461,0x26bbac64,0x1f713abf,0xd1c23c7e,0xe6fd569e,0xf08bbfcd } },
  46265. /* 144 */
  46266. { { 0x84770ee3,0x5f8163f4,0x744a1706,0x0e0c7f94,0xe1b2d46d,0x9c8f05f7,
  46267. 0xd01fd99a,0x417eafe7,0x11440e5b,0x2ba15df5,0x91a6fbcf,0xdc5c552a },
  46268. { 0xa270f721,0x86271d74,0xa004485b,0x32c0a075,0x8defa075,0x9d1a87e3,
  46269. 0xbf0d20fe,0xb590a7ac,0x8feda1f5,0x430c41c2,0x58f6ec24,0x454d2879 } },
  46270. /* 145 */
  46271. { { 0x7c525435,0x52b7a635,0x37c4bdbc,0x3d9ef57f,0xdffcc475,0x2bb93e9e,
  46272. 0x7710f3be,0xf7b8ba98,0x21b727de,0x42ee86da,0x2e490d01,0x55ac3f19 },
  46273. { 0xc0c1c390,0x487e3a6e,0x446cde7b,0x036fb345,0x496ae951,0x089eb276,
  46274. 0x71ed1234,0xedfed4d9,0x900f0b46,0x661b0dd5,0x8582f0d3,0x11bd6f1b } },
  46275. /* 146 */
  46276. { { 0x076bc9d1,0x5cf9350f,0xcf3cd2c3,0x15d903be,0x25af031c,0x21cfc8c2,
  46277. 0x8b1cc657,0xe0ad3248,0x70014e87,0xdd9fb963,0x297f1658,0xf0f3a5a1 },
  46278. { 0xf1f703aa,0xbb908fba,0x2f6760ba,0x2f9cc420,0x66a38b51,0x00ceec66,
  46279. 0x05d645da,0x4deda330,0xf7de3394,0xb9cf5c72,0x1ad4c906,0xaeef6502 } },
  46280. /* 147 */
  46281. { { 0x7a19045d,0x0583c8b1,0xd052824c,0xae7c3102,0xff6cfa58,0x2a234979,
  46282. 0x62c733c0,0xfe9dffc9,0x9c0c4b09,0x3a7fa250,0x4fe21805,0x516437bb },
  46283. { 0xc2a23ddb,0x9454e3d5,0x289c104e,0x0726d887,0x4fd15243,0x8977d918,
  46284. 0x6d7790ba,0xc559e73f,0x465af85f,0x8fd3e87d,0x5feee46b,0xa2615c74 } },
  46285. /* 148 */
  46286. { { 0x4335167d,0xc8d607a8,0xe0f5c887,0x8b42d804,0x398d11f9,0x5f9f13df,
  46287. 0x20740c67,0x5aaa5087,0xa3d9234b,0x83da9a6a,0x2a54bad1,0xbd3a5c4e },
  46288. { 0x2db0f658,0xdd13914c,0x5a3f373a,0x29dcb66e,0x5245a72b,0xbfd62df5,
  46289. 0x91e40847,0x19d18023,0xb136b1ae,0xd9df74db,0x3f93bc5b,0x72a06b6b } },
  46290. /* 149 */
  46291. { { 0xad19d96f,0x6da19ec3,0xfb2a4099,0xb342daa4,0x662271ea,0x0e61633a,
  46292. 0xce8c054b,0x3bcece81,0x8bd62dc6,0x7cc8e061,0xee578d8b,0xae189e19 },
  46293. { 0xdced1eed,0x73e7a25d,0x7875d3ab,0xc1257f0a,0x1cfef026,0x2cb2d5a2,
  46294. 0xb1fdf61c,0xd98ef39b,0x24e83e6c,0xcd8e6f69,0xc7b7088b,0xd71e7076 } },
  46295. /* 150 */
  46296. { { 0x9d4245bf,0x33936830,0x2ac2953b,0x22d96217,0x56c3c3cd,0xb3bf5a82,
  46297. 0x0d0699e8,0x50c9be91,0x8f366459,0xec094463,0x513b7c35,0x6c056dba },
  46298. { 0x045ab0e3,0x687a6a83,0x445c9295,0x8d40b57f,0xa16f5954,0x0f345048,
  46299. 0x3d8f0a87,0x64b5c639,0x9f71c5e2,0x106353a2,0x874f0dd4,0xdd58b475 } },
  46300. /* 151 */
  46301. { { 0x62230c72,0x67ec084f,0x481385e3,0xf14f6cca,0x4cda7774,0xf58bb407,
  46302. 0xaa2dbb6b,0xe15011b1,0x0c035ab1,0xd488369d,0x8245f2fd,0xef83c24a },
  46303. { 0x9fdc2538,0xfb57328f,0x191fe46a,0x79808293,0x32ede548,0xe28f5c44,
  46304. 0xea1a022c,0x1b3cda99,0x3df2ec7f,0x39e639b7,0x760e9a18,0x77b6272b } },
  46305. /* 152 */
  46306. { { 0xa65d56d5,0x2b1d51bd,0x7ea696e0,0x3a9b71f9,0x9904f4c4,0x95250ecc,
  46307. 0xe75774b7,0x8bc4d6eb,0xeaeeb9aa,0x0e343f8a,0x930e04cb,0xc473c1d1 },
  46308. { 0x064cd8ae,0x282321b1,0x5562221c,0xf4b4371e,0xd1bf1221,0xc1cc81ec,
  46309. 0xe2c8082f,0xa52a07a9,0xba64a958,0x350d8e59,0x6fb32c9a,0x29e4f3de } },
  46310. /* 153 */
  46311. { { 0xba89aaa5,0x0aa9d56c,0xc4c6059e,0xf0208ac0,0xbd6ddca4,0x7400d9c6,
  46312. 0xf2c2f74a,0xb384e475,0xb1562dd3,0x4c1061fc,0x2e153b8d,0x3924e248 },
  46313. { 0x849808ab,0xf38b8d98,0xa491aa36,0x29bf3260,0x88220ede,0x85159ada,
  46314. 0xbe5bc422,0x8b47915b,0xd7300967,0xa934d72e,0x2e515d0d,0xc4f30398 } },
  46315. /* 154 */
  46316. { { 0x1b1de38b,0xe3e9ee42,0x42636760,0xa124e25a,0x90165b1a,0x90bf73c0,
  46317. 0x146434c5,0x21802a34,0x2e1fa109,0x54aa83f2,0xed9c51e9,0x1d4bd03c },
  46318. { 0x798751e6,0xc2d96a38,0x8c3507f5,0xed27235f,0xc8c24f88,0xb5fb80e2,
  46319. 0xd37f4f78,0xf873eefa,0xf224ba96,0x7229fd74,0x9edd7149,0x9dcd9199 } },
  46320. /* 155 */
  46321. { { 0x4e94f22a,0xee9f81a6,0xf71ec341,0xe5609892,0xa998284e,0x6c818ddd,
  46322. 0x3b54b098,0x9fd47295,0x0e8a7cc9,0x47a6ac03,0xb207a382,0xde684e5e },
  46323. { 0x2b6b956b,0x4bdd1ecd,0xf01b3583,0x09084414,0x55233b14,0xe2f80b32,
  46324. 0xef5ebc5e,0x5a0fec54,0xbf8b29a2,0x74cf25e6,0x7f29e014,0x1c757fa0 } },
  46325. /* 156 */
  46326. { { 0xeb0fdfe4,0x1bcb5c4a,0xf0899367,0xd7c649b3,0x05bc083b,0xaef68e3f,
  46327. 0xa78aa607,0x57a06e46,0x21223a44,0xa2136ecc,0x52f5a50b,0x89bd6484 },
  46328. { 0x4455f15a,0x724411b9,0x08a9c0fd,0x23dfa970,0x6db63bef,0x7b0da4d1,
  46329. 0xfb162443,0x6f8a7ec1,0xe98284fb,0xc1ac9cee,0x33566022,0x085a582b } },
  46330. /* 157 */
  46331. { { 0xec1f138a,0x15cb61f9,0x668f0c28,0x11c9a230,0xdf93f38f,0xac829729,
  46332. 0x4048848d,0xcef25698,0x2bba8fbf,0x3f686da0,0x111c619a,0xed5fea78 },
  46333. { 0xd6d1c833,0x9b4f73bc,0x86e7bf80,0x50951606,0x042b1d51,0xa2a73508,
  46334. 0x5fb89ec2,0x9ef6ea49,0x5ef8b892,0xf1008ce9,0x9ae8568b,0x78a7e684 } },
  46335. /* 158 */
  46336. { { 0x10470cd8,0x3fe83a7c,0xf86df000,0x92734682,0xda9409b5,0xb5dac06b,
  46337. 0x94939c5f,0x1e7a9660,0x5cc116dc,0xdec6c150,0x66bac8cc,0x1a52b408 },
  46338. { 0x6e864045,0x5303a365,0x9139efc1,0x45eae72a,0x6f31d54f,0x83bec646,
  46339. 0x6e958a6d,0x2fb4a86f,0x4ff44030,0x6760718e,0xe91ae0df,0x008117e3 } },
  46340. /* 159 */
  46341. { { 0x384310a2,0x5d5833ba,0x1fd6c9fc,0xbdfb4edc,0x849c4fb8,0xb9a4f102,
  46342. 0x581c1e1f,0xe5fb239a,0xd0a9746d,0xba44b2e7,0x3bd942b9,0x78f7b768 },
  46343. { 0xc87607ae,0x076c8ca1,0xd5caaa7e,0x82b23c2e,0x2763e461,0x6a581f39,
  46344. 0x3886df11,0xca8a5e4a,0x264e7f22,0xc87e90cf,0x215cfcfc,0x04f74870 } },
  46345. /* 160 */
  46346. { { 0x141d161c,0x5285d116,0x93c4ed17,0x67cd2e0e,0x7c36187e,0x12c62a64,
  46347. 0xed2584ca,0xf5329539,0x42fbbd69,0xc4c777c4,0x1bdfc50a,0x107de776 },
  46348. { 0xe96beebd,0x9976dcc5,0xa865a151,0xbe2aff95,0x9d8872af,0x0e0a9da1,
  46349. 0xa63c17cc,0x5e357a3d,0xe15cc67c,0xd31fdfd8,0x7970c6d8,0xc44bbefd } },
  46350. /* 161 */
  46351. { { 0x4c0c62f1,0x703f83e2,0x4e195572,0x9b1e28ee,0xfe26cced,0x6a82858b,
  46352. 0xc43638fa,0xd381c84b,0xa5ba43d8,0x94f72867,0x10b82743,0x3b4a783d },
  46353. { 0x7576451e,0xee1ad7b5,0x14b6b5c8,0xc3d0b597,0xfcacc1b8,0x3dc30954,
  46354. 0x472c9d7b,0x55df110e,0x02f8a328,0x97c86ed7,0x88dc098f,0xd0433413 } },
  46355. /* 162 */
  46356. { { 0x2ca8f2fe,0x1a60d152,0x491bd41f,0x61640948,0x58dfe035,0x6dae29a5,
  46357. 0x278e4863,0x9a615bea,0x9ad7c8e5,0xbbdb4477,0x2ceac2fc,0x1c706630 },
  46358. { 0x99699b4b,0x5e2b54c6,0x239e17e8,0xb509ca6d,0xea063a82,0x728165fe,
  46359. 0xb6a22e02,0x6b5e609d,0xb26ee1df,0x12813905,0x439491fa,0x07b9f722 } },
  46360. /* 163 */
  46361. { { 0x48ff4e49,0x1592ec14,0x6d644129,0x3e4e9f17,0x1156acc0,0x7acf8288,
  46362. 0xbb092b0b,0x5aa34ba8,0x7d38393d,0xcd0f9022,0xea4f8187,0x416724dd },
  46363. { 0xc0139e73,0x3c4e641c,0x91e4d87d,0xe0fe46cf,0xcab61f8a,0xedb3c792,
  46364. 0xd3868753,0x4cb46de4,0x20f1098a,0xe449c21d,0xf5b8ea6e,0x5e5fd059 } },
  46365. /* 164 */
  46366. { { 0x75856031,0x7fcadd46,0xeaf2fbd0,0x89c7a4cd,0x7a87c480,0x1af523ce,
  46367. 0x61d9ae90,0xe5fc1095,0xbcdb95f5,0x3fb5864f,0xbb5b2c7d,0xbeb5188e },
  46368. { 0x3ae65825,0x3d1563c3,0x0e57d641,0x116854c4,0x1942ebd3,0x11f73d34,
  46369. 0xc06955b3,0x24dc5904,0x995a0a62,0x8a0d4c83,0x5d577b7d,0xfb26b86d } },
  46370. /* 165 */
  46371. { { 0xc686ae17,0xc53108e7,0xd1c1da56,0x9090d739,0x9aec50ae,0x4583b013,
  46372. 0xa49a6ab2,0xdd9a088b,0xf382f850,0x28192eea,0xf5fe910e,0xcc8df756 },
  46373. { 0x9cab7630,0x877823a3,0xfb8e7fc1,0x64984a9a,0x364bfc16,0x5448ef9c,
  46374. 0xc44e2a9a,0xbbb4f871,0x435c95e9,0x901a41ab,0xaaa50a06,0xc6c23e5f } },
  46375. /* 166 */
  46376. { { 0x9034d8dd,0xb78016c1,0x0b13e79b,0x856bb44b,0xb3241a05,0x85c6409a,
  46377. 0x2d78ed21,0x8d2fe19a,0x726eddf2,0xdcc7c26d,0x25104f04,0x3ccaff5f },
  46378. { 0x6b21f843,0x397d7edc,0xe975de4c,0xda88e4dd,0x4f5ab69e,0x5273d396,
  46379. 0x9aae6cc0,0x537680e3,0x3e6f9461,0xf749cce5,0x957bffd3,0x021ddbd9 } },
  46380. /* 167 */
  46381. { { 0x777233cf,0x7b64585f,0x0942a6f0,0xfe6771f6,0xdfe6eef0,0x636aba7a,
  46382. 0x86038029,0x63bbeb56,0xde8fcf36,0xacee5842,0xd4a20524,0x48d9aa99 },
  46383. { 0x0da5e57a,0xcff7a74c,0xe549d6c9,0xc232593c,0xf0f2287b,0x68504bcc,
  46384. 0xbc8360b5,0x6d7d098d,0x5b402f41,0xeac5f149,0xb87d1bf1,0x61936f11 } },
  46385. /* 168 */
  46386. { { 0xb8153a9d,0xaa9da167,0x9e83ecf0,0xa49fe3ac,0x1b661384,0x14c18f8e,
  46387. 0x38434de1,0x61c24dab,0x283dae96,0x3d973c3a,0x82754fc9,0xc99baa01 },
  46388. { 0x4c26b1e3,0x477d198f,0xa7516202,0x12e8e186,0x362addfa,0x386e52f6,
  46389. 0xc3962853,0x31e8f695,0x6aaedb60,0xdec2af13,0x29cf74ac,0xfcfdb4c6 } },
  46390. /* 169 */
  46391. { { 0xcca40298,0x6b3ee958,0xf2f5d195,0xc3878153,0xed2eae5b,0x0c565630,
  46392. 0x3a697cf2,0xd089b37e,0xad5029ea,0xc2ed2ac7,0x0f0dda6a,0x7e5cdfad },
  46393. { 0xd9b86202,0xf98426df,0x4335e054,0xed1960b1,0x3f14639e,0x1fdb0246,
  46394. 0x0db6c670,0x17f709c3,0x773421e1,0xbfc687ae,0x26c1a8ac,0x13fefc4a } },
  46395. /* 170 */
  46396. { { 0x7ffa0a5f,0xe361a198,0xc63fe109,0xf4b26102,0x6c74e111,0x264acbc5,
  46397. 0x77abebaf,0x4af445fa,0x24cddb75,0x448c4fdd,0x44506eea,0x0b13157d },
  46398. { 0x72e9993d,0x22a6b159,0x85e5ecbe,0x2c3c57e4,0xfd83e1a1,0xa673560b,
  46399. 0xc3b8c83b,0x6be23f82,0x40bbe38e,0x40b13a96,0xad17399b,0x66eea033 } },
  46400. /* 171 */
  46401. { { 0xb4c6c693,0x49fc6e95,0x36af7d38,0xefc735de,0x35fe42fc,0xe053343d,
  46402. 0x6a9ab7c3,0xf0aa427c,0x4a0fcb24,0xc79f0436,0x93ebbc50,0x16287243 },
  46403. { 0x16927e1e,0x5c3d6bd0,0x673b984c,0x40158ed2,0x4cd48b9a,0xa7f86fc8,
  46404. 0x60ea282d,0x1643eda6,0xe2a1beed,0x45b393ea,0x19571a94,0x664c839e } },
  46405. /* 172 */
  46406. { { 0x27eeaf94,0x57745750,0xea99e1e7,0x2875c925,0x5086adea,0xc127e7ba,
  46407. 0x86fe424f,0x765252a0,0x2b6c0281,0x1143cc6c,0xd671312d,0xc9bb2989 },
  46408. { 0x51acb0a5,0x880c337c,0xd3c60f78,0xa3710915,0x9262b6ed,0x496113c0,
  46409. 0x9ce48182,0x5d25d9f8,0xb3813586,0x53b6ad72,0x4c0e159c,0x0ea3bebc } },
  46410. /* 173 */
  46411. { { 0xc5e49bea,0xcaba450a,0x7c05da59,0x684e5415,0xde7ac36c,0xa2e9cab9,
  46412. 0x2e6f957b,0x4ca79b5f,0x09b817b1,0xef7b0247,0x7d89df0f,0xeb304990 },
  46413. { 0x46fe5096,0x508f7307,0x2e04eaaf,0x695810e8,0x3512f76c,0x88ef1bd9,
  46414. 0x3ebca06b,0x77661351,0xccf158b7,0xf7d4863a,0x94ee57da,0xb2a81e44 } },
  46415. /* 174 */
  46416. { { 0x6d53e6ba,0xff288e5b,0x14484ea2,0xa90de1a9,0xed33c8ec,0x2fadb60c,
  46417. 0x28b66a40,0x579d6ef3,0xec24372d,0x4f2dd6dd,0x1d66ec7d,0xe9e33fc9 },
  46418. { 0x039eab6e,0x110899d2,0x3e97bb5e,0xa31a667a,0xcfdce68e,0x6200166d,
  46419. 0x5137d54b,0xbe83ebae,0x4800acdf,0x085f7d87,0x0c6f8c86,0xcf4ab133 } },
  46420. /* 175 */
  46421. { { 0x931e08fb,0x03f65845,0x1506e2c0,0x6438551e,0x9c36961f,0x5791f0dc,
  46422. 0xe3dcc916,0x68107b29,0xf495d2ca,0x83242374,0x6ee5895b,0xd8cfb663 },
  46423. { 0xa0349b1b,0x525e0f16,0x4a0fab86,0x33cd2c6c,0x2af8dda9,0x46c12ee8,
  46424. 0x71e97ad3,0x7cc424ba,0x37621eb0,0x69766ddf,0xa5f0d390,0x95565f56 } },
  46425. /* 176 */
  46426. { { 0x1a0f5e94,0xe0e7bbf2,0x1d82d327,0xf771e115,0xceb111fa,0x10033e3d,
  46427. 0xd3426638,0xd269744d,0x00d01ef6,0xbdf2d9da,0xa049ceaf,0x1cb80c71 },
  46428. { 0x9e21c677,0x17f18328,0x19c8f98b,0x6452af05,0x80b67997,0x35b9c5f7,
  46429. 0x40f8f3d4,0x5c2e1cbe,0x66d667ca,0x43f91656,0xcf9d6e79,0x9faaa059 } },
  46430. /* 177 */
  46431. { { 0x0a078fe6,0x8ad24618,0x464fd1dd,0xf6cc73e6,0xc3e37448,0x4d2ce34d,
  46432. 0xe3271b5f,0x624950c5,0xefc5af72,0x62910f5e,0xaa132bc6,0x8b585bf8 },
  46433. { 0xa839327f,0x11723985,0x4aac252f,0x34e2d27d,0x6296cc4e,0x402f59ef,
  46434. 0x47053de9,0x00ae055c,0x28b4f09b,0xfc22a972,0xfa0c180e,0xa9e86264 } },
  46435. /* 178 */
  46436. { { 0xbc310ecc,0x0b7b6224,0x67fa14ed,0x8a1a74f1,0x7214395c,0x87dd0960,
  46437. 0xf5c91128,0xdf1b3d09,0x86b264a8,0x39ff23c6,0x3e58d4c5,0xdc2d49d0 },
  46438. { 0xa9d6f501,0x2152b7d3,0xc04094f7,0xf4c32e24,0xd938990f,0xc6366596,
  46439. 0x94fb207f,0x084d078f,0x328594cb,0xfd99f1d7,0xcb2d96b3,0x36defa64 } },
  46440. /* 179 */
  46441. { { 0x13ed7cbe,0x4619b781,0x9784bd0e,0x95e50015,0x2c7705fe,0x2a32251c,
  46442. 0x5f0dd083,0xa376af99,0x0361a45b,0x55425c6c,0x1f291e7b,0x812d2cef },
  46443. { 0x5fd94972,0xccf581a0,0xe56dc383,0x26e20e39,0x63dbfbf0,0x0093685d,
  46444. 0x36b8c575,0x1fc164cc,0x390ef5e7,0xb9c5ab81,0x26908c66,0x40086beb } },
  46445. /* 180 */
  46446. { { 0x37e3c115,0xe5e54f79,0xc1445a8a,0x69b8ee8c,0xb7659709,0x79aedff2,
  46447. 0x1b46fbe6,0xe288e163,0xd18d7bb7,0xdb4844f0,0x48aa6424,0xe0ea23d0 },
  46448. { 0xf3d80a73,0x714c0e4e,0x3bd64f98,0x87a0aa9e,0x2ec63080,0x8844b8a8,
  46449. 0x255d81a3,0xe0ac9c30,0x455397fc,0x86151237,0x2f820155,0x0b979464 } },
  46450. /* 181 */
  46451. { { 0x4ae03080,0x127a255a,0x580a89fb,0x232306b4,0x6416f539,0x04e8cd6a,
  46452. 0x13b02a0e,0xaeb70dee,0x4c09684a,0xa3038cf8,0x28e433ee,0xa710ec3c },
  46453. { 0x681b1f7d,0x77a72567,0x2fc28170,0x86fbce95,0xf5735ac8,0xd3408683,
  46454. 0x6bd68e93,0x3a324e2a,0xc027d155,0x7ec74353,0xd4427177,0xab60354c } },
  46455. /* 182 */
  46456. { { 0xef4c209d,0x32a5342a,0x08d62704,0x2ba75274,0xc825d5fe,0x4bb4af6f,
  46457. 0xd28e7ff1,0x1c3919ce,0xde0340f6,0x1dfc2fdc,0x29f33ba9,0xc6580baf },
  46458. { 0x41d442cb,0xae121e75,0x3a4724e4,0x4c7727fd,0x524f3474,0xe556d6a4,
  46459. 0x785642a2,0x87e13cc7,0xa17845fd,0x182efbb1,0x4e144857,0xdcec0cf1 } },
  46460. /* 183 */
  46461. { { 0xe9539819,0x1cb89541,0x9d94dbf1,0xc8cb3b4f,0x417da578,0x1d353f63,
  46462. 0x8053a09e,0xb7a697fb,0xc35d8b78,0x8d841731,0xb656a7a9,0x85748d6f },
  46463. { 0xc1859c5d,0x1fd03947,0x535d22a2,0x6ce965c1,0x0ca3aadc,0x1966a13e,
  46464. 0x4fb14eff,0x9802e41d,0x76dd3fcd,0xa9048cbb,0xe9455bba,0x89b182b5 } },
  46465. /* 184 */
  46466. { { 0x43360710,0xd777ad6a,0x55e9936b,0x841287ef,0x04a21b24,0xbaf5c670,
  46467. 0x35ad86f1,0xf2c0725f,0xc707e72e,0x338fa650,0xd8883e52,0x2bf8ed2e },
  46468. { 0xb56e0d6a,0xb0212cf4,0x6843290c,0x50537e12,0x98b3dc6f,0xd8b184a1,
  46469. 0x0210b722,0xd2be9a35,0x559781ee,0x407406db,0x0bc18534,0x5a78d591 } },
  46470. /* 185 */
  46471. { { 0xd748b02c,0x4d57aa2a,0xa12b3b95,0xbe5b3451,0x64711258,0xadca7a45,
  46472. 0x322153db,0x597e091a,0x32eb1eab,0xf3271006,0x2873f301,0xbd9adcba },
  46473. { 0x38543f7f,0xd1dc79d1,0x921b1fef,0x00022092,0x1e5df8ed,0x86db3ef5,
  46474. 0x9e6b944a,0x888cae04,0x791a32b4,0x71bd29ec,0xa6d1c13e,0xd3516206 } },
  46475. /* 186 */
  46476. { { 0x55924f43,0x2ef6b952,0x4f9de8d5,0xd2f401ae,0xadc68042,0xfc73e8d7,
  46477. 0x0d9d1bb4,0x627ea70c,0xbbf35679,0xc3bb3e3e,0xd882dee4,0x7e8a254a },
  46478. { 0xb5924407,0x08906f50,0xa1ad444a,0xf14a0e61,0x65f3738e,0xaa0efa21,
  46479. 0xae71f161,0xd60c7dd6,0xf175894d,0x9e8390fa,0x149f4c00,0xd115cd20 } },
  46480. /* 187 */
  46481. { { 0xa52abf77,0x2f2e2c1d,0x54232568,0xc2a0dca5,0x54966dcc,0xed423ea2,
  46482. 0xcd0dd039,0xe48c93c7,0x176405c7,0x1e54a225,0x70d58f2e,0x1efb5b16 },
  46483. { 0x94fb1471,0xa751f9d9,0x67d2941d,0xfdb31e1f,0x53733698,0xa6c74eb2,
  46484. 0x89a0f64a,0xd3155d11,0xa4b8d2b6,0x4414cfe4,0xf7a8e9e3,0x8d5a4be8 } },
  46485. /* 188 */
  46486. { { 0x52669e98,0x5c96b4d4,0x8fd42a03,0x4547f922,0xd285174e,0xcf5c1319,
  46487. 0x064bffa0,0x805cd1ae,0x246d27e7,0x50e8bc4f,0xd5781e11,0xf89ef98f },
  46488. { 0xdee0b63f,0xb4ff95f6,0x222663a4,0xad850047,0x4d23ce9c,0x02691860,
  46489. 0x50019f59,0x3e5309ce,0x69a508ae,0x27e6f722,0x267ba52c,0xe9376652 } },
  46490. /* 189 */
  46491. { { 0xc0368708,0xa04d289c,0x5e306e1d,0xc458872f,0x33112fea,0x76fa23de,
  46492. 0x6efde42e,0x718e3974,0x1d206091,0xf0c98cdc,0x14a71987,0x5fa3ca62 },
  46493. { 0xdcaa9f2a,0xeee8188b,0x589a860d,0x312cc732,0xc63aeb1f,0xf9808dd6,
  46494. 0x4ea62b53,0x70fd43db,0x890b6e97,0x2c2bfe34,0xfa426aa6,0x105f863c } },
  46495. /* 190 */
  46496. { { 0xb38059ad,0x0b29795d,0x90647ea0,0x5686b77e,0xdb473a3e,0xeff0470e,
  46497. 0xf9b6d1e2,0x278d2340,0xbd594ec7,0xebbff95b,0xd3a7f23d,0xf4b72334 },
  46498. { 0xa5a83f0b,0x2a285980,0x9716a8b3,0x0786c41a,0x22511812,0x138901bd,
  46499. 0xe2fede6e,0xd1b55221,0xdf4eb590,0x0806e264,0x762e462e,0x6c4c897e } },
  46500. /* 191 */
  46501. { { 0xb4b41d9d,0xd10b905f,0x4523a65b,0x826ca466,0xb699fa37,0x535bbd13,
  46502. 0x73bc8f90,0x5b9933d7,0xcd2118ad,0x9332d61f,0xd4a65fd0,0x158c693e },
  46503. { 0xe6806e63,0x4ddfb2a8,0xb5de651b,0xe31ed3ec,0x819bc69a,0xf9460e51,
  46504. 0x2c76b1f8,0x6229c0d6,0x901970a3,0xbb78f231,0x9cee72b8,0x31f3820f } },
  46505. /* 192 */
  46506. { { 0xc09e1c72,0xe931caf2,0x12990cf4,0x0715f298,0x943262d8,0x33aad81d,
  46507. 0x73048d3f,0x5d292b7a,0xdc7415f6,0xb152aaa4,0x0fd19587,0xc3d10fd9 },
  46508. { 0x75ddadd0,0xf76b35c5,0x1e7b694c,0x9f5f4a51,0xc0663025,0x2f1ab7eb,
  46509. 0x920260b0,0x01c9cc87,0x05d39da6,0xc4b1f61a,0xeb4a9c4e,0x6dcd76c4 } },
  46510. /* 193 */
  46511. { { 0xfdc83f01,0x0ba0916f,0x9553e4f9,0x354c8b44,0xffc5e622,0xa6cc511a,
  46512. 0xe95be787,0xb954726a,0x75b41a62,0xcb048115,0xebfde989,0xfa2ae6cd },
  46513. { 0x0f24659a,0x6376bbc7,0x4c289c43,0x13a999fd,0xec9abd8b,0xc7134184,
  46514. 0xa789ab04,0x28c02bf6,0xd3e526ec,0xff841ebc,0x640893a8,0x442b191e } },
  46515. /* 194 */
  46516. { { 0xfa2b6e20,0x4cac6c62,0xf6d69861,0x97f29e9b,0xbc96d12d,0x228ab1db,
  46517. 0x5e8e108d,0x6eb91327,0x40771245,0xd4b3d4d1,0xca8a803a,0x61b20623 },
  46518. { 0xa6a560b1,0x2c2f3b41,0x3859fcf4,0x879e1d40,0x024dbfc3,0x7cdb5145,
  46519. 0x3bfa5315,0x55d08f15,0xaa93823a,0x2f57d773,0xc6a2c9a2,0xa97f259c } },
  46520. /* 195 */
  46521. { { 0xe58edbbb,0xc306317b,0x79dfdf13,0x25ade51c,0x16d83dd6,0x6b5beaf1,
  46522. 0x1dd8f925,0xe8038a44,0xb2a87b6b,0x7f00143c,0xf5b438de,0xa885d00d },
  46523. { 0xcf9e48bd,0xe9f76790,0xa5162768,0xf0bdf9f0,0xad7b57cb,0x0436709f,
  46524. 0xf7c15db7,0x7e151c12,0x5d90ee3b,0x3514f022,0x2c361a8d,0x2e84e803 } },
  46525. /* 196 */
  46526. { { 0x563ec8d8,0x2277607d,0xe3934cb7,0xa661811f,0xf58fd5de,0x3ca72e7a,
  46527. 0x62294c6a,0x7989da04,0xf6bbefe9,0x88b3708b,0x53ed7c82,0x0d524cf7 },
  46528. { 0x2f30c073,0x69f699ca,0x9dc1dcf3,0xf0fa264b,0x05f0aaf6,0x44ca4568,
  46529. 0xd19b9baf,0x0f5b23c7,0xeabd1107,0x39193f41,0x2a7c9b83,0x9e3e10ad } },
  46530. /* 197 */
  46531. { { 0xd4ae972f,0xa90824f0,0xc6e846e7,0x43eef02b,0x29d2160a,0x7e460612,
  46532. 0xfe604e91,0x29a178ac,0x4eb184b2,0x23056f04,0xeb54cdf4,0x4fcad55f },
  46533. { 0xae728d15,0xa0ff96f3,0xc6a00331,0x8a2680c6,0x7ee52556,0x5f84cae0,
  46534. 0xc5a65dad,0x5e462c3a,0xe2d23f4f,0x5d2b81df,0xc5b1eb07,0x6e47301b } },
  46535. /* 198 */
  46536. { { 0xaf8219b9,0x77411d68,0x51b1907a,0xcb883ce6,0x101383b5,0x25c87e57,
  46537. 0x982f970d,0x9c7d9859,0x118305d2,0xaa6abca5,0x9013a5db,0x725fed2f },
  46538. { 0xababd109,0x487cdbaf,0x87586528,0xc0f8cf56,0x8ad58254,0xa02591e6,
  46539. 0xdebbd526,0xc071b1d1,0x961e7e31,0x927dfe8b,0x9263dfe1,0x55f895f9 } },
  46540. /* 199 */
  46541. { { 0xb175645b,0xf899b00d,0xb65b4b92,0x51f3a627,0xb67399ef,0xa2f3ac8d,
  46542. 0xe400bc20,0xe717867f,0x1967b952,0x42cc9020,0x3ecd1de1,0x3d596751 },
  46543. { 0xdb979775,0xd41ebcde,0x6a2e7e88,0x99ba61bc,0x321504f2,0x039149a5,
  46544. 0x27ba2fad,0xe7dc2314,0xb57d8368,0x9f556308,0x57da80a7,0x2b6d16c9 } },
  46545. /* 200 */
  46546. { { 0x279ad982,0x84af5e76,0x9c8b81a6,0x9bb4c92d,0x0e698e67,0xd79ad44e,
  46547. 0x265fc167,0xe8be9048,0x0c3a4ccc,0xf135f7e6,0xb8863a33,0xa0a10d38 },
  46548. { 0xd386efd9,0xe197247c,0xb52346c2,0x0eefd3f9,0x78607bc8,0xc22415f9,
  46549. 0x508674ce,0xa2a8f862,0xc8c9d607,0xa72ad09e,0x50fa764f,0xcd9f0ede } },
  46550. /* 201 */
  46551. { { 0xd1a46d4d,0x063391c7,0x9eb01693,0x2df51c11,0x849e83de,0xc5849800,
  46552. 0x8ad08382,0x48fd09aa,0xaa742736,0xa405d873,0xe1f9600c,0xee49e61e },
  46553. { 0x48c76f73,0xd76676be,0x01274b2a,0xd9c100f6,0x83f8718d,0x110bb67c,
  46554. 0x02fc0d73,0xec85a420,0x744656ad,0xc0449e1e,0x37d9939b,0x28ce7376 } },
  46555. /* 202 */
  46556. { { 0x44544ac7,0x97e9af72,0xba010426,0xf2c658d5,0xfb3adfbd,0x732dec39,
  46557. 0xa2df0b07,0xd12faf91,0x2171e208,0x8ac26725,0x5b24fa54,0xf820cdc8 },
  46558. { 0x94f4cf77,0x307a6eea,0x944a33c6,0x18c783d2,0x0b741ac5,0x4b939d4c,
  46559. 0x3ffbb6e4,0x1d7acd15,0x7a255e44,0x06a24858,0xce336d50,0x14fbc494 } },
  46560. /* 203 */
  46561. { { 0x51584e3c,0x9b920c0c,0xf7e54027,0xc7733c59,0x88422bbe,0xe24ce139,
  46562. 0x523bd6ab,0x11ada812,0xb88e6def,0xde068800,0xfe8c582d,0x7b872671 },
  46563. { 0x7de53510,0x4e746f28,0xf7971968,0x492f8b99,0x7d928ac2,0x1ec80bc7,
  46564. 0x432eb1b5,0xb3913e48,0x32028f6e,0xad084866,0x8fc2f38b,0x122bb835 } },
  46565. /* 204 */
  46566. { { 0x3b0b29c3,0x0a9f3b1e,0x4fa44151,0x837b6432,0x17b28ea7,0xb9905c92,
  46567. 0x98451750,0xf39bc937,0xce8b6da1,0xcd383c24,0x010620b2,0x299f57db },
  46568. { 0x58afdce3,0x7b6ac396,0x3d05ef47,0xa15206b3,0xb9bb02ff,0xa0ae37e2,
  46569. 0x9db3964c,0x107760ab,0x67954bea,0xe29de9a0,0x431c3f82,0x446a1ad8 } },
  46570. /* 205 */
  46571. { { 0x5c6b8195,0xc6fecea0,0xf49e71b9,0xd744a7c5,0x177a7ae7,0xa8e96acc,
  46572. 0x358773a7,0x1a05746c,0x37567369,0xa4162146,0x87d1c971,0xaa0217f7 },
  46573. { 0x77fd3226,0x61e9d158,0xe4f600be,0x0f6f2304,0x7a6dff07,0xa9c4cebc,
  46574. 0x09f12a24,0xd15afa01,0x8c863ee9,0x2bbadb22,0xe5eb8c78,0xa28290e4 } },
  46575. /* 206 */
  46576. { { 0x3e9de330,0x55b87fa0,0x195c145b,0x12b26066,0xa920bef0,0xe08536e0,
  46577. 0x4d195adc,0x7bff6f2c,0x945f4187,0x7f319e9d,0xf892ce47,0xf9848863 },
  46578. { 0x4fe37657,0xd0efc1d3,0x5cf0e45a,0x3c58de82,0x8b0ccbbe,0x626ad21a,
  46579. 0xaf952fc5,0xd2a31208,0xeb437357,0x81791995,0x98e95d4f,0x5f19d30f } },
  46580. /* 207 */
  46581. { { 0x0e6865bb,0x72e83d9a,0xf63456a6,0x22f5af3b,0x463c8d9e,0x409e9c73,
  46582. 0xdfe6970e,0x40e9e578,0x711b91ca,0x876b6efa,0x942625a3,0x895512cf },
  46583. { 0xcb4e462b,0x84c8eda8,0x4412e7c8,0x84c0154a,0xceb7b71f,0x04325db1,
  46584. 0x66f70877,0x1537dde3,0x1992b9ac,0xf3a09399,0xd498ae77,0xa7316606 } },
  46585. /* 208 */
  46586. { { 0xcad260f5,0x13990d2f,0xeec0e8c0,0x76c3be29,0x0f7bd7d5,0x7dc5bee0,
  46587. 0xefebda4b,0x9be167d2,0x9122b87e,0xcce3dde6,0x82b5415c,0x75a28b09 },
  46588. { 0xe84607a6,0xf6810bcd,0x6f4dbf0d,0xc6d58128,0x1b4dafeb,0xfead577d,
  46589. 0x066b28eb,0x9bc440b2,0x8b17e84b,0x53f1da97,0xcda9a575,0x0459504b } },
  46590. /* 209 */
  46591. { { 0x329e5836,0x13e39a02,0xf717269d,0x2c9e7d51,0xf26c963b,0xc5ac58d6,
  46592. 0x79967bf5,0x3b0c6c43,0x55908d9d,0x60bbea3f,0xf07c9ad1,0xd84811e7 },
  46593. { 0x5bd20e4a,0xfe7609a7,0x0a70baa8,0xe4325dd2,0xb3600386,0x3711f370,
  46594. 0xd0924302,0x97f9562f,0x4acc4436,0x040dc0c3,0xde79cdd4,0xfd6d725c } },
  46595. /* 210 */
  46596. { { 0xcf13eafb,0xb3efd0e3,0x5aa0ae5f,0x21009cbb,0x79022279,0xe480c553,
  46597. 0xb2fc9a6d,0x755cf334,0x07096ae7,0x8564a5bf,0xbd238139,0xddd649d0 },
  46598. { 0x8a045041,0xd0de10b1,0xc957d572,0x6e05b413,0x4e0fb25c,0x5c5ff806,
  46599. 0x641162fb,0xd933179b,0xe57439f9,0x42d48485,0x8a8d72aa,0x70c5bd0a } },
  46600. /* 211 */
  46601. { { 0x97bdf646,0xa7671738,0xab329f7c,0xaa1485b4,0xf8f25fdf,0xce3e11d6,
  46602. 0xc6221824,0x76a3fc7e,0xf3924740,0x045f281f,0x96d13a9a,0x24557d4e },
  46603. { 0xdd4c27cd,0x875c804b,0x0f5c7fea,0x11c5f0f4,0xdc55ff7e,0xac8c880b,
  46604. 0x1103f101,0x2acddec5,0xf99faa89,0x38341a21,0xce9d6b57,0xc7b67a2c } },
  46605. /* 212 */
  46606. { { 0x8e357586,0x9a0d724f,0xdf648da0,0x1d7f4ff5,0xfdee62a5,0x9c3e6c9b,
  46607. 0x0389b372,0x0499cef0,0x98eab879,0xe904050d,0x6c051617,0xe8eef1b6 },
  46608. { 0xc37e3ca9,0xebf5bfeb,0xa4e0b91d,0x7c5e946d,0x2c4bea28,0x79097314,
  46609. 0xee67b2b7,0x81f6c109,0xdafc5ede,0xaf237d9b,0x2abb04c7,0xd2e60201 } },
  46610. /* 213 */
  46611. { { 0x8a4f57bf,0x6156060c,0xff11182a,0xf9758696,0x6296ef00,0x8336773c,
  46612. 0xff666899,0x9c054bce,0x719cd11c,0xd6a11611,0xdbe1acfa,0x9824a641 },
  46613. { 0xba89fd01,0x0b7b7a5f,0x889f79d8,0xf8d3b809,0xf578285c,0xc5e1ea08,
  46614. 0xae6d8288,0x7ac74536,0x7521ef5f,0x5d37a200,0xb260a25d,0x5ecc4184 } },
  46615. /* 214 */
  46616. { { 0xa708c8d3,0xddcebb19,0xc63f81ec,0xe63ed04f,0x11873f95,0xd045f5a0,
  46617. 0x79f276d5,0x3b5ad544,0x425ae5b3,0x81272a3d,0x10ce1605,0x8bfeb501 },
  46618. { 0x888228bf,0x4233809c,0xb2aff7df,0x4bd82acf,0x0cbd4a7f,0x9c68f180,
  46619. 0x6b44323d,0xfcd77124,0x891db957,0x60c0fcf6,0x04da8f7f,0xcfbb4d89 } },
  46620. /* 215 */
  46621. { { 0x3b26139a,0x9a6a5df9,0xb2cc7eb8,0x3e076a83,0x5a964bcd,0x47a8e82d,
  46622. 0xb9278d6b,0x8a4e2a39,0xe4443549,0x93506c98,0xf1e0d566,0x06497a8f },
  46623. { 0x2b1efa05,0x3dee8d99,0x45393e33,0x2da63ca8,0xcf0579ad,0xa4af7277,
  46624. 0x3236d8ea,0xaf4b4639,0x32b617f5,0x6ccad95b,0xb88bb124,0xce76d8b8 } },
  46625. /* 216 */
  46626. { { 0x083843dc,0x63d2537a,0x1e4153b4,0x89eb3514,0xea9afc94,0x5175ebc4,
  46627. 0x8ed1aed7,0x7a652580,0xd85e8297,0x67295611,0xb584b73d,0x8dd2d68b },
  46628. { 0x0133c3a4,0x237139e6,0x4bd278ea,0x9de838ab,0xc062fcd9,0xe829b072,
  46629. 0x63ba8706,0x70730d4f,0xd3cd05ec,0x6080483f,0x0c85f84d,0x872ab5b8 } },
  46630. /* 217 */
  46631. { { 0x999d4d49,0xfc0776d3,0xec3f45e7,0xa3eb59de,0x0dae1fc1,0xbc990e44,
  46632. 0xa15371ff,0x33596b1e,0x9bc7ab25,0xd447dcb2,0x35979582,0xcd5b63e9 },
  46633. { 0x77d1ff11,0xae3366fa,0xedee6903,0x59f28f05,0xa4433bf2,0x6f43fed1,
  46634. 0xdf9ce00e,0x15409c9b,0xaca9c5dc,0x21b5cded,0x82d7bdb4,0xf9f33595 } },
  46635. /* 218 */
  46636. { { 0x9422c792,0x95944378,0xc958b8bf,0x239ea923,0xdf076541,0x4b61a247,
  46637. 0xbb9fc544,0x4d29ce85,0x0b424559,0x9a692a67,0x0e486900,0x6e0ca5a0 },
  46638. { 0x85b3bece,0x6b79a782,0xc61f9892,0x41f35e39,0xae747f82,0xff82099a,
  46639. 0xd0ca59d6,0x58c8ae3f,0x99406b5f,0x4ac930e2,0x9df24243,0x2ce04eb9 } },
  46640. /* 219 */
  46641. { { 0x1ac37b82,0x4366b994,0x25b04d83,0xff0c728d,0x19c47b7c,0x1f551361,
  46642. 0xbeff13e7,0xdbf2d5ed,0xe12a683d,0xf78efd51,0x989cf9c4,0x82cd85b9 },
  46643. { 0xe0cb5d37,0xe23c6db6,0x72ee1a15,0x818aeebd,0x28771b14,0x8212aafd,
  46644. 0x1def817d,0x7bc221d9,0x9445c51f,0xdac403a2,0x12c3746b,0x711b0517 } },
  46645. /* 220 */
  46646. { { 0x5ea99ecc,0x0ed9ed48,0xb8cab5e1,0xf799500d,0xb570cbdc,0xa8ec87dc,
  46647. 0xd35dfaec,0x52cfb2c2,0x6e4d80a4,0x8d31fae2,0xdcdeabe5,0xe6a37dc9 },
  46648. { 0x1deca452,0x5d365a34,0x0d68b44e,0x09a5f8a5,0xa60744b1,0x59238ea5,
  46649. 0xbb4249e9,0xf2fedc0d,0xa909b2e3,0xe395c74e,0x39388250,0xe156d1a5 } },
  46650. /* 221 */
  46651. { { 0x47181ae9,0xd796b3d0,0x44197808,0xbaf44ba8,0x34cf3fac,0xe6933094,
  46652. 0xc3bd5c46,0x41aa6ade,0xeed947c6,0x4fda75d8,0x9ea5a525,0xacd9d412 },
  46653. { 0xd430301b,0x65cc55a3,0x7b52ea49,0x3c9a5bcf,0x159507f0,0x22d319cf,
  46654. 0xde74a8dd,0x2ee0b9b5,0x877ac2b6,0x20c26a1e,0x92e7c314,0x387d73da } },
  46655. /* 222 */
  46656. { { 0x8cd3fdac,0x13c4833e,0x332e5b8e,0x76fcd473,0xe2fe1fd3,0xff671b4b,
  46657. 0x5d98d8ec,0x4d734e8b,0x514bbc11,0xb1ead3c6,0x7b390494,0xd14ca858 },
  46658. { 0x5d2d37e9,0x95a443af,0x00464622,0x73c6ea73,0x15755044,0xa44aeb4b,
  46659. 0xfab58fee,0xba3f8575,0xdc680a6f,0x9779dbc9,0x7b37ddfc,0xe1ee5f5a } },
  46660. /* 223 */
  46661. { { 0x12d29f46,0xcd0b4648,0x0ed53137,0x93295b0b,0x80bef6c9,0xbfe26094,
  46662. 0x54248b00,0xa6565788,0x80e7f9c4,0x69c43fca,0xbe141ea1,0x2190837b },
  46663. { 0xa1b26cfb,0x875e159a,0x7affe852,0x90ca9f87,0x92ca598e,0x15e6550d,
  46664. 0x1938ad11,0xe3e0945d,0x366ef937,0xef7636bb,0xb39869e5,0xb6034d0b } },
  46665. /* 224 */
  46666. { { 0x26d8356e,0x4d255e30,0xd314626f,0xf83666ed,0xd0c8ed64,0x421ddf61,
  46667. 0x26677b61,0x96e473c5,0x9e9b18b3,0xdad4af7e,0xa9393f75,0xfceffd4a },
  46668. { 0x11c731d5,0x843138a1,0xb2f141d9,0x05bcb3a1,0x617b7671,0x20e1fa95,
  46669. 0x88ccec7b,0xbefce812,0x90f1b568,0x582073dc,0x1f055cb7,0xf572261a } },
  46670. /* 225 */
  46671. { { 0x36973088,0xf3148277,0x86a9f980,0xc008e708,0xe046c261,0x1b795947,
  46672. 0xca76bca0,0xdf1e6a7d,0x71acddf0,0xabafd886,0x1364d8f4,0xff7054d9 },
  46673. { 0xe2260594,0x2cf63547,0xd73b277e,0x468a5372,0xef9bd35e,0xc7419e24,
  46674. 0x24043cc3,0x2b4a1c20,0x890b39cd,0xa28f047a,0x46f9a2e3,0xdca2cea1 } },
  46675. /* 226 */
  46676. { { 0x53277538,0xab788736,0xcf697738,0xa734e225,0x6b22e2c1,0x66ee1d1e,
  46677. 0xebe1d212,0x2c615389,0x02bb0766,0xf36cad40,0x3e64f207,0x120885c3 },
  46678. { 0x90fbfec2,0x59e77d56,0xd7a574ae,0xf9e781aa,0x5d045e53,0x801410b0,
  46679. 0xa91b5f0e,0xd3b5f0aa,0x7fbb3521,0xb3d1df00,0xc72bee9a,0x11c4b33e } },
  46680. /* 227 */
  46681. { { 0x83c3a7f3,0xd32b9832,0x88d8a354,0x8083abcf,0x50f4ec5a,0xdeb16404,
  46682. 0x641e2907,0x18d747f0,0xf1bbf03e,0x4e8978ae,0x88a0cd89,0x932447dc },
  46683. { 0xcf3d5897,0x561e0feb,0x13600e6d,0xfc3a682f,0xd16a6b73,0xc78b9d73,
  46684. 0xd29bf580,0xe713fede,0x08d69e5c,0x0a225223,0x1ff7fda4,0x3a924a57 } },
  46685. /* 228 */
  46686. { { 0xb4093bee,0xfb64554c,0xa58c6ec0,0xa6d65a25,0x43d0ed37,0x4126994d,
  46687. 0x55152d44,0xa5689a51,0x284caa8d,0xb8e5ea8c,0xd1f25538,0x33f05d4f },
  46688. { 0x1b615d6e,0xe0fdfe09,0x705507da,0x2ded7e8f,0x17bbcc80,0xdd5631e5,
  46689. 0x267fd11f,0x4f87453e,0xff89d62d,0xc6da723f,0xe3cda21d,0x55cbcae2 } },
  46690. /* 229 */
  46691. { { 0x6b4e84f3,0x336bc94e,0x4ef72c35,0x72863031,0xeeb57f99,0x6d85fdee,
  46692. 0xa42ece1b,0x7f4e3272,0x36f0320a,0x7f86cbb5,0x923331e6,0xf09b6a2b },
  46693. { 0x56778435,0x21d3ecf1,0x8323b2d2,0x2977ba99,0x1704bc0f,0x6a1b57fb,
  46694. 0x389f048a,0xd777cf8b,0xac6b42cd,0x9ce2174f,0x09e6c55a,0x404e2bff } },
  46695. /* 230 */
  46696. { { 0x204c5ddb,0x9b9b135e,0x3eff550e,0x9dbfe044,0xec3be0f6,0x35eab4bf,
  46697. 0x0a43e56f,0x8b4c3f0d,0x0e73f9b3,0x4c1c6673,0x2c78c905,0x92ed38bd },
  46698. { 0xa386e27c,0xc7003f6a,0xaced8507,0xb9c4f46f,0x59df5464,0xea024ec8,
  46699. 0x429572ea,0x4af96152,0xe1fc1194,0x279cd5e2,0x281e358c,0xaa376a03 } },
  46700. /* 231 */
  46701. { { 0x3cdbc95c,0x07859223,0xef2e337a,0xaae1aa6a,0x472a8544,0xc040108d,
  46702. 0x8d037b7d,0x80c853e6,0x8c7eee24,0xd221315c,0x8ee47752,0x195d3856 },
  46703. { 0xdacd7fbe,0xd4b1ba03,0xd3e0c52b,0x4b5ac61e,0x6aab7b52,0x68d3c052,
  46704. 0x660e3fea,0xf0d7248c,0x3145efb4,0xafdb3f89,0x8f40936d,0xa73fd9a3 } },
  46705. /* 232 */
  46706. { { 0xbb1b17ce,0x891b9ef3,0xc6127f31,0x14023667,0x305521fd,0x12b2e58d,
  46707. 0xe3508088,0x3a47e449,0xff751507,0xe49fc84b,0x5310d16e,0x4023f722 },
  46708. { 0xb73399fa,0xa608e5ed,0xd532aa3e,0xf12632d8,0x845e8415,0x13a2758e,
  46709. 0x1fc2d861,0xae4b6f85,0x339d02f2,0x3879f5b1,0x80d99ebd,0x446d22a6 } },
  46710. /* 233 */
  46711. { { 0x4be164f1,0x0f502302,0x88b81920,0x8d09d2d6,0x984aceff,0x514056f1,
  46712. 0x75e9e80d,0xa5c4ddf0,0xdf496a93,0x38cb47e6,0x38df6bf7,0x899e1d6b },
  46713. { 0xb59eb2a6,0x69e87e88,0x9b47f38b,0x280d9d63,0x3654e955,0x599411ea,
  46714. 0x969aa581,0xcf8dd4fd,0x530742a7,0xff5c2baf,0x1a373085,0xa4391536 } },
  46715. /* 234 */
  46716. { { 0xa8a4bdd2,0x6ace72a3,0xb68ef702,0xc656cdd1,0x90c4dad8,0xd4a33e7e,
  46717. 0x9d951c50,0x4aece08a,0x085d68e6,0xea8005ae,0x6f7502b8,0xfdd7a7d7 },
  46718. { 0x98d6fa45,0xce6fb0a6,0x1104eb8c,0x228f8672,0xda09d7dc,0xd23d8787,
  46719. 0x2ae93065,0x5521428b,0xea56c366,0x95faba3d,0x0a88aca5,0xedbe5039 } },
  46720. /* 235 */
  46721. { { 0xbfb26c82,0xd64da0ad,0x952c2f9c,0xe5d70b3c,0xf7e77f68,0xf5e8f365,
  46722. 0x08f2d695,0x7234e002,0xd12e7be6,0xfaf900ee,0x4acf734e,0x27dc6934 },
  46723. { 0xc260a46a,0x80e4ff5e,0x2dc31c28,0x7da5ebce,0xca69f552,0x485c5d73,
  46724. 0x69cc84c2,0xcdfb6b29,0xed6d4eca,0x031c5afe,0x22247637,0xc7bbf4c8 } },
  46725. /* 236 */
  46726. { { 0x49fe01b2,0x9d5b72c7,0x793a91b8,0x34785186,0xcf460438,0xa3ba3c54,
  46727. 0x3ab21b6f,0x73e8e43d,0xbe57b8ab,0x50cde8e0,0xdd204264,0x6488b3a7 },
  46728. { 0xdddc4582,0xa9e398b3,0x5bec46fe,0x1698c1a9,0x156d3843,0x7f1446ef,
  46729. 0x770329a2,0x3fd25dd8,0x2c710668,0x05b1221a,0xa72ee6cf,0x65b2dc2a } },
  46730. /* 237 */
  46731. { { 0xcd021d63,0x21a885f7,0xfea61f08,0x3f344b15,0xc5cf73e6,0xad5ba6dd,
  46732. 0x227a8b23,0x154d0d8f,0xdc559311,0x9b74373c,0x98620fa1,0x4feab715 },
  46733. { 0x7d9ec924,0x5098938e,0x6d47e550,0x84d54a5e,0x1b617506,0x1a2d1bdc,
  46734. 0x615868a4,0x99fe1782,0x3005a924,0x171da780,0x7d8f79b6,0xa70bf5ed } },
  46735. /* 238 */
  46736. { { 0xfe2216c5,0x0bc1250d,0x7601b351,0x2c37e250,0xd6f06b7e,0xb6300175,
  46737. 0x8bfeb9b7,0x4dde8ca1,0xb82f843d,0x4f210432,0xb1ac0afd,0x8d70e2f9 },
  46738. { 0xaae91abb,0x25c73b78,0x863028f2,0x0230dca3,0xe5cf30b7,0x8b923ecf,
  46739. 0x5506f265,0xed754ec2,0x729a5e39,0x8e41b88c,0xbabf889b,0xee67cec2 } },
  46740. /* 239 */
  46741. { { 0x1be46c65,0xe183acf5,0xe7565d7a,0x9789538f,0xd9627b4e,0x87873391,
  46742. 0x9f1d9187,0xbf4ac4c1,0x4691f5c8,0x5db99f63,0x74a1fb98,0xa68df803 },
  46743. { 0xbf92b5fa,0x3c448ed1,0x3e0bdc32,0xa098c841,0x79bf016c,0x8e74cd55,
  46744. 0x115e244d,0x5df0d09c,0x3410b66e,0x9418ad01,0x17a02130,0x8b6124cb } },
  46745. /* 240 */
  46746. { { 0xc26e3392,0x425ec3af,0xa1722e00,0xc07f8470,0xe2356b43,0xdcc28190,
  46747. 0xb1ef59a6,0x4ed97dff,0xc63028c1,0xc22b3ad1,0x68c18988,0x070723c2 },
  46748. { 0x4cf49e7d,0x70da302f,0x3f12a522,0xc5e87c93,0x18594148,0x74acdd1d,
  46749. 0xca74124c,0xad5f73ab,0xd69fd478,0xe72e4a3e,0x7b117cc3,0x61593868 } },
  46750. /* 241 */
  46751. { { 0xa9aa0486,0x7b7b9577,0xa063d557,0x6e41fb35,0xda9047d7,0xb017d5c7,
  46752. 0x68a87ba9,0x8c748280,0xdf08ad93,0xab45fa5c,0x4c288a28,0xcd9fb217 },
  46753. { 0x5747843d,0x59544642,0xa56111e3,0x34d64c6c,0x4bfce8d5,0x12e47ea1,
  46754. 0x6169267f,0x17740e05,0xeed03fb5,0x5c49438e,0x4fc3f513,0x9da30add } },
  46755. /* 242 */
  46756. { { 0xccfa5200,0xc4e85282,0x6a19b13d,0x2707608f,0xf5726e2f,0xdcb9a53d,
  46757. 0xe9427de5,0x612407c9,0xd54d582a,0x3e5a17e1,0x655ae118,0xb99877de },
  46758. { 0x015254de,0x6f0e972b,0xf0a6f7c5,0x92a56db1,0xa656f8b2,0xd297e4e1,
  46759. 0xad981983,0x99fe0052,0x07cfed84,0xd3652d2f,0x843c1738,0xc784352e } },
  46760. /* 243 */
  46761. { { 0x7e9b2d8a,0x6ee90af0,0x57cf1964,0xac8d7018,0x71f28efc,0xf6ed9031,
  46762. 0x6812b20e,0x7f70d5a9,0xf1c61eee,0x27b557f4,0xc6263758,0xf1c9bd57 },
  46763. { 0x2a1a6194,0x5cf7d014,0x1890ab84,0xdd614e0b,0x0e93c2a6,0x3ef9de10,
  46764. 0xe0cd91c5,0xf98cf575,0x14befc32,0x504ec0c6,0x6279d68c,0xd0513a66 } },
  46765. /* 244 */
  46766. { { 0xa859fb6a,0xa8eadbad,0xdb283666,0xcf8346e7,0x3e22e355,0x7b35e61a,
  46767. 0x99639c6b,0x293ece2c,0x56f241c8,0xfa0162e2,0xbf7a1dda,0xd2e6c7b9 },
  46768. { 0x40075e63,0xd0de6253,0xf9ec8286,0x2405aa61,0x8fe45494,0x2237830a,
  46769. 0x364e9c8c,0x4fd01ac7,0x904ba750,0x4d9c3d21,0xaf1b520b,0xd589be14 } },
  46770. /* 245 */
  46771. { { 0x4662e53b,0x13576a4f,0xf9077676,0x35ec2f51,0x97c0af97,0x66297d13,
  46772. 0x9e598b58,0xed3201fe,0x5e70f604,0x49bc752a,0xbb12d951,0xb54af535 },
  46773. { 0x212c1c76,0x36ea4c2b,0xeb250dfd,0x18f5bbc7,0x9a0a1a46,0xa0d466cc,
  46774. 0xdac2d917,0x52564da4,0x8e95fab5,0x206559f4,0x9ca67a33,0x7487c190 } },
  46775. /* 246 */
  46776. { { 0xdde98e9c,0x75abfe37,0x2a411199,0x99b90b26,0xdcdb1f7c,0x1b410996,
  46777. 0x8b3b5675,0xab346f11,0xf1f8ae1e,0x04852193,0x6b8b98c1,0x1ec4d227 },
  46778. { 0x45452baa,0xba3bc926,0xacc4a572,0x387d1858,0xe51f171e,0x9478eff6,
  46779. 0x931e1c00,0xf357077d,0xe54c8ca8,0xffee77cd,0x551dc9a4,0xfb4892ff } },
  46780. /* 247 */
  46781. { { 0x2db8dff8,0x5b1bdad0,0x5a2285a2,0xd462f4fd,0xda00b461,0x1d6aad8e,
  46782. 0x41306d1b,0x43fbefcf,0x6a13fe19,0x428e86f3,0x17f89404,0xc8b2f118 },
  46783. { 0xf0d51afb,0x762528aa,0x549b1d06,0xa3e2fea4,0xea3ddf66,0x86fad8f2,
  46784. 0x4fbdd206,0x0d9ccc4b,0xc189ff5a,0xcde97d4c,0x199f19a6,0xc36793d6 } },
  46785. /* 248 */
  46786. { { 0x51b85197,0xea38909b,0xb4c92895,0xffb17dd0,0x1ddb3f3f,0x0eb0878b,
  46787. 0xc57cf0f2,0xb05d28ff,0x1abd57e2,0xd8bde2e7,0xc40c1b20,0x7f2be28d },
  46788. { 0x299a2d48,0x6554dca2,0x8377982d,0x5130ba2e,0x1071971a,0x8863205f,
  46789. 0x7cf2825d,0x15ee6282,0x03748f2b,0xd4b6c57f,0x430385a0,0xa9e3f4da } },
  46790. /* 249 */
  46791. { { 0x83fbc9c6,0x33eb7cec,0x4541777e,0x24a311c7,0x4f0767fc,0xc81377f7,
  46792. 0x4ab702da,0x12adae36,0x2a779696,0xb7fcb6db,0x01cea6ad,0x4a6fb284 },
  46793. { 0xcdfc73de,0x5e8b1d2a,0x1b02fd32,0xd0efae8d,0xd81d8519,0x3f99c190,
  46794. 0xfc808971,0x3c18f7fa,0x51b7ae7b,0x41f713e7,0xf07fc3f8,0x0a4b3435 } },
  46795. /* 250 */
  46796. { { 0x019b7d2e,0x7dda3c4c,0xd4dc4b89,0x631c8d1a,0x1cdb313c,0x5489cd6e,
  46797. 0x4c07bb06,0xd44aed10,0x75f000d1,0x8f97e13a,0xdda5df4d,0x0e9ee64f },
  46798. { 0x3e346910,0xeaa99f3b,0xfa294ad7,0x622f6921,0x0d0b2fe9,0x22aaa20d,
  46799. 0x1e5881ba,0x4fed2f99,0xc1571802,0x9af3b2d6,0xdc7ee17c,0x919e67a8 } },
  46800. /* 251 */
  46801. { { 0x76250533,0xc724fe4c,0x7d817ef8,0x8a2080e5,0x172c9751,0xa2afb0f4,
  46802. 0x17c0702e,0x9b10cdeb,0xc9b7e3e9,0xbf3975e3,0x1cd0cdc5,0x206117df },
  46803. { 0xbe05ebd5,0xfb049e61,0x16c782c0,0xeb0bb55c,0xab7fed09,0x13a331b8,
  46804. 0x632863f0,0xf6c58b1d,0x4d3b6195,0x6264ef6e,0x9a53f116,0x92c51b63 } },
  46805. /* 252 */
  46806. { { 0x288b364d,0xa57c7bc8,0x7b41e5c4,0x4a562e08,0x698a9a11,0x699d21c6,
  46807. 0xf3f849b9,0xa4ed9581,0x9eb726ba,0xa223eef3,0xcc2884f9,0x13159c23 },
  46808. { 0x3a3f4963,0x73931e58,0x0ada6a81,0x96500389,0x5ab2950b,0x3ee8a1c6,
  46809. 0x775fab52,0xeedf4949,0x4f2671b6,0x63d652e1,0x3c4e2f55,0xfed4491c } },
  46810. /* 253 */
  46811. { { 0xf4eb453e,0x335eadc3,0xcadd1a5b,0x5ff74b63,0x5d84a91a,0x6933d0d7,
  46812. 0xb49ba337,0x9ca3eeb9,0xc04c15b8,0x1f6facce,0xdc09a7e4,0x4ef19326 },
  46813. { 0x3dca3233,0x53d2d324,0xa2259d4b,0x0ee40590,0x5546f002,0x18c22edb,
  46814. 0x09ea6b71,0x92429801,0xb0e91e61,0xaada0add,0x99963c50,0x5fe53ef4 } },
  46815. /* 254 */
  46816. { { 0x90c28c65,0x372dd06b,0x119ce47d,0x1765242c,0x6b22fc82,0xc041fb80,
  46817. 0xb0a7ccc1,0x667edf07,0x1261bece,0xc79599e7,0x19cff22a,0xbc69d9ba },
  46818. { 0x13c06819,0x009d77cd,0xe282b79d,0x635a66ae,0x225b1be8,0x4edac4a6,
  46819. 0x524008f9,0x57d4f4e4,0xb056af84,0xee299ac5,0x3a0bc386,0xcc38444c } },
  46820. /* 255 */
  46821. { { 0xcd4c2356,0x490643b1,0x750547be,0x740a4851,0xd4944c04,0x643eaf29,
  46822. 0x299a98a0,0xba572479,0xee05fdf9,0x48b29f16,0x089b2d7b,0x33fb4f61 },
  46823. { 0xa950f955,0x86704902,0xfedc3ddf,0x97e1034d,0x05fbb6a2,0x211320b6,
  46824. 0x432299bb,0x23d7b93f,0x8590e4a3,0x1fe1a057,0xf58c0ce6,0x8e1d0586 } },
  46825. };
  46826. /* Multiply the base point of P384 by the scalar and return the result.
  46827. * If map is true then convert result to affine coordinates.
  46828. *
  46829. * Stripe implementation.
  46830. * Pre-generated: 2^0, 2^48, ...
  46831. * Pre-generated: products of all combinations of above.
  46832. * 8 doubles and adds (with qz=1)
  46833. *
  46834. * r Resulting point.
  46835. * k Scalar to multiply by.
  46836. * map Indicates whether to convert result to affine.
  46837. * ct Constant time required.
  46838. * heap Heap to use for allocation.
  46839. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  46840. */
  46841. static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k,
  46842. int map, int ct, void* heap)
  46843. {
  46844. return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table,
  46845. k, map, ct, heap);
  46846. }
  46847. #endif
  46848. /* Multiply the base point of P384 by the scalar and return the result.
  46849. * If map is true then convert result to affine coordinates.
  46850. *
  46851. * km Scalar to multiply by.
  46852. * r Resulting point.
  46853. * map Indicates whether to convert result to affine.
  46854. * heap Heap to use for allocation.
  46855. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  46856. */
  46857. int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap)
  46858. {
  46859. #ifdef WOLFSSL_SP_SMALL_STACK
  46860. sp_point_384* point = NULL;
  46861. sp_digit* k = NULL;
  46862. #else
  46863. sp_point_384 point[1];
  46864. sp_digit k[12];
  46865. #endif
  46866. int err = MP_OKAY;
  46867. #ifdef WOLFSSL_SP_SMALL_STACK
  46868. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  46869. DYNAMIC_TYPE_ECC);
  46870. if (point == NULL)
  46871. err = MEMORY_E;
  46872. if (err == MP_OKAY) {
  46873. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap,
  46874. DYNAMIC_TYPE_ECC);
  46875. if (k == NULL)
  46876. err = MEMORY_E;
  46877. }
  46878. #endif
  46879. if (err == MP_OKAY) {
  46880. sp_384_from_mp(k, 12, km);
  46881. err = sp_384_ecc_mulmod_base_12(point, k, map, 1, heap);
  46882. }
  46883. if (err == MP_OKAY) {
  46884. err = sp_384_point_to_ecc_point_12(point, r);
  46885. }
  46886. #ifdef WOLFSSL_SP_SMALL_STACK
  46887. if (k != NULL)
  46888. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  46889. if (point != NULL)
  46890. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  46891. #endif
  46892. return err;
  46893. }
  46894. /* Multiply the base point of P384 by the scalar, add point a and return
  46895. * the result. If map is true then convert result to affine coordinates.
  46896. *
  46897. * km Scalar to multiply by.
  46898. * am Point to add to scalar multiply result.
  46899. * inMont Point to add is in montgomery form.
  46900. * r Resulting point.
  46901. * map Indicates whether to convert result to affine.
  46902. * heap Heap to use for allocation.
  46903. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  46904. */
  46905. int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am,
  46906. int inMont, ecc_point* r, int map, void* heap)
  46907. {
  46908. #ifdef WOLFSSL_SP_SMALL_STACK
  46909. sp_point_384* point = NULL;
  46910. sp_digit* k = NULL;
  46911. #else
  46912. sp_point_384 point[2];
  46913. sp_digit k[12 + 12 * 2 * 6];
  46914. #endif
  46915. sp_point_384* addP = NULL;
  46916. sp_digit* tmp = NULL;
  46917. int err = MP_OKAY;
  46918. #ifdef WOLFSSL_SP_SMALL_STACK
  46919. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  46920. DYNAMIC_TYPE_ECC);
  46921. if (point == NULL)
  46922. err = MEMORY_E;
  46923. if (err == MP_OKAY) {
  46924. k = (sp_digit*)XMALLOC(
  46925. sizeof(sp_digit) * (12 + 12 * 2 * 6),
  46926. heap, DYNAMIC_TYPE_ECC);
  46927. if (k == NULL)
  46928. err = MEMORY_E;
  46929. }
  46930. #endif
  46931. if (err == MP_OKAY) {
  46932. addP = point + 1;
  46933. tmp = k + 12;
  46934. sp_384_from_mp(k, 12, km);
  46935. sp_384_point_from_ecc_point_12(addP, am);
  46936. }
  46937. if ((err == MP_OKAY) && (!inMont)) {
  46938. err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod);
  46939. }
  46940. if ((err == MP_OKAY) && (!inMont)) {
  46941. err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod);
  46942. }
  46943. if ((err == MP_OKAY) && (!inMont)) {
  46944. err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod);
  46945. }
  46946. if (err == MP_OKAY) {
  46947. err = sp_384_ecc_mulmod_base_12(point, k, 0, 0, heap);
  46948. }
  46949. if (err == MP_OKAY) {
  46950. sp_384_proj_point_add_12(point, point, addP, tmp);
  46951. if (map) {
  46952. sp_384_map_12(point, point, tmp);
  46953. }
  46954. err = sp_384_point_to_ecc_point_12(point, r);
  46955. }
  46956. #ifdef WOLFSSL_SP_SMALL_STACK
  46957. if (k != NULL)
  46958. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  46959. if (point)
  46960. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  46961. #endif
  46962. return err;
  46963. }
  46964. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  46965. defined(HAVE_ECC_VERIFY)
  46966. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  46967. /* Add 1 to a. (a = a + 1)
  46968. *
  46969. * a A single precision integer.
  46970. */
  46971. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  46972. static void sp_384_add_one_12(sp_digit* a_p)
  46973. #else
  46974. static void sp_384_add_one_12(sp_digit* a)
  46975. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  46976. {
  46977. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  46978. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  46979. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  46980. __asm__ __volatile__ (
  46981. "LDM %[a], {r1, r2, r3, r4}\n\t"
  46982. "ADDS r1, r1, #0x1\n\t"
  46983. "ADCS r2, r2, #0x0\n\t"
  46984. "ADCS r3, r3, #0x0\n\t"
  46985. "ADCS r4, r4, #0x0\n\t"
  46986. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  46987. "LDM %[a], {r1, r2, r3, r4}\n\t"
  46988. "ADCS r1, r1, #0x0\n\t"
  46989. "ADCS r2, r2, #0x0\n\t"
  46990. "ADCS r3, r3, #0x0\n\t"
  46991. "ADCS r4, r4, #0x0\n\t"
  46992. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  46993. "LDM %[a], {r1, r2, r3, r4}\n\t"
  46994. "ADCS r1, r1, #0x0\n\t"
  46995. "ADCS r2, r2, #0x0\n\t"
  46996. "ADCS r3, r3, #0x0\n\t"
  46997. "ADCS r4, r4, #0x0\n\t"
  46998. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  46999. : [a] "+r" (a)
  47000. :
  47001. : "memory", "r1", "r2", "r3", "r4", "cc"
  47002. );
  47003. }
  47004. /* Read big endian unsigned byte array into r.
  47005. *
  47006. * r A single precision integer.
  47007. * size Maximum number of bytes to convert
  47008. * a Byte array.
  47009. * n Number of bytes in array to read.
  47010. */
  47011. static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n)
  47012. {
  47013. int i;
  47014. int j;
  47015. byte* d;
  47016. for (i = n - 1,j = 0; i >= 3; i -= 4) {
  47017. r[j] = ((sp_digit)a[i - 0] << 0) |
  47018. ((sp_digit)a[i - 1] << 8) |
  47019. ((sp_digit)a[i - 2] << 16) |
  47020. ((sp_digit)a[i - 3] << 24);
  47021. j++;
  47022. }
  47023. if (i >= 0) {
  47024. r[j] = 0;
  47025. d = (byte*)r;
  47026. switch (i) {
  47027. case 2: d[n - 1 - 2] = a[2]; //fallthrough
  47028. case 1: d[n - 1 - 1] = a[1]; //fallthrough
  47029. case 0: d[n - 1 - 0] = a[0]; //fallthrough
  47030. }
  47031. j++;
  47032. }
  47033. for (; j < size; j++) {
  47034. r[j] = 0;
  47035. }
  47036. }
  47037. /* Generates a scalar that is in the range 1..order-1.
  47038. *
  47039. * rng Random number generator.
  47040. * k Scalar value.
  47041. * returns RNG failures, MEMORY_E when memory allocation fails and
  47042. * MP_OKAY on success.
  47043. */
  47044. static int sp_384_ecc_gen_k_12(WC_RNG* rng, sp_digit* k)
  47045. {
  47046. int err;
  47047. byte buf[48];
  47048. do {
  47049. err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
  47050. if (err == 0) {
  47051. sp_384_from_bin(k, 12, buf, (int)sizeof(buf));
  47052. if (sp_384_cmp_12(k, p384_order2) <= 0) {
  47053. sp_384_add_one_12(k);
  47054. break;
  47055. }
  47056. }
  47057. }
  47058. while (err == 0);
  47059. return err;
  47060. }
  47061. /* Makes a random EC key pair.
  47062. *
  47063. * rng Random number generator.
  47064. * priv Generated private value.
  47065. * pub Generated public point.
  47066. * heap Heap to use for allocation.
  47067. * returns ECC_INF_E when the point does not have the correct order, RNG
  47068. * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
  47069. */
  47070. int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
  47071. {
  47072. #ifdef WOLFSSL_SP_SMALL_STACK
  47073. sp_point_384* point = NULL;
  47074. sp_digit* k = NULL;
  47075. #else
  47076. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47077. sp_point_384 point[2];
  47078. #else
  47079. sp_point_384 point[1];
  47080. #endif
  47081. sp_digit k[12];
  47082. #endif
  47083. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47084. sp_point_384* infinity = NULL;
  47085. #endif
  47086. int err = MP_OKAY;
  47087. (void)heap;
  47088. #ifdef WOLFSSL_SP_SMALL_STACK
  47089. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47090. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC);
  47091. #else
  47092. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
  47093. #endif
  47094. if (point == NULL)
  47095. err = MEMORY_E;
  47096. if (err == MP_OKAY) {
  47097. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap,
  47098. DYNAMIC_TYPE_ECC);
  47099. if (k == NULL)
  47100. err = MEMORY_E;
  47101. }
  47102. #endif
  47103. if (err == MP_OKAY) {
  47104. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47105. infinity = point + 1;
  47106. #endif
  47107. err = sp_384_ecc_gen_k_12(rng, k);
  47108. }
  47109. if (err == MP_OKAY) {
  47110. err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, NULL);
  47111. }
  47112. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47113. if (err == MP_OKAY) {
  47114. err = sp_384_ecc_mulmod_12(infinity, point, p384_order, 1, 1, NULL);
  47115. }
  47116. if (err == MP_OKAY) {
  47117. if (sp_384_iszero_12(point->x) || sp_384_iszero_12(point->y)) {
  47118. err = ECC_INF_E;
  47119. }
  47120. }
  47121. #endif
  47122. if (err == MP_OKAY) {
  47123. err = sp_384_to_mp(k, priv);
  47124. }
  47125. if (err == MP_OKAY) {
  47126. err = sp_384_point_to_ecc_point_12(point, pub);
  47127. }
  47128. #ifdef WOLFSSL_SP_SMALL_STACK
  47129. if (k != NULL)
  47130. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  47131. if (point != NULL) {
  47132. /* point is not sensitive, so no need to zeroize */
  47133. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  47134. }
  47135. #endif
  47136. return err;
  47137. }
  47138. #ifdef WOLFSSL_SP_NONBLOCK
  47139. typedef struct sp_ecc_key_gen_384_ctx {
  47140. int state;
  47141. sp_384_ecc_mulmod_12_ctx mulmod_ctx;
  47142. sp_digit k[12];
  47143. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47144. sp_point_384 point[2];
  47145. #else
  47146. sp_point_384 point[1];
  47147. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  47148. } sp_ecc_key_gen_384_ctx;
  47149. int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv,
  47150. ecc_point* pub, void* heap)
  47151. {
  47152. int err = FP_WOULDBLOCK;
  47153. sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data;
  47154. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47155. sp_point_384* infinity = ctx->point + 1;
  47156. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  47157. typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx)
  47158. >= sizeof(*sp_ctx) ? -1 : 1];
  47159. (void)sizeof(ctx_size_test);
  47160. switch (ctx->state) {
  47161. case 0:
  47162. err = sp_384_ecc_gen_k_12(rng, ctx->k);
  47163. if (err == MP_OKAY) {
  47164. err = FP_WOULDBLOCK;
  47165. ctx->state = 1;
  47166. }
  47167. break;
  47168. case 1:
  47169. err = sp_384_ecc_mulmod_base_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  47170. ctx->point, ctx->k, 1, 1, heap);
  47171. if (err == MP_OKAY) {
  47172. err = FP_WOULDBLOCK;
  47173. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47174. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  47175. ctx->state = 2;
  47176. #else
  47177. ctx->state = 3;
  47178. #endif
  47179. }
  47180. break;
  47181. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  47182. case 2:
  47183. err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  47184. infinity, ctx->point, p384_order, 1, 1);
  47185. if (err == MP_OKAY) {
  47186. if (sp_384_iszero_12(ctx->point->x) ||
  47187. sp_384_iszero_12(ctx->point->y)) {
  47188. err = ECC_INF_E;
  47189. }
  47190. else {
  47191. err = FP_WOULDBLOCK;
  47192. ctx->state = 3;
  47193. }
  47194. }
  47195. break;
  47196. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  47197. case 3:
  47198. err = sp_384_to_mp(ctx->k, priv);
  47199. if (err == MP_OKAY) {
  47200. err = sp_384_point_to_ecc_point_12(ctx->point, pub);
  47201. }
  47202. break;
  47203. }
  47204. if (err != FP_WOULDBLOCK) {
  47205. XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx));
  47206. }
  47207. return err;
  47208. }
  47209. #endif /* WOLFSSL_SP_NONBLOCK */
  47210. #ifdef HAVE_ECC_DHE
  47211. /* Write r as big endian to byte array.
  47212. * Fixed length number of bytes written: 48
  47213. *
  47214. * r A single precision integer.
  47215. * a Byte array.
  47216. */
  47217. static void sp_384_to_bin_12(sp_digit* r, byte* a)
  47218. {
  47219. int i;
  47220. int j = 0;
  47221. for (i = 11; i >= 0; i--) {
  47222. a[j++] = r[i] >> 24;
  47223. a[j++] = r[i] >> 16;
  47224. a[j++] = r[i] >> 8;
  47225. a[j++] = r[i] >> 0;
  47226. }
  47227. }
  47228. /* Multiply the point by the scalar and serialize the X ordinate.
  47229. * The number is 0 padded to maximum size on output.
  47230. *
  47231. * priv Scalar to multiply the point by.
  47232. * pub Point to multiply.
  47233. * out Buffer to hold X ordinate.
  47234. * outLen On entry, size of the buffer in bytes.
  47235. * On exit, length of data in buffer in bytes.
  47236. * heap Heap to use for allocation.
  47237. * returns BUFFER_E if the buffer is to small for output size,
  47238. * MEMORY_E when memory allocation fails and MP_OKAY on success.
  47239. */
  47240. int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out,
  47241. word32* outLen, void* heap)
  47242. {
  47243. #ifdef WOLFSSL_SP_SMALL_STACK
  47244. sp_point_384* point = NULL;
  47245. sp_digit* k = NULL;
  47246. #else
  47247. sp_point_384 point[1];
  47248. sp_digit k[12];
  47249. #endif
  47250. int err = MP_OKAY;
  47251. if (*outLen < 48U) {
  47252. err = BUFFER_E;
  47253. }
  47254. #ifdef WOLFSSL_SP_SMALL_STACK
  47255. if (err == MP_OKAY) {
  47256. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  47257. DYNAMIC_TYPE_ECC);
  47258. if (point == NULL)
  47259. err = MEMORY_E;
  47260. }
  47261. if (err == MP_OKAY) {
  47262. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap,
  47263. DYNAMIC_TYPE_ECC);
  47264. if (k == NULL)
  47265. err = MEMORY_E;
  47266. }
  47267. #endif
  47268. if (err == MP_OKAY) {
  47269. sp_384_from_mp(k, 12, priv);
  47270. sp_384_point_from_ecc_point_12(point, pub);
  47271. err = sp_384_ecc_mulmod_12(point, point, k, 1, 1, heap);
  47272. }
  47273. if (err == MP_OKAY) {
  47274. sp_384_to_bin_12(point->x, out);
  47275. *outLen = 48;
  47276. }
  47277. #ifdef WOLFSSL_SP_SMALL_STACK
  47278. if (k != NULL)
  47279. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  47280. if (point != NULL)
  47281. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  47282. #endif
  47283. return err;
  47284. }
  47285. #ifdef WOLFSSL_SP_NONBLOCK
  47286. typedef struct sp_ecc_sec_gen_384_ctx {
  47287. int state;
  47288. union {
  47289. sp_384_ecc_mulmod_12_ctx mulmod_ctx;
  47290. };
  47291. sp_digit k[12];
  47292. sp_point_384 point;
  47293. } sp_ecc_sec_gen_384_ctx;
  47294. int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
  47295. const ecc_point* pub, byte* out, word32* outLen, void* heap)
  47296. {
  47297. int err = FP_WOULDBLOCK;
  47298. sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data;
  47299. typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  47300. (void)sizeof(ctx_size_test);
  47301. if (*outLen < 32U) {
  47302. err = BUFFER_E;
  47303. }
  47304. switch (ctx->state) {
  47305. case 0:
  47306. sp_384_from_mp(ctx->k, 12, priv);
  47307. sp_384_point_from_ecc_point_12(&ctx->point, pub);
  47308. ctx->state = 1;
  47309. break;
  47310. case 1:
  47311. err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  47312. &ctx->point, &ctx->point, ctx->k, 1, 1, heap);
  47313. if (err == MP_OKAY) {
  47314. sp_384_to_bin_12(ctx->point.x, out);
  47315. *outLen = 48;
  47316. }
  47317. break;
  47318. }
  47319. if (err == MP_OKAY && ctx->state != 1) {
  47320. err = FP_WOULDBLOCK;
  47321. }
  47322. if (err != FP_WOULDBLOCK) {
  47323. XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx));
  47324. }
  47325. return err;
  47326. }
  47327. #endif /* WOLFSSL_SP_NONBLOCK */
  47328. #endif /* HAVE_ECC_DHE */
  47329. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  47330. #endif
  47331. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  47332. #endif
  47333. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  47334. #ifdef WOLFSSL_SP_SMALL
  47335. /* Sub b from a into a. (a -= b)
  47336. *
  47337. * a A single precision integer.
  47338. * b A single precision integer.
  47339. */
  47340. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47341. static sp_digit sp_384_sub_in_place_12(sp_digit* a_p, const sp_digit* b_p)
  47342. #else
  47343. static sp_digit sp_384_sub_in_place_12(sp_digit* a, const sp_digit* b)
  47344. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47345. {
  47346. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47347. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  47348. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  47349. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47350. __asm__ __volatile__ (
  47351. "MOV r10, #0x0\n\t"
  47352. "ADD r11, %[a], #0x30\n\t"
  47353. "\n"
  47354. "L_sp_384_sub_in_pkace_12_word:\n\t"
  47355. "RSBS r10, r10, #0x0\n\t"
  47356. "LDM %[a], {r2, r3, r4, r5}\n\t"
  47357. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  47358. "SBCS r2, r2, r6\n\t"
  47359. "SBCS r3, r3, r7\n\t"
  47360. "SBCS r4, r4, r8\n\t"
  47361. "SBCS r5, r5, r9\n\t"
  47362. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  47363. "SBC r10, r10, r10\n\t"
  47364. "CMP %[a], r11\n\t"
  47365. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  47366. "BNE L_sp_384_sub_in_pkace_12_word\n\t"
  47367. #else
  47368. "BNE.N L_sp_384_sub_in_pkace_12_word\n\t"
  47369. #endif
  47370. "MOV %[a], r10\n\t"
  47371. : [a] "+r" (a), [b] "+r" (b)
  47372. :
  47373. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  47374. );
  47375. return (uint32_t)(size_t)a;
  47376. }
  47377. #else
  47378. /* Sub b from a into a. (a -= b)
  47379. *
  47380. * a A single precision integer and result.
  47381. * b A single precision integer.
  47382. */
  47383. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47384. static sp_digit sp_384_sub_in_place_12(sp_digit* a_p, const sp_digit* b_p)
  47385. #else
  47386. static sp_digit sp_384_sub_in_place_12(sp_digit* a, const sp_digit* b)
  47387. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47388. {
  47389. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47390. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  47391. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  47392. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47393. __asm__ __volatile__ (
  47394. "LDM %[a], {r2, r3, r4, r5}\n\t"
  47395. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  47396. "SUBS r2, r2, r6\n\t"
  47397. "SBCS r3, r3, r7\n\t"
  47398. "SBCS r4, r4, r8\n\t"
  47399. "SBCS r5, r5, r9\n\t"
  47400. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  47401. "LDM %[a], {r2, r3, r4, r5}\n\t"
  47402. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  47403. "SBCS r2, r2, r6\n\t"
  47404. "SBCS r3, r3, r7\n\t"
  47405. "SBCS r4, r4, r8\n\t"
  47406. "SBCS r5, r5, r9\n\t"
  47407. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  47408. "LDM %[a], {r2, r3, r4, r5}\n\t"
  47409. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  47410. "SBCS r2, r2, r6\n\t"
  47411. "SBCS r3, r3, r7\n\t"
  47412. "SBCS r4, r4, r8\n\t"
  47413. "SBCS r5, r5, r9\n\t"
  47414. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  47415. "SBC %[a], r9, r9\n\t"
  47416. : [a] "+r" (a), [b] "+r" (b)
  47417. :
  47418. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  47419. );
  47420. return (uint32_t)(size_t)a;
  47421. }
  47422. #endif /* WOLFSSL_SP_SMALL */
  47423. #ifdef WOLFSSL_SP_SMALL
  47424. /* Mul a by digit b into r. (r = a * b)
  47425. *
  47426. * r A single precision integer.
  47427. * a A single precision integer.
  47428. * b A single precision digit.
  47429. */
  47430. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47431. static void sp_384_mul_d_12(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  47432. #else
  47433. static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a, sp_digit b)
  47434. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47435. {
  47436. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47437. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  47438. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  47439. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  47440. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47441. __asm__ __volatile__ (
  47442. /* A[0] * B */
  47443. "LDR r8, [%[a]]\n\t"
  47444. "UMULL r5, r3, %[b], r8\n\t"
  47445. "MOV r4, #0x0\n\t"
  47446. "STR r5, [%[r]]\n\t"
  47447. "MOV r5, #0x0\n\t"
  47448. "MOV r9, #0x4\n\t"
  47449. "\n"
  47450. "L_sp_384_mul_d_12_word:\n\t"
  47451. /* A[i] * B */
  47452. "LDR r8, [%[a], r9]\n\t"
  47453. "UMULL r6, r7, %[b], r8\n\t"
  47454. "ADDS r3, r3, r6\n\t"
  47455. "ADCS r4, r4, r7\n\t"
  47456. "ADC r5, r5, #0x0\n\t"
  47457. "STR r3, [%[r], r9]\n\t"
  47458. "MOV r3, r4\n\t"
  47459. "MOV r4, r5\n\t"
  47460. "MOV r5, #0x0\n\t"
  47461. "ADD r9, r9, #0x4\n\t"
  47462. "CMP r9, #0x30\n\t"
  47463. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  47464. "BLT L_sp_384_mul_d_12_word\n\t"
  47465. #else
  47466. "BLT.N L_sp_384_mul_d_12_word\n\t"
  47467. #endif
  47468. "STR r3, [%[r], #48]\n\t"
  47469. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  47470. :
  47471. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  47472. );
  47473. }
  47474. #else
  47475. /* Mul a by digit b into r. (r = a * b)
  47476. *
  47477. * r A single precision integer.
  47478. * a A single precision integer.
  47479. * b A single precision digit.
  47480. */
  47481. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47482. static void sp_384_mul_d_12(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  47483. #else
  47484. static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a, sp_digit b)
  47485. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47486. {
  47487. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47488. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  47489. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  47490. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  47491. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47492. __asm__ __volatile__ (
  47493. /* A[0] * B */
  47494. "LDM %[a]!, {r8}\n\t"
  47495. "UMULL r3, r4, %[b], r8\n\t"
  47496. "STM %[r]!, {r3}\n\t"
  47497. "MOV r5, #0x0\n\t"
  47498. /* A[1] * B */
  47499. "LDM %[a]!, {r8}\n\t"
  47500. "UMLAL r4, r5, %[b], r8\n\t"
  47501. "STM %[r]!, {r4}\n\t"
  47502. "MOV r3, #0x0\n\t"
  47503. /* A[2] * B */
  47504. "LDM %[a]!, {r8}\n\t"
  47505. "UMLAL r5, r3, %[b], r8\n\t"
  47506. "STM %[r]!, {r5}\n\t"
  47507. "MOV r4, #0x0\n\t"
  47508. /* A[3] * B */
  47509. "LDM %[a]!, {r8}\n\t"
  47510. "UMLAL r3, r4, %[b], r8\n\t"
  47511. "STM %[r]!, {r3}\n\t"
  47512. "MOV r5, #0x0\n\t"
  47513. /* A[4] * B */
  47514. "LDM %[a]!, {r8}\n\t"
  47515. "UMLAL r4, r5, %[b], r8\n\t"
  47516. "STM %[r]!, {r4}\n\t"
  47517. "MOV r3, #0x0\n\t"
  47518. /* A[5] * B */
  47519. "LDM %[a]!, {r8}\n\t"
  47520. "UMLAL r5, r3, %[b], r8\n\t"
  47521. "STM %[r]!, {r5}\n\t"
  47522. "MOV r4, #0x0\n\t"
  47523. /* A[6] * B */
  47524. "LDM %[a]!, {r8}\n\t"
  47525. "UMLAL r3, r4, %[b], r8\n\t"
  47526. "STM %[r]!, {r3}\n\t"
  47527. "MOV r5, #0x0\n\t"
  47528. /* A[7] * B */
  47529. "LDM %[a]!, {r8}\n\t"
  47530. "UMLAL r4, r5, %[b], r8\n\t"
  47531. "STM %[r]!, {r4}\n\t"
  47532. "MOV r3, #0x0\n\t"
  47533. /* A[8] * B */
  47534. "LDM %[a]!, {r8}\n\t"
  47535. "UMLAL r5, r3, %[b], r8\n\t"
  47536. "STM %[r]!, {r5}\n\t"
  47537. "MOV r4, #0x0\n\t"
  47538. /* A[9] * B */
  47539. "LDM %[a]!, {r8}\n\t"
  47540. "UMLAL r3, r4, %[b], r8\n\t"
  47541. "STM %[r]!, {r3}\n\t"
  47542. "MOV r5, #0x0\n\t"
  47543. /* A[10] * B */
  47544. "LDM %[a]!, {r8}\n\t"
  47545. "UMLAL r4, r5, %[b], r8\n\t"
  47546. "STM %[r]!, {r4}\n\t"
  47547. "MOV r3, #0x0\n\t"
  47548. /* A[11] * B */
  47549. "LDM %[a]!, {r8}\n\t"
  47550. "UMLAL r5, r3, %[b], r8\n\t"
  47551. "STM %[r]!, {r5}\n\t"
  47552. "STR r3, [%[r]]\n\t"
  47553. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  47554. :
  47555. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  47556. );
  47557. }
  47558. #endif /* WOLFSSL_SP_SMALL */
  47559. #ifdef WOLFSSL_SP_USE_UDIV
  47560. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  47561. *
  47562. * d1 The high order half of the number to divide.
  47563. * d0 The low order half of the number to divide.
  47564. * div The divisor.
  47565. * returns the result of the division.
  47566. *
  47567. * Note that this is an approximate div. It may give an answer 1 larger.
  47568. */
  47569. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47570. SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  47571. #else
  47572. SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1, sp_digit d0, sp_digit div)
  47573. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47574. {
  47575. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47576. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  47577. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  47578. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  47579. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47580. __asm__ __volatile__ (
  47581. "LSR r8, %[div], #16\n\t"
  47582. "ADD r5, r8, #0x1\n\t"
  47583. "UDIV r6, %[d1], r5\n\t"
  47584. "LSL r7, %[div], #16\n\t"
  47585. "LSL r6, r6, #16\n\t"
  47586. "UMULL r3, r4, %[div], r6\n\t"
  47587. "SUBS %[d0], %[d0], r3\n\t"
  47588. "SBC %[d1], %[d1], r4\n\t"
  47589. "SUBS r3, %[d1], r5\n\t"
  47590. "SBC r9, r9, r9\n\t"
  47591. "ADD r9, r9, #0x1\n\t"
  47592. "RSB r10, r9, #0x0\n\t"
  47593. "LSL r9, r9, #16\n\t"
  47594. "AND r7, r7, r10\n\t"
  47595. "AND r8, r8, r10\n\t"
  47596. "SUBS %[d0], %[d0], r7\n\t"
  47597. "ADD r6, r6, r9\n\t"
  47598. "SBC %[d1], %[d1], r8\n\t"
  47599. "LSL r4, %[d1], #16\n\t"
  47600. "LSR r3, %[d0], #16\n\t"
  47601. "ORR r3, r3, r4\n\t"
  47602. "UDIV r3, r3, r5\n\t"
  47603. "ADD r6, r6, r3\n\t"
  47604. "UMULL r3, r4, %[div], r3\n\t"
  47605. "SUBS %[d0], %[d0], r3\n\t"
  47606. "SBC %[d1], %[d1], r4\n\t"
  47607. "LSL r4, %[d1], #16\n\t"
  47608. "LSR r3, %[d0], #16\n\t"
  47609. "ORR r3, r3, r4\n\t"
  47610. "UDIV r3, r3, r5\n\t"
  47611. "ADD r6, r6, r3\n\t"
  47612. "MUL r3, %[div], r3\n\t"
  47613. "SUB %[d0], %[d0], r3\n\t"
  47614. "UDIV r3, %[d0], %[div]\n\t"
  47615. "ADD %[d1], r6, r3\n\t"
  47616. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  47617. :
  47618. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  47619. );
  47620. return (uint32_t)(size_t)d1;
  47621. }
  47622. #else
  47623. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  47624. *
  47625. * d1 The high order half of the number to divide.
  47626. * d0 The low order half of the number to divide.
  47627. * div The divisor.
  47628. * returns the result of the division.
  47629. *
  47630. * Note that this is an approximate div. It may give an answer 1 larger.
  47631. */
  47632. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47633. SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  47634. #else
  47635. SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1, sp_digit d0, sp_digit div)
  47636. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47637. {
  47638. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  47639. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  47640. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  47641. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  47642. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  47643. __asm__ __volatile__ (
  47644. "LSR r5, %[div], #1\n\t"
  47645. "ADD r5, r5, #0x1\n\t"
  47646. "MOV r6, %[d0]\n\t"
  47647. "MOV r7, %[d1]\n\t"
  47648. /* Do top 32 */
  47649. "SUBS r8, r5, r7\n\t"
  47650. "SBC r8, r8, r8\n\t"
  47651. "MOV r3, #0x0\n\t"
  47652. "SUB r3, r3, r8\n\t"
  47653. "AND r8, r8, r5\n\t"
  47654. "SUBS r7, r7, r8\n\t"
  47655. /* Next 30 bits */
  47656. "MOV r4, #0x1d\n\t"
  47657. "\n"
  47658. "L_div_384_word_12_bit:\n\t"
  47659. "LSLS r6, r6, #1\n\t"
  47660. "ADC r7, r7, r7\n\t"
  47661. "SUBS r8, r5, r7\n\t"
  47662. "SBC r8, r8, r8\n\t"
  47663. "ADD r3, r3, r3\n\t"
  47664. "SUB r3, r3, r8\n\t"
  47665. "AND r8, r8, r5\n\t"
  47666. "SUBS r7, r7, r8\n\t"
  47667. "SUBS r4, r4, #0x1\n\t"
  47668. "bpl L_div_384_word_12_bit\n\t"
  47669. "ADD r3, r3, r3\n\t"
  47670. "ADD r3, r3, #0x1\n\t"
  47671. "UMULL r6, r7, r3, %[div]\n\t"
  47672. "SUBS r9, %[d0], r6\n\t"
  47673. "SBC r10, %[d1], r7\n\t"
  47674. "ADD r3, r3, r10\n\t"
  47675. "UMULL r6, r7, r3, %[div]\n\t"
  47676. "SUBS r9, %[d0], r6\n\t"
  47677. "SBC r10, %[d1], r7\n\t"
  47678. "ADD r3, r3, r10\n\t"
  47679. "UMULL r6, r7, r3, %[div]\n\t"
  47680. "SUBS r9, %[d0], r6\n\t"
  47681. "SBC r10, %[d1], r7\n\t"
  47682. "ADD r3, r3, r10\n\t"
  47683. "SUBS r8, %[div], r9\n\t"
  47684. "SBC r8, r8, r8\n\t"
  47685. "SUB %[d1], r3, r8\n\t"
  47686. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  47687. :
  47688. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  47689. );
  47690. return (uint32_t)(size_t)d1;
  47691. }
  47692. #endif
  47693. /* AND m into each word of a and store in r.
  47694. *
  47695. * r A single precision integer.
  47696. * a A single precision integer.
  47697. * m Mask to AND against each digit.
  47698. */
  47699. static void sp_384_mask_12(sp_digit* r, const sp_digit* a, sp_digit m)
  47700. {
  47701. #ifdef WOLFSSL_SP_SMALL
  47702. int i;
  47703. for (i=0; i<12; i++) {
  47704. r[i] = a[i] & m;
  47705. }
  47706. #else
  47707. r[0] = a[0] & m;
  47708. r[1] = a[1] & m;
  47709. r[2] = a[2] & m;
  47710. r[3] = a[3] & m;
  47711. r[4] = a[4] & m;
  47712. r[5] = a[5] & m;
  47713. r[6] = a[6] & m;
  47714. r[7] = a[7] & m;
  47715. r[8] = a[8] & m;
  47716. r[9] = a[9] & m;
  47717. r[10] = a[10] & m;
  47718. r[11] = a[11] & m;
  47719. #endif
  47720. }
  47721. /* Divide d in a and put remainder into r (m*d + r = a)
  47722. * m is not calculated as it is not needed at this time.
  47723. *
  47724. * a Number to be divided.
  47725. * d Number to divide with.
  47726. * m Multiplier result.
  47727. * r Remainder from the division.
  47728. * returns MP_OKAY indicating success.
  47729. */
  47730. static WC_INLINE int sp_384_div_12(const sp_digit* a, const sp_digit* d,
  47731. sp_digit* m, sp_digit* r)
  47732. {
  47733. sp_digit t1[24], t2[13];
  47734. sp_digit div, r1;
  47735. int i;
  47736. (void)m;
  47737. div = d[11];
  47738. XMEMCPY(t1, a, sizeof(*t1) * 2 * 12);
  47739. r1 = sp_384_cmp_12(&t1[12], d) >= 0;
  47740. sp_384_cond_sub_12(&t1[12], &t1[12], d, (sp_digit)0 - r1);
  47741. for (i = 11; i >= 0; i--) {
  47742. volatile sp_digit mask = (sp_digit)0 - (t1[12 + i] == div);
  47743. sp_digit hi = t1[12 + i] + mask;
  47744. r1 = div_384_word_12(hi, t1[12 + i - 1], div);
  47745. r1 |= mask;
  47746. sp_384_mul_d_12(t2, d, r1);
  47747. t1[12 + i] += sp_384_sub_in_place_12(&t1[i], t2);
  47748. t1[12 + i] -= t2[12];
  47749. sp_384_mask_12(t2, d, t1[12 + i]);
  47750. t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2);
  47751. sp_384_mask_12(t2, d, t1[12 + i]);
  47752. t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2);
  47753. }
  47754. r1 = sp_384_cmp_12(t1, d) >= 0;
  47755. sp_384_cond_sub_12(r, t1, d, (sp_digit)0 - r1);
  47756. return MP_OKAY;
  47757. }
  47758. /* Reduce a modulo m into r. (r = a mod m)
  47759. *
  47760. * r A single precision number that is the reduced result.
  47761. * a A single precision number that is to be reduced.
  47762. * m A single precision number that is the modulus to reduce with.
  47763. * returns MP_OKAY indicating success.
  47764. */
  47765. static WC_INLINE int sp_384_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
  47766. {
  47767. return sp_384_div_12(a, m, NULL, r);
  47768. }
  47769. #endif
  47770. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  47771. /* Multiply two number mod the order of P384 curve. (r = a * b mod order)
  47772. *
  47773. * r Result of the multiplication.
  47774. * a First operand of the multiplication.
  47775. * b Second operand of the multiplication.
  47776. */
  47777. static void sp_384_mont_mul_order_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
  47778. {
  47779. sp_384_mul_12(r, a, b);
  47780. sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order);
  47781. }
  47782. #if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
  47783. #ifdef WOLFSSL_SP_SMALL
  47784. /* Order-2 for the P384 curve. */
  47785. static const uint32_t p384_order_minus_2[12] = {
  47786. 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U,
  47787. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU
  47788. };
  47789. #else
  47790. /* The low half of the order-2 of the P384 curve. */
  47791. static const uint32_t p384_order_low[6] = {
  47792. 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U
  47793. };
  47794. #endif /* WOLFSSL_SP_SMALL */
  47795. /* Square number mod the order of P384 curve. (r = a * a mod order)
  47796. *
  47797. * r Result of the squaring.
  47798. * a Number to square.
  47799. */
  47800. static void sp_384_mont_sqr_order_12(sp_digit* r, const sp_digit* a)
  47801. {
  47802. sp_384_sqr_12(r, a);
  47803. sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order);
  47804. }
  47805. #ifndef WOLFSSL_SP_SMALL
  47806. /* Square number mod the order of P384 curve a number of times.
  47807. * (r = a ^ n mod order)
  47808. *
  47809. * r Result of the squaring.
  47810. * a Number to square.
  47811. */
  47812. static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n)
  47813. {
  47814. int i;
  47815. sp_384_mont_sqr_order_12(r, a);
  47816. for (i=1; i<n; i++) {
  47817. sp_384_mont_sqr_order_12(r, r);
  47818. }
  47819. }
  47820. #endif /* !WOLFSSL_SP_SMALL */
  47821. /* Invert the number, in Montgomery form, modulo the order of the P384 curve.
  47822. * (r = 1 / a mod order)
  47823. *
  47824. * r Inverse result.
  47825. * a Number to invert.
  47826. * td Temporary data.
  47827. */
  47828. #ifdef WOLFSSL_SP_NONBLOCK
  47829. typedef struct sp_384_mont_inv_order_12_ctx {
  47830. int state;
  47831. int i;
  47832. } sp_384_mont_inv_order_12_ctx;
  47833. static int sp_384_mont_inv_order_12_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
  47834. sp_digit* t)
  47835. {
  47836. int err = FP_WOULDBLOCK;
  47837. sp_384_mont_inv_order_12_ctx* ctx = (sp_384_mont_inv_order_12_ctx*)sp_ctx;
  47838. typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  47839. (void)sizeof(ctx_size_test);
  47840. switch (ctx->state) {
  47841. case 0:
  47842. XMEMCPY(t, a, sizeof(sp_digit) * 12);
  47843. ctx->i = 382;
  47844. ctx->state = 1;
  47845. break;
  47846. case 1:
  47847. sp_384_mont_sqr_order_12(t, t);
  47848. ctx->state = 2;
  47849. break;
  47850. case 2:
  47851. if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
  47852. sp_384_mont_mul_order_12(t, t, a);
  47853. }
  47854. ctx->i--;
  47855. ctx->state = (ctx->i == 0) ? 3 : 1;
  47856. break;
  47857. case 3:
  47858. XMEMCPY(r, t, sizeof(sp_digit) * 12U);
  47859. err = MP_OKAY;
  47860. break;
  47861. }
  47862. return err;
  47863. }
  47864. #endif /* WOLFSSL_SP_NONBLOCK */
  47865. static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a,
  47866. sp_digit* td)
  47867. {
  47868. #ifdef WOLFSSL_SP_SMALL
  47869. sp_digit* t = td;
  47870. int i;
  47871. XMEMCPY(t, a, sizeof(sp_digit) * 12);
  47872. for (i=382; i>=0; i--) {
  47873. sp_384_mont_sqr_order_12(t, t);
  47874. if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  47875. sp_384_mont_mul_order_12(t, t, a);
  47876. }
  47877. }
  47878. XMEMCPY(r, t, sizeof(sp_digit) * 12U);
  47879. #else
  47880. sp_digit* t = td;
  47881. sp_digit* t2 = td + 2 * 12;
  47882. sp_digit* t3 = td + 4 * 12;
  47883. int i;
  47884. /* t = a^2 */
  47885. sp_384_mont_sqr_order_12(t, a);
  47886. /* t = a^3 = t * a */
  47887. sp_384_mont_mul_order_12(t, t, a);
  47888. /* t2= a^c = t ^ 2 ^ 2 */
  47889. sp_384_mont_sqr_n_order_12(t2, t, 2);
  47890. /* t = a^f = t2 * t */
  47891. sp_384_mont_mul_order_12(t, t2, t);
  47892. /* t2= a^f0 = t ^ 2 ^ 4 */
  47893. sp_384_mont_sqr_n_order_12(t2, t, 4);
  47894. /* t = a^ff = t2 * t */
  47895. sp_384_mont_mul_order_12(t, t2, t);
  47896. /* t2= a^ff00 = t ^ 2 ^ 8 */
  47897. sp_384_mont_sqr_n_order_12(t2, t, 8);
  47898. /* t3= a^ffff = t2 * t */
  47899. sp_384_mont_mul_order_12(t3, t2, t);
  47900. /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */
  47901. sp_384_mont_sqr_n_order_12(t2, t3, 16);
  47902. /* t = a^ffffffff = t2 * t3 */
  47903. sp_384_mont_mul_order_12(t, t2, t3);
  47904. /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */
  47905. sp_384_mont_sqr_n_order_12(t2, t, 16);
  47906. /* t = a^ffffffffffff = t2 * t3 */
  47907. sp_384_mont_mul_order_12(t, t2, t3);
  47908. /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */
  47909. sp_384_mont_sqr_n_order_12(t2, t, 48);
  47910. /* t= a^fffffffffffffffffffffffff = t2 * t */
  47911. sp_384_mont_mul_order_12(t, t2, t);
  47912. /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */
  47913. sp_384_mont_sqr_n_order_12(t2, t, 96);
  47914. /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */
  47915. sp_384_mont_mul_order_12(t2, t2, t);
  47916. for (i=191; i>=1; i--) {
  47917. sp_384_mont_sqr_order_12(t2, t2);
  47918. if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  47919. sp_384_mont_mul_order_12(t2, t2, a);
  47920. }
  47921. }
  47922. sp_384_mont_sqr_order_12(t2, t2);
  47923. sp_384_mont_mul_order_12(r, t2, a);
  47924. #endif /* WOLFSSL_SP_SMALL */
  47925. }
  47926. #endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
  47927. #endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  47928. #ifdef HAVE_ECC_SIGN
  47929. #ifndef SP_ECC_MAX_SIG_GEN
  47930. #define SP_ECC_MAX_SIG_GEN 64
  47931. #endif
  47932. /* Calculate second signature value S from R, k and private value.
  47933. *
  47934. * s = (r * x + e) / k
  47935. *
  47936. * s Signature value.
  47937. * r First signature value.
  47938. * k Ephemeral private key.
  47939. * x Private key as a number.
  47940. * e Hash of message as a number.
  47941. * tmp Temporary storage for intermediate numbers.
  47942. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  47943. */
  47944. static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k,
  47945. sp_digit* x, const sp_digit* e, sp_digit* tmp)
  47946. {
  47947. int err;
  47948. sp_digit carry;
  47949. sp_int32 c;
  47950. sp_digit* kInv = k;
  47951. /* Conv k to Montgomery form (mod order) */
  47952. sp_384_mul_12(k, k, p384_norm_order);
  47953. err = sp_384_mod_12(k, k, p384_order);
  47954. if (err == MP_OKAY) {
  47955. sp_384_norm_12(k);
  47956. /* kInv = 1/k mod order */
  47957. sp_384_mont_inv_order_12(kInv, k, tmp);
  47958. sp_384_norm_12(kInv);
  47959. /* s = r * x + e */
  47960. sp_384_mul_12(x, x, r);
  47961. err = sp_384_mod_12(x, x, p384_order);
  47962. }
  47963. if (err == MP_OKAY) {
  47964. sp_384_norm_12(x);
  47965. carry = sp_384_add_12(s, e, x);
  47966. sp_384_cond_sub_12(s, s, p384_order, 0 - carry);
  47967. sp_384_norm_12(s);
  47968. c = sp_384_cmp_12(s, p384_order);
  47969. sp_384_cond_sub_12(s, s, p384_order,
  47970. (sp_digit)0 - (sp_digit)(c >= 0));
  47971. sp_384_norm_12(s);
  47972. /* s = s * k^-1 mod order */
  47973. sp_384_mont_mul_order_12(s, s, kInv);
  47974. sp_384_norm_12(s);
  47975. }
  47976. return err;
  47977. }
  47978. /* Sign the hash using the private key.
  47979. * e = [hash, 384 bits] from binary
  47980. * r = (k.G)->x mod order
  47981. * s = (r * x + e) / k mod order
  47982. * The hash is truncated to the first 384 bits.
  47983. *
  47984. * hash Hash to sign.
  47985. * hashLen Length of the hash data.
  47986. * rng Random number generator.
  47987. * priv Private part of key - scalar.
  47988. * rm First part of result as an mp_int.
  47989. * sm Sirst part of result as an mp_int.
  47990. * heap Heap to use for allocation.
  47991. * returns RNG failures, MEMORY_E when memory allocation fails and
  47992. * MP_OKAY on success.
  47993. */
  47994. int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng,
  47995. const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  47996. {
  47997. #ifdef WOLFSSL_SP_SMALL_STACK
  47998. sp_digit* e = NULL;
  47999. sp_point_384* point = NULL;
  48000. #else
  48001. sp_digit e[7 * 2 * 12];
  48002. sp_point_384 point[1];
  48003. #endif
  48004. sp_digit* x = NULL;
  48005. sp_digit* k = NULL;
  48006. sp_digit* r = NULL;
  48007. sp_digit* tmp = NULL;
  48008. sp_digit* s = NULL;
  48009. sp_int32 c;
  48010. int err = MP_OKAY;
  48011. int i;
  48012. (void)heap;
  48013. #ifdef WOLFSSL_SP_SMALL_STACK
  48014. if (err == MP_OKAY) {
  48015. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  48016. DYNAMIC_TYPE_ECC);
  48017. if (point == NULL)
  48018. err = MEMORY_E;
  48019. }
  48020. if (err == MP_OKAY) {
  48021. e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap,
  48022. DYNAMIC_TYPE_ECC);
  48023. if (e == NULL)
  48024. err = MEMORY_E;
  48025. }
  48026. #endif
  48027. if (err == MP_OKAY) {
  48028. x = e + 2 * 12;
  48029. k = e + 4 * 12;
  48030. r = e + 6 * 12;
  48031. tmp = e + 8 * 12;
  48032. s = e;
  48033. if (hashLen > 48U) {
  48034. hashLen = 48U;
  48035. }
  48036. }
  48037. for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
  48038. /* New random point. */
  48039. if (km == NULL || mp_iszero(km)) {
  48040. err = sp_384_ecc_gen_k_12(rng, k);
  48041. }
  48042. else {
  48043. sp_384_from_mp(k, 12, km);
  48044. mp_zero(km);
  48045. }
  48046. if (err == MP_OKAY) {
  48047. err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap);
  48048. }
  48049. if (err == MP_OKAY) {
  48050. /* r = point->x mod order */
  48051. XMEMCPY(r, point->x, sizeof(sp_digit) * 12U);
  48052. sp_384_norm_12(r);
  48053. c = sp_384_cmp_12(r, p384_order);
  48054. sp_384_cond_sub_12(r, r, p384_order,
  48055. (sp_digit)0 - (sp_digit)(c >= 0));
  48056. sp_384_norm_12(r);
  48057. if (!sp_384_iszero_12(r)) {
  48058. /* x is modified in calculation of s. */
  48059. sp_384_from_mp(x, 12, priv);
  48060. /* s ptr == e ptr, e is modified in calculation of s. */
  48061. sp_384_from_bin(e, 12, hash, (int)hashLen);
  48062. err = sp_384_calc_s_12(s, r, k, x, e, tmp);
  48063. /* Check that signature is usable. */
  48064. if ((err == MP_OKAY) && (!sp_384_iszero_12(s))) {
  48065. break;
  48066. }
  48067. }
  48068. }
  48069. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  48070. i = 1;
  48071. #endif
  48072. }
  48073. if (i == 0) {
  48074. err = RNG_FAILURE_E;
  48075. }
  48076. if (err == MP_OKAY) {
  48077. err = sp_384_to_mp(r, rm);
  48078. }
  48079. if (err == MP_OKAY) {
  48080. err = sp_384_to_mp(s, sm);
  48081. }
  48082. #ifdef WOLFSSL_SP_SMALL_STACK
  48083. if (e != NULL)
  48084. #endif
  48085. {
  48086. ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12);
  48087. #ifdef WOLFSSL_SP_SMALL_STACK
  48088. XFREE(e, heap, DYNAMIC_TYPE_ECC);
  48089. #endif
  48090. }
  48091. #ifdef WOLFSSL_SP_SMALL_STACK
  48092. if (point != NULL)
  48093. #endif
  48094. {
  48095. ForceZero(point, sizeof(sp_point_384));
  48096. #ifdef WOLFSSL_SP_SMALL_STACK
  48097. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  48098. #endif
  48099. }
  48100. return err;
  48101. }
  48102. #ifdef WOLFSSL_SP_NONBLOCK
  48103. typedef struct sp_ecc_sign_384_ctx {
  48104. int state;
  48105. union {
  48106. sp_384_ecc_mulmod_12_ctx mulmod_ctx;
  48107. sp_384_mont_inv_order_12_ctx mont_inv_order_ctx;
  48108. };
  48109. sp_digit e[2*12];
  48110. sp_digit x[2*12];
  48111. sp_digit k[2*12];
  48112. sp_digit r[2*12];
  48113. sp_digit tmp[3 * 2*12];
  48114. sp_point_384 point;
  48115. sp_digit* s;
  48116. sp_digit* kInv;
  48117. int i;
  48118. } sp_ecc_sign_384_ctx;
  48119. int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
  48120. mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  48121. {
  48122. int err = FP_WOULDBLOCK;
  48123. sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data;
  48124. typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  48125. (void)sizeof(ctx_size_test);
  48126. switch (ctx->state) {
  48127. case 0: /* INIT */
  48128. ctx->s = ctx->e;
  48129. ctx->kInv = ctx->k;
  48130. ctx->i = SP_ECC_MAX_SIG_GEN;
  48131. ctx->state = 1;
  48132. break;
  48133. case 1: /* GEN */
  48134. /* New random point. */
  48135. if (km == NULL || mp_iszero(km)) {
  48136. err = sp_384_ecc_gen_k_12(rng, ctx->k);
  48137. }
  48138. else {
  48139. sp_384_from_mp(ctx->k, 12, km);
  48140. mp_zero(km);
  48141. }
  48142. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  48143. ctx->state = 2;
  48144. break;
  48145. case 2: /* MULMOD */
  48146. err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  48147. &ctx->point, &p384_base, ctx->k, 1, 1, heap);
  48148. if (err == MP_OKAY) {
  48149. ctx->state = 3;
  48150. }
  48151. break;
  48152. case 3: /* MODORDER */
  48153. {
  48154. sp_int32 c;
  48155. /* r = point->x mod order */
  48156. XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 12U);
  48157. sp_384_norm_12(ctx->r);
  48158. c = sp_384_cmp_12(ctx->r, p384_order);
  48159. sp_384_cond_sub_12(ctx->r, ctx->r, p384_order,
  48160. (sp_digit)0 - (sp_digit)(c >= 0));
  48161. sp_384_norm_12(ctx->r);
  48162. if (hashLen > 48U) {
  48163. hashLen = 48U;
  48164. }
  48165. sp_384_from_mp(ctx->x, 12, priv);
  48166. sp_384_from_bin(ctx->e, 12, hash, (int)hashLen);
  48167. ctx->state = 4;
  48168. break;
  48169. }
  48170. case 4: /* KMODORDER */
  48171. /* Conv k to Montgomery form (mod order) */
  48172. sp_384_mul_12(ctx->k, ctx->k, p384_norm_order);
  48173. err = sp_384_mod_12(ctx->k, ctx->k, p384_order);
  48174. if (err == MP_OKAY) {
  48175. sp_384_norm_12(ctx->k);
  48176. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  48177. ctx->state = 5;
  48178. }
  48179. break;
  48180. case 5: /* KINV */
  48181. /* kInv = 1/k mod order */
  48182. err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
  48183. if (err == MP_OKAY) {
  48184. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  48185. ctx->state = 6;
  48186. }
  48187. break;
  48188. case 6: /* KINVNORM */
  48189. sp_384_norm_12(ctx->kInv);
  48190. ctx->state = 7;
  48191. break;
  48192. case 7: /* R */
  48193. /* s = r * x + e */
  48194. sp_384_mul_12(ctx->x, ctx->x, ctx->r);
  48195. ctx->state = 8;
  48196. break;
  48197. case 8: /* S1 */
  48198. err = sp_384_mod_12(ctx->x, ctx->x, p384_order);
  48199. if (err == MP_OKAY)
  48200. ctx->state = 9;
  48201. break;
  48202. case 9: /* S2 */
  48203. {
  48204. sp_digit carry;
  48205. sp_int32 c;
  48206. sp_384_norm_12(ctx->x);
  48207. carry = sp_384_add_12(ctx->s, ctx->e, ctx->x);
  48208. sp_384_cond_sub_12(ctx->s, ctx->s,
  48209. p384_order, 0 - carry);
  48210. sp_384_norm_12(ctx->s);
  48211. c = sp_384_cmp_12(ctx->s, p384_order);
  48212. sp_384_cond_sub_12(ctx->s, ctx->s, p384_order,
  48213. (sp_digit)0 - (sp_digit)(c >= 0));
  48214. sp_384_norm_12(ctx->s);
  48215. /* s = s * k^-1 mod order */
  48216. sp_384_mont_mul_order_12(ctx->s, ctx->s, ctx->kInv);
  48217. sp_384_norm_12(ctx->s);
  48218. /* Check that signature is usable. */
  48219. if (sp_384_iszero_12(ctx->s) == 0) {
  48220. ctx->state = 10;
  48221. break;
  48222. }
  48223. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  48224. ctx->i = 1;
  48225. #endif
  48226. /* not usable gen, try again */
  48227. ctx->i--;
  48228. if (ctx->i == 0) {
  48229. err = RNG_FAILURE_E;
  48230. }
  48231. ctx->state = 1;
  48232. break;
  48233. }
  48234. case 10: /* RES */
  48235. err = sp_384_to_mp(ctx->r, rm);
  48236. if (err == MP_OKAY) {
  48237. err = sp_384_to_mp(ctx->s, sm);
  48238. }
  48239. break;
  48240. }
  48241. if (err == MP_OKAY && ctx->state != 10) {
  48242. err = FP_WOULDBLOCK;
  48243. }
  48244. if (err != FP_WOULDBLOCK) {
  48245. XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 12U);
  48246. XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 12U);
  48247. XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 12U);
  48248. XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 12U);
  48249. XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U);
  48250. }
  48251. return err;
  48252. }
  48253. #endif /* WOLFSSL_SP_NONBLOCK */
  48254. #endif /* HAVE_ECC_SIGN */
  48255. #ifndef WOLFSSL_SP_SMALL
  48256. /* Divide the number by 2 mod the modulus. (r = a / 2 % m)
  48257. *
  48258. * r Result of division by 2.
  48259. * a Number to divide.
  48260. * m Modulus.
  48261. */
  48262. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  48263. static void sp_384_div2_mod_12(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  48264. #else
  48265. static void sp_384_div2_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
  48266. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  48267. {
  48268. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  48269. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  48270. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  48271. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  48272. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  48273. __asm__ __volatile__ (
  48274. "LDM %[a]!, {r4}\n\t"
  48275. "ANDS r3, r4, #0x1\n\t"
  48276. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48277. "BEQ L_sp_384_div2_mod_12_even\n\t"
  48278. #else
  48279. "BEQ.N L_sp_384_div2_mod_12_even\n\t"
  48280. #endif
  48281. "MOV r12, #0x0\n\t"
  48282. "LDM %[a]!, {r5, r6, r7}\n\t"
  48283. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  48284. "ADDS r4, r4, r8\n\t"
  48285. "ADCS r5, r5, r9\n\t"
  48286. "ADCS r6, r6, r10\n\t"
  48287. "ADCS r7, r7, r11\n\t"
  48288. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  48289. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  48290. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  48291. "ADCS r4, r4, r8\n\t"
  48292. "ADCS r5, r5, r9\n\t"
  48293. "ADCS r6, r6, r10\n\t"
  48294. "ADCS r7, r7, r11\n\t"
  48295. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  48296. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  48297. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  48298. "ADCS r4, r4, r8\n\t"
  48299. "ADCS r5, r5, r9\n\t"
  48300. "ADCS r6, r6, r10\n\t"
  48301. "ADCS r7, r7, r11\n\t"
  48302. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  48303. "ADC r3, r12, r12\n\t"
  48304. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48305. "B L_sp_384_div2_mod_12_div2\n\t"
  48306. #else
  48307. "B.N L_sp_384_div2_mod_12_div2\n\t"
  48308. #endif
  48309. "\n"
  48310. "L_sp_384_div2_mod_12_even:\n\t"
  48311. "LDM %[a]!, {r5, r6, r7}\n\t"
  48312. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  48313. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  48314. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  48315. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  48316. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  48317. "\n"
  48318. "L_sp_384_div2_mod_12_div2:\n\t"
  48319. "SUB %[r], %[r], #0x30\n\t"
  48320. "LDRD r8, r9, [%[r]]\n\t"
  48321. "LSR r8, r8, #1\n\t"
  48322. "ORR r8, r8, r9, lsl #31\n\t"
  48323. "LSR r9, r9, #1\n\t"
  48324. "LDR r10, [%[r], #8]\n\t"
  48325. "STR r8, [%[r]]\n\t"
  48326. "ORR r9, r9, r10, lsl #31\n\t"
  48327. "LSR r10, r10, #1\n\t"
  48328. "LDR r8, [%[r], #12]\n\t"
  48329. "STR r9, [%[r], #4]\n\t"
  48330. "ORR r10, r10, r8, lsl #31\n\t"
  48331. "LSR r8, r8, #1\n\t"
  48332. "LDR r9, [%[r], #16]\n\t"
  48333. "STR r10, [%[r], #8]\n\t"
  48334. "ORR r8, r8, r9, lsl #31\n\t"
  48335. "LSR r9, r9, #1\n\t"
  48336. "LDR r10, [%[r], #20]\n\t"
  48337. "STR r8, [%[r], #12]\n\t"
  48338. "ORR r9, r9, r10, lsl #31\n\t"
  48339. "LSR r10, r10, #1\n\t"
  48340. "LDR r8, [%[r], #24]\n\t"
  48341. "STR r9, [%[r], #16]\n\t"
  48342. "ORR r10, r10, r8, lsl #31\n\t"
  48343. "LSR r8, r8, #1\n\t"
  48344. "LDR r9, [%[r], #28]\n\t"
  48345. "STR r10, [%[r], #20]\n\t"
  48346. "ORR r8, r8, r9, lsl #31\n\t"
  48347. "LSR r9, r9, #1\n\t"
  48348. "LDR r10, [%[r], #32]\n\t"
  48349. "STR r8, [%[r], #24]\n\t"
  48350. "ORR r9, r9, r10, lsl #31\n\t"
  48351. "LSR r10, r10, #1\n\t"
  48352. "LDR r8, [%[r], #36]\n\t"
  48353. "STR r9, [%[r], #28]\n\t"
  48354. "ORR r10, r10, r8, lsl #31\n\t"
  48355. "LSR r8, r8, #1\n\t"
  48356. "LDR r9, [%[r], #40]\n\t"
  48357. "STR r10, [%[r], #32]\n\t"
  48358. "ORR r8, r8, r9, lsl #31\n\t"
  48359. "LSR r9, r9, #1\n\t"
  48360. "LDR r10, [%[r], #44]\n\t"
  48361. "STR r8, [%[r], #36]\n\t"
  48362. "ORR r9, r9, r10, lsl #31\n\t"
  48363. "LSR r10, r10, #1\n\t"
  48364. "ORR r10, r10, r3, lsl #31\n\t"
  48365. "STR r9, [%[r], #40]\n\t"
  48366. "STR r10, [%[r], #44]\n\t"
  48367. : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
  48368. :
  48369. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  48370. );
  48371. }
  48372. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  48373. static int sp_384_num_bits_12(const sp_digit* a_p)
  48374. #else
  48375. static int sp_384_num_bits_12(const sp_digit* a)
  48376. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  48377. {
  48378. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  48379. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  48380. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  48381. __asm__ __volatile__ (
  48382. "LDR r1, [%[a], #44]\n\t"
  48383. "CMP r1, #0x0\n\t"
  48384. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48385. "BEQ L_sp_384_num_bits_12_11\n\t"
  48386. #else
  48387. "BEQ.N L_sp_384_num_bits_12_11\n\t"
  48388. #endif
  48389. "MOV r2, #0x180\n\t"
  48390. "CLZ r4, r1\n\t"
  48391. "SUB r4, r2, r4\n\t"
  48392. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48393. "B L_sp_384_num_bits_12_13\n\t"
  48394. #else
  48395. "B.N L_sp_384_num_bits_12_13\n\t"
  48396. #endif
  48397. "\n"
  48398. "L_sp_384_num_bits_12_11:\n\t"
  48399. "LDR r1, [%[a], #40]\n\t"
  48400. "CMP r1, #0x0\n\t"
  48401. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48402. "BEQ L_sp_384_num_bits_12_10\n\t"
  48403. #else
  48404. "BEQ.N L_sp_384_num_bits_12_10\n\t"
  48405. #endif
  48406. "MOV r2, #0x160\n\t"
  48407. "CLZ r4, r1\n\t"
  48408. "SUB r4, r2, r4\n\t"
  48409. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48410. "B L_sp_384_num_bits_12_13\n\t"
  48411. #else
  48412. "B.N L_sp_384_num_bits_12_13\n\t"
  48413. #endif
  48414. "\n"
  48415. "L_sp_384_num_bits_12_10:\n\t"
  48416. "LDR r1, [%[a], #36]\n\t"
  48417. "CMP r1, #0x0\n\t"
  48418. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48419. "BEQ L_sp_384_num_bits_12_9\n\t"
  48420. #else
  48421. "BEQ.N L_sp_384_num_bits_12_9\n\t"
  48422. #endif
  48423. "MOV r2, #0x140\n\t"
  48424. "CLZ r4, r1\n\t"
  48425. "SUB r4, r2, r4\n\t"
  48426. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48427. "B L_sp_384_num_bits_12_13\n\t"
  48428. #else
  48429. "B.N L_sp_384_num_bits_12_13\n\t"
  48430. #endif
  48431. "\n"
  48432. "L_sp_384_num_bits_12_9:\n\t"
  48433. "LDR r1, [%[a], #32]\n\t"
  48434. "CMP r1, #0x0\n\t"
  48435. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48436. "BEQ L_sp_384_num_bits_12_8\n\t"
  48437. #else
  48438. "BEQ.N L_sp_384_num_bits_12_8\n\t"
  48439. #endif
  48440. "MOV r2, #0x120\n\t"
  48441. "CLZ r4, r1\n\t"
  48442. "SUB r4, r2, r4\n\t"
  48443. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48444. "B L_sp_384_num_bits_12_13\n\t"
  48445. #else
  48446. "B.N L_sp_384_num_bits_12_13\n\t"
  48447. #endif
  48448. "\n"
  48449. "L_sp_384_num_bits_12_8:\n\t"
  48450. "LDR r1, [%[a], #28]\n\t"
  48451. "CMP r1, #0x0\n\t"
  48452. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48453. "BEQ L_sp_384_num_bits_12_7\n\t"
  48454. #else
  48455. "BEQ.N L_sp_384_num_bits_12_7\n\t"
  48456. #endif
  48457. "MOV r2, #0x100\n\t"
  48458. "CLZ r4, r1\n\t"
  48459. "SUB r4, r2, r4\n\t"
  48460. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48461. "B L_sp_384_num_bits_12_13\n\t"
  48462. #else
  48463. "B.N L_sp_384_num_bits_12_13\n\t"
  48464. #endif
  48465. "\n"
  48466. "L_sp_384_num_bits_12_7:\n\t"
  48467. "LDR r1, [%[a], #24]\n\t"
  48468. "CMP r1, #0x0\n\t"
  48469. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48470. "BEQ L_sp_384_num_bits_12_6\n\t"
  48471. #else
  48472. "BEQ.N L_sp_384_num_bits_12_6\n\t"
  48473. #endif
  48474. "MOV r2, #0xe0\n\t"
  48475. "CLZ r4, r1\n\t"
  48476. "SUB r4, r2, r4\n\t"
  48477. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48478. "B L_sp_384_num_bits_12_13\n\t"
  48479. #else
  48480. "B.N L_sp_384_num_bits_12_13\n\t"
  48481. #endif
  48482. "\n"
  48483. "L_sp_384_num_bits_12_6:\n\t"
  48484. "LDR r1, [%[a], #20]\n\t"
  48485. "CMP r1, #0x0\n\t"
  48486. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48487. "BEQ L_sp_384_num_bits_12_5\n\t"
  48488. #else
  48489. "BEQ.N L_sp_384_num_bits_12_5\n\t"
  48490. #endif
  48491. "MOV r2, #0xc0\n\t"
  48492. "CLZ r4, r1\n\t"
  48493. "SUB r4, r2, r4\n\t"
  48494. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48495. "B L_sp_384_num_bits_12_13\n\t"
  48496. #else
  48497. "B.N L_sp_384_num_bits_12_13\n\t"
  48498. #endif
  48499. "\n"
  48500. "L_sp_384_num_bits_12_5:\n\t"
  48501. "LDR r1, [%[a], #16]\n\t"
  48502. "CMP r1, #0x0\n\t"
  48503. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48504. "BEQ L_sp_384_num_bits_12_4\n\t"
  48505. #else
  48506. "BEQ.N L_sp_384_num_bits_12_4\n\t"
  48507. #endif
  48508. "MOV r2, #0xa0\n\t"
  48509. "CLZ r4, r1\n\t"
  48510. "SUB r4, r2, r4\n\t"
  48511. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48512. "B L_sp_384_num_bits_12_13\n\t"
  48513. #else
  48514. "B.N L_sp_384_num_bits_12_13\n\t"
  48515. #endif
  48516. "\n"
  48517. "L_sp_384_num_bits_12_4:\n\t"
  48518. "LDR r1, [%[a], #12]\n\t"
  48519. "CMP r1, #0x0\n\t"
  48520. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48521. "BEQ L_sp_384_num_bits_12_3\n\t"
  48522. #else
  48523. "BEQ.N L_sp_384_num_bits_12_3\n\t"
  48524. #endif
  48525. "MOV r2, #0x80\n\t"
  48526. "CLZ r4, r1\n\t"
  48527. "SUB r4, r2, r4\n\t"
  48528. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48529. "B L_sp_384_num_bits_12_13\n\t"
  48530. #else
  48531. "B.N L_sp_384_num_bits_12_13\n\t"
  48532. #endif
  48533. "\n"
  48534. "L_sp_384_num_bits_12_3:\n\t"
  48535. "LDR r1, [%[a], #8]\n\t"
  48536. "CMP r1, #0x0\n\t"
  48537. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48538. "BEQ L_sp_384_num_bits_12_2\n\t"
  48539. #else
  48540. "BEQ.N L_sp_384_num_bits_12_2\n\t"
  48541. #endif
  48542. "MOV r2, #0x60\n\t"
  48543. "CLZ r4, r1\n\t"
  48544. "SUB r4, r2, r4\n\t"
  48545. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48546. "B L_sp_384_num_bits_12_13\n\t"
  48547. #else
  48548. "B.N L_sp_384_num_bits_12_13\n\t"
  48549. #endif
  48550. "\n"
  48551. "L_sp_384_num_bits_12_2:\n\t"
  48552. "LDR r1, [%[a], #4]\n\t"
  48553. "CMP r1, #0x0\n\t"
  48554. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48555. "BEQ L_sp_384_num_bits_12_1\n\t"
  48556. #else
  48557. "BEQ.N L_sp_384_num_bits_12_1\n\t"
  48558. #endif
  48559. "MOV r2, #0x40\n\t"
  48560. "CLZ r4, r1\n\t"
  48561. "SUB r4, r2, r4\n\t"
  48562. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  48563. "B L_sp_384_num_bits_12_13\n\t"
  48564. #else
  48565. "B.N L_sp_384_num_bits_12_13\n\t"
  48566. #endif
  48567. "\n"
  48568. "L_sp_384_num_bits_12_1:\n\t"
  48569. "LDR r1, [%[a]]\n\t"
  48570. "MOV r2, #0x20\n\t"
  48571. "CLZ r4, r1\n\t"
  48572. "SUB r4, r2, r4\n\t"
  48573. "\n"
  48574. "L_sp_384_num_bits_12_13:\n\t"
  48575. "MOV %[a], r4\n\t"
  48576. : [a] "+r" (a)
  48577. :
  48578. : "memory", "r1", "r2", "r3", "r4", "r5", "cc"
  48579. );
  48580. return (uint32_t)(size_t)a;
  48581. }
  48582. /* Non-constant time modular inversion.
  48583. *
  48584. * @param [out] r Resulting number.
  48585. * @param [in] a Number to invert.
  48586. * @param [in] m Modulus.
  48587. * @return MP_OKAY on success.
  48588. */
  48589. static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m)
  48590. {
  48591. sp_digit u[12];
  48592. sp_digit v[12];
  48593. sp_digit b[12];
  48594. sp_digit d[12];
  48595. int ut, vt;
  48596. sp_digit o;
  48597. XMEMCPY(u, m, sizeof(u));
  48598. XMEMCPY(v, a, sizeof(v));
  48599. ut = sp_384_num_bits_12(u);
  48600. vt = sp_384_num_bits_12(v);
  48601. XMEMSET(b, 0, sizeof(b));
  48602. if ((v[0] & 1) == 0) {
  48603. sp_384_rshift1_12(v, v);
  48604. XMEMCPY(d, m, sizeof(u));
  48605. d[0] += 1;
  48606. sp_384_rshift1_12(d, d);
  48607. vt--;
  48608. while ((v[0] & 1) == 0) {
  48609. sp_384_rshift1_12(v, v);
  48610. sp_384_div2_mod_12(d, d, m);
  48611. vt--;
  48612. }
  48613. }
  48614. else {
  48615. XMEMSET(d+1, 0, sizeof(d)-sizeof(sp_digit));
  48616. d[0] = 1;
  48617. }
  48618. while (ut > 1 && vt > 1) {
  48619. if ((ut > vt) || ((ut == vt) && (sp_384_cmp_12(u, v) >= 0))) {
  48620. sp_384_sub_12(u, u, v);
  48621. o = sp_384_sub_12(b, b, d);
  48622. if (o != 0)
  48623. sp_384_add_12(b, b, m);
  48624. ut = sp_384_num_bits_12(u);
  48625. do {
  48626. sp_384_rshift1_12(u, u);
  48627. sp_384_div2_mod_12(b, b, m);
  48628. ut--;
  48629. }
  48630. while (ut > 0 && (u[0] & 1) == 0);
  48631. }
  48632. else {
  48633. sp_384_sub_12(v, v, u);
  48634. o = sp_384_sub_12(d, d, b);
  48635. if (o != 0)
  48636. sp_384_add_12(d, d, m);
  48637. vt = sp_384_num_bits_12(v);
  48638. do {
  48639. sp_384_rshift1_12(v, v);
  48640. sp_384_div2_mod_12(d, d, m);
  48641. vt--;
  48642. }
  48643. while (vt > 0 && (v[0] & 1) == 0);
  48644. }
  48645. }
  48646. if (ut == 1)
  48647. XMEMCPY(r, b, sizeof(b));
  48648. else
  48649. XMEMCPY(r, d, sizeof(d));
  48650. return MP_OKAY;
  48651. }
  48652. #endif /* WOLFSSL_SP_SMALL */
  48653. /* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
  48654. *
  48655. * p1 First point to add and holds result.
  48656. * p2 Second point to add.
  48657. * tmp Temporary storage for intermediate numbers.
  48658. */
  48659. static void sp_384_add_points_12(sp_point_384* p1, const sp_point_384* p2,
  48660. sp_digit* tmp)
  48661. {
  48662. sp_384_proj_point_add_12(p1, p1, p2, tmp);
  48663. if (sp_384_iszero_12(p1->z)) {
  48664. if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) {
  48665. sp_384_proj_point_dbl_12(p1, p2, tmp);
  48666. }
  48667. else {
  48668. /* Y ordinate is not used from here - don't set. */
  48669. p1->x[0] = 0;
  48670. p1->x[1] = 0;
  48671. p1->x[2] = 0;
  48672. p1->x[3] = 0;
  48673. p1->x[4] = 0;
  48674. p1->x[5] = 0;
  48675. p1->x[6] = 0;
  48676. p1->x[7] = 0;
  48677. p1->x[8] = 0;
  48678. p1->x[9] = 0;
  48679. p1->x[10] = 0;
  48680. p1->x[11] = 0;
  48681. XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
  48682. }
  48683. }
  48684. }
  48685. /* Calculate the verification point: [e/s]G + [r/s]Q
  48686. *
  48687. * p1 Calculated point.
  48688. * p2 Public point and temporary.
  48689. * s Second part of signature as a number.
  48690. * u1 Temporary number.
  48691. * u2 Temporary number.
  48692. * heap Heap to use for allocation.
  48693. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  48694. */
  48695. static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2,
  48696. sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
  48697. {
  48698. int err;
  48699. #ifndef WOLFSSL_SP_SMALL
  48700. err = sp_384_mod_inv_12(s, s, p384_order);
  48701. if (err == MP_OKAY)
  48702. #endif /* !WOLFSSL_SP_SMALL */
  48703. {
  48704. sp_384_mul_12(s, s, p384_norm_order);
  48705. err = sp_384_mod_12(s, s, p384_order);
  48706. }
  48707. if (err == MP_OKAY) {
  48708. sp_384_norm_12(s);
  48709. #ifdef WOLFSSL_SP_SMALL
  48710. {
  48711. sp_384_mont_inv_order_12(s, s, tmp);
  48712. sp_384_mont_mul_order_12(u1, u1, s);
  48713. sp_384_mont_mul_order_12(u2, u2, s);
  48714. }
  48715. #else
  48716. {
  48717. sp_384_mont_mul_order_12(u1, u1, s);
  48718. sp_384_mont_mul_order_12(u2, u2, s);
  48719. }
  48720. #endif /* WOLFSSL_SP_SMALL */
  48721. {
  48722. err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap);
  48723. }
  48724. }
  48725. if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) {
  48726. p1->infinity = 1;
  48727. }
  48728. if (err == MP_OKAY) {
  48729. err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap);
  48730. }
  48731. if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) {
  48732. p2->infinity = 1;
  48733. }
  48734. if (err == MP_OKAY) {
  48735. sp_384_add_points_12(p1, p2, tmp);
  48736. }
  48737. return err;
  48738. }
  48739. #ifdef HAVE_ECC_VERIFY
  48740. /* Verify the signature values with the hash and public key.
  48741. * e = Truncate(hash, 384)
  48742. * u1 = e/s mod order
  48743. * u2 = r/s mod order
  48744. * r == (u1.G + u2.Q)->x mod order
  48745. * Optimization: Leave point in projective form.
  48746. * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
  48747. * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
  48748. * The hash is truncated to the first 384 bits.
  48749. *
  48750. * hash Hash to sign.
  48751. * hashLen Length of the hash data.
  48752. * rng Random number generator.
  48753. * priv Private part of key - scalar.
  48754. * rm First part of result as an mp_int.
  48755. * sm Sirst part of result as an mp_int.
  48756. * heap Heap to use for allocation.
  48757. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  48758. */
  48759. int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX,
  48760. const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
  48761. int* res, void* heap)
  48762. {
  48763. #ifdef WOLFSSL_SP_SMALL_STACK
  48764. sp_digit* u1 = NULL;
  48765. sp_point_384* p1 = NULL;
  48766. #else
  48767. sp_digit u1[18 * 12];
  48768. sp_point_384 p1[2];
  48769. #endif
  48770. sp_digit* u2 = NULL;
  48771. sp_digit* s = NULL;
  48772. sp_digit* tmp = NULL;
  48773. sp_point_384* p2 = NULL;
  48774. sp_digit carry;
  48775. sp_int32 c = 0;
  48776. int err = MP_OKAY;
  48777. #ifdef WOLFSSL_SP_SMALL_STACK
  48778. if (err == MP_OKAY) {
  48779. p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  48780. DYNAMIC_TYPE_ECC);
  48781. if (p1 == NULL)
  48782. err = MEMORY_E;
  48783. }
  48784. if (err == MP_OKAY) {
  48785. u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 12, heap,
  48786. DYNAMIC_TYPE_ECC);
  48787. if (u1 == NULL)
  48788. err = MEMORY_E;
  48789. }
  48790. #endif
  48791. if (err == MP_OKAY) {
  48792. u2 = u1 + 2 * 12;
  48793. s = u1 + 4 * 12;
  48794. tmp = u1 + 6 * 12;
  48795. p2 = p1 + 1;
  48796. if (hashLen > 48U) {
  48797. hashLen = 48U;
  48798. }
  48799. sp_384_from_bin(u1, 12, hash, (int)hashLen);
  48800. sp_384_from_mp(u2, 12, rm);
  48801. sp_384_from_mp(s, 12, sm);
  48802. sp_384_from_mp(p2->x, 12, pX);
  48803. sp_384_from_mp(p2->y, 12, pY);
  48804. sp_384_from_mp(p2->z, 12, pZ);
  48805. err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap);
  48806. }
  48807. if (err == MP_OKAY) {
  48808. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  48809. /* Reload r and convert to Montgomery form. */
  48810. sp_384_from_mp(u2, 12, rm);
  48811. err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
  48812. }
  48813. if (err == MP_OKAY) {
  48814. /* u1 = r.z'.z' mod prime */
  48815. sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod);
  48816. sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod);
  48817. *res = (int)(sp_384_cmp_12(p1->x, u1) == 0);
  48818. if (*res == 0) {
  48819. /* Reload r and add order. */
  48820. sp_384_from_mp(u2, 12, rm);
  48821. carry = sp_384_add_12(u2, u2, p384_order);
  48822. /* Carry means result is greater than mod and is not valid. */
  48823. if (carry == 0) {
  48824. sp_384_norm_12(u2);
  48825. /* Compare with mod and if greater or equal then not valid. */
  48826. c = sp_384_cmp_12(u2, p384_mod);
  48827. }
  48828. }
  48829. if ((*res == 0) && (c < 0)) {
  48830. /* Convert to Montogomery form */
  48831. err = sp_384_mod_mul_norm_12(u2, u2, p384_mod);
  48832. if (err == MP_OKAY) {
  48833. /* u1 = (r + 1*order).z'.z' mod prime */
  48834. {
  48835. sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod);
  48836. }
  48837. *res = (sp_384_cmp_12(p1->x, u1) == 0);
  48838. }
  48839. }
  48840. }
  48841. #ifdef WOLFSSL_SP_SMALL_STACK
  48842. if (u1 != NULL)
  48843. XFREE(u1, heap, DYNAMIC_TYPE_ECC);
  48844. if (p1 != NULL)
  48845. XFREE(p1, heap, DYNAMIC_TYPE_ECC);
  48846. #endif
  48847. return err;
  48848. }
  48849. #ifdef WOLFSSL_SP_NONBLOCK
  48850. typedef struct sp_ecc_verify_384_ctx {
  48851. int state;
  48852. union {
  48853. sp_384_ecc_mulmod_12_ctx mulmod_ctx;
  48854. sp_384_mont_inv_order_12_ctx mont_inv_order_ctx;
  48855. sp_384_proj_point_dbl_12_ctx dbl_ctx;
  48856. sp_384_proj_point_add_12_ctx add_ctx;
  48857. };
  48858. sp_digit u1[2*12];
  48859. sp_digit u2[2*12];
  48860. sp_digit s[2*12];
  48861. sp_digit tmp[2*12 * 6];
  48862. sp_point_384 p1;
  48863. sp_point_384 p2;
  48864. } sp_ecc_verify_384_ctx;
  48865. int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
  48866. word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
  48867. const mp_int* rm, const mp_int* sm, int* res, void* heap)
  48868. {
  48869. int err = FP_WOULDBLOCK;
  48870. sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data;
  48871. typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  48872. (void)sizeof(ctx_size_test);
  48873. switch (ctx->state) {
  48874. case 0: /* INIT */
  48875. if (hashLen > 48U) {
  48876. hashLen = 48U;
  48877. }
  48878. sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen);
  48879. sp_384_from_mp(ctx->u2, 12, rm);
  48880. sp_384_from_mp(ctx->s, 12, sm);
  48881. sp_384_from_mp(ctx->p2.x, 12, pX);
  48882. sp_384_from_mp(ctx->p2.y, 12, pY);
  48883. sp_384_from_mp(ctx->p2.z, 12, pZ);
  48884. ctx->state = 1;
  48885. break;
  48886. case 1: /* NORMS0 */
  48887. sp_384_mul_12(ctx->s, ctx->s, p384_norm_order);
  48888. err = sp_384_mod_12(ctx->s, ctx->s, p384_order);
  48889. if (err == MP_OKAY)
  48890. ctx->state = 2;
  48891. break;
  48892. case 2: /* NORMS1 */
  48893. sp_384_norm_12(ctx->s);
  48894. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  48895. ctx->state = 3;
  48896. break;
  48897. case 3: /* NORMS2 */
  48898. err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
  48899. if (err == MP_OKAY) {
  48900. ctx->state = 4;
  48901. }
  48902. break;
  48903. case 4: /* NORMS3 */
  48904. sp_384_mont_mul_order_12(ctx->u1, ctx->u1, ctx->s);
  48905. ctx->state = 5;
  48906. break;
  48907. case 5: /* NORMS4 */
  48908. sp_384_mont_mul_order_12(ctx->u2, ctx->u2, ctx->s);
  48909. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  48910. ctx->state = 6;
  48911. break;
  48912. case 6: /* MULBASE */
  48913. err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, 0, heap);
  48914. if (err == MP_OKAY) {
  48915. if (sp_384_iszero_12(ctx->p1.z)) {
  48916. ctx->p1.infinity = 1;
  48917. }
  48918. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  48919. ctx->state = 7;
  48920. }
  48921. break;
  48922. case 7: /* MULMOD */
  48923. err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
  48924. if (err == MP_OKAY) {
  48925. if (sp_384_iszero_12(ctx->p2.z)) {
  48926. ctx->p2.infinity = 1;
  48927. }
  48928. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  48929. ctx->state = 8;
  48930. }
  48931. break;
  48932. case 8: /* ADD */
  48933. err = sp_384_proj_point_add_12_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
  48934. if (err == MP_OKAY)
  48935. ctx->state = 9;
  48936. break;
  48937. case 9: /* MONT */
  48938. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  48939. /* Reload r and convert to Montgomery form. */
  48940. sp_384_from_mp(ctx->u2, 12, rm);
  48941. err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod);
  48942. if (err == MP_OKAY)
  48943. ctx->state = 10;
  48944. break;
  48945. case 10: /* SQR */
  48946. /* u1 = r.z'.z' mod prime */
  48947. sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod);
  48948. ctx->state = 11;
  48949. break;
  48950. case 11: /* MUL */
  48951. sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod);
  48952. ctx->state = 12;
  48953. break;
  48954. case 12: /* RES */
  48955. {
  48956. sp_int32 c = 0;
  48957. err = MP_OKAY; /* math okay, now check result */
  48958. *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0);
  48959. if (*res == 0) {
  48960. sp_digit carry;
  48961. /* Reload r and add order. */
  48962. sp_384_from_mp(ctx->u2, 12, rm);
  48963. carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order);
  48964. /* Carry means result is greater than mod and is not valid. */
  48965. if (carry == 0) {
  48966. sp_384_norm_12(ctx->u2);
  48967. /* Compare with mod and if greater or equal then not valid. */
  48968. c = sp_384_cmp_12(ctx->u2, p384_mod);
  48969. }
  48970. }
  48971. if ((*res == 0) && (c < 0)) {
  48972. /* Convert to Montogomery form */
  48973. err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod);
  48974. if (err == MP_OKAY) {
  48975. /* u1 = (r + 1*order).z'.z' mod prime */
  48976. sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod,
  48977. p384_mp_mod);
  48978. *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0);
  48979. }
  48980. }
  48981. break;
  48982. }
  48983. } /* switch */
  48984. if (err == MP_OKAY && ctx->state != 12) {
  48985. err = FP_WOULDBLOCK;
  48986. }
  48987. return err;
  48988. }
  48989. #endif /* WOLFSSL_SP_NONBLOCK */
  48990. #endif /* HAVE_ECC_VERIFY */
  48991. #ifdef HAVE_ECC_CHECK_KEY
  48992. /* Check that the x and y ordinates are a valid point on the curve.
  48993. *
  48994. * point EC point.
  48995. * heap Heap to use if dynamically allocating.
  48996. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  48997. * not on the curve and MP_OKAY otherwise.
  48998. */
  48999. static int sp_384_ecc_is_point_12(const sp_point_384* point,
  49000. void* heap)
  49001. {
  49002. #ifdef WOLFSSL_SP_SMALL_STACK
  49003. sp_digit* t1 = NULL;
  49004. #else
  49005. sp_digit t1[12 * 4];
  49006. #endif
  49007. sp_digit* t2 = NULL;
  49008. int err = MP_OKAY;
  49009. #ifdef WOLFSSL_SP_SMALL_STACK
  49010. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC);
  49011. if (t1 == NULL)
  49012. err = MEMORY_E;
  49013. #endif
  49014. (void)heap;
  49015. if (err == MP_OKAY) {
  49016. t2 = t1 + 2 * 12;
  49017. /* y^2 - x^3 - a.x = b */
  49018. sp_384_sqr_12(t1, point->y);
  49019. (void)sp_384_mod_12(t1, t1, p384_mod);
  49020. sp_384_sqr_12(t2, point->x);
  49021. (void)sp_384_mod_12(t2, t2, p384_mod);
  49022. sp_384_mul_12(t2, t2, point->x);
  49023. (void)sp_384_mod_12(t2, t2, p384_mod);
  49024. sp_384_mont_sub_12(t1, t1, t2, p384_mod);
  49025. /* y^2 - x^3 + 3.x = b, when a = -3 */
  49026. sp_384_mont_add_12(t1, t1, point->x, p384_mod);
  49027. sp_384_mont_add_12(t1, t1, point->x, p384_mod);
  49028. sp_384_mont_add_12(t1, t1, point->x, p384_mod);
  49029. if (sp_384_cmp_12(t1, p384_b) != 0) {
  49030. err = MP_VAL;
  49031. }
  49032. }
  49033. #ifdef WOLFSSL_SP_SMALL_STACK
  49034. if (t1 != NULL)
  49035. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  49036. #endif
  49037. return err;
  49038. }
  49039. /* Check that the x and y ordinates are a valid point on the curve.
  49040. *
  49041. * pX X ordinate of EC point.
  49042. * pY Y ordinate of EC point.
  49043. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  49044. * not on the curve and MP_OKAY otherwise.
  49045. */
  49046. int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY)
  49047. {
  49048. #ifdef WOLFSSL_SP_SMALL_STACK
  49049. sp_point_384* pub = NULL;
  49050. #else
  49051. sp_point_384 pub[1];
  49052. #endif
  49053. const byte one[1] = { 1 };
  49054. int err = MP_OKAY;
  49055. #ifdef WOLFSSL_SP_SMALL_STACK
  49056. pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
  49057. DYNAMIC_TYPE_ECC);
  49058. if (pub == NULL)
  49059. err = MEMORY_E;
  49060. #endif
  49061. if (err == MP_OKAY) {
  49062. sp_384_from_mp(pub->x, 12, pX);
  49063. sp_384_from_mp(pub->y, 12, pY);
  49064. sp_384_from_bin(pub->z, 12, one, (int)sizeof(one));
  49065. err = sp_384_ecc_is_point_12(pub, NULL);
  49066. }
  49067. #ifdef WOLFSSL_SP_SMALL_STACK
  49068. if (pub != NULL)
  49069. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  49070. #endif
  49071. return err;
  49072. }
  49073. /* Check that the private scalar generates the EC point (px, py), the point is
  49074. * on the curve and the point has the correct order.
  49075. *
  49076. * pX X ordinate of EC point.
  49077. * pY Y ordinate of EC point.
  49078. * privm Private scalar that generates EC point.
  49079. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  49080. * not on the curve, ECC_INF_E if the point does not have the correct order,
  49081. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  49082. * MP_OKAY otherwise.
  49083. */
  49084. int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY,
  49085. const mp_int* privm, void* heap)
  49086. {
  49087. #ifdef WOLFSSL_SP_SMALL_STACK
  49088. sp_digit* priv = NULL;
  49089. sp_point_384* pub = NULL;
  49090. #else
  49091. sp_digit priv[12];
  49092. sp_point_384 pub[2];
  49093. #endif
  49094. sp_point_384* p = NULL;
  49095. const byte one[1] = { 1 };
  49096. int err = MP_OKAY;
  49097. /* Quick check the lengs of public key ordinates and private key are in
  49098. * range. Proper check later.
  49099. */
  49100. if (((mp_count_bits(pX) > 384) ||
  49101. (mp_count_bits(pY) > 384) ||
  49102. ((privm != NULL) && (mp_count_bits(privm) > 384)))) {
  49103. err = ECC_OUT_OF_RANGE_E;
  49104. }
  49105. #ifdef WOLFSSL_SP_SMALL_STACK
  49106. if (err == MP_OKAY) {
  49107. pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  49108. DYNAMIC_TYPE_ECC);
  49109. if (pub == NULL)
  49110. err = MEMORY_E;
  49111. }
  49112. if (err == MP_OKAY && privm) {
  49113. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap,
  49114. DYNAMIC_TYPE_ECC);
  49115. if (priv == NULL)
  49116. err = MEMORY_E;
  49117. }
  49118. #endif
  49119. if (err == MP_OKAY) {
  49120. p = pub + 1;
  49121. sp_384_from_mp(pub->x, 12, pX);
  49122. sp_384_from_mp(pub->y, 12, pY);
  49123. sp_384_from_bin(pub->z, 12, one, (int)sizeof(one));
  49124. if (privm)
  49125. sp_384_from_mp(priv, 12, privm);
  49126. /* Check point at infinitiy. */
  49127. if ((sp_384_iszero_12(pub->x) != 0) &&
  49128. (sp_384_iszero_12(pub->y) != 0)) {
  49129. err = ECC_INF_E;
  49130. }
  49131. }
  49132. /* Check range of X and Y */
  49133. if ((err == MP_OKAY) &&
  49134. ((sp_384_cmp_12(pub->x, p384_mod) >= 0) ||
  49135. (sp_384_cmp_12(pub->y, p384_mod) >= 0))) {
  49136. err = ECC_OUT_OF_RANGE_E;
  49137. }
  49138. if (err == MP_OKAY) {
  49139. /* Check point is on curve */
  49140. err = sp_384_ecc_is_point_12(pub, heap);
  49141. }
  49142. if (err == MP_OKAY) {
  49143. /* Point * order = infinity */
  49144. err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, 1, heap);
  49145. }
  49146. /* Check result is infinity */
  49147. if ((err == MP_OKAY) && ((sp_384_iszero_12(p->x) == 0) ||
  49148. (sp_384_iszero_12(p->y) == 0))) {
  49149. err = ECC_INF_E;
  49150. }
  49151. if (privm) {
  49152. if (err == MP_OKAY) {
  49153. /* Base * private = point */
  49154. err = sp_384_ecc_mulmod_base_12(p, priv, 1, 1, heap);
  49155. }
  49156. /* Check result is public key */
  49157. if ((err == MP_OKAY) &&
  49158. ((sp_384_cmp_12(p->x, pub->x) != 0) ||
  49159. (sp_384_cmp_12(p->y, pub->y) != 0))) {
  49160. err = ECC_PRIV_KEY_E;
  49161. }
  49162. }
  49163. #ifdef WOLFSSL_SP_SMALL_STACK
  49164. if (pub != NULL)
  49165. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  49166. if (priv != NULL)
  49167. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  49168. #endif
  49169. return err;
  49170. }
  49171. #endif
  49172. #ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
  49173. /* Add two projective EC points together.
  49174. * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
  49175. *
  49176. * pX First EC point's X ordinate.
  49177. * pY First EC point's Y ordinate.
  49178. * pZ First EC point's Z ordinate.
  49179. * qX Second EC point's X ordinate.
  49180. * qY Second EC point's Y ordinate.
  49181. * qZ Second EC point's Z ordinate.
  49182. * rX Resultant EC point's X ordinate.
  49183. * rY Resultant EC point's Y ordinate.
  49184. * rZ Resultant EC point's Z ordinate.
  49185. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  49186. */
  49187. int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ,
  49188. mp_int* qX, mp_int* qY, mp_int* qZ,
  49189. mp_int* rX, mp_int* rY, mp_int* rZ)
  49190. {
  49191. #ifdef WOLFSSL_SP_SMALL_STACK
  49192. sp_digit* tmp = NULL;
  49193. sp_point_384* p = NULL;
  49194. #else
  49195. sp_digit tmp[2 * 12 * 6];
  49196. sp_point_384 p[2];
  49197. #endif
  49198. sp_point_384* q = NULL;
  49199. int err = MP_OKAY;
  49200. #ifdef WOLFSSL_SP_SMALL_STACK
  49201. if (err == MP_OKAY) {
  49202. p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL,
  49203. DYNAMIC_TYPE_ECC);
  49204. if (p == NULL)
  49205. err = MEMORY_E;
  49206. }
  49207. if (err == MP_OKAY) {
  49208. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL,
  49209. DYNAMIC_TYPE_ECC);
  49210. if (tmp == NULL) {
  49211. err = MEMORY_E;
  49212. }
  49213. }
  49214. #endif
  49215. if (err == MP_OKAY) {
  49216. q = p + 1;
  49217. sp_384_from_mp(p->x, 12, pX);
  49218. sp_384_from_mp(p->y, 12, pY);
  49219. sp_384_from_mp(p->z, 12, pZ);
  49220. sp_384_from_mp(q->x, 12, qX);
  49221. sp_384_from_mp(q->y, 12, qY);
  49222. sp_384_from_mp(q->z, 12, qZ);
  49223. p->infinity = sp_384_iszero_12(p->x) &
  49224. sp_384_iszero_12(p->y);
  49225. q->infinity = sp_384_iszero_12(q->x) &
  49226. sp_384_iszero_12(q->y);
  49227. sp_384_proj_point_add_12(p, p, q, tmp);
  49228. }
  49229. if (err == MP_OKAY) {
  49230. err = sp_384_to_mp(p->x, rX);
  49231. }
  49232. if (err == MP_OKAY) {
  49233. err = sp_384_to_mp(p->y, rY);
  49234. }
  49235. if (err == MP_OKAY) {
  49236. err = sp_384_to_mp(p->z, rZ);
  49237. }
  49238. #ifdef WOLFSSL_SP_SMALL_STACK
  49239. if (tmp != NULL)
  49240. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  49241. if (p != NULL)
  49242. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  49243. #endif
  49244. return err;
  49245. }
  49246. /* Double a projective EC point.
  49247. * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
  49248. *
  49249. * pX EC point's X ordinate.
  49250. * pY EC point's Y ordinate.
  49251. * pZ EC point's Z ordinate.
  49252. * rX Resultant EC point's X ordinate.
  49253. * rY Resultant EC point's Y ordinate.
  49254. * rZ Resultant EC point's Z ordinate.
  49255. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  49256. */
  49257. int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ,
  49258. mp_int* rX, mp_int* rY, mp_int* rZ)
  49259. {
  49260. #ifdef WOLFSSL_SP_SMALL_STACK
  49261. sp_digit* tmp = NULL;
  49262. sp_point_384* p = NULL;
  49263. #else
  49264. sp_digit tmp[2 * 12 * 2];
  49265. sp_point_384 p[1];
  49266. #endif
  49267. int err = MP_OKAY;
  49268. #ifdef WOLFSSL_SP_SMALL_STACK
  49269. if (err == MP_OKAY) {
  49270. p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
  49271. DYNAMIC_TYPE_ECC);
  49272. if (p == NULL)
  49273. err = MEMORY_E;
  49274. }
  49275. if (err == MP_OKAY) {
  49276. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 2, NULL,
  49277. DYNAMIC_TYPE_ECC);
  49278. if (tmp == NULL)
  49279. err = MEMORY_E;
  49280. }
  49281. #endif
  49282. if (err == MP_OKAY) {
  49283. sp_384_from_mp(p->x, 12, pX);
  49284. sp_384_from_mp(p->y, 12, pY);
  49285. sp_384_from_mp(p->z, 12, pZ);
  49286. p->infinity = sp_384_iszero_12(p->x) &
  49287. sp_384_iszero_12(p->y);
  49288. sp_384_proj_point_dbl_12(p, p, tmp);
  49289. }
  49290. if (err == MP_OKAY) {
  49291. err = sp_384_to_mp(p->x, rX);
  49292. }
  49293. if (err == MP_OKAY) {
  49294. err = sp_384_to_mp(p->y, rY);
  49295. }
  49296. if (err == MP_OKAY) {
  49297. err = sp_384_to_mp(p->z, rZ);
  49298. }
  49299. #ifdef WOLFSSL_SP_SMALL_STACK
  49300. if (tmp != NULL)
  49301. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  49302. if (p != NULL)
  49303. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  49304. #endif
  49305. return err;
  49306. }
  49307. /* Map a projective EC point to affine in place.
  49308. * pZ will be one.
  49309. *
  49310. * pX EC point's X ordinate.
  49311. * pY EC point's Y ordinate.
  49312. * pZ EC point's Z ordinate.
  49313. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  49314. */
  49315. int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ)
  49316. {
  49317. #ifdef WOLFSSL_SP_SMALL_STACK
  49318. sp_digit* tmp = NULL;
  49319. sp_point_384* p = NULL;
  49320. #else
  49321. sp_digit tmp[2 * 12 * 6];
  49322. sp_point_384 p[1];
  49323. #endif
  49324. int err = MP_OKAY;
  49325. #ifdef WOLFSSL_SP_SMALL_STACK
  49326. if (err == MP_OKAY) {
  49327. p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
  49328. DYNAMIC_TYPE_ECC);
  49329. if (p == NULL)
  49330. err = MEMORY_E;
  49331. }
  49332. if (err == MP_OKAY) {
  49333. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL,
  49334. DYNAMIC_TYPE_ECC);
  49335. if (tmp == NULL)
  49336. err = MEMORY_E;
  49337. }
  49338. #endif
  49339. if (err == MP_OKAY) {
  49340. sp_384_from_mp(p->x, 12, pX);
  49341. sp_384_from_mp(p->y, 12, pY);
  49342. sp_384_from_mp(p->z, 12, pZ);
  49343. p->infinity = sp_384_iszero_12(p->x) &
  49344. sp_384_iszero_12(p->y);
  49345. sp_384_map_12(p, p, tmp);
  49346. }
  49347. if (err == MP_OKAY) {
  49348. err = sp_384_to_mp(p->x, pX);
  49349. }
  49350. if (err == MP_OKAY) {
  49351. err = sp_384_to_mp(p->y, pY);
  49352. }
  49353. if (err == MP_OKAY) {
  49354. err = sp_384_to_mp(p->z, pZ);
  49355. }
  49356. #ifdef WOLFSSL_SP_SMALL_STACK
  49357. if (tmp != NULL)
  49358. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  49359. if (p != NULL)
  49360. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  49361. #endif
  49362. return err;
  49363. }
  49364. #endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
  49365. #ifdef HAVE_COMP_KEY
  49366. /* Find the square root of a number mod the prime of the curve.
  49367. *
  49368. * y The number to operate on and the result.
  49369. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  49370. */
  49371. static int sp_384_mont_sqrt_12(sp_digit* y)
  49372. {
  49373. #ifdef WOLFSSL_SP_SMALL_STACK
  49374. sp_digit* t1 = NULL;
  49375. #else
  49376. sp_digit t1[5 * 2 * 12];
  49377. #endif
  49378. sp_digit* t2 = NULL;
  49379. sp_digit* t3 = NULL;
  49380. sp_digit* t4 = NULL;
  49381. sp_digit* t5 = NULL;
  49382. int err = MP_OKAY;
  49383. #ifdef WOLFSSL_SP_SMALL_STACK
  49384. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC);
  49385. if (t1 == NULL)
  49386. err = MEMORY_E;
  49387. #endif
  49388. if (err == MP_OKAY) {
  49389. t2 = t1 + 2 * 12;
  49390. t3 = t1 + 4 * 12;
  49391. t4 = t1 + 6 * 12;
  49392. t5 = t1 + 8 * 12;
  49393. {
  49394. /* t2 = y ^ 0x2 */
  49395. sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod);
  49396. /* t1 = y ^ 0x3 */
  49397. sp_384_mont_mul_12(t1, t2, y, p384_mod, p384_mp_mod);
  49398. /* t5 = y ^ 0xc */
  49399. sp_384_mont_sqr_n_12(t5, t1, 2, p384_mod, p384_mp_mod);
  49400. /* t1 = y ^ 0xf */
  49401. sp_384_mont_mul_12(t1, t1, t5, p384_mod, p384_mp_mod);
  49402. /* t2 = y ^ 0x1e */
  49403. sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod);
  49404. /* t3 = y ^ 0x1f */
  49405. sp_384_mont_mul_12(t3, t2, y, p384_mod, p384_mp_mod);
  49406. /* t2 = y ^ 0x3e0 */
  49407. sp_384_mont_sqr_n_12(t2, t3, 5, p384_mod, p384_mp_mod);
  49408. /* t1 = y ^ 0x3ff */
  49409. sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod);
  49410. /* t2 = y ^ 0x7fe0 */
  49411. sp_384_mont_sqr_n_12(t2, t1, 5, p384_mod, p384_mp_mod);
  49412. /* t3 = y ^ 0x7fff */
  49413. sp_384_mont_mul_12(t3, t3, t2, p384_mod, p384_mp_mod);
  49414. /* t2 = y ^ 0x3fff800 */
  49415. sp_384_mont_sqr_n_12(t2, t3, 15, p384_mod, p384_mp_mod);
  49416. /* t4 = y ^ 0x3ffffff */
  49417. sp_384_mont_mul_12(t4, t3, t2, p384_mod, p384_mp_mod);
  49418. /* t2 = y ^ 0xffffffc000000 */
  49419. sp_384_mont_sqr_n_12(t2, t4, 30, p384_mod, p384_mp_mod);
  49420. /* t1 = y ^ 0xfffffffffffff */
  49421. sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod);
  49422. /* t2 = y ^ 0xfffffffffffffff000000000000000 */
  49423. sp_384_mont_sqr_n_12(t2, t1, 60, p384_mod, p384_mp_mod);
  49424. /* t1 = y ^ 0xffffffffffffffffffffffffffffff */
  49425. sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod);
  49426. /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */
  49427. sp_384_mont_sqr_n_12(t2, t1, 120, p384_mod, p384_mp_mod);
  49428. /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  49429. sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod);
  49430. /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */
  49431. sp_384_mont_sqr_n_12(t2, t1, 15, p384_mod, p384_mp_mod);
  49432. /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  49433. sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod);
  49434. /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */
  49435. sp_384_mont_sqr_n_12(t2, t1, 31, p384_mod, p384_mp_mod);
  49436. /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */
  49437. sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod);
  49438. /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */
  49439. sp_384_mont_sqr_n_12(t2, t1, 4, p384_mod, p384_mp_mod);
  49440. /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */
  49441. sp_384_mont_mul_12(t1, t5, t2, p384_mod, p384_mp_mod);
  49442. /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */
  49443. sp_384_mont_sqr_n_12(t2, t1, 62, p384_mod, p384_mp_mod);
  49444. /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */
  49445. sp_384_mont_mul_12(t1, y, t2, p384_mod, p384_mp_mod);
  49446. /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */
  49447. sp_384_mont_sqr_n_12(y, t1, 30, p384_mod, p384_mp_mod);
  49448. }
  49449. }
  49450. #ifdef WOLFSSL_SP_SMALL_STACK
  49451. if (t1 != NULL)
  49452. XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
  49453. #endif
  49454. return err;
  49455. }
  49456. /* Uncompress the point given the X ordinate.
  49457. *
  49458. * xm X ordinate.
  49459. * odd Whether the Y ordinate is odd.
  49460. * ym Calculated Y ordinate.
  49461. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  49462. */
  49463. int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym)
  49464. {
  49465. #ifdef WOLFSSL_SP_SMALL_STACK
  49466. sp_digit* x = NULL;
  49467. #else
  49468. sp_digit x[4 * 12];
  49469. #endif
  49470. sp_digit* y = NULL;
  49471. int err = MP_OKAY;
  49472. #ifdef WOLFSSL_SP_SMALL_STACK
  49473. x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC);
  49474. if (x == NULL)
  49475. err = MEMORY_E;
  49476. #endif
  49477. if (err == MP_OKAY) {
  49478. y = x + 2 * 12;
  49479. sp_384_from_mp(x, 12, xm);
  49480. err = sp_384_mod_mul_norm_12(x, x, p384_mod);
  49481. }
  49482. if (err == MP_OKAY) {
  49483. /* y = x^3 */
  49484. {
  49485. sp_384_mont_sqr_12(y, x, p384_mod, p384_mp_mod);
  49486. sp_384_mont_mul_12(y, y, x, p384_mod, p384_mp_mod);
  49487. }
  49488. /* y = x^3 - 3x */
  49489. sp_384_mont_sub_12(y, y, x, p384_mod);
  49490. sp_384_mont_sub_12(y, y, x, p384_mod);
  49491. sp_384_mont_sub_12(y, y, x, p384_mod);
  49492. /* y = x^3 - 3x + b */
  49493. err = sp_384_mod_mul_norm_12(x, p384_b, p384_mod);
  49494. }
  49495. if (err == MP_OKAY) {
  49496. sp_384_mont_add_12(y, y, x, p384_mod);
  49497. /* y = sqrt(x^3 - 3x + b) */
  49498. err = sp_384_mont_sqrt_12(y);
  49499. }
  49500. if (err == MP_OKAY) {
  49501. XMEMSET(y + 12, 0, 12U * sizeof(sp_digit));
  49502. sp_384_mont_reduce_12(y, p384_mod, p384_mp_mod);
  49503. if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
  49504. sp_384_mont_sub_12(y, p384_mod, y, p384_mod);
  49505. }
  49506. err = sp_384_to_mp(y, ym);
  49507. }
  49508. #ifdef WOLFSSL_SP_SMALL_STACK
  49509. if (x != NULL)
  49510. XFREE(x, NULL, DYNAMIC_TYPE_ECC);
  49511. #endif
  49512. return err;
  49513. }
  49514. #endif
  49515. #endif /* WOLFSSL_SP_384 */
  49516. #ifdef WOLFSSL_SP_521
  49517. /* Point structure to use. */
  49518. typedef struct sp_point_521 {
  49519. /* X ordinate of point. */
  49520. sp_digit x[2 * 17];
  49521. /* Y ordinate of point. */
  49522. sp_digit y[2 * 17];
  49523. /* Z ordinate of point. */
  49524. sp_digit z[2 * 17];
  49525. /* Indicates point is at infinity. */
  49526. int infinity;
  49527. } sp_point_521;
  49528. /* The modulus (prime) of the curve P521. */
  49529. static const sp_digit p521_mod[17] = {
  49530. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,
  49531. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,
  49532. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0x000001ff
  49533. };
  49534. /* The Montgomery normalizer for modulus of the curve P521. */
  49535. static const sp_digit p521_norm_mod[17] = {
  49536. 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  49537. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  49538. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
  49539. };
  49540. /* The Montgomery multiplier for modulus of the curve P521. */
  49541. static sp_digit p521_mp_mod = 0x00000001;
  49542. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  49543. defined(HAVE_ECC_VERIFY)
  49544. /* The order of the curve P521. */
  49545. static const sp_digit p521_order[17] = {
  49546. 0x91386409,0xbb6fb71e,0x899c47ae,0x3bb5c9b8,0xf709a5d0,0x7fcc0148,
  49547. 0xbf2f966b,0x51868783,0xfffffffa,0xffffffff,0xffffffff,0xffffffff,
  49548. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0x000001ff
  49549. };
  49550. #endif
  49551. /* The order of the curve P521 minus 2. */
  49552. static const sp_digit p521_order2[17] = {
  49553. 0x91386407,0xbb6fb71e,0x899c47ae,0x3bb5c9b8,0xf709a5d0,0x7fcc0148,
  49554. 0xbf2f966b,0x51868783,0xfffffffa,0xffffffff,0xffffffff,0xffffffff,
  49555. 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0x000001ff
  49556. };
  49557. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  49558. /* The Montgomery normalizer for order of the curve P521. */
  49559. static const sp_digit p521_norm_order[17] = {
  49560. 0x6ec79bf7,0x449048e1,0x7663b851,0xc44a3647,0x08f65a2f,0x8033feb7,
  49561. 0x40d06994,0xae79787c,0x00000005,0x00000000,0x00000000,0x00000000,
  49562. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
  49563. };
  49564. #endif
  49565. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  49566. /* The Montgomery multiplier for order of the curve P521. */
  49567. static sp_digit p521_mp_order = 0x79a995c7;
  49568. #endif
  49569. /* The base point of curve P521. */
  49570. static const sp_point_521 p521_base = {
  49571. /* X ordinate */
  49572. {
  49573. 0xc2e5bd66,0xf97e7e31,0x856a429b,0x3348b3c1,0xa2ffa8de,0xfe1dc127,
  49574. 0xefe75928,0xa14b5e77,0x6b4d3dba,0xf828af60,0x053fb521,0x9c648139,
  49575. 0x2395b442,0x9e3ecb66,0x0404e9cd,0x858e06b7,0x000000c6,
  49576. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49577. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49578. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49579. (sp_digit)0, (sp_digit)0
  49580. },
  49581. /* Y ordinate */
  49582. {
  49583. 0x9fd16650,0x88be9476,0xa272c240,0x353c7086,0x3fad0761,0xc550b901,
  49584. 0x5ef42640,0x97ee7299,0x273e662c,0x17afbd17,0x579b4468,0x98f54449,
  49585. 0x2c7d1bd9,0x5c8a5fb4,0x9a3bc004,0x39296a78,0x00000118,
  49586. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49587. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49588. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49589. (sp_digit)0, (sp_digit)0
  49590. },
  49591. /* Z ordinate */
  49592. {
  49593. 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  49594. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  49595. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  49596. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49597. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49598. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  49599. (sp_digit)0, (sp_digit)0
  49600. },
  49601. /* infinity */
  49602. 0
  49603. };
  49604. #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
  49605. static const sp_digit p521_b[17] = {
  49606. 0x6b503f00,0xef451fd4,0x3d2c34f1,0x3573df88,0x3bb1bf07,0x1652c0bd,
  49607. 0xec7e937b,0x56193951,0x8ef109e1,0xb8b48991,0x99b315f3,0xa2da725b,
  49608. 0xb68540ee,0x929a21a0,0x8e1c9a1f,0x953eb961,0x00000051
  49609. };
  49610. #endif
  49611. #ifdef WOLFSSL_SP_SMALL
  49612. /* Multiply a and b into r. (r = a * b)
  49613. *
  49614. * r A single precision integer.
  49615. * a A single precision integer.
  49616. * b A single precision integer.
  49617. */
  49618. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  49619. static void sp_521_mul_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  49620. #else
  49621. static void sp_521_mul_17(sp_digit* r, const sp_digit* a, const sp_digit* b)
  49622. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  49623. {
  49624. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  49625. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  49626. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  49627. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  49628. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  49629. __asm__ __volatile__ (
  49630. "SUB sp, sp, #0x88\n\t"
  49631. "LDR lr, [%[a]]\n\t"
  49632. "LDR r11, [%[b]]\n\t"
  49633. "UMULL r8, r6, lr, r11\n\t"
  49634. "STR r8, [sp]\n\t"
  49635. "MOV r7, #0x0\n\t"
  49636. "MOV r8, #0x0\n\t"
  49637. "MOV r5, #0x4\n\t"
  49638. "\n"
  49639. "L_sp_521_mul_17_outer:\n\t"
  49640. "SUBS r3, r5, #0x40\n\t"
  49641. "IT cc\n\t"
  49642. "MOVCC r3, #0x0\n\t"
  49643. "SUB r4, r5, r3\n\t"
  49644. "\n"
  49645. "L_sp_521_mul_17_inner:\n\t"
  49646. "LDR lr, [%[a], r3]\n\t"
  49647. "LDR r11, [%[b], r4]\n\t"
  49648. "UMULL r9, r10, lr, r11\n\t"
  49649. "ADDS r6, r6, r9\n\t"
  49650. "ADCS r7, r7, r10\n\t"
  49651. "ADC r8, r8, #0x0\n\t"
  49652. "LDR lr, [%[a], r4]\n\t"
  49653. "LDR r11, [%[b], r3]\n\t"
  49654. "UMULL r9, r10, lr, r11\n\t"
  49655. "ADDS r6, r6, r9\n\t"
  49656. "ADCS r7, r7, r10\n\t"
  49657. "ADC r8, r8, #0x0\n\t"
  49658. "ADD r3, r3, #0x4\n\t"
  49659. "SUB r4, r4, #0x4\n\t"
  49660. "CMP r3, r4\n\t"
  49661. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  49662. "BGT L_sp_521_mul_17_inner_done\n\t"
  49663. #else
  49664. "BGT.N L_sp_521_mul_17_inner_done\n\t"
  49665. #endif
  49666. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  49667. "BLT L_sp_521_mul_17_inner\n\t"
  49668. #else
  49669. "BLT.N L_sp_521_mul_17_inner\n\t"
  49670. #endif
  49671. "LDR lr, [%[a], r3]\n\t"
  49672. "LDR r11, [%[b], r3]\n\t"
  49673. "UMULL r9, r10, lr, r11\n\t"
  49674. "ADDS r6, r6, r9\n\t"
  49675. "ADCS r7, r7, r10\n\t"
  49676. "ADC r8, r8, #0x0\n\t"
  49677. "\n"
  49678. "L_sp_521_mul_17_inner_done:\n\t"
  49679. "STR r6, [sp, r5]\n\t"
  49680. "MOV r6, r7\n\t"
  49681. "MOV r7, r8\n\t"
  49682. "MOV r8, #0x0\n\t"
  49683. "ADD r5, r5, #0x4\n\t"
  49684. "CMP r5, #0x7c\n\t"
  49685. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  49686. "BLE L_sp_521_mul_17_outer\n\t"
  49687. #else
  49688. "BLE.N L_sp_521_mul_17_outer\n\t"
  49689. #endif
  49690. "LDR lr, [%[a], #64]\n\t"
  49691. "LDR r11, [%[b], #64]\n\t"
  49692. "UMLAL r6, r7, lr, r11\n\t"
  49693. "STR r6, [sp, r5]\n\t"
  49694. "ADD r5, r5, #0x4\n\t"
  49695. "STR r7, [sp, r5]\n\t"
  49696. "LDM sp!, {r6, r7}\n\t"
  49697. "STM %[r]!, {r6, r7}\n\t"
  49698. "SUB r5, r5, #0x8\n\t"
  49699. "\n"
  49700. "L_sp_521_mul_17_store:\n\t"
  49701. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  49702. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  49703. "SUBS r5, r5, #0x20\n\t"
  49704. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  49705. "BGT L_sp_521_mul_17_store\n\t"
  49706. #else
  49707. "BGT.N L_sp_521_mul_17_store\n\t"
  49708. #endif
  49709. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  49710. :
  49711. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  49712. );
  49713. }
  49714. #else
  49715. /* Multiply a and b into r. (r = a * b)
  49716. *
  49717. * r A single precision integer.
  49718. * a A single precision integer.
  49719. * b A single precision integer.
  49720. */
  49721. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  49722. static void sp_521_mul_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  49723. #else
  49724. static void sp_521_mul_17(sp_digit* r, const sp_digit* a, const sp_digit* b)
  49725. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  49726. {
  49727. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  49728. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  49729. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  49730. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  49731. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  49732. __asm__ __volatile__ (
  49733. "SUB sp, sp, #0x44\n\t"
  49734. /* A[0] * B[0] */
  49735. "LDR r11, [%[a]]\n\t"
  49736. "LDR r12, [%[b]]\n\t"
  49737. "UMULL r3, r4, r11, r12\n\t"
  49738. "MOV r5, #0x0\n\t"
  49739. "STR r3, [sp]\n\t"
  49740. /* A[0] * B[1] */
  49741. "LDR r9, [%[b], #4]\n\t"
  49742. "UMULL r6, r7, r11, r9\n\t"
  49743. "ADDS r4, r4, r6\n\t"
  49744. "ADCS r5, r5, r7\n\t"
  49745. "MOV r3, #0x0\n\t"
  49746. "ADC r3, r3, #0x0\n\t"
  49747. /* A[1] * B[0] */
  49748. "LDR r8, [%[a], #4]\n\t"
  49749. "UMULL r6, r7, r8, r12\n\t"
  49750. "ADDS r4, r4, r6\n\t"
  49751. "ADCS r5, r5, r7\n\t"
  49752. "ADC r3, r3, #0x0\n\t"
  49753. "STR r4, [sp, #4]\n\t"
  49754. /* A[2] * B[0] */
  49755. "LDR r8, [%[a], #8]\n\t"
  49756. "UMULL r6, r7, r8, r12\n\t"
  49757. "ADDS r5, r5, r6\n\t"
  49758. "ADCS r3, r3, r7\n\t"
  49759. "MOV r4, #0x0\n\t"
  49760. "ADC r4, r4, #0x0\n\t"
  49761. /* A[1] * B[1] */
  49762. "LDR r11, [%[a], #4]\n\t"
  49763. "LDR r12, [%[b], #4]\n\t"
  49764. "UMULL r6, r7, r11, r12\n\t"
  49765. "ADDS r5, r5, r6\n\t"
  49766. "ADCS r3, r3, r7\n\t"
  49767. "ADC r4, r4, #0x0\n\t"
  49768. /* A[0] * B[2] */
  49769. "LDR r8, [%[a]]\n\t"
  49770. "LDR r9, [%[b], #8]\n\t"
  49771. "UMULL r6, r7, r8, r9\n\t"
  49772. "ADDS r5, r5, r6\n\t"
  49773. "ADCS r3, r3, r7\n\t"
  49774. "ADC r4, r4, #0x0\n\t"
  49775. "STR r5, [sp, #8]\n\t"
  49776. /* A[0] * B[3] */
  49777. "LDR r9, [%[b], #12]\n\t"
  49778. "UMULL r6, r7, r8, r9\n\t"
  49779. "ADDS r3, r3, r6\n\t"
  49780. "ADCS r4, r4, r7\n\t"
  49781. "MOV r5, #0x0\n\t"
  49782. "ADC r5, r5, #0x0\n\t"
  49783. /* A[1] * B[2] */
  49784. "LDR r9, [%[b], #8]\n\t"
  49785. "UMULL r6, r7, r11, r9\n\t"
  49786. "ADDS r3, r3, r6\n\t"
  49787. "ADCS r4, r4, r7\n\t"
  49788. "ADC r5, r5, #0x0\n\t"
  49789. /* A[2] * B[1] */
  49790. "LDR r8, [%[a], #8]\n\t"
  49791. "UMULL r6, r7, r8, r12\n\t"
  49792. "ADDS r3, r3, r6\n\t"
  49793. "ADCS r4, r4, r7\n\t"
  49794. "ADC r5, r5, #0x0\n\t"
  49795. /* A[3] * B[0] */
  49796. "LDR r8, [%[a], #12]\n\t"
  49797. "LDR r9, [%[b]]\n\t"
  49798. "UMULL r6, r7, r8, r9\n\t"
  49799. "ADDS r3, r3, r6\n\t"
  49800. "ADCS r4, r4, r7\n\t"
  49801. "ADC r5, r5, #0x0\n\t"
  49802. "STR r3, [sp, #12]\n\t"
  49803. /* A[4] * B[0] */
  49804. "LDR r8, [%[a], #16]\n\t"
  49805. "UMULL r6, r7, r8, r9\n\t"
  49806. "ADDS r4, r4, r6\n\t"
  49807. "ADCS r5, r5, r7\n\t"
  49808. "MOV r3, #0x0\n\t"
  49809. "ADC r3, r3, #0x0\n\t"
  49810. /* A[3] * B[1] */
  49811. "LDR r8, [%[a], #12]\n\t"
  49812. "UMULL r6, r7, r8, r12\n\t"
  49813. "ADDS r4, r4, r6\n\t"
  49814. "ADCS r5, r5, r7\n\t"
  49815. "ADC r3, r3, #0x0\n\t"
  49816. /* A[2] * B[2] */
  49817. "LDR r11, [%[a], #8]\n\t"
  49818. "LDR r12, [%[b], #8]\n\t"
  49819. "UMULL r6, r7, r11, r12\n\t"
  49820. "ADDS r4, r4, r6\n\t"
  49821. "ADCS r5, r5, r7\n\t"
  49822. "ADC r3, r3, #0x0\n\t"
  49823. /* A[1] * B[3] */
  49824. "LDR r8, [%[a], #4]\n\t"
  49825. "LDR r9, [%[b], #12]\n\t"
  49826. "UMULL r6, r7, r8, r9\n\t"
  49827. "ADDS r4, r4, r6\n\t"
  49828. "ADCS r5, r5, r7\n\t"
  49829. "ADC r3, r3, #0x0\n\t"
  49830. /* A[0] * B[4] */
  49831. "LDR r8, [%[a]]\n\t"
  49832. "LDR r9, [%[b], #16]\n\t"
  49833. "UMULL r6, r7, r8, r9\n\t"
  49834. "ADDS r4, r4, r6\n\t"
  49835. "ADCS r5, r5, r7\n\t"
  49836. "ADC r3, r3, #0x0\n\t"
  49837. "STR r4, [sp, #16]\n\t"
  49838. /* A[0] * B[5] */
  49839. "LDR r9, [%[b], #20]\n\t"
  49840. "UMULL r6, r7, r8, r9\n\t"
  49841. "ADDS r5, r5, r6\n\t"
  49842. "ADCS r3, r3, r7\n\t"
  49843. "MOV r4, #0x0\n\t"
  49844. "ADC r4, r4, #0x0\n\t"
  49845. /* A[1] * B[4] */
  49846. "LDR r8, [%[a], #4]\n\t"
  49847. "LDR r9, [%[b], #16]\n\t"
  49848. "UMULL r6, r7, r8, r9\n\t"
  49849. "ADDS r5, r5, r6\n\t"
  49850. "ADCS r3, r3, r7\n\t"
  49851. "ADC r4, r4, #0x0\n\t"
  49852. /* A[2] * B[3] */
  49853. "LDR r9, [%[b], #12]\n\t"
  49854. "UMULL r6, r7, r11, r9\n\t"
  49855. "ADDS r5, r5, r6\n\t"
  49856. "ADCS r3, r3, r7\n\t"
  49857. "ADC r4, r4, #0x0\n\t"
  49858. /* A[3] * B[2] */
  49859. "LDR r8, [%[a], #12]\n\t"
  49860. "UMULL r6, r7, r8, r12\n\t"
  49861. "ADDS r5, r5, r6\n\t"
  49862. "ADCS r3, r3, r7\n\t"
  49863. "ADC r4, r4, #0x0\n\t"
  49864. /* A[4] * B[1] */
  49865. "LDR r8, [%[a], #16]\n\t"
  49866. "LDR r9, [%[b], #4]\n\t"
  49867. "UMULL r6, r7, r8, r9\n\t"
  49868. "ADDS r5, r5, r6\n\t"
  49869. "ADCS r3, r3, r7\n\t"
  49870. "ADC r4, r4, #0x0\n\t"
  49871. /* A[5] * B[0] */
  49872. "LDR r8, [%[a], #20]\n\t"
  49873. "LDR r9, [%[b]]\n\t"
  49874. "UMULL r6, r7, r8, r9\n\t"
  49875. "ADDS r5, r5, r6\n\t"
  49876. "ADCS r3, r3, r7\n\t"
  49877. "ADC r4, r4, #0x0\n\t"
  49878. "STR r5, [sp, #20]\n\t"
  49879. /* A[6] * B[0] */
  49880. "LDR r8, [%[a], #24]\n\t"
  49881. "UMULL r6, r7, r8, r9\n\t"
  49882. "ADDS r3, r3, r6\n\t"
  49883. "ADCS r4, r4, r7\n\t"
  49884. "MOV r5, #0x0\n\t"
  49885. "ADC r5, r5, #0x0\n\t"
  49886. /* A[5] * B[1] */
  49887. "LDR r8, [%[a], #20]\n\t"
  49888. "LDR r9, [%[b], #4]\n\t"
  49889. "UMULL r6, r7, r8, r9\n\t"
  49890. "ADDS r3, r3, r6\n\t"
  49891. "ADCS r4, r4, r7\n\t"
  49892. "ADC r5, r5, #0x0\n\t"
  49893. /* A[4] * B[2] */
  49894. "LDR r8, [%[a], #16]\n\t"
  49895. "UMULL r6, r7, r8, r12\n\t"
  49896. "ADDS r3, r3, r6\n\t"
  49897. "ADCS r4, r4, r7\n\t"
  49898. "ADC r5, r5, #0x0\n\t"
  49899. /* A[3] * B[3] */
  49900. "LDR r11, [%[a], #12]\n\t"
  49901. "LDR r12, [%[b], #12]\n\t"
  49902. "UMULL r6, r7, r11, r12\n\t"
  49903. "ADDS r3, r3, r6\n\t"
  49904. "ADCS r4, r4, r7\n\t"
  49905. "ADC r5, r5, #0x0\n\t"
  49906. /* A[2] * B[4] */
  49907. "LDR r8, [%[a], #8]\n\t"
  49908. "LDR r9, [%[b], #16]\n\t"
  49909. "UMULL r6, r7, r8, r9\n\t"
  49910. "ADDS r3, r3, r6\n\t"
  49911. "ADCS r4, r4, r7\n\t"
  49912. "ADC r5, r5, #0x0\n\t"
  49913. /* A[1] * B[5] */
  49914. "LDR r8, [%[a], #4]\n\t"
  49915. "LDR r9, [%[b], #20]\n\t"
  49916. "UMULL r6, r7, r8, r9\n\t"
  49917. "ADDS r3, r3, r6\n\t"
  49918. "ADCS r4, r4, r7\n\t"
  49919. "ADC r5, r5, #0x0\n\t"
  49920. /* A[0] * B[6] */
  49921. "LDR r8, [%[a]]\n\t"
  49922. "LDR r9, [%[b], #24]\n\t"
  49923. "UMULL r6, r7, r8, r9\n\t"
  49924. "ADDS r3, r3, r6\n\t"
  49925. "ADCS r4, r4, r7\n\t"
  49926. "ADC r5, r5, #0x0\n\t"
  49927. "STR r3, [sp, #24]\n\t"
  49928. /* A[0] * B[7] */
  49929. "LDR r9, [%[b], #28]\n\t"
  49930. "UMULL r6, r7, r8, r9\n\t"
  49931. "ADDS r4, r4, r6\n\t"
  49932. "ADCS r5, r5, r7\n\t"
  49933. "MOV r3, #0x0\n\t"
  49934. "ADC r3, r3, #0x0\n\t"
  49935. /* A[1] * B[6] */
  49936. "LDR r8, [%[a], #4]\n\t"
  49937. "LDR r9, [%[b], #24]\n\t"
  49938. "UMULL r6, r7, r8, r9\n\t"
  49939. "ADDS r4, r4, r6\n\t"
  49940. "ADCS r5, r5, r7\n\t"
  49941. "ADC r3, r3, #0x0\n\t"
  49942. /* A[2] * B[5] */
  49943. "LDR r8, [%[a], #8]\n\t"
  49944. "LDR r9, [%[b], #20]\n\t"
  49945. "UMULL r6, r7, r8, r9\n\t"
  49946. "ADDS r4, r4, r6\n\t"
  49947. "ADCS r5, r5, r7\n\t"
  49948. "ADC r3, r3, #0x0\n\t"
  49949. /* A[3] * B[4] */
  49950. "LDR r9, [%[b], #16]\n\t"
  49951. "UMULL r6, r7, r11, r9\n\t"
  49952. "ADDS r4, r4, r6\n\t"
  49953. "ADCS r5, r5, r7\n\t"
  49954. "ADC r3, r3, #0x0\n\t"
  49955. /* A[4] * B[3] */
  49956. "LDR r8, [%[a], #16]\n\t"
  49957. "UMULL r6, r7, r8, r12\n\t"
  49958. "ADDS r4, r4, r6\n\t"
  49959. "ADCS r5, r5, r7\n\t"
  49960. "ADC r3, r3, #0x0\n\t"
  49961. /* A[5] * B[2] */
  49962. "LDR r8, [%[a], #20]\n\t"
  49963. "LDR r9, [%[b], #8]\n\t"
  49964. "UMULL r6, r7, r8, r9\n\t"
  49965. "ADDS r4, r4, r6\n\t"
  49966. "ADCS r5, r5, r7\n\t"
  49967. "ADC r3, r3, #0x0\n\t"
  49968. /* A[6] * B[1] */
  49969. "LDR r8, [%[a], #24]\n\t"
  49970. "LDR r9, [%[b], #4]\n\t"
  49971. "UMULL r6, r7, r8, r9\n\t"
  49972. "ADDS r4, r4, r6\n\t"
  49973. "ADCS r5, r5, r7\n\t"
  49974. "ADC r3, r3, #0x0\n\t"
  49975. /* A[7] * B[0] */
  49976. "LDR r8, [%[a], #28]\n\t"
  49977. "LDR r9, [%[b]]\n\t"
  49978. "UMULL r6, r7, r8, r9\n\t"
  49979. "ADDS r4, r4, r6\n\t"
  49980. "ADCS r5, r5, r7\n\t"
  49981. "ADC r3, r3, #0x0\n\t"
  49982. "STR r4, [sp, #28]\n\t"
  49983. /* A[8] * B[0] */
  49984. "LDR r8, [%[a], #32]\n\t"
  49985. "UMULL r6, r7, r8, r9\n\t"
  49986. "ADDS r5, r5, r6\n\t"
  49987. "ADCS r3, r3, r7\n\t"
  49988. "MOV r4, #0x0\n\t"
  49989. "ADC r4, r4, #0x0\n\t"
  49990. /* A[7] * B[1] */
  49991. "LDR r8, [%[a], #28]\n\t"
  49992. "LDR r9, [%[b], #4]\n\t"
  49993. "UMULL r6, r7, r8, r9\n\t"
  49994. "ADDS r5, r5, r6\n\t"
  49995. "ADCS r3, r3, r7\n\t"
  49996. "ADC r4, r4, #0x0\n\t"
  49997. /* A[6] * B[2] */
  49998. "LDR r8, [%[a], #24]\n\t"
  49999. "LDR r9, [%[b], #8]\n\t"
  50000. "UMULL r6, r7, r8, r9\n\t"
  50001. "ADDS r5, r5, r6\n\t"
  50002. "ADCS r3, r3, r7\n\t"
  50003. "ADC r4, r4, #0x0\n\t"
  50004. /* A[5] * B[3] */
  50005. "LDR r8, [%[a], #20]\n\t"
  50006. "UMULL r6, r7, r8, r12\n\t"
  50007. "ADDS r5, r5, r6\n\t"
  50008. "ADCS r3, r3, r7\n\t"
  50009. "ADC r4, r4, #0x0\n\t"
  50010. /* A[4] * B[4] */
  50011. "LDR r11, [%[a], #16]\n\t"
  50012. "LDR r12, [%[b], #16]\n\t"
  50013. "UMULL r6, r7, r11, r12\n\t"
  50014. "ADDS r5, r5, r6\n\t"
  50015. "ADCS r3, r3, r7\n\t"
  50016. "ADC r4, r4, #0x0\n\t"
  50017. /* A[3] * B[5] */
  50018. "LDR r8, [%[a], #12]\n\t"
  50019. "LDR r9, [%[b], #20]\n\t"
  50020. "UMULL r6, r7, r8, r9\n\t"
  50021. "ADDS r5, r5, r6\n\t"
  50022. "ADCS r3, r3, r7\n\t"
  50023. "ADC r4, r4, #0x0\n\t"
  50024. /* A[2] * B[6] */
  50025. "LDR r8, [%[a], #8]\n\t"
  50026. "LDR r9, [%[b], #24]\n\t"
  50027. "UMULL r6, r7, r8, r9\n\t"
  50028. "ADDS r5, r5, r6\n\t"
  50029. "ADCS r3, r3, r7\n\t"
  50030. "ADC r4, r4, #0x0\n\t"
  50031. /* A[1] * B[7] */
  50032. "LDR r8, [%[a], #4]\n\t"
  50033. "LDR r9, [%[b], #28]\n\t"
  50034. "UMULL r6, r7, r8, r9\n\t"
  50035. "ADDS r5, r5, r6\n\t"
  50036. "ADCS r3, r3, r7\n\t"
  50037. "ADC r4, r4, #0x0\n\t"
  50038. /* A[0] * B[8] */
  50039. "LDR r8, [%[a]]\n\t"
  50040. "LDR r9, [%[b], #32]\n\t"
  50041. "UMULL r6, r7, r8, r9\n\t"
  50042. "ADDS r5, r5, r6\n\t"
  50043. "ADCS r3, r3, r7\n\t"
  50044. "ADC r4, r4, #0x0\n\t"
  50045. "STR r5, [sp, #32]\n\t"
  50046. /* A[0] * B[9] */
  50047. "LDR r9, [%[b], #36]\n\t"
  50048. "UMULL r6, r7, r8, r9\n\t"
  50049. "ADDS r3, r3, r6\n\t"
  50050. "ADCS r4, r4, r7\n\t"
  50051. "MOV r5, #0x0\n\t"
  50052. "ADC r5, r5, #0x0\n\t"
  50053. /* A[1] * B[8] */
  50054. "LDR r8, [%[a], #4]\n\t"
  50055. "LDR r9, [%[b], #32]\n\t"
  50056. "UMULL r6, r7, r8, r9\n\t"
  50057. "ADDS r3, r3, r6\n\t"
  50058. "ADCS r4, r4, r7\n\t"
  50059. "ADC r5, r5, #0x0\n\t"
  50060. /* A[2] * B[7] */
  50061. "LDR r8, [%[a], #8]\n\t"
  50062. "LDR r9, [%[b], #28]\n\t"
  50063. "UMULL r6, r7, r8, r9\n\t"
  50064. "ADDS r3, r3, r6\n\t"
  50065. "ADCS r4, r4, r7\n\t"
  50066. "ADC r5, r5, #0x0\n\t"
  50067. /* A[3] * B[6] */
  50068. "LDR r8, [%[a], #12]\n\t"
  50069. "LDR r9, [%[b], #24]\n\t"
  50070. "UMULL r6, r7, r8, r9\n\t"
  50071. "ADDS r3, r3, r6\n\t"
  50072. "ADCS r4, r4, r7\n\t"
  50073. "ADC r5, r5, #0x0\n\t"
  50074. /* A[4] * B[5] */
  50075. "LDR r9, [%[b], #20]\n\t"
  50076. "UMULL r6, r7, r11, r9\n\t"
  50077. "ADDS r3, r3, r6\n\t"
  50078. "ADCS r4, r4, r7\n\t"
  50079. "ADC r5, r5, #0x0\n\t"
  50080. /* A[5] * B[4] */
  50081. "LDR r8, [%[a], #20]\n\t"
  50082. "UMULL r6, r7, r8, r12\n\t"
  50083. "ADDS r3, r3, r6\n\t"
  50084. "ADCS r4, r4, r7\n\t"
  50085. "ADC r5, r5, #0x0\n\t"
  50086. /* A[6] * B[3] */
  50087. "LDR r8, [%[a], #24]\n\t"
  50088. "LDR r9, [%[b], #12]\n\t"
  50089. "UMULL r6, r7, r8, r9\n\t"
  50090. "ADDS r3, r3, r6\n\t"
  50091. "ADCS r4, r4, r7\n\t"
  50092. "ADC r5, r5, #0x0\n\t"
  50093. /* A[7] * B[2] */
  50094. "LDR r8, [%[a], #28]\n\t"
  50095. "LDR r9, [%[b], #8]\n\t"
  50096. "UMULL r6, r7, r8, r9\n\t"
  50097. "ADDS r3, r3, r6\n\t"
  50098. "ADCS r4, r4, r7\n\t"
  50099. "ADC r5, r5, #0x0\n\t"
  50100. /* A[8] * B[1] */
  50101. "LDR r8, [%[a], #32]\n\t"
  50102. "LDR r9, [%[b], #4]\n\t"
  50103. "UMULL r6, r7, r8, r9\n\t"
  50104. "ADDS r3, r3, r6\n\t"
  50105. "ADCS r4, r4, r7\n\t"
  50106. "ADC r5, r5, #0x0\n\t"
  50107. /* A[9] * B[0] */
  50108. "LDR r8, [%[a], #36]\n\t"
  50109. "LDR r9, [%[b]]\n\t"
  50110. "UMULL r6, r7, r8, r9\n\t"
  50111. "ADDS r3, r3, r6\n\t"
  50112. "ADCS r4, r4, r7\n\t"
  50113. "ADC r5, r5, #0x0\n\t"
  50114. "STR r3, [sp, #36]\n\t"
  50115. /* A[10] * B[0] */
  50116. "LDR r8, [%[a], #40]\n\t"
  50117. "UMULL r6, r7, r8, r9\n\t"
  50118. "ADDS r4, r4, r6\n\t"
  50119. "ADCS r5, r5, r7\n\t"
  50120. "MOV r3, #0x0\n\t"
  50121. "ADC r3, r3, #0x0\n\t"
  50122. /* A[9] * B[1] */
  50123. "LDR r8, [%[a], #36]\n\t"
  50124. "LDR r9, [%[b], #4]\n\t"
  50125. "UMULL r6, r7, r8, r9\n\t"
  50126. "ADDS r4, r4, r6\n\t"
  50127. "ADCS r5, r5, r7\n\t"
  50128. "ADC r3, r3, #0x0\n\t"
  50129. /* A[8] * B[2] */
  50130. "LDR r8, [%[a], #32]\n\t"
  50131. "LDR r9, [%[b], #8]\n\t"
  50132. "UMULL r6, r7, r8, r9\n\t"
  50133. "ADDS r4, r4, r6\n\t"
  50134. "ADCS r5, r5, r7\n\t"
  50135. "ADC r3, r3, #0x0\n\t"
  50136. /* A[7] * B[3] */
  50137. "LDR r8, [%[a], #28]\n\t"
  50138. "LDR r9, [%[b], #12]\n\t"
  50139. "UMULL r6, r7, r8, r9\n\t"
  50140. "ADDS r4, r4, r6\n\t"
  50141. "ADCS r5, r5, r7\n\t"
  50142. "ADC r3, r3, #0x0\n\t"
  50143. /* A[6] * B[4] */
  50144. "LDR r8, [%[a], #24]\n\t"
  50145. "UMULL r6, r7, r8, r12\n\t"
  50146. "ADDS r4, r4, r6\n\t"
  50147. "ADCS r5, r5, r7\n\t"
  50148. "ADC r3, r3, #0x0\n\t"
  50149. /* A[5] * B[5] */
  50150. "LDR r11, [%[a], #20]\n\t"
  50151. "LDR r12, [%[b], #20]\n\t"
  50152. "UMULL r6, r7, r11, r12\n\t"
  50153. "ADDS r4, r4, r6\n\t"
  50154. "ADCS r5, r5, r7\n\t"
  50155. "ADC r3, r3, #0x0\n\t"
  50156. /* A[4] * B[6] */
  50157. "LDR r8, [%[a], #16]\n\t"
  50158. "LDR r9, [%[b], #24]\n\t"
  50159. "UMULL r6, r7, r8, r9\n\t"
  50160. "ADDS r4, r4, r6\n\t"
  50161. "ADCS r5, r5, r7\n\t"
  50162. "ADC r3, r3, #0x0\n\t"
  50163. /* A[3] * B[7] */
  50164. "LDR r8, [%[a], #12]\n\t"
  50165. "LDR r9, [%[b], #28]\n\t"
  50166. "UMULL r6, r7, r8, r9\n\t"
  50167. "ADDS r4, r4, r6\n\t"
  50168. "ADCS r5, r5, r7\n\t"
  50169. "ADC r3, r3, #0x0\n\t"
  50170. /* A[2] * B[8] */
  50171. "LDR r8, [%[a], #8]\n\t"
  50172. "LDR r9, [%[b], #32]\n\t"
  50173. "UMULL r6, r7, r8, r9\n\t"
  50174. "ADDS r4, r4, r6\n\t"
  50175. "ADCS r5, r5, r7\n\t"
  50176. "ADC r3, r3, #0x0\n\t"
  50177. /* A[1] * B[9] */
  50178. "LDR r8, [%[a], #4]\n\t"
  50179. "LDR r9, [%[b], #36]\n\t"
  50180. "UMULL r6, r7, r8, r9\n\t"
  50181. "ADDS r4, r4, r6\n\t"
  50182. "ADCS r5, r5, r7\n\t"
  50183. "ADC r3, r3, #0x0\n\t"
  50184. /* A[0] * B[10] */
  50185. "LDR r8, [%[a]]\n\t"
  50186. "LDR r9, [%[b], #40]\n\t"
  50187. "UMULL r6, r7, r8, r9\n\t"
  50188. "ADDS r4, r4, r6\n\t"
  50189. "ADCS r5, r5, r7\n\t"
  50190. "ADC r3, r3, #0x0\n\t"
  50191. "STR r4, [sp, #40]\n\t"
  50192. /* A[0] * B[11] */
  50193. "LDR r9, [%[b], #44]\n\t"
  50194. "UMULL r6, r7, r8, r9\n\t"
  50195. "ADDS r5, r5, r6\n\t"
  50196. "ADCS r3, r3, r7\n\t"
  50197. "MOV r4, #0x0\n\t"
  50198. "ADC r4, r4, #0x0\n\t"
  50199. /* A[1] * B[10] */
  50200. "LDR r8, [%[a], #4]\n\t"
  50201. "LDR r9, [%[b], #40]\n\t"
  50202. "UMULL r6, r7, r8, r9\n\t"
  50203. "ADDS r5, r5, r6\n\t"
  50204. "ADCS r3, r3, r7\n\t"
  50205. "ADC r4, r4, #0x0\n\t"
  50206. /* A[2] * B[9] */
  50207. "LDR r8, [%[a], #8]\n\t"
  50208. "LDR r9, [%[b], #36]\n\t"
  50209. "UMULL r6, r7, r8, r9\n\t"
  50210. "ADDS r5, r5, r6\n\t"
  50211. "ADCS r3, r3, r7\n\t"
  50212. "ADC r4, r4, #0x0\n\t"
  50213. /* A[3] * B[8] */
  50214. "LDR r8, [%[a], #12]\n\t"
  50215. "LDR r9, [%[b], #32]\n\t"
  50216. "UMULL r6, r7, r8, r9\n\t"
  50217. "ADDS r5, r5, r6\n\t"
  50218. "ADCS r3, r3, r7\n\t"
  50219. "ADC r4, r4, #0x0\n\t"
  50220. /* A[4] * B[7] */
  50221. "LDR r8, [%[a], #16]\n\t"
  50222. "LDR r9, [%[b], #28]\n\t"
  50223. "UMULL r6, r7, r8, r9\n\t"
  50224. "ADDS r5, r5, r6\n\t"
  50225. "ADCS r3, r3, r7\n\t"
  50226. "ADC r4, r4, #0x0\n\t"
  50227. /* A[5] * B[6] */
  50228. "LDR r9, [%[b], #24]\n\t"
  50229. "UMULL r6, r7, r11, r9\n\t"
  50230. "ADDS r5, r5, r6\n\t"
  50231. "ADCS r3, r3, r7\n\t"
  50232. "ADC r4, r4, #0x0\n\t"
  50233. /* A[6] * B[5] */
  50234. "LDR r8, [%[a], #24]\n\t"
  50235. "UMULL r6, r7, r8, r12\n\t"
  50236. "ADDS r5, r5, r6\n\t"
  50237. "ADCS r3, r3, r7\n\t"
  50238. "ADC r4, r4, #0x0\n\t"
  50239. /* A[7] * B[4] */
  50240. "LDR r8, [%[a], #28]\n\t"
  50241. "LDR r9, [%[b], #16]\n\t"
  50242. "UMULL r6, r7, r8, r9\n\t"
  50243. "ADDS r5, r5, r6\n\t"
  50244. "ADCS r3, r3, r7\n\t"
  50245. "ADC r4, r4, #0x0\n\t"
  50246. /* A[8] * B[3] */
  50247. "LDR r8, [%[a], #32]\n\t"
  50248. "LDR r9, [%[b], #12]\n\t"
  50249. "UMULL r6, r7, r8, r9\n\t"
  50250. "ADDS r5, r5, r6\n\t"
  50251. "ADCS r3, r3, r7\n\t"
  50252. "ADC r4, r4, #0x0\n\t"
  50253. /* A[9] * B[2] */
  50254. "LDR r8, [%[a], #36]\n\t"
  50255. "LDR r9, [%[b], #8]\n\t"
  50256. "UMULL r6, r7, r8, r9\n\t"
  50257. "ADDS r5, r5, r6\n\t"
  50258. "ADCS r3, r3, r7\n\t"
  50259. "ADC r4, r4, #0x0\n\t"
  50260. /* A[10] * B[1] */
  50261. "LDR r8, [%[a], #40]\n\t"
  50262. "LDR r9, [%[b], #4]\n\t"
  50263. "UMULL r6, r7, r8, r9\n\t"
  50264. "ADDS r5, r5, r6\n\t"
  50265. "ADCS r3, r3, r7\n\t"
  50266. "ADC r4, r4, #0x0\n\t"
  50267. /* A[11] * B[0] */
  50268. "LDR r8, [%[a], #44]\n\t"
  50269. "LDR r9, [%[b]]\n\t"
  50270. "UMULL r6, r7, r8, r9\n\t"
  50271. "ADDS r5, r5, r6\n\t"
  50272. "ADCS r3, r3, r7\n\t"
  50273. "ADC r4, r4, #0x0\n\t"
  50274. "STR r5, [sp, #44]\n\t"
  50275. /* A[12] * B[0] */
  50276. "LDR r8, [%[a], #48]\n\t"
  50277. "UMULL r6, r7, r8, r9\n\t"
  50278. "ADDS r3, r3, r6\n\t"
  50279. "ADCS r4, r4, r7\n\t"
  50280. "MOV r5, #0x0\n\t"
  50281. "ADC r5, r5, #0x0\n\t"
  50282. /* A[11] * B[1] */
  50283. "LDR r8, [%[a], #44]\n\t"
  50284. "LDR r9, [%[b], #4]\n\t"
  50285. "UMULL r6, r7, r8, r9\n\t"
  50286. "ADDS r3, r3, r6\n\t"
  50287. "ADCS r4, r4, r7\n\t"
  50288. "ADC r5, r5, #0x0\n\t"
  50289. /* A[10] * B[2] */
  50290. "LDR r8, [%[a], #40]\n\t"
  50291. "LDR r9, [%[b], #8]\n\t"
  50292. "UMULL r6, r7, r8, r9\n\t"
  50293. "ADDS r3, r3, r6\n\t"
  50294. "ADCS r4, r4, r7\n\t"
  50295. "ADC r5, r5, #0x0\n\t"
  50296. /* A[9] * B[3] */
  50297. "LDR r8, [%[a], #36]\n\t"
  50298. "LDR r9, [%[b], #12]\n\t"
  50299. "UMULL r6, r7, r8, r9\n\t"
  50300. "ADDS r3, r3, r6\n\t"
  50301. "ADCS r4, r4, r7\n\t"
  50302. "ADC r5, r5, #0x0\n\t"
  50303. /* A[8] * B[4] */
  50304. "LDR r8, [%[a], #32]\n\t"
  50305. "LDR r9, [%[b], #16]\n\t"
  50306. "UMULL r6, r7, r8, r9\n\t"
  50307. "ADDS r3, r3, r6\n\t"
  50308. "ADCS r4, r4, r7\n\t"
  50309. "ADC r5, r5, #0x0\n\t"
  50310. /* A[7] * B[5] */
  50311. "LDR r8, [%[a], #28]\n\t"
  50312. "UMULL r6, r7, r8, r12\n\t"
  50313. "ADDS r3, r3, r6\n\t"
  50314. "ADCS r4, r4, r7\n\t"
  50315. "ADC r5, r5, #0x0\n\t"
  50316. /* A[6] * B[6] */
  50317. "LDR r11, [%[a], #24]\n\t"
  50318. "LDR r12, [%[b], #24]\n\t"
  50319. "UMULL r6, r7, r11, r12\n\t"
  50320. "ADDS r3, r3, r6\n\t"
  50321. "ADCS r4, r4, r7\n\t"
  50322. "ADC r5, r5, #0x0\n\t"
  50323. /* A[5] * B[7] */
  50324. "LDR r8, [%[a], #20]\n\t"
  50325. "LDR r9, [%[b], #28]\n\t"
  50326. "UMULL r6, r7, r8, r9\n\t"
  50327. "ADDS r3, r3, r6\n\t"
  50328. "ADCS r4, r4, r7\n\t"
  50329. "ADC r5, r5, #0x0\n\t"
  50330. /* A[4] * B[8] */
  50331. "LDR r8, [%[a], #16]\n\t"
  50332. "LDR r9, [%[b], #32]\n\t"
  50333. "UMULL r6, r7, r8, r9\n\t"
  50334. "ADDS r3, r3, r6\n\t"
  50335. "ADCS r4, r4, r7\n\t"
  50336. "ADC r5, r5, #0x0\n\t"
  50337. /* A[3] * B[9] */
  50338. "LDR r8, [%[a], #12]\n\t"
  50339. "LDR r9, [%[b], #36]\n\t"
  50340. "UMULL r6, r7, r8, r9\n\t"
  50341. "ADDS r3, r3, r6\n\t"
  50342. "ADCS r4, r4, r7\n\t"
  50343. "ADC r5, r5, #0x0\n\t"
  50344. /* A[2] * B[10] */
  50345. "LDR r8, [%[a], #8]\n\t"
  50346. "LDR r9, [%[b], #40]\n\t"
  50347. "UMULL r6, r7, r8, r9\n\t"
  50348. "ADDS r3, r3, r6\n\t"
  50349. "ADCS r4, r4, r7\n\t"
  50350. "ADC r5, r5, #0x0\n\t"
  50351. /* A[1] * B[11] */
  50352. "LDR r8, [%[a], #4]\n\t"
  50353. "LDR r9, [%[b], #44]\n\t"
  50354. "UMULL r6, r7, r8, r9\n\t"
  50355. "ADDS r3, r3, r6\n\t"
  50356. "ADCS r4, r4, r7\n\t"
  50357. "ADC r5, r5, #0x0\n\t"
  50358. /* A[0] * B[12] */
  50359. "LDR r8, [%[a]]\n\t"
  50360. "LDR r9, [%[b], #48]\n\t"
  50361. "UMULL r6, r7, r8, r9\n\t"
  50362. "ADDS r3, r3, r6\n\t"
  50363. "ADCS r4, r4, r7\n\t"
  50364. "ADC r5, r5, #0x0\n\t"
  50365. "STR r3, [sp, #48]\n\t"
  50366. /* A[0] * B[13] */
  50367. "LDR r9, [%[b], #52]\n\t"
  50368. "UMULL r6, r7, r8, r9\n\t"
  50369. "ADDS r4, r4, r6\n\t"
  50370. "ADCS r5, r5, r7\n\t"
  50371. "MOV r3, #0x0\n\t"
  50372. "ADC r3, r3, #0x0\n\t"
  50373. /* A[1] * B[12] */
  50374. "LDR r8, [%[a], #4]\n\t"
  50375. "LDR r9, [%[b], #48]\n\t"
  50376. "UMULL r6, r7, r8, r9\n\t"
  50377. "ADDS r4, r4, r6\n\t"
  50378. "ADCS r5, r5, r7\n\t"
  50379. "ADC r3, r3, #0x0\n\t"
  50380. /* A[2] * B[11] */
  50381. "LDR r8, [%[a], #8]\n\t"
  50382. "LDR r9, [%[b], #44]\n\t"
  50383. "UMULL r6, r7, r8, r9\n\t"
  50384. "ADDS r4, r4, r6\n\t"
  50385. "ADCS r5, r5, r7\n\t"
  50386. "ADC r3, r3, #0x0\n\t"
  50387. /* A[3] * B[10] */
  50388. "LDR r8, [%[a], #12]\n\t"
  50389. "LDR r9, [%[b], #40]\n\t"
  50390. "UMULL r6, r7, r8, r9\n\t"
  50391. "ADDS r4, r4, r6\n\t"
  50392. "ADCS r5, r5, r7\n\t"
  50393. "ADC r3, r3, #0x0\n\t"
  50394. /* A[4] * B[9] */
  50395. "LDR r8, [%[a], #16]\n\t"
  50396. "LDR r9, [%[b], #36]\n\t"
  50397. "UMULL r6, r7, r8, r9\n\t"
  50398. "ADDS r4, r4, r6\n\t"
  50399. "ADCS r5, r5, r7\n\t"
  50400. "ADC r3, r3, #0x0\n\t"
  50401. /* A[5] * B[8] */
  50402. "LDR r8, [%[a], #20]\n\t"
  50403. "LDR r9, [%[b], #32]\n\t"
  50404. "UMULL r6, r7, r8, r9\n\t"
  50405. "ADDS r4, r4, r6\n\t"
  50406. "ADCS r5, r5, r7\n\t"
  50407. "ADC r3, r3, #0x0\n\t"
  50408. /* A[6] * B[7] */
  50409. "LDR r9, [%[b], #28]\n\t"
  50410. "UMULL r6, r7, r11, r9\n\t"
  50411. "ADDS r4, r4, r6\n\t"
  50412. "ADCS r5, r5, r7\n\t"
  50413. "ADC r3, r3, #0x0\n\t"
  50414. /* A[7] * B[6] */
  50415. "LDR r8, [%[a], #28]\n\t"
  50416. "UMULL r6, r7, r8, r12\n\t"
  50417. "ADDS r4, r4, r6\n\t"
  50418. "ADCS r5, r5, r7\n\t"
  50419. "ADC r3, r3, #0x0\n\t"
  50420. /* A[8] * B[5] */
  50421. "LDR r8, [%[a], #32]\n\t"
  50422. "LDR r9, [%[b], #20]\n\t"
  50423. "UMULL r6, r7, r8, r9\n\t"
  50424. "ADDS r4, r4, r6\n\t"
  50425. "ADCS r5, r5, r7\n\t"
  50426. "ADC r3, r3, #0x0\n\t"
  50427. /* A[9] * B[4] */
  50428. "LDR r8, [%[a], #36]\n\t"
  50429. "LDR r9, [%[b], #16]\n\t"
  50430. "UMULL r6, r7, r8, r9\n\t"
  50431. "ADDS r4, r4, r6\n\t"
  50432. "ADCS r5, r5, r7\n\t"
  50433. "ADC r3, r3, #0x0\n\t"
  50434. /* A[10] * B[3] */
  50435. "LDR r8, [%[a], #40]\n\t"
  50436. "LDR r9, [%[b], #12]\n\t"
  50437. "UMULL r6, r7, r8, r9\n\t"
  50438. "ADDS r4, r4, r6\n\t"
  50439. "ADCS r5, r5, r7\n\t"
  50440. "ADC r3, r3, #0x0\n\t"
  50441. /* A[11] * B[2] */
  50442. "LDR r8, [%[a], #44]\n\t"
  50443. "LDR r9, [%[b], #8]\n\t"
  50444. "UMULL r6, r7, r8, r9\n\t"
  50445. "ADDS r4, r4, r6\n\t"
  50446. "ADCS r5, r5, r7\n\t"
  50447. "ADC r3, r3, #0x0\n\t"
  50448. /* A[12] * B[1] */
  50449. "LDR r8, [%[a], #48]\n\t"
  50450. "LDR r9, [%[b], #4]\n\t"
  50451. "UMULL r6, r7, r8, r9\n\t"
  50452. "ADDS r4, r4, r6\n\t"
  50453. "ADCS r5, r5, r7\n\t"
  50454. "ADC r3, r3, #0x0\n\t"
  50455. /* A[13] * B[0] */
  50456. "LDR r8, [%[a], #52]\n\t"
  50457. "LDR r9, [%[b]]\n\t"
  50458. "UMULL r6, r7, r8, r9\n\t"
  50459. "ADDS r4, r4, r6\n\t"
  50460. "ADCS r5, r5, r7\n\t"
  50461. "ADC r3, r3, #0x0\n\t"
  50462. "STR r4, [sp, #52]\n\t"
  50463. /* A[14] * B[0] */
  50464. "LDR r8, [%[a], #56]\n\t"
  50465. "UMULL r6, r7, r8, r9\n\t"
  50466. "ADDS r5, r5, r6\n\t"
  50467. "ADCS r3, r3, r7\n\t"
  50468. "MOV r4, #0x0\n\t"
  50469. "ADC r4, r4, #0x0\n\t"
  50470. /* A[13] * B[1] */
  50471. "LDR r8, [%[a], #52]\n\t"
  50472. "LDR r9, [%[b], #4]\n\t"
  50473. "UMULL r6, r7, r8, r9\n\t"
  50474. "ADDS r5, r5, r6\n\t"
  50475. "ADCS r3, r3, r7\n\t"
  50476. "ADC r4, r4, #0x0\n\t"
  50477. /* A[12] * B[2] */
  50478. "LDR r8, [%[a], #48]\n\t"
  50479. "LDR r9, [%[b], #8]\n\t"
  50480. "UMULL r6, r7, r8, r9\n\t"
  50481. "ADDS r5, r5, r6\n\t"
  50482. "ADCS r3, r3, r7\n\t"
  50483. "ADC r4, r4, #0x0\n\t"
  50484. /* A[11] * B[3] */
  50485. "LDR r8, [%[a], #44]\n\t"
  50486. "LDR r9, [%[b], #12]\n\t"
  50487. "UMULL r6, r7, r8, r9\n\t"
  50488. "ADDS r5, r5, r6\n\t"
  50489. "ADCS r3, r3, r7\n\t"
  50490. "ADC r4, r4, #0x0\n\t"
  50491. /* A[10] * B[4] */
  50492. "LDR r8, [%[a], #40]\n\t"
  50493. "LDR r9, [%[b], #16]\n\t"
  50494. "UMULL r6, r7, r8, r9\n\t"
  50495. "ADDS r5, r5, r6\n\t"
  50496. "ADCS r3, r3, r7\n\t"
  50497. "ADC r4, r4, #0x0\n\t"
  50498. /* A[9] * B[5] */
  50499. "LDR r8, [%[a], #36]\n\t"
  50500. "LDR r9, [%[b], #20]\n\t"
  50501. "UMULL r6, r7, r8, r9\n\t"
  50502. "ADDS r5, r5, r6\n\t"
  50503. "ADCS r3, r3, r7\n\t"
  50504. "ADC r4, r4, #0x0\n\t"
  50505. /* A[8] * B[6] */
  50506. "LDR r8, [%[a], #32]\n\t"
  50507. "UMULL r6, r7, r8, r12\n\t"
  50508. "ADDS r5, r5, r6\n\t"
  50509. "ADCS r3, r3, r7\n\t"
  50510. "ADC r4, r4, #0x0\n\t"
  50511. /* A[7] * B[7] */
  50512. "LDR r11, [%[a], #28]\n\t"
  50513. "LDR r12, [%[b], #28]\n\t"
  50514. "UMULL r6, r7, r11, r12\n\t"
  50515. "ADDS r5, r5, r6\n\t"
  50516. "ADCS r3, r3, r7\n\t"
  50517. "ADC r4, r4, #0x0\n\t"
  50518. /* A[6] * B[8] */
  50519. "LDR r8, [%[a], #24]\n\t"
  50520. "LDR r9, [%[b], #32]\n\t"
  50521. "UMULL r6, r7, r8, r9\n\t"
  50522. "ADDS r5, r5, r6\n\t"
  50523. "ADCS r3, r3, r7\n\t"
  50524. "ADC r4, r4, #0x0\n\t"
  50525. /* A[5] * B[9] */
  50526. "LDR r8, [%[a], #20]\n\t"
  50527. "LDR r9, [%[b], #36]\n\t"
  50528. "UMULL r6, r7, r8, r9\n\t"
  50529. "ADDS r5, r5, r6\n\t"
  50530. "ADCS r3, r3, r7\n\t"
  50531. "ADC r4, r4, #0x0\n\t"
  50532. /* A[4] * B[10] */
  50533. "LDR r8, [%[a], #16]\n\t"
  50534. "LDR r9, [%[b], #40]\n\t"
  50535. "UMULL r6, r7, r8, r9\n\t"
  50536. "ADDS r5, r5, r6\n\t"
  50537. "ADCS r3, r3, r7\n\t"
  50538. "ADC r4, r4, #0x0\n\t"
  50539. /* A[3] * B[11] */
  50540. "LDR r8, [%[a], #12]\n\t"
  50541. "LDR r9, [%[b], #44]\n\t"
  50542. "UMULL r6, r7, r8, r9\n\t"
  50543. "ADDS r5, r5, r6\n\t"
  50544. "ADCS r3, r3, r7\n\t"
  50545. "ADC r4, r4, #0x0\n\t"
  50546. /* A[2] * B[12] */
  50547. "LDR r8, [%[a], #8]\n\t"
  50548. "LDR r9, [%[b], #48]\n\t"
  50549. "UMULL r6, r7, r8, r9\n\t"
  50550. "ADDS r5, r5, r6\n\t"
  50551. "ADCS r3, r3, r7\n\t"
  50552. "ADC r4, r4, #0x0\n\t"
  50553. /* A[1] * B[13] */
  50554. "LDR r8, [%[a], #4]\n\t"
  50555. "LDR r9, [%[b], #52]\n\t"
  50556. "UMULL r6, r7, r8, r9\n\t"
  50557. "ADDS r5, r5, r6\n\t"
  50558. "ADCS r3, r3, r7\n\t"
  50559. "ADC r4, r4, #0x0\n\t"
  50560. /* A[0] * B[14] */
  50561. "LDR r8, [%[a]]\n\t"
  50562. "LDR r9, [%[b], #56]\n\t"
  50563. "UMULL r6, r7, r8, r9\n\t"
  50564. "ADDS r5, r5, r6\n\t"
  50565. "ADCS r3, r3, r7\n\t"
  50566. "ADC r4, r4, #0x0\n\t"
  50567. "STR r5, [sp, #56]\n\t"
  50568. /* A[0] * B[15] */
  50569. "LDR r9, [%[b], #60]\n\t"
  50570. "UMULL r6, r7, r8, r9\n\t"
  50571. "ADDS r3, r3, r6\n\t"
  50572. "ADCS r4, r4, r7\n\t"
  50573. "MOV r5, #0x0\n\t"
  50574. "ADC r5, r5, #0x0\n\t"
  50575. /* A[1] * B[14] */
  50576. "LDR r8, [%[a], #4]\n\t"
  50577. "LDR r9, [%[b], #56]\n\t"
  50578. "UMULL r6, r7, r8, r9\n\t"
  50579. "ADDS r3, r3, r6\n\t"
  50580. "ADCS r4, r4, r7\n\t"
  50581. "ADC r5, r5, #0x0\n\t"
  50582. /* A[2] * B[13] */
  50583. "LDR r8, [%[a], #8]\n\t"
  50584. "LDR r9, [%[b], #52]\n\t"
  50585. "UMULL r6, r7, r8, r9\n\t"
  50586. "ADDS r3, r3, r6\n\t"
  50587. "ADCS r4, r4, r7\n\t"
  50588. "ADC r5, r5, #0x0\n\t"
  50589. /* A[3] * B[12] */
  50590. "LDR r8, [%[a], #12]\n\t"
  50591. "LDR r9, [%[b], #48]\n\t"
  50592. "UMULL r6, r7, r8, r9\n\t"
  50593. "ADDS r3, r3, r6\n\t"
  50594. "ADCS r4, r4, r7\n\t"
  50595. "ADC r5, r5, #0x0\n\t"
  50596. /* A[4] * B[11] */
  50597. "LDR r8, [%[a], #16]\n\t"
  50598. "LDR r9, [%[b], #44]\n\t"
  50599. "UMULL r6, r7, r8, r9\n\t"
  50600. "ADDS r3, r3, r6\n\t"
  50601. "ADCS r4, r4, r7\n\t"
  50602. "ADC r5, r5, #0x0\n\t"
  50603. /* A[5] * B[10] */
  50604. "LDR r8, [%[a], #20]\n\t"
  50605. "LDR r9, [%[b], #40]\n\t"
  50606. "UMULL r6, r7, r8, r9\n\t"
  50607. "ADDS r3, r3, r6\n\t"
  50608. "ADCS r4, r4, r7\n\t"
  50609. "ADC r5, r5, #0x0\n\t"
  50610. /* A[6] * B[9] */
  50611. "LDR r8, [%[a], #24]\n\t"
  50612. "LDR r9, [%[b], #36]\n\t"
  50613. "UMULL r6, r7, r8, r9\n\t"
  50614. "ADDS r3, r3, r6\n\t"
  50615. "ADCS r4, r4, r7\n\t"
  50616. "ADC r5, r5, #0x0\n\t"
  50617. /* A[7] * B[8] */
  50618. "LDR r9, [%[b], #32]\n\t"
  50619. "UMULL r6, r7, r11, r9\n\t"
  50620. "ADDS r3, r3, r6\n\t"
  50621. "ADCS r4, r4, r7\n\t"
  50622. "ADC r5, r5, #0x0\n\t"
  50623. /* A[8] * B[7] */
  50624. "LDR r8, [%[a], #32]\n\t"
  50625. "UMULL r6, r7, r8, r12\n\t"
  50626. "ADDS r3, r3, r6\n\t"
  50627. "ADCS r4, r4, r7\n\t"
  50628. "ADC r5, r5, #0x0\n\t"
  50629. /* A[9] * B[6] */
  50630. "LDR r8, [%[a], #36]\n\t"
  50631. "LDR r9, [%[b], #24]\n\t"
  50632. "UMULL r6, r7, r8, r9\n\t"
  50633. "ADDS r3, r3, r6\n\t"
  50634. "ADCS r4, r4, r7\n\t"
  50635. "ADC r5, r5, #0x0\n\t"
  50636. /* A[10] * B[5] */
  50637. "LDR r8, [%[a], #40]\n\t"
  50638. "LDR r9, [%[b], #20]\n\t"
  50639. "UMULL r6, r7, r8, r9\n\t"
  50640. "ADDS r3, r3, r6\n\t"
  50641. "ADCS r4, r4, r7\n\t"
  50642. "ADC r5, r5, #0x0\n\t"
  50643. /* A[11] * B[4] */
  50644. "LDR r8, [%[a], #44]\n\t"
  50645. "LDR r9, [%[b], #16]\n\t"
  50646. "UMULL r6, r7, r8, r9\n\t"
  50647. "ADDS r3, r3, r6\n\t"
  50648. "ADCS r4, r4, r7\n\t"
  50649. "ADC r5, r5, #0x0\n\t"
  50650. /* A[12] * B[3] */
  50651. "LDR r8, [%[a], #48]\n\t"
  50652. "LDR r9, [%[b], #12]\n\t"
  50653. "UMULL r6, r7, r8, r9\n\t"
  50654. "ADDS r3, r3, r6\n\t"
  50655. "ADCS r4, r4, r7\n\t"
  50656. "ADC r5, r5, #0x0\n\t"
  50657. /* A[13] * B[2] */
  50658. "LDR r8, [%[a], #52]\n\t"
  50659. "LDR r9, [%[b], #8]\n\t"
  50660. "UMULL r6, r7, r8, r9\n\t"
  50661. "ADDS r3, r3, r6\n\t"
  50662. "ADCS r4, r4, r7\n\t"
  50663. "ADC r5, r5, #0x0\n\t"
  50664. /* A[14] * B[1] */
  50665. "LDR r8, [%[a], #56]\n\t"
  50666. "LDR r9, [%[b], #4]\n\t"
  50667. "UMULL r6, r7, r8, r9\n\t"
  50668. "ADDS r3, r3, r6\n\t"
  50669. "ADCS r4, r4, r7\n\t"
  50670. "ADC r5, r5, #0x0\n\t"
  50671. /* A[15] * B[0] */
  50672. "LDR r8, [%[a], #60]\n\t"
  50673. "LDR r9, [%[b]]\n\t"
  50674. "UMULL r6, r7, r8, r9\n\t"
  50675. "ADDS r3, r3, r6\n\t"
  50676. "ADCS r4, r4, r7\n\t"
  50677. "ADC r5, r5, #0x0\n\t"
  50678. "STR r3, [sp, #60]\n\t"
  50679. /* A[16] * B[0] */
  50680. "LDR r8, [%[a], #64]\n\t"
  50681. "UMULL r6, r7, r8, r9\n\t"
  50682. "ADDS r4, r4, r6\n\t"
  50683. "ADCS r5, r5, r7\n\t"
  50684. "MOV r3, #0x0\n\t"
  50685. "ADC r3, r3, #0x0\n\t"
  50686. /* A[15] * B[1] */
  50687. "LDR r8, [%[a], #60]\n\t"
  50688. "LDR r9, [%[b], #4]\n\t"
  50689. "UMULL r6, r7, r8, r9\n\t"
  50690. "ADDS r4, r4, r6\n\t"
  50691. "ADCS r5, r5, r7\n\t"
  50692. "ADC r3, r3, #0x0\n\t"
  50693. /* A[14] * B[2] */
  50694. "LDR r8, [%[a], #56]\n\t"
  50695. "LDR r9, [%[b], #8]\n\t"
  50696. "UMULL r6, r7, r8, r9\n\t"
  50697. "ADDS r4, r4, r6\n\t"
  50698. "ADCS r5, r5, r7\n\t"
  50699. "ADC r3, r3, #0x0\n\t"
  50700. /* A[13] * B[3] */
  50701. "LDR r8, [%[a], #52]\n\t"
  50702. "LDR r9, [%[b], #12]\n\t"
  50703. "UMULL r6, r7, r8, r9\n\t"
  50704. "ADDS r4, r4, r6\n\t"
  50705. "ADCS r5, r5, r7\n\t"
  50706. "ADC r3, r3, #0x0\n\t"
  50707. /* A[12] * B[4] */
  50708. "LDR r8, [%[a], #48]\n\t"
  50709. "LDR r9, [%[b], #16]\n\t"
  50710. "UMULL r6, r7, r8, r9\n\t"
  50711. "ADDS r4, r4, r6\n\t"
  50712. "ADCS r5, r5, r7\n\t"
  50713. "ADC r3, r3, #0x0\n\t"
  50714. /* A[11] * B[5] */
  50715. "LDR r8, [%[a], #44]\n\t"
  50716. "LDR r9, [%[b], #20]\n\t"
  50717. "UMULL r6, r7, r8, r9\n\t"
  50718. "ADDS r4, r4, r6\n\t"
  50719. "ADCS r5, r5, r7\n\t"
  50720. "ADC r3, r3, #0x0\n\t"
  50721. /* A[10] * B[6] */
  50722. "LDR r8, [%[a], #40]\n\t"
  50723. "LDR r9, [%[b], #24]\n\t"
  50724. "UMULL r6, r7, r8, r9\n\t"
  50725. "ADDS r4, r4, r6\n\t"
  50726. "ADCS r5, r5, r7\n\t"
  50727. "ADC r3, r3, #0x0\n\t"
  50728. /* A[9] * B[7] */
  50729. "LDR r8, [%[a], #36]\n\t"
  50730. "UMULL r6, r7, r8, r12\n\t"
  50731. "ADDS r4, r4, r6\n\t"
  50732. "ADCS r5, r5, r7\n\t"
  50733. "ADC r3, r3, #0x0\n\t"
  50734. /* A[8] * B[8] */
  50735. "LDR r11, [%[a], #32]\n\t"
  50736. "LDR r12, [%[b], #32]\n\t"
  50737. "UMULL r6, r7, r11, r12\n\t"
  50738. "ADDS r4, r4, r6\n\t"
  50739. "ADCS r5, r5, r7\n\t"
  50740. "ADC r3, r3, #0x0\n\t"
  50741. /* A[7] * B[9] */
  50742. "LDR r8, [%[a], #28]\n\t"
  50743. "LDR r9, [%[b], #36]\n\t"
  50744. "UMULL r6, r7, r8, r9\n\t"
  50745. "ADDS r4, r4, r6\n\t"
  50746. "ADCS r5, r5, r7\n\t"
  50747. "ADC r3, r3, #0x0\n\t"
  50748. /* A[6] * B[10] */
  50749. "LDR r8, [%[a], #24]\n\t"
  50750. "LDR r9, [%[b], #40]\n\t"
  50751. "UMULL r6, r7, r8, r9\n\t"
  50752. "ADDS r4, r4, r6\n\t"
  50753. "ADCS r5, r5, r7\n\t"
  50754. "ADC r3, r3, #0x0\n\t"
  50755. /* A[5] * B[11] */
  50756. "LDR r8, [%[a], #20]\n\t"
  50757. "LDR r9, [%[b], #44]\n\t"
  50758. "UMULL r6, r7, r8, r9\n\t"
  50759. "ADDS r4, r4, r6\n\t"
  50760. "ADCS r5, r5, r7\n\t"
  50761. "ADC r3, r3, #0x0\n\t"
  50762. /* A[4] * B[12] */
  50763. "LDR r8, [%[a], #16]\n\t"
  50764. "LDR r9, [%[b], #48]\n\t"
  50765. "UMULL r6, r7, r8, r9\n\t"
  50766. "ADDS r4, r4, r6\n\t"
  50767. "ADCS r5, r5, r7\n\t"
  50768. "ADC r3, r3, #0x0\n\t"
  50769. /* A[3] * B[13] */
  50770. "LDR r8, [%[a], #12]\n\t"
  50771. "LDR r9, [%[b], #52]\n\t"
  50772. "UMULL r6, r7, r8, r9\n\t"
  50773. "ADDS r4, r4, r6\n\t"
  50774. "ADCS r5, r5, r7\n\t"
  50775. "ADC r3, r3, #0x0\n\t"
  50776. /* A[2] * B[14] */
  50777. "LDR r8, [%[a], #8]\n\t"
  50778. "LDR r9, [%[b], #56]\n\t"
  50779. "UMULL r6, r7, r8, r9\n\t"
  50780. "ADDS r4, r4, r6\n\t"
  50781. "ADCS r5, r5, r7\n\t"
  50782. "ADC r3, r3, #0x0\n\t"
  50783. /* A[1] * B[15] */
  50784. "LDR r8, [%[a], #4]\n\t"
  50785. "LDR r9, [%[b], #60]\n\t"
  50786. "UMULL r6, r7, r8, r9\n\t"
  50787. "ADDS r4, r4, r6\n\t"
  50788. "ADCS r5, r5, r7\n\t"
  50789. "ADC r3, r3, #0x0\n\t"
  50790. /* A[0] * B[16] */
  50791. "LDR r8, [%[a]]\n\t"
  50792. "LDR r9, [%[b], #64]\n\t"
  50793. "UMULL r6, r7, r8, r9\n\t"
  50794. "ADDS r4, r4, r6\n\t"
  50795. "ADCS r5, r5, r7\n\t"
  50796. "ADC r3, r3, #0x0\n\t"
  50797. "STR r4, [sp, #64]\n\t"
  50798. /* A[1] * B[16] */
  50799. "LDR r8, [%[a], #4]\n\t"
  50800. "UMULL r6, r7, r8, r9\n\t"
  50801. "ADDS r5, r5, r6\n\t"
  50802. "ADCS r3, r3, r7\n\t"
  50803. "MOV r4, #0x0\n\t"
  50804. "ADC r4, r4, #0x0\n\t"
  50805. /* A[2] * B[15] */
  50806. "LDR r8, [%[a], #8]\n\t"
  50807. "LDR r9, [%[b], #60]\n\t"
  50808. "UMULL r6, r7, r8, r9\n\t"
  50809. "ADDS r5, r5, r6\n\t"
  50810. "ADCS r3, r3, r7\n\t"
  50811. "ADC r4, r4, #0x0\n\t"
  50812. /* A[3] * B[14] */
  50813. "LDR r8, [%[a], #12]\n\t"
  50814. "LDR r9, [%[b], #56]\n\t"
  50815. "UMULL r6, r7, r8, r9\n\t"
  50816. "ADDS r5, r5, r6\n\t"
  50817. "ADCS r3, r3, r7\n\t"
  50818. "ADC r4, r4, #0x0\n\t"
  50819. /* A[4] * B[13] */
  50820. "LDR r8, [%[a], #16]\n\t"
  50821. "LDR r9, [%[b], #52]\n\t"
  50822. "UMULL r6, r7, r8, r9\n\t"
  50823. "ADDS r5, r5, r6\n\t"
  50824. "ADCS r3, r3, r7\n\t"
  50825. "ADC r4, r4, #0x0\n\t"
  50826. /* A[5] * B[12] */
  50827. "LDR r8, [%[a], #20]\n\t"
  50828. "LDR r9, [%[b], #48]\n\t"
  50829. "UMULL r6, r7, r8, r9\n\t"
  50830. "ADDS r5, r5, r6\n\t"
  50831. "ADCS r3, r3, r7\n\t"
  50832. "ADC r4, r4, #0x0\n\t"
  50833. /* A[6] * B[11] */
  50834. "LDR r8, [%[a], #24]\n\t"
  50835. "LDR r9, [%[b], #44]\n\t"
  50836. "UMULL r6, r7, r8, r9\n\t"
  50837. "ADDS r5, r5, r6\n\t"
  50838. "ADCS r3, r3, r7\n\t"
  50839. "ADC r4, r4, #0x0\n\t"
  50840. /* A[7] * B[10] */
  50841. "LDR r8, [%[a], #28]\n\t"
  50842. "LDR r9, [%[b], #40]\n\t"
  50843. "UMULL r6, r7, r8, r9\n\t"
  50844. "ADDS r5, r5, r6\n\t"
  50845. "ADCS r3, r3, r7\n\t"
  50846. "ADC r4, r4, #0x0\n\t"
  50847. /* A[8] * B[9] */
  50848. "LDR r9, [%[b], #36]\n\t"
  50849. "UMULL r6, r7, r11, r9\n\t"
  50850. "ADDS r5, r5, r6\n\t"
  50851. "ADCS r3, r3, r7\n\t"
  50852. "ADC r4, r4, #0x0\n\t"
  50853. /* A[9] * B[8] */
  50854. "LDR r8, [%[a], #36]\n\t"
  50855. "UMULL r6, r7, r8, r12\n\t"
  50856. "ADDS r5, r5, r6\n\t"
  50857. "ADCS r3, r3, r7\n\t"
  50858. "ADC r4, r4, #0x0\n\t"
  50859. /* A[10] * B[7] */
  50860. "LDR r8, [%[a], #40]\n\t"
  50861. "LDR r9, [%[b], #28]\n\t"
  50862. "UMULL r6, r7, r8, r9\n\t"
  50863. "ADDS r5, r5, r6\n\t"
  50864. "ADCS r3, r3, r7\n\t"
  50865. "ADC r4, r4, #0x0\n\t"
  50866. /* A[11] * B[6] */
  50867. "LDR r8, [%[a], #44]\n\t"
  50868. "LDR r9, [%[b], #24]\n\t"
  50869. "UMULL r6, r7, r8, r9\n\t"
  50870. "ADDS r5, r5, r6\n\t"
  50871. "ADCS r3, r3, r7\n\t"
  50872. "ADC r4, r4, #0x0\n\t"
  50873. /* A[12] * B[5] */
  50874. "LDR r8, [%[a], #48]\n\t"
  50875. "LDR r9, [%[b], #20]\n\t"
  50876. "UMULL r6, r7, r8, r9\n\t"
  50877. "ADDS r5, r5, r6\n\t"
  50878. "ADCS r3, r3, r7\n\t"
  50879. "ADC r4, r4, #0x0\n\t"
  50880. /* A[13] * B[4] */
  50881. "LDR r8, [%[a], #52]\n\t"
  50882. "LDR r9, [%[b], #16]\n\t"
  50883. "UMULL r6, r7, r8, r9\n\t"
  50884. "ADDS r5, r5, r6\n\t"
  50885. "ADCS r3, r3, r7\n\t"
  50886. "ADC r4, r4, #0x0\n\t"
  50887. /* A[14] * B[3] */
  50888. "LDR r8, [%[a], #56]\n\t"
  50889. "LDR r9, [%[b], #12]\n\t"
  50890. "UMULL r6, r7, r8, r9\n\t"
  50891. "ADDS r5, r5, r6\n\t"
  50892. "ADCS r3, r3, r7\n\t"
  50893. "ADC r4, r4, #0x0\n\t"
  50894. /* A[15] * B[2] */
  50895. "LDR r8, [%[a], #60]\n\t"
  50896. "LDR r9, [%[b], #8]\n\t"
  50897. "UMULL r6, r7, r8, r9\n\t"
  50898. "ADDS r5, r5, r6\n\t"
  50899. "ADCS r3, r3, r7\n\t"
  50900. "ADC r4, r4, #0x0\n\t"
  50901. /* A[16] * B[1] */
  50902. "LDR r8, [%[a], #64]\n\t"
  50903. "LDR r9, [%[b], #4]\n\t"
  50904. "UMULL r6, r7, r8, r9\n\t"
  50905. "ADDS r5, r5, r6\n\t"
  50906. "ADCS r3, r3, r7\n\t"
  50907. "ADC r4, r4, #0x0\n\t"
  50908. "STR r5, [%[r], #68]\n\t"
  50909. /* A[16] * B[2] */
  50910. "LDR r9, [%[b], #8]\n\t"
  50911. "UMULL r6, r7, r8, r9\n\t"
  50912. "ADDS r3, r3, r6\n\t"
  50913. "ADCS r4, r4, r7\n\t"
  50914. "MOV r5, #0x0\n\t"
  50915. "ADC r5, r5, #0x0\n\t"
  50916. /* A[15] * B[3] */
  50917. "LDR r8, [%[a], #60]\n\t"
  50918. "LDR r9, [%[b], #12]\n\t"
  50919. "UMULL r6, r7, r8, r9\n\t"
  50920. "ADDS r3, r3, r6\n\t"
  50921. "ADCS r4, r4, r7\n\t"
  50922. "ADC r5, r5, #0x0\n\t"
  50923. /* A[14] * B[4] */
  50924. "LDR r8, [%[a], #56]\n\t"
  50925. "LDR r9, [%[b], #16]\n\t"
  50926. "UMULL r6, r7, r8, r9\n\t"
  50927. "ADDS r3, r3, r6\n\t"
  50928. "ADCS r4, r4, r7\n\t"
  50929. "ADC r5, r5, #0x0\n\t"
  50930. /* A[13] * B[5] */
  50931. "LDR r8, [%[a], #52]\n\t"
  50932. "LDR r9, [%[b], #20]\n\t"
  50933. "UMULL r6, r7, r8, r9\n\t"
  50934. "ADDS r3, r3, r6\n\t"
  50935. "ADCS r4, r4, r7\n\t"
  50936. "ADC r5, r5, #0x0\n\t"
  50937. /* A[12] * B[6] */
  50938. "LDR r8, [%[a], #48]\n\t"
  50939. "LDR r9, [%[b], #24]\n\t"
  50940. "UMULL r6, r7, r8, r9\n\t"
  50941. "ADDS r3, r3, r6\n\t"
  50942. "ADCS r4, r4, r7\n\t"
  50943. "ADC r5, r5, #0x0\n\t"
  50944. /* A[11] * B[7] */
  50945. "LDR r8, [%[a], #44]\n\t"
  50946. "LDR r9, [%[b], #28]\n\t"
  50947. "UMULL r6, r7, r8, r9\n\t"
  50948. "ADDS r3, r3, r6\n\t"
  50949. "ADCS r4, r4, r7\n\t"
  50950. "ADC r5, r5, #0x0\n\t"
  50951. /* A[10] * B[8] */
  50952. "LDR r8, [%[a], #40]\n\t"
  50953. "UMULL r6, r7, r8, r12\n\t"
  50954. "ADDS r3, r3, r6\n\t"
  50955. "ADCS r4, r4, r7\n\t"
  50956. "ADC r5, r5, #0x0\n\t"
  50957. /* A[9] * B[9] */
  50958. "LDR r11, [%[a], #36]\n\t"
  50959. "LDR r12, [%[b], #36]\n\t"
  50960. "UMULL r6, r7, r11, r12\n\t"
  50961. "ADDS r3, r3, r6\n\t"
  50962. "ADCS r4, r4, r7\n\t"
  50963. "ADC r5, r5, #0x0\n\t"
  50964. /* A[8] * B[10] */
  50965. "LDR r8, [%[a], #32]\n\t"
  50966. "LDR r9, [%[b], #40]\n\t"
  50967. "UMULL r6, r7, r8, r9\n\t"
  50968. "ADDS r3, r3, r6\n\t"
  50969. "ADCS r4, r4, r7\n\t"
  50970. "ADC r5, r5, #0x0\n\t"
  50971. /* A[7] * B[11] */
  50972. "LDR r8, [%[a], #28]\n\t"
  50973. "LDR r9, [%[b], #44]\n\t"
  50974. "UMULL r6, r7, r8, r9\n\t"
  50975. "ADDS r3, r3, r6\n\t"
  50976. "ADCS r4, r4, r7\n\t"
  50977. "ADC r5, r5, #0x0\n\t"
  50978. /* A[6] * B[12] */
  50979. "LDR r8, [%[a], #24]\n\t"
  50980. "LDR r9, [%[b], #48]\n\t"
  50981. "UMULL r6, r7, r8, r9\n\t"
  50982. "ADDS r3, r3, r6\n\t"
  50983. "ADCS r4, r4, r7\n\t"
  50984. "ADC r5, r5, #0x0\n\t"
  50985. /* A[5] * B[13] */
  50986. "LDR r8, [%[a], #20]\n\t"
  50987. "LDR r9, [%[b], #52]\n\t"
  50988. "UMULL r6, r7, r8, r9\n\t"
  50989. "ADDS r3, r3, r6\n\t"
  50990. "ADCS r4, r4, r7\n\t"
  50991. "ADC r5, r5, #0x0\n\t"
  50992. /* A[4] * B[14] */
  50993. "LDR r8, [%[a], #16]\n\t"
  50994. "LDR r9, [%[b], #56]\n\t"
  50995. "UMULL r6, r7, r8, r9\n\t"
  50996. "ADDS r3, r3, r6\n\t"
  50997. "ADCS r4, r4, r7\n\t"
  50998. "ADC r5, r5, #0x0\n\t"
  50999. /* A[3] * B[15] */
  51000. "LDR r8, [%[a], #12]\n\t"
  51001. "LDR r9, [%[b], #60]\n\t"
  51002. "UMULL r6, r7, r8, r9\n\t"
  51003. "ADDS r3, r3, r6\n\t"
  51004. "ADCS r4, r4, r7\n\t"
  51005. "ADC r5, r5, #0x0\n\t"
  51006. /* A[2] * B[16] */
  51007. "LDR r8, [%[a], #8]\n\t"
  51008. "LDR r9, [%[b], #64]\n\t"
  51009. "UMULL r6, r7, r8, r9\n\t"
  51010. "ADDS r3, r3, r6\n\t"
  51011. "ADCS r4, r4, r7\n\t"
  51012. "ADC r5, r5, #0x0\n\t"
  51013. "STR r3, [%[r], #72]\n\t"
  51014. /* A[3] * B[16] */
  51015. "LDR r8, [%[a], #12]\n\t"
  51016. "UMULL r6, r7, r8, r9\n\t"
  51017. "ADDS r4, r4, r6\n\t"
  51018. "ADCS r5, r5, r7\n\t"
  51019. "MOV r3, #0x0\n\t"
  51020. "ADC r3, r3, #0x0\n\t"
  51021. /* A[4] * B[15] */
  51022. "LDR r8, [%[a], #16]\n\t"
  51023. "LDR r9, [%[b], #60]\n\t"
  51024. "UMULL r6, r7, r8, r9\n\t"
  51025. "ADDS r4, r4, r6\n\t"
  51026. "ADCS r5, r5, r7\n\t"
  51027. "ADC r3, r3, #0x0\n\t"
  51028. /* A[5] * B[14] */
  51029. "LDR r8, [%[a], #20]\n\t"
  51030. "LDR r9, [%[b], #56]\n\t"
  51031. "UMULL r6, r7, r8, r9\n\t"
  51032. "ADDS r4, r4, r6\n\t"
  51033. "ADCS r5, r5, r7\n\t"
  51034. "ADC r3, r3, #0x0\n\t"
  51035. /* A[6] * B[13] */
  51036. "LDR r8, [%[a], #24]\n\t"
  51037. "LDR r9, [%[b], #52]\n\t"
  51038. "UMULL r6, r7, r8, r9\n\t"
  51039. "ADDS r4, r4, r6\n\t"
  51040. "ADCS r5, r5, r7\n\t"
  51041. "ADC r3, r3, #0x0\n\t"
  51042. /* A[7] * B[12] */
  51043. "LDR r8, [%[a], #28]\n\t"
  51044. "LDR r9, [%[b], #48]\n\t"
  51045. "UMULL r6, r7, r8, r9\n\t"
  51046. "ADDS r4, r4, r6\n\t"
  51047. "ADCS r5, r5, r7\n\t"
  51048. "ADC r3, r3, #0x0\n\t"
  51049. /* A[8] * B[11] */
  51050. "LDR r8, [%[a], #32]\n\t"
  51051. "LDR r9, [%[b], #44]\n\t"
  51052. "UMULL r6, r7, r8, r9\n\t"
  51053. "ADDS r4, r4, r6\n\t"
  51054. "ADCS r5, r5, r7\n\t"
  51055. "ADC r3, r3, #0x0\n\t"
  51056. /* A[9] * B[10] */
  51057. "LDR r9, [%[b], #40]\n\t"
  51058. "UMULL r6, r7, r11, r9\n\t"
  51059. "ADDS r4, r4, r6\n\t"
  51060. "ADCS r5, r5, r7\n\t"
  51061. "ADC r3, r3, #0x0\n\t"
  51062. /* A[10] * B[9] */
  51063. "LDR r8, [%[a], #40]\n\t"
  51064. "UMULL r6, r7, r8, r12\n\t"
  51065. "ADDS r4, r4, r6\n\t"
  51066. "ADCS r5, r5, r7\n\t"
  51067. "ADC r3, r3, #0x0\n\t"
  51068. /* A[11] * B[8] */
  51069. "LDR r8, [%[a], #44]\n\t"
  51070. "LDR r9, [%[b], #32]\n\t"
  51071. "UMULL r6, r7, r8, r9\n\t"
  51072. "ADDS r4, r4, r6\n\t"
  51073. "ADCS r5, r5, r7\n\t"
  51074. "ADC r3, r3, #0x0\n\t"
  51075. /* A[12] * B[7] */
  51076. "LDR r8, [%[a], #48]\n\t"
  51077. "LDR r9, [%[b], #28]\n\t"
  51078. "UMULL r6, r7, r8, r9\n\t"
  51079. "ADDS r4, r4, r6\n\t"
  51080. "ADCS r5, r5, r7\n\t"
  51081. "ADC r3, r3, #0x0\n\t"
  51082. /* A[13] * B[6] */
  51083. "LDR r8, [%[a], #52]\n\t"
  51084. "LDR r9, [%[b], #24]\n\t"
  51085. "UMULL r6, r7, r8, r9\n\t"
  51086. "ADDS r4, r4, r6\n\t"
  51087. "ADCS r5, r5, r7\n\t"
  51088. "ADC r3, r3, #0x0\n\t"
  51089. /* A[14] * B[5] */
  51090. "LDR r8, [%[a], #56]\n\t"
  51091. "LDR r9, [%[b], #20]\n\t"
  51092. "UMULL r6, r7, r8, r9\n\t"
  51093. "ADDS r4, r4, r6\n\t"
  51094. "ADCS r5, r5, r7\n\t"
  51095. "ADC r3, r3, #0x0\n\t"
  51096. /* A[15] * B[4] */
  51097. "LDR r8, [%[a], #60]\n\t"
  51098. "LDR r9, [%[b], #16]\n\t"
  51099. "UMULL r6, r7, r8, r9\n\t"
  51100. "ADDS r4, r4, r6\n\t"
  51101. "ADCS r5, r5, r7\n\t"
  51102. "ADC r3, r3, #0x0\n\t"
  51103. /* A[16] * B[3] */
  51104. "LDR r8, [%[a], #64]\n\t"
  51105. "LDR r9, [%[b], #12]\n\t"
  51106. "UMULL r6, r7, r8, r9\n\t"
  51107. "ADDS r4, r4, r6\n\t"
  51108. "ADCS r5, r5, r7\n\t"
  51109. "ADC r3, r3, #0x0\n\t"
  51110. "STR r4, [%[r], #76]\n\t"
  51111. /* A[16] * B[4] */
  51112. "LDR r9, [%[b], #16]\n\t"
  51113. "UMULL r6, r7, r8, r9\n\t"
  51114. "ADDS r5, r5, r6\n\t"
  51115. "ADCS r3, r3, r7\n\t"
  51116. "MOV r4, #0x0\n\t"
  51117. "ADC r4, r4, #0x0\n\t"
  51118. /* A[15] * B[5] */
  51119. "LDR r8, [%[a], #60]\n\t"
  51120. "LDR r9, [%[b], #20]\n\t"
  51121. "UMULL r6, r7, r8, r9\n\t"
  51122. "ADDS r5, r5, r6\n\t"
  51123. "ADCS r3, r3, r7\n\t"
  51124. "ADC r4, r4, #0x0\n\t"
  51125. /* A[14] * B[6] */
  51126. "LDR r8, [%[a], #56]\n\t"
  51127. "LDR r9, [%[b], #24]\n\t"
  51128. "UMULL r6, r7, r8, r9\n\t"
  51129. "ADDS r5, r5, r6\n\t"
  51130. "ADCS r3, r3, r7\n\t"
  51131. "ADC r4, r4, #0x0\n\t"
  51132. /* A[13] * B[7] */
  51133. "LDR r8, [%[a], #52]\n\t"
  51134. "LDR r9, [%[b], #28]\n\t"
  51135. "UMULL r6, r7, r8, r9\n\t"
  51136. "ADDS r5, r5, r6\n\t"
  51137. "ADCS r3, r3, r7\n\t"
  51138. "ADC r4, r4, #0x0\n\t"
  51139. /* A[12] * B[8] */
  51140. "LDR r8, [%[a], #48]\n\t"
  51141. "LDR r9, [%[b], #32]\n\t"
  51142. "UMULL r6, r7, r8, r9\n\t"
  51143. "ADDS r5, r5, r6\n\t"
  51144. "ADCS r3, r3, r7\n\t"
  51145. "ADC r4, r4, #0x0\n\t"
  51146. /* A[11] * B[9] */
  51147. "LDR r8, [%[a], #44]\n\t"
  51148. "UMULL r6, r7, r8, r12\n\t"
  51149. "ADDS r5, r5, r6\n\t"
  51150. "ADCS r3, r3, r7\n\t"
  51151. "ADC r4, r4, #0x0\n\t"
  51152. /* A[10] * B[10] */
  51153. "LDR r11, [%[a], #40]\n\t"
  51154. "LDR r12, [%[b], #40]\n\t"
  51155. "UMULL r6, r7, r11, r12\n\t"
  51156. "ADDS r5, r5, r6\n\t"
  51157. "ADCS r3, r3, r7\n\t"
  51158. "ADC r4, r4, #0x0\n\t"
  51159. /* A[9] * B[11] */
  51160. "LDR r8, [%[a], #36]\n\t"
  51161. "LDR r9, [%[b], #44]\n\t"
  51162. "UMULL r6, r7, r8, r9\n\t"
  51163. "ADDS r5, r5, r6\n\t"
  51164. "ADCS r3, r3, r7\n\t"
  51165. "ADC r4, r4, #0x0\n\t"
  51166. /* A[8] * B[12] */
  51167. "LDR r8, [%[a], #32]\n\t"
  51168. "LDR r9, [%[b], #48]\n\t"
  51169. "UMULL r6, r7, r8, r9\n\t"
  51170. "ADDS r5, r5, r6\n\t"
  51171. "ADCS r3, r3, r7\n\t"
  51172. "ADC r4, r4, #0x0\n\t"
  51173. /* A[7] * B[13] */
  51174. "LDR r8, [%[a], #28]\n\t"
  51175. "LDR r9, [%[b], #52]\n\t"
  51176. "UMULL r6, r7, r8, r9\n\t"
  51177. "ADDS r5, r5, r6\n\t"
  51178. "ADCS r3, r3, r7\n\t"
  51179. "ADC r4, r4, #0x0\n\t"
  51180. /* A[6] * B[14] */
  51181. "LDR r8, [%[a], #24]\n\t"
  51182. "LDR r9, [%[b], #56]\n\t"
  51183. "UMULL r6, r7, r8, r9\n\t"
  51184. "ADDS r5, r5, r6\n\t"
  51185. "ADCS r3, r3, r7\n\t"
  51186. "ADC r4, r4, #0x0\n\t"
  51187. /* A[5] * B[15] */
  51188. "LDR r8, [%[a], #20]\n\t"
  51189. "LDR r9, [%[b], #60]\n\t"
  51190. "UMULL r6, r7, r8, r9\n\t"
  51191. "ADDS r5, r5, r6\n\t"
  51192. "ADCS r3, r3, r7\n\t"
  51193. "ADC r4, r4, #0x0\n\t"
  51194. /* A[4] * B[16] */
  51195. "LDR r8, [%[a], #16]\n\t"
  51196. "LDR r9, [%[b], #64]\n\t"
  51197. "UMULL r6, r7, r8, r9\n\t"
  51198. "ADDS r5, r5, r6\n\t"
  51199. "ADCS r3, r3, r7\n\t"
  51200. "ADC r4, r4, #0x0\n\t"
  51201. "STR r5, [%[r], #80]\n\t"
  51202. /* A[5] * B[16] */
  51203. "LDR r8, [%[a], #20]\n\t"
  51204. "UMULL r6, r7, r8, r9\n\t"
  51205. "ADDS r3, r3, r6\n\t"
  51206. "ADCS r4, r4, r7\n\t"
  51207. "MOV r5, #0x0\n\t"
  51208. "ADC r5, r5, #0x0\n\t"
  51209. /* A[6] * B[15] */
  51210. "LDR r8, [%[a], #24]\n\t"
  51211. "LDR r9, [%[b], #60]\n\t"
  51212. "UMULL r6, r7, r8, r9\n\t"
  51213. "ADDS r3, r3, r6\n\t"
  51214. "ADCS r4, r4, r7\n\t"
  51215. "ADC r5, r5, #0x0\n\t"
  51216. /* A[7] * B[14] */
  51217. "LDR r8, [%[a], #28]\n\t"
  51218. "LDR r9, [%[b], #56]\n\t"
  51219. "UMULL r6, r7, r8, r9\n\t"
  51220. "ADDS r3, r3, r6\n\t"
  51221. "ADCS r4, r4, r7\n\t"
  51222. "ADC r5, r5, #0x0\n\t"
  51223. /* A[8] * B[13] */
  51224. "LDR r8, [%[a], #32]\n\t"
  51225. "LDR r9, [%[b], #52]\n\t"
  51226. "UMULL r6, r7, r8, r9\n\t"
  51227. "ADDS r3, r3, r6\n\t"
  51228. "ADCS r4, r4, r7\n\t"
  51229. "ADC r5, r5, #0x0\n\t"
  51230. /* A[9] * B[12] */
  51231. "LDR r8, [%[a], #36]\n\t"
  51232. "LDR r9, [%[b], #48]\n\t"
  51233. "UMULL r6, r7, r8, r9\n\t"
  51234. "ADDS r3, r3, r6\n\t"
  51235. "ADCS r4, r4, r7\n\t"
  51236. "ADC r5, r5, #0x0\n\t"
  51237. /* A[10] * B[11] */
  51238. "LDR r9, [%[b], #44]\n\t"
  51239. "UMULL r6, r7, r11, r9\n\t"
  51240. "ADDS r3, r3, r6\n\t"
  51241. "ADCS r4, r4, r7\n\t"
  51242. "ADC r5, r5, #0x0\n\t"
  51243. /* A[11] * B[10] */
  51244. "LDR r8, [%[a], #44]\n\t"
  51245. "UMULL r6, r7, r8, r12\n\t"
  51246. "ADDS r3, r3, r6\n\t"
  51247. "ADCS r4, r4, r7\n\t"
  51248. "ADC r5, r5, #0x0\n\t"
  51249. /* A[12] * B[9] */
  51250. "LDR r8, [%[a], #48]\n\t"
  51251. "LDR r9, [%[b], #36]\n\t"
  51252. "UMULL r6, r7, r8, r9\n\t"
  51253. "ADDS r3, r3, r6\n\t"
  51254. "ADCS r4, r4, r7\n\t"
  51255. "ADC r5, r5, #0x0\n\t"
  51256. /* A[13] * B[8] */
  51257. "LDR r8, [%[a], #52]\n\t"
  51258. "LDR r9, [%[b], #32]\n\t"
  51259. "UMULL r6, r7, r8, r9\n\t"
  51260. "ADDS r3, r3, r6\n\t"
  51261. "ADCS r4, r4, r7\n\t"
  51262. "ADC r5, r5, #0x0\n\t"
  51263. /* A[14] * B[7] */
  51264. "LDR r8, [%[a], #56]\n\t"
  51265. "LDR r9, [%[b], #28]\n\t"
  51266. "UMULL r6, r7, r8, r9\n\t"
  51267. "ADDS r3, r3, r6\n\t"
  51268. "ADCS r4, r4, r7\n\t"
  51269. "ADC r5, r5, #0x0\n\t"
  51270. /* A[15] * B[6] */
  51271. "LDR r8, [%[a], #60]\n\t"
  51272. "LDR r9, [%[b], #24]\n\t"
  51273. "UMULL r6, r7, r8, r9\n\t"
  51274. "ADDS r3, r3, r6\n\t"
  51275. "ADCS r4, r4, r7\n\t"
  51276. "ADC r5, r5, #0x0\n\t"
  51277. /* A[16] * B[5] */
  51278. "LDR r8, [%[a], #64]\n\t"
  51279. "LDR r9, [%[b], #20]\n\t"
  51280. "UMULL r6, r7, r8, r9\n\t"
  51281. "ADDS r3, r3, r6\n\t"
  51282. "ADCS r4, r4, r7\n\t"
  51283. "ADC r5, r5, #0x0\n\t"
  51284. "STR r3, [%[r], #84]\n\t"
  51285. /* A[16] * B[6] */
  51286. "LDR r9, [%[b], #24]\n\t"
  51287. "UMULL r6, r7, r8, r9\n\t"
  51288. "ADDS r4, r4, r6\n\t"
  51289. "ADCS r5, r5, r7\n\t"
  51290. "MOV r3, #0x0\n\t"
  51291. "ADC r3, r3, #0x0\n\t"
  51292. /* A[15] * B[7] */
  51293. "LDR r8, [%[a], #60]\n\t"
  51294. "LDR r9, [%[b], #28]\n\t"
  51295. "UMULL r6, r7, r8, r9\n\t"
  51296. "ADDS r4, r4, r6\n\t"
  51297. "ADCS r5, r5, r7\n\t"
  51298. "ADC r3, r3, #0x0\n\t"
  51299. /* A[14] * B[8] */
  51300. "LDR r8, [%[a], #56]\n\t"
  51301. "LDR r9, [%[b], #32]\n\t"
  51302. "UMULL r6, r7, r8, r9\n\t"
  51303. "ADDS r4, r4, r6\n\t"
  51304. "ADCS r5, r5, r7\n\t"
  51305. "ADC r3, r3, #0x0\n\t"
  51306. /* A[13] * B[9] */
  51307. "LDR r8, [%[a], #52]\n\t"
  51308. "LDR r9, [%[b], #36]\n\t"
  51309. "UMULL r6, r7, r8, r9\n\t"
  51310. "ADDS r4, r4, r6\n\t"
  51311. "ADCS r5, r5, r7\n\t"
  51312. "ADC r3, r3, #0x0\n\t"
  51313. /* A[12] * B[10] */
  51314. "LDR r8, [%[a], #48]\n\t"
  51315. "UMULL r6, r7, r8, r12\n\t"
  51316. "ADDS r4, r4, r6\n\t"
  51317. "ADCS r5, r5, r7\n\t"
  51318. "ADC r3, r3, #0x0\n\t"
  51319. /* A[11] * B[11] */
  51320. "LDR r11, [%[a], #44]\n\t"
  51321. "LDR r12, [%[b], #44]\n\t"
  51322. "UMULL r6, r7, r11, r12\n\t"
  51323. "ADDS r4, r4, r6\n\t"
  51324. "ADCS r5, r5, r7\n\t"
  51325. "ADC r3, r3, #0x0\n\t"
  51326. /* A[10] * B[12] */
  51327. "LDR r8, [%[a], #40]\n\t"
  51328. "LDR r9, [%[b], #48]\n\t"
  51329. "UMULL r6, r7, r8, r9\n\t"
  51330. "ADDS r4, r4, r6\n\t"
  51331. "ADCS r5, r5, r7\n\t"
  51332. "ADC r3, r3, #0x0\n\t"
  51333. /* A[9] * B[13] */
  51334. "LDR r8, [%[a], #36]\n\t"
  51335. "LDR r9, [%[b], #52]\n\t"
  51336. "UMULL r6, r7, r8, r9\n\t"
  51337. "ADDS r4, r4, r6\n\t"
  51338. "ADCS r5, r5, r7\n\t"
  51339. "ADC r3, r3, #0x0\n\t"
  51340. /* A[8] * B[14] */
  51341. "LDR r8, [%[a], #32]\n\t"
  51342. "LDR r9, [%[b], #56]\n\t"
  51343. "UMULL r6, r7, r8, r9\n\t"
  51344. "ADDS r4, r4, r6\n\t"
  51345. "ADCS r5, r5, r7\n\t"
  51346. "ADC r3, r3, #0x0\n\t"
  51347. /* A[7] * B[15] */
  51348. "LDR r8, [%[a], #28]\n\t"
  51349. "LDR r9, [%[b], #60]\n\t"
  51350. "UMULL r6, r7, r8, r9\n\t"
  51351. "ADDS r4, r4, r6\n\t"
  51352. "ADCS r5, r5, r7\n\t"
  51353. "ADC r3, r3, #0x0\n\t"
  51354. /* A[6] * B[16] */
  51355. "LDR r8, [%[a], #24]\n\t"
  51356. "LDR r9, [%[b], #64]\n\t"
  51357. "UMULL r6, r7, r8, r9\n\t"
  51358. "ADDS r4, r4, r6\n\t"
  51359. "ADCS r5, r5, r7\n\t"
  51360. "ADC r3, r3, #0x0\n\t"
  51361. "STR r4, [%[r], #88]\n\t"
  51362. /* A[7] * B[16] */
  51363. "LDR r8, [%[a], #28]\n\t"
  51364. "UMULL r6, r7, r8, r9\n\t"
  51365. "ADDS r5, r5, r6\n\t"
  51366. "ADCS r3, r3, r7\n\t"
  51367. "MOV r4, #0x0\n\t"
  51368. "ADC r4, r4, #0x0\n\t"
  51369. /* A[8] * B[15] */
  51370. "LDR r8, [%[a], #32]\n\t"
  51371. "LDR r9, [%[b], #60]\n\t"
  51372. "UMULL r6, r7, r8, r9\n\t"
  51373. "ADDS r5, r5, r6\n\t"
  51374. "ADCS r3, r3, r7\n\t"
  51375. "ADC r4, r4, #0x0\n\t"
  51376. /* A[9] * B[14] */
  51377. "LDR r8, [%[a], #36]\n\t"
  51378. "LDR r9, [%[b], #56]\n\t"
  51379. "UMULL r6, r7, r8, r9\n\t"
  51380. "ADDS r5, r5, r6\n\t"
  51381. "ADCS r3, r3, r7\n\t"
  51382. "ADC r4, r4, #0x0\n\t"
  51383. /* A[10] * B[13] */
  51384. "LDR r8, [%[a], #40]\n\t"
  51385. "LDR r9, [%[b], #52]\n\t"
  51386. "UMULL r6, r7, r8, r9\n\t"
  51387. "ADDS r5, r5, r6\n\t"
  51388. "ADCS r3, r3, r7\n\t"
  51389. "ADC r4, r4, #0x0\n\t"
  51390. /* A[11] * B[12] */
  51391. "LDR r9, [%[b], #48]\n\t"
  51392. "UMULL r6, r7, r11, r9\n\t"
  51393. "ADDS r5, r5, r6\n\t"
  51394. "ADCS r3, r3, r7\n\t"
  51395. "ADC r4, r4, #0x0\n\t"
  51396. /* A[12] * B[11] */
  51397. "LDR r8, [%[a], #48]\n\t"
  51398. "UMULL r6, r7, r8, r12\n\t"
  51399. "ADDS r5, r5, r6\n\t"
  51400. "ADCS r3, r3, r7\n\t"
  51401. "ADC r4, r4, #0x0\n\t"
  51402. /* A[13] * B[10] */
  51403. "LDR r8, [%[a], #52]\n\t"
  51404. "LDR r9, [%[b], #40]\n\t"
  51405. "UMULL r6, r7, r8, r9\n\t"
  51406. "ADDS r5, r5, r6\n\t"
  51407. "ADCS r3, r3, r7\n\t"
  51408. "ADC r4, r4, #0x0\n\t"
  51409. /* A[14] * B[9] */
  51410. "LDR r8, [%[a], #56]\n\t"
  51411. "LDR r9, [%[b], #36]\n\t"
  51412. "UMULL r6, r7, r8, r9\n\t"
  51413. "ADDS r5, r5, r6\n\t"
  51414. "ADCS r3, r3, r7\n\t"
  51415. "ADC r4, r4, #0x0\n\t"
  51416. /* A[15] * B[8] */
  51417. "LDR r8, [%[a], #60]\n\t"
  51418. "LDR r9, [%[b], #32]\n\t"
  51419. "UMULL r6, r7, r8, r9\n\t"
  51420. "ADDS r5, r5, r6\n\t"
  51421. "ADCS r3, r3, r7\n\t"
  51422. "ADC r4, r4, #0x0\n\t"
  51423. /* A[16] * B[7] */
  51424. "LDR r8, [%[a], #64]\n\t"
  51425. "LDR r9, [%[b], #28]\n\t"
  51426. "UMULL r6, r7, r8, r9\n\t"
  51427. "ADDS r5, r5, r6\n\t"
  51428. "ADCS r3, r3, r7\n\t"
  51429. "ADC r4, r4, #0x0\n\t"
  51430. "STR r5, [%[r], #92]\n\t"
  51431. /* A[16] * B[8] */
  51432. "LDR r9, [%[b], #32]\n\t"
  51433. "UMULL r6, r7, r8, r9\n\t"
  51434. "ADDS r3, r3, r6\n\t"
  51435. "ADCS r4, r4, r7\n\t"
  51436. "MOV r5, #0x0\n\t"
  51437. "ADC r5, r5, #0x0\n\t"
  51438. /* A[15] * B[9] */
  51439. "LDR r8, [%[a], #60]\n\t"
  51440. "LDR r9, [%[b], #36]\n\t"
  51441. "UMULL r6, r7, r8, r9\n\t"
  51442. "ADDS r3, r3, r6\n\t"
  51443. "ADCS r4, r4, r7\n\t"
  51444. "ADC r5, r5, #0x0\n\t"
  51445. /* A[14] * B[10] */
  51446. "LDR r8, [%[a], #56]\n\t"
  51447. "LDR r9, [%[b], #40]\n\t"
  51448. "UMULL r6, r7, r8, r9\n\t"
  51449. "ADDS r3, r3, r6\n\t"
  51450. "ADCS r4, r4, r7\n\t"
  51451. "ADC r5, r5, #0x0\n\t"
  51452. /* A[13] * B[11] */
  51453. "LDR r8, [%[a], #52]\n\t"
  51454. "UMULL r6, r7, r8, r12\n\t"
  51455. "ADDS r3, r3, r6\n\t"
  51456. "ADCS r4, r4, r7\n\t"
  51457. "ADC r5, r5, #0x0\n\t"
  51458. /* A[12] * B[12] */
  51459. "LDR r11, [%[a], #48]\n\t"
  51460. "LDR r12, [%[b], #48]\n\t"
  51461. "UMULL r6, r7, r11, r12\n\t"
  51462. "ADDS r3, r3, r6\n\t"
  51463. "ADCS r4, r4, r7\n\t"
  51464. "ADC r5, r5, #0x0\n\t"
  51465. /* A[11] * B[13] */
  51466. "LDR r8, [%[a], #44]\n\t"
  51467. "LDR r9, [%[b], #52]\n\t"
  51468. "UMULL r6, r7, r8, r9\n\t"
  51469. "ADDS r3, r3, r6\n\t"
  51470. "ADCS r4, r4, r7\n\t"
  51471. "ADC r5, r5, #0x0\n\t"
  51472. /* A[10] * B[14] */
  51473. "LDR r8, [%[a], #40]\n\t"
  51474. "LDR r9, [%[b], #56]\n\t"
  51475. "UMULL r6, r7, r8, r9\n\t"
  51476. "ADDS r3, r3, r6\n\t"
  51477. "ADCS r4, r4, r7\n\t"
  51478. "ADC r5, r5, #0x0\n\t"
  51479. /* A[9] * B[15] */
  51480. "LDR r8, [%[a], #36]\n\t"
  51481. "LDR r9, [%[b], #60]\n\t"
  51482. "UMULL r6, r7, r8, r9\n\t"
  51483. "ADDS r3, r3, r6\n\t"
  51484. "ADCS r4, r4, r7\n\t"
  51485. "ADC r5, r5, #0x0\n\t"
  51486. /* A[8] * B[16] */
  51487. "LDR r8, [%[a], #32]\n\t"
  51488. "LDR r9, [%[b], #64]\n\t"
  51489. "UMULL r6, r7, r8, r9\n\t"
  51490. "ADDS r3, r3, r6\n\t"
  51491. "ADCS r4, r4, r7\n\t"
  51492. "ADC r5, r5, #0x0\n\t"
  51493. "STR r3, [%[r], #96]\n\t"
  51494. /* A[9] * B[16] */
  51495. "LDR r8, [%[a], #36]\n\t"
  51496. "UMULL r6, r7, r8, r9\n\t"
  51497. "ADDS r4, r4, r6\n\t"
  51498. "ADCS r5, r5, r7\n\t"
  51499. "MOV r3, #0x0\n\t"
  51500. "ADC r3, r3, #0x0\n\t"
  51501. /* A[10] * B[15] */
  51502. "LDR r8, [%[a], #40]\n\t"
  51503. "LDR r9, [%[b], #60]\n\t"
  51504. "UMULL r6, r7, r8, r9\n\t"
  51505. "ADDS r4, r4, r6\n\t"
  51506. "ADCS r5, r5, r7\n\t"
  51507. "ADC r3, r3, #0x0\n\t"
  51508. /* A[11] * B[14] */
  51509. "LDR r8, [%[a], #44]\n\t"
  51510. "LDR r9, [%[b], #56]\n\t"
  51511. "UMULL r6, r7, r8, r9\n\t"
  51512. "ADDS r4, r4, r6\n\t"
  51513. "ADCS r5, r5, r7\n\t"
  51514. "ADC r3, r3, #0x0\n\t"
  51515. /* A[12] * B[13] */
  51516. "LDR r9, [%[b], #52]\n\t"
  51517. "UMULL r6, r7, r11, r9\n\t"
  51518. "ADDS r4, r4, r6\n\t"
  51519. "ADCS r5, r5, r7\n\t"
  51520. "ADC r3, r3, #0x0\n\t"
  51521. /* A[13] * B[12] */
  51522. "LDR r8, [%[a], #52]\n\t"
  51523. "UMULL r6, r7, r8, r12\n\t"
  51524. "ADDS r4, r4, r6\n\t"
  51525. "ADCS r5, r5, r7\n\t"
  51526. "ADC r3, r3, #0x0\n\t"
  51527. /* A[14] * B[11] */
  51528. "LDR r8, [%[a], #56]\n\t"
  51529. "LDR r9, [%[b], #44]\n\t"
  51530. "UMULL r6, r7, r8, r9\n\t"
  51531. "ADDS r4, r4, r6\n\t"
  51532. "ADCS r5, r5, r7\n\t"
  51533. "ADC r3, r3, #0x0\n\t"
  51534. /* A[15] * B[10] */
  51535. "LDR r8, [%[a], #60]\n\t"
  51536. "LDR r9, [%[b], #40]\n\t"
  51537. "UMULL r6, r7, r8, r9\n\t"
  51538. "ADDS r4, r4, r6\n\t"
  51539. "ADCS r5, r5, r7\n\t"
  51540. "ADC r3, r3, #0x0\n\t"
  51541. /* A[16] * B[9] */
  51542. "LDR r8, [%[a], #64]\n\t"
  51543. "LDR r9, [%[b], #36]\n\t"
  51544. "UMULL r6, r7, r8, r9\n\t"
  51545. "ADDS r4, r4, r6\n\t"
  51546. "ADCS r5, r5, r7\n\t"
  51547. "ADC r3, r3, #0x0\n\t"
  51548. "STR r4, [%[r], #100]\n\t"
  51549. /* A[16] * B[10] */
  51550. "LDR r9, [%[b], #40]\n\t"
  51551. "UMULL r6, r7, r8, r9\n\t"
  51552. "ADDS r5, r5, r6\n\t"
  51553. "ADCS r3, r3, r7\n\t"
  51554. "MOV r4, #0x0\n\t"
  51555. "ADC r4, r4, #0x0\n\t"
  51556. /* A[15] * B[11] */
  51557. "LDR r8, [%[a], #60]\n\t"
  51558. "LDR r9, [%[b], #44]\n\t"
  51559. "UMULL r6, r7, r8, r9\n\t"
  51560. "ADDS r5, r5, r6\n\t"
  51561. "ADCS r3, r3, r7\n\t"
  51562. "ADC r4, r4, #0x0\n\t"
  51563. /* A[14] * B[12] */
  51564. "LDR r8, [%[a], #56]\n\t"
  51565. "UMULL r6, r7, r8, r12\n\t"
  51566. "ADDS r5, r5, r6\n\t"
  51567. "ADCS r3, r3, r7\n\t"
  51568. "ADC r4, r4, #0x0\n\t"
  51569. /* A[13] * B[13] */
  51570. "LDR r11, [%[a], #52]\n\t"
  51571. "LDR r12, [%[b], #52]\n\t"
  51572. "UMULL r6, r7, r11, r12\n\t"
  51573. "ADDS r5, r5, r6\n\t"
  51574. "ADCS r3, r3, r7\n\t"
  51575. "ADC r4, r4, #0x0\n\t"
  51576. /* A[12] * B[14] */
  51577. "LDR r8, [%[a], #48]\n\t"
  51578. "LDR r9, [%[b], #56]\n\t"
  51579. "UMULL r6, r7, r8, r9\n\t"
  51580. "ADDS r5, r5, r6\n\t"
  51581. "ADCS r3, r3, r7\n\t"
  51582. "ADC r4, r4, #0x0\n\t"
  51583. /* A[11] * B[15] */
  51584. "LDR r8, [%[a], #44]\n\t"
  51585. "LDR r9, [%[b], #60]\n\t"
  51586. "UMULL r6, r7, r8, r9\n\t"
  51587. "ADDS r5, r5, r6\n\t"
  51588. "ADCS r3, r3, r7\n\t"
  51589. "ADC r4, r4, #0x0\n\t"
  51590. /* A[10] * B[16] */
  51591. "LDR r8, [%[a], #40]\n\t"
  51592. "LDR r9, [%[b], #64]\n\t"
  51593. "UMULL r6, r7, r8, r9\n\t"
  51594. "ADDS r5, r5, r6\n\t"
  51595. "ADCS r3, r3, r7\n\t"
  51596. "ADC r4, r4, #0x0\n\t"
  51597. "STR r5, [%[r], #104]\n\t"
  51598. /* A[11] * B[16] */
  51599. "LDR r8, [%[a], #44]\n\t"
  51600. "UMULL r6, r7, r8, r9\n\t"
  51601. "ADDS r3, r3, r6\n\t"
  51602. "ADCS r4, r4, r7\n\t"
  51603. "MOV r5, #0x0\n\t"
  51604. "ADC r5, r5, #0x0\n\t"
  51605. /* A[12] * B[15] */
  51606. "LDR r8, [%[a], #48]\n\t"
  51607. "LDR r9, [%[b], #60]\n\t"
  51608. "UMULL r6, r7, r8, r9\n\t"
  51609. "ADDS r3, r3, r6\n\t"
  51610. "ADCS r4, r4, r7\n\t"
  51611. "ADC r5, r5, #0x0\n\t"
  51612. /* A[13] * B[14] */
  51613. "LDR r9, [%[b], #56]\n\t"
  51614. "UMULL r6, r7, r11, r9\n\t"
  51615. "ADDS r3, r3, r6\n\t"
  51616. "ADCS r4, r4, r7\n\t"
  51617. "ADC r5, r5, #0x0\n\t"
  51618. /* A[14] * B[13] */
  51619. "LDR r8, [%[a], #56]\n\t"
  51620. "UMULL r6, r7, r8, r12\n\t"
  51621. "ADDS r3, r3, r6\n\t"
  51622. "ADCS r4, r4, r7\n\t"
  51623. "ADC r5, r5, #0x0\n\t"
  51624. /* A[15] * B[12] */
  51625. "LDR r8, [%[a], #60]\n\t"
  51626. "LDR r9, [%[b], #48]\n\t"
  51627. "UMULL r6, r7, r8, r9\n\t"
  51628. "ADDS r3, r3, r6\n\t"
  51629. "ADCS r4, r4, r7\n\t"
  51630. "ADC r5, r5, #0x0\n\t"
  51631. /* A[16] * B[11] */
  51632. "LDR r8, [%[a], #64]\n\t"
  51633. "LDR r9, [%[b], #44]\n\t"
  51634. "UMULL r6, r7, r8, r9\n\t"
  51635. "ADDS r3, r3, r6\n\t"
  51636. "ADCS r4, r4, r7\n\t"
  51637. "ADC r5, r5, #0x0\n\t"
  51638. "STR r3, [%[r], #108]\n\t"
  51639. /* A[16] * B[12] */
  51640. "LDR r9, [%[b], #48]\n\t"
  51641. "UMULL r6, r7, r8, r9\n\t"
  51642. "ADDS r4, r4, r6\n\t"
  51643. "ADCS r5, r5, r7\n\t"
  51644. "MOV r3, #0x0\n\t"
  51645. "ADC r3, r3, #0x0\n\t"
  51646. /* A[15] * B[13] */
  51647. "LDR r8, [%[a], #60]\n\t"
  51648. "UMULL r6, r7, r8, r12\n\t"
  51649. "ADDS r4, r4, r6\n\t"
  51650. "ADCS r5, r5, r7\n\t"
  51651. "ADC r3, r3, #0x0\n\t"
  51652. /* A[14] * B[14] */
  51653. "LDR r11, [%[a], #56]\n\t"
  51654. "LDR r12, [%[b], #56]\n\t"
  51655. "UMULL r6, r7, r11, r12\n\t"
  51656. "ADDS r4, r4, r6\n\t"
  51657. "ADCS r5, r5, r7\n\t"
  51658. "ADC r3, r3, #0x0\n\t"
  51659. /* A[13] * B[15] */
  51660. "LDR r8, [%[a], #52]\n\t"
  51661. "LDR r9, [%[b], #60]\n\t"
  51662. "UMULL r6, r7, r8, r9\n\t"
  51663. "ADDS r4, r4, r6\n\t"
  51664. "ADCS r5, r5, r7\n\t"
  51665. "ADC r3, r3, #0x0\n\t"
  51666. /* A[12] * B[16] */
  51667. "LDR r8, [%[a], #48]\n\t"
  51668. "LDR r9, [%[b], #64]\n\t"
  51669. "UMULL r6, r7, r8, r9\n\t"
  51670. "ADDS r4, r4, r6\n\t"
  51671. "ADCS r5, r5, r7\n\t"
  51672. "ADC r3, r3, #0x0\n\t"
  51673. "STR r4, [%[r], #112]\n\t"
  51674. /* A[13] * B[16] */
  51675. "LDR r8, [%[a], #52]\n\t"
  51676. "UMULL r6, r7, r8, r9\n\t"
  51677. "ADDS r5, r5, r6\n\t"
  51678. "ADCS r3, r3, r7\n\t"
  51679. "MOV r4, #0x0\n\t"
  51680. "ADC r4, r4, #0x0\n\t"
  51681. /* A[14] * B[15] */
  51682. "LDR r9, [%[b], #60]\n\t"
  51683. "UMULL r6, r7, r11, r9\n\t"
  51684. "ADDS r5, r5, r6\n\t"
  51685. "ADCS r3, r3, r7\n\t"
  51686. "ADC r4, r4, #0x0\n\t"
  51687. /* A[15] * B[14] */
  51688. "LDR r8, [%[a], #60]\n\t"
  51689. "UMULL r6, r7, r8, r12\n\t"
  51690. "ADDS r5, r5, r6\n\t"
  51691. "ADCS r3, r3, r7\n\t"
  51692. "ADC r4, r4, #0x0\n\t"
  51693. /* A[16] * B[13] */
  51694. "LDR r8, [%[a], #64]\n\t"
  51695. "LDR r9, [%[b], #52]\n\t"
  51696. "UMULL r6, r7, r8, r9\n\t"
  51697. "ADDS r5, r5, r6\n\t"
  51698. "ADCS r3, r3, r7\n\t"
  51699. "ADC r4, r4, #0x0\n\t"
  51700. "STR r5, [%[r], #116]\n\t"
  51701. /* A[16] * B[14] */
  51702. "UMULL r6, r7, r8, r12\n\t"
  51703. "ADDS r3, r3, r6\n\t"
  51704. "ADCS r4, r4, r7\n\t"
  51705. "MOV r5, #0x0\n\t"
  51706. "ADC r5, r5, #0x0\n\t"
  51707. /* A[15] * B[15] */
  51708. "LDR r11, [%[a], #60]\n\t"
  51709. "LDR r12, [%[b], #60]\n\t"
  51710. "UMULL r6, r7, r11, r12\n\t"
  51711. "ADDS r3, r3, r6\n\t"
  51712. "ADCS r4, r4, r7\n\t"
  51713. "ADC r5, r5, #0x0\n\t"
  51714. /* A[14] * B[16] */
  51715. "LDR r8, [%[a], #56]\n\t"
  51716. "LDR r9, [%[b], #64]\n\t"
  51717. "UMULL r6, r7, r8, r9\n\t"
  51718. "ADDS r3, r3, r6\n\t"
  51719. "ADCS r4, r4, r7\n\t"
  51720. "ADC r5, r5, #0x0\n\t"
  51721. "STR r3, [%[r], #120]\n\t"
  51722. /* A[15] * B[16] */
  51723. "UMULL r6, r7, r11, r9\n\t"
  51724. "ADDS r4, r4, r6\n\t"
  51725. "ADCS r5, r5, r7\n\t"
  51726. "MOV r3, #0x0\n\t"
  51727. "ADC r3, r3, #0x0\n\t"
  51728. /* A[16] * B[15] */
  51729. "LDR r8, [%[a], #64]\n\t"
  51730. "UMULL r6, r7, r8, r12\n\t"
  51731. "ADDS r4, r4, r6\n\t"
  51732. "ADCS r5, r5, r7\n\t"
  51733. "ADC r3, r3, #0x0\n\t"
  51734. "STR r4, [%[r], #124]\n\t"
  51735. /* A[16] * B[16] */
  51736. "UMLAL r5, r3, r8, r9\n\t"
  51737. "STR r5, [%[r], #128]\n\t"
  51738. "STR r3, [%[r], #132]\n\t"
  51739. "LDM sp!, {r3, r4, r5, r6}\n\t"
  51740. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  51741. "LDM sp!, {r3, r4, r5, r6}\n\t"
  51742. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  51743. "LDM sp!, {r3, r4, r5, r6}\n\t"
  51744. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  51745. "LDM sp!, {r3, r4, r5, r6}\n\t"
  51746. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  51747. "LDM sp!, {r3}\n\t"
  51748. "STM %[r]!, {r3}\n\t"
  51749. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  51750. :
  51751. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r11", "r12", "cc"
  51752. );
  51753. }
  51754. #endif /* WOLFSSL_SP_SMALL */
  51755. #ifdef WOLFSSL_SP_SMALL
  51756. /* Square a and put result in r. (r = a * a)
  51757. *
  51758. * r A single precision integer.
  51759. * a A single precision integer.
  51760. */
  51761. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  51762. static void sp_521_sqr_17(sp_digit* r_p, const sp_digit* a_p)
  51763. #else
  51764. static void sp_521_sqr_17(sp_digit* r, const sp_digit* a)
  51765. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  51766. {
  51767. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  51768. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  51769. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  51770. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  51771. __asm__ __volatile__ (
  51772. "SUB sp, sp, #0x88\n\t"
  51773. "LDR lr, [%[a]]\n\t"
  51774. "UMULL r8, r6, lr, lr\n\t"
  51775. "STR r8, [sp]\n\t"
  51776. "MOV r7, #0x0\n\t"
  51777. "MOV r8, #0x0\n\t"
  51778. "MOV r5, #0x4\n\t"
  51779. "\n"
  51780. "L_sp_521_sqr_17_outer:\n\t"
  51781. "SUBS r3, r5, #0x40\n\t"
  51782. "IT cc\n\t"
  51783. "MOVCC r3, #0x0\n\t"
  51784. "SUB r4, r5, r3\n\t"
  51785. "\n"
  51786. "L_sp_521_sqr_17_inner:\n\t"
  51787. "LDR lr, [%[a], r3]\n\t"
  51788. "LDR r11, [%[a], r4]\n\t"
  51789. "UMULL r9, r10, lr, r11\n\t"
  51790. "ADDS r6, r6, r9\n\t"
  51791. "ADCS r7, r7, r10\n\t"
  51792. "ADC r8, r8, #0x0\n\t"
  51793. "ADDS r6, r6, r9\n\t"
  51794. "ADCS r7, r7, r10\n\t"
  51795. "ADC r8, r8, #0x0\n\t"
  51796. "ADD r3, r3, #0x4\n\t"
  51797. "SUB r4, r4, #0x4\n\t"
  51798. "CMP r3, r4\n\t"
  51799. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  51800. "BGT L_sp_521_sqr_17_inner_done\n\t"
  51801. #else
  51802. "BGT.N L_sp_521_sqr_17_inner_done\n\t"
  51803. #endif
  51804. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  51805. "BLT L_sp_521_sqr_17_inner\n\t"
  51806. #else
  51807. "BLT.N L_sp_521_sqr_17_inner\n\t"
  51808. #endif
  51809. "LDR lr, [%[a], r3]\n\t"
  51810. "UMULL r9, r10, lr, lr\n\t"
  51811. "ADDS r6, r6, r9\n\t"
  51812. "ADCS r7, r7, r10\n\t"
  51813. "ADC r8, r8, #0x0\n\t"
  51814. "\n"
  51815. "L_sp_521_sqr_17_inner_done:\n\t"
  51816. "STR r6, [sp, r5]\n\t"
  51817. "MOV r6, r7\n\t"
  51818. "MOV r7, r8\n\t"
  51819. "MOV r8, #0x0\n\t"
  51820. "ADD r5, r5, #0x4\n\t"
  51821. "CMP r5, #0x7c\n\t"
  51822. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  51823. "BLE L_sp_521_sqr_17_outer\n\t"
  51824. #else
  51825. "BLE.N L_sp_521_sqr_17_outer\n\t"
  51826. #endif
  51827. "LDR lr, [%[a], #64]\n\t"
  51828. "UMLAL r6, r7, lr, lr\n\t"
  51829. "STR r6, [sp, r5]\n\t"
  51830. "ADD r5, r5, #0x4\n\t"
  51831. "STR r7, [sp, r5]\n\t"
  51832. "LDM sp!, {r6, r7}\n\t"
  51833. "STM %[r]!, {r6, r7}\n\t"
  51834. "SUB r5, r5, #0x8\n\t"
  51835. "\n"
  51836. "L_sp_521_sqr_17_store:\n\t"
  51837. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  51838. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  51839. "SUBS r5, r5, #0x20\n\t"
  51840. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  51841. "BGT L_sp_521_sqr_17_store\n\t"
  51842. #else
  51843. "BGT.N L_sp_521_sqr_17_store\n\t"
  51844. #endif
  51845. : [r] "+r" (r), [a] "+r" (a)
  51846. :
  51847. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  51848. );
  51849. }
  51850. #else
  51851. /* Square a and put result in r. (r = a * a)
  51852. *
  51853. * r A single precision integer.
  51854. * a A single precision integer.
  51855. */
  51856. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  51857. static void sp_521_sqr_17(sp_digit* r_p, const sp_digit* a_p)
  51858. #else
  51859. static void sp_521_sqr_17(sp_digit* r, const sp_digit* a)
  51860. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  51861. {
  51862. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  51863. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  51864. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  51865. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  51866. __asm__ __volatile__ (
  51867. "SUB sp, sp, #0x44\n\t"
  51868. /* A[0] * A[0] */
  51869. "LDR r10, [%[a]]\n\t"
  51870. "UMULL r8, r3, r10, r10\n\t"
  51871. "MOV r4, #0x0\n\t"
  51872. "STR r8, [sp]\n\t"
  51873. /* A[0] * A[1] */
  51874. "LDR r10, [%[a], #4]\n\t"
  51875. "LDR r12, [%[a]]\n\t"
  51876. "UMULL r8, r9, r10, r12\n\t"
  51877. "ADDS r3, r3, r8\n\t"
  51878. "ADCS r4, r4, r9\n\t"
  51879. "MOV r2, #0x0\n\t"
  51880. "ADC r2, r2, #0x0\n\t"
  51881. "ADDS r3, r3, r8\n\t"
  51882. "ADCS r4, r4, r9\n\t"
  51883. "MOV r2, #0x0\n\t"
  51884. "ADC r2, r2, #0x0\n\t"
  51885. "STR r3, [sp, #4]\n\t"
  51886. /* A[0] * A[2] */
  51887. "LDR r10, [%[a], #8]\n\t"
  51888. "LDR r12, [%[a]]\n\t"
  51889. "UMULL r8, r9, r10, r12\n\t"
  51890. "ADDS r4, r4, r8\n\t"
  51891. "ADCS r2, r2, r9\n\t"
  51892. "MOV r3, #0x0\n\t"
  51893. "ADC r3, r3, #0x0\n\t"
  51894. "ADDS r4, r4, r8\n\t"
  51895. "ADCS r2, r2, r9\n\t"
  51896. "MOV r3, #0x0\n\t"
  51897. "ADC r3, r3, #0x0\n\t"
  51898. /* A[1] * A[1] */
  51899. "LDR r10, [%[a], #4]\n\t"
  51900. "UMULL r8, r9, r10, r10\n\t"
  51901. "ADDS r4, r4, r8\n\t"
  51902. "ADCS r2, r2, r9\n\t"
  51903. "ADC r3, r3, #0x0\n\t"
  51904. "STR r4, [sp, #8]\n\t"
  51905. /* A[0] * A[3] */
  51906. "LDR r10, [%[a], #12]\n\t"
  51907. "LDR r12, [%[a]]\n\t"
  51908. "UMULL r8, r9, r10, r12\n\t"
  51909. "ADDS r2, r2, r8\n\t"
  51910. "ADCS r3, r3, r9\n\t"
  51911. "MOV r4, #0x0\n\t"
  51912. "ADC r4, r4, #0x0\n\t"
  51913. "ADDS r2, r2, r8\n\t"
  51914. "ADCS r3, r3, r9\n\t"
  51915. "MOV r4, #0x0\n\t"
  51916. "ADC r4, r4, #0x0\n\t"
  51917. /* A[1] * A[2] */
  51918. "LDR r10, [%[a], #8]\n\t"
  51919. "LDR r12, [%[a], #4]\n\t"
  51920. "UMULL r8, r9, r10, r12\n\t"
  51921. "ADDS r2, r2, r8\n\t"
  51922. "ADCS r3, r3, r9\n\t"
  51923. "ADC r4, r4, #0x0\n\t"
  51924. "ADDS r2, r2, r8\n\t"
  51925. "ADCS r3, r3, r9\n\t"
  51926. "ADC r4, r4, #0x0\n\t"
  51927. "STR r2, [sp, #12]\n\t"
  51928. /* A[0] * A[4] */
  51929. "LDR r10, [%[a], #16]\n\t"
  51930. "LDR r12, [%[a]]\n\t"
  51931. "UMULL r8, r9, r10, r12\n\t"
  51932. "ADDS r3, r3, r8\n\t"
  51933. "ADCS r4, r4, r9\n\t"
  51934. "MOV r2, #0x0\n\t"
  51935. "ADC r2, r2, #0x0\n\t"
  51936. "ADDS r3, r3, r8\n\t"
  51937. "ADCS r4, r4, r9\n\t"
  51938. "MOV r2, #0x0\n\t"
  51939. "ADC r2, r2, #0x0\n\t"
  51940. /* A[1] * A[3] */
  51941. "LDR r10, [%[a], #12]\n\t"
  51942. "LDR r12, [%[a], #4]\n\t"
  51943. "UMULL r8, r9, r10, r12\n\t"
  51944. "ADDS r3, r3, r8\n\t"
  51945. "ADCS r4, r4, r9\n\t"
  51946. "ADC r2, r2, #0x0\n\t"
  51947. "ADDS r3, r3, r8\n\t"
  51948. "ADCS r4, r4, r9\n\t"
  51949. "ADC r2, r2, #0x0\n\t"
  51950. /* A[2] * A[2] */
  51951. "LDR r10, [%[a], #8]\n\t"
  51952. "UMULL r8, r9, r10, r10\n\t"
  51953. "ADDS r3, r3, r8\n\t"
  51954. "ADCS r4, r4, r9\n\t"
  51955. "ADC r2, r2, #0x0\n\t"
  51956. "STR r3, [sp, #16]\n\t"
  51957. /* A[0] * A[5] */
  51958. "LDR r10, [%[a], #20]\n\t"
  51959. "LDR r12, [%[a]]\n\t"
  51960. "UMULL r5, r6, r10, r12\n\t"
  51961. "MOV r3, #0x0\n\t"
  51962. "MOV r7, #0x0\n\t"
  51963. /* A[1] * A[4] */
  51964. "LDR r10, [%[a], #16]\n\t"
  51965. "LDR r12, [%[a], #4]\n\t"
  51966. "UMULL r8, r9, r10, r12\n\t"
  51967. "ADDS r5, r5, r8\n\t"
  51968. "ADCS r6, r6, r9\n\t"
  51969. "ADC r7, r7, #0x0\n\t"
  51970. /* A[2] * A[3] */
  51971. "LDR r10, [%[a], #12]\n\t"
  51972. "LDR r12, [%[a], #8]\n\t"
  51973. "UMULL r8, r9, r10, r12\n\t"
  51974. "ADDS r5, r5, r8\n\t"
  51975. "ADCS r6, r6, r9\n\t"
  51976. "ADC r7, r7, #0x0\n\t"
  51977. "ADDS r5, r5, r5\n\t"
  51978. "ADCS r6, r6, r6\n\t"
  51979. "ADC r7, r7, r7\n\t"
  51980. "ADDS r4, r4, r5\n\t"
  51981. "ADCS r2, r2, r6\n\t"
  51982. "ADC r3, r3, r7\n\t"
  51983. "STR r4, [sp, #20]\n\t"
  51984. /* A[0] * A[6] */
  51985. "LDR r10, [%[a], #24]\n\t"
  51986. "LDR r12, [%[a]]\n\t"
  51987. "UMULL r5, r6, r10, r12\n\t"
  51988. "MOV r4, #0x0\n\t"
  51989. "MOV r7, #0x0\n\t"
  51990. /* A[1] * A[5] */
  51991. "LDR r10, [%[a], #20]\n\t"
  51992. "LDR r12, [%[a], #4]\n\t"
  51993. "UMULL r8, r9, r10, r12\n\t"
  51994. "ADDS r5, r5, r8\n\t"
  51995. "ADCS r6, r6, r9\n\t"
  51996. "ADC r7, r7, #0x0\n\t"
  51997. /* A[2] * A[4] */
  51998. "LDR r10, [%[a], #16]\n\t"
  51999. "LDR r12, [%[a], #8]\n\t"
  52000. "UMULL r8, r9, r10, r12\n\t"
  52001. "ADDS r5, r5, r8\n\t"
  52002. "ADCS r6, r6, r9\n\t"
  52003. "ADC r7, r7, #0x0\n\t"
  52004. /* A[3] * A[3] */
  52005. "LDR r10, [%[a], #12]\n\t"
  52006. "UMULL r8, r9, r10, r10\n\t"
  52007. "ADDS r5, r5, r5\n\t"
  52008. "ADCS r6, r6, r6\n\t"
  52009. "ADC r7, r7, r7\n\t"
  52010. "ADDS r2, r2, r8\n\t"
  52011. "ADCS r3, r3, r9\n\t"
  52012. "ADC r4, r4, #0x0\n\t"
  52013. "ADDS r2, r2, r5\n\t"
  52014. "ADCS r3, r3, r6\n\t"
  52015. "ADC r4, r4, r7\n\t"
  52016. "STR r2, [sp, #24]\n\t"
  52017. /* A[0] * A[7] */
  52018. "LDR r10, [%[a], #28]\n\t"
  52019. "LDR r12, [%[a]]\n\t"
  52020. "UMULL r5, r6, r10, r12\n\t"
  52021. "MOV r2, #0x0\n\t"
  52022. "MOV r7, #0x0\n\t"
  52023. /* A[1] * A[6] */
  52024. "LDR r10, [%[a], #24]\n\t"
  52025. "LDR r12, [%[a], #4]\n\t"
  52026. "UMULL r8, r9, r10, r12\n\t"
  52027. "ADDS r5, r5, r8\n\t"
  52028. "ADCS r6, r6, r9\n\t"
  52029. "ADC r7, r7, #0x0\n\t"
  52030. /* A[2] * A[5] */
  52031. "LDR r10, [%[a], #20]\n\t"
  52032. "LDR r12, [%[a], #8]\n\t"
  52033. "UMULL r8, r9, r10, r12\n\t"
  52034. "ADDS r5, r5, r8\n\t"
  52035. "ADCS r6, r6, r9\n\t"
  52036. "ADC r7, r7, #0x0\n\t"
  52037. /* A[3] * A[4] */
  52038. "LDR r10, [%[a], #16]\n\t"
  52039. "LDR r12, [%[a], #12]\n\t"
  52040. "UMULL r8, r9, r10, r12\n\t"
  52041. "ADDS r5, r5, r8\n\t"
  52042. "ADCS r6, r6, r9\n\t"
  52043. "ADC r7, r7, #0x0\n\t"
  52044. "ADDS r5, r5, r5\n\t"
  52045. "ADCS r6, r6, r6\n\t"
  52046. "ADC r7, r7, r7\n\t"
  52047. "ADDS r3, r3, r5\n\t"
  52048. "ADCS r4, r4, r6\n\t"
  52049. "ADC r2, r2, r7\n\t"
  52050. "STR r3, [sp, #28]\n\t"
  52051. /* A[0] * A[8] */
  52052. "LDR r10, [%[a], #32]\n\t"
  52053. "LDR r12, [%[a]]\n\t"
  52054. "UMULL r5, r6, r10, r12\n\t"
  52055. "MOV r3, #0x0\n\t"
  52056. "MOV r7, #0x0\n\t"
  52057. /* A[1] * A[7] */
  52058. "LDR r10, [%[a], #28]\n\t"
  52059. "LDR r12, [%[a], #4]\n\t"
  52060. "UMULL r8, r9, r10, r12\n\t"
  52061. "ADDS r5, r5, r8\n\t"
  52062. "ADCS r6, r6, r9\n\t"
  52063. "ADC r7, r7, #0x0\n\t"
  52064. /* A[2] * A[6] */
  52065. "LDR r10, [%[a], #24]\n\t"
  52066. "LDR r12, [%[a], #8]\n\t"
  52067. "UMULL r8, r9, r10, r12\n\t"
  52068. "ADDS r5, r5, r8\n\t"
  52069. "ADCS r6, r6, r9\n\t"
  52070. "ADC r7, r7, #0x0\n\t"
  52071. /* A[3] * A[5] */
  52072. "LDR r10, [%[a], #20]\n\t"
  52073. "LDR r12, [%[a], #12]\n\t"
  52074. "UMULL r8, r9, r10, r12\n\t"
  52075. "ADDS r5, r5, r8\n\t"
  52076. "ADCS r6, r6, r9\n\t"
  52077. "ADC r7, r7, #0x0\n\t"
  52078. /* A[4] * A[4] */
  52079. "LDR r10, [%[a], #16]\n\t"
  52080. "UMULL r8, r9, r10, r10\n\t"
  52081. "ADDS r5, r5, r5\n\t"
  52082. "ADCS r6, r6, r6\n\t"
  52083. "ADC r7, r7, r7\n\t"
  52084. "ADDS r4, r4, r8\n\t"
  52085. "ADCS r2, r2, r9\n\t"
  52086. "ADC r3, r3, #0x0\n\t"
  52087. "ADDS r4, r4, r5\n\t"
  52088. "ADCS r2, r2, r6\n\t"
  52089. "ADC r3, r3, r7\n\t"
  52090. "STR r4, [sp, #32]\n\t"
  52091. /* A[0] * A[9] */
  52092. "LDR r10, [%[a], #36]\n\t"
  52093. "LDR r12, [%[a]]\n\t"
  52094. "UMULL r5, r6, r10, r12\n\t"
  52095. "MOV r4, #0x0\n\t"
  52096. "MOV r7, #0x0\n\t"
  52097. /* A[1] * A[8] */
  52098. "LDR r10, [%[a], #32]\n\t"
  52099. "LDR r12, [%[a], #4]\n\t"
  52100. "UMULL r8, r9, r10, r12\n\t"
  52101. "ADDS r5, r5, r8\n\t"
  52102. "ADCS r6, r6, r9\n\t"
  52103. "ADC r7, r7, #0x0\n\t"
  52104. /* A[2] * A[7] */
  52105. "LDR r10, [%[a], #28]\n\t"
  52106. "LDR r12, [%[a], #8]\n\t"
  52107. "UMULL r8, r9, r10, r12\n\t"
  52108. "ADDS r5, r5, r8\n\t"
  52109. "ADCS r6, r6, r9\n\t"
  52110. "ADC r7, r7, #0x0\n\t"
  52111. /* A[3] * A[6] */
  52112. "LDR r10, [%[a], #24]\n\t"
  52113. "LDR r12, [%[a], #12]\n\t"
  52114. "UMULL r8, r9, r10, r12\n\t"
  52115. "ADDS r5, r5, r8\n\t"
  52116. "ADCS r6, r6, r9\n\t"
  52117. "ADC r7, r7, #0x0\n\t"
  52118. /* A[4] * A[5] */
  52119. "LDR r10, [%[a], #20]\n\t"
  52120. "LDR r12, [%[a], #16]\n\t"
  52121. "UMULL r8, r9, r10, r12\n\t"
  52122. "ADDS r5, r5, r8\n\t"
  52123. "ADCS r6, r6, r9\n\t"
  52124. "ADC r7, r7, #0x0\n\t"
  52125. "ADDS r5, r5, r5\n\t"
  52126. "ADCS r6, r6, r6\n\t"
  52127. "ADC r7, r7, r7\n\t"
  52128. "ADDS r2, r2, r5\n\t"
  52129. "ADCS r3, r3, r6\n\t"
  52130. "ADC r4, r4, r7\n\t"
  52131. "STR r2, [sp, #36]\n\t"
  52132. /* A[0] * A[10] */
  52133. "LDR r10, [%[a], #40]\n\t"
  52134. "LDR r12, [%[a]]\n\t"
  52135. "UMULL r5, r6, r10, r12\n\t"
  52136. "MOV r2, #0x0\n\t"
  52137. "MOV r7, #0x0\n\t"
  52138. /* A[1] * A[9] */
  52139. "LDR r10, [%[a], #36]\n\t"
  52140. "LDR r12, [%[a], #4]\n\t"
  52141. "UMULL r8, r9, r10, r12\n\t"
  52142. "ADDS r5, r5, r8\n\t"
  52143. "ADCS r6, r6, r9\n\t"
  52144. "ADC r7, r7, #0x0\n\t"
  52145. /* A[2] * A[8] */
  52146. "LDR r10, [%[a], #32]\n\t"
  52147. "LDR r12, [%[a], #8]\n\t"
  52148. "UMULL r8, r9, r10, r12\n\t"
  52149. "ADDS r5, r5, r8\n\t"
  52150. "ADCS r6, r6, r9\n\t"
  52151. "ADC r7, r7, #0x0\n\t"
  52152. /* A[3] * A[7] */
  52153. "LDR r10, [%[a], #28]\n\t"
  52154. "LDR r12, [%[a], #12]\n\t"
  52155. "UMULL r8, r9, r10, r12\n\t"
  52156. "ADDS r5, r5, r8\n\t"
  52157. "ADCS r6, r6, r9\n\t"
  52158. "ADC r7, r7, #0x0\n\t"
  52159. /* A[4] * A[6] */
  52160. "LDR r10, [%[a], #24]\n\t"
  52161. "LDR r12, [%[a], #16]\n\t"
  52162. "UMULL r8, r9, r10, r12\n\t"
  52163. "ADDS r5, r5, r8\n\t"
  52164. "ADCS r6, r6, r9\n\t"
  52165. "ADC r7, r7, #0x0\n\t"
  52166. /* A[5] * A[5] */
  52167. "LDR r10, [%[a], #20]\n\t"
  52168. "UMULL r8, r9, r10, r10\n\t"
  52169. "ADDS r5, r5, r5\n\t"
  52170. "ADCS r6, r6, r6\n\t"
  52171. "ADC r7, r7, r7\n\t"
  52172. "ADDS r3, r3, r8\n\t"
  52173. "ADCS r4, r4, r9\n\t"
  52174. "ADC r2, r2, #0x0\n\t"
  52175. "ADDS r3, r3, r5\n\t"
  52176. "ADCS r4, r4, r6\n\t"
  52177. "ADC r2, r2, r7\n\t"
  52178. "STR r3, [sp, #40]\n\t"
  52179. /* A[0] * A[11] */
  52180. "LDR r10, [%[a], #44]\n\t"
  52181. "LDR r12, [%[a]]\n\t"
  52182. "UMULL r5, r6, r10, r12\n\t"
  52183. "MOV r3, #0x0\n\t"
  52184. "MOV r7, #0x0\n\t"
  52185. /* A[1] * A[10] */
  52186. "LDR r10, [%[a], #40]\n\t"
  52187. "LDR r12, [%[a], #4]\n\t"
  52188. "UMULL r8, r9, r10, r12\n\t"
  52189. "ADDS r5, r5, r8\n\t"
  52190. "ADCS r6, r6, r9\n\t"
  52191. "ADC r7, r7, #0x0\n\t"
  52192. /* A[2] * A[9] */
  52193. "LDR r10, [%[a], #36]\n\t"
  52194. "LDR r12, [%[a], #8]\n\t"
  52195. "UMULL r8, r9, r10, r12\n\t"
  52196. "ADDS r5, r5, r8\n\t"
  52197. "ADCS r6, r6, r9\n\t"
  52198. "ADC r7, r7, #0x0\n\t"
  52199. /* A[3] * A[8] */
  52200. "LDR r10, [%[a], #32]\n\t"
  52201. "LDR r12, [%[a], #12]\n\t"
  52202. "UMULL r8, r9, r10, r12\n\t"
  52203. "ADDS r5, r5, r8\n\t"
  52204. "ADCS r6, r6, r9\n\t"
  52205. "ADC r7, r7, #0x0\n\t"
  52206. /* A[4] * A[7] */
  52207. "LDR r10, [%[a], #28]\n\t"
  52208. "LDR r12, [%[a], #16]\n\t"
  52209. "UMULL r8, r9, r10, r12\n\t"
  52210. "ADDS r5, r5, r8\n\t"
  52211. "ADCS r6, r6, r9\n\t"
  52212. "ADC r7, r7, #0x0\n\t"
  52213. /* A[5] * A[6] */
  52214. "LDR r10, [%[a], #24]\n\t"
  52215. "LDR r12, [%[a], #20]\n\t"
  52216. "UMULL r8, r9, r10, r12\n\t"
  52217. "ADDS r5, r5, r8\n\t"
  52218. "ADCS r6, r6, r9\n\t"
  52219. "ADC r7, r7, #0x0\n\t"
  52220. "ADDS r5, r5, r5\n\t"
  52221. "ADCS r6, r6, r6\n\t"
  52222. "ADC r7, r7, r7\n\t"
  52223. "ADDS r4, r4, r5\n\t"
  52224. "ADCS r2, r2, r6\n\t"
  52225. "ADC r3, r3, r7\n\t"
  52226. "STR r4, [sp, #44]\n\t"
  52227. /* A[0] * A[12] */
  52228. "LDR r10, [%[a], #48]\n\t"
  52229. "LDR r12, [%[a]]\n\t"
  52230. "UMULL r5, r6, r10, r12\n\t"
  52231. "MOV r4, #0x0\n\t"
  52232. "MOV r7, #0x0\n\t"
  52233. /* A[1] * A[11] */
  52234. "LDR r10, [%[a], #44]\n\t"
  52235. "LDR r12, [%[a], #4]\n\t"
  52236. "UMULL r8, r9, r10, r12\n\t"
  52237. "ADDS r5, r5, r8\n\t"
  52238. "ADCS r6, r6, r9\n\t"
  52239. "ADC r7, r7, #0x0\n\t"
  52240. /* A[2] * A[10] */
  52241. "LDR r10, [%[a], #40]\n\t"
  52242. "LDR r12, [%[a], #8]\n\t"
  52243. "UMULL r8, r9, r10, r12\n\t"
  52244. "ADDS r5, r5, r8\n\t"
  52245. "ADCS r6, r6, r9\n\t"
  52246. "ADC r7, r7, #0x0\n\t"
  52247. /* A[3] * A[9] */
  52248. "LDR r10, [%[a], #36]\n\t"
  52249. "LDR r12, [%[a], #12]\n\t"
  52250. "UMULL r8, r9, r10, r12\n\t"
  52251. "ADDS r5, r5, r8\n\t"
  52252. "ADCS r6, r6, r9\n\t"
  52253. "ADC r7, r7, #0x0\n\t"
  52254. /* A[4] * A[8] */
  52255. "LDR r10, [%[a], #32]\n\t"
  52256. "LDR r12, [%[a], #16]\n\t"
  52257. "UMULL r8, r9, r10, r12\n\t"
  52258. "ADDS r5, r5, r8\n\t"
  52259. "ADCS r6, r6, r9\n\t"
  52260. "ADC r7, r7, #0x0\n\t"
  52261. /* A[5] * A[7] */
  52262. "LDR r10, [%[a], #28]\n\t"
  52263. "LDR r12, [%[a], #20]\n\t"
  52264. "UMULL r8, r9, r10, r12\n\t"
  52265. "ADDS r5, r5, r8\n\t"
  52266. "ADCS r6, r6, r9\n\t"
  52267. "ADC r7, r7, #0x0\n\t"
  52268. /* A[6] * A[6] */
  52269. "LDR r10, [%[a], #24]\n\t"
  52270. "UMULL r8, r9, r10, r10\n\t"
  52271. "ADDS r5, r5, r5\n\t"
  52272. "ADCS r6, r6, r6\n\t"
  52273. "ADC r7, r7, r7\n\t"
  52274. "ADDS r2, r2, r8\n\t"
  52275. "ADCS r3, r3, r9\n\t"
  52276. "ADC r4, r4, #0x0\n\t"
  52277. "ADDS r2, r2, r5\n\t"
  52278. "ADCS r3, r3, r6\n\t"
  52279. "ADC r4, r4, r7\n\t"
  52280. "STR r2, [sp, #48]\n\t"
  52281. /* A[0] * A[13] */
  52282. "LDR r10, [%[a], #52]\n\t"
  52283. "LDR r12, [%[a]]\n\t"
  52284. "UMULL r5, r6, r10, r12\n\t"
  52285. "MOV r2, #0x0\n\t"
  52286. "MOV r7, #0x0\n\t"
  52287. /* A[1] * A[12] */
  52288. "LDR r10, [%[a], #48]\n\t"
  52289. "LDR r12, [%[a], #4]\n\t"
  52290. "UMULL r8, r9, r10, r12\n\t"
  52291. "ADDS r5, r5, r8\n\t"
  52292. "ADCS r6, r6, r9\n\t"
  52293. "ADC r7, r7, #0x0\n\t"
  52294. /* A[2] * A[11] */
  52295. "LDR r10, [%[a], #44]\n\t"
  52296. "LDR r12, [%[a], #8]\n\t"
  52297. "UMULL r8, r9, r10, r12\n\t"
  52298. "ADDS r5, r5, r8\n\t"
  52299. "ADCS r6, r6, r9\n\t"
  52300. "ADC r7, r7, #0x0\n\t"
  52301. /* A[3] * A[10] */
  52302. "LDR r10, [%[a], #40]\n\t"
  52303. "LDR r12, [%[a], #12]\n\t"
  52304. "UMULL r8, r9, r10, r12\n\t"
  52305. "ADDS r5, r5, r8\n\t"
  52306. "ADCS r6, r6, r9\n\t"
  52307. "ADC r7, r7, #0x0\n\t"
  52308. /* A[4] * A[9] */
  52309. "LDR r10, [%[a], #36]\n\t"
  52310. "LDR r12, [%[a], #16]\n\t"
  52311. "UMULL r8, r9, r10, r12\n\t"
  52312. "ADDS r5, r5, r8\n\t"
  52313. "ADCS r6, r6, r9\n\t"
  52314. "ADC r7, r7, #0x0\n\t"
  52315. /* A[5] * A[8] */
  52316. "LDR r10, [%[a], #32]\n\t"
  52317. "LDR r12, [%[a], #20]\n\t"
  52318. "UMULL r8, r9, r10, r12\n\t"
  52319. "ADDS r5, r5, r8\n\t"
  52320. "ADCS r6, r6, r9\n\t"
  52321. "ADC r7, r7, #0x0\n\t"
  52322. /* A[6] * A[7] */
  52323. "LDR r10, [%[a], #28]\n\t"
  52324. "LDR r12, [%[a], #24]\n\t"
  52325. "UMULL r8, r9, r10, r12\n\t"
  52326. "ADDS r5, r5, r8\n\t"
  52327. "ADCS r6, r6, r9\n\t"
  52328. "ADC r7, r7, #0x0\n\t"
  52329. "ADDS r5, r5, r5\n\t"
  52330. "ADCS r6, r6, r6\n\t"
  52331. "ADC r7, r7, r7\n\t"
  52332. "ADDS r3, r3, r5\n\t"
  52333. "ADCS r4, r4, r6\n\t"
  52334. "ADC r2, r2, r7\n\t"
  52335. "STR r3, [sp, #52]\n\t"
  52336. /* A[0] * A[14] */
  52337. "LDR r10, [%[a], #56]\n\t"
  52338. "LDR r12, [%[a]]\n\t"
  52339. "UMULL r5, r6, r10, r12\n\t"
  52340. "MOV r3, #0x0\n\t"
  52341. "MOV r7, #0x0\n\t"
  52342. /* A[1] * A[13] */
  52343. "LDR r10, [%[a], #52]\n\t"
  52344. "LDR r12, [%[a], #4]\n\t"
  52345. "UMULL r8, r9, r10, r12\n\t"
  52346. "ADDS r5, r5, r8\n\t"
  52347. "ADCS r6, r6, r9\n\t"
  52348. "ADC r7, r7, #0x0\n\t"
  52349. /* A[2] * A[12] */
  52350. "LDR r10, [%[a], #48]\n\t"
  52351. "LDR r12, [%[a], #8]\n\t"
  52352. "UMULL r8, r9, r10, r12\n\t"
  52353. "ADDS r5, r5, r8\n\t"
  52354. "ADCS r6, r6, r9\n\t"
  52355. "ADC r7, r7, #0x0\n\t"
  52356. /* A[3] * A[11] */
  52357. "LDR r10, [%[a], #44]\n\t"
  52358. "LDR r12, [%[a], #12]\n\t"
  52359. "UMULL r8, r9, r10, r12\n\t"
  52360. "ADDS r5, r5, r8\n\t"
  52361. "ADCS r6, r6, r9\n\t"
  52362. "ADC r7, r7, #0x0\n\t"
  52363. /* A[4] * A[10] */
  52364. "LDR r10, [%[a], #40]\n\t"
  52365. "LDR r12, [%[a], #16]\n\t"
  52366. "UMULL r8, r9, r10, r12\n\t"
  52367. "ADDS r5, r5, r8\n\t"
  52368. "ADCS r6, r6, r9\n\t"
  52369. "ADC r7, r7, #0x0\n\t"
  52370. /* A[5] * A[9] */
  52371. "LDR r10, [%[a], #36]\n\t"
  52372. "LDR r12, [%[a], #20]\n\t"
  52373. "UMULL r8, r9, r10, r12\n\t"
  52374. "ADDS r5, r5, r8\n\t"
  52375. "ADCS r6, r6, r9\n\t"
  52376. "ADC r7, r7, #0x0\n\t"
  52377. /* A[6] * A[8] */
  52378. "LDR r10, [%[a], #32]\n\t"
  52379. "LDR r12, [%[a], #24]\n\t"
  52380. "UMULL r8, r9, r10, r12\n\t"
  52381. "ADDS r5, r5, r8\n\t"
  52382. "ADCS r6, r6, r9\n\t"
  52383. "ADC r7, r7, #0x0\n\t"
  52384. /* A[7] * A[7] */
  52385. "LDR r10, [%[a], #28]\n\t"
  52386. "UMULL r8, r9, r10, r10\n\t"
  52387. "ADDS r5, r5, r5\n\t"
  52388. "ADCS r6, r6, r6\n\t"
  52389. "ADC r7, r7, r7\n\t"
  52390. "ADDS r4, r4, r8\n\t"
  52391. "ADCS r2, r2, r9\n\t"
  52392. "ADC r3, r3, #0x0\n\t"
  52393. "ADDS r4, r4, r5\n\t"
  52394. "ADCS r2, r2, r6\n\t"
  52395. "ADC r3, r3, r7\n\t"
  52396. "STR r4, [sp, #56]\n\t"
  52397. /* A[0] * A[15] */
  52398. "LDR r10, [%[a], #60]\n\t"
  52399. "LDR r12, [%[a]]\n\t"
  52400. "UMULL r5, r6, r10, r12\n\t"
  52401. "MOV r4, #0x0\n\t"
  52402. "MOV r7, #0x0\n\t"
  52403. /* A[1] * A[14] */
  52404. "LDR r10, [%[a], #56]\n\t"
  52405. "LDR r12, [%[a], #4]\n\t"
  52406. "UMULL r8, r9, r10, r12\n\t"
  52407. "ADDS r5, r5, r8\n\t"
  52408. "ADCS r6, r6, r9\n\t"
  52409. "ADC r7, r7, #0x0\n\t"
  52410. /* A[2] * A[13] */
  52411. "LDR r10, [%[a], #52]\n\t"
  52412. "LDR r12, [%[a], #8]\n\t"
  52413. "UMULL r8, r9, r10, r12\n\t"
  52414. "ADDS r5, r5, r8\n\t"
  52415. "ADCS r6, r6, r9\n\t"
  52416. "ADC r7, r7, #0x0\n\t"
  52417. /* A[3] * A[12] */
  52418. "LDR r10, [%[a], #48]\n\t"
  52419. "LDR r12, [%[a], #12]\n\t"
  52420. "UMULL r8, r9, r10, r12\n\t"
  52421. "ADDS r5, r5, r8\n\t"
  52422. "ADCS r6, r6, r9\n\t"
  52423. "ADC r7, r7, #0x0\n\t"
  52424. /* A[4] * A[11] */
  52425. "LDR r10, [%[a], #44]\n\t"
  52426. "LDR r12, [%[a], #16]\n\t"
  52427. "UMULL r8, r9, r10, r12\n\t"
  52428. "ADDS r5, r5, r8\n\t"
  52429. "ADCS r6, r6, r9\n\t"
  52430. "ADC r7, r7, #0x0\n\t"
  52431. /* A[5] * A[10] */
  52432. "LDR r10, [%[a], #40]\n\t"
  52433. "LDR r12, [%[a], #20]\n\t"
  52434. "UMULL r8, r9, r10, r12\n\t"
  52435. "ADDS r5, r5, r8\n\t"
  52436. "ADCS r6, r6, r9\n\t"
  52437. "ADC r7, r7, #0x0\n\t"
  52438. /* A[6] * A[9] */
  52439. "LDR r10, [%[a], #36]\n\t"
  52440. "LDR r12, [%[a], #24]\n\t"
  52441. "UMULL r8, r9, r10, r12\n\t"
  52442. "ADDS r5, r5, r8\n\t"
  52443. "ADCS r6, r6, r9\n\t"
  52444. "ADC r7, r7, #0x0\n\t"
  52445. /* A[7] * A[8] */
  52446. "LDR r10, [%[a], #32]\n\t"
  52447. "LDR r12, [%[a], #28]\n\t"
  52448. "UMULL r8, r9, r10, r12\n\t"
  52449. "ADDS r5, r5, r8\n\t"
  52450. "ADCS r6, r6, r9\n\t"
  52451. "ADC r7, r7, #0x0\n\t"
  52452. "ADDS r5, r5, r5\n\t"
  52453. "ADCS r6, r6, r6\n\t"
  52454. "ADC r7, r7, r7\n\t"
  52455. "ADDS r2, r2, r5\n\t"
  52456. "ADCS r3, r3, r6\n\t"
  52457. "ADC r4, r4, r7\n\t"
  52458. "STR r2, [sp, #60]\n\t"
  52459. /* A[0] * A[16] */
  52460. "LDR r10, [%[a], #64]\n\t"
  52461. "LDR r12, [%[a]]\n\t"
  52462. "UMULL r5, r6, r10, r12\n\t"
  52463. "MOV r2, #0x0\n\t"
  52464. "MOV r7, #0x0\n\t"
  52465. /* A[1] * A[15] */
  52466. "LDR r10, [%[a], #60]\n\t"
  52467. "LDR r12, [%[a], #4]\n\t"
  52468. "UMULL r8, r9, r10, r12\n\t"
  52469. "ADDS r5, r5, r8\n\t"
  52470. "ADCS r6, r6, r9\n\t"
  52471. "ADC r7, r7, #0x0\n\t"
  52472. /* A[2] * A[14] */
  52473. "LDR r10, [%[a], #56]\n\t"
  52474. "LDR r12, [%[a], #8]\n\t"
  52475. "UMULL r8, r9, r10, r12\n\t"
  52476. "ADDS r5, r5, r8\n\t"
  52477. "ADCS r6, r6, r9\n\t"
  52478. "ADC r7, r7, #0x0\n\t"
  52479. /* A[3] * A[13] */
  52480. "LDR r10, [%[a], #52]\n\t"
  52481. "LDR r12, [%[a], #12]\n\t"
  52482. "UMULL r8, r9, r10, r12\n\t"
  52483. "ADDS r5, r5, r8\n\t"
  52484. "ADCS r6, r6, r9\n\t"
  52485. "ADC r7, r7, #0x0\n\t"
  52486. /* A[4] * A[12] */
  52487. "LDR r10, [%[a], #48]\n\t"
  52488. "LDR r12, [%[a], #16]\n\t"
  52489. "UMULL r8, r9, r10, r12\n\t"
  52490. "ADDS r5, r5, r8\n\t"
  52491. "ADCS r6, r6, r9\n\t"
  52492. "ADC r7, r7, #0x0\n\t"
  52493. /* A[5] * A[11] */
  52494. "LDR r10, [%[a], #44]\n\t"
  52495. "LDR r12, [%[a], #20]\n\t"
  52496. "UMULL r8, r9, r10, r12\n\t"
  52497. "ADDS r5, r5, r8\n\t"
  52498. "ADCS r6, r6, r9\n\t"
  52499. "ADC r7, r7, #0x0\n\t"
  52500. /* A[6] * A[10] */
  52501. "LDR r10, [%[a], #40]\n\t"
  52502. "LDR r12, [%[a], #24]\n\t"
  52503. "UMULL r8, r9, r10, r12\n\t"
  52504. "ADDS r5, r5, r8\n\t"
  52505. "ADCS r6, r6, r9\n\t"
  52506. "ADC r7, r7, #0x0\n\t"
  52507. /* A[7] * A[9] */
  52508. "LDR r10, [%[a], #36]\n\t"
  52509. "LDR r12, [%[a], #28]\n\t"
  52510. "UMULL r8, r9, r10, r12\n\t"
  52511. "ADDS r5, r5, r8\n\t"
  52512. "ADCS r6, r6, r9\n\t"
  52513. "ADC r7, r7, #0x0\n\t"
  52514. /* A[8] * A[8] */
  52515. "LDR r10, [%[a], #32]\n\t"
  52516. "UMULL r8, r9, r10, r10\n\t"
  52517. "ADDS r5, r5, r5\n\t"
  52518. "ADCS r6, r6, r6\n\t"
  52519. "ADC r7, r7, r7\n\t"
  52520. "ADDS r3, r3, r8\n\t"
  52521. "ADCS r4, r4, r9\n\t"
  52522. "ADC r2, r2, #0x0\n\t"
  52523. "ADDS r3, r3, r5\n\t"
  52524. "ADCS r4, r4, r6\n\t"
  52525. "ADC r2, r2, r7\n\t"
  52526. "STR r3, [sp, #64]\n\t"
  52527. /* A[1] * A[16] */
  52528. "LDR r10, [%[a], #64]\n\t"
  52529. "LDR r12, [%[a], #4]\n\t"
  52530. "UMULL r5, r6, r10, r12\n\t"
  52531. "MOV r3, #0x0\n\t"
  52532. "MOV r7, #0x0\n\t"
  52533. /* A[2] * A[15] */
  52534. "LDR r10, [%[a], #60]\n\t"
  52535. "LDR r12, [%[a], #8]\n\t"
  52536. "UMULL r8, r9, r10, r12\n\t"
  52537. "ADDS r5, r5, r8\n\t"
  52538. "ADCS r6, r6, r9\n\t"
  52539. "ADC r7, r7, #0x0\n\t"
  52540. /* A[3] * A[14] */
  52541. "LDR r10, [%[a], #56]\n\t"
  52542. "LDR r12, [%[a], #12]\n\t"
  52543. "UMULL r8, r9, r10, r12\n\t"
  52544. "ADDS r5, r5, r8\n\t"
  52545. "ADCS r6, r6, r9\n\t"
  52546. "ADC r7, r7, #0x0\n\t"
  52547. /* A[4] * A[13] */
  52548. "LDR r10, [%[a], #52]\n\t"
  52549. "LDR r12, [%[a], #16]\n\t"
  52550. "UMULL r8, r9, r10, r12\n\t"
  52551. "ADDS r5, r5, r8\n\t"
  52552. "ADCS r6, r6, r9\n\t"
  52553. "ADC r7, r7, #0x0\n\t"
  52554. /* A[5] * A[12] */
  52555. "LDR r10, [%[a], #48]\n\t"
  52556. "LDR r12, [%[a], #20]\n\t"
  52557. "UMULL r8, r9, r10, r12\n\t"
  52558. "ADDS r5, r5, r8\n\t"
  52559. "ADCS r6, r6, r9\n\t"
  52560. "ADC r7, r7, #0x0\n\t"
  52561. /* A[6] * A[11] */
  52562. "LDR r10, [%[a], #44]\n\t"
  52563. "LDR r12, [%[a], #24]\n\t"
  52564. "UMULL r8, r9, r10, r12\n\t"
  52565. "ADDS r5, r5, r8\n\t"
  52566. "ADCS r6, r6, r9\n\t"
  52567. "ADC r7, r7, #0x0\n\t"
  52568. /* A[7] * A[10] */
  52569. "LDR r10, [%[a], #40]\n\t"
  52570. "LDR r12, [%[a], #28]\n\t"
  52571. "UMULL r8, r9, r10, r12\n\t"
  52572. "ADDS r5, r5, r8\n\t"
  52573. "ADCS r6, r6, r9\n\t"
  52574. "ADC r7, r7, #0x0\n\t"
  52575. /* A[8] * A[9] */
  52576. "LDR r10, [%[a], #36]\n\t"
  52577. "LDR r12, [%[a], #32]\n\t"
  52578. "UMULL r8, r9, r10, r12\n\t"
  52579. "ADDS r5, r5, r8\n\t"
  52580. "ADCS r6, r6, r9\n\t"
  52581. "ADC r7, r7, #0x0\n\t"
  52582. "ADDS r5, r5, r5\n\t"
  52583. "ADCS r6, r6, r6\n\t"
  52584. "ADC r7, r7, r7\n\t"
  52585. "ADDS r4, r4, r5\n\t"
  52586. "ADCS r2, r2, r6\n\t"
  52587. "ADC r3, r3, r7\n\t"
  52588. "STR r4, [%[r], #68]\n\t"
  52589. /* A[2] * A[16] */
  52590. "LDR r10, [%[a], #64]\n\t"
  52591. "LDR r12, [%[a], #8]\n\t"
  52592. "UMULL r5, r6, r10, r12\n\t"
  52593. "MOV r4, #0x0\n\t"
  52594. "MOV r7, #0x0\n\t"
  52595. /* A[3] * A[15] */
  52596. "LDR r10, [%[a], #60]\n\t"
  52597. "LDR r12, [%[a], #12]\n\t"
  52598. "UMULL r8, r9, r10, r12\n\t"
  52599. "ADDS r5, r5, r8\n\t"
  52600. "ADCS r6, r6, r9\n\t"
  52601. "ADC r7, r7, #0x0\n\t"
  52602. /* A[4] * A[14] */
  52603. "LDR r10, [%[a], #56]\n\t"
  52604. "LDR r12, [%[a], #16]\n\t"
  52605. "UMULL r8, r9, r10, r12\n\t"
  52606. "ADDS r5, r5, r8\n\t"
  52607. "ADCS r6, r6, r9\n\t"
  52608. "ADC r7, r7, #0x0\n\t"
  52609. /* A[5] * A[13] */
  52610. "LDR r10, [%[a], #52]\n\t"
  52611. "LDR r12, [%[a], #20]\n\t"
  52612. "UMULL r8, r9, r10, r12\n\t"
  52613. "ADDS r5, r5, r8\n\t"
  52614. "ADCS r6, r6, r9\n\t"
  52615. "ADC r7, r7, #0x0\n\t"
  52616. /* A[6] * A[12] */
  52617. "LDR r10, [%[a], #48]\n\t"
  52618. "LDR r12, [%[a], #24]\n\t"
  52619. "UMULL r8, r9, r10, r12\n\t"
  52620. "ADDS r5, r5, r8\n\t"
  52621. "ADCS r6, r6, r9\n\t"
  52622. "ADC r7, r7, #0x0\n\t"
  52623. /* A[7] * A[11] */
  52624. "LDR r10, [%[a], #44]\n\t"
  52625. "LDR r12, [%[a], #28]\n\t"
  52626. "UMULL r8, r9, r10, r12\n\t"
  52627. "ADDS r5, r5, r8\n\t"
  52628. "ADCS r6, r6, r9\n\t"
  52629. "ADC r7, r7, #0x0\n\t"
  52630. /* A[8] * A[10] */
  52631. "LDR r10, [%[a], #40]\n\t"
  52632. "LDR r12, [%[a], #32]\n\t"
  52633. "UMULL r8, r9, r10, r12\n\t"
  52634. "ADDS r5, r5, r8\n\t"
  52635. "ADCS r6, r6, r9\n\t"
  52636. "ADC r7, r7, #0x0\n\t"
  52637. /* A[9] * A[9] */
  52638. "LDR r10, [%[a], #36]\n\t"
  52639. "UMULL r8, r9, r10, r10\n\t"
  52640. "ADDS r5, r5, r5\n\t"
  52641. "ADCS r6, r6, r6\n\t"
  52642. "ADC r7, r7, r7\n\t"
  52643. "ADDS r2, r2, r8\n\t"
  52644. "ADCS r3, r3, r9\n\t"
  52645. "ADC r4, r4, #0x0\n\t"
  52646. "ADDS r2, r2, r5\n\t"
  52647. "ADCS r3, r3, r6\n\t"
  52648. "ADC r4, r4, r7\n\t"
  52649. "STR r2, [%[r], #72]\n\t"
  52650. /* A[3] * A[16] */
  52651. "LDR r10, [%[a], #64]\n\t"
  52652. "LDR r12, [%[a], #12]\n\t"
  52653. "UMULL r5, r6, r10, r12\n\t"
  52654. "MOV r2, #0x0\n\t"
  52655. "MOV r7, #0x0\n\t"
  52656. /* A[4] * A[15] */
  52657. "LDR r10, [%[a], #60]\n\t"
  52658. "LDR r12, [%[a], #16]\n\t"
  52659. "UMULL r8, r9, r10, r12\n\t"
  52660. "ADDS r5, r5, r8\n\t"
  52661. "ADCS r6, r6, r9\n\t"
  52662. "ADC r7, r7, #0x0\n\t"
  52663. /* A[5] * A[14] */
  52664. "LDR r10, [%[a], #56]\n\t"
  52665. "LDR r12, [%[a], #20]\n\t"
  52666. "UMULL r8, r9, r10, r12\n\t"
  52667. "ADDS r5, r5, r8\n\t"
  52668. "ADCS r6, r6, r9\n\t"
  52669. "ADC r7, r7, #0x0\n\t"
  52670. /* A[6] * A[13] */
  52671. "LDR r10, [%[a], #52]\n\t"
  52672. "LDR r12, [%[a], #24]\n\t"
  52673. "UMULL r8, r9, r10, r12\n\t"
  52674. "ADDS r5, r5, r8\n\t"
  52675. "ADCS r6, r6, r9\n\t"
  52676. "ADC r7, r7, #0x0\n\t"
  52677. /* A[7] * A[12] */
  52678. "LDR r10, [%[a], #48]\n\t"
  52679. "LDR r12, [%[a], #28]\n\t"
  52680. "UMULL r8, r9, r10, r12\n\t"
  52681. "ADDS r5, r5, r8\n\t"
  52682. "ADCS r6, r6, r9\n\t"
  52683. "ADC r7, r7, #0x0\n\t"
  52684. /* A[8] * A[11] */
  52685. "LDR r10, [%[a], #44]\n\t"
  52686. "LDR r12, [%[a], #32]\n\t"
  52687. "UMULL r8, r9, r10, r12\n\t"
  52688. "ADDS r5, r5, r8\n\t"
  52689. "ADCS r6, r6, r9\n\t"
  52690. "ADC r7, r7, #0x0\n\t"
  52691. /* A[9] * A[10] */
  52692. "LDR r10, [%[a], #40]\n\t"
  52693. "LDR r12, [%[a], #36]\n\t"
  52694. "UMULL r8, r9, r10, r12\n\t"
  52695. "ADDS r5, r5, r8\n\t"
  52696. "ADCS r6, r6, r9\n\t"
  52697. "ADC r7, r7, #0x0\n\t"
  52698. "ADDS r5, r5, r5\n\t"
  52699. "ADCS r6, r6, r6\n\t"
  52700. "ADC r7, r7, r7\n\t"
  52701. "ADDS r3, r3, r5\n\t"
  52702. "ADCS r4, r4, r6\n\t"
  52703. "ADC r2, r2, r7\n\t"
  52704. "STR r3, [%[r], #76]\n\t"
  52705. /* A[4] * A[16] */
  52706. "LDR r10, [%[a], #64]\n\t"
  52707. "LDR r12, [%[a], #16]\n\t"
  52708. "UMULL r5, r6, r10, r12\n\t"
  52709. "MOV r3, #0x0\n\t"
  52710. "MOV r7, #0x0\n\t"
  52711. /* A[5] * A[15] */
  52712. "LDR r10, [%[a], #60]\n\t"
  52713. "LDR r12, [%[a], #20]\n\t"
  52714. "UMULL r8, r9, r10, r12\n\t"
  52715. "ADDS r5, r5, r8\n\t"
  52716. "ADCS r6, r6, r9\n\t"
  52717. "ADC r7, r7, #0x0\n\t"
  52718. /* A[6] * A[14] */
  52719. "LDR r10, [%[a], #56]\n\t"
  52720. "LDR r12, [%[a], #24]\n\t"
  52721. "UMULL r8, r9, r10, r12\n\t"
  52722. "ADDS r5, r5, r8\n\t"
  52723. "ADCS r6, r6, r9\n\t"
  52724. "ADC r7, r7, #0x0\n\t"
  52725. /* A[7] * A[13] */
  52726. "LDR r10, [%[a], #52]\n\t"
  52727. "LDR r12, [%[a], #28]\n\t"
  52728. "UMULL r8, r9, r10, r12\n\t"
  52729. "ADDS r5, r5, r8\n\t"
  52730. "ADCS r6, r6, r9\n\t"
  52731. "ADC r7, r7, #0x0\n\t"
  52732. /* A[8] * A[12] */
  52733. "LDR r10, [%[a], #48]\n\t"
  52734. "LDR r12, [%[a], #32]\n\t"
  52735. "UMULL r8, r9, r10, r12\n\t"
  52736. "ADDS r5, r5, r8\n\t"
  52737. "ADCS r6, r6, r9\n\t"
  52738. "ADC r7, r7, #0x0\n\t"
  52739. /* A[9] * A[11] */
  52740. "LDR r10, [%[a], #44]\n\t"
  52741. "LDR r12, [%[a], #36]\n\t"
  52742. "UMULL r8, r9, r10, r12\n\t"
  52743. "ADDS r5, r5, r8\n\t"
  52744. "ADCS r6, r6, r9\n\t"
  52745. "ADC r7, r7, #0x0\n\t"
  52746. /* A[10] * A[10] */
  52747. "LDR r10, [%[a], #40]\n\t"
  52748. "UMULL r8, r9, r10, r10\n\t"
  52749. "ADDS r5, r5, r5\n\t"
  52750. "ADCS r6, r6, r6\n\t"
  52751. "ADC r7, r7, r7\n\t"
  52752. "ADDS r4, r4, r8\n\t"
  52753. "ADCS r2, r2, r9\n\t"
  52754. "ADC r3, r3, #0x0\n\t"
  52755. "ADDS r4, r4, r5\n\t"
  52756. "ADCS r2, r2, r6\n\t"
  52757. "ADC r3, r3, r7\n\t"
  52758. "STR r4, [%[r], #80]\n\t"
  52759. /* A[5] * A[16] */
  52760. "LDR r10, [%[a], #64]\n\t"
  52761. "LDR r12, [%[a], #20]\n\t"
  52762. "UMULL r5, r6, r10, r12\n\t"
  52763. "MOV r4, #0x0\n\t"
  52764. "MOV r7, #0x0\n\t"
  52765. /* A[6] * A[15] */
  52766. "LDR r10, [%[a], #60]\n\t"
  52767. "LDR r12, [%[a], #24]\n\t"
  52768. "UMULL r8, r9, r10, r12\n\t"
  52769. "ADDS r5, r5, r8\n\t"
  52770. "ADCS r6, r6, r9\n\t"
  52771. "ADC r7, r7, #0x0\n\t"
  52772. /* A[7] * A[14] */
  52773. "LDR r10, [%[a], #56]\n\t"
  52774. "LDR r12, [%[a], #28]\n\t"
  52775. "UMULL r8, r9, r10, r12\n\t"
  52776. "ADDS r5, r5, r8\n\t"
  52777. "ADCS r6, r6, r9\n\t"
  52778. "ADC r7, r7, #0x0\n\t"
  52779. /* A[8] * A[13] */
  52780. "LDR r10, [%[a], #52]\n\t"
  52781. "LDR r12, [%[a], #32]\n\t"
  52782. "UMULL r8, r9, r10, r12\n\t"
  52783. "ADDS r5, r5, r8\n\t"
  52784. "ADCS r6, r6, r9\n\t"
  52785. "ADC r7, r7, #0x0\n\t"
  52786. /* A[9] * A[12] */
  52787. "LDR r10, [%[a], #48]\n\t"
  52788. "LDR r12, [%[a], #36]\n\t"
  52789. "UMULL r8, r9, r10, r12\n\t"
  52790. "ADDS r5, r5, r8\n\t"
  52791. "ADCS r6, r6, r9\n\t"
  52792. "ADC r7, r7, #0x0\n\t"
  52793. /* A[10] * A[11] */
  52794. "LDR r10, [%[a], #44]\n\t"
  52795. "LDR r12, [%[a], #40]\n\t"
  52796. "UMULL r8, r9, r10, r12\n\t"
  52797. "ADDS r5, r5, r8\n\t"
  52798. "ADCS r6, r6, r9\n\t"
  52799. "ADC r7, r7, #0x0\n\t"
  52800. "ADDS r5, r5, r5\n\t"
  52801. "ADCS r6, r6, r6\n\t"
  52802. "ADC r7, r7, r7\n\t"
  52803. "ADDS r2, r2, r5\n\t"
  52804. "ADCS r3, r3, r6\n\t"
  52805. "ADC r4, r4, r7\n\t"
  52806. "STR r2, [%[r], #84]\n\t"
  52807. /* A[6] * A[16] */
  52808. "LDR r10, [%[a], #64]\n\t"
  52809. "LDR r12, [%[a], #24]\n\t"
  52810. "UMULL r5, r6, r10, r12\n\t"
  52811. "MOV r2, #0x0\n\t"
  52812. "MOV r7, #0x0\n\t"
  52813. /* A[7] * A[15] */
  52814. "LDR r10, [%[a], #60]\n\t"
  52815. "LDR r12, [%[a], #28]\n\t"
  52816. "UMULL r8, r9, r10, r12\n\t"
  52817. "ADDS r5, r5, r8\n\t"
  52818. "ADCS r6, r6, r9\n\t"
  52819. "ADC r7, r7, #0x0\n\t"
  52820. /* A[8] * A[14] */
  52821. "LDR r10, [%[a], #56]\n\t"
  52822. "LDR r12, [%[a], #32]\n\t"
  52823. "UMULL r8, r9, r10, r12\n\t"
  52824. "ADDS r5, r5, r8\n\t"
  52825. "ADCS r6, r6, r9\n\t"
  52826. "ADC r7, r7, #0x0\n\t"
  52827. /* A[9] * A[13] */
  52828. "LDR r10, [%[a], #52]\n\t"
  52829. "LDR r12, [%[a], #36]\n\t"
  52830. "UMULL r8, r9, r10, r12\n\t"
  52831. "ADDS r5, r5, r8\n\t"
  52832. "ADCS r6, r6, r9\n\t"
  52833. "ADC r7, r7, #0x0\n\t"
  52834. /* A[10] * A[12] */
  52835. "LDR r10, [%[a], #48]\n\t"
  52836. "LDR r12, [%[a], #40]\n\t"
  52837. "UMULL r8, r9, r10, r12\n\t"
  52838. "ADDS r5, r5, r8\n\t"
  52839. "ADCS r6, r6, r9\n\t"
  52840. "ADC r7, r7, #0x0\n\t"
  52841. /* A[11] * A[11] */
  52842. "LDR r10, [%[a], #44]\n\t"
  52843. "UMULL r8, r9, r10, r10\n\t"
  52844. "ADDS r5, r5, r5\n\t"
  52845. "ADCS r6, r6, r6\n\t"
  52846. "ADC r7, r7, r7\n\t"
  52847. "ADDS r3, r3, r8\n\t"
  52848. "ADCS r4, r4, r9\n\t"
  52849. "ADC r2, r2, #0x0\n\t"
  52850. "ADDS r3, r3, r5\n\t"
  52851. "ADCS r4, r4, r6\n\t"
  52852. "ADC r2, r2, r7\n\t"
  52853. "STR r3, [%[r], #88]\n\t"
  52854. /* A[7] * A[16] */
  52855. "LDR r10, [%[a], #64]\n\t"
  52856. "LDR r12, [%[a], #28]\n\t"
  52857. "UMULL r5, r6, r10, r12\n\t"
  52858. "MOV r3, #0x0\n\t"
  52859. "MOV r7, #0x0\n\t"
  52860. /* A[8] * A[15] */
  52861. "LDR r10, [%[a], #60]\n\t"
  52862. "LDR r12, [%[a], #32]\n\t"
  52863. "UMULL r8, r9, r10, r12\n\t"
  52864. "ADDS r5, r5, r8\n\t"
  52865. "ADCS r6, r6, r9\n\t"
  52866. "ADC r7, r7, #0x0\n\t"
  52867. /* A[9] * A[14] */
  52868. "LDR r10, [%[a], #56]\n\t"
  52869. "LDR r12, [%[a], #36]\n\t"
  52870. "UMULL r8, r9, r10, r12\n\t"
  52871. "ADDS r5, r5, r8\n\t"
  52872. "ADCS r6, r6, r9\n\t"
  52873. "ADC r7, r7, #0x0\n\t"
  52874. /* A[10] * A[13] */
  52875. "LDR r10, [%[a], #52]\n\t"
  52876. "LDR r12, [%[a], #40]\n\t"
  52877. "UMULL r8, r9, r10, r12\n\t"
  52878. "ADDS r5, r5, r8\n\t"
  52879. "ADCS r6, r6, r9\n\t"
  52880. "ADC r7, r7, #0x0\n\t"
  52881. /* A[11] * A[12] */
  52882. "LDR r10, [%[a], #48]\n\t"
  52883. "LDR r12, [%[a], #44]\n\t"
  52884. "UMULL r8, r9, r10, r12\n\t"
  52885. "ADDS r5, r5, r8\n\t"
  52886. "ADCS r6, r6, r9\n\t"
  52887. "ADC r7, r7, #0x0\n\t"
  52888. "ADDS r5, r5, r5\n\t"
  52889. "ADCS r6, r6, r6\n\t"
  52890. "ADC r7, r7, r7\n\t"
  52891. "ADDS r4, r4, r5\n\t"
  52892. "ADCS r2, r2, r6\n\t"
  52893. "ADC r3, r3, r7\n\t"
  52894. "STR r4, [%[r], #92]\n\t"
  52895. /* A[8] * A[16] */
  52896. "LDR r10, [%[a], #64]\n\t"
  52897. "LDR r12, [%[a], #32]\n\t"
  52898. "UMULL r5, r6, r10, r12\n\t"
  52899. "MOV r4, #0x0\n\t"
  52900. "MOV r7, #0x0\n\t"
  52901. /* A[9] * A[15] */
  52902. "LDR r10, [%[a], #60]\n\t"
  52903. "LDR r12, [%[a], #36]\n\t"
  52904. "UMULL r8, r9, r10, r12\n\t"
  52905. "ADDS r5, r5, r8\n\t"
  52906. "ADCS r6, r6, r9\n\t"
  52907. "ADC r7, r7, #0x0\n\t"
  52908. /* A[10] * A[14] */
  52909. "LDR r10, [%[a], #56]\n\t"
  52910. "LDR r12, [%[a], #40]\n\t"
  52911. "UMULL r8, r9, r10, r12\n\t"
  52912. "ADDS r5, r5, r8\n\t"
  52913. "ADCS r6, r6, r9\n\t"
  52914. "ADC r7, r7, #0x0\n\t"
  52915. /* A[11] * A[13] */
  52916. "LDR r10, [%[a], #52]\n\t"
  52917. "LDR r12, [%[a], #44]\n\t"
  52918. "UMULL r8, r9, r10, r12\n\t"
  52919. "ADDS r5, r5, r8\n\t"
  52920. "ADCS r6, r6, r9\n\t"
  52921. "ADC r7, r7, #0x0\n\t"
  52922. /* A[12] * A[12] */
  52923. "LDR r10, [%[a], #48]\n\t"
  52924. "UMULL r8, r9, r10, r10\n\t"
  52925. "ADDS r5, r5, r5\n\t"
  52926. "ADCS r6, r6, r6\n\t"
  52927. "ADC r7, r7, r7\n\t"
  52928. "ADDS r2, r2, r8\n\t"
  52929. "ADCS r3, r3, r9\n\t"
  52930. "ADC r4, r4, #0x0\n\t"
  52931. "ADDS r2, r2, r5\n\t"
  52932. "ADCS r3, r3, r6\n\t"
  52933. "ADC r4, r4, r7\n\t"
  52934. "STR r2, [%[r], #96]\n\t"
  52935. /* A[9] * A[16] */
  52936. "LDR r10, [%[a], #64]\n\t"
  52937. "LDR r12, [%[a], #36]\n\t"
  52938. "UMULL r5, r6, r10, r12\n\t"
  52939. "MOV r2, #0x0\n\t"
  52940. "MOV r7, #0x0\n\t"
  52941. /* A[10] * A[15] */
  52942. "LDR r10, [%[a], #60]\n\t"
  52943. "LDR r12, [%[a], #40]\n\t"
  52944. "UMULL r8, r9, r10, r12\n\t"
  52945. "ADDS r5, r5, r8\n\t"
  52946. "ADCS r6, r6, r9\n\t"
  52947. "ADC r7, r7, #0x0\n\t"
  52948. /* A[11] * A[14] */
  52949. "LDR r10, [%[a], #56]\n\t"
  52950. "LDR r12, [%[a], #44]\n\t"
  52951. "UMULL r8, r9, r10, r12\n\t"
  52952. "ADDS r5, r5, r8\n\t"
  52953. "ADCS r6, r6, r9\n\t"
  52954. "ADC r7, r7, #0x0\n\t"
  52955. /* A[12] * A[13] */
  52956. "LDR r10, [%[a], #52]\n\t"
  52957. "LDR r12, [%[a], #48]\n\t"
  52958. "UMULL r8, r9, r10, r12\n\t"
  52959. "ADDS r5, r5, r8\n\t"
  52960. "ADCS r6, r6, r9\n\t"
  52961. "ADC r7, r7, #0x0\n\t"
  52962. "ADDS r5, r5, r5\n\t"
  52963. "ADCS r6, r6, r6\n\t"
  52964. "ADC r7, r7, r7\n\t"
  52965. "ADDS r3, r3, r5\n\t"
  52966. "ADCS r4, r4, r6\n\t"
  52967. "ADC r2, r2, r7\n\t"
  52968. "STR r3, [%[r], #100]\n\t"
  52969. /* A[10] * A[16] */
  52970. "LDR r10, [%[a], #64]\n\t"
  52971. "LDR r12, [%[a], #40]\n\t"
  52972. "UMULL r5, r6, r10, r12\n\t"
  52973. "MOV r3, #0x0\n\t"
  52974. "MOV r7, #0x0\n\t"
  52975. /* A[11] * A[15] */
  52976. "LDR r10, [%[a], #60]\n\t"
  52977. "LDR r12, [%[a], #44]\n\t"
  52978. "UMULL r8, r9, r10, r12\n\t"
  52979. "ADDS r5, r5, r8\n\t"
  52980. "ADCS r6, r6, r9\n\t"
  52981. "ADC r7, r7, #0x0\n\t"
  52982. /* A[12] * A[14] */
  52983. "LDR r10, [%[a], #56]\n\t"
  52984. "LDR r12, [%[a], #48]\n\t"
  52985. "UMULL r8, r9, r10, r12\n\t"
  52986. "ADDS r5, r5, r8\n\t"
  52987. "ADCS r6, r6, r9\n\t"
  52988. "ADC r7, r7, #0x0\n\t"
  52989. /* A[13] * A[13] */
  52990. "LDR r10, [%[a], #52]\n\t"
  52991. "UMULL r8, r9, r10, r10\n\t"
  52992. "ADDS r5, r5, r5\n\t"
  52993. "ADCS r6, r6, r6\n\t"
  52994. "ADC r7, r7, r7\n\t"
  52995. "ADDS r4, r4, r8\n\t"
  52996. "ADCS r2, r2, r9\n\t"
  52997. "ADC r3, r3, #0x0\n\t"
  52998. "ADDS r4, r4, r5\n\t"
  52999. "ADCS r2, r2, r6\n\t"
  53000. "ADC r3, r3, r7\n\t"
  53001. "STR r4, [%[r], #104]\n\t"
  53002. /* A[11] * A[16] */
  53003. "LDR r10, [%[a], #64]\n\t"
  53004. "LDR r12, [%[a], #44]\n\t"
  53005. "UMULL r5, r6, r10, r12\n\t"
  53006. "MOV r4, #0x0\n\t"
  53007. "MOV r7, #0x0\n\t"
  53008. /* A[12] * A[15] */
  53009. "LDR r10, [%[a], #60]\n\t"
  53010. "LDR r12, [%[a], #48]\n\t"
  53011. "UMULL r8, r9, r10, r12\n\t"
  53012. "ADDS r5, r5, r8\n\t"
  53013. "ADCS r6, r6, r9\n\t"
  53014. "ADC r7, r7, #0x0\n\t"
  53015. /* A[13] * A[14] */
  53016. "LDR r10, [%[a], #56]\n\t"
  53017. "LDR r12, [%[a], #52]\n\t"
  53018. "UMULL r8, r9, r10, r12\n\t"
  53019. "ADDS r5, r5, r8\n\t"
  53020. "ADCS r6, r6, r9\n\t"
  53021. "ADC r7, r7, #0x0\n\t"
  53022. "ADDS r5, r5, r5\n\t"
  53023. "ADCS r6, r6, r6\n\t"
  53024. "ADC r7, r7, r7\n\t"
  53025. "ADDS r2, r2, r5\n\t"
  53026. "ADCS r3, r3, r6\n\t"
  53027. "ADC r4, r4, r7\n\t"
  53028. "STR r2, [%[r], #108]\n\t"
  53029. /* A[12] * A[16] */
  53030. "LDR r10, [%[a], #64]\n\t"
  53031. "LDR r12, [%[a], #48]\n\t"
  53032. "UMULL r8, r9, r10, r12\n\t"
  53033. "ADDS r3, r3, r8\n\t"
  53034. "ADCS r4, r4, r9\n\t"
  53035. "MOV r2, #0x0\n\t"
  53036. "ADC r2, r2, #0x0\n\t"
  53037. "ADDS r3, r3, r8\n\t"
  53038. "ADCS r4, r4, r9\n\t"
  53039. "MOV r2, #0x0\n\t"
  53040. "ADC r2, r2, #0x0\n\t"
  53041. /* A[13] * A[15] */
  53042. "LDR r10, [%[a], #60]\n\t"
  53043. "LDR r12, [%[a], #52]\n\t"
  53044. "UMULL r8, r9, r10, r12\n\t"
  53045. "ADDS r3, r3, r8\n\t"
  53046. "ADCS r4, r4, r9\n\t"
  53047. "ADC r2, r2, #0x0\n\t"
  53048. "ADDS r3, r3, r8\n\t"
  53049. "ADCS r4, r4, r9\n\t"
  53050. "ADC r2, r2, #0x0\n\t"
  53051. /* A[14] * A[14] */
  53052. "LDR r10, [%[a], #56]\n\t"
  53053. "UMULL r8, r9, r10, r10\n\t"
  53054. "ADDS r3, r3, r8\n\t"
  53055. "ADCS r4, r4, r9\n\t"
  53056. "ADC r2, r2, #0x0\n\t"
  53057. "STR r3, [%[r], #112]\n\t"
  53058. /* A[13] * A[16] */
  53059. "LDR r10, [%[a], #64]\n\t"
  53060. "LDR r12, [%[a], #52]\n\t"
  53061. "UMULL r8, r9, r10, r12\n\t"
  53062. "ADDS r4, r4, r8\n\t"
  53063. "ADCS r2, r2, r9\n\t"
  53064. "MOV r3, #0x0\n\t"
  53065. "ADC r3, r3, #0x0\n\t"
  53066. "ADDS r4, r4, r8\n\t"
  53067. "ADCS r2, r2, r9\n\t"
  53068. "MOV r3, #0x0\n\t"
  53069. "ADC r3, r3, #0x0\n\t"
  53070. /* A[14] * A[15] */
  53071. "LDR r10, [%[a], #60]\n\t"
  53072. "LDR r12, [%[a], #56]\n\t"
  53073. "UMULL r8, r9, r10, r12\n\t"
  53074. "ADDS r4, r4, r8\n\t"
  53075. "ADCS r2, r2, r9\n\t"
  53076. "ADC r3, r3, #0x0\n\t"
  53077. "ADDS r4, r4, r8\n\t"
  53078. "ADCS r2, r2, r9\n\t"
  53079. "ADC r3, r3, #0x0\n\t"
  53080. "STR r4, [%[r], #116]\n\t"
  53081. /* A[14] * A[16] */
  53082. "LDR r10, [%[a], #64]\n\t"
  53083. "LDR r12, [%[a], #56]\n\t"
  53084. "UMULL r8, r9, r10, r12\n\t"
  53085. "ADDS r2, r2, r8\n\t"
  53086. "ADCS r3, r3, r9\n\t"
  53087. "MOV r4, #0x0\n\t"
  53088. "ADC r4, r4, #0x0\n\t"
  53089. "ADDS r2, r2, r8\n\t"
  53090. "ADCS r3, r3, r9\n\t"
  53091. "MOV r4, #0x0\n\t"
  53092. "ADC r4, r4, #0x0\n\t"
  53093. /* A[15] * A[15] */
  53094. "LDR r10, [%[a], #60]\n\t"
  53095. "UMULL r8, r9, r10, r10\n\t"
  53096. "ADDS r2, r2, r8\n\t"
  53097. "ADCS r3, r3, r9\n\t"
  53098. "ADC r4, r4, #0x0\n\t"
  53099. "STR r2, [%[r], #120]\n\t"
  53100. /* A[15] * A[16] */
  53101. "LDR r10, [%[a], #64]\n\t"
  53102. "LDR r12, [%[a], #60]\n\t"
  53103. "UMULL r8, r9, r10, r12\n\t"
  53104. "ADDS r3, r3, r8\n\t"
  53105. "ADCS r4, r4, r9\n\t"
  53106. "MOV r2, #0x0\n\t"
  53107. "ADC r2, r2, #0x0\n\t"
  53108. "ADDS r3, r3, r8\n\t"
  53109. "ADCS r4, r4, r9\n\t"
  53110. "MOV r2, #0x0\n\t"
  53111. "ADC r2, r2, #0x0\n\t"
  53112. "STR r3, [%[r], #124]\n\t"
  53113. /* A[16] * A[16] */
  53114. "LDR r10, [%[a], #64]\n\t"
  53115. "UMLAL r4, r2, r10, r10\n\t"
  53116. "STR r4, [%[r], #128]\n\t"
  53117. "STR r2, [%[r], #132]\n\t"
  53118. "LDM sp!, {r2, r3, r4, r8}\n\t"
  53119. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  53120. "LDM sp!, {r2, r3, r4, r8}\n\t"
  53121. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  53122. "LDM sp!, {r2, r3, r4, r8}\n\t"
  53123. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  53124. "LDM sp!, {r2, r3, r4, r8}\n\t"
  53125. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  53126. "LDM sp!, {r2}\n\t"
  53127. "STM %[r]!, {r2}\n\t"
  53128. : [r] "+r" (r), [a] "+r" (a)
  53129. :
  53130. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "cc"
  53131. );
  53132. }
  53133. #endif /* WOLFSSL_SP_SMALL */
  53134. #ifdef WOLFSSL_SP_SMALL
  53135. /* Add b to a into r. (r = a + b)
  53136. *
  53137. * r A single precision integer.
  53138. * a A single precision integer.
  53139. * b A single precision integer.
  53140. */
  53141. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53142. static sp_digit sp_521_add_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  53143. #else
  53144. static sp_digit sp_521_add_17(sp_digit* r, const sp_digit* a, const sp_digit* b)
  53145. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53146. {
  53147. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53148. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  53149. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  53150. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  53151. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53152. __asm__ __volatile__ (
  53153. "MOV r3, #0x0\n\t"
  53154. "ADD r12, %[a], #0x40\n\t"
  53155. "\n"
  53156. "L_sp_521_add_17_word:\n\t"
  53157. "ADDS r3, r3, #0xffffffff\n\t"
  53158. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  53159. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  53160. "ADCS r4, r4, r8\n\t"
  53161. "ADCS r5, r5, r9\n\t"
  53162. "ADCS r6, r6, r10\n\t"
  53163. "ADCS r7, r7, r11\n\t"
  53164. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  53165. "MOV r4, #0x0\n\t"
  53166. "ADC r3, r4, #0x0\n\t"
  53167. "CMP %[a], r12\n\t"
  53168. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  53169. "BNE L_sp_521_add_17_word\n\t"
  53170. #else
  53171. "BNE.N L_sp_521_add_17_word\n\t"
  53172. #endif
  53173. "ADDS r3, r3, #0xffffffff\n\t"
  53174. "LDM %[a], {r4}\n\t"
  53175. "LDM %[b], {r8}\n\t"
  53176. "ADCS r4, r4, r8\n\t"
  53177. "STM %[r]!, {r4}\n\t"
  53178. "MOV r4, #0x0\n\t"
  53179. "ADC %[r], r4, #0x0\n\t"
  53180. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  53181. :
  53182. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  53183. );
  53184. return (uint32_t)(size_t)r;
  53185. }
  53186. #else
  53187. /* Add b to a into r. (r = a + b)
  53188. *
  53189. * r A single precision integer.
  53190. * a A single precision integer.
  53191. * b A single precision integer.
  53192. */
  53193. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53194. static sp_digit sp_521_add_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  53195. #else
  53196. static sp_digit sp_521_add_17(sp_digit* r, const sp_digit* a, const sp_digit* b)
  53197. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53198. {
  53199. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53200. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  53201. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  53202. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  53203. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53204. __asm__ __volatile__ (
  53205. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  53206. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  53207. "ADDS r3, r3, r7\n\t"
  53208. "ADCS r4, r4, r8\n\t"
  53209. "ADCS r5, r5, r9\n\t"
  53210. "ADCS r6, r6, r10\n\t"
  53211. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  53212. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  53213. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  53214. "ADCS r3, r3, r7\n\t"
  53215. "ADCS r4, r4, r8\n\t"
  53216. "ADCS r5, r5, r9\n\t"
  53217. "ADCS r6, r6, r10\n\t"
  53218. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  53219. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  53220. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  53221. "ADCS r3, r3, r7\n\t"
  53222. "ADCS r4, r4, r8\n\t"
  53223. "ADCS r5, r5, r9\n\t"
  53224. "ADCS r6, r6, r10\n\t"
  53225. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  53226. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  53227. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  53228. "ADCS r3, r3, r7\n\t"
  53229. "ADCS r4, r4, r8\n\t"
  53230. "ADCS r5, r5, r9\n\t"
  53231. "ADCS r6, r6, r10\n\t"
  53232. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  53233. "LDM %[a]!, {r3}\n\t"
  53234. "LDM %[b]!, {r7}\n\t"
  53235. "ADCS r3, r3, r7\n\t"
  53236. "STM %[r]!, {r3}\n\t"
  53237. "MOV %[r], #0x0\n\t"
  53238. "ADC %[r], %[r], #0x0\n\t"
  53239. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  53240. :
  53241. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  53242. );
  53243. return (uint32_t)(size_t)r;
  53244. }
  53245. #endif /* WOLFSSL_SP_SMALL */
  53246. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  53247. *
  53248. * r The resulting Montgomery form number.
  53249. * a The number to convert.
  53250. * m The modulus (prime).
  53251. * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
  53252. */
  53253. static int sp_521_mod_mul_norm_17(sp_digit* r, const sp_digit* a, const sp_digit* m)
  53254. {
  53255. (void)m;
  53256. if (r != a) {
  53257. XMEMCPY(r, a, 17 * sizeof(sp_digit));
  53258. }
  53259. return MP_OKAY;
  53260. }
  53261. /* Convert an mp_int to an array of sp_digit.
  53262. *
  53263. * r A single precision integer.
  53264. * size Maximum number of bytes to convert
  53265. * a A multi-precision integer.
  53266. */
  53267. static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a)
  53268. {
  53269. #if DIGIT_BIT == 32
  53270. int i;
  53271. sp_digit j = (sp_digit)0 - (sp_digit)a->used;
  53272. int o = 0;
  53273. for (i = 0; i < size; i++) {
  53274. sp_digit mask = (sp_digit)0 - (j >> 31);
  53275. r[i] = a->dp[o] & mask;
  53276. j++;
  53277. o += (int)(j >> 31);
  53278. }
  53279. #elif DIGIT_BIT > 32
  53280. unsigned int i;
  53281. int j = 0;
  53282. word32 s = 0;
  53283. r[0] = 0;
  53284. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  53285. r[j] |= ((sp_digit)a->dp[i] << s);
  53286. r[j] &= 0xffffffff;
  53287. s = 32U - s;
  53288. if (j + 1 >= size) {
  53289. break;
  53290. }
  53291. /* lint allow cast of mismatch word32 and mp_digit */
  53292. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  53293. while ((s + 32U) <= (word32)DIGIT_BIT) {
  53294. s += 32U;
  53295. r[j] &= 0xffffffff;
  53296. if (j + 1 >= size) {
  53297. break;
  53298. }
  53299. if (s < (word32)DIGIT_BIT) {
  53300. /* lint allow cast of mismatch word32 and mp_digit */
  53301. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  53302. }
  53303. else {
  53304. r[++j] = (sp_digit)0;
  53305. }
  53306. }
  53307. s = (word32)DIGIT_BIT - s;
  53308. }
  53309. for (j++; j < size; j++) {
  53310. r[j] = 0;
  53311. }
  53312. #else
  53313. unsigned int i;
  53314. int j = 0;
  53315. int s = 0;
  53316. r[0] = 0;
  53317. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  53318. r[j] |= ((sp_digit)a->dp[i]) << s;
  53319. if (s + DIGIT_BIT >= 32) {
  53320. r[j] &= 0xffffffff;
  53321. if (j + 1 >= size) {
  53322. break;
  53323. }
  53324. s = 32 - s;
  53325. if (s == DIGIT_BIT) {
  53326. r[++j] = 0;
  53327. s = 0;
  53328. }
  53329. else {
  53330. r[++j] = a->dp[i] >> s;
  53331. s = DIGIT_BIT - s;
  53332. }
  53333. }
  53334. else {
  53335. s += DIGIT_BIT;
  53336. }
  53337. }
  53338. for (j++; j < size; j++) {
  53339. r[j] = 0;
  53340. }
  53341. #endif
  53342. }
  53343. /* Convert a point of type ecc_point to type sp_point_521.
  53344. *
  53345. * p Point of type sp_point_521 (result).
  53346. * pm Point of type ecc_point.
  53347. */
  53348. static void sp_521_point_from_ecc_point_17(sp_point_521* p,
  53349. const ecc_point* pm)
  53350. {
  53351. XMEMSET(p->x, 0, sizeof(p->x));
  53352. XMEMSET(p->y, 0, sizeof(p->y));
  53353. XMEMSET(p->z, 0, sizeof(p->z));
  53354. sp_521_from_mp(p->x, 17, pm->x);
  53355. sp_521_from_mp(p->y, 17, pm->y);
  53356. sp_521_from_mp(p->z, 17, pm->z);
  53357. p->infinity = 0;
  53358. }
  53359. /* Convert an array of sp_digit to an mp_int.
  53360. *
  53361. * a A single precision integer.
  53362. * r A multi-precision integer.
  53363. */
  53364. static int sp_521_to_mp(const sp_digit* a, mp_int* r)
  53365. {
  53366. int err;
  53367. err = mp_grow(r, (521 + DIGIT_BIT - 1) / DIGIT_BIT);
  53368. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  53369. #if DIGIT_BIT == 32
  53370. XMEMCPY(r->dp, a, sizeof(sp_digit) * 17);
  53371. r->used = 17;
  53372. mp_clamp(r);
  53373. #elif DIGIT_BIT < 32
  53374. int i;
  53375. int j = 0;
  53376. int s = 0;
  53377. r->dp[0] = 0;
  53378. for (i = 0; i < 17; i++) {
  53379. r->dp[j] |= (mp_digit)(a[i] << s);
  53380. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  53381. s = DIGIT_BIT - s;
  53382. r->dp[++j] = (mp_digit)(a[i] >> s);
  53383. while (s + DIGIT_BIT <= 32) {
  53384. s += DIGIT_BIT;
  53385. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  53386. if (s == SP_WORD_SIZE) {
  53387. r->dp[j] = 0;
  53388. }
  53389. else {
  53390. r->dp[j] = (mp_digit)(a[i] >> s);
  53391. }
  53392. }
  53393. s = 32 - s;
  53394. }
  53395. r->used = (521 + DIGIT_BIT - 1) / DIGIT_BIT;
  53396. mp_clamp(r);
  53397. #else
  53398. int i;
  53399. int j = 0;
  53400. int s = 0;
  53401. r->dp[0] = 0;
  53402. for (i = 0; i < 17; i++) {
  53403. r->dp[j] |= ((mp_digit)a[i]) << s;
  53404. if (s + 32 >= DIGIT_BIT) {
  53405. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  53406. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  53407. #endif
  53408. s = DIGIT_BIT - s;
  53409. r->dp[++j] = a[i] >> s;
  53410. s = 32 - s;
  53411. }
  53412. else {
  53413. s += 32;
  53414. }
  53415. }
  53416. r->used = (521 + DIGIT_BIT - 1) / DIGIT_BIT;
  53417. mp_clamp(r);
  53418. #endif
  53419. }
  53420. return err;
  53421. }
  53422. /* Convert a point of type sp_point_521 to type ecc_point.
  53423. *
  53424. * p Point of type sp_point_521.
  53425. * pm Point of type ecc_point (result).
  53426. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  53427. * MP_OKAY.
  53428. */
  53429. static int sp_521_point_to_ecc_point_17(const sp_point_521* p, ecc_point* pm)
  53430. {
  53431. int err;
  53432. err = sp_521_to_mp(p->x, pm->x);
  53433. if (err == MP_OKAY) {
  53434. err = sp_521_to_mp(p->y, pm->y);
  53435. }
  53436. if (err == MP_OKAY) {
  53437. err = sp_521_to_mp(p->z, pm->z);
  53438. }
  53439. return err;
  53440. }
  53441. #ifdef WOLFSSL_SP_SMALL
  53442. /* Conditionally subtract b from a using the mask m.
  53443. * m is -1 to subtract and 0 when not copying.
  53444. *
  53445. * r A single precision number representing condition subtract result.
  53446. * a A single precision number to subtract from.
  53447. * b A single precision number to subtract.
  53448. * m Mask value to apply.
  53449. */
  53450. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53451. static sp_digit sp_521_cond_sub_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  53452. #else
  53453. static sp_digit sp_521_cond_sub_17(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  53454. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53455. {
  53456. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53457. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  53458. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  53459. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  53460. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  53461. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53462. __asm__ __volatile__ (
  53463. "MOV r8, #0x0\n\t"
  53464. "MOV r4, #0x0\n\t"
  53465. "MOV r5, #0x0\n\t"
  53466. "\n"
  53467. "L_sp_521_cond_sub_17_words:\n\t"
  53468. "SUBS r4, r8, r4\n\t"
  53469. "LDR r6, [%[a], r5]\n\t"
  53470. "LDR r7, [%[b], r5]\n\t"
  53471. "AND r7, r7, %[m]\n\t"
  53472. "SBCS r6, r6, r7\n\t"
  53473. "SBC r4, r8, r8\n\t"
  53474. "STR r6, [%[r], r5]\n\t"
  53475. "ADD r5, r5, #0x4\n\t"
  53476. "CMP r5, #0x44\n\t"
  53477. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  53478. "BLT L_sp_521_cond_sub_17_words\n\t"
  53479. #else
  53480. "BLT.N L_sp_521_cond_sub_17_words\n\t"
  53481. #endif
  53482. "MOV %[r], r4\n\t"
  53483. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  53484. :
  53485. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  53486. );
  53487. return (uint32_t)(size_t)r;
  53488. }
  53489. #else
  53490. /* Conditionally subtract b from a using the mask m.
  53491. * m is -1 to subtract and 0 when not copying.
  53492. *
  53493. * r A single precision number representing condition subtract result.
  53494. * a A single precision number to subtract from.
  53495. * b A single precision number to subtract.
  53496. * m Mask value to apply.
  53497. */
  53498. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53499. static sp_digit sp_521_cond_sub_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  53500. #else
  53501. static sp_digit sp_521_cond_sub_17(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  53502. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53503. {
  53504. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53505. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  53506. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  53507. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  53508. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  53509. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53510. __asm__ __volatile__ (
  53511. "MOV r5, #0x0\n\t"
  53512. "LDM %[a]!, {r6, r7}\n\t"
  53513. "LDM %[b]!, {r8, r9}\n\t"
  53514. "AND r8, r8, %[m]\n\t"
  53515. "AND r9, r9, %[m]\n\t"
  53516. "SUBS r6, r6, r8\n\t"
  53517. "SBCS r7, r7, r9\n\t"
  53518. "STM %[r]!, {r6, r7}\n\t"
  53519. "LDM %[a]!, {r6, r7}\n\t"
  53520. "LDM %[b]!, {r8, r9}\n\t"
  53521. "AND r8, r8, %[m]\n\t"
  53522. "AND r9, r9, %[m]\n\t"
  53523. "SBCS r6, r6, r8\n\t"
  53524. "SBCS r7, r7, r9\n\t"
  53525. "STM %[r]!, {r6, r7}\n\t"
  53526. "LDM %[a]!, {r6, r7}\n\t"
  53527. "LDM %[b]!, {r8, r9}\n\t"
  53528. "AND r8, r8, %[m]\n\t"
  53529. "AND r9, r9, %[m]\n\t"
  53530. "SBCS r6, r6, r8\n\t"
  53531. "SBCS r7, r7, r9\n\t"
  53532. "STM %[r]!, {r6, r7}\n\t"
  53533. "LDM %[a]!, {r6, r7}\n\t"
  53534. "LDM %[b]!, {r8, r9}\n\t"
  53535. "AND r8, r8, %[m]\n\t"
  53536. "AND r9, r9, %[m]\n\t"
  53537. "SBCS r6, r6, r8\n\t"
  53538. "SBCS r7, r7, r9\n\t"
  53539. "STM %[r]!, {r6, r7}\n\t"
  53540. "LDM %[a]!, {r6, r7}\n\t"
  53541. "LDM %[b]!, {r8, r9}\n\t"
  53542. "AND r8, r8, %[m]\n\t"
  53543. "AND r9, r9, %[m]\n\t"
  53544. "SBCS r6, r6, r8\n\t"
  53545. "SBCS r7, r7, r9\n\t"
  53546. "STM %[r]!, {r6, r7}\n\t"
  53547. "LDM %[a]!, {r6, r7}\n\t"
  53548. "LDM %[b]!, {r8, r9}\n\t"
  53549. "AND r8, r8, %[m]\n\t"
  53550. "AND r9, r9, %[m]\n\t"
  53551. "SBCS r6, r6, r8\n\t"
  53552. "SBCS r7, r7, r9\n\t"
  53553. "STM %[r]!, {r6, r7}\n\t"
  53554. "LDM %[a]!, {r6, r7}\n\t"
  53555. "LDM %[b]!, {r8, r9}\n\t"
  53556. "AND r8, r8, %[m]\n\t"
  53557. "AND r9, r9, %[m]\n\t"
  53558. "SBCS r6, r6, r8\n\t"
  53559. "SBCS r7, r7, r9\n\t"
  53560. "STM %[r]!, {r6, r7}\n\t"
  53561. "LDM %[a]!, {r6, r7}\n\t"
  53562. "LDM %[b]!, {r8, r9}\n\t"
  53563. "AND r8, r8, %[m]\n\t"
  53564. "AND r9, r9, %[m]\n\t"
  53565. "SBCS r6, r6, r8\n\t"
  53566. "SBCS r7, r7, r9\n\t"
  53567. "STM %[r]!, {r6, r7}\n\t"
  53568. "LDR r6, [%[a]]\n\t"
  53569. "LDR r8, [%[b]]\n\t"
  53570. "AND r8, r8, %[m]\n\t"
  53571. "SBCS r6, r6, r8\n\t"
  53572. "STR r6, [%[r]]\n\t"
  53573. "SBC %[r], r5, r5\n\t"
  53574. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  53575. :
  53576. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  53577. );
  53578. return (uint32_t)(size_t)r;
  53579. }
  53580. #endif /* WOLFSSL_SP_SMALL */
  53581. /* Reduce the number back to 521 bits using Montgomery reduction.
  53582. *
  53583. * a A single precision number to reduce in place.
  53584. * m The single precision number representing the modulus.
  53585. * mp The digit representing the negative inverse of m mod 2^n.
  53586. */
  53587. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53588. SP_NOINLINE static void sp_521_mont_reduce_17(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  53589. #else
  53590. SP_NOINLINE static void sp_521_mont_reduce_17(sp_digit* a, const sp_digit* m, sp_digit mp)
  53591. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53592. {
  53593. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53594. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  53595. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53596. __asm__ __volatile__ (
  53597. "SUB sp, sp, #0x44\n\t"
  53598. "MOV r12, sp\n\t"
  53599. /* Shift top down by 9 bits */
  53600. "ADD lr, %[a], #0x40\n\t"
  53601. /* 0-7 */
  53602. "LDM lr!, {r1, r2, r3, r4, r5, r6, r7, r8, r9}\n\t"
  53603. "LSR r1, r1, #9\n\t"
  53604. "ORR r1, r1, r2, LSL #23\n\t"
  53605. "LSR r2, r2, #9\n\t"
  53606. "ORR r2, r2, r3, LSL #23\n\t"
  53607. "LSR r3, r3, #9\n\t"
  53608. "ORR r3, r3, r4, LSL #23\n\t"
  53609. "LSR r4, r4, #9\n\t"
  53610. "ORR r4, r4, r5, LSL #23\n\t"
  53611. "LSR r5, r5, #9\n\t"
  53612. "ORR r5, r5, r6, LSL #23\n\t"
  53613. "LSR r6, r6, #9\n\t"
  53614. "ORR r6, r6, r7, LSL #23\n\t"
  53615. "LSR r7, r7, #9\n\t"
  53616. "ORR r7, r7, r8, LSL #23\n\t"
  53617. "LSR r8, r8, #9\n\t"
  53618. "ORR r8, r8, r9, LSL #23\n\t"
  53619. "STM r12!, {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  53620. "MOV r1, r9\n\t"
  53621. /* 8-16 */
  53622. "LDM lr!, {r2, r3, r4, r5, r6, r7, r8, r9}\n\t"
  53623. "LSR r1, r1, #9\n\t"
  53624. "ORR r1, r1, r2, LSL #23\n\t"
  53625. "LSR r2, r2, #9\n\t"
  53626. "ORR r2, r2, r3, LSL #23\n\t"
  53627. "LSR r3, r3, #9\n\t"
  53628. "ORR r3, r3, r4, LSL #23\n\t"
  53629. "LSR r4, r4, #9\n\t"
  53630. "ORR r4, r4, r5, LSL #23\n\t"
  53631. "LSR r5, r5, #9\n\t"
  53632. "ORR r5, r5, r6, LSL #23\n\t"
  53633. "LSR r6, r6, #9\n\t"
  53634. "ORR r6, r6, r7, LSL #23\n\t"
  53635. "LSR r7, r7, #9\n\t"
  53636. "ORR r7, r7, r8, LSL #23\n\t"
  53637. "LSR r8, r8, #9\n\t"
  53638. "ORR r8, r8, r9, LSL #23\n\t"
  53639. "LSR r9, r9, #9\n\t"
  53640. "STM r12!, {r1, r2, r3, r4, r5, r6, r7, r8, r9}\n\t"
  53641. /* Add top to bottom */
  53642. /* 0-5 */
  53643. "LDM %[a], {r1, r2, r3, r4, r5, r6}\n\t"
  53644. "LDM sp!, {r7, r8, r9, r10, r11, r12}\n\t"
  53645. "ADDS r1, r1, r7\n\t"
  53646. "ADCS r2, r2, r8\n\t"
  53647. "ADCS r3, r3, r9\n\t"
  53648. "ADCS r4, r4, r10\n\t"
  53649. "ADCS r5, r5, r11\n\t"
  53650. "ADCS r6, r6, r12\n\t"
  53651. "STM %[a]!, {r1, r2, r3, r4, r5, r6}\n\t"
  53652. /* 6-11 */
  53653. "LDM %[a], {r1, r2, r3, r4, r5, r6}\n\t"
  53654. "LDM sp!, {r7, r8, r9, r10, r11, r12}\n\t"
  53655. "ADCS r1, r1, r7\n\t"
  53656. "ADCS r2, r2, r8\n\t"
  53657. "ADCS r3, r3, r9\n\t"
  53658. "ADCS r4, r4, r10\n\t"
  53659. "ADCS r5, r5, r11\n\t"
  53660. "ADCS r6, r6, r12\n\t"
  53661. "STM %[a]!, {r1, r2, r3, r4, r5, r6}\n\t"
  53662. /* 12-16 */
  53663. "LDM %[a], {r1, r2, r3, r4, r5}\n\t"
  53664. "LDM sp!, {r7, r8, r9, r10, r11}\n\t"
  53665. "MOV lr, #0x1ff\n\t"
  53666. "AND r5, r5, lr\n\t"
  53667. "ADCS r1, r1, r7\n\t"
  53668. "ADCS r2, r2, r8\n\t"
  53669. "ADCS r3, r3, r9\n\t"
  53670. "ADCS r4, r4, r10\n\t"
  53671. "ADCS r5, r5, r11\n\t"
  53672. "LSR r12, r5, #9\n\t"
  53673. "AND r5, r5, lr\n\t"
  53674. "STM %[a]!, {r1, r2, r3, r4, r5}\n\t"
  53675. "SUB %[a], %[a], #0x44\n\t"
  53676. /* Add overflow */
  53677. /* 0-8 */
  53678. "LDM %[a], {r1, r2, r3, r4, r5, r6, r7, r8, r9}\n\t"
  53679. "ADDS r1, r1, r12\n\t"
  53680. "ADCS r2, r2, #0x0\n\t"
  53681. "ADCS r3, r3, #0x0\n\t"
  53682. "ADCS r4, r4, #0x0\n\t"
  53683. "ADCS r5, r5, #0x0\n\t"
  53684. "ADCS r6, r6, #0x0\n\t"
  53685. "ADCS r7, r7, #0x0\n\t"
  53686. "ADCS r8, r8, #0x0\n\t"
  53687. "ADCS r9, r9, #0x0\n\t"
  53688. "STM %[a]!, {r1, r2, r3, r4, r5, r6, r7, r8, r9}\n\t"
  53689. /* 9-16 */
  53690. "LDM %[a], {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  53691. "ADCS r1, r1, #0x0\n\t"
  53692. "ADCS r2, r2, #0x0\n\t"
  53693. "ADCS r3, r3, #0x0\n\t"
  53694. "ADCS r4, r4, #0x0\n\t"
  53695. "ADCS r5, r5, #0x0\n\t"
  53696. "ADCS r6, r6, #0x0\n\t"
  53697. "ADCS r7, r7, #0x0\n\t"
  53698. "ADCS r8, r8, #0x0\n\t"
  53699. "STM %[a]!, {r1, r2, r3, r4, r5, r6, r7, r8}\n\t"
  53700. : [a] "+r" (a)
  53701. :
  53702. : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  53703. );
  53704. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53705. (void)m_p;
  53706. #else
  53707. (void)m;
  53708. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53709. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53710. (void)mp_p;
  53711. #else
  53712. (void)mp;
  53713. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53714. }
  53715. #ifdef WOLFSSL_SP_NO_UMAAL
  53716. /* Reduce the number back to 521 bits using Montgomery reduction.
  53717. *
  53718. * a A single precision number to reduce in place.
  53719. * m The single precision number representing the modulus.
  53720. * mp The digit representing the negative inverse of m mod 2^n.
  53721. */
  53722. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53723. SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  53724. #else
  53725. SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a, const sp_digit* m, sp_digit mp)
  53726. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53727. {
  53728. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53729. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  53730. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  53731. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  53732. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53733. __asm__ __volatile__ (
  53734. "LDR lr, [%[m]]\n\t"
  53735. /* i = 0 */
  53736. "MOV r11, #0x0\n\t"
  53737. "MOV r3, #0x0\n\t"
  53738. "LDR r4, [%[a]]\n\t"
  53739. "LDR r5, [%[a], #4]\n\t"
  53740. "\n"
  53741. "L_sp_521_mont_reduce_order_17_word:\n\t"
  53742. /* mu = a[i] * mp */
  53743. "MUL r10, %[mp], r4\n\t"
  53744. "CMP r11, #0x40\n\t"
  53745. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  53746. "BNE L_sp_521_mont_reduce_order_17_nomask\n\t"
  53747. #else
  53748. "BNE.N L_sp_521_mont_reduce_order_17_nomask\n\t"
  53749. #endif
  53750. "MOV r9, #0x1ff\n\t"
  53751. "AND r10, r10, r9\n\t"
  53752. "\n"
  53753. "L_sp_521_mont_reduce_order_17_nomask:\n\t"
  53754. /* a[i+0] += m[0] * mu */
  53755. "MOV r7, #0x0\n\t"
  53756. "UMLAL r4, r7, r10, lr\n\t"
  53757. "STR r4, [%[a]]\n\t"
  53758. /* a[i+1] += m[1] * mu */
  53759. "LDR r9, [%[m], #4]\n\t"
  53760. "MOV r6, #0x0\n\t"
  53761. "UMLAL r5, r6, r10, r9\n\t"
  53762. "MOV r4, r5\n\t"
  53763. "ADDS r4, r4, r7\n\t"
  53764. "ADC r6, r6, #0x0\n\t"
  53765. /* a[i+2] += m[2] * mu */
  53766. "LDR r9, [%[m], #8]\n\t"
  53767. "LDR r5, [%[a], #8]\n\t"
  53768. "MOV r7, #0x0\n\t"
  53769. "UMLAL r5, r7, r10, r9\n\t"
  53770. "ADDS r5, r5, r6\n\t"
  53771. "ADC r7, r7, #0x0\n\t"
  53772. /* a[i+3] += m[3] * mu */
  53773. "LDR r9, [%[m], #12]\n\t"
  53774. "LDR r12, [%[a], #12]\n\t"
  53775. "MOV r6, #0x0\n\t"
  53776. "UMLAL r12, r6, r10, r9\n\t"
  53777. "ADDS r12, r12, r7\n\t"
  53778. "STR r12, [%[a], #12]\n\t"
  53779. "ADC r6, r6, #0x0\n\t"
  53780. /* a[i+4] += m[4] * mu */
  53781. "LDR r9, [%[m], #16]\n\t"
  53782. "LDR r12, [%[a], #16]\n\t"
  53783. "MOV r7, #0x0\n\t"
  53784. "UMLAL r12, r7, r10, r9\n\t"
  53785. "ADDS r12, r12, r6\n\t"
  53786. "STR r12, [%[a], #16]\n\t"
  53787. "ADC r7, r7, #0x0\n\t"
  53788. /* a[i+5] += m[5] * mu */
  53789. "LDR r9, [%[m], #20]\n\t"
  53790. "LDR r12, [%[a], #20]\n\t"
  53791. "MOV r6, #0x0\n\t"
  53792. "UMLAL r12, r6, r10, r9\n\t"
  53793. "ADDS r12, r12, r7\n\t"
  53794. "STR r12, [%[a], #20]\n\t"
  53795. "ADC r6, r6, #0x0\n\t"
  53796. /* a[i+6] += m[6] * mu */
  53797. "LDR r9, [%[m], #24]\n\t"
  53798. "LDR r12, [%[a], #24]\n\t"
  53799. "MOV r7, #0x0\n\t"
  53800. "UMLAL r12, r7, r10, r9\n\t"
  53801. "ADDS r12, r12, r6\n\t"
  53802. "STR r12, [%[a], #24]\n\t"
  53803. "ADC r7, r7, #0x0\n\t"
  53804. /* a[i+7] += m[7] * mu */
  53805. "LDR r9, [%[m], #28]\n\t"
  53806. "LDR r12, [%[a], #28]\n\t"
  53807. "MOV r6, #0x0\n\t"
  53808. "UMLAL r12, r6, r10, r9\n\t"
  53809. "ADDS r12, r12, r7\n\t"
  53810. "STR r12, [%[a], #28]\n\t"
  53811. "ADC r6, r6, #0x0\n\t"
  53812. /* a[i+8] += m[8] * mu */
  53813. "LDR r9, [%[m], #32]\n\t"
  53814. "LDR r12, [%[a], #32]\n\t"
  53815. "MOV r7, #0x0\n\t"
  53816. "UMLAL r12, r7, r10, r9\n\t"
  53817. "ADDS r12, r12, r6\n\t"
  53818. "STR r12, [%[a], #32]\n\t"
  53819. "ADC r7, r7, #0x0\n\t"
  53820. /* a[i+9] += m[9] * mu */
  53821. "LDR r9, [%[m], #36]\n\t"
  53822. "LDR r12, [%[a], #36]\n\t"
  53823. "MOV r6, #0x0\n\t"
  53824. "UMLAL r12, r6, r10, r9\n\t"
  53825. "ADDS r12, r12, r7\n\t"
  53826. "STR r12, [%[a], #36]\n\t"
  53827. "ADC r6, r6, #0x0\n\t"
  53828. /* a[i+10] += m[10] * mu */
  53829. "LDR r9, [%[m], #40]\n\t"
  53830. "LDR r12, [%[a], #40]\n\t"
  53831. "MOV r7, #0x0\n\t"
  53832. "UMLAL r12, r7, r10, r9\n\t"
  53833. "ADDS r12, r12, r6\n\t"
  53834. "STR r12, [%[a], #40]\n\t"
  53835. "ADC r7, r7, #0x0\n\t"
  53836. /* a[i+11] += m[11] * mu */
  53837. "LDR r9, [%[m], #44]\n\t"
  53838. "LDR r12, [%[a], #44]\n\t"
  53839. "MOV r6, #0x0\n\t"
  53840. "UMLAL r12, r6, r10, r9\n\t"
  53841. "ADDS r12, r12, r7\n\t"
  53842. "STR r12, [%[a], #44]\n\t"
  53843. "ADC r6, r6, #0x0\n\t"
  53844. /* a[i+12] += m[12] * mu */
  53845. "LDR r9, [%[m], #48]\n\t"
  53846. "LDR r12, [%[a], #48]\n\t"
  53847. "MOV r7, #0x0\n\t"
  53848. "UMLAL r12, r7, r10, r9\n\t"
  53849. "ADDS r12, r12, r6\n\t"
  53850. "STR r12, [%[a], #48]\n\t"
  53851. "ADC r7, r7, #0x0\n\t"
  53852. /* a[i+13] += m[13] * mu */
  53853. "LDR r9, [%[m], #52]\n\t"
  53854. "LDR r12, [%[a], #52]\n\t"
  53855. "MOV r6, #0x0\n\t"
  53856. "UMLAL r12, r6, r10, r9\n\t"
  53857. "ADDS r12, r12, r7\n\t"
  53858. "STR r12, [%[a], #52]\n\t"
  53859. "ADC r6, r6, #0x0\n\t"
  53860. /* a[i+14] += m[14] * mu */
  53861. "LDR r9, [%[m], #56]\n\t"
  53862. "LDR r12, [%[a], #56]\n\t"
  53863. "MOV r7, #0x0\n\t"
  53864. "UMLAL r12, r7, r10, r9\n\t"
  53865. "ADDS r12, r12, r6\n\t"
  53866. "STR r12, [%[a], #56]\n\t"
  53867. "ADC r7, r7, #0x0\n\t"
  53868. /* a[i+15] += m[15] * mu */
  53869. "LDR r9, [%[m], #60]\n\t"
  53870. "LDR r12, [%[a], #60]\n\t"
  53871. "MOV r6, #0x0\n\t"
  53872. "UMLAL r12, r6, r10, r9\n\t"
  53873. "ADDS r12, r12, r7\n\t"
  53874. "STR r12, [%[a], #60]\n\t"
  53875. "ADC r6, r6, #0x0\n\t"
  53876. /* a[i+16] += m[16] * mu */
  53877. "LDR r9, [%[m], #64]\n\t"
  53878. "LDR r12, [%[a], #64]\n\t"
  53879. "UMULL r8, r9, r10, r9\n\t"
  53880. "ADDS r6, r6, r8\n\t"
  53881. "ADCS r7, r9, r3\n\t"
  53882. "MOV r3, #0x0\n\t"
  53883. "ADC r3, r3, r3\n\t"
  53884. "ADDS r12, r12, r6\n\t"
  53885. "STR r12, [%[a], #64]\n\t"
  53886. "LDR r12, [%[a], #68]\n\t"
  53887. "ADCS r12, r12, r7\n\t"
  53888. "STR r12, [%[a], #68]\n\t"
  53889. "ADC r3, r3, #0x0\n\t"
  53890. /* i += 1 */
  53891. "ADD r11, r11, #0x4\n\t"
  53892. "ADD %[a], %[a], #0x4\n\t"
  53893. "CMP r11, #0x44\n\t"
  53894. #ifdef __GNUC__
  53895. "BLT L_sp_521_mont_reduce_order_17_word\n\t"
  53896. #else
  53897. "BLT.W L_sp_521_mont_reduce_order_17_word\n\t"
  53898. #endif
  53899. /* Loop Done */
  53900. "STR r4, [%[a]]\n\t"
  53901. "STR r5, [%[a], #4]\n\t"
  53902. "SUB %[a], %[a], #0x4\n\t"
  53903. "LDR r6, [%[a]]\n\t"
  53904. "LDR r7, [%[a], #4]\n\t"
  53905. "LSR r6, r6, #9\n\t"
  53906. "ORR r6, r6, r7, LSL #23\n\t"
  53907. "STR r6, [%[a], #4]\n\t"
  53908. "LDR r6, [%[a], #8]\n\t"
  53909. "LSR r7, r7, #9\n\t"
  53910. "ORR r7, r7, r6, LSL #23\n\t"
  53911. "STR r7, [%[a], #8]\n\t"
  53912. "LDR r7, [%[a], #12]\n\t"
  53913. "LSR r6, r6, #9\n\t"
  53914. "ORR r6, r6, r7, LSL #23\n\t"
  53915. "STR r6, [%[a], #12]\n\t"
  53916. "LDR r6, [%[a], #16]\n\t"
  53917. "LSR r7, r7, #9\n\t"
  53918. "ORR r7, r7, r6, LSL #23\n\t"
  53919. "STR r7, [%[a], #16]\n\t"
  53920. "LDR r7, [%[a], #20]\n\t"
  53921. "LSR r6, r6, #9\n\t"
  53922. "ORR r6, r6, r7, LSL #23\n\t"
  53923. "STR r6, [%[a], #20]\n\t"
  53924. "LDR r6, [%[a], #24]\n\t"
  53925. "LSR r7, r7, #9\n\t"
  53926. "ORR r7, r7, r6, LSL #23\n\t"
  53927. "STR r7, [%[a], #24]\n\t"
  53928. "LDR r7, [%[a], #28]\n\t"
  53929. "LSR r6, r6, #9\n\t"
  53930. "ORR r6, r6, r7, LSL #23\n\t"
  53931. "STR r6, [%[a], #28]\n\t"
  53932. "LDR r6, [%[a], #32]\n\t"
  53933. "LSR r7, r7, #9\n\t"
  53934. "ORR r7, r7, r6, LSL #23\n\t"
  53935. "STR r7, [%[a], #32]\n\t"
  53936. "LDR r7, [%[a], #36]\n\t"
  53937. "LSR r6, r6, #9\n\t"
  53938. "ORR r6, r6, r7, LSL #23\n\t"
  53939. "STR r6, [%[a], #36]\n\t"
  53940. "LDR r6, [%[a], #40]\n\t"
  53941. "LSR r7, r7, #9\n\t"
  53942. "ORR r7, r7, r6, LSL #23\n\t"
  53943. "STR r7, [%[a], #40]\n\t"
  53944. "LDR r7, [%[a], #44]\n\t"
  53945. "LSR r6, r6, #9\n\t"
  53946. "ORR r6, r6, r7, LSL #23\n\t"
  53947. "STR r6, [%[a], #44]\n\t"
  53948. "LDR r6, [%[a], #48]\n\t"
  53949. "LSR r7, r7, #9\n\t"
  53950. "ORR r7, r7, r6, LSL #23\n\t"
  53951. "STR r7, [%[a], #48]\n\t"
  53952. "LDR r7, [%[a], #52]\n\t"
  53953. "LSR r6, r6, #9\n\t"
  53954. "ORR r6, r6, r7, LSL #23\n\t"
  53955. "STR r6, [%[a], #52]\n\t"
  53956. "LDR r6, [%[a], #56]\n\t"
  53957. "LSR r7, r7, #9\n\t"
  53958. "ORR r7, r7, r6, LSL #23\n\t"
  53959. "STR r7, [%[a], #56]\n\t"
  53960. "LDR r7, [%[a], #60]\n\t"
  53961. "LSR r6, r6, #9\n\t"
  53962. "ORR r6, r6, r7, LSL #23\n\t"
  53963. "STR r6, [%[a], #60]\n\t"
  53964. "LDR r6, [%[a], #64]\n\t"
  53965. "LSR r7, r7, #9\n\t"
  53966. "ORR r7, r7, r6, LSL #23\n\t"
  53967. "STR r7, [%[a], #64]\n\t"
  53968. "LSR r6, r6, #9\n\t"
  53969. "STR r6, [%[a], #68]\n\t"
  53970. "LSR r3, r6, #9\n\t"
  53971. "ADD %[a], %[a], #0x4\n\t"
  53972. "MOV %[mp], r3\n\t"
  53973. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  53974. :
  53975. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  53976. );
  53977. sp_521_cond_sub_17(a - 17, a, m, (sp_digit)0 - mp);
  53978. }
  53979. #else
  53980. /* Reduce the number back to 521 bits using Montgomery reduction.
  53981. *
  53982. * a A single precision number to reduce in place.
  53983. * m The single precision number representing the modulus.
  53984. * mp The digit representing the negative inverse of m mod 2^n.
  53985. */
  53986. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53987. SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  53988. #else
  53989. SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a, const sp_digit* m, sp_digit mp)
  53990. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53991. {
  53992. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  53993. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  53994. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  53995. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  53996. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  53997. __asm__ __volatile__ (
  53998. /* i = 0 */
  53999. "MOV r4, #0x0\n\t"
  54000. "MOV r5, #0x0\n\t"
  54001. "LDR r6, [%[a]]\n\t"
  54002. "LDR r7, [%[a], #4]\n\t"
  54003. "LDR r8, [%[a], #8]\n\t"
  54004. "LDR r9, [%[a], #12]\n\t"
  54005. "LDR r10, [%[a], #16]\n\t"
  54006. "\n"
  54007. "L_sp_521_mont_reduce_order_17_word:\n\t"
  54008. /* mu = a[i] * mp */
  54009. "MUL lr, %[mp], r6\n\t"
  54010. "CMP r4, #0x40\n\t"
  54011. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  54012. "BNE L_sp_521_mont_reduce_order_17_nomask\n\t"
  54013. #else
  54014. "BNE.N L_sp_521_mont_reduce_order_17_nomask\n\t"
  54015. #endif
  54016. "MOV r12, #0x1ff\n\t"
  54017. "AND lr, lr, r12\n\t"
  54018. "\n"
  54019. "L_sp_521_mont_reduce_order_17_nomask:\n\t"
  54020. /* a[i+0] += m[0] * mu */
  54021. "LDR r12, [%[m]]\n\t"
  54022. "MOV r3, #0x0\n\t"
  54023. "UMAAL r6, r3, lr, r12\n\t"
  54024. "STR r6, [%[a]]\n\t"
  54025. /* a[i+1] += m[1] * mu */
  54026. "LDR r12, [%[m], #4]\n\t"
  54027. "MOV r6, r7\n\t"
  54028. "UMAAL r6, r3, lr, r12\n\t"
  54029. /* a[i+2] += m[2] * mu */
  54030. "LDR r12, [%[m], #8]\n\t"
  54031. "MOV r7, r8\n\t"
  54032. "UMAAL r7, r3, lr, r12\n\t"
  54033. /* a[i+3] += m[3] * mu */
  54034. "LDR r12, [%[m], #12]\n\t"
  54035. "MOV r8, r9\n\t"
  54036. "UMAAL r8, r3, lr, r12\n\t"
  54037. /* a[i+4] += m[4] * mu */
  54038. "LDR r12, [%[m], #16]\n\t"
  54039. "MOV r9, r10\n\t"
  54040. "UMAAL r9, r3, lr, r12\n\t"
  54041. /* a[i+5] += m[5] * mu */
  54042. "LDR r12, [%[m], #20]\n\t"
  54043. "LDR r10, [%[a], #20]\n\t"
  54044. "UMAAL r10, r3, lr, r12\n\t"
  54045. /* a[i+6] += m[6] * mu */
  54046. "LDR r12, [%[m], #24]\n\t"
  54047. "LDR r11, [%[a], #24]\n\t"
  54048. "UMAAL r11, r3, lr, r12\n\t"
  54049. "STR r11, [%[a], #24]\n\t"
  54050. /* a[i+7] += m[7] * mu */
  54051. "LDR r12, [%[m], #28]\n\t"
  54052. "LDR r11, [%[a], #28]\n\t"
  54053. "UMAAL r11, r3, lr, r12\n\t"
  54054. "STR r11, [%[a], #28]\n\t"
  54055. /* a[i+8] += m[8] * mu */
  54056. "LDR r12, [%[m], #32]\n\t"
  54057. "LDR r11, [%[a], #32]\n\t"
  54058. "UMAAL r11, r3, lr, r12\n\t"
  54059. "STR r11, [%[a], #32]\n\t"
  54060. /* a[i+9] += m[9] * mu */
  54061. "LDR r12, [%[m], #36]\n\t"
  54062. "LDR r11, [%[a], #36]\n\t"
  54063. "UMAAL r11, r3, lr, r12\n\t"
  54064. "STR r11, [%[a], #36]\n\t"
  54065. /* a[i+10] += m[10] * mu */
  54066. "LDR r12, [%[m], #40]\n\t"
  54067. "LDR r11, [%[a], #40]\n\t"
  54068. "UMAAL r11, r3, lr, r12\n\t"
  54069. "STR r11, [%[a], #40]\n\t"
  54070. /* a[i+11] += m[11] * mu */
  54071. "LDR r12, [%[m], #44]\n\t"
  54072. "LDR r11, [%[a], #44]\n\t"
  54073. "UMAAL r11, r3, lr, r12\n\t"
  54074. "STR r11, [%[a], #44]\n\t"
  54075. /* a[i+12] += m[12] * mu */
  54076. "LDR r12, [%[m], #48]\n\t"
  54077. "LDR r11, [%[a], #48]\n\t"
  54078. "UMAAL r11, r3, lr, r12\n\t"
  54079. "STR r11, [%[a], #48]\n\t"
  54080. /* a[i+13] += m[13] * mu */
  54081. "LDR r12, [%[m], #52]\n\t"
  54082. "LDR r11, [%[a], #52]\n\t"
  54083. "UMAAL r11, r3, lr, r12\n\t"
  54084. "STR r11, [%[a], #52]\n\t"
  54085. /* a[i+14] += m[14] * mu */
  54086. "LDR r12, [%[m], #56]\n\t"
  54087. "LDR r11, [%[a], #56]\n\t"
  54088. "UMAAL r11, r3, lr, r12\n\t"
  54089. "STR r11, [%[a], #56]\n\t"
  54090. /* a[i+15] += m[15] * mu */
  54091. "LDR r12, [%[m], #60]\n\t"
  54092. "LDR r11, [%[a], #60]\n\t"
  54093. "UMAAL r11, r3, lr, r12\n\t"
  54094. "STR r11, [%[a], #60]\n\t"
  54095. /* a[i+16] += m[16] * mu */
  54096. "LDR r12, [%[m], #64]\n\t"
  54097. "LDR r11, [%[a], #64]\n\t"
  54098. "UMAAL r11, r3, lr, r12\n\t"
  54099. "LDR lr, [%[a], #68]\n\t"
  54100. "MOV r12, #0x0\n\t"
  54101. "UMAAL r3, lr, r12, r12\n\t"
  54102. "STR r11, [%[a], #64]\n\t"
  54103. "ADDS r3, r3, r5\n\t"
  54104. "ADC r5, lr, #0x0\n\t"
  54105. "STR r3, [%[a], #68]\n\t"
  54106. /* i += 1 */
  54107. "ADD r4, r4, #0x4\n\t"
  54108. "ADD %[a], %[a], #0x4\n\t"
  54109. "CMP r4, #0x44\n\t"
  54110. #ifdef __GNUC__
  54111. "BLT L_sp_521_mont_reduce_order_17_word\n\t"
  54112. #else
  54113. "BLT.W L_sp_521_mont_reduce_order_17_word\n\t"
  54114. #endif
  54115. /* Loop Done */
  54116. "STR r6, [%[a]]\n\t"
  54117. "STR r7, [%[a], #4]\n\t"
  54118. "STR r8, [%[a], #8]\n\t"
  54119. "STR r9, [%[a], #12]\n\t"
  54120. "STR r10, [%[a], #16]\n\t"
  54121. "SUB %[a], %[a], #0x4\n\t"
  54122. "LDR r12, [%[a]]\n\t"
  54123. "LDR r3, [%[a], #4]\n\t"
  54124. "LSR r12, r12, #9\n\t"
  54125. "ORR r12, r12, r3, LSL #23\n\t"
  54126. "STR r12, [%[a], #4]\n\t"
  54127. "LDR r12, [%[a], #8]\n\t"
  54128. "LSR r3, r3, #9\n\t"
  54129. "ORR r3, r3, r12, LSL #23\n\t"
  54130. "STR r3, [%[a], #8]\n\t"
  54131. "LDR r3, [%[a], #12]\n\t"
  54132. "LSR r12, r12, #9\n\t"
  54133. "ORR r12, r12, r3, LSL #23\n\t"
  54134. "STR r12, [%[a], #12]\n\t"
  54135. "LDR r12, [%[a], #16]\n\t"
  54136. "LSR r3, r3, #9\n\t"
  54137. "ORR r3, r3, r12, LSL #23\n\t"
  54138. "STR r3, [%[a], #16]\n\t"
  54139. "LDR r3, [%[a], #20]\n\t"
  54140. "LSR r12, r12, #9\n\t"
  54141. "ORR r12, r12, r3, LSL #23\n\t"
  54142. "STR r12, [%[a], #20]\n\t"
  54143. "LDR r12, [%[a], #24]\n\t"
  54144. "LSR r3, r3, #9\n\t"
  54145. "ORR r3, r3, r12, LSL #23\n\t"
  54146. "STR r3, [%[a], #24]\n\t"
  54147. "LDR r3, [%[a], #28]\n\t"
  54148. "LSR r12, r12, #9\n\t"
  54149. "ORR r12, r12, r3, LSL #23\n\t"
  54150. "STR r12, [%[a], #28]\n\t"
  54151. "LDR r12, [%[a], #32]\n\t"
  54152. "LSR r3, r3, #9\n\t"
  54153. "ORR r3, r3, r12, LSL #23\n\t"
  54154. "STR r3, [%[a], #32]\n\t"
  54155. "LDR r3, [%[a], #36]\n\t"
  54156. "LSR r12, r12, #9\n\t"
  54157. "ORR r12, r12, r3, LSL #23\n\t"
  54158. "STR r12, [%[a], #36]\n\t"
  54159. "LDR r12, [%[a], #40]\n\t"
  54160. "LSR r3, r3, #9\n\t"
  54161. "ORR r3, r3, r12, LSL #23\n\t"
  54162. "STR r3, [%[a], #40]\n\t"
  54163. "LDR r3, [%[a], #44]\n\t"
  54164. "LSR r12, r12, #9\n\t"
  54165. "ORR r12, r12, r3, LSL #23\n\t"
  54166. "STR r12, [%[a], #44]\n\t"
  54167. "LDR r12, [%[a], #48]\n\t"
  54168. "LSR r3, r3, #9\n\t"
  54169. "ORR r3, r3, r12, LSL #23\n\t"
  54170. "STR r3, [%[a], #48]\n\t"
  54171. "LDR r3, [%[a], #52]\n\t"
  54172. "LSR r12, r12, #9\n\t"
  54173. "ORR r12, r12, r3, LSL #23\n\t"
  54174. "STR r12, [%[a], #52]\n\t"
  54175. "LDR r12, [%[a], #56]\n\t"
  54176. "LSR r3, r3, #9\n\t"
  54177. "ORR r3, r3, r12, LSL #23\n\t"
  54178. "STR r3, [%[a], #56]\n\t"
  54179. "LDR r3, [%[a], #60]\n\t"
  54180. "LSR r12, r12, #9\n\t"
  54181. "ORR r12, r12, r3, LSL #23\n\t"
  54182. "STR r12, [%[a], #60]\n\t"
  54183. "LDR r12, [%[a], #64]\n\t"
  54184. "LSR r3, r3, #9\n\t"
  54185. "ORR r3, r3, r12, LSL #23\n\t"
  54186. "STR r3, [%[a], #64]\n\t"
  54187. "LSR r12, r12, #9\n\t"
  54188. "STR r12, [%[a], #68]\n\t"
  54189. "LSR r5, r12, #9\n\t"
  54190. "ADD %[a], %[a], #0x4\n\t"
  54191. "MOV %[mp], r5\n\t"
  54192. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  54193. :
  54194. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  54195. );
  54196. sp_521_cond_sub_17(a - 17, a, m, (sp_digit)0 - mp);
  54197. }
  54198. #endif
  54199. /* Multiply two Montgomery form numbers mod the modulus (prime).
  54200. * (r = a * b mod m)
  54201. *
  54202. * r Result of multiplication.
  54203. * a First number to multiply in Montgomery form.
  54204. * b Second number to multiply in Montgomery form.
  54205. * m Modulus (prime).
  54206. * mp Montgomery multiplier.
  54207. */
  54208. SP_NOINLINE static void sp_521_mont_mul_17(sp_digit* r, const sp_digit* a,
  54209. const sp_digit* b, const sp_digit* m, sp_digit mp)
  54210. {
  54211. sp_521_mul_17(r, a, b);
  54212. sp_521_mont_reduce_17(r, m, mp);
  54213. }
  54214. /* Square the Montgomery form number. (r = a * a mod m)
  54215. *
  54216. * r Result of squaring.
  54217. * a Number to square in Montgomery form.
  54218. * m Modulus (prime).
  54219. * mp Montgomery multiplier.
  54220. */
  54221. SP_NOINLINE static void sp_521_mont_sqr_17(sp_digit* r, const sp_digit* a,
  54222. const sp_digit* m, sp_digit mp)
  54223. {
  54224. sp_521_sqr_17(r, a);
  54225. sp_521_mont_reduce_17(r, m, mp);
  54226. }
  54227. #ifndef WOLFSSL_SP_SMALL
  54228. /* Square the Montgomery form number a number of times. (r = a ^ n mod m)
  54229. *
  54230. * r Result of squaring.
  54231. * a Number to square in Montgomery form.
  54232. * n Number of times to square.
  54233. * m Modulus (prime).
  54234. * mp Montgomery multiplier.
  54235. */
  54236. SP_NOINLINE static void sp_521_mont_sqr_n_17(sp_digit* r,
  54237. const sp_digit* a, int n, const sp_digit* m, sp_digit mp)
  54238. {
  54239. sp_521_mont_sqr_17(r, a, m, mp);
  54240. for (; n > 1; n--) {
  54241. sp_521_mont_sqr_17(r, r, m, mp);
  54242. }
  54243. }
  54244. #endif /* !WOLFSSL_SP_SMALL */
  54245. #ifdef WOLFSSL_SP_SMALL
  54246. /* Mod-2 for the P521 curve. */
  54247. static const uint32_t p521_mod_minus_2[17] = {
  54248. 0xfffffffdU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,
  54249. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,
  54250. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU
  54251. };
  54252. #endif /* !WOLFSSL_SP_SMALL */
  54253. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  54254. * P521 curve. (r = 1 / a mod m)
  54255. *
  54256. * r Inverse result.
  54257. * a Number to invert.
  54258. * td Temporary data.
  54259. */
  54260. static void sp_521_mont_inv_17(sp_digit* r, const sp_digit* a, sp_digit* td)
  54261. {
  54262. #ifdef WOLFSSL_SP_SMALL
  54263. sp_digit* t = td;
  54264. int i;
  54265. XMEMCPY(t, a, sizeof(sp_digit) * 17);
  54266. for (i=519; i>=0; i--) {
  54267. sp_521_mont_sqr_17(t, t, p521_mod, p521_mp_mod);
  54268. if (p521_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
  54269. sp_521_mont_mul_17(t, t, a, p521_mod, p521_mp_mod);
  54270. }
  54271. XMEMCPY(r, t, sizeof(sp_digit) * 17);
  54272. #else
  54273. sp_digit* t1 = td;
  54274. sp_digit* t2 = td + 2 * 17;
  54275. sp_digit* t3 = td + 4 * 17;
  54276. /* 0x2 */
  54277. sp_521_mont_sqr_17(t1, a, p521_mod, p521_mp_mod);
  54278. /* 0x3 */
  54279. sp_521_mont_mul_17(t2, t1, a, p521_mod, p521_mp_mod);
  54280. /* 0x6 */
  54281. sp_521_mont_sqr_17(t1, t2, p521_mod, p521_mp_mod);
  54282. /* 0x7 */
  54283. sp_521_mont_mul_17(t3, t1, a, p521_mod, p521_mp_mod);
  54284. /* 0xc */
  54285. sp_521_mont_sqr_n_17(t1, t2, 2, p521_mod, p521_mp_mod);
  54286. /* 0xf */
  54287. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54288. /* 0x78 */
  54289. sp_521_mont_sqr_n_17(t1, t2, 3, p521_mod, p521_mp_mod);
  54290. /* 0x7f */
  54291. sp_521_mont_mul_17(t3, t3, t1, p521_mod, p521_mp_mod);
  54292. /* 0xf0 */
  54293. sp_521_mont_sqr_n_17(t1, t2, 4, p521_mod, p521_mp_mod);
  54294. /* 0xff */
  54295. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54296. /* 0xff00 */
  54297. sp_521_mont_sqr_n_17(t1, t2, 8, p521_mod, p521_mp_mod);
  54298. /* 0xffff */
  54299. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54300. /* 0xffff0000 */
  54301. sp_521_mont_sqr_n_17(t1, t2, 16, p521_mod, p521_mp_mod);
  54302. /* 0xffffffff */
  54303. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54304. /* 0xffffffff00000000 */
  54305. sp_521_mont_sqr_n_17(t1, t2, 32, p521_mod, p521_mp_mod);
  54306. /* 0xffffffffffffffff */
  54307. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54308. /* 0xffffffffffffffff0000000000000000 */
  54309. sp_521_mont_sqr_n_17(t1, t2, 64, p521_mod, p521_mp_mod);
  54310. /* 0xffffffffffffffffffffffffffffffff */
  54311. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54312. /* 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000 */
  54313. sp_521_mont_sqr_n_17(t1, t2, 128, p521_mod, p521_mp_mod);
  54314. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  54315. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54316. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000 */
  54317. sp_521_mont_sqr_n_17(t1, t2, 256, p521_mod, p521_mp_mod);
  54318. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  54319. sp_521_mont_mul_17(t2, t2, t1, p521_mod, p521_mp_mod);
  54320. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 */
  54321. sp_521_mont_sqr_n_17(t1, t2, 7, p521_mod, p521_mp_mod);
  54322. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  54323. sp_521_mont_mul_17(t2, t3, t1, p521_mod, p521_mp_mod);
  54324. /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc */
  54325. sp_521_mont_sqr_n_17(t1, t2, 2, p521_mod, p521_mp_mod);
  54326. /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd */
  54327. sp_521_mont_mul_17(r, t1, a, p521_mod, p521_mp_mod);
  54328. #endif /* WOLFSSL_SP_SMALL */
  54329. }
  54330. /* Compare a with b in constant time.
  54331. *
  54332. * a A single precision integer.
  54333. * b A single precision integer.
  54334. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  54335. * respectively.
  54336. */
  54337. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54338. static sp_int32 sp_521_cmp_17(const sp_digit* a_p, const sp_digit* b_p)
  54339. #else
  54340. static sp_int32 sp_521_cmp_17(const sp_digit* a, const sp_digit* b)
  54341. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54342. {
  54343. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54344. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  54345. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  54346. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54347. __asm__ __volatile__ (
  54348. "MOV r2, #0xffffffff\n\t"
  54349. "MOV r8, #0x1\n\t"
  54350. "MOV r7, #0x0\n\t"
  54351. "MOV r3, #0xffffffff\n\t"
  54352. #ifdef WOLFSSL_SP_SMALL
  54353. "MOV r6, #0x40\n\t"
  54354. "\n"
  54355. "L_sp_521_cmp_17_words:\n\t"
  54356. "LDR r4, [%[a], r6]\n\t"
  54357. "LDR r5, [%[b], r6]\n\t"
  54358. "AND r4, r4, r3\n\t"
  54359. "AND r5, r5, r3\n\t"
  54360. "SUBS r4, r4, r5\n\t"
  54361. "IT hi\n\t"
  54362. "movhi r2, r8\n\t"
  54363. "IT lo\n\t"
  54364. "movlo r2, r3\n\t"
  54365. "IT ne\n\t"
  54366. "movne r3, r7\n\t"
  54367. "SUBS r6, r6, #0x4\n\t"
  54368. "bcs L_sp_521_cmp_17_words\n\t"
  54369. "EOR r2, r2, r3\n\t"
  54370. #else
  54371. "LDR r4, [%[a], #64]\n\t"
  54372. "LDR r5, [%[b], #64]\n\t"
  54373. "AND r4, r4, r3\n\t"
  54374. "AND r5, r5, r3\n\t"
  54375. "SUBS r4, r4, r5\n\t"
  54376. "IT hi\n\t"
  54377. "movhi r2, r8\n\t"
  54378. "IT lo\n\t"
  54379. "movlo r2, r3\n\t"
  54380. "IT ne\n\t"
  54381. "movne r3, r7\n\t"
  54382. "LDR r4, [%[a], #60]\n\t"
  54383. "LDR r5, [%[b], #60]\n\t"
  54384. "AND r4, r4, r3\n\t"
  54385. "AND r5, r5, r3\n\t"
  54386. "SUBS r4, r4, r5\n\t"
  54387. "IT hi\n\t"
  54388. "movhi r2, r8\n\t"
  54389. "IT lo\n\t"
  54390. "movlo r2, r3\n\t"
  54391. "IT ne\n\t"
  54392. "movne r3, r7\n\t"
  54393. "LDR r4, [%[a], #56]\n\t"
  54394. "LDR r5, [%[b], #56]\n\t"
  54395. "AND r4, r4, r3\n\t"
  54396. "AND r5, r5, r3\n\t"
  54397. "SUBS r4, r4, r5\n\t"
  54398. "IT hi\n\t"
  54399. "movhi r2, r8\n\t"
  54400. "IT lo\n\t"
  54401. "movlo r2, r3\n\t"
  54402. "IT ne\n\t"
  54403. "movne r3, r7\n\t"
  54404. "LDR r4, [%[a], #52]\n\t"
  54405. "LDR r5, [%[b], #52]\n\t"
  54406. "AND r4, r4, r3\n\t"
  54407. "AND r5, r5, r3\n\t"
  54408. "SUBS r4, r4, r5\n\t"
  54409. "IT hi\n\t"
  54410. "movhi r2, r8\n\t"
  54411. "IT lo\n\t"
  54412. "movlo r2, r3\n\t"
  54413. "IT ne\n\t"
  54414. "movne r3, r7\n\t"
  54415. "LDR r4, [%[a], #48]\n\t"
  54416. "LDR r5, [%[b], #48]\n\t"
  54417. "AND r4, r4, r3\n\t"
  54418. "AND r5, r5, r3\n\t"
  54419. "SUBS r4, r4, r5\n\t"
  54420. "IT hi\n\t"
  54421. "movhi r2, r8\n\t"
  54422. "IT lo\n\t"
  54423. "movlo r2, r3\n\t"
  54424. "IT ne\n\t"
  54425. "movne r3, r7\n\t"
  54426. "LDR r4, [%[a], #44]\n\t"
  54427. "LDR r5, [%[b], #44]\n\t"
  54428. "AND r4, r4, r3\n\t"
  54429. "AND r5, r5, r3\n\t"
  54430. "SUBS r4, r4, r5\n\t"
  54431. "IT hi\n\t"
  54432. "movhi r2, r8\n\t"
  54433. "IT lo\n\t"
  54434. "movlo r2, r3\n\t"
  54435. "IT ne\n\t"
  54436. "movne r3, r7\n\t"
  54437. "LDR r4, [%[a], #40]\n\t"
  54438. "LDR r5, [%[b], #40]\n\t"
  54439. "AND r4, r4, r3\n\t"
  54440. "AND r5, r5, r3\n\t"
  54441. "SUBS r4, r4, r5\n\t"
  54442. "IT hi\n\t"
  54443. "movhi r2, r8\n\t"
  54444. "IT lo\n\t"
  54445. "movlo r2, r3\n\t"
  54446. "IT ne\n\t"
  54447. "movne r3, r7\n\t"
  54448. "LDR r4, [%[a], #36]\n\t"
  54449. "LDR r5, [%[b], #36]\n\t"
  54450. "AND r4, r4, r3\n\t"
  54451. "AND r5, r5, r3\n\t"
  54452. "SUBS r4, r4, r5\n\t"
  54453. "IT hi\n\t"
  54454. "movhi r2, r8\n\t"
  54455. "IT lo\n\t"
  54456. "movlo r2, r3\n\t"
  54457. "IT ne\n\t"
  54458. "movne r3, r7\n\t"
  54459. "LDR r4, [%[a], #32]\n\t"
  54460. "LDR r5, [%[b], #32]\n\t"
  54461. "AND r4, r4, r3\n\t"
  54462. "AND r5, r5, r3\n\t"
  54463. "SUBS r4, r4, r5\n\t"
  54464. "IT hi\n\t"
  54465. "movhi r2, r8\n\t"
  54466. "IT lo\n\t"
  54467. "movlo r2, r3\n\t"
  54468. "IT ne\n\t"
  54469. "movne r3, r7\n\t"
  54470. "LDR r4, [%[a], #28]\n\t"
  54471. "LDR r5, [%[b], #28]\n\t"
  54472. "AND r4, r4, r3\n\t"
  54473. "AND r5, r5, r3\n\t"
  54474. "SUBS r4, r4, r5\n\t"
  54475. "IT hi\n\t"
  54476. "movhi r2, r8\n\t"
  54477. "IT lo\n\t"
  54478. "movlo r2, r3\n\t"
  54479. "IT ne\n\t"
  54480. "movne r3, r7\n\t"
  54481. "LDR r4, [%[a], #24]\n\t"
  54482. "LDR r5, [%[b], #24]\n\t"
  54483. "AND r4, r4, r3\n\t"
  54484. "AND r5, r5, r3\n\t"
  54485. "SUBS r4, r4, r5\n\t"
  54486. "IT hi\n\t"
  54487. "movhi r2, r8\n\t"
  54488. "IT lo\n\t"
  54489. "movlo r2, r3\n\t"
  54490. "IT ne\n\t"
  54491. "movne r3, r7\n\t"
  54492. "LDR r4, [%[a], #20]\n\t"
  54493. "LDR r5, [%[b], #20]\n\t"
  54494. "AND r4, r4, r3\n\t"
  54495. "AND r5, r5, r3\n\t"
  54496. "SUBS r4, r4, r5\n\t"
  54497. "IT hi\n\t"
  54498. "movhi r2, r8\n\t"
  54499. "IT lo\n\t"
  54500. "movlo r2, r3\n\t"
  54501. "IT ne\n\t"
  54502. "movne r3, r7\n\t"
  54503. "LDR r4, [%[a], #16]\n\t"
  54504. "LDR r5, [%[b], #16]\n\t"
  54505. "AND r4, r4, r3\n\t"
  54506. "AND r5, r5, r3\n\t"
  54507. "SUBS r4, r4, r5\n\t"
  54508. "IT hi\n\t"
  54509. "movhi r2, r8\n\t"
  54510. "IT lo\n\t"
  54511. "movlo r2, r3\n\t"
  54512. "IT ne\n\t"
  54513. "movne r3, r7\n\t"
  54514. "LDR r4, [%[a], #12]\n\t"
  54515. "LDR r5, [%[b], #12]\n\t"
  54516. "AND r4, r4, r3\n\t"
  54517. "AND r5, r5, r3\n\t"
  54518. "SUBS r4, r4, r5\n\t"
  54519. "IT hi\n\t"
  54520. "movhi r2, r8\n\t"
  54521. "IT lo\n\t"
  54522. "movlo r2, r3\n\t"
  54523. "IT ne\n\t"
  54524. "movne r3, r7\n\t"
  54525. "LDR r4, [%[a], #8]\n\t"
  54526. "LDR r5, [%[b], #8]\n\t"
  54527. "AND r4, r4, r3\n\t"
  54528. "AND r5, r5, r3\n\t"
  54529. "SUBS r4, r4, r5\n\t"
  54530. "IT hi\n\t"
  54531. "movhi r2, r8\n\t"
  54532. "IT lo\n\t"
  54533. "movlo r2, r3\n\t"
  54534. "IT ne\n\t"
  54535. "movne r3, r7\n\t"
  54536. "LDR r4, [%[a], #4]\n\t"
  54537. "LDR r5, [%[b], #4]\n\t"
  54538. "AND r4, r4, r3\n\t"
  54539. "AND r5, r5, r3\n\t"
  54540. "SUBS r4, r4, r5\n\t"
  54541. "IT hi\n\t"
  54542. "movhi r2, r8\n\t"
  54543. "IT lo\n\t"
  54544. "movlo r2, r3\n\t"
  54545. "IT ne\n\t"
  54546. "movne r3, r7\n\t"
  54547. "LDR r4, [%[a]]\n\t"
  54548. "LDR r5, [%[b]]\n\t"
  54549. "AND r4, r4, r3\n\t"
  54550. "AND r5, r5, r3\n\t"
  54551. "SUBS r4, r4, r5\n\t"
  54552. "IT hi\n\t"
  54553. "movhi r2, r8\n\t"
  54554. "IT lo\n\t"
  54555. "movlo r2, r3\n\t"
  54556. "IT ne\n\t"
  54557. "movne r3, r7\n\t"
  54558. "EOR r2, r2, r3\n\t"
  54559. #endif /*WOLFSSL_SP_SMALL */
  54560. "MOV %[a], r2\n\t"
  54561. : [a] "+r" (a), [b] "+r" (b)
  54562. :
  54563. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  54564. );
  54565. return (uint32_t)(size_t)a;
  54566. }
  54567. /* Normalize the values in each word to 32.
  54568. *
  54569. * a Array of sp_digit to normalize.
  54570. */
  54571. #define sp_521_norm_17(a)
  54572. /* Map the Montgomery form projective coordinate point to an affine point.
  54573. *
  54574. * r Resulting affine coordinate point.
  54575. * p Montgomery form projective coordinate point.
  54576. * t Temporary ordinate data.
  54577. */
  54578. static void sp_521_map_17(sp_point_521* r, const sp_point_521* p,
  54579. sp_digit* t)
  54580. {
  54581. sp_digit* t1 = t;
  54582. sp_digit* t2 = t + 2*17;
  54583. sp_int32 n;
  54584. sp_521_mont_inv_17(t1, p->z, t + 2*17);
  54585. sp_521_mont_sqr_17(t2, t1, p521_mod, p521_mp_mod);
  54586. sp_521_mont_mul_17(t1, t2, t1, p521_mod, p521_mp_mod);
  54587. /* x /= z^2 */
  54588. sp_521_mont_mul_17(r->x, p->x, t2, p521_mod, p521_mp_mod);
  54589. XMEMSET(r->x + 17, 0, sizeof(sp_digit) * 17U);
  54590. sp_521_mont_reduce_17(r->x, p521_mod, p521_mp_mod);
  54591. /* Reduce x to less than modulus */
  54592. n = sp_521_cmp_17(r->x, p521_mod);
  54593. sp_521_cond_sub_17(r->x, r->x, p521_mod, ~(n >> 31));
  54594. sp_521_norm_17(r->x);
  54595. /* y /= z^3 */
  54596. sp_521_mont_mul_17(r->y, p->y, t1, p521_mod, p521_mp_mod);
  54597. XMEMSET(r->y + 17, 0, sizeof(sp_digit) * 17U);
  54598. sp_521_mont_reduce_17(r->y, p521_mod, p521_mp_mod);
  54599. /* Reduce y to less than modulus */
  54600. n = sp_521_cmp_17(r->y, p521_mod);
  54601. sp_521_cond_sub_17(r->y, r->y, p521_mod, ~(n >> 31));
  54602. sp_521_norm_17(r->y);
  54603. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  54604. r->z[0] = 1;
  54605. }
  54606. /* Add two Montgomery form numbers (r = a + b % m).
  54607. *
  54608. * r Result of addition.
  54609. * a First number to add in Montgomery form.
  54610. * b Second number to add in Montgomery form.
  54611. * m Modulus (prime).
  54612. */
  54613. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54614. SP_NOINLINE static void sp_521_mont_add_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  54615. #else
  54616. SP_NOINLINE static void sp_521_mont_add_17(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  54617. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54618. {
  54619. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54620. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  54621. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  54622. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  54623. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54624. __asm__ __volatile__ (
  54625. "MOV r3, #0x0\n\t"
  54626. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54627. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54628. "ADDS r8, r8, r4\n\t"
  54629. "ADCS r9, r9, r5\n\t"
  54630. "ADCS r10, r10, r6\n\t"
  54631. "ADCS r11, r11, r7\n\t"
  54632. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54633. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54634. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54635. "ADCS r8, r8, r4\n\t"
  54636. "ADCS r9, r9, r5\n\t"
  54637. "ADCS r10, r10, r6\n\t"
  54638. "ADCS r11, r11, r7\n\t"
  54639. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54640. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54641. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54642. "ADCS r8, r8, r4\n\t"
  54643. "ADCS r9, r9, r5\n\t"
  54644. "ADCS r10, r10, r6\n\t"
  54645. "ADCS r11, r11, r7\n\t"
  54646. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54647. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54648. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54649. "ADCS r8, r8, r4\n\t"
  54650. "ADCS r9, r9, r5\n\t"
  54651. "ADCS r10, r10, r6\n\t"
  54652. "ADCS r11, r11, r7\n\t"
  54653. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54654. "LDM %[a]!, {r8}\n\t"
  54655. "LDM %[b]!, {r4}\n\t"
  54656. "ADCS r8, r8, r4\n\t"
  54657. "MOV r12, #0x1ff\n\t"
  54658. "LSR r3, r8, #9\n\t"
  54659. "AND r8, r8, r12\n\t"
  54660. "STM %[r]!, {r8}\n\t"
  54661. "SUB %[r], %[r], #0x44\n\t"
  54662. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54663. "ADDS r4, r4, r3\n\t"
  54664. "ADCS r5, r5, #0x0\n\t"
  54665. "ADCS r6, r6, #0x0\n\t"
  54666. "ADCS r7, r7, #0x0\n\t"
  54667. "ADCS r8, r8, #0x0\n\t"
  54668. "ADCS r9, r9, #0x0\n\t"
  54669. "ADCS r10, r10, #0x0\n\t"
  54670. "ADCS r11, r11, #0x0\n\t"
  54671. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54672. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54673. "ADCS r4, r4, #0x0\n\t"
  54674. "ADCS r5, r5, #0x0\n\t"
  54675. "ADCS r6, r6, #0x0\n\t"
  54676. "ADCS r7, r7, #0x0\n\t"
  54677. "ADCS r8, r8, #0x0\n\t"
  54678. "ADCS r9, r9, #0x0\n\t"
  54679. "ADCS r10, r10, #0x0\n\t"
  54680. "ADCS r11, r11, #0x0\n\t"
  54681. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54682. "LDM %[r], {r4}\n\t"
  54683. "ADCS r4, r4, #0x0\n\t"
  54684. "STM %[r]!, {r4}\n\t"
  54685. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  54686. :
  54687. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  54688. );
  54689. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54690. (void)m_p;
  54691. #else
  54692. (void)m;
  54693. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54694. }
  54695. /* Double a Montgomery form number (r = a + a % m).
  54696. *
  54697. * r Result of doubling.
  54698. * a Number to double in Montgomery form.
  54699. * m Modulus (prime).
  54700. */
  54701. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54702. SP_NOINLINE static void sp_521_mont_dbl_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  54703. #else
  54704. SP_NOINLINE static void sp_521_mont_dbl_17(sp_digit* r, const sp_digit* a, const sp_digit* m)
  54705. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54706. {
  54707. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54708. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  54709. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  54710. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54711. __asm__ __volatile__ (
  54712. "MOV r2, #0x0\n\t"
  54713. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54714. "ADDS r4, r4, r4\n\t"
  54715. "ADCS r5, r5, r5\n\t"
  54716. "ADCS r6, r6, r6\n\t"
  54717. "ADCS r7, r7, r7\n\t"
  54718. "ADCS r8, r8, r8\n\t"
  54719. "ADCS r9, r9, r9\n\t"
  54720. "ADCS r10, r10, r10\n\t"
  54721. "ADCS r11, r11, r11\n\t"
  54722. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54723. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54724. "ADCS r4, r4, r4\n\t"
  54725. "ADCS r5, r5, r5\n\t"
  54726. "ADCS r6, r6, r6\n\t"
  54727. "ADCS r7, r7, r7\n\t"
  54728. "ADCS r8, r8, r8\n\t"
  54729. "ADCS r9, r9, r9\n\t"
  54730. "ADCS r10, r10, r10\n\t"
  54731. "ADCS r11, r11, r11\n\t"
  54732. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54733. "LDM %[a]!, {r4}\n\t"
  54734. "ADCS r4, r4, r4\n\t"
  54735. "MOV r3, #0x1ff\n\t"
  54736. "LSR r2, r4, #9\n\t"
  54737. "AND r4, r4, r3\n\t"
  54738. "STM %[r]!, {r4}\n\t"
  54739. "SUB %[r], %[r], #0x44\n\t"
  54740. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54741. "ADDS r4, r4, r2\n\t"
  54742. "ADCS r5, r5, #0x0\n\t"
  54743. "ADCS r6, r6, #0x0\n\t"
  54744. "ADCS r7, r7, #0x0\n\t"
  54745. "ADCS r8, r8, #0x0\n\t"
  54746. "ADCS r9, r9, #0x0\n\t"
  54747. "ADCS r10, r10, #0x0\n\t"
  54748. "ADCS r11, r11, #0x0\n\t"
  54749. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54750. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54751. "ADCS r4, r4, #0x0\n\t"
  54752. "ADCS r5, r5, #0x0\n\t"
  54753. "ADCS r6, r6, #0x0\n\t"
  54754. "ADCS r7, r7, #0x0\n\t"
  54755. "ADCS r8, r8, #0x0\n\t"
  54756. "ADCS r9, r9, #0x0\n\t"
  54757. "ADCS r10, r10, #0x0\n\t"
  54758. "ADCS r11, r11, #0x0\n\t"
  54759. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54760. "LDM %[r], {r4}\n\t"
  54761. "ADCS r4, r4, #0x0\n\t"
  54762. "STM %[r]!, {r4}\n\t"
  54763. : [r] "+r" (r), [a] "+r" (a)
  54764. :
  54765. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r2", "r3", "cc"
  54766. );
  54767. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54768. (void)m_p;
  54769. #else
  54770. (void)m;
  54771. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54772. }
  54773. /* Triple a Montgomery form number (r = a + a + a % m).
  54774. *
  54775. * r Result of Tripling.
  54776. * a Number to triple in Montgomery form.
  54777. * m Modulus (prime).
  54778. */
  54779. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54780. SP_NOINLINE static void sp_521_mont_tpl_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  54781. #else
  54782. SP_NOINLINE static void sp_521_mont_tpl_17(sp_digit* r, const sp_digit* a, const sp_digit* m)
  54783. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54784. {
  54785. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54786. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  54787. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  54788. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54789. __asm__ __volatile__ (
  54790. "MOV r2, #0x0\n\t"
  54791. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54792. "ADDS r4, r4, r4\n\t"
  54793. "ADCS r5, r5, r5\n\t"
  54794. "ADCS r6, r6, r6\n\t"
  54795. "ADCS r7, r7, r7\n\t"
  54796. "ADCS r8, r8, r8\n\t"
  54797. "ADCS r9, r9, r9\n\t"
  54798. "ADCS r10, r10, r10\n\t"
  54799. "ADCS r11, r11, r11\n\t"
  54800. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54801. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54802. "ADCS r4, r4, r4\n\t"
  54803. "ADCS r5, r5, r5\n\t"
  54804. "ADCS r6, r6, r6\n\t"
  54805. "ADCS r7, r7, r7\n\t"
  54806. "ADCS r8, r8, r8\n\t"
  54807. "ADCS r9, r9, r9\n\t"
  54808. "ADCS r10, r10, r10\n\t"
  54809. "ADCS r11, r11, r11\n\t"
  54810. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54811. "LDM %[a]!, {r4}\n\t"
  54812. "ADCS r4, r4, r4\n\t"
  54813. "STM %[r]!, {r4}\n\t"
  54814. "SUB %[r], %[r], #0x44\n\t"
  54815. "SUB %[a], %[a], #0x44\n\t"
  54816. "LDM %[r], {r4, r5, r6, r7}\n\t"
  54817. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54818. "ADDS r4, r4, r8\n\t"
  54819. "ADCS r5, r5, r9\n\t"
  54820. "ADCS r6, r6, r10\n\t"
  54821. "ADCS r7, r7, r11\n\t"
  54822. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  54823. "LDM %[r], {r4, r5, r6, r7}\n\t"
  54824. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54825. "ADCS r4, r4, r8\n\t"
  54826. "ADCS r5, r5, r9\n\t"
  54827. "ADCS r6, r6, r10\n\t"
  54828. "ADCS r7, r7, r11\n\t"
  54829. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  54830. "LDM %[r], {r4, r5, r6, r7}\n\t"
  54831. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54832. "ADCS r4, r4, r8\n\t"
  54833. "ADCS r5, r5, r9\n\t"
  54834. "ADCS r6, r6, r10\n\t"
  54835. "ADCS r7, r7, r11\n\t"
  54836. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  54837. "LDM %[r], {r4, r5, r6, r7}\n\t"
  54838. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54839. "ADCS r4, r4, r8\n\t"
  54840. "ADCS r5, r5, r9\n\t"
  54841. "ADCS r6, r6, r10\n\t"
  54842. "ADCS r7, r7, r11\n\t"
  54843. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  54844. "LDM %[r], {r4}\n\t"
  54845. "LDM %[a]!, {r8}\n\t"
  54846. "ADCS r4, r4, r8\n\t"
  54847. "MOV r3, #0x1ff\n\t"
  54848. "LSR r2, r4, #9\n\t"
  54849. "AND r4, r4, r3\n\t"
  54850. "STM %[r]!, {r4}\n\t"
  54851. "SUB %[r], %[r], #0x44\n\t"
  54852. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54853. "ADDS r4, r4, r2\n\t"
  54854. "ADCS r4, r4, #0x0\n\t"
  54855. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54856. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54857. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54858. "LDM %[r], {r4}\n\t"
  54859. "ADCS r4, r4, #0x0\n\t"
  54860. "STM %[r]!, {r4}\n\t"
  54861. : [r] "+r" (r), [a] "+r" (a)
  54862. :
  54863. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r2", "r3", "cc"
  54864. );
  54865. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54866. (void)m_p;
  54867. #else
  54868. (void)m;
  54869. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54870. }
  54871. /* Subtract two Montgomery form numbers (r = a - b % m).
  54872. *
  54873. * r Result of subtration.
  54874. * a Number to subtract from in Montgomery form.
  54875. * b Number to subtract with in Montgomery form.
  54876. * m Modulus (prime).
  54877. */
  54878. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54879. SP_NOINLINE static void sp_521_mont_sub_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  54880. #else
  54881. SP_NOINLINE static void sp_521_mont_sub_17(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  54882. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54883. {
  54884. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54885. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  54886. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  54887. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  54888. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54889. __asm__ __volatile__ (
  54890. "MOV r3, #0x0\n\t"
  54891. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54892. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54893. "SUBS r8, r8, r4\n\t"
  54894. "SBCS r9, r9, r5\n\t"
  54895. "SBCS r10, r10, r6\n\t"
  54896. "SBCS r11, r11, r7\n\t"
  54897. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54898. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54899. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54900. "SBCS r8, r8, r4\n\t"
  54901. "SBCS r9, r9, r5\n\t"
  54902. "SBCS r10, r10, r6\n\t"
  54903. "SBCS r11, r11, r7\n\t"
  54904. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54905. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54906. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54907. "SBCS r8, r8, r4\n\t"
  54908. "SBCS r9, r9, r5\n\t"
  54909. "SBCS r10, r10, r6\n\t"
  54910. "SBCS r11, r11, r7\n\t"
  54911. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54912. "LDM %[a]!, {r8, r9, r10, r11}\n\t"
  54913. "LDM %[b]!, {r4, r5, r6, r7}\n\t"
  54914. "SBCS r8, r8, r4\n\t"
  54915. "SBCS r9, r9, r5\n\t"
  54916. "SBCS r10, r10, r6\n\t"
  54917. "SBCS r11, r11, r7\n\t"
  54918. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  54919. "LDM %[a]!, {r8}\n\t"
  54920. "LDM %[b]!, {r4}\n\t"
  54921. "SBCS r8, r8, r4\n\t"
  54922. "MOV r12, #0x1ff\n\t"
  54923. "ASR r3, r8, #9\n\t"
  54924. "AND r8, r8, r12\n\t"
  54925. "neg r3, r3\n\t"
  54926. "STM %[r]!, {r8}\n\t"
  54927. "SUB %[r], %[r], #0x44\n\t"
  54928. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54929. "SUBS r4, r4, r3\n\t"
  54930. "SBCS r5, r5, #0x0\n\t"
  54931. "SBCS r6, r6, #0x0\n\t"
  54932. "SBCS r7, r7, #0x0\n\t"
  54933. "SBCS r8, r8, #0x0\n\t"
  54934. "SBCS r9, r9, #0x0\n\t"
  54935. "SBCS r10, r10, #0x0\n\t"
  54936. "SBCS r11, r11, #0x0\n\t"
  54937. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54938. "LDM %[r], {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54939. "SBCS r4, r4, #0x0\n\t"
  54940. "SBCS r5, r5, #0x0\n\t"
  54941. "SBCS r6, r6, #0x0\n\t"
  54942. "SBCS r7, r7, #0x0\n\t"
  54943. "SBCS r8, r8, #0x0\n\t"
  54944. "SBCS r9, r9, #0x0\n\t"
  54945. "SBCS r10, r10, #0x0\n\t"
  54946. "SBCS r11, r11, #0x0\n\t"
  54947. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  54948. "LDM %[r], {r4}\n\t"
  54949. "SBCS r4, r4, #0x0\n\t"
  54950. "STM %[r]!, {r4}\n\t"
  54951. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  54952. :
  54953. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  54954. );
  54955. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54956. (void)m_p;
  54957. #else
  54958. (void)m;
  54959. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54960. }
  54961. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54962. static void sp_521_rshift1_17(sp_digit* r_p, const sp_digit* a_p)
  54963. #else
  54964. static void sp_521_rshift1_17(sp_digit* r, const sp_digit* a)
  54965. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54966. {
  54967. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  54968. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  54969. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  54970. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  54971. __asm__ __volatile__ (
  54972. "LDM %[a], {r2, r3}\n\t"
  54973. "LSR r2, r2, #1\n\t"
  54974. "ORR r2, r2, r3, lsl #31\n\t"
  54975. "LSR r3, r3, #1\n\t"
  54976. "LDR r4, [%[a], #8]\n\t"
  54977. "STR r2, [%[r]]\n\t"
  54978. "ORR r3, r3, r4, lsl #31\n\t"
  54979. "LSR r4, r4, #1\n\t"
  54980. "LDR r2, [%[a], #12]\n\t"
  54981. "STR r3, [%[r], #4]\n\t"
  54982. "ORR r4, r4, r2, lsl #31\n\t"
  54983. "LSR r2, r2, #1\n\t"
  54984. "LDR r3, [%[a], #16]\n\t"
  54985. "STR r4, [%[r], #8]\n\t"
  54986. "ORR r2, r2, r3, lsl #31\n\t"
  54987. "LSR r3, r3, #1\n\t"
  54988. "LDR r4, [%[a], #20]\n\t"
  54989. "STR r2, [%[r], #12]\n\t"
  54990. "ORR r3, r3, r4, lsl #31\n\t"
  54991. "LSR r4, r4, #1\n\t"
  54992. "LDR r2, [%[a], #24]\n\t"
  54993. "STR r3, [%[r], #16]\n\t"
  54994. "ORR r4, r4, r2, lsl #31\n\t"
  54995. "LSR r2, r2, #1\n\t"
  54996. "LDR r3, [%[a], #28]\n\t"
  54997. "STR r4, [%[r], #20]\n\t"
  54998. "ORR r2, r2, r3, lsl #31\n\t"
  54999. "LSR r3, r3, #1\n\t"
  55000. "LDR r4, [%[a], #32]\n\t"
  55001. "STR r2, [%[r], #24]\n\t"
  55002. "ORR r3, r3, r4, lsl #31\n\t"
  55003. "LSR r4, r4, #1\n\t"
  55004. "LDR r2, [%[a], #36]\n\t"
  55005. "STR r3, [%[r], #28]\n\t"
  55006. "ORR r4, r4, r2, lsl #31\n\t"
  55007. "LSR r2, r2, #1\n\t"
  55008. "LDR r3, [%[a], #40]\n\t"
  55009. "STR r4, [%[r], #32]\n\t"
  55010. "ORR r2, r2, r3, lsl #31\n\t"
  55011. "LSR r3, r3, #1\n\t"
  55012. "LDR r4, [%[a], #44]\n\t"
  55013. "STR r2, [%[r], #36]\n\t"
  55014. "ORR r3, r3, r4, lsl #31\n\t"
  55015. "LSR r4, r4, #1\n\t"
  55016. "LDR r2, [%[a], #48]\n\t"
  55017. "STR r3, [%[r], #40]\n\t"
  55018. "ORR r4, r4, r2, lsl #31\n\t"
  55019. "LSR r2, r2, #1\n\t"
  55020. "LDR r3, [%[a], #52]\n\t"
  55021. "STR r4, [%[r], #44]\n\t"
  55022. "ORR r2, r2, r3, lsl #31\n\t"
  55023. "LSR r3, r3, #1\n\t"
  55024. "LDR r4, [%[a], #56]\n\t"
  55025. "STR r2, [%[r], #48]\n\t"
  55026. "ORR r3, r3, r4, lsl #31\n\t"
  55027. "LSR r4, r4, #1\n\t"
  55028. "LDR r2, [%[a], #60]\n\t"
  55029. "STR r3, [%[r], #52]\n\t"
  55030. "ORR r4, r4, r2, lsl #31\n\t"
  55031. "LSR r2, r2, #1\n\t"
  55032. "LDR r3, [%[a], #64]\n\t"
  55033. "STR r4, [%[r], #56]\n\t"
  55034. "ORR r2, r2, r3, lsl #31\n\t"
  55035. "LSR r3, r3, #1\n\t"
  55036. "STR r2, [%[r], #60]\n\t"
  55037. "STR r3, [%[r], #64]\n\t"
  55038. : [r] "+r" (r), [a] "+r" (a)
  55039. :
  55040. : "memory", "r2", "r3", "r4", "cc"
  55041. );
  55042. }
  55043. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  55044. *
  55045. * r Result of division by 2.
  55046. * a Number to divide.
  55047. * m Modulus (prime).
  55048. */
  55049. static void sp_521_mont_div2_17(sp_digit* r, const sp_digit* a, const sp_digit* m)
  55050. {
  55051. sp_digit o = a[0] & 1;
  55052. (void)m;
  55053. sp_521_rshift1_17(r, r);
  55054. r[16] |= o << 8;
  55055. }
  55056. /* Double the Montgomery form projective point p.
  55057. *
  55058. * r Result of doubling point.
  55059. * p Point to double.
  55060. * t Temporary ordinate data.
  55061. */
  55062. static void sp_521_proj_point_dbl_17(sp_point_521* r, const sp_point_521* p,
  55063. sp_digit* t)
  55064. {
  55065. sp_digit* t1 = t;
  55066. sp_digit* t2 = t + 2*17;
  55067. sp_digit* x;
  55068. sp_digit* y;
  55069. sp_digit* z;
  55070. x = r->x;
  55071. y = r->y;
  55072. z = r->z;
  55073. /* Put infinity into result. */
  55074. if (r != p) {
  55075. r->infinity = p->infinity;
  55076. }
  55077. /* T1 = Z * Z */
  55078. sp_521_mont_sqr_17(t1, p->z, p521_mod, p521_mp_mod);
  55079. /* Z = Y * Z */
  55080. sp_521_mont_mul_17(z, p->y, p->z, p521_mod, p521_mp_mod);
  55081. /* Z = 2Z */
  55082. sp_521_mont_dbl_17(z, z, p521_mod);
  55083. /* T2 = X - T1 */
  55084. sp_521_mont_sub_17(t2, p->x, t1, p521_mod);
  55085. /* T1 = X + T1 */
  55086. sp_521_mont_add_17(t1, p->x, t1, p521_mod);
  55087. /* T2 = T1 * T2 */
  55088. sp_521_mont_mul_17(t2, t1, t2, p521_mod, p521_mp_mod);
  55089. /* T1 = 3T2 */
  55090. sp_521_mont_tpl_17(t1, t2, p521_mod);
  55091. /* Y = 2Y */
  55092. sp_521_mont_dbl_17(y, p->y, p521_mod);
  55093. /* Y = Y * Y */
  55094. sp_521_mont_sqr_17(y, y, p521_mod, p521_mp_mod);
  55095. /* T2 = Y * Y */
  55096. sp_521_mont_sqr_17(t2, y, p521_mod, p521_mp_mod);
  55097. /* T2 = T2/2 */
  55098. sp_521_mont_div2_17(t2, t2, p521_mod);
  55099. /* Y = Y * X */
  55100. sp_521_mont_mul_17(y, y, p->x, p521_mod, p521_mp_mod);
  55101. /* X = T1 * T1 */
  55102. sp_521_mont_sqr_17(x, t1, p521_mod, p521_mp_mod);
  55103. /* X = X - Y */
  55104. sp_521_mont_sub_17(x, x, y, p521_mod);
  55105. /* X = X - Y */
  55106. sp_521_mont_sub_17(x, x, y, p521_mod);
  55107. /* Y = Y - X */
  55108. sp_521_mont_sub_17(y, y, x, p521_mod);
  55109. /* Y = Y * T1 */
  55110. sp_521_mont_mul_17(y, y, t1, p521_mod, p521_mp_mod);
  55111. /* Y = Y - T2 */
  55112. sp_521_mont_sub_17(y, y, t2, p521_mod);
  55113. }
  55114. #ifdef WOLFSSL_SP_NONBLOCK
  55115. typedef struct sp_521_proj_point_dbl_17_ctx {
  55116. int state;
  55117. sp_digit* t1;
  55118. sp_digit* t2;
  55119. sp_digit* x;
  55120. sp_digit* y;
  55121. sp_digit* z;
  55122. } sp_521_proj_point_dbl_17_ctx;
  55123. /* Double the Montgomery form projective point p.
  55124. *
  55125. * r Result of doubling point.
  55126. * p Point to double.
  55127. * t Temporary ordinate data.
  55128. */
  55129. static int sp_521_proj_point_dbl_17_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r,
  55130. const sp_point_521* p, sp_digit* t)
  55131. {
  55132. int err = FP_WOULDBLOCK;
  55133. sp_521_proj_point_dbl_17_ctx* ctx = (sp_521_proj_point_dbl_17_ctx*)sp_ctx->data;
  55134. typedef char ctx_size_test[sizeof(sp_521_proj_point_dbl_17_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  55135. (void)sizeof(ctx_size_test);
  55136. switch (ctx->state) {
  55137. case 0:
  55138. ctx->t1 = t;
  55139. ctx->t2 = t + 2*17;
  55140. ctx->x = r->x;
  55141. ctx->y = r->y;
  55142. ctx->z = r->z;
  55143. /* Put infinity into result. */
  55144. if (r != p) {
  55145. r->infinity = p->infinity;
  55146. }
  55147. ctx->state = 1;
  55148. break;
  55149. case 1:
  55150. /* T1 = Z * Z */
  55151. sp_521_mont_sqr_17(ctx->t1, p->z, p521_mod, p521_mp_mod);
  55152. ctx->state = 2;
  55153. break;
  55154. case 2:
  55155. /* Z = Y * Z */
  55156. sp_521_mont_mul_17(ctx->z, p->y, p->z, p521_mod, p521_mp_mod);
  55157. ctx->state = 3;
  55158. break;
  55159. case 3:
  55160. /* Z = 2Z */
  55161. sp_521_mont_dbl_17(ctx->z, ctx->z, p521_mod);
  55162. ctx->state = 4;
  55163. break;
  55164. case 4:
  55165. /* T2 = X - T1 */
  55166. sp_521_mont_sub_17(ctx->t2, p->x, ctx->t1, p521_mod);
  55167. ctx->state = 5;
  55168. break;
  55169. case 5:
  55170. /* T1 = X + T1 */
  55171. sp_521_mont_add_17(ctx->t1, p->x, ctx->t1, p521_mod);
  55172. ctx->state = 6;
  55173. break;
  55174. case 6:
  55175. /* T2 = T1 * T2 */
  55176. sp_521_mont_mul_17(ctx->t2, ctx->t1, ctx->t2, p521_mod, p521_mp_mod);
  55177. ctx->state = 7;
  55178. break;
  55179. case 7:
  55180. /* T1 = 3T2 */
  55181. sp_521_mont_tpl_17(ctx->t1, ctx->t2, p521_mod);
  55182. ctx->state = 8;
  55183. break;
  55184. case 8:
  55185. /* Y = 2Y */
  55186. sp_521_mont_dbl_17(ctx->y, p->y, p521_mod);
  55187. ctx->state = 9;
  55188. break;
  55189. case 9:
  55190. /* Y = Y * Y */
  55191. sp_521_mont_sqr_17(ctx->y, ctx->y, p521_mod, p521_mp_mod);
  55192. ctx->state = 10;
  55193. break;
  55194. case 10:
  55195. /* T2 = Y * Y */
  55196. sp_521_mont_sqr_17(ctx->t2, ctx->y, p521_mod, p521_mp_mod);
  55197. ctx->state = 11;
  55198. break;
  55199. case 11:
  55200. /* T2 = T2/2 */
  55201. sp_521_mont_div2_17(ctx->t2, ctx->t2, p521_mod);
  55202. ctx->state = 12;
  55203. break;
  55204. case 12:
  55205. /* Y = Y * X */
  55206. sp_521_mont_mul_17(ctx->y, ctx->y, p->x, p521_mod, p521_mp_mod);
  55207. ctx->state = 13;
  55208. break;
  55209. case 13:
  55210. /* X = T1 * T1 */
  55211. sp_521_mont_sqr_17(ctx->x, ctx->t1, p521_mod, p521_mp_mod);
  55212. ctx->state = 14;
  55213. break;
  55214. case 14:
  55215. /* X = X - Y */
  55216. sp_521_mont_sub_17(ctx->x, ctx->x, ctx->y, p521_mod);
  55217. ctx->state = 15;
  55218. break;
  55219. case 15:
  55220. /* X = X - Y */
  55221. sp_521_mont_sub_17(ctx->x, ctx->x, ctx->y, p521_mod);
  55222. ctx->state = 16;
  55223. break;
  55224. case 16:
  55225. /* Y = Y - X */
  55226. sp_521_mont_sub_17(ctx->y, ctx->y, ctx->x, p521_mod);
  55227. ctx->state = 17;
  55228. break;
  55229. case 17:
  55230. /* Y = Y * T1 */
  55231. sp_521_mont_mul_17(ctx->y, ctx->y, ctx->t1, p521_mod, p521_mp_mod);
  55232. ctx->state = 18;
  55233. break;
  55234. case 18:
  55235. /* Y = Y - T2 */
  55236. sp_521_mont_sub_17(ctx->y, ctx->y, ctx->t2, p521_mod);
  55237. ctx->state = 19;
  55238. /* fall-through */
  55239. case 19:
  55240. err = MP_OKAY;
  55241. break;
  55242. }
  55243. if (err == MP_OKAY && ctx->state != 19) {
  55244. err = FP_WOULDBLOCK;
  55245. }
  55246. return err;
  55247. }
  55248. #endif /* WOLFSSL_SP_NONBLOCK */
  55249. /* Compare two numbers to determine if they are equal.
  55250. * Constant time implementation.
  55251. *
  55252. * a First number to compare.
  55253. * b Second number to compare.
  55254. * returns 1 when equal and 0 otherwise.
  55255. */
  55256. static int sp_521_cmp_equal_17(const sp_digit* a, const sp_digit* b)
  55257. {
  55258. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  55259. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  55260. (a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
  55261. (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
  55262. (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) |
  55263. (a[15] ^ b[15]) | (a[16] ^ b[16])) == 0;
  55264. }
  55265. /* Returns 1 if the number of zero.
  55266. * Implementation is constant time.
  55267. *
  55268. * a Number to check.
  55269. * returns 1 if the number is zero and 0 otherwise.
  55270. */
  55271. static int sp_521_iszero_17(const sp_digit* a)
  55272. {
  55273. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
  55274. a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
  55275. a[16]) == 0;
  55276. }
  55277. /* Add two Montgomery form projective points.
  55278. *
  55279. * r Result of addition.
  55280. * p First point to add.
  55281. * q Second point to add.
  55282. * t Temporary ordinate data.
  55283. */
  55284. static void sp_521_proj_point_add_17(sp_point_521* r,
  55285. const sp_point_521* p, const sp_point_521* q, sp_digit* t)
  55286. {
  55287. sp_digit* t6 = t;
  55288. sp_digit* t1 = t + 2*17;
  55289. sp_digit* t2 = t + 4*17;
  55290. sp_digit* t3 = t + 6*17;
  55291. sp_digit* t4 = t + 8*17;
  55292. sp_digit* t5 = t + 10*17;
  55293. /* U1 = X1*Z2^2 */
  55294. sp_521_mont_sqr_17(t1, q->z, p521_mod, p521_mp_mod);
  55295. sp_521_mont_mul_17(t3, t1, q->z, p521_mod, p521_mp_mod);
  55296. sp_521_mont_mul_17(t1, t1, p->x, p521_mod, p521_mp_mod);
  55297. /* U2 = X2*Z1^2 */
  55298. sp_521_mont_sqr_17(t2, p->z, p521_mod, p521_mp_mod);
  55299. sp_521_mont_mul_17(t4, t2, p->z, p521_mod, p521_mp_mod);
  55300. sp_521_mont_mul_17(t2, t2, q->x, p521_mod, p521_mp_mod);
  55301. /* S1 = Y1*Z2^3 */
  55302. sp_521_mont_mul_17(t3, t3, p->y, p521_mod, p521_mp_mod);
  55303. /* S2 = Y2*Z1^3 */
  55304. sp_521_mont_mul_17(t4, t4, q->y, p521_mod, p521_mp_mod);
  55305. /* Check double */
  55306. if ((~p->infinity) & (~q->infinity) &
  55307. sp_521_cmp_equal_17(t2, t1) &
  55308. sp_521_cmp_equal_17(t4, t3)) {
  55309. sp_521_proj_point_dbl_17(r, p, t);
  55310. }
  55311. else {
  55312. sp_digit* x = t6;
  55313. sp_digit* y = t1;
  55314. sp_digit* z = t2;
  55315. /* H = U2 - U1 */
  55316. sp_521_mont_sub_17(t2, t2, t1, p521_mod);
  55317. /* R = S2 - S1 */
  55318. sp_521_mont_sub_17(t4, t4, t3, p521_mod);
  55319. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  55320. sp_521_mont_sqr_17(t5, t2, p521_mod, p521_mp_mod);
  55321. sp_521_mont_mul_17(y, t1, t5, p521_mod, p521_mp_mod);
  55322. sp_521_mont_mul_17(t5, t5, t2, p521_mod, p521_mp_mod);
  55323. /* Z3 = H*Z1*Z2 */
  55324. sp_521_mont_mul_17(z, p->z, t2, p521_mod, p521_mp_mod);
  55325. sp_521_mont_mul_17(z, z, q->z, p521_mod, p521_mp_mod);
  55326. sp_521_mont_sqr_17(x, t4, p521_mod, p521_mp_mod);
  55327. sp_521_mont_sub_17(x, x, t5, p521_mod);
  55328. sp_521_mont_mul_17(t5, t5, t3, p521_mod, p521_mp_mod);
  55329. sp_521_mont_dbl_17(t3, y, p521_mod);
  55330. sp_521_mont_sub_17(x, x, t3, p521_mod);
  55331. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  55332. sp_521_mont_sub_17(y, y, x, p521_mod);
  55333. sp_521_mont_mul_17(y, y, t4, p521_mod, p521_mp_mod);
  55334. sp_521_mont_sub_17(y, y, t5, p521_mod);
  55335. {
  55336. int i;
  55337. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  55338. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  55339. sp_digit maskt = ~(maskp | maskq);
  55340. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  55341. for (i = 0; i < 17; i++) {
  55342. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  55343. (x[i] & maskt);
  55344. }
  55345. for (i = 0; i < 17; i++) {
  55346. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  55347. (y[i] & maskt);
  55348. }
  55349. for (i = 0; i < 17; i++) {
  55350. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  55351. (z[i] & maskt);
  55352. }
  55353. r->z[0] |= inf;
  55354. r->infinity = (word32)inf;
  55355. }
  55356. }
  55357. }
  55358. #ifdef WOLFSSL_SP_NONBLOCK
  55359. typedef struct sp_521_proj_point_add_17_ctx {
  55360. int state;
  55361. sp_521_proj_point_dbl_17_ctx dbl_ctx;
  55362. const sp_point_521* ap[2];
  55363. sp_point_521* rp[2];
  55364. sp_digit* t1;
  55365. sp_digit* t2;
  55366. sp_digit* t3;
  55367. sp_digit* t4;
  55368. sp_digit* t5;
  55369. sp_digit* t6;
  55370. sp_digit* x;
  55371. sp_digit* y;
  55372. sp_digit* z;
  55373. } sp_521_proj_point_add_17_ctx;
  55374. /* Add two Montgomery form projective points.
  55375. *
  55376. * r Result of addition.
  55377. * p First point to add.
  55378. * q Second point to add.
  55379. * t Temporary ordinate data.
  55380. */
  55381. static int sp_521_proj_point_add_17_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r,
  55382. const sp_point_521* p, const sp_point_521* q, sp_digit* t)
  55383. {
  55384. int err = FP_WOULDBLOCK;
  55385. sp_521_proj_point_add_17_ctx* ctx = (sp_521_proj_point_add_17_ctx*)sp_ctx->data;
  55386. /* Ensure only the first point is the same as the result. */
  55387. if (q == r) {
  55388. const sp_point_521* a = p;
  55389. p = q;
  55390. q = a;
  55391. }
  55392. typedef char ctx_size_test[sizeof(sp_521_proj_point_add_17_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  55393. (void)sizeof(ctx_size_test);
  55394. switch (ctx->state) {
  55395. case 0: /* INIT */
  55396. ctx->t6 = t;
  55397. ctx->t1 = t + 2*17;
  55398. ctx->t2 = t + 4*17;
  55399. ctx->t3 = t + 6*17;
  55400. ctx->t4 = t + 8*17;
  55401. ctx->t5 = t + 10*17;
  55402. ctx->x = ctx->t6;
  55403. ctx->y = ctx->t1;
  55404. ctx->z = ctx->t2;
  55405. ctx->state = 1;
  55406. break;
  55407. case 1:
  55408. /* U1 = X1*Z2^2 */
  55409. sp_521_mont_sqr_17(ctx->t1, q->z, p521_mod, p521_mp_mod);
  55410. ctx->state = 2;
  55411. break;
  55412. case 2:
  55413. sp_521_mont_mul_17(ctx->t3, ctx->t1, q->z, p521_mod, p521_mp_mod);
  55414. ctx->state = 3;
  55415. break;
  55416. case 3:
  55417. sp_521_mont_mul_17(ctx->t1, ctx->t1, p->x, p521_mod, p521_mp_mod);
  55418. ctx->state = 4;
  55419. break;
  55420. case 4:
  55421. /* U2 = X2*Z1^2 */
  55422. sp_521_mont_sqr_17(ctx->t2, p->z, p521_mod, p521_mp_mod);
  55423. ctx->state = 5;
  55424. break;
  55425. case 5:
  55426. sp_521_mont_mul_17(ctx->t4, ctx->t2, p->z, p521_mod, p521_mp_mod);
  55427. ctx->state = 6;
  55428. break;
  55429. case 6:
  55430. sp_521_mont_mul_17(ctx->t2, ctx->t2, q->x, p521_mod, p521_mp_mod);
  55431. ctx->state = 7;
  55432. break;
  55433. case 7:
  55434. /* S1 = Y1*Z2^3 */
  55435. sp_521_mont_mul_17(ctx->t3, ctx->t3, p->y, p521_mod, p521_mp_mod);
  55436. ctx->state = 8;
  55437. break;
  55438. case 8:
  55439. /* S2 = Y2*Z1^3 */
  55440. sp_521_mont_mul_17(ctx->t4, ctx->t4, q->y, p521_mod, p521_mp_mod);
  55441. ctx->state = 9;
  55442. break;
  55443. case 9:
  55444. /* Check double */
  55445. if ((~p->infinity) & (~q->infinity) &
  55446. sp_521_cmp_equal_17(ctx->t2, ctx->t1) &
  55447. sp_521_cmp_equal_17(ctx->t4, ctx->t3)) {
  55448. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  55449. sp_521_proj_point_dbl_17(r, p, t);
  55450. ctx->state = 25;
  55451. }
  55452. else {
  55453. ctx->state = 10;
  55454. }
  55455. break;
  55456. case 10:
  55457. /* H = U2 - U1 */
  55458. sp_521_mont_sub_17(ctx->t2, ctx->t2, ctx->t1, p521_mod);
  55459. ctx->state = 11;
  55460. break;
  55461. case 11:
  55462. /* R = S2 - S1 */
  55463. sp_521_mont_sub_17(ctx->t4, ctx->t4, ctx->t3, p521_mod);
  55464. ctx->state = 12;
  55465. break;
  55466. case 12:
  55467. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  55468. sp_521_mont_sqr_17(ctx->t5, ctx->t2, p521_mod, p521_mp_mod);
  55469. ctx->state = 13;
  55470. break;
  55471. case 13:
  55472. sp_521_mont_mul_17(ctx->y, ctx->t1, ctx->t5, p521_mod, p521_mp_mod);
  55473. ctx->state = 14;
  55474. break;
  55475. case 14:
  55476. sp_521_mont_mul_17(ctx->t5, ctx->t5, ctx->t2, p521_mod, p521_mp_mod);
  55477. ctx->state = 15;
  55478. break;
  55479. case 15:
  55480. /* Z3 = H*Z1*Z2 */
  55481. sp_521_mont_mul_17(ctx->z, p->z, ctx->t2, p521_mod, p521_mp_mod);
  55482. ctx->state = 16;
  55483. break;
  55484. case 16:
  55485. sp_521_mont_mul_17(ctx->z, ctx->z, q->z, p521_mod, p521_mp_mod);
  55486. ctx->state = 17;
  55487. break;
  55488. case 17:
  55489. sp_521_mont_sqr_17(ctx->x, ctx->t4, p521_mod, p521_mp_mod);
  55490. ctx->state = 18;
  55491. break;
  55492. case 18:
  55493. sp_521_mont_sub_17(ctx->x, ctx->x, ctx->t5, p521_mod);
  55494. ctx->state = 19;
  55495. break;
  55496. case 19:
  55497. sp_521_mont_mul_17(ctx->t5, ctx->t5, ctx->t3, p521_mod, p521_mp_mod);
  55498. ctx->state = 20;
  55499. break;
  55500. case 20:
  55501. sp_521_mont_dbl_17(ctx->t3, ctx->y, p521_mod);
  55502. sp_521_mont_sub_17(ctx->x, ctx->x, ctx->t3, p521_mod);
  55503. ctx->state = 21;
  55504. break;
  55505. case 21:
  55506. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  55507. sp_521_mont_sub_17(ctx->y, ctx->y, ctx->x, p521_mod);
  55508. ctx->state = 22;
  55509. break;
  55510. case 22:
  55511. sp_521_mont_mul_17(ctx->y, ctx->y, ctx->t4, p521_mod, p521_mp_mod);
  55512. ctx->state = 23;
  55513. break;
  55514. case 23:
  55515. sp_521_mont_sub_17(ctx->y, ctx->y, ctx->t5, p521_mod);
  55516. ctx->state = 24;
  55517. break;
  55518. case 24:
  55519. {
  55520. {
  55521. int i;
  55522. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  55523. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  55524. sp_digit maskt = ~(maskp | maskq);
  55525. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  55526. for (i = 0; i < 17; i++) {
  55527. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  55528. (ctx->x[i] & maskt);
  55529. }
  55530. for (i = 0; i < 17; i++) {
  55531. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  55532. (ctx->y[i] & maskt);
  55533. }
  55534. for (i = 0; i < 17; i++) {
  55535. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  55536. (ctx->z[i] & maskt);
  55537. }
  55538. r->z[0] |= inf;
  55539. r->infinity = (word32)inf;
  55540. }
  55541. ctx->state = 25;
  55542. break;
  55543. }
  55544. case 25:
  55545. err = MP_OKAY;
  55546. break;
  55547. }
  55548. if (err == MP_OKAY && ctx->state != 25) {
  55549. err = FP_WOULDBLOCK;
  55550. }
  55551. return err;
  55552. }
  55553. #endif /* WOLFSSL_SP_NONBLOCK */
  55554. #ifndef WC_NO_CACHE_RESISTANT
  55555. /* Touch each possible point that could be being copied.
  55556. *
  55557. * r Point to copy into.
  55558. * table Table - start of the entries to access
  55559. * idx Index of entry to retrieve.
  55560. */
  55561. static void sp_521_get_point_16_17(sp_point_521* r, const sp_point_521* table,
  55562. int idx)
  55563. {
  55564. int i;
  55565. sp_digit mask;
  55566. r->x[0] = 0;
  55567. r->x[1] = 0;
  55568. r->x[2] = 0;
  55569. r->x[3] = 0;
  55570. r->x[4] = 0;
  55571. r->x[5] = 0;
  55572. r->x[6] = 0;
  55573. r->x[7] = 0;
  55574. r->x[8] = 0;
  55575. r->x[9] = 0;
  55576. r->x[10] = 0;
  55577. r->x[11] = 0;
  55578. r->x[12] = 0;
  55579. r->x[13] = 0;
  55580. r->x[14] = 0;
  55581. r->x[15] = 0;
  55582. r->x[16] = 0;
  55583. r->y[0] = 0;
  55584. r->y[1] = 0;
  55585. r->y[2] = 0;
  55586. r->y[3] = 0;
  55587. r->y[4] = 0;
  55588. r->y[5] = 0;
  55589. r->y[6] = 0;
  55590. r->y[7] = 0;
  55591. r->y[8] = 0;
  55592. r->y[9] = 0;
  55593. r->y[10] = 0;
  55594. r->y[11] = 0;
  55595. r->y[12] = 0;
  55596. r->y[13] = 0;
  55597. r->y[14] = 0;
  55598. r->y[15] = 0;
  55599. r->y[16] = 0;
  55600. r->z[0] = 0;
  55601. r->z[1] = 0;
  55602. r->z[2] = 0;
  55603. r->z[3] = 0;
  55604. r->z[4] = 0;
  55605. r->z[5] = 0;
  55606. r->z[6] = 0;
  55607. r->z[7] = 0;
  55608. r->z[8] = 0;
  55609. r->z[9] = 0;
  55610. r->z[10] = 0;
  55611. r->z[11] = 0;
  55612. r->z[12] = 0;
  55613. r->z[13] = 0;
  55614. r->z[14] = 0;
  55615. r->z[15] = 0;
  55616. r->z[16] = 0;
  55617. for (i = 1; i < 16; i++) {
  55618. mask = 0 - (i == idx);
  55619. r->x[0] |= mask & table[i].x[0];
  55620. r->x[1] |= mask & table[i].x[1];
  55621. r->x[2] |= mask & table[i].x[2];
  55622. r->x[3] |= mask & table[i].x[3];
  55623. r->x[4] |= mask & table[i].x[4];
  55624. r->x[5] |= mask & table[i].x[5];
  55625. r->x[6] |= mask & table[i].x[6];
  55626. r->x[7] |= mask & table[i].x[7];
  55627. r->x[8] |= mask & table[i].x[8];
  55628. r->x[9] |= mask & table[i].x[9];
  55629. r->x[10] |= mask & table[i].x[10];
  55630. r->x[11] |= mask & table[i].x[11];
  55631. r->x[12] |= mask & table[i].x[12];
  55632. r->x[13] |= mask & table[i].x[13];
  55633. r->x[14] |= mask & table[i].x[14];
  55634. r->x[15] |= mask & table[i].x[15];
  55635. r->x[16] |= mask & table[i].x[16];
  55636. r->y[0] |= mask & table[i].y[0];
  55637. r->y[1] |= mask & table[i].y[1];
  55638. r->y[2] |= mask & table[i].y[2];
  55639. r->y[3] |= mask & table[i].y[3];
  55640. r->y[4] |= mask & table[i].y[4];
  55641. r->y[5] |= mask & table[i].y[5];
  55642. r->y[6] |= mask & table[i].y[6];
  55643. r->y[7] |= mask & table[i].y[7];
  55644. r->y[8] |= mask & table[i].y[8];
  55645. r->y[9] |= mask & table[i].y[9];
  55646. r->y[10] |= mask & table[i].y[10];
  55647. r->y[11] |= mask & table[i].y[11];
  55648. r->y[12] |= mask & table[i].y[12];
  55649. r->y[13] |= mask & table[i].y[13];
  55650. r->y[14] |= mask & table[i].y[14];
  55651. r->y[15] |= mask & table[i].y[15];
  55652. r->y[16] |= mask & table[i].y[16];
  55653. r->z[0] |= mask & table[i].z[0];
  55654. r->z[1] |= mask & table[i].z[1];
  55655. r->z[2] |= mask & table[i].z[2];
  55656. r->z[3] |= mask & table[i].z[3];
  55657. r->z[4] |= mask & table[i].z[4];
  55658. r->z[5] |= mask & table[i].z[5];
  55659. r->z[6] |= mask & table[i].z[6];
  55660. r->z[7] |= mask & table[i].z[7];
  55661. r->z[8] |= mask & table[i].z[8];
  55662. r->z[9] |= mask & table[i].z[9];
  55663. r->z[10] |= mask & table[i].z[10];
  55664. r->z[11] |= mask & table[i].z[11];
  55665. r->z[12] |= mask & table[i].z[12];
  55666. r->z[13] |= mask & table[i].z[13];
  55667. r->z[14] |= mask & table[i].z[14];
  55668. r->z[15] |= mask & table[i].z[15];
  55669. r->z[16] |= mask & table[i].z[16];
  55670. }
  55671. }
  55672. #endif /* !WC_NO_CACHE_RESISTANT */
  55673. /* Multiply the point by the scalar and return the result.
  55674. * If map is true then convert result to affine coordinates.
  55675. *
  55676. * Fast implementation that generates a pre-computation table.
  55677. * 4 bits of window (no sliding!).
  55678. * Uses add and double for calculating table.
  55679. * 521 doubles.
  55680. * 143 adds.
  55681. *
  55682. * r Resulting point.
  55683. * g Point to multiply.
  55684. * k Scalar to multiply by.
  55685. * map Indicates whether to convert result to affine.
  55686. * ct Constant time required.
  55687. * heap Heap to use for allocation.
  55688. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  55689. */
  55690. static int sp_521_ecc_mulmod_fast_17(sp_point_521* r, const sp_point_521* g, const sp_digit* k,
  55691. int map, int ct, void* heap)
  55692. {
  55693. #ifdef WOLFSSL_SP_SMALL_STACK
  55694. sp_point_521* t = NULL;
  55695. sp_digit* tmp = NULL;
  55696. #else
  55697. sp_point_521 t[16 + 1];
  55698. sp_digit tmp[2 * 17 * 6];
  55699. #endif
  55700. sp_point_521* rt = NULL;
  55701. #ifndef WC_NO_CACHE_RESISTANT
  55702. #ifdef WOLFSSL_SP_SMALL_STACK
  55703. sp_point_521* p = NULL;
  55704. #else
  55705. sp_point_521 p[1];
  55706. #endif
  55707. #endif /* !WC_NO_CACHE_RESISTANT */
  55708. sp_digit n;
  55709. int i;
  55710. int c;
  55711. int y;
  55712. int err = MP_OKAY;
  55713. /* Constant time used for cache attack resistance implementation. */
  55714. (void)ct;
  55715. (void)heap;
  55716. #ifdef WOLFSSL_SP_SMALL_STACK
  55717. t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * (16 + 1),
  55718. heap, DYNAMIC_TYPE_ECC);
  55719. if (t == NULL)
  55720. err = MEMORY_E;
  55721. #ifndef WC_NO_CACHE_RESISTANT
  55722. if (err == MP_OKAY) {
  55723. p = (sp_point_521*)XMALLOC(sizeof(sp_point_521),
  55724. heap, DYNAMIC_TYPE_ECC);
  55725. if (p == NULL)
  55726. err = MEMORY_E;
  55727. }
  55728. #endif
  55729. if (err == MP_OKAY) {
  55730. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 6, heap,
  55731. DYNAMIC_TYPE_ECC);
  55732. if (tmp == NULL)
  55733. err = MEMORY_E;
  55734. }
  55735. #endif
  55736. if (err == MP_OKAY) {
  55737. rt = t + 16;
  55738. /* t[0] = {0, 0, 1} * norm */
  55739. XMEMSET(&t[0], 0, sizeof(t[0]));
  55740. t[0].infinity = 1;
  55741. /* t[1] = {g->x, g->y, g->z} * norm */
  55742. (void)sp_521_mod_mul_norm_17(t[1].x, g->x, p521_mod);
  55743. (void)sp_521_mod_mul_norm_17(t[1].y, g->y, p521_mod);
  55744. (void)sp_521_mod_mul_norm_17(t[1].z, g->z, p521_mod);
  55745. t[1].infinity = 0;
  55746. sp_521_proj_point_dbl_17(&t[ 2], &t[ 1], tmp);
  55747. t[ 2].infinity = 0;
  55748. sp_521_proj_point_add_17(&t[ 3], &t[ 2], &t[ 1], tmp);
  55749. t[ 3].infinity = 0;
  55750. sp_521_proj_point_dbl_17(&t[ 4], &t[ 2], tmp);
  55751. t[ 4].infinity = 0;
  55752. sp_521_proj_point_add_17(&t[ 5], &t[ 3], &t[ 2], tmp);
  55753. t[ 5].infinity = 0;
  55754. sp_521_proj_point_dbl_17(&t[ 6], &t[ 3], tmp);
  55755. t[ 6].infinity = 0;
  55756. sp_521_proj_point_add_17(&t[ 7], &t[ 4], &t[ 3], tmp);
  55757. t[ 7].infinity = 0;
  55758. sp_521_proj_point_dbl_17(&t[ 8], &t[ 4], tmp);
  55759. t[ 8].infinity = 0;
  55760. sp_521_proj_point_add_17(&t[ 9], &t[ 5], &t[ 4], tmp);
  55761. t[ 9].infinity = 0;
  55762. sp_521_proj_point_dbl_17(&t[10], &t[ 5], tmp);
  55763. t[10].infinity = 0;
  55764. sp_521_proj_point_add_17(&t[11], &t[ 6], &t[ 5], tmp);
  55765. t[11].infinity = 0;
  55766. sp_521_proj_point_dbl_17(&t[12], &t[ 6], tmp);
  55767. t[12].infinity = 0;
  55768. sp_521_proj_point_add_17(&t[13], &t[ 7], &t[ 6], tmp);
  55769. t[13].infinity = 0;
  55770. sp_521_proj_point_dbl_17(&t[14], &t[ 7], tmp);
  55771. t[14].infinity = 0;
  55772. sp_521_proj_point_add_17(&t[15], &t[ 8], &t[ 7], tmp);
  55773. t[15].infinity = 0;
  55774. i = 15;
  55775. n = k[i+1] << 0;
  55776. c = 5;
  55777. y = (int)(n >> 5);
  55778. #ifndef WC_NO_CACHE_RESISTANT
  55779. if (ct) {
  55780. sp_521_get_point_16_17(rt, t, y);
  55781. rt->infinity = !y;
  55782. }
  55783. else
  55784. #endif
  55785. {
  55786. XMEMCPY(rt, &t[y], sizeof(sp_point_521));
  55787. }
  55788. n <<= 27;
  55789. for (; i>=0 || c>=4; ) {
  55790. if (c < 4) {
  55791. n = (k[i+1] << 31) | (k[i] >> 1);
  55792. i--;
  55793. c += 32;
  55794. }
  55795. y = (n >> 28) & 0xf;
  55796. n <<= 4;
  55797. c -= 4;
  55798. sp_521_proj_point_dbl_17(rt, rt, tmp);
  55799. sp_521_proj_point_dbl_17(rt, rt, tmp);
  55800. sp_521_proj_point_dbl_17(rt, rt, tmp);
  55801. sp_521_proj_point_dbl_17(rt, rt, tmp);
  55802. #ifndef WC_NO_CACHE_RESISTANT
  55803. if (ct) {
  55804. sp_521_get_point_16_17(p, t, y);
  55805. p->infinity = !y;
  55806. sp_521_proj_point_add_17(rt, rt, p, tmp);
  55807. }
  55808. else
  55809. #endif
  55810. {
  55811. sp_521_proj_point_add_17(rt, rt, &t[y], tmp);
  55812. }
  55813. }
  55814. y = k[0] & 0x1;
  55815. sp_521_proj_point_dbl_17(rt, rt, tmp);
  55816. sp_521_proj_point_add_17(rt, rt, &t[y], tmp);
  55817. if (map != 0) {
  55818. sp_521_map_17(r, rt, tmp);
  55819. }
  55820. else {
  55821. XMEMCPY(r, rt, sizeof(sp_point_521));
  55822. }
  55823. }
  55824. #ifdef WOLFSSL_SP_SMALL_STACK
  55825. if (tmp != NULL)
  55826. #endif
  55827. {
  55828. ForceZero(tmp, sizeof(sp_digit) * 2 * 17 * 6);
  55829. #ifdef WOLFSSL_SP_SMALL_STACK
  55830. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  55831. #endif
  55832. }
  55833. #ifndef WC_NO_CACHE_RESISTANT
  55834. #ifdef WOLFSSL_SP_SMALL_STACK
  55835. if (p != NULL)
  55836. #endif
  55837. {
  55838. ForceZero(p, sizeof(sp_point_521));
  55839. #ifdef WOLFSSL_SP_SMALL_STACK
  55840. XFREE(p, heap, DYNAMIC_TYPE_ECC);
  55841. #endif
  55842. }
  55843. #endif /* !WC_NO_CACHE_RESISTANT */
  55844. #ifdef WOLFSSL_SP_SMALL_STACK
  55845. if (t != NULL)
  55846. #endif
  55847. {
  55848. ForceZero(t, sizeof(sp_point_521) * 17);
  55849. #ifdef WOLFSSL_SP_SMALL_STACK
  55850. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  55851. #endif
  55852. }
  55853. return err;
  55854. }
  55855. #ifdef FP_ECC
  55856. /* Double the Montgomery form projective point p a number of times.
  55857. *
  55858. * r Result of repeated doubling of point.
  55859. * p Point to double.
  55860. * n Number of times to double
  55861. * t Temporary ordinate data.
  55862. */
  55863. static void sp_521_proj_point_dbl_n_17(sp_point_521* p, int i,
  55864. sp_digit* t)
  55865. {
  55866. sp_digit* w = t;
  55867. sp_digit* a = t + 2*17;
  55868. sp_digit* b = t + 4*17;
  55869. sp_digit* t1 = t + 6*17;
  55870. sp_digit* t2 = t + 8*17;
  55871. sp_digit* x;
  55872. sp_digit* y;
  55873. sp_digit* z;
  55874. volatile int n = i;
  55875. x = p->x;
  55876. y = p->y;
  55877. z = p->z;
  55878. /* Y = 2*Y */
  55879. sp_521_mont_dbl_17(y, y, p521_mod);
  55880. /* W = Z^4 */
  55881. sp_521_mont_sqr_17(w, z, p521_mod, p521_mp_mod);
  55882. sp_521_mont_sqr_17(w, w, p521_mod, p521_mp_mod);
  55883. #ifndef WOLFSSL_SP_SMALL
  55884. while (--n > 0)
  55885. #else
  55886. while (--n >= 0)
  55887. #endif
  55888. {
  55889. /* A = 3*(X^2 - W) */
  55890. sp_521_mont_sqr_17(t1, x, p521_mod, p521_mp_mod);
  55891. sp_521_mont_sub_17(t1, t1, w, p521_mod);
  55892. sp_521_mont_tpl_17(a, t1, p521_mod);
  55893. /* B = X*Y^2 */
  55894. sp_521_mont_sqr_17(t1, y, p521_mod, p521_mp_mod);
  55895. sp_521_mont_mul_17(b, t1, x, p521_mod, p521_mp_mod);
  55896. /* X = A^2 - 2B */
  55897. sp_521_mont_sqr_17(x, a, p521_mod, p521_mp_mod);
  55898. sp_521_mont_dbl_17(t2, b, p521_mod);
  55899. sp_521_mont_sub_17(x, x, t2, p521_mod);
  55900. /* B = 2.(B - X) */
  55901. sp_521_mont_sub_17(t2, b, x, p521_mod);
  55902. sp_521_mont_dbl_17(b, t2, p521_mod);
  55903. /* Z = Z*Y */
  55904. sp_521_mont_mul_17(z, z, y, p521_mod, p521_mp_mod);
  55905. /* t1 = Y^4 */
  55906. sp_521_mont_sqr_17(t1, t1, p521_mod, p521_mp_mod);
  55907. #ifdef WOLFSSL_SP_SMALL
  55908. if (n != 0)
  55909. #endif
  55910. {
  55911. /* W = W*Y^4 */
  55912. sp_521_mont_mul_17(w, w, t1, p521_mod, p521_mp_mod);
  55913. }
  55914. /* y = 2*A*(B - X) - Y^4 */
  55915. sp_521_mont_mul_17(y, b, a, p521_mod, p521_mp_mod);
  55916. sp_521_mont_sub_17(y, y, t1, p521_mod);
  55917. }
  55918. #ifndef WOLFSSL_SP_SMALL
  55919. /* A = 3*(X^2 - W) */
  55920. sp_521_mont_sqr_17(t1, x, p521_mod, p521_mp_mod);
  55921. sp_521_mont_sub_17(t1, t1, w, p521_mod);
  55922. sp_521_mont_tpl_17(a, t1, p521_mod);
  55923. /* B = X*Y^2 */
  55924. sp_521_mont_sqr_17(t1, y, p521_mod, p521_mp_mod);
  55925. sp_521_mont_mul_17(b, t1, x, p521_mod, p521_mp_mod);
  55926. /* X = A^2 - 2B */
  55927. sp_521_mont_sqr_17(x, a, p521_mod, p521_mp_mod);
  55928. sp_521_mont_dbl_17(t2, b, p521_mod);
  55929. sp_521_mont_sub_17(x, x, t2, p521_mod);
  55930. /* B = 2.(B - X) */
  55931. sp_521_mont_sub_17(t2, b, x, p521_mod);
  55932. sp_521_mont_dbl_17(b, t2, p521_mod);
  55933. /* Z = Z*Y */
  55934. sp_521_mont_mul_17(z, z, y, p521_mod, p521_mp_mod);
  55935. /* t1 = Y^4 */
  55936. sp_521_mont_sqr_17(t1, t1, p521_mod, p521_mp_mod);
  55937. /* y = 2*A*(B - X) - Y^4 */
  55938. sp_521_mont_mul_17(y, b, a, p521_mod, p521_mp_mod);
  55939. sp_521_mont_sub_17(y, y, t1, p521_mod);
  55940. #endif /* WOLFSSL_SP_SMALL */
  55941. /* Y = Y/2 */
  55942. sp_521_mont_div2_17(y, y, p521_mod);
  55943. }
  55944. /* Convert the projective point to affine.
  55945. * Ordinates are in Montgomery form.
  55946. *
  55947. * a Point to convert.
  55948. * t Temporary data.
  55949. */
  55950. static void sp_521_proj_to_affine_17(sp_point_521* a, sp_digit* t)
  55951. {
  55952. sp_digit* t1 = t;
  55953. sp_digit* t2 = t + 2 * 17;
  55954. sp_digit* tmp = t + 4 * 17;
  55955. sp_521_mont_inv_17(t1, a->z, tmp);
  55956. sp_521_mont_sqr_17(t2, t1, p521_mod, p521_mp_mod);
  55957. sp_521_mont_mul_17(t1, t2, t1, p521_mod, p521_mp_mod);
  55958. sp_521_mont_mul_17(a->x, a->x, t2, p521_mod, p521_mp_mod);
  55959. sp_521_mont_mul_17(a->y, a->y, t1, p521_mod, p521_mp_mod);
  55960. XMEMCPY(a->z, p521_norm_mod, sizeof(p521_norm_mod));
  55961. }
  55962. #endif /* FP_ECC */
  55963. /* A table entry for pre-computed points. */
  55964. typedef struct sp_table_entry_521 {
  55965. sp_digit x[17];
  55966. sp_digit y[17];
  55967. } sp_table_entry_521;
  55968. #ifdef FP_ECC
  55969. #endif /* FP_ECC */
  55970. /* Add two Montgomery form projective points. The second point has a q value of
  55971. * one.
  55972. * Only the first point can be the same pointer as the result point.
  55973. *
  55974. * r Result of addition.
  55975. * p First point to add.
  55976. * q Second point to add.
  55977. * t Temporary ordinate data.
  55978. */
  55979. static void sp_521_proj_point_add_qz1_17(sp_point_521* r,
  55980. const sp_point_521* p, const sp_point_521* q, sp_digit* t)
  55981. {
  55982. sp_digit* t2 = t;
  55983. sp_digit* t3 = t + 2*17;
  55984. sp_digit* t6 = t + 4*17;
  55985. sp_digit* t1 = t + 6*17;
  55986. sp_digit* t4 = t + 8*17;
  55987. sp_digit* t5 = t + 10*17;
  55988. /* Calculate values to subtract from P->x and P->y. */
  55989. /* U2 = X2*Z1^2 */
  55990. sp_521_mont_sqr_17(t2, p->z, p521_mod, p521_mp_mod);
  55991. sp_521_mont_mul_17(t4, t2, p->z, p521_mod, p521_mp_mod);
  55992. sp_521_mont_mul_17(t2, t2, q->x, p521_mod, p521_mp_mod);
  55993. /* S2 = Y2*Z1^3 */
  55994. sp_521_mont_mul_17(t4, t4, q->y, p521_mod, p521_mp_mod);
  55995. if ((~p->infinity) & (~q->infinity) &
  55996. sp_521_cmp_equal_17(p->x, t2) &
  55997. sp_521_cmp_equal_17(p->y, t4)) {
  55998. sp_521_proj_point_dbl_17(r, p, t);
  55999. }
  56000. else {
  56001. sp_digit* x = t2;
  56002. sp_digit* y = t3;
  56003. sp_digit* z = t6;
  56004. /* H = U2 - X1 */
  56005. sp_521_mont_sub_17(t2, t2, p->x, p521_mod);
  56006. /* R = S2 - Y1 */
  56007. sp_521_mont_sub_17(t4, t4, p->y, p521_mod);
  56008. /* Z3 = H*Z1 */
  56009. sp_521_mont_mul_17(z, p->z, t2, p521_mod, p521_mp_mod);
  56010. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  56011. sp_521_mont_sqr_17(t1, t2, p521_mod, p521_mp_mod);
  56012. sp_521_mont_mul_17(t3, p->x, t1, p521_mod, p521_mp_mod);
  56013. sp_521_mont_mul_17(t1, t1, t2, p521_mod, p521_mp_mod);
  56014. sp_521_mont_sqr_17(t2, t4, p521_mod, p521_mp_mod);
  56015. sp_521_mont_sub_17(t2, t2, t1, p521_mod);
  56016. sp_521_mont_dbl_17(t5, t3, p521_mod);
  56017. sp_521_mont_sub_17(x, t2, t5, p521_mod);
  56018. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  56019. sp_521_mont_sub_17(t3, t3, x, p521_mod);
  56020. sp_521_mont_mul_17(t3, t3, t4, p521_mod, p521_mp_mod);
  56021. sp_521_mont_mul_17(t1, t1, p->y, p521_mod, p521_mp_mod);
  56022. sp_521_mont_sub_17(y, t3, t1, p521_mod);
  56023. {
  56024. int i;
  56025. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  56026. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  56027. sp_digit maskt = ~(maskp | maskq);
  56028. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  56029. for (i = 0; i < 17; i++) {
  56030. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  56031. (x[i] & maskt);
  56032. }
  56033. for (i = 0; i < 17; i++) {
  56034. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  56035. (y[i] & maskt);
  56036. }
  56037. for (i = 0; i < 17; i++) {
  56038. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  56039. (z[i] & maskt);
  56040. }
  56041. r->z[0] |= inf;
  56042. r->infinity = (word32)inf;
  56043. }
  56044. }
  56045. }
  56046. #ifdef WOLFSSL_SP_SMALL
  56047. #ifdef FP_ECC
  56048. /* Generate the pre-computed table of points for the base point.
  56049. *
  56050. * width = 4
  56051. * 16 entries
  56052. * 130 bits between
  56053. *
  56054. * a The base point.
  56055. * table Place to store generated point data.
  56056. * tmp Temporary data.
  56057. * heap Heap to use for allocation.
  56058. */
  56059. static int sp_521_gen_stripe_table_17(const sp_point_521* a,
  56060. sp_table_entry_521* table, sp_digit* tmp, void* heap)
  56061. {
  56062. #ifdef WOLFSSL_SP_SMALL_STACK
  56063. sp_point_521* t = NULL;
  56064. #else
  56065. sp_point_521 t[3];
  56066. #endif
  56067. sp_point_521* s1 = NULL;
  56068. sp_point_521* s2 = NULL;
  56069. int i;
  56070. int j;
  56071. int err = MP_OKAY;
  56072. (void)heap;
  56073. #ifdef WOLFSSL_SP_SMALL_STACK
  56074. t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap,
  56075. DYNAMIC_TYPE_ECC);
  56076. if (t == NULL)
  56077. err = MEMORY_E;
  56078. #endif
  56079. if (err == MP_OKAY) {
  56080. s1 = t + 1;
  56081. s2 = t + 2;
  56082. err = sp_521_mod_mul_norm_17(t->x, a->x, p521_mod);
  56083. }
  56084. if (err == MP_OKAY) {
  56085. err = sp_521_mod_mul_norm_17(t->y, a->y, p521_mod);
  56086. }
  56087. if (err == MP_OKAY) {
  56088. err = sp_521_mod_mul_norm_17(t->z, a->z, p521_mod);
  56089. }
  56090. if (err == MP_OKAY) {
  56091. t->infinity = 0;
  56092. sp_521_proj_to_affine_17(t, tmp);
  56093. XMEMCPY(s1->z, p521_norm_mod, sizeof(p521_norm_mod));
  56094. s1->infinity = 0;
  56095. XMEMCPY(s2->z, p521_norm_mod, sizeof(p521_norm_mod));
  56096. s2->infinity = 0;
  56097. /* table[0] = {0, 0, infinity} */
  56098. XMEMSET(&table[0], 0, sizeof(sp_table_entry_521));
  56099. /* table[1] = Affine version of 'a' in Montgomery form */
  56100. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  56101. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  56102. for (i=1; i<4; i++) {
  56103. sp_521_proj_point_dbl_n_17(t, 131, tmp);
  56104. sp_521_proj_to_affine_17(t, tmp);
  56105. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  56106. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  56107. }
  56108. for (i=1; i<4; i++) {
  56109. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  56110. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  56111. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  56112. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  56113. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  56114. sp_521_proj_point_add_qz1_17(t, s1, s2, tmp);
  56115. sp_521_proj_to_affine_17(t, tmp);
  56116. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  56117. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  56118. }
  56119. }
  56120. }
  56121. #ifdef WOLFSSL_SP_SMALL_STACK
  56122. if (t != NULL)
  56123. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  56124. #endif
  56125. return err;
  56126. }
  56127. #endif /* FP_ECC */
  56128. #ifndef WC_NO_CACHE_RESISTANT
  56129. /* Touch each possible entry that could be being copied.
  56130. *
  56131. * r Point to copy into.
  56132. * table Table - start of the entries to access
  56133. * idx Index of entry to retrieve.
  56134. */
  56135. static void sp_521_get_entry_16_17(sp_point_521* r,
  56136. const sp_table_entry_521* table, int idx)
  56137. {
  56138. int i;
  56139. sp_digit mask;
  56140. r->x[0] = 0;
  56141. r->x[1] = 0;
  56142. r->x[2] = 0;
  56143. r->x[3] = 0;
  56144. r->x[4] = 0;
  56145. r->x[5] = 0;
  56146. r->x[6] = 0;
  56147. r->x[7] = 0;
  56148. r->x[8] = 0;
  56149. r->x[9] = 0;
  56150. r->x[10] = 0;
  56151. r->x[11] = 0;
  56152. r->x[12] = 0;
  56153. r->x[13] = 0;
  56154. r->x[14] = 0;
  56155. r->x[15] = 0;
  56156. r->x[16] = 0;
  56157. r->y[0] = 0;
  56158. r->y[1] = 0;
  56159. r->y[2] = 0;
  56160. r->y[3] = 0;
  56161. r->y[4] = 0;
  56162. r->y[5] = 0;
  56163. r->y[6] = 0;
  56164. r->y[7] = 0;
  56165. r->y[8] = 0;
  56166. r->y[9] = 0;
  56167. r->y[10] = 0;
  56168. r->y[11] = 0;
  56169. r->y[12] = 0;
  56170. r->y[13] = 0;
  56171. r->y[14] = 0;
  56172. r->y[15] = 0;
  56173. r->y[16] = 0;
  56174. for (i = 1; i < 16; i++) {
  56175. mask = 0 - (i == idx);
  56176. r->x[0] |= mask & table[i].x[0];
  56177. r->x[1] |= mask & table[i].x[1];
  56178. r->x[2] |= mask & table[i].x[2];
  56179. r->x[3] |= mask & table[i].x[3];
  56180. r->x[4] |= mask & table[i].x[4];
  56181. r->x[5] |= mask & table[i].x[5];
  56182. r->x[6] |= mask & table[i].x[6];
  56183. r->x[7] |= mask & table[i].x[7];
  56184. r->x[8] |= mask & table[i].x[8];
  56185. r->x[9] |= mask & table[i].x[9];
  56186. r->x[10] |= mask & table[i].x[10];
  56187. r->x[11] |= mask & table[i].x[11];
  56188. r->x[12] |= mask & table[i].x[12];
  56189. r->x[13] |= mask & table[i].x[13];
  56190. r->x[14] |= mask & table[i].x[14];
  56191. r->x[15] |= mask & table[i].x[15];
  56192. r->x[16] |= mask & table[i].x[16];
  56193. r->y[0] |= mask & table[i].y[0];
  56194. r->y[1] |= mask & table[i].y[1];
  56195. r->y[2] |= mask & table[i].y[2];
  56196. r->y[3] |= mask & table[i].y[3];
  56197. r->y[4] |= mask & table[i].y[4];
  56198. r->y[5] |= mask & table[i].y[5];
  56199. r->y[6] |= mask & table[i].y[6];
  56200. r->y[7] |= mask & table[i].y[7];
  56201. r->y[8] |= mask & table[i].y[8];
  56202. r->y[9] |= mask & table[i].y[9];
  56203. r->y[10] |= mask & table[i].y[10];
  56204. r->y[11] |= mask & table[i].y[11];
  56205. r->y[12] |= mask & table[i].y[12];
  56206. r->y[13] |= mask & table[i].y[13];
  56207. r->y[14] |= mask & table[i].y[14];
  56208. r->y[15] |= mask & table[i].y[15];
  56209. r->y[16] |= mask & table[i].y[16];
  56210. }
  56211. }
  56212. #endif /* !WC_NO_CACHE_RESISTANT */
  56213. /* Multiply the point by the scalar and return the result.
  56214. * If map is true then convert result to affine coordinates.
  56215. *
  56216. * Stripe implementation.
  56217. * Pre-generated: 2^0, 2^130, ...
  56218. * Pre-generated: products of all combinations of above.
  56219. * 4 doubles and adds (with qz=1)
  56220. *
  56221. * r Resulting point.
  56222. * k Scalar to multiply by.
  56223. * table Pre-computed table.
  56224. * map Indicates whether to convert result to affine.
  56225. * ct Constant time required.
  56226. * heap Heap to use for allocation.
  56227. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  56228. */
  56229. static int sp_521_ecc_mulmod_stripe_17(sp_point_521* r, const sp_point_521* g,
  56230. const sp_table_entry_521* table, const sp_digit* k, int map,
  56231. int ct, void* heap)
  56232. {
  56233. #ifdef WOLFSSL_SP_SMALL_STACK
  56234. sp_point_521* rt = NULL;
  56235. sp_digit* t = NULL;
  56236. #else
  56237. sp_point_521 rt[2];
  56238. sp_digit t[2 * 17 * 6];
  56239. #endif
  56240. sp_point_521* p = NULL;
  56241. int i;
  56242. int j;
  56243. int y;
  56244. int x;
  56245. int err = MP_OKAY;
  56246. (void)g;
  56247. /* Constant time used for cache attack resistance implementation. */
  56248. (void)ct;
  56249. (void)heap;
  56250. #ifdef WOLFSSL_SP_SMALL_STACK
  56251. rt = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  56252. DYNAMIC_TYPE_ECC);
  56253. if (rt == NULL)
  56254. err = MEMORY_E;
  56255. if (err == MP_OKAY) {
  56256. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 6, heap,
  56257. DYNAMIC_TYPE_ECC);
  56258. if (t == NULL)
  56259. err = MEMORY_E;
  56260. }
  56261. #endif
  56262. if (err == MP_OKAY) {
  56263. p = rt + 1;
  56264. XMEMCPY(p->z, p521_norm_mod, sizeof(p521_norm_mod));
  56265. XMEMCPY(rt->z, p521_norm_mod, sizeof(p521_norm_mod));
  56266. y = 0;
  56267. x = 130;
  56268. for (j=0; j<4 && x<521; j++) {
  56269. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  56270. x += 131;
  56271. }
  56272. #ifndef WC_NO_CACHE_RESISTANT
  56273. if (ct) {
  56274. sp_521_get_entry_16_17(rt, table, y);
  56275. } else
  56276. #endif
  56277. {
  56278. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  56279. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  56280. }
  56281. rt->infinity = !y;
  56282. for (i=129; i>=0; i--) {
  56283. y = 0;
  56284. x = i;
  56285. for (j=0; j<4 && x<521; j++) {
  56286. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  56287. x += 131;
  56288. }
  56289. sp_521_proj_point_dbl_17(rt, rt, t);
  56290. #ifndef WC_NO_CACHE_RESISTANT
  56291. if (ct) {
  56292. sp_521_get_entry_16_17(p, table, y);
  56293. }
  56294. else
  56295. #endif
  56296. {
  56297. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  56298. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  56299. }
  56300. p->infinity = !y;
  56301. sp_521_proj_point_add_qz1_17(rt, rt, p, t);
  56302. }
  56303. if (map != 0) {
  56304. sp_521_map_17(r, rt, t);
  56305. }
  56306. else {
  56307. XMEMCPY(r, rt, sizeof(sp_point_521));
  56308. }
  56309. }
  56310. #ifdef WOLFSSL_SP_SMALL_STACK
  56311. if (t != NULL)
  56312. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  56313. if (rt != NULL)
  56314. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  56315. #endif
  56316. return err;
  56317. }
  56318. #ifdef FP_ECC
  56319. #ifndef FP_ENTRIES
  56320. #define FP_ENTRIES 16
  56321. #endif
  56322. /* Cache entry - holds precomputation tables for a point. */
  56323. typedef struct sp_cache_521_t {
  56324. /* X ordinate of point that table was generated from. */
  56325. sp_digit x[17];
  56326. /* Y ordinate of point that table was generated from. */
  56327. sp_digit y[17];
  56328. /* Precomputation table for point. */
  56329. sp_table_entry_521 table[16];
  56330. /* Count of entries in table. */
  56331. uint32_t cnt;
  56332. /* Point and table set in entry. */
  56333. int set;
  56334. } sp_cache_521_t;
  56335. /* Cache of tables. */
  56336. static THREAD_LS_T sp_cache_521_t sp_cache_521[FP_ENTRIES];
  56337. /* Index of last entry in cache. */
  56338. static THREAD_LS_T int sp_cache_521_last = -1;
  56339. /* Cache has been initialized. */
  56340. static THREAD_LS_T int sp_cache_521_inited = 0;
  56341. #ifndef HAVE_THREAD_LS
  56342. static volatile int initCacheMutex_521 = 0;
  56343. static wolfSSL_Mutex sp_cache_521_lock;
  56344. #endif
  56345. /* Get the cache entry for the point.
  56346. *
  56347. * g [in] Point scalar multiplying.
  56348. * cache [out] Cache table to use.
  56349. */
  56350. static void sp_ecc_get_cache_521(const sp_point_521* g, sp_cache_521_t** cache)
  56351. {
  56352. int i;
  56353. int j;
  56354. uint32_t least;
  56355. if (sp_cache_521_inited == 0) {
  56356. for (i=0; i<FP_ENTRIES; i++) {
  56357. sp_cache_521[i].set = 0;
  56358. }
  56359. sp_cache_521_inited = 1;
  56360. }
  56361. /* Compare point with those in cache. */
  56362. for (i=0; i<FP_ENTRIES; i++) {
  56363. if (!sp_cache_521[i].set)
  56364. continue;
  56365. if (sp_521_cmp_equal_17(g->x, sp_cache_521[i].x) &
  56366. sp_521_cmp_equal_17(g->y, sp_cache_521[i].y)) {
  56367. sp_cache_521[i].cnt++;
  56368. break;
  56369. }
  56370. }
  56371. /* No match. */
  56372. if (i == FP_ENTRIES) {
  56373. /* Find empty entry. */
  56374. i = (sp_cache_521_last + 1) % FP_ENTRIES;
  56375. for (; i != sp_cache_521_last; i=(i+1)%FP_ENTRIES) {
  56376. if (!sp_cache_521[i].set) {
  56377. break;
  56378. }
  56379. }
  56380. /* Evict least used. */
  56381. if (i == sp_cache_521_last) {
  56382. least = sp_cache_521[0].cnt;
  56383. for (j=1; j<FP_ENTRIES; j++) {
  56384. if (sp_cache_521[j].cnt < least) {
  56385. i = j;
  56386. least = sp_cache_521[i].cnt;
  56387. }
  56388. }
  56389. }
  56390. XMEMCPY(sp_cache_521[i].x, g->x, sizeof(sp_cache_521[i].x));
  56391. XMEMCPY(sp_cache_521[i].y, g->y, sizeof(sp_cache_521[i].y));
  56392. sp_cache_521[i].set = 1;
  56393. sp_cache_521[i].cnt = 1;
  56394. }
  56395. *cache = &sp_cache_521[i];
  56396. sp_cache_521_last = i;
  56397. }
  56398. #endif /* FP_ECC */
  56399. /* Multiply the base point of P521 by the scalar and return the result.
  56400. * If map is true then convert result to affine coordinates.
  56401. *
  56402. * r Resulting point.
  56403. * g Point to multiply.
  56404. * k Scalar to multiply by.
  56405. * map Indicates whether to convert result to affine.
  56406. * ct Constant time required.
  56407. * heap Heap to use for allocation.
  56408. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  56409. */
  56410. static int sp_521_ecc_mulmod_17(sp_point_521* r, const sp_point_521* g,
  56411. const sp_digit* k, int map, int ct, void* heap)
  56412. {
  56413. #ifndef FP_ECC
  56414. return sp_521_ecc_mulmod_fast_17(r, g, k, map, ct, heap);
  56415. #else
  56416. #ifdef WOLFSSL_SP_SMALL_STACK
  56417. sp_digit* tmp;
  56418. #else
  56419. sp_digit tmp[2 * 17 * 6];
  56420. #endif
  56421. sp_cache_521_t* cache;
  56422. int err = MP_OKAY;
  56423. #ifdef WOLFSSL_SP_SMALL_STACK
  56424. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 6, heap, DYNAMIC_TYPE_ECC);
  56425. if (tmp == NULL) {
  56426. err = MEMORY_E;
  56427. }
  56428. #endif
  56429. #ifndef HAVE_THREAD_LS
  56430. if (err == MP_OKAY) {
  56431. if (initCacheMutex_521 == 0) {
  56432. wc_InitMutex(&sp_cache_521_lock);
  56433. initCacheMutex_521 = 1;
  56434. }
  56435. if (wc_LockMutex(&sp_cache_521_lock) != 0) {
  56436. err = BAD_MUTEX_E;
  56437. }
  56438. }
  56439. #endif /* HAVE_THREAD_LS */
  56440. if (err == MP_OKAY) {
  56441. sp_ecc_get_cache_521(g, &cache);
  56442. if (cache->cnt == 2)
  56443. sp_521_gen_stripe_table_17(g, cache->table, tmp, heap);
  56444. #ifndef HAVE_THREAD_LS
  56445. wc_UnLockMutex(&sp_cache_521_lock);
  56446. #endif /* HAVE_THREAD_LS */
  56447. if (cache->cnt < 2) {
  56448. err = sp_521_ecc_mulmod_fast_17(r, g, k, map, ct, heap);
  56449. }
  56450. else {
  56451. err = sp_521_ecc_mulmod_stripe_17(r, g, cache->table, k,
  56452. map, ct, heap);
  56453. }
  56454. }
  56455. #ifdef WOLFSSL_SP_SMALL_STACK
  56456. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  56457. #endif
  56458. return err;
  56459. #endif
  56460. }
  56461. #else
  56462. #ifdef FP_ECC
  56463. /* Generate the pre-computed table of points for the base point.
  56464. *
  56465. * width = 8
  56466. * 256 entries
  56467. * 65 bits between
  56468. *
  56469. * a The base point.
  56470. * table Place to store generated point data.
  56471. * tmp Temporary data.
  56472. * heap Heap to use for allocation.
  56473. */
  56474. static int sp_521_gen_stripe_table_17(const sp_point_521* a,
  56475. sp_table_entry_521* table, sp_digit* tmp, void* heap)
  56476. {
  56477. #ifdef WOLFSSL_SP_SMALL_STACK
  56478. sp_point_521* t = NULL;
  56479. #else
  56480. sp_point_521 t[3];
  56481. #endif
  56482. sp_point_521* s1 = NULL;
  56483. sp_point_521* s2 = NULL;
  56484. int i;
  56485. int j;
  56486. int err = MP_OKAY;
  56487. (void)heap;
  56488. #ifdef WOLFSSL_SP_SMALL_STACK
  56489. t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap,
  56490. DYNAMIC_TYPE_ECC);
  56491. if (t == NULL)
  56492. err = MEMORY_E;
  56493. #endif
  56494. if (err == MP_OKAY) {
  56495. s1 = t + 1;
  56496. s2 = t + 2;
  56497. err = sp_521_mod_mul_norm_17(t->x, a->x, p521_mod);
  56498. }
  56499. if (err == MP_OKAY) {
  56500. err = sp_521_mod_mul_norm_17(t->y, a->y, p521_mod);
  56501. }
  56502. if (err == MP_OKAY) {
  56503. err = sp_521_mod_mul_norm_17(t->z, a->z, p521_mod);
  56504. }
  56505. if (err == MP_OKAY) {
  56506. t->infinity = 0;
  56507. sp_521_proj_to_affine_17(t, tmp);
  56508. XMEMCPY(s1->z, p521_norm_mod, sizeof(p521_norm_mod));
  56509. s1->infinity = 0;
  56510. XMEMCPY(s2->z, p521_norm_mod, sizeof(p521_norm_mod));
  56511. s2->infinity = 0;
  56512. /* table[0] = {0, 0, infinity} */
  56513. XMEMSET(&table[0], 0, sizeof(sp_table_entry_521));
  56514. /* table[1] = Affine version of 'a' in Montgomery form */
  56515. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  56516. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  56517. for (i=1; i<8; i++) {
  56518. sp_521_proj_point_dbl_n_17(t, 66, tmp);
  56519. sp_521_proj_to_affine_17(t, tmp);
  56520. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  56521. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  56522. }
  56523. for (i=1; i<8; i++) {
  56524. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  56525. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  56526. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  56527. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  56528. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  56529. sp_521_proj_point_add_qz1_17(t, s1, s2, tmp);
  56530. sp_521_proj_to_affine_17(t, tmp);
  56531. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  56532. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  56533. }
  56534. }
  56535. }
  56536. #ifdef WOLFSSL_SP_SMALL_STACK
  56537. if (t != NULL)
  56538. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  56539. #endif
  56540. return err;
  56541. }
  56542. #endif /* FP_ECC */
  56543. #ifndef WC_NO_CACHE_RESISTANT
  56544. /* Touch each possible entry that could be being copied.
  56545. *
  56546. * r Point to copy into.
  56547. * table Table - start of the entries to access
  56548. * idx Index of entry to retrieve.
  56549. */
  56550. static void sp_521_get_entry_256_17(sp_point_521* r,
  56551. const sp_table_entry_521* table, int idx)
  56552. {
  56553. int i;
  56554. sp_digit mask;
  56555. r->x[0] = 0;
  56556. r->x[1] = 0;
  56557. r->x[2] = 0;
  56558. r->x[3] = 0;
  56559. r->x[4] = 0;
  56560. r->x[5] = 0;
  56561. r->x[6] = 0;
  56562. r->x[7] = 0;
  56563. r->x[8] = 0;
  56564. r->x[9] = 0;
  56565. r->x[10] = 0;
  56566. r->x[11] = 0;
  56567. r->x[12] = 0;
  56568. r->x[13] = 0;
  56569. r->x[14] = 0;
  56570. r->x[15] = 0;
  56571. r->x[16] = 0;
  56572. r->y[0] = 0;
  56573. r->y[1] = 0;
  56574. r->y[2] = 0;
  56575. r->y[3] = 0;
  56576. r->y[4] = 0;
  56577. r->y[5] = 0;
  56578. r->y[6] = 0;
  56579. r->y[7] = 0;
  56580. r->y[8] = 0;
  56581. r->y[9] = 0;
  56582. r->y[10] = 0;
  56583. r->y[11] = 0;
  56584. r->y[12] = 0;
  56585. r->y[13] = 0;
  56586. r->y[14] = 0;
  56587. r->y[15] = 0;
  56588. r->y[16] = 0;
  56589. for (i = 1; i < 256; i++) {
  56590. mask = 0 - (i == idx);
  56591. r->x[0] |= mask & table[i].x[0];
  56592. r->x[1] |= mask & table[i].x[1];
  56593. r->x[2] |= mask & table[i].x[2];
  56594. r->x[3] |= mask & table[i].x[3];
  56595. r->x[4] |= mask & table[i].x[4];
  56596. r->x[5] |= mask & table[i].x[5];
  56597. r->x[6] |= mask & table[i].x[6];
  56598. r->x[7] |= mask & table[i].x[7];
  56599. r->x[8] |= mask & table[i].x[8];
  56600. r->x[9] |= mask & table[i].x[9];
  56601. r->x[10] |= mask & table[i].x[10];
  56602. r->x[11] |= mask & table[i].x[11];
  56603. r->x[12] |= mask & table[i].x[12];
  56604. r->x[13] |= mask & table[i].x[13];
  56605. r->x[14] |= mask & table[i].x[14];
  56606. r->x[15] |= mask & table[i].x[15];
  56607. r->x[16] |= mask & table[i].x[16];
  56608. r->y[0] |= mask & table[i].y[0];
  56609. r->y[1] |= mask & table[i].y[1];
  56610. r->y[2] |= mask & table[i].y[2];
  56611. r->y[3] |= mask & table[i].y[3];
  56612. r->y[4] |= mask & table[i].y[4];
  56613. r->y[5] |= mask & table[i].y[5];
  56614. r->y[6] |= mask & table[i].y[6];
  56615. r->y[7] |= mask & table[i].y[7];
  56616. r->y[8] |= mask & table[i].y[8];
  56617. r->y[9] |= mask & table[i].y[9];
  56618. r->y[10] |= mask & table[i].y[10];
  56619. r->y[11] |= mask & table[i].y[11];
  56620. r->y[12] |= mask & table[i].y[12];
  56621. r->y[13] |= mask & table[i].y[13];
  56622. r->y[14] |= mask & table[i].y[14];
  56623. r->y[15] |= mask & table[i].y[15];
  56624. r->y[16] |= mask & table[i].y[16];
  56625. }
  56626. }
  56627. #endif /* !WC_NO_CACHE_RESISTANT */
  56628. /* Multiply the point by the scalar and return the result.
  56629. * If map is true then convert result to affine coordinates.
  56630. *
  56631. * Stripe implementation.
  56632. * Pre-generated: 2^0, 2^65, ...
  56633. * Pre-generated: products of all combinations of above.
  56634. * 8 doubles and adds (with qz=1)
  56635. *
  56636. * r Resulting point.
  56637. * k Scalar to multiply by.
  56638. * table Pre-computed table.
  56639. * map Indicates whether to convert result to affine.
  56640. * ct Constant time required.
  56641. * heap Heap to use for allocation.
  56642. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  56643. */
  56644. static int sp_521_ecc_mulmod_stripe_17(sp_point_521* r, const sp_point_521* g,
  56645. const sp_table_entry_521* table, const sp_digit* k, int map,
  56646. int ct, void* heap)
  56647. {
  56648. #ifdef WOLFSSL_SP_SMALL_STACK
  56649. sp_point_521* rt = NULL;
  56650. sp_digit* t = NULL;
  56651. #else
  56652. sp_point_521 rt[2];
  56653. sp_digit t[2 * 17 * 6];
  56654. #endif
  56655. sp_point_521* p = NULL;
  56656. int i;
  56657. int j;
  56658. int y;
  56659. int x;
  56660. int err = MP_OKAY;
  56661. (void)g;
  56662. /* Constant time used for cache attack resistance implementation. */
  56663. (void)ct;
  56664. (void)heap;
  56665. #ifdef WOLFSSL_SP_SMALL_STACK
  56666. rt = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  56667. DYNAMIC_TYPE_ECC);
  56668. if (rt == NULL)
  56669. err = MEMORY_E;
  56670. if (err == MP_OKAY) {
  56671. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 6, heap,
  56672. DYNAMIC_TYPE_ECC);
  56673. if (t == NULL)
  56674. err = MEMORY_E;
  56675. }
  56676. #endif
  56677. if (err == MP_OKAY) {
  56678. p = rt + 1;
  56679. XMEMCPY(p->z, p521_norm_mod, sizeof(p521_norm_mod));
  56680. XMEMCPY(rt->z, p521_norm_mod, sizeof(p521_norm_mod));
  56681. y = 0;
  56682. x = 65;
  56683. for (j=0; j<8 && x<521; j++) {
  56684. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  56685. x += 66;
  56686. }
  56687. #ifndef WC_NO_CACHE_RESISTANT
  56688. if (ct) {
  56689. sp_521_get_entry_256_17(rt, table, y);
  56690. } else
  56691. #endif
  56692. {
  56693. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  56694. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  56695. }
  56696. rt->infinity = !y;
  56697. for (i=64; i>=0; i--) {
  56698. y = 0;
  56699. x = i;
  56700. for (j=0; j<8 && x<521; j++) {
  56701. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  56702. x += 66;
  56703. }
  56704. sp_521_proj_point_dbl_17(rt, rt, t);
  56705. #ifndef WC_NO_CACHE_RESISTANT
  56706. if (ct) {
  56707. sp_521_get_entry_256_17(p, table, y);
  56708. }
  56709. else
  56710. #endif
  56711. {
  56712. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  56713. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  56714. }
  56715. p->infinity = !y;
  56716. sp_521_proj_point_add_qz1_17(rt, rt, p, t);
  56717. }
  56718. if (map != 0) {
  56719. sp_521_map_17(r, rt, t);
  56720. }
  56721. else {
  56722. XMEMCPY(r, rt, sizeof(sp_point_521));
  56723. }
  56724. }
  56725. #ifdef WOLFSSL_SP_SMALL_STACK
  56726. if (t != NULL)
  56727. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  56728. if (rt != NULL)
  56729. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  56730. #endif
  56731. return err;
  56732. }
  56733. #ifdef FP_ECC
  56734. #ifndef FP_ENTRIES
  56735. #define FP_ENTRIES 16
  56736. #endif
  56737. /* Cache entry - holds precomputation tables for a point. */
  56738. typedef struct sp_cache_521_t {
  56739. /* X ordinate of point that table was generated from. */
  56740. sp_digit x[17];
  56741. /* Y ordinate of point that table was generated from. */
  56742. sp_digit y[17];
  56743. /* Precomputation table for point. */
  56744. sp_table_entry_521 table[256];
  56745. /* Count of entries in table. */
  56746. uint32_t cnt;
  56747. /* Point and table set in entry. */
  56748. int set;
  56749. } sp_cache_521_t;
  56750. /* Cache of tables. */
  56751. static THREAD_LS_T sp_cache_521_t sp_cache_521[FP_ENTRIES];
  56752. /* Index of last entry in cache. */
  56753. static THREAD_LS_T int sp_cache_521_last = -1;
  56754. /* Cache has been initialized. */
  56755. static THREAD_LS_T int sp_cache_521_inited = 0;
  56756. #ifndef HAVE_THREAD_LS
  56757. static volatile int initCacheMutex_521 = 0;
  56758. static wolfSSL_Mutex sp_cache_521_lock;
  56759. #endif
  56760. /* Get the cache entry for the point.
  56761. *
  56762. * g [in] Point scalar multiplying.
  56763. * cache [out] Cache table to use.
  56764. */
  56765. static void sp_ecc_get_cache_521(const sp_point_521* g, sp_cache_521_t** cache)
  56766. {
  56767. int i;
  56768. int j;
  56769. uint32_t least;
  56770. if (sp_cache_521_inited == 0) {
  56771. for (i=0; i<FP_ENTRIES; i++) {
  56772. sp_cache_521[i].set = 0;
  56773. }
  56774. sp_cache_521_inited = 1;
  56775. }
  56776. /* Compare point with those in cache. */
  56777. for (i=0; i<FP_ENTRIES; i++) {
  56778. if (!sp_cache_521[i].set)
  56779. continue;
  56780. if (sp_521_cmp_equal_17(g->x, sp_cache_521[i].x) &
  56781. sp_521_cmp_equal_17(g->y, sp_cache_521[i].y)) {
  56782. sp_cache_521[i].cnt++;
  56783. break;
  56784. }
  56785. }
  56786. /* No match. */
  56787. if (i == FP_ENTRIES) {
  56788. /* Find empty entry. */
  56789. i = (sp_cache_521_last + 1) % FP_ENTRIES;
  56790. for (; i != sp_cache_521_last; i=(i+1)%FP_ENTRIES) {
  56791. if (!sp_cache_521[i].set) {
  56792. break;
  56793. }
  56794. }
  56795. /* Evict least used. */
  56796. if (i == sp_cache_521_last) {
  56797. least = sp_cache_521[0].cnt;
  56798. for (j=1; j<FP_ENTRIES; j++) {
  56799. if (sp_cache_521[j].cnt < least) {
  56800. i = j;
  56801. least = sp_cache_521[i].cnt;
  56802. }
  56803. }
  56804. }
  56805. XMEMCPY(sp_cache_521[i].x, g->x, sizeof(sp_cache_521[i].x));
  56806. XMEMCPY(sp_cache_521[i].y, g->y, sizeof(sp_cache_521[i].y));
  56807. sp_cache_521[i].set = 1;
  56808. sp_cache_521[i].cnt = 1;
  56809. }
  56810. *cache = &sp_cache_521[i];
  56811. sp_cache_521_last = i;
  56812. }
  56813. #endif /* FP_ECC */
  56814. /* Multiply the base point of P521 by the scalar and return the result.
  56815. * If map is true then convert result to affine coordinates.
  56816. *
  56817. * r Resulting point.
  56818. * g Point to multiply.
  56819. * k Scalar to multiply by.
  56820. * map Indicates whether to convert result to affine.
  56821. * ct Constant time required.
  56822. * heap Heap to use for allocation.
  56823. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  56824. */
  56825. static int sp_521_ecc_mulmod_17(sp_point_521* r, const sp_point_521* g,
  56826. const sp_digit* k, int map, int ct, void* heap)
  56827. {
  56828. #ifndef FP_ECC
  56829. return sp_521_ecc_mulmod_fast_17(r, g, k, map, ct, heap);
  56830. #else
  56831. #ifdef WOLFSSL_SP_SMALL_STACK
  56832. sp_digit* tmp;
  56833. #else
  56834. sp_digit tmp[2 * 17 * 6];
  56835. #endif
  56836. sp_cache_521_t* cache;
  56837. int err = MP_OKAY;
  56838. #ifdef WOLFSSL_SP_SMALL_STACK
  56839. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 6, heap, DYNAMIC_TYPE_ECC);
  56840. if (tmp == NULL) {
  56841. err = MEMORY_E;
  56842. }
  56843. #endif
  56844. #ifndef HAVE_THREAD_LS
  56845. if (err == MP_OKAY) {
  56846. if (initCacheMutex_521 == 0) {
  56847. wc_InitMutex(&sp_cache_521_lock);
  56848. initCacheMutex_521 = 1;
  56849. }
  56850. if (wc_LockMutex(&sp_cache_521_lock) != 0) {
  56851. err = BAD_MUTEX_E;
  56852. }
  56853. }
  56854. #endif /* HAVE_THREAD_LS */
  56855. if (err == MP_OKAY) {
  56856. sp_ecc_get_cache_521(g, &cache);
  56857. if (cache->cnt == 2)
  56858. sp_521_gen_stripe_table_17(g, cache->table, tmp, heap);
  56859. #ifndef HAVE_THREAD_LS
  56860. wc_UnLockMutex(&sp_cache_521_lock);
  56861. #endif /* HAVE_THREAD_LS */
  56862. if (cache->cnt < 2) {
  56863. err = sp_521_ecc_mulmod_fast_17(r, g, k, map, ct, heap);
  56864. }
  56865. else {
  56866. err = sp_521_ecc_mulmod_stripe_17(r, g, cache->table, k,
  56867. map, ct, heap);
  56868. }
  56869. }
  56870. #ifdef WOLFSSL_SP_SMALL_STACK
  56871. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  56872. #endif
  56873. return err;
  56874. #endif
  56875. }
  56876. #endif /* WOLFSSL_SP_SMALL */
  56877. /* Multiply the point by the scalar and return the result.
  56878. * If map is true then convert result to affine coordinates.
  56879. *
  56880. * km Scalar to multiply by.
  56881. * p Point to multiply.
  56882. * r Resulting point.
  56883. * map Indicates whether to convert result to affine.
  56884. * heap Heap to use for allocation.
  56885. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  56886. */
  56887. int sp_ecc_mulmod_521(const mp_int* km, const ecc_point* gm, ecc_point* r,
  56888. int map, void* heap)
  56889. {
  56890. #ifdef WOLFSSL_SP_SMALL_STACK
  56891. sp_point_521* point = NULL;
  56892. sp_digit* k = NULL;
  56893. #else
  56894. sp_point_521 point[1];
  56895. sp_digit k[17];
  56896. #endif
  56897. int err = MP_OKAY;
  56898. #ifdef WOLFSSL_SP_SMALL_STACK
  56899. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  56900. DYNAMIC_TYPE_ECC);
  56901. if (point == NULL)
  56902. err = MEMORY_E;
  56903. if (err == MP_OKAY) {
  56904. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 17, heap,
  56905. DYNAMIC_TYPE_ECC);
  56906. if (k == NULL)
  56907. err = MEMORY_E;
  56908. }
  56909. #endif
  56910. if (err == MP_OKAY) {
  56911. sp_521_from_mp(k, 17, km);
  56912. sp_521_point_from_ecc_point_17(point, gm);
  56913. err = sp_521_ecc_mulmod_17(point, point, k, map, 1, heap);
  56914. }
  56915. if (err == MP_OKAY) {
  56916. err = sp_521_point_to_ecc_point_17(point, r);
  56917. }
  56918. #ifdef WOLFSSL_SP_SMALL_STACK
  56919. if (k != NULL)
  56920. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  56921. if (point != NULL)
  56922. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  56923. #endif
  56924. return err;
  56925. }
  56926. /* Multiply the point by the scalar, add point a and return the result.
  56927. * If map is true then convert result to affine coordinates.
  56928. *
  56929. * km Scalar to multiply by.
  56930. * p Point to multiply.
  56931. * am Point to add to scalar multiply result.
  56932. * inMont Point to add is in montgomery form.
  56933. * r Resulting point.
  56934. * map Indicates whether to convert result to affine.
  56935. * heap Heap to use for allocation.
  56936. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  56937. */
  56938. int sp_ecc_mulmod_add_521(const mp_int* km, const ecc_point* gm,
  56939. const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
  56940. {
  56941. #ifdef WOLFSSL_SP_SMALL_STACK
  56942. sp_point_521* point = NULL;
  56943. sp_digit* k = NULL;
  56944. #else
  56945. sp_point_521 point[2];
  56946. sp_digit k[17 + 17 * 2 * 6];
  56947. #endif
  56948. sp_point_521* addP = NULL;
  56949. sp_digit* tmp = NULL;
  56950. int err = MP_OKAY;
  56951. #ifdef WOLFSSL_SP_SMALL_STACK
  56952. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  56953. DYNAMIC_TYPE_ECC);
  56954. if (point == NULL)
  56955. err = MEMORY_E;
  56956. if (err == MP_OKAY) {
  56957. k = (sp_digit*)XMALLOC(
  56958. sizeof(sp_digit) * (17 + 17 * 2 * 6), heap,
  56959. DYNAMIC_TYPE_ECC);
  56960. if (k == NULL)
  56961. err = MEMORY_E;
  56962. }
  56963. #endif
  56964. if (err == MP_OKAY) {
  56965. addP = point + 1;
  56966. tmp = k + 17;
  56967. sp_521_from_mp(k, 17, km);
  56968. sp_521_point_from_ecc_point_17(point, gm);
  56969. sp_521_point_from_ecc_point_17(addP, am);
  56970. }
  56971. if ((err == MP_OKAY) && (!inMont)) {
  56972. err = sp_521_mod_mul_norm_17(addP->x, addP->x, p521_mod);
  56973. }
  56974. if ((err == MP_OKAY) && (!inMont)) {
  56975. err = sp_521_mod_mul_norm_17(addP->y, addP->y, p521_mod);
  56976. }
  56977. if ((err == MP_OKAY) && (!inMont)) {
  56978. err = sp_521_mod_mul_norm_17(addP->z, addP->z, p521_mod);
  56979. }
  56980. if (err == MP_OKAY) {
  56981. err = sp_521_ecc_mulmod_17(point, point, k, 0, 0, heap);
  56982. }
  56983. if (err == MP_OKAY) {
  56984. sp_521_proj_point_add_17(point, point, addP, tmp);
  56985. if (map) {
  56986. sp_521_map_17(point, point, tmp);
  56987. }
  56988. err = sp_521_point_to_ecc_point_17(point, r);
  56989. }
  56990. #ifdef WOLFSSL_SP_SMALL_STACK
  56991. if (k != NULL)
  56992. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  56993. if (point != NULL)
  56994. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  56995. #endif
  56996. return err;
  56997. }
  56998. #ifdef WOLFSSL_SP_SMALL
  56999. /* Striping precomputation table.
  57000. * 4 points combined into a table of 16 points.
  57001. * Distance of 131 between points.
  57002. */
  57003. static const sp_table_entry_521 p521_table[16] = {
  57004. /* 0 */
  57005. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57006. 0x00, 0x00, 0x00, 0x00, 0x00 },
  57007. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57008. 0x00, 0x00, 0x00, 0x00, 0x00 } },
  57009. /* 1 */
  57010. { { 0xc2e5bd66,0xf97e7e31,0x856a429b,0x3348b3c1,0xa2ffa8de,0xfe1dc127,
  57011. 0xefe75928,0xa14b5e77,0x6b4d3dba,0xf828af60,0x053fb521,0x9c648139,
  57012. 0x2395b442,0x9e3ecb66,0x0404e9cd,0x858e06b7,0x000000c6 },
  57013. { 0x9fd16650,0x88be9476,0xa272c240,0x353c7086,0x3fad0761,0xc550b901,
  57014. 0x5ef42640,0x97ee7299,0x273e662c,0x17afbd17,0x579b4468,0x98f54449,
  57015. 0x2c7d1bd9,0x5c8a5fb4,0x9a3bc004,0x39296a78,0x00000118 } },
  57016. /* 2 */
  57017. { { 0x66fd07ca,0x1036eb9b,0x6b7fb490,0x6ca52cc1,0xd3e0c270,0x512e973e,
  57018. 0x73d92d11,0x889980bf,0xa4005eea,0x38b4cfe4,0x8ceb4313,0xb6f992cc,
  57019. 0x6daf7c23,0xd0ac2f8d,0xe32a93cb,0x1ccfbf17,0x000000c2 },
  57020. { 0x2f508cca,0x7bd9d6f1,0x595a72af,0xe82d7171,0x97512873,0x25d02976,
  57021. 0x8cf39fbc,0xefc1de8b,0x9a1237f4,0x25e6b77f,0xd4d98b5d,0x9f3b73e7,
  57022. 0xeccb07fe,0xe1fda62b,0x625350cf,0xdb813b03,0x00000014 } },
  57023. /* 3 */
  57024. { { 0x9b27bd61,0x415a1c9b,0x606854d6,0x74522753,0x92e73538,0x9e331ef4,
  57025. 0x817e7a6d,0x0b3dba85,0x49ac273b,0x55c4bd53,0xfcb5417f,0xad42c78d,
  57026. 0x92e08d38,0x528998b9,0xcc1914cc,0x14c2fff6,0x000000c1 },
  57027. { 0x767e9645,0x35b26fb0,0xc5e5a659,0x162b512f,0xcc47fbb8,0xa6e03696,
  57028. 0x0a29a69b,0x732db065,0xd56bdf5d,0x058a74ed,0x25c858d9,0x4b7b60a0,
  57029. 0xbd43373d,0x17f8a6d4,0xedf610b4,0x7b968f51,0x0000011f } },
  57030. /* 4 */
  57031. { { 0x1bc0fa77,0x5f56b5a4,0x64fd36f5,0x6cdd6bb5,0x8a5b7c7f,0xd0ac68b5,
  57032. 0x09919ef9,0x4a92d9bf,0x71c3c520,0xc305e12b,0xdb699aee,0x554a9d1c,
  57033. 0x61f54643,0x7fde0077,0x479115ce,0x99c13124,0x00000039 },
  57034. { 0xc271ac2d,0x25f890e1,0x94b370ac,0x1353ccd3,0x744d4011,0xc7b5adf6,
  57035. 0xbe378127,0x9ccd7687,0x06c4e3cd,0xa8489b5c,0x305505f9,0x1945580a,
  57036. 0x4ab3b12b,0x07190a20,0x1534ea4d,0x0ff53eb1,0x00000159 } },
  57037. /* 5 */
  57038. { { 0x91798548,0x877d4edd,0x031d657a,0xc43c7b25,0xfab18a04,0x47603671,
  57039. 0xf670b476,0x7e39e7f2,0xb02fcc03,0xf7b76431,0x877f46f5,0x7c5662f3,
  57040. 0x1c8b0c61,0x5bf8327e,0x4a8be322,0xe9cdb353,0x000001ae },
  57041. { 0x9d264420,0xa2d7092e,0x533ff3db,0x1f970352,0x99b5b52e,0x31dd232b,
  57042. 0x850f45e9,0x8a9ce16b,0xc3011849,0x01c99023,0xc8e9301e,0x4bc30989,
  57043. 0xcd95f64c,0x77a4de70,0x1026f289,0xbc8797bb,0x000000d7 } },
  57044. /* 6 */
  57045. { { 0x2be9edf8,0x98ea0934,0xfcb98199,0x6c2f3132,0xfaf83aeb,0xf579893d,
  57046. 0xc73fda0f,0x858e87bb,0x7a0b9d1c,0xd3c0b3fb,0x71ee68b1,0x21fe6305,
  57047. 0x66aa6f16,0x5bf8f01f,0xbca825ed,0x30934c99,0x000000d1 },
  57048. { 0x913022f2,0xe4309850,0xde5b80ce,0xfdc336c9,0x8b6130ef,0xb716d689,
  57049. 0xa758d2f4,0x8a58b405,0xaa5cbc1c,0x98879df8,0xc12ce0bb,0x847cfd06,
  57050. 0x8c02ff3c,0xa1006360,0x3438695b,0x836e906a,0x00000136 } },
  57051. /* 7 */
  57052. { { 0x259ce02d,0xac8fe351,0xdae5e0f7,0xa506da0c,0xf043421d,0x77b56e98,
  57053. 0xa1647490,0xe0d041c7,0x9cb90101,0xe41f0789,0xda3e72e6,0x29bbf572,
  57054. 0x04a14df0,0x6b635c47,0xe81ef5d3,0x56873f58,0x000001dd },
  57055. { 0x5cf9e33f,0x77abe79e,0x0a1117fd,0x91aab581,0xcbac2fe1,0x11edf3b1,
  57056. 0xd72113b7,0xef43e017,0x06b74002,0xf9ad685c,0x8fbd3b1a,0x7e6370ce,
  57057. 0x42f73a82,0x550dd50b,0xc5e64a9b,0x8f2146be,0x000001f2 } },
  57058. /* 8 */
  57059. { { 0x2934ed82,0x05a704cc,0x989edd8c,0x647089fb,0x0ce7c62d,0xe0b239d4,
  57060. 0x105a5eff,0x4c892ea6,0xd5ed6b04,0xa519395f,0x509ed794,0x806c7003,
  57061. 0xe70ce5c4,0x882e9886,0xff01f6a9,0x50730ca1,0x00000088 },
  57062. { 0xdbcc5484,0x90a78a16,0xfd454b50,0xc1ab078c,0xcb09e525,0x6f488252,
  57063. 0xe19b2ed7,0xdd663f53,0xa67bf59c,0x16b10da1,0x36bb770a,0xb47f6b95,
  57064. 0x777b2bce,0x6bdc8428,0x561553f8,0xcd02ae3d,0x00000017 } },
  57065. /* 9 */
  57066. { { 0x1579d15a,0x1e3633a0,0x3e98cd1f,0x574f0c23,0xc60f4f99,0x45969dca,
  57067. 0x49fb9f24,0x10062c93,0xd378f640,0xd29a29d7,0xd7d48c2f,0xec941760,
  57068. 0x31fbea5c,0xf0591c59,0xb40f9ebf,0xd6173e6b,0x00000063 },
  57069. { 0x5a984a72,0x220f4f39,0x32510f26,0x9a3f82ce,0x8c069a1d,0xf3d04c76,
  57070. 0x69a21e57,0xf1d6d891,0xdc4db601,0x6b96b30b,0x64dcf3e0,0x71eeb728,
  57071. 0xc7caaff3,0x6f80c483,0x571b66e4,0x45533092,0x000000b0 } },
  57072. /* 10 */
  57073. { { 0x87140dad,0x49ae4521,0x57e2803e,0xda73032b,0x026ea20a,0x13f5e5eb,
  57074. 0x6e00afb9,0x2d54c4b0,0x7a150474,0x4393b92b,0x13f1a7da,0xb5b41bf8,
  57075. 0x02b5867a,0x6d786907,0xaf2ea4d1,0x5193a9ac,0x000001b3 },
  57076. { 0xa6b186cb,0x2a1563f7,0xe28e57b6,0x73a70a44,0x78fc8a1d,0xd7c4fc6d,
  57077. 0xdf3d6d99,0x4c9b4581,0x1e373aab,0x544f5249,0xe913498e,0xe99434a2,
  57078. 0xc4700f4c,0x30159749,0xe5142766,0xb8ef02cc,0x000001d0 } },
  57079. /* 11 */
  57080. { { 0xb9e6ffc9,0xe99805a6,0xf74d977b,0x1a357f05,0x5c9941bc,0xc8ddef31,
  57081. 0xcbe842e7,0x4b6d66ca,0xa20dc12d,0x84e1f75f,0x5f0c02fc,0x8b1b2c50,
  57082. 0x037b493d,0x3fa1889e,0x95705046,0x720bd9e0,0x000001c2 },
  57083. { 0x93ab9309,0x1a1f3378,0x226a8f94,0xe05a30a2,0x4045f1bd,0x2c01a52d,
  57084. 0xab5f5115,0xf42e8fd5,0x0c05fecf,0x954d1d09,0x8d0650d3,0x47e964d1,
  57085. 0x3c860801,0x6866fa5d,0x5abbb4af,0xac2fecbf,0x0000012c } },
  57086. /* 12 */
  57087. { { 0xe5537747,0x846dc3d2,0x1f5f9f46,0xe28e00df,0x3f31e42d,0x041af624,
  57088. 0x256af225,0x4948947f,0xff4f9550,0x3896c61a,0x34bb5a3e,0xcb40c773,
  57089. 0xeceafacc,0xb9becb07,0x4d45e83e,0xfe29f049,0x000001aa },
  57090. { 0x6b5578db,0x83fb71b3,0x0a710526,0x3017f115,0x5f220d77,0x189ec946,
  57091. 0x48465e68,0xba87ae07,0x70e0cbea,0x1da474d5,0x2b2ba7c5,0xb92cb0a6,
  57092. 0x8b1fb7e2,0x35cb356d,0x2cc8cb18,0x1155296a,0x0000000f } },
  57093. /* 13 */
  57094. { { 0x6ed0f604,0x7f9c9d9b,0xcb49c6d7,0x765e43e9,0xae9be5ca,0x03c4dd67,
  57095. 0x405aed36,0x5480888b,0x920ccddb,0x3a69ebb2,0x03f0c7cc,0x44ec0573,
  57096. 0xce89b026,0x158e2437,0x4f179a17,0x86795029,0x0000003a },
  57097. { 0x9f193dd9,0xf7854032,0xdcc158a9,0x531e4068,0x3642b1a5,0x774171bf,
  57098. 0xc1e53aa3,0x12b4920f,0xfd87478d,0xd1c5fb53,0xa7cba7ca,0x48958c58,
  57099. 0x3f66f2c7,0x375b2cb2,0x598899bd,0x1b510d0f,0x000001b8 } },
  57100. /* 14 */
  57101. { { 0x52007e41,0xfe96299d,0xcd708dcd,0x997140b5,0xf655f6fa,0xe9294eed,
  57102. 0xd58b839d,0x7701d45d,0xb6f77cdb,0x5dbdf5ad,0x95a572f0,0x265189f4,
  57103. 0xb3515e7b,0xc162794e,0x72655e0b,0xbfb571e0,0x00000168 },
  57104. { 0xbda82a6b,0xf0d2b863,0x390a9cc7,0x3df5b283,0x700fcd7b,0xbab9995a,
  57105. 0xfa4e6c06,0xc01ef0af,0x76a392d4,0x10a98513,0x955392f0,0xa7e3fc72,
  57106. 0x1d7a8550,0x8e3c0128,0x361898a8,0xcbca551a,0x0000010f } },
  57107. /* 15 */
  57108. { { 0x3ab71115,0xc8a4cd40,0xbcb9b55b,0xb783170d,0xabd9b426,0x1be20f6a,
  57109. 0x5377b714,0x32d2ea64,0x6b358bbf,0xda342480,0x6e202211,0x782bc800,
  57110. 0xaa27c499,0xf80974c4,0x50341cde,0xc2e66fa9,0x0000004e },
  57111. { 0x24ae60c3,0x082cb95b,0x83ad7484,0xd4b80af4,0x6205256b,0x84b739ce,
  57112. 0xae1fe063,0x616f505e,0x342f218f,0xef14ea68,0x64a01186,0x2b17d66c,
  57113. 0x50858bce,0x60e889ce,0xd5881005,0xdb046c59,0x000001e1 } },
  57114. };
  57115. /* Multiply the base point of P521 by the scalar and return the result.
  57116. * If map is true then convert result to affine coordinates.
  57117. *
  57118. * Stripe implementation.
  57119. * Pre-generated: 2^0, 2^130, ...
  57120. * Pre-generated: products of all combinations of above.
  57121. * 4 doubles and adds (with qz=1)
  57122. *
  57123. * r Resulting point.
  57124. * k Scalar to multiply by.
  57125. * map Indicates whether to convert result to affine.
  57126. * ct Constant time required.
  57127. * heap Heap to use for allocation.
  57128. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  57129. */
  57130. static int sp_521_ecc_mulmod_base_17(sp_point_521* r, const sp_digit* k,
  57131. int map, int ct, void* heap)
  57132. {
  57133. return sp_521_ecc_mulmod_stripe_17(r, &p521_base, p521_table,
  57134. k, map, ct, heap);
  57135. }
  57136. #else
  57137. /* Striping precomputation table.
  57138. * 8 points combined into a table of 256 points.
  57139. * Distance of 66 between points.
  57140. */
  57141. static const sp_table_entry_521 p521_table[256] = {
  57142. /* 0 */
  57143. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57144. 0x00, 0x00, 0x00, 0x00, 0x00 },
  57145. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57146. 0x00, 0x00, 0x00, 0x00, 0x00 } },
  57147. /* 1 */
  57148. { { 0xc2e5bd66,0xf97e7e31,0x856a429b,0x3348b3c1,0xa2ffa8de,0xfe1dc127,
  57149. 0xefe75928,0xa14b5e77,0x6b4d3dba,0xf828af60,0x053fb521,0x9c648139,
  57150. 0x2395b442,0x9e3ecb66,0x0404e9cd,0x858e06b7,0x000000c6 },
  57151. { 0x9fd16650,0x88be9476,0xa272c240,0x353c7086,0x3fad0761,0xc550b901,
  57152. 0x5ef42640,0x97ee7299,0x273e662c,0x17afbd17,0x579b4468,0x98f54449,
  57153. 0x2c7d1bd9,0x5c8a5fb4,0x9a3bc004,0x39296a78,0x00000118 } },
  57154. /* 2 */
  57155. { { 0x0f0ccb51,0x80398667,0x3654974a,0xb87e1d01,0xb2b29ed9,0x7f58cf21,
  57156. 0xa3add337,0x06c0e9aa,0xe9d08ffb,0xf13b35d0,0x96761627,0xdd8bf44c,
  57157. 0x758a3ef4,0xa4a18c14,0xa0043adb,0x96a576dd,0x0000013e },
  57158. { 0x632d95a3,0x2bde24f8,0x4c524829,0x79f15ef1,0x9bdaba19,0xaadd863e,
  57159. 0xa962b707,0xdde053f4,0x14258d98,0xc598a2de,0x061c235c,0x9fa5a19d,
  57160. 0xe8ffd32c,0x0ed46510,0xef78ceac,0x2aea9dd1,0x00000185 } },
  57161. /* 3 */
  57162. { { 0xeaaf1fe3,0xd0a91dd8,0x4400b52b,0x0db38662,0x21abf0d2,0xff6a06a9,
  57163. 0xa768c940,0x9412879a,0x9a1eec37,0xf3791abc,0x2738343c,0xc913fbe6,
  57164. 0xe222abc1,0x728b42ab,0x2b9ef313,0x874c0a86,0x00000157 },
  57165. { 0xe6f03d49,0x0ac8f184,0x1e48be03,0xa9c357e4,0x815cbdef,0x02ce5ef3,
  57166. 0x5fd8dc3c,0x7a41c7ab,0xfaeb109d,0x4bef67c9,0xa84f4d38,0x2f98cca1,
  57167. 0x672f0aae,0x7e03d47d,0x1d58968b,0x24b1ab58,0x00000007 } },
  57168. /* 4 */
  57169. { { 0xdf9314e0,0x904f2d4b,0xe7a00aac,0xdaae850d,0x582efb03,0x79231083,
  57170. 0xec7fe6d2,0x80f1c283,0x199d74a8,0x2d5b3996,0x395007e7,0x5f120b9b,
  57171. 0x4773f03e,0x30d23773,0x3b78b686,0xf4c19273,0x00000121 },
  57172. { 0xfa8b51f0,0xf103ff6d,0x40e2bdf0,0xae7afb51,0x83254171,0x1130380e,
  57173. 0xcda10d95,0xe83501b8,0x4f3a8c01,0x1057771e,0xac807069,0x8f52196a,
  57174. 0xa5623821,0x3609b0aa,0x94a0a7f1,0x8c257906,0x000001db } },
  57175. /* 5 */
  57176. { { 0xb2c0958d,0x300370cc,0x69a7b387,0x89aef166,0x480c9b38,0x2792f3cf,
  57177. 0xfab3e149,0x0b2984f2,0x50748967,0x9751e436,0xad33db2a,0x9cab99d5,
  57178. 0xb44a4daa,0x4d945d32,0x16c77325,0xa26cca52,0x0000000a },
  57179. { 0xf9e66d18,0xcdbe1d41,0xaa117e7a,0x80aeef96,0xddb0d24b,0x053214a2,
  57180. 0x5c98b7bf,0x6dcfb227,0xdfd3c848,0x613e7436,0x3ca4d52c,0x6e703fa1,
  57181. 0x18551e64,0x0c8e2977,0xbfa8527d,0xf5e90eac,0x000001c6 } },
  57182. /* 6 */
  57183. { { 0x4ab2d58f,0xa2c2f1e7,0x2a097802,0xc1bbf82c,0x770bb76a,0x6583eb24,
  57184. 0x5667f7bd,0x8e4ed9ed,0xfd96897e,0xd8c01d86,0x3fbe0f15,0x66395a13,
  57185. 0xd99cdcb1,0x51e4f39d,0x720deb25,0xde08424a,0x00000082 },
  57186. { 0x60ea91af,0x97aa53b2,0x7a31dfdd,0xa4384af7,0x5cd09bbe,0xcd82f239,
  57187. 0xf30058e1,0x997c19da,0xe5c78e97,0x443b60c6,0x575b1845,0xfaae9b5f,
  57188. 0x08c2ce16,0x5ce86f33,0x4f63fa86,0x983ce58f,0x00000073 } },
  57189. /* 7 */
  57190. { { 0x8217609d,0xaee93131,0x2412fc00,0x7f8a9dd4,0x286c6329,0xe117e64c,
  57191. 0x7bf1c65e,0xcc3782d6,0x8d03eee5,0xe8c144db,0x9ab93799,0x01acacb2,
  57192. 0xb07784c7,0x215eb1b5,0x1affcd87,0x2c409fa8,0x000000f8 },
  57193. { 0x378139a4,0x007d3766,0xb55bea93,0xc6d969eb,0x68c8bc9d,0xc7c60d6f,
  57194. 0x5f93f242,0x844e8461,0x741717d9,0x8461ca2a,0xf0bf120e,0x8e930e79,
  57195. 0x6b5699d7,0xe1554a02,0x6a4fb6de,0xe69c7702,0x0000007d } },
  57196. /* 8 */
  57197. { { 0x4bee80d7,0x61b51bb0,0x7692de69,0x0e1f6a1f,0xa0ebc3bd,0x8379e46c,
  57198. 0x930644f0,0x1c0bffa7,0x390db077,0x97c67b87,0xfada1ce9,0x095c33e1,
  57199. 0xac54b512,0x3c500add,0xd3118656,0xc231d360,0x000000b0 },
  57200. { 0x39bcab2f,0x06289298,0x64dd220a,0xc0c06780,0x763dc2a0,0x062f6084,
  57201. 0x1938c3e3,0x88e9da73,0x52e46eb9,0x69be8f2d,0x6a5de0fd,0xe55c8d2d,
  57202. 0xdb2c0e26,0xf3a3fd63,0x1e4bff57,0x899c6d9f,0x0000014a } },
  57203. /* 9 */
  57204. { { 0xec05ce88,0x9ff6e3a1,0xb6afd202,0xf8fc2496,0x6fbeb007,0x0b9d2077,
  57205. 0xeebded40,0xb50ec0bd,0x693700f7,0xaef97742,0x3f7b030e,0x806e37a1,
  57206. 0x1b901f77,0x5cf17d17,0xca95ae0f,0x9036e5df,0x00000159 },
  57207. { 0x000e8e0c,0x00af64b5,0x06fb4df9,0xd3f2ae04,0x449f23ba,0x5f61da67,
  57208. 0x255b25a9,0x0ca91842,0x8e33c650,0xfa6af3e6,0xc2c027c1,0x14373c00,
  57209. 0x972840a5,0x99f3cda1,0xd0e84240,0x98c62b79,0x000000e7 } },
  57210. /* 10 */
  57211. { { 0xae4d0f28,0xe8c7c4a8,0x566d006e,0x3a8a55ef,0x066e4023,0x37985f65,
  57212. 0x5d321b76,0x8deccab5,0xb8351b07,0x38b966d6,0x57d548ab,0x2e889e53,
  57213. 0xe631ab0b,0x7a9e8e2f,0xe75c537b,0x45c60f95,0x00000059 },
  57214. { 0x7867d79c,0xbca27d34,0x81c81980,0x7f460b15,0x976b8c51,0x7ec2d9ab,
  57215. 0x61b91ed9,0xfcd04486,0xd9c1d15f,0x730a7a25,0xf94c9db9,0x8a2cf259,
  57216. 0x5dec5a3b,0x8e784b87,0x3e5131ee,0x06252607,0x00000004 } },
  57217. /* 11 */
  57218. { { 0xf1631bba,0xdee04e5c,0x156f4524,0x40e6c1df,0xe4c30990,0x06603f30,
  57219. 0x6b6abec7,0xdb649a43,0xf6b94f6e,0x354f509c,0x36b7e0b5,0x7fecf469,
  57220. 0xba1e6dd2,0xa7a7107e,0x689450ca,0x889edac5,0x00000022 },
  57221. { 0xd05596f2,0x9012916e,0xb023cb8b,0xe3901dac,0xe7d4abe1,0x2501d3ec,
  57222. 0xa9c90313,0xb2815040,0xc6d146d0,0x9dbcd3f1,0x74ee1896,0x6fa1d5b1,
  57223. 0xa91226fb,0x49aea161,0xb8a80984,0x754ceedf,0x00000154 } },
  57224. /* 12 */
  57225. { { 0x4270b2f0,0xb64e27b0,0xbf4d74d7,0x84b34e48,0x0c2722ba,0xb186be8b,
  57226. 0x9ff9b71c,0xf54a589d,0x34fd6bc4,0x9887e4df,0x7412f49d,0xb7c669fd,
  57227. 0x77f89d16,0x4008d9bb,0xc902e074,0xafb9426b,0x000001cf },
  57228. { 0x662935ca,0xcca4f2d1,0x997dcc46,0x2847c703,0x353c79f8,0xc089e9e5,
  57229. 0x5215f0f4,0x9ed8d989,0x80911b9d,0x59cf08bc,0x6de27aa3,0x4b03540e,
  57230. 0xf69e320d,0x52f4d63e,0x94ef193b,0xa0217fd6,0x000000e6 } },
  57231. /* 13 */
  57232. { { 0x74214780,0xb77de627,0x207459ea,0xca066817,0xe9c7fb01,0xf78579b7,
  57233. 0xd6d4b7c7,0xe55548c1,0xa66caa39,0x45756190,0x98505a4f,0xf8141b03,
  57234. 0x4c8864eb,0xa5ca0d7c,0x9e129d3f,0xbf8af950,0x00000053 },
  57235. { 0x85285092,0xbc9b29d8,0x8eed5e5f,0x82f31daa,0xf618aab9,0x9c33690e,
  57236. 0xd2626ed1,0x0eee14f4,0x07ed8e09,0x4229570b,0x8736d040,0x1977920e,
  57237. 0xede7d01d,0x47ee25ff,0xbc7ab73b,0x3c921c3a,0x000001b9 } },
  57238. /* 14 */
  57239. { { 0xa08b2b14,0x0b6a07cc,0xbf174c7f,0xaa978deb,0xc40cb2a4,0x291cb828,
  57240. 0x90adc838,0x95c78272,0x8c1edde6,0x08da8b2a,0x90fbd220,0x741ceb2f,
  57241. 0x322db94e,0x5f89c9e5,0xb73c548e,0x18266085,0x0000007d },
  57242. { 0x2defd012,0x69ebf82a,0x5a1537ef,0x01ecb094,0x3ef0811d,0x3c557535,
  57243. 0xb2bd4dea,0x59c882a7,0x7bf969c8,0x00a1f972,0x0b25ad1b,0x063adf5e,
  57244. 0xf2536005,0x4c1ff306,0x4112fe18,0x8e515bec,0x00000117 } },
  57245. /* 15 */
  57246. { { 0xefe3d3d5,0x9314787f,0x9d897227,0x29e76f65,0xe0b6acf5,0x15c77ed1,
  57247. 0x1c5e8dd9,0x9c2b7b20,0x5f5667af,0x788038f1,0xf3576ef4,0xf38c766f,
  57248. 0x0040154a,0x9f0623c8,0xde883b53,0x47d3c44b,0x00000096 },
  57249. { 0xde1b21a4,0x32075638,0x571081c1,0xbb6399c1,0x75c03599,0x322e6067,
  57250. 0xade60cf5,0x5c7fde7f,0xefc19059,0x1b195440,0xdd7b3960,0x7e70ac8c,
  57251. 0x6a6fa73e,0x4aa5a83d,0x63080764,0x34f8cfac,0x00000042 } },
  57252. /* 16 */
  57253. { { 0x286492ad,0xee31e71a,0x65f86ac4,0x08f3de44,0xda713cb4,0xe89700d4,
  57254. 0xa86b7104,0x7ad0f5e9,0x2572c161,0xd9a62e4f,0x25cc1c99,0x77d223ef,
  57255. 0x3b962e0c,0xedff6961,0x81d8b205,0x818d28f3,0x0000008e },
  57256. { 0x8cdf1f60,0x721231cf,0x6717760f,0x8b640f2b,0xe045a403,0xbe726f8c,
  57257. 0x0370689f,0x422285dc,0x72ea0dcb,0x7196bf8f,0xc8086623,0xa16f7855,
  57258. 0xc326fe48,0xd4e19fc7,0x8f68bf44,0xfdbc856e,0x0000013e } },
  57259. /* 17 */
  57260. { { 0xe6a3ace5,0xde34d04f,0x896191c1,0x0dbb603e,0xf75ed0f4,0xb4dc0007,
  57261. 0x95b259b5,0x15e0e6bc,0x2615f020,0xdfbcba66,0xd31ea3f8,0xb2ec5433,
  57262. 0x103ff824,0x42b0b0e4,0xc480332e,0x19315060,0x00000111 },
  57263. { 0x045452f1,0x9997ea28,0x71f3f73b,0x80b678cf,0x41e9328e,0x4a52bddc,
  57264. 0xe6af1c23,0xb7f2656e,0xb44215e7,0xc43805b9,0xf0a4028b,0x3aa734f2,
  57265. 0x422476e2,0xe3c72479,0x68c60cf7,0x6dc2e8b0,0x000001f1 } },
  57266. /* 18 */
  57267. { { 0xfffc0de5,0xbcdfae6f,0xab4a5f24,0xa801814f,0xea2aa8dd,0x19013658,
  57268. 0xda4f0441,0xf3b1caf5,0x34100611,0xf24b9cdb,0x96e0cf88,0x48c324ed,
  57269. 0x23055c82,0x4b7ea334,0x89092e29,0x6e835b64,0x000001d3 },
  57270. { 0x07372f27,0x7eb77ae7,0x83bae19a,0x4779b4fa,0x65429ebb,0xa175dae1,
  57271. 0xfc03ef3f,0x942ec266,0x6991c7c4,0x0e5fc6a9,0x56253d3c,0xa0f61e4f,
  57272. 0xde74e738,0x7a11ff58,0x624de919,0x60524cd4,0x00000002 } },
  57273. /* 19 */
  57274. { { 0x01342e08,0x45b5d0ca,0xb749f0af,0x509ed4f0,0x6529d804,0xeb5502d9,
  57275. 0x6d80359c,0x5eb087db,0x4c384800,0xeaa66a87,0xc75a8784,0xe972c7a0,
  57276. 0x6874317e,0x8c169e21,0xe5c9fbf4,0x81c556e0,0x0000014f },
  57277. { 0xe120674d,0x26b0b12b,0x219f00ac,0xc6bf09b9,0xd658caa6,0x1e1e732d,
  57278. 0x8292d99e,0xc771c5af,0x25fdbf80,0x5d813529,0x3666c37d,0xe61bd798,
  57279. 0x1d0df680,0x8dac946a,0xc39f0983,0x58dcf684,0x0000009f } },
  57280. /* 20 */
  57281. { { 0x7b7dc837,0x14169102,0xb50eb1c4,0x2d719754,0xd7e6741b,0x04f4092a,
  57282. 0xbc824a38,0x1d0a7f1d,0xc8e20bcf,0x570b2056,0xda181db0,0x6732e3b9,
  57283. 0x0a7b508a,0x7880636e,0xc9f70492,0x11af502c,0x00000045 },
  57284. { 0xc56f4ffa,0x0b820d94,0xc4f0c0fa,0x1c6205a2,0xa1a0606a,0x99f33d4e,
  57285. 0x79b316fb,0x1bab6466,0xe4f240fc,0x05aa0852,0x92d7dc43,0x22539b78,
  57286. 0x06e3c073,0x03657f12,0xcedb6633,0x28405280,0x00000059 } },
  57287. /* 21 */
  57288. { { 0x4397760c,0x90d08711,0x1c9fcd06,0xb9020b76,0x987e24f7,0xc7fec7fa,
  57289. 0x522335a0,0x0e33b8a0,0xae21ca10,0x73dbeafd,0x3b032220,0x458c060a,
  57290. 0xee145da6,0x9b9c73b8,0x27ff62ef,0x31c661e5,0x000000aa },
  57291. { 0x81430b5e,0xaf518eb0,0x50ee0d69,0xb32f9cea,0xaa6ebe8b,0x0ecdb0b5,
  57292. 0x9fe1d689,0x1f15f7f2,0x1a59cc9a,0xce5d68f3,0x08ab2a63,0xf4d67994,
  57293. 0x4347ce54,0xe85b1cef,0x286d0776,0x8ff423c0,0x00000176 } },
  57294. /* 22 */
  57295. { { 0x33dcec23,0x8564104c,0xcdd07519,0xbaf0d61b,0x4c4f309a,0x486daf51,
  57296. 0xde488715,0xf01bc8f5,0xd3539ba3,0xddd6baf1,0x3a3be8ec,0xbb7e665d,
  57297. 0xcb5d865f,0xf919dac3,0xf12149a0,0xfe203da3,0x00000173 },
  57298. { 0x78d4a3d1,0x043ae9a1,0x865316d8,0xa4d5cf58,0x41176463,0xeaf026c0,
  57299. 0xf84afa44,0x316c638f,0xffea422d,0x512f2397,0x6622b613,0x691eaa04,
  57300. 0x97e7068d,0x48856ea3,0xf4a1b33c,0x42d1b2e3,0x000001b5 } },
  57301. /* 23 */
  57302. { { 0x1f487402,0xf51b2d5e,0x7aaf1dd5,0xe36016e6,0x6da9c20a,0x1eb3f1f5,
  57303. 0xece45bfd,0x25b7d361,0x027a9e18,0x42db0633,0xe8411649,0xbf228777,
  57304. 0x458773d0,0xf5fce0c4,0x2dd7a5f0,0xb2b3151d,0x0000001f },
  57305. { 0xfbaa096a,0x102773e8,0xe093a878,0x152726eb,0x2c7f1781,0x5c53cd07,
  57306. 0xab5dca76,0x38d3dfd0,0x87ef2d4a,0xbb4a7d85,0xb7eb11c2,0x5c9c2013,
  57307. 0x0b6da22f,0x5e353c34,0xa325ecad,0x846d50a5,0x00000039 } },
  57308. /* 24 */
  57309. { { 0x1677df58,0x76da7736,0x1cb50d6c,0x364bd567,0x0a080ff2,0x0443c7d7,
  57310. 0x86532430,0xa0a85429,0xc35101e7,0x82002dd2,0x48c5cd76,0xbebc6143,
  57311. 0xca6cf13f,0xff1591ae,0x98bf8dc0,0x91c7c2e6,0x000000fb },
  57312. { 0x12de14d5,0x6a7c5cad,0x6561c822,0xbc448c5f,0x7cdbb3da,0x9f8de430,
  57313. 0xc76811d7,0x9c58f011,0x75462049,0x1e89806e,0xc9a74e49,0xe52ad0a2,
  57314. 0xb2be37c3,0x2034685c,0x0a0bc72d,0x7a863245,0x000000ec } },
  57315. /* 25 */
  57316. { { 0x8a86786e,0x33818c21,0x2137e2c8,0xed537f74,0xa7e6eb20,0x5d9690d1,
  57317. 0x5cdc4803,0x9790ec70,0x24f7bd75,0x469162c8,0x4e1f0f14,0x09e7ef9d,
  57318. 0xce9915ca,0xd30c128b,0x6c71226f,0x810145f6,0x0000002d },
  57319. { 0xb71d87e5,0x312749f5,0x7b02ceda,0x25f3b141,0xe0baff16,0x02456d2e,
  57320. 0xfcae6627,0x97f7b3a9,0x37bd985f,0x0d6ebf8f,0x7fa6d0c1,0x20aa81b9,
  57321. 0x21f2f137,0xb29f1a01,0x5cc0ddb1,0xe326a2f8,0x0000003d } },
  57322. /* 26 */
  57323. { { 0x38c2ee78,0x26f3398b,0xa75a0bee,0x40c3d101,0x565a7f8e,0x35a31706,
  57324. 0x04019e5d,0xd12985e3,0xb8174b6e,0x21e2a642,0xaf80a52a,0x25a15ee8,
  57325. 0x8518d80e,0x5d1e0fe6,0x04f6ea9a,0x8cbbc138,0x00000084 },
  57326. { 0xdfd45169,0x76828690,0x59d3e8d0,0x38d7e098,0xcdb8bfc2,0x23758811,
  57327. 0x162cf648,0x8499547a,0xb4d15b8c,0x494bab3b,0xc60499a6,0x822cbc57,
  57328. 0xa8a1cfed,0xac43224e,0x57c6598b,0x43563469,0x000000d9 } },
  57329. /* 27 */
  57330. { { 0x68271323,0x2b069253,0x49cd04d7,0x24d9e0a8,0x2b31cc7d,0xaae35fbf,
  57331. 0x57a3e361,0x44f64b4f,0x0294e856,0x14904686,0x43ced4ae,0xddc82ee7,
  57332. 0x7e2cda47,0xcb92a6a5,0xbfc1f968,0x989c42ef,0x0000013f },
  57333. { 0xb8651600,0xbed98bdf,0x7a3cfaee,0x8c363434,0x35b1a226,0x93a12543,
  57334. 0xd5825507,0x558da7dd,0x852eb1e9,0xa5173b23,0x2295f545,0xdf5ae585,
  57335. 0x6646d101,0xe546e2ef,0x5d89f862,0xf7e16a2c,0x000001fa } },
  57336. /* 28 */
  57337. { { 0xc7ec136d,0x0d746c8e,0xcd11351b,0xf8e1d827,0xf187a116,0x764a3ad3,
  57338. 0x136e8465,0x2f1b968f,0x850983c2,0xd41aa294,0xbe717259,0x2123ecc4,
  57339. 0x763c149c,0xdcdcab52,0x1022b82d,0xa7f50b18,0x0000016d },
  57340. { 0x0ca5e258,0xf99e532d,0x97b62a7b,0xa148ad17,0xc77fddef,0x8d0a242e,
  57341. 0x74f9b6c4,0x58518bcd,0x7fd122d4,0xc53b30b8,0xfb50b2d7,0xbb8cd193,
  57342. 0xbc01aae9,0x1a169aee,0x1de26e09,0x7e49b10a,0x000001c5 } },
  57343. /* 29 */
  57344. { { 0x21210716,0x2cabe675,0x07e02400,0x81a296a3,0x8c83795b,0x94afc11d,
  57345. 0xdd9efa6a,0x68f20334,0x677d686f,0x5be2f9eb,0xbf5ce275,0x6a13f277,
  57346. 0xb9757c5c,0xf7d92241,0xc74f4b8c,0x70c3d2f4,0x00000132 },
  57347. { 0x8d209aa4,0xf9c8609c,0xdb2b5436,0x46f413a2,0x2992345d,0x96b72d1a,
  57348. 0x9487c34f,0x186f2aeb,0xb440a375,0x4fa72176,0x7da5358e,0x3a420936,
  57349. 0xff25b310,0xf11eade3,0x505d60b8,0x9a570153,0x000001a9 } },
  57350. /* 30 */
  57351. { { 0x6e7495bb,0xae151393,0x490879d1,0xebd2fd28,0x29fd76fc,0x9c232b0b,
  57352. 0xc60e721c,0xa1a0d49b,0x517a09e2,0x9f582b83,0x9d8badf8,0xac37809e,
  57353. 0x0ad48bb4,0x4aa4de9e,0xcb6cc487,0xfd041312,0x00000027 },
  57354. { 0xead4fb6d,0xc05502ee,0x0a602cbe,0x760c25ed,0xbd7f4a07,0x58ba6841,
  57355. 0x54edce14,0xc28b6032,0x0397614c,0xb9d41e39,0x181eed93,0x4221b71d,
  57356. 0x332d4b0b,0xd010e3c2,0xdab0e419,0xdfe58a27,0x00000096 } },
  57357. /* 31 */
  57358. { { 0x7debd24e,0x4cd6fcd6,0x9ae2b075,0xbe3fca60,0xf217c26c,0xa7d8c22e,
  57359. 0xb9620e3f,0xd42d03e0,0xc7f9f87d,0x634bf216,0x8972ffee,0x22b1ec53,
  57360. 0xd60d3e77,0x83a957c1,0x0f6a537e,0xedfe5f86,0x00000162 },
  57361. { 0xf0ea20b8,0x40a05400,0x1d796900,0x2872ac7e,0x0edb0cac,0x7765a5c9,
  57362. 0xb62939a7,0x9df5b930,0xaf2cb708,0xf78a676e,0x52febc12,0x030732bf,
  57363. 0xba190ad3,0x3a6640de,0x93e7e341,0x36eae15f,0x000000d5 } },
  57364. /* 32 */
  57365. { { 0xa1c88f3c,0x6c6119f6,0x2ec6944a,0x924e5fec,0x5742ff2a,0x4c8aac60,
  57366. 0xddb22c7c,0x60adde1e,0xfa5d25bb,0x9728938c,0xec117de0,0xfa5ac4f7,
  57367. 0x482929c1,0x41f35ab7,0x0afd95f5,0xd1c4e8f9,0x00000180 },
  57368. { 0xa7cd8358,0x2fc4e73d,0xf2a1c920,0x39361a57,0xad94d288,0xf6f2f130,
  57369. 0x2b6a78e2,0xe37e2466,0x79c262cd,0x0babff8b,0x61b597b9,0x6cae01ef,
  57370. 0xa60d4e64,0x9c1e33f0,0xdd01f845,0x52a42280,0x0000000e } },
  57371. /* 33 */
  57372. { { 0x0f013755,0x72d640a4,0xfb8380e9,0x0b6dce77,0x7eb64b31,0x2789ce79,
  57373. 0x93ca5a36,0x8e704b0b,0x58bdffc9,0x18c360ff,0xb230c372,0x53b1f323,
  57374. 0x5a7385d1,0xd6b39088,0x56b93bf7,0x071130f5,0x0000004a },
  57375. { 0xfeef3f88,0x29a2096b,0xb82b3945,0x22eba869,0x872664a7,0x7fe2184a,
  57376. 0x858ff942,0xa0dc0ba1,0x7490c9da,0x33799eb5,0x81588ce8,0x1d356f62,
  57377. 0xa7b2cee2,0x7dd9bc7f,0xa3cfaee9,0x1e61a4e8,0x000000d2 } },
  57378. /* 34 */
  57379. { { 0xe9068656,0xec5db629,0x9fede4df,0x623bd70c,0xfcd45546,0xc78ad5bd,
  57380. 0x6291a741,0xf7981dd2,0x761e688e,0x3ac53d92,0x55b9272f,0x6a96892a,
  57381. 0x06546fec,0x4217e7b8,0xab9e2f56,0x793c03cb,0x0000015e },
  57382. { 0x6eff39be,0x08fd9543,0xdbff4f68,0x5a1af07e,0xb0241616,0x83d47abd,
  57383. 0xd4798029,0x37c5d2fd,0x60b2e6fb,0x9d86d978,0xce8db998,0xe3e3284e,
  57384. 0xd868b9bb,0x9f049eb5,0x9dad18b3,0x3b3e8a78,0x0000018e } },
  57385. /* 35 */
  57386. { { 0xe51e61f0,0x57026c56,0x307f2757,0xdddbcaa3,0xb1aeaf41,0x92a026eb,
  57387. 0xe2d7f5ba,0xa33e937c,0xbc5ead91,0x1f7cc01e,0x2e46807d,0x90ab665d,
  57388. 0x53419519,0xc2a44f55,0x79664049,0x099c1ca6,0x000000aa },
  57389. { 0x8f97e387,0xb561a909,0x45e1dd69,0xf6051778,0x7ff1d6ab,0x1ffa512b,
  57390. 0xd09a9c89,0x42da55a4,0xd2282e2b,0x5e5a7c71,0xe74185ad,0xdfa5a203,
  57391. 0xea0baeff,0x19b1369d,0x1ecc0a16,0xa5eef914,0x000001a3 } },
  57392. /* 36 */
  57393. { { 0x7a573b81,0x2af20d0a,0x66194cef,0x7eac1ca8,0x0b711c34,0xef0d2d8d,
  57394. 0xba099d42,0x6aea016c,0x5067a8ca,0xa6609d28,0x7a1351ef,0x6a52c600,
  57395. 0xb11c2634,0xdab85818,0xbb1c033c,0xf17fa45d,0x00000121 },
  57396. { 0xfc3279d6,0x9fb8b87a,0xc201f1e1,0xe30e76ab,0x806c21dd,0x02af6a83,
  57397. 0xc63f824f,0xeafd7e2b,0x46bd1a53,0x7b074e26,0xa2139164,0xcd6f4931,
  57398. 0xc172d9bf,0xab2cfd39,0x4db59cf1,0x62f3eb4b,0x0000010a } },
  57399. /* 37 */
  57400. { { 0xe0689a1b,0xe402de36,0x7dcafe72,0x9dccc9fd,0x255d0bfb,0xe4dead7e,
  57401. 0x4ada04d9,0xd7ee87ee,0xbfd2e774,0x5a85039e,0x770b2b9b,0x282c6657,
  57402. 0xba103bba,0xa7aca826,0xc7cd5071,0xac7028ba,0x0000011a },
  57403. { 0x680c8f04,0x2e61d39c,0xb48b3b5e,0x2f09c4cc,0x95744f3c,0x131609bd,
  57404. 0xaaccb593,0x6d72e4b4,0x5adfb209,0xdb7060ca,0x1fd3eccf,0xc67d9e43,
  57405. 0xe1752a73,0x1487a26f,0x64d0857c,0x3d953663,0x000001e3 } },
  57406. /* 38 */
  57407. { { 0x4cec9e7f,0xe664506b,0x30aab98f,0xa44564b4,0x173fa284,0x5e1b501f,
  57408. 0x15c97472,0xe7b7bd7e,0x82dec033,0xd6cc67a8,0x0a63b762,0x1fe2e934,
  57409. 0x3f8e2fcd,0x3a084e1b,0x9ae6e752,0xccce4da8,0x000000fd },
  57410. { 0xc12fd820,0x0797f8ee,0x96da4733,0x325f892a,0x55997bf4,0x597d241d,
  57411. 0x02b753cf,0x3aef35ac,0xf677ceba,0x8a73f95d,0xd1bbac6c,0x5b2892b7,
  57412. 0xcc5278b0,0x90751583,0xa47f45f6,0x2f5ed53f,0x0000001c } },
  57413. /* 39 */
  57414. { { 0xab40b79c,0x3914165e,0x25b489a8,0xbfb6eed8,0x8a6c107f,0xda136b7d,
  57415. 0x8e01f28b,0xd431db8b,0xa4d79907,0x84e5d0dd,0xa471e685,0x69a91472,
  57416. 0x98376ff8,0x58d06969,0xc46311fd,0xce369b74,0x00000006 },
  57417. { 0x1add1452,0x6c0773d1,0xed8e9a2a,0x2e4e9c95,0xca15a40c,0xe8ff8e32,
  57418. 0xaf62f18f,0x3fcb7d36,0xeec9484b,0x2ca336ee,0x3b20405b,0xa4d6e7a9,
  57419. 0x956d8352,0x6d90d031,0xd9ca03e7,0xdd375603,0x000000e5 } },
  57420. /* 40 */
  57421. { { 0x8b481bf7,0xcc5f297d,0x2a13383c,0x06a2a3e4,0xdc40b96c,0x9e14528c,
  57422. 0x1189da3c,0x9a2bf35f,0x6cd57fa7,0xb8adb989,0x9357d32b,0xc1a4935c,
  57423. 0xc2d76fad,0x51fb2580,0x24f23de1,0x98721eb4,0x000001ba },
  57424. { 0x52a4b397,0x8c02daaf,0x0d0b4e54,0xc3c5f4cc,0x7b7e79cd,0x29be4db3,
  57425. 0xb33970b6,0xf34336ec,0x92808c7f,0xed3dcb7c,0x02288db1,0xec290eff,
  57426. 0xe96ed59a,0x2a479d51,0x76d8fa5f,0x9d7ed870,0x00000092 } },
  57427. /* 41 */
  57428. { { 0xe660043c,0xd8edaf0b,0x016e074d,0x84aa2ccb,0xe2cc3b3d,0x9d2368e7,
  57429. 0x5c269fc4,0x47b50130,0x3de33e36,0xd0194ee1,0x789ca504,0xdb3361b9,
  57430. 0x984db11d,0x8cd51833,0xc8ec92f0,0xd5b801ec,0x000000c6 },
  57431. { 0x47ab9887,0x33f91c15,0x6b5ab011,0x2f285e2a,0x133fc818,0x9b734e5a,
  57432. 0x38d8692c,0x5c435a74,0x43282e81,0x3c92b47c,0x9c7bcdaa,0x191231f5,
  57433. 0x4d158c86,0x3ae425c3,0xc5a23cca,0x7f568feb,0x00000011 } },
  57434. /* 42 */
  57435. { { 0xbf5caa87,0x8ccbd9d5,0x68dd8c9d,0x17bfc60f,0xc7d4dede,0x63eb4dbb,
  57436. 0x8270b5bf,0xbf6e5945,0xcc098fe7,0x887137a5,0x05d7b8f5,0xca5eb687,
  57437. 0x4b25a533,0x4b7deeee,0x4a700a6c,0x8e045c32,0x000000ef },
  57438. { 0x70cf52bc,0x160c1c92,0x90cc6298,0x4bf3f63a,0xbf3028fb,0x5fff421c,
  57439. 0x523beff1,0x0a8102d7,0x8b9ce105,0xff3309a3,0x06621b1e,0x8e9da4d0,
  57440. 0xcc0a7807,0x9775f89f,0x00178612,0x59044865,0x000000eb } },
  57441. /* 43 */
  57442. { { 0xebbd33ec,0x8a6664fd,0xce5ad579,0x0cf9a660,0x50fb56ed,0xecd06c05,
  57443. 0x1d5aaa6e,0xb4ca5fad,0x948a7f07,0x36daee5b,0xefe1c11a,0xd2e37887,
  57444. 0x91d2544b,0x41f61ac4,0x2bffd8ea,0x49df7071,0x000000be },
  57445. { 0x65acdb56,0x60e2f1f5,0x5e5e5bde,0xf2f13c84,0xe17a0412,0xb97fd354,
  57446. 0xd9c93bef,0x8a2867cf,0x25a957e4,0x9ca9d16b,0x4a18635f,0x1f55c19b,
  57447. 0x8d26ae71,0x9b3868f5,0x4c94541d,0xac448041,0x00000000 } },
  57448. /* 44 */
  57449. { { 0xd4ad38db,0x6c1bcf89,0x3d714511,0x1180f381,0xcb70243a,0x5b4c2759,
  57450. 0x163a716c,0x5dd64d63,0x13648bdb,0xbbd2efea,0xe4de9969,0xa47187f9,
  57451. 0xe2de8c45,0x65de6912,0x4bdad0a7,0xe075f29c,0x00000048 },
  57452. { 0x5e4dd88d,0x00335474,0x80577afc,0x18283638,0x227288f7,0xe4b35c01,
  57453. 0xe68989de,0xd008fd91,0xcd3f71ba,0x42142315,0x3e4da1e2,0x5cb023ff,
  57454. 0xb5662bb1,0x7e6b9c35,0x7fb04fe5,0x143f4165,0x00000072 } },
  57455. /* 45 */
  57456. { { 0x26f40f2c,0xb06b046c,0x6cd7c31d,0xbd5d246c,0x1953a9b7,0xaaa56270,
  57457. 0x8f00436f,0x5ac929b8,0x21d0660d,0x1937392c,0x9bd6dbe6,0xd279ed15,
  57458. 0xd17c43f9,0x377c4d5a,0xb8fcd025,0x800eda50,0x00000179 },
  57459. { 0x36132f31,0xb88ddc0b,0x2ade73a3,0x6f8f4f01,0x203de2b9,0x38859ec3,
  57460. 0x231b6533,0xedb03814,0xa14093ca,0xad08cd20,0x5c2be2f9,0xb9f86d44,
  57461. 0xf6ebc09f,0xfd3d9532,0x1aef478d,0x757b5899,0x0000013d } },
  57462. /* 46 */
  57463. { { 0x580f894b,0x7d9ad100,0xd925e46f,0xb612488a,0x2e5a6865,0x45497e14,
  57464. 0x17f9a813,0xc86e1053,0xf8a33541,0xd8aa820a,0x7a66d578,0xa6790660,
  57465. 0x5f758e23,0x47df60ae,0xa7f8ab5c,0xcadd4c90,0x00000107 },
  57466. { 0x6764ad0e,0x356b044f,0x250189b3,0xf69fe0e1,0x5f14db6a,0x2deaca62,
  57467. 0x1bd77d54,0xe9f2779f,0x5cfa895c,0x979911f2,0xb6f19ac3,0xd4e94ced,
  57468. 0x01af44b1,0xc3533417,0x50c727f5,0xcac43fff,0x0000003b } },
  57469. /* 47 */
  57470. { { 0x83c1d4cf,0x1742951c,0xb245c34f,0xe03791d0,0x9c2dcc71,0xea8f8ef6,
  57471. 0x2a310767,0x2ea57a29,0xb12948bd,0x255b46bb,0x0feaeb83,0x2adc1e09,
  57472. 0x449abf59,0xa0d2d18c,0xc4a8a689,0x9e8c9ff5,0x00000019 },
  57473. { 0xeb28171a,0xc9f7b9cd,0xd576987b,0xefd78403,0x22ff824c,0x58b4f3bf,
  57474. 0xbf333cc5,0xee09b393,0xb01ceb72,0xebff83a2,0x220299cd,0x5bb34c45,
  57475. 0x66ebf751,0xa3c3e8a0,0x49d05cf3,0x5dee07bb,0x000001a6 } },
  57476. /* 48 */
  57477. { { 0xb114257b,0x09a958d6,0xd4975e30,0x729afd41,0x3aae7b11,0x072879b5,
  57478. 0xedd1ac83,0x0791b093,0x1eb67975,0xcfefc7d1,0xe2675b4a,0x0e54bd37,
  57479. 0x8d69517f,0x89a62d7e,0x202109a3,0x96f805d8,0x0000006b },
  57480. { 0x57b5f9f4,0x4815d517,0x405b44d1,0xe5c9e436,0xe4870160,0x3442dde0,
  57481. 0x1ef6b3f8,0x953fef95,0xf7497faf,0x919e4cf5,0x016ef0b7,0x24e3cc4d,
  57482. 0x2512eeed,0xfc5caa87,0xa3bd1703,0xf1ba4029,0x000001b6 } },
  57483. /* 49 */
  57484. { { 0x529252ac,0x2a668435,0x74e7b0d8,0x3da626c0,0xe0be86ab,0x55080cc1,
  57485. 0x4ed5dc53,0x534a53f7,0x0cd41fd0,0xa9eff140,0x5674891c,0x0e7c945c,
  57486. 0xec53b5ad,0xdea4b895,0x15150988,0xefc67bef,0x000001ff },
  57487. { 0x306033fd,0x988dc109,0xf36875d9,0x1b287979,0xe3c335c5,0x4d39af26,
  57488. 0x124e29d6,0xa47259fd,0xc41dbdfc,0x5d60c570,0x0cc0d895,0x06224b61,
  57489. 0xeea8ff86,0xa041d4e5,0xae4d8707,0x2920e15c,0x000001fd } },
  57490. /* 50 */
  57491. { { 0xcd67da85,0x66d15f0c,0x5ac54a15,0xae98b6f4,0xf1ac71c3,0x2f05e021,
  57492. 0x47559224,0x1feb2226,0x66e856dc,0x2a2f1561,0x6fb4ba47,0x65eb1456,
  57493. 0xa29d920b,0x34688bd2,0xf9d4cb9b,0x943ce86e,0x00000061 },
  57494. { 0xaac91174,0xb4696218,0x41dd9234,0x85b519ec,0x9f0763a4,0xb7efadf2,
  57495. 0x712c8b33,0x98517f27,0xb0538630,0xa02e7ec3,0x1ff3e3e4,0x46bc45bb,
  57496. 0x29496486,0x46ae896f,0xebd2b93f,0x2aeb1649,0x00000146 } },
  57497. /* 51 */
  57498. { { 0xe8e4d3c3,0x1f34f41f,0x5bb7e9db,0xc80d87ff,0xd910b579,0xf0216c0a,
  57499. 0xb87349ae,0x2a24b761,0x2b0a6cc0,0x054bc528,0xaf2d1957,0x3b4c7029,
  57500. 0xadbe6cdd,0x0e4b90e2,0x26060a34,0x8e774f81,0x000000cf },
  57501. { 0x2e229950,0x3c7f9dbc,0xd9f82b70,0xab11f846,0xf10c05f3,0x2b7ad9a3,
  57502. 0x0f1820ca,0x203ead4f,0xccbfb332,0x51dbcbc8,0x066706f1,0x3bd9caf0,
  57503. 0x06059d5e,0x5a39be25,0xdcafe64e,0x984387c8,0x0000014c } },
  57504. /* 52 */
  57505. { { 0x8e011531,0x708a757f,0xc3dcd57c,0x7f45b172,0xc2d99e29,0xa8eac9fd,
  57506. 0xb93b6415,0x9d4ee81f,0xa5488e86,0xa5833b54,0x0bb7ab70,0xddd561c3,
  57507. 0xb3bdf3a9,0xb5bda384,0x1ddf332b,0xf909f8e0,0x00000124 },
  57508. { 0xab41e782,0xc5b8aa84,0x851ddb87,0x1de20126,0x99482bd2,0xf49baa7d,
  57509. 0xf4b6413b,0x05963deb,0x7cd1e224,0xed369fbb,0x1bad60ee,0xdcf495dd,
  57510. 0x892e30ed,0xeb475693,0xaf0a212d,0xaaf11bd8,0x0000010b } },
  57511. /* 53 */
  57512. { { 0x16ec64e2,0x71460174,0x7d7c6ebe,0xbfd14acf,0x668b7176,0x1e3504a3,
  57513. 0x741b041c,0x72e3f3f3,0x2d3b67b0,0x651fa54a,0xe57d928d,0x623edca3,
  57514. 0x72c8f419,0x29b74e8b,0x327abaef,0x3d99cb47,0x00000038 },
  57515. { 0xda342a3f,0x808dd0b3,0xdef4a954,0x12002462,0xeab5a860,0x1b1c642e,
  57516. 0x06e54b6d,0x5e1e2a05,0x10c6cf1a,0x9ba1710f,0x0f903cd0,0x334fc366,
  57517. 0x134166f5,0x969e0001,0x155c4353,0xfaa26074,0x000000fa } },
  57518. /* 54 */
  57519. { { 0x712de285,0xc85cd0e6,0x869f5dc5,0xcd2ff8b0,0xdf4ed389,0x372a2b92,
  57520. 0x55b99c84,0x63524d30,0xe07a0033,0x46fef5a2,0xd6e09493,0x0a2c82da,
  57521. 0x72a8952b,0xb3626621,0xaf217eb6,0x9afcb188,0x0000002c },
  57522. { 0x9a64c5b5,0xd3b9d476,0x44c4cfe1,0xa0d8d5de,0x11c6dbff,0x560858ef,
  57523. 0x41c14aed,0xce1d978f,0x35efe854,0x251f9e72,0x0474575d,0xf9d0c14c,
  57524. 0xbda89c03,0x0d2c838e,0x36cc9dc0,0xa25f040b,0x0000016f } },
  57525. /* 55 */
  57526. { { 0x9cad682d,0xb23d9dea,0x46369391,0x87acb1b3,0x5c0f24d7,0x9f5c1988,
  57527. 0xd41883ce,0xdff62fc7,0x53555e46,0xd1ab29df,0x891cda05,0x569b1cb2,
  57528. 0x52c633ed,0xdb14dbc4,0x2a345428,0x1acbb86c,0x00000194 },
  57529. { 0x24db8127,0xd86a70c8,0x41b7cf5b,0x84a6563f,0xb908d9b4,0x8d84dabe,
  57530. 0x899c260a,0xaaeaae63,0x44436957,0x13ed6b2b,0xd0a92c8d,0x3bc94f99,
  57531. 0xd04bcb97,0x978f2e2b,0x716a565f,0x56a388ef,0x00000074 } },
  57532. /* 56 */
  57533. { { 0x96fc1f77,0x6082dfe4,0x1347ad6a,0xb04c435f,0x25ebe457,0xf42694dc,
  57534. 0xb6f764aa,0x64a17069,0x04d83da1,0xe03873d5,0xe0c82330,0xb0b9db52,
  57535. 0xd4239b3e,0x9886b34e,0x598814da,0x76587f2a,0x0000016a },
  57536. { 0xebc71a5d,0x6918f8e8,0x85405233,0x49141a42,0xc182cbcc,0xd63f09cc,
  57537. 0xe09057a7,0x4afe59d3,0xe239d8eb,0xe633db0d,0xfd9494b2,0xbac8582d,
  57538. 0x4704fd61,0x8b915a41,0xfceaefd9,0xe0866a9d,0x0000010e } },
  57539. /* 57 */
  57540. { { 0x52e07a4d,0x2b50c470,0xe5d745d0,0x7f6d38b8,0xe1af1226,0xb414c47c,
  57541. 0x39c505f7,0x03e4b44b,0x86f739be,0x59f3d795,0xe7c2f1bc,0xca19bca7,
  57542. 0xc063fad4,0x1c51c01e,0x7f428afb,0xda3937a5,0x00000080 },
  57543. { 0x102369fa,0xe9d8ca9d,0x706c0e35,0xe009bffb,0x96b55d80,0x2e0a19a7,
  57544. 0xac0d094c,0xda0e42de,0x787c187a,0x6c1be2c5,0x9cfa04b6,0x6d4ae2cc,
  57545. 0x76577340,0x5b0cea60,0xc7c96285,0x2d525245,0x000000d8 } },
  57546. /* 58 */
  57547. { { 0xae93de69,0x6dcb238c,0x3bfdae9b,0x4963c833,0xe8b79836,0x33c81f4d,
  57548. 0xae8bf8ae,0xe13a2244,0x4c3ebacc,0x0bc6e786,0x555a5ad6,0xa837a53c,
  57549. 0xbc7e9459,0x875d8d35,0xf9f46fcd,0xb3705534,0x0000001f },
  57550. { 0x7fb974a1,0x78e9270c,0xe9ed2481,0x23448fa0,0x64bffbd4,0x14166c3d,
  57551. 0xd79f4b3c,0xa05aa443,0x3b9f32a0,0xd855a4f1,0xac90235e,0x4bebcf8d,
  57552. 0x8db52b48,0x65849987,0xe48d09d1,0xaa4d59f1,0x00000183 } },
  57553. /* 59 */
  57554. { { 0xdbffad9f,0xee585d75,0xf419d8fc,0x64df6174,0xe6c69345,0x6f73bf59,
  57555. 0x83d59b0c,0xb80793d1,0x929c8950,0x6baf4fc3,0x29962bab,0xbd445a95,
  57556. 0xeaa91273,0x52b61945,0x3d1c785b,0x4fccdfff,0x000001be },
  57557. { 0x7cb2857f,0x05c384d9,0x06b7abf4,0x4cf83058,0x43ace6b2,0xf528dd17,
  57558. 0xbc43d6b6,0x2c7b8fa2,0x14e564b9,0x8f0e28bf,0xd2b9f01a,0x1b69bc73,
  57559. 0x3dd383e6,0xab8beb40,0x9791946b,0xaccea0c5,0x000000ae } },
  57560. /* 60 */
  57561. { { 0x0163c2de,0x9a68baee,0xeb2768a4,0xc42d0b2b,0xffdae767,0x5686f124,
  57562. 0x0aaca943,0x926da5d5,0xe01091cf,0x699c34ce,0x5324becd,0x3d254540,
  57563. 0x4193a0a9,0x1b6b58f1,0xd611cc9d,0xf144925e,0x0000014f },
  57564. { 0xc1ed9259,0x7f61a60c,0x2f1d5a7f,0x1be37aa3,0x07aef431,0x0384713d,
  57565. 0x4e6fa7ba,0x99f33d49,0x8bd3730c,0x43928c16,0x5b9557dc,0x73cf8ccf,
  57566. 0xd1a2bee5,0x0bc6d460,0x83b15610,0x27cd1943,0x00000145 } },
  57567. /* 61 */
  57568. { { 0x3427af4e,0x4be65135,0x310d937d,0x2e6c0bb1,0xcaa671c3,0xbd8ea76a,
  57569. 0xd3a9c376,0x9d7b3fd4,0x471709aa,0x124ce863,0x018051c0,0x225ce41d,
  57570. 0xf9e8ee1c,0x5489284f,0x535c4ec8,0x22d829c9,0x0000013d },
  57571. { 0xa1b15e02,0x6b01ed9d,0x301e5868,0x1d092bac,0x5764135b,0xbfa7a183,
  57572. 0x6f7159a4,0xc0ee59b7,0x18090d0d,0x9171a051,0xb8052196,0x5c1531bb,
  57573. 0x20927904,0x740930fc,0x76337685,0x963b48cc,0x00000008 } },
  57574. /* 62 */
  57575. { { 0xf4aaaed5,0x0fe8b620,0xfe871ee8,0x1068de7d,0xfebfcb4b,0x2b22030f,
  57576. 0xc3a2155b,0xd4dfbee7,0x2769b805,0xa7a26a8c,0x6d39eaf0,0x377de770,
  57577. 0xf615f032,0xf1a92447,0x42d9b731,0xa1b81a84,0x0000012a },
  57578. { 0xb1152e8f,0x299e67d0,0x92b5e14c,0x2e773d97,0xf1cb57a2,0xe0d81073,
  57579. 0xbf1da4a2,0x03af0a9c,0xc22b449a,0x169b160e,0xdd2d7d1d,0xb82c1ac8,
  57580. 0xbfc98ee4,0x7508aca6,0xe3cbea15,0x54992440,0x00000150 } },
  57581. /* 63 */
  57582. { { 0xa13a4602,0x70004a0a,0xd0d2c60e,0x505c71a3,0xa6d79bc5,0xa4fe2463,
  57583. 0xd54d9df4,0xe878eb3a,0x73d3c7b8,0x7ecca907,0x244ecfa5,0x5b3bb278,
  57584. 0xb124d179,0x8a30f61f,0x4f632af0,0x5b7e5001,0x00000115 },
  57585. { 0x9ef0021a,0x62c42ecc,0xf856c9d4,0x58017fd7,0x2e6478bc,0x10e243b8,
  57586. 0x1505a4db,0xaf074669,0x4cd7eea5,0xd9bb0a1c,0xd52aed0a,0xe8ba39a2,
  57587. 0xb549f09d,0x0747449a,0x9e57fa64,0xd5c8f7bd,0x0000013f } },
  57588. /* 64 */
  57589. { { 0x5a53c22b,0x1bd8ce7b,0x7cab446a,0x78733fcd,0x48acb394,0xc44ca4e2,
  57590. 0xa38c790f,0xa9888b1e,0x15c34237,0x36afb6eb,0xfb702063,0xb913b8a8,
  57591. 0x917508fa,0x34b77cc5,0xf9e4732b,0xa931d7a7,0x00000050 },
  57592. { 0x56d21d18,0xa90a4290,0x55b410a1,0x82666307,0x894a6b05,0xb4684a8b,
  57593. 0x828cf75c,0x8a1ade63,0x127702a3,0x4fb2f85a,0xadf7b709,0x83ff7d05,
  57594. 0xa68d1db6,0x1d3f5a92,0xc093cd5c,0x243ce1db,0x000000f5 } },
  57595. /* 65 */
  57596. { { 0xd37d7891,0x8fc183c3,0xfd865eca,0x17b50149,0x8f218441,0x0f6e43d6,
  57597. 0x5a07f658,0xaf51ec25,0xad303202,0x8fe5a6cb,0x10676ef5,0x95de68f3,
  57598. 0xca4e000c,0x7508e31f,0x77735254,0x783e5a95,0x00000159 },
  57599. { 0x2e537ad9,0xbc1db571,0x35be9cf7,0x5e87112d,0xd57f9bcb,0xbb522b48,
  57600. 0xa8b3cbc7,0x1eff7890,0xe5ecdb5c,0x4f306e11,0x3387e7ed,0x30da8392,
  57601. 0x72321e3d,0x4d91fcf4,0xe412a67c,0x8487bb62,0x0000009f } },
  57602. /* 66 */
  57603. { { 0x8cb8e08e,0x86f5f80f,0x2496fed6,0x7cfd2c41,0x60b7dcdf,0x0061b743,
  57604. 0x57f4d05f,0x4dbaffdf,0x458061f2,0xb1993c2a,0x9de994c4,0x6c6ca8d0,
  57605. 0x2747e062,0xef70d24d,0xb9995cbc,0xd4e5d4e3,0x000000ff },
  57606. { 0xc6f40077,0x3171e245,0x0723e506,0x1592e045,0x6a6bfd88,0x35c86f7e,
  57607. 0x6d9d9ce0,0xba0959d1,0x3eb5770c,0x2e7f8fe8,0xc40d63dd,0x58eb0881,
  57608. 0xeb9e4419,0x56333bda,0x3afd1f4d,0xfb0397df,0x00000034 } },
  57609. /* 67 */
  57610. { { 0xb358815c,0x7b84e05e,0xe41087d9,0x3abcb2d4,0x07f05d7a,0x87a75889,
  57611. 0x7a9d481c,0x350778d5,0x42d64cbd,0x9d34cff8,0xccf289fe,0x0859cd5a,
  57612. 0xdd2b2c6e,0x8372d591,0x18b40b62,0xc06d482e,0x0000006b },
  57613. { 0xda4ed375,0xd10695a0,0x298daaea,0x51baf588,0xf4b7092c,0xb028a1b4,
  57614. 0x7a335b35,0x8ab87dae,0x0567efd8,0xa7359362,0x3320c374,0x7a49fc10,
  57615. 0xa3558b30,0x737acac4,0x4c0fce9b,0xd30696a3,0x0000001e } },
  57616. /* 68 */
  57617. { { 0xbd3902fe,0xd9550ab0,0x86a9d3b3,0x9bba4b4b,0x975cac37,0x3a59e0a9,
  57618. 0x333605dc,0x045e8731,0x1afc2c58,0xf2c598c2,0xeef9cbf1,0x81ff8d6f,
  57619. 0x9bf83c42,0x82bed5d0,0x528131d5,0x9d1d9d5b,0x00000157 },
  57620. { 0x5519258e,0x687da305,0x027de2a8,0x73f539f9,0xd6a230d6,0x69fa9747,
  57621. 0x5f5d1684,0xab1aeb23,0x5f7e41f5,0x5bbfe947,0x16a7feb3,0xbd546abb,
  57622. 0xe16d5187,0x2afbd4e8,0xbcc953dd,0x7437be13,0x00000160 } },
  57623. /* 69 */
  57624. { { 0xee9755a3,0x55f165a9,0xb82c9ab1,0x0c8d5a1a,0xab6b97e6,0x65a1e45a,
  57625. 0xab05e271,0x3004cdb0,0x6db0830f,0x9e0c3b52,0x75acbdeb,0xaae1ec1a,
  57626. 0x761e8498,0x413d4484,0xb1b9c62e,0x589e09bb,0x000001e9 },
  57627. { 0x9c72258d,0x67512081,0x5c1593d4,0x61dcd734,0x91c11fdb,0x6c627a7b,
  57628. 0x8857908e,0xd1d3e9bf,0x530bc68e,0x9aac06fe,0x6b5b44ff,0x125c16bb,
  57629. 0xdb90edd5,0x38860bb6,0xfbbedb5c,0x96fe8b08,0x000001aa } },
  57630. /* 70 */
  57631. { { 0xf257c0f8,0x323a5dd8,0xdd3a10d9,0x4884dc92,0xbbb8ce03,0x03f379ce,
  57632. 0xa47262a9,0x6217ad53,0x52e06c6d,0xa1df2017,0xc32428cd,0xf5b723e0,
  57633. 0x2c30c62c,0x1e5d3889,0x477f82cc,0xd9a90f1f,0x000001fd },
  57634. { 0x1763ab59,0x830d27ba,0x723783e9,0xcf27d93e,0x945968aa,0x81558264,
  57635. 0x1700d5d5,0x63251a32,0x03146d9f,0xcf6bbe73,0xe65bf0f2,0x6cdcf455,
  57636. 0x632323fb,0x80aa00ce,0xd96a4744,0x6e49e62c,0x00000149 } },
  57637. /* 71 */
  57638. { { 0x40574c09,0xbeff0b7e,0x3fe80e96,0xb76f2643,0xeb237d91,0x0b3bd352,
  57639. 0x7edc3102,0x3c0c62b7,0x424a36dc,0xf989394b,0x7c6c435e,0xe9ea64c2,
  57640. 0xe388d076,0x2dfc21c4,0xa4e69e4b,0xcc3852f6,0x00000139 },
  57641. { 0xbb096b91,0x5238a3ff,0x73d8d43e,0xee72c9e5,0x8c577558,0xc116db11,
  57642. 0xdc47d4b4,0x54ec89d2,0x42e1955f,0x2006dd35,0x7437475c,0x004aed6a,
  57643. 0x2bee9041,0xc1ddc32a,0xed9332c9,0x597417a2,0x000001fb } },
  57644. /* 72 */
  57645. { { 0x859bae66,0x3c0f1981,0x845d7c1b,0xab48e9b1,0x452a3c1e,0xc6ce9c03,
  57646. 0xff810339,0x2384a00c,0x5f98d6fe,0xcd7ede11,0x38a0dd5b,0xf7a00e3d,
  57647. 0x3c7e1c06,0x56dd948a,0x8e53a61f,0x9d21a7d1,0x000000d0 },
  57648. { 0x880eb3fb,0xf9cfdbaf,0x5e83f7c9,0x64cfd297,0xa28a74b4,0x61ba7d6f,
  57649. 0xdfb13e03,0xb8200d5f,0x232a6128,0x03bc8f4b,0x81a8d86e,0xd1fb92c2,
  57650. 0x706d6ea7,0x68675fae,0xefab18c2,0x9b08608a,0x0000011d } },
  57651. /* 73 */
  57652. { { 0xbbd2f539,0x17cf6146,0x76e26ba2,0x96052fc0,0xd4be4a67,0x36821d18,
  57653. 0x9f3f39a8,0x8f823422,0x433f873a,0x68b846b9,0x716f4568,0x7a1d3f36,
  57654. 0x2fd47750,0xdf603e28,0x6975e226,0x77cb02c5,0x00000003 },
  57655. { 0x8c01dd59,0xf275add3,0xb9c1a37a,0x9c213a9e,0x4dfc5403,0x690ad104,
  57656. 0x07ee0d86,0x202ee206,0x661fc40e,0x896ede95,0xd0b02f56,0x6b4d7398,
  57657. 0xe5af1a24,0xccb96991,0xc13f7125,0xd5c281af,0x0000009f } },
  57658. /* 74 */
  57659. { { 0xd7073a5a,0xc858c54b,0x861eac7d,0x87c81a5c,0xe720201a,0x51f84a39,
  57660. 0x40e003ce,0x952a9f8e,0x58f199de,0x76bdc4ab,0xd56cc02b,0x1cf12322,
  57661. 0x83f162f3,0xb6634e63,0x8f969e11,0x84c017ee,0x00000169 },
  57662. { 0x5c89f1fa,0xf1f43362,0xb697b078,0x4a02a630,0x4b05b7f4,0x33311e5c,
  57663. 0x4fede4cc,0xa7ccae51,0x4b025aa4,0x0d26e874,0xf84db7ad,0x7d5b77bb,
  57664. 0xf571c1fe,0x39ef1aa8,0x418ccd20,0x65eba928,0x0000018d } },
  57665. /* 75 */
  57666. { { 0x8abb2537,0xa37866ab,0x65b3096f,0x14ac4cbb,0x2a428ad3,0x827fa7ed,
  57667. 0x10e9e196,0x95d19f62,0x89801b4e,0x31eb97a0,0xaae8b823,0xaae77a62,
  57668. 0x5f5c9642,0x9693d62a,0x3e368b84,0xff5bfe97,0x000000ad },
  57669. { 0x492b0dee,0xa3efae21,0x9602c2ce,0x2143e9ee,0x6f3b99e5,0x21367c99,
  57670. 0xe93b8f59,0xdd78b2b0,0x1064c13e,0x8d541c38,0xf5738e7a,0xe6b970da,
  57671. 0x8373b1a4,0xaf6ecc16,0x74ae208f,0xdbfa3f4f,0x00000180 } },
  57672. /* 76 */
  57673. { { 0x907a6aa0,0xb024621a,0x407879f6,0xef56cb68,0x8168a934,0x44c38b68,
  57674. 0x9b9a9048,0x70d638d3,0x82541f20,0x6968caa0,0x1fc88b50,0x0c597053,
  57675. 0xaf635784,0x5564ded5,0xc4d494cf,0xe7e898c7,0x00000097 },
  57676. { 0x6b6ebb2f,0xe1dc98d9,0x7aa9e126,0x292a17fc,0xfa2a2c68,0xb60f0fdb,
  57677. 0xb2e1851b,0x9c63270c,0x81ca4cfe,0x898db265,0xb11959d5,0x94082638,
  57678. 0xa54b8d19,0xe44f308e,0x44e63094,0x96399eb8,0x000000d6 } },
  57679. /* 77 */
  57680. { { 0xb83769ee,0xfa00f362,0x3efc4cb3,0x72d040ac,0x57abd687,0xc3933889,
  57681. 0x940a7128,0x62264425,0xec242a31,0x909c4c8f,0x65a1a551,0xd1e48f1e,
  57682. 0x049c2172,0x68bd70f1,0x709b7fd4,0xc8692d2b,0x00000041 },
  57683. { 0xdf816784,0x4e388aa1,0x01be75ce,0x4a58c8a5,0x02a67812,0x9b49dffb,
  57684. 0xeda721e0,0xa73299e0,0xe67a65ec,0x8a0bd1f5,0x856c71b6,0xd81e91e8,
  57685. 0xc005aa30,0x37aee2f4,0x0595bbf2,0xd9400750,0x00000073 } },
  57686. /* 78 */
  57687. { { 0x010c0ef3,0xa912ac4a,0x4e81b1a0,0x0e654bd8,0x4f353509,0x8f0563dc,
  57688. 0xb47d189a,0x10dc41f3,0xf238c09c,0x122edd06,0xc41acf67,0x224c16af,
  57689. 0x83758520,0x1ccb9334,0x2275ae6f,0x1a4b5f29,0x00000127 },
  57690. { 0x3ce688b5,0x792fd473,0xdca9c68b,0x14566d37,0x541711d0,0xfce9326e,
  57691. 0x3cc341a8,0xe3ba14ee,0x2122c11f,0x6b8ab4cc,0xf5d379b5,0xc0fa763b,
  57692. 0xf1522f91,0x95e2d2ae,0x31cf95a5,0xd4e21b3d,0x000000ac } },
  57693. /* 79 */
  57694. { { 0x1d8e061a,0x4013a779,0xacc84a30,0x62707e70,0xeb2f636a,0x6ac08266,
  57695. 0x77b25c9d,0xe917ea21,0x70ff35cf,0xddb78bbd,0x041898be,0x5008db2b,
  57696. 0xce0ae445,0x0f58a4fc,0x2257d0e7,0xed092397,0x00000043 },
  57697. { 0xe2e129e6,0x2cad77b3,0x0f1be4d7,0xfb8c4a87,0x20056333,0xaee50dff,
  57698. 0x2a691543,0xbc2658c1,0xb8fe2640,0x95dc0cca,0x1965a0af,0x694eb584,
  57699. 0xedd1d99e,0x7d3baa53,0x8a1edc87,0x2df13b20,0x00000083 } },
  57700. /* 80 */
  57701. { { 0xd181c3f2,0xfead2247,0xf337b23f,0x915d35be,0x74890672,0xdb4cfcba,
  57702. 0xfda7a3a1,0xe4f70d8f,0x79275686,0x226b6419,0x6ff1f79e,0xe8040863,
  57703. 0xcf5fa4e8,0x98e84b39,0xd8a09f60,0x57aa0be9,0x000000da },
  57704. { 0x4efcea66,0xd40cecf5,0xafc76fae,0x98df2aec,0xc91585a8,0x63f19a48,
  57705. 0x13f00aa5,0xb111bda7,0x44b5cb9f,0x6687afab,0x652620d1,0xc6d5fb12,
  57706. 0xbacb35ab,0xaf953f1b,0xff94c4d2,0x99709370,0x000000ed } },
  57707. /* 81 */
  57708. { { 0x68b54c89,0xac9f56e0,0xce737c22,0x08ecc17d,0xab089b53,0x208ee83f,
  57709. 0x543fbd1b,0xb0f3a129,0x844dd706,0x1b204cf8,0xdec2e40d,0x80975c89,
  57710. 0x9399914a,0x08b011ae,0x74674df7,0x6b4ba170,0x00000017 },
  57711. { 0x8fdfc175,0x71216ea9,0x7e0f5b0c,0x77b7fc63,0xceb33a34,0x88d0285f,
  57712. 0x0223eab7,0xb679814f,0x51c6d922,0x9078720b,0x9c13f51d,0x5859d5a4,
  57713. 0xfaed60b5,0xe69f850b,0x6d0ccab2,0x2499a844,0x0000005c } },
  57714. /* 82 */
  57715. { { 0x73e7bcf1,0x41d581fb,0xdd3c17be,0x16dde61c,0xfa199fd9,0xc62997ec,
  57716. 0xc159db97,0x1a758873,0x64132830,0x4ed77896,0x2942a918,0x9672ce89,
  57717. 0x816ba4bb,0xf3ee4587,0xce54dd7f,0x4fb7a148,0x00000123 },
  57718. { 0xf009be8c,0xf05d80af,0x78df1ba1,0x62e938d7,0x312de620,0xa7e22e84,
  57719. 0x6070c4b9,0x48d29e7f,0xa1b5da37,0x5cd9c3eb,0xa4717453,0x1e51bd2f,
  57720. 0x56ab9e67,0x94098ab0,0x49f7c6a1,0xbb584abc,0x00000049 } },
  57721. /* 83 */
  57722. { { 0x1ea470f7,0xa9f25530,0xe9254e30,0xa01bf808,0x71a0038d,0x098569ea,
  57723. 0x5913ca87,0x0d2b2ee1,0xb8281fdb,0xae17004b,0x118e5c2a,0xdb5c6eb0,
  57724. 0x1fa943ab,0xa56ac64c,0x1a92d501,0x1aaf6477,0x00000053 },
  57725. { 0x06345730,0x9679ef49,0x846f37c2,0x946aaa4e,0x1a7c3aab,0xf81726b0,
  57726. 0x8166df4e,0xcb808da2,0x4e04dc3e,0xe9fb3fc2,0x76ec19b4,0x9e0b61db,
  57727. 0xeed6d13e,0x6e7f665e,0x86a75384,0x70ed8c07,0x000000e5 } },
  57728. /* 84 */
  57729. { { 0x108ce13f,0x66456e58,0x0e397813,0xb5bfc58d,0xea3949e9,0x04b6a84b,
  57730. 0x75af667d,0xea9b66bc,0xa891566b,0x7cb4d6dc,0xbf61595a,0x1b3cecf0,
  57731. 0x002e2520,0x4312c73d,0x6135a5fa,0x81d76898,0x0000014b },
  57732. { 0x841078ec,0x4047bc25,0x179c454d,0x75aa9c96,0x4851f8fc,0x6a160609,
  57733. 0xce34091f,0x998d4e3e,0x88e54102,0x9a9f6704,0x5da8ac5e,0xbf280f88,
  57734. 0x8fec230c,0xc64caca0,0x5094b775,0x0ac864b0,0x0000002b } },
  57735. /* 85 */
  57736. { { 0x8f5daf7f,0x6b606e39,0x10927506,0x48385489,0x08c58a72,0xa2255c5c,
  57737. 0xc90f3ee3,0x2f362fd0,0x08795f02,0xc9633af4,0x0425f5aa,0x71710bd1,
  57738. 0xec06dbfb,0xc2017e05,0xc1b8bbcd,0xd9c7dc82,0x000001c8 },
  57739. { 0x18b8bed9,0x7db41fdf,0xe3a23125,0xe9483308,0x7291c4bb,0xbcf91de7,
  57740. 0x41448aaf,0x9b0b972b,0xc44da462,0x95dfc633,0x01bf50a2,0x90b9c463,
  57741. 0x869e3131,0x18b66f77,0x121baad9,0xa8a4e2fa,0x000000f5 } },
  57742. /* 86 */
  57743. { { 0xca0251ea,0x8ca55109,0x27a6c9b0,0xf2aeed8b,0x5620f528,0x901a8beb,
  57744. 0xae13fc56,0x9a8421e8,0x85993c07,0x1349f1c4,0x0d1ab0d7,0x29e08359,
  57745. 0xaeb5d909,0x96e2929b,0xf599a66f,0x96c2f1f8,0x000000ce },
  57746. { 0x12be8bd7,0xe4bc4b51,0x3c67e99b,0xf4846a0f,0x4d3a3864,0xd89cc7d3,
  57747. 0x73f43981,0x1f647112,0x26dce567,0xc32bc324,0xf02b096b,0xf7134ebf,
  57748. 0x0d0682b7,0x5604f00b,0xe3ce8b59,0xfd23d7ea,0x0000011c } },
  57749. /* 87 */
  57750. { { 0xa27689a6,0xf89646cc,0x5564172b,0xd6a7dc43,0xb57cbfcc,0x30bda48e,
  57751. 0x5b1adfe5,0x9b11fffb,0x711d8bf4,0x9f2d80db,0xb70e5a5b,0xe879fdf0,
  57752. 0x6bd18a1d,0x97534183,0x8cbfd504,0xc8c526bd,0x00000114 },
  57753. { 0xef7388bd,0xd5fe725b,0xe7ffaea7,0xf1c3dbdf,0x7e6de2ac,0x78395b89,
  57754. 0x9ebf1bfb,0x81a72c9a,0x69785146,0x65265707,0xf52670af,0x3925ecd9,
  57755. 0x83d57d48,0x437bcdd2,0xc80ecb02,0xb5d732a7,0x000001ce } },
  57756. /* 88 */
  57757. { { 0xcfd376d7,0xa7f9fcce,0xa66b084d,0x6b4eab3e,0xd5b91bd8,0x6ac90d08,
  57758. 0x8aa304d8,0xaa3d5b7e,0x7f866a4f,0x27f3d42b,0xbb813ae1,0x95d19fa8,
  57759. 0xe34a9206,0xd38798d7,0xa32c1cdd,0xdf7c0a69,0x00000073 },
  57760. { 0x38315b16,0xbe2c01bb,0x9e18c8f9,0x1daa7c89,0x08b6b853,0xa3d43fb4,
  57761. 0x68092a81,0xb159e48c,0x836faad4,0x77e93d9e,0xa4699730,0xd4ed6361,
  57762. 0x6297e476,0x569cb3f6,0xe7811fa6,0xb69d8183,0x00000185 } },
  57763. /* 89 */
  57764. { { 0xab9cb764,0x18f27eb3,0x8ebc1d6d,0xbbbefc21,0x0479aa79,0x47760ddb,
  57765. 0x09e542f5,0xb4d16d24,0xbc699b96,0xe35c38d1,0x8c8d8c8a,0x13b2ae25,
  57766. 0x67a3a45d,0x8579c152,0x6c554c04,0x773b7357,0x000000d9 },
  57767. { 0x0218c299,0x9620a473,0x99f78a33,0x69be29b3,0x484f414f,0x4684a009,
  57768. 0x9a2ca4d4,0xb2c74937,0x68db7ab3,0x09c0773e,0x935c357f,0x6181f059,
  57769. 0x8b7de3f2,0x0931303d,0xe0fb6e08,0xf3effcd0,0x00000060 } },
  57770. /* 90 */
  57771. { { 0xb25d6530,0x723c14be,0x9a97d40f,0x5e015b39,0xfbf7f622,0x209c3c4b,
  57772. 0x14b4f0f1,0x83d8c59c,0x3f7e8ecf,0xcf002fde,0x1eb1ef0f,0x35d353c9,
  57773. 0x201f0c60,0x394c42a5,0x7be8ee34,0x787128ab,0x000001b5 },
  57774. { 0xb70110cd,0xa0937d3a,0x477911b5,0xe0fa4efc,0xc53a4c19,0xc6acaf5b,
  57775. 0x38d509f2,0xbd3010f3,0xe54ac1c6,0x3ee2a82b,0xe4f2a3bf,0x31ea67c3,
  57776. 0xf089c7b9,0x7a4ca66e,0x34a2362f,0x5bda2c4f,0x000000b0 } },
  57777. /* 91 */
  57778. { { 0xd1f575cd,0xb424a071,0xa5237182,0x15693b01,0x9a2c9d40,0x14133602,
  57779. 0x9c914a60,0x50c4348b,0x095b31c1,0x9024573d,0x22fd4962,0x6f975fd2,
  57780. 0xe210b277,0xa1704886,0x6dba937b,0xac29b813,0x000001f6 },
  57781. { 0x775da491,0x09edef55,0x2b6aad82,0x25953f9e,0x1bb40d5b,0x6696a106,
  57782. 0x4d5127d8,0xcfc45311,0x81ead062,0x2f21dca9,0xaf3b7123,0x3f3e4f07,
  57783. 0x9646f20d,0x12cd06b8,0x6910f5bb,0x24136369,0x0000015e } },
  57784. /* 92 */
  57785. { { 0x3ecfc44e,0x0c844fd0,0x5043b3d5,0x4095f2c8,0xc9bd059a,0x9a5fe7db,
  57786. 0xf65becdf,0x239328fa,0xa67961cd,0xe3102471,0xbbb5dfdd,0xea9e39bf,
  57787. 0x133dc5ba,0x8022b6d0,0x5f12c379,0xbed7aa9b,0x00000141 },
  57788. { 0xfd94d941,0x096f0059,0x7d4ff018,0xfc6e9f00,0x779f05e3,0xe63af598,
  57789. 0x00483c99,0x4c40f0b3,0x72a19870,0x04d2feef,0x464a4a71,0xdb773b5b,
  57790. 0x49367f1e,0x00b6770f,0x2a9fbd2a,0x4f7e0301,0x00000169 } },
  57791. /* 93 */
  57792. { { 0x8a9095fd,0x0df5dd73,0xd3ce857a,0xc4b7a021,0xe5edc767,0x90aa796b,
  57793. 0x180a0808,0x56497eff,0x66f10aab,0xb9856e1f,0x39879766,0x31298824,
  57794. 0x3ba80601,0x61748cf7,0x555da929,0x07d9076c,0x00000012 },
  57795. { 0x1c44394d,0x0b049a01,0x0ce49e45,0xf5f25ef7,0xb1694265,0x1e3a09f0,
  57796. 0x109b33f8,0x2c5bd9fe,0xa30932e4,0x07f2a43f,0xc6cf8af2,0x736abfca,
  57797. 0xf3366722,0xadf7fa04,0xfa9d26b0,0x2f1e92fb,0x000000e0 } },
  57798. /* 94 */
  57799. { { 0x63be4d4a,0x9524e4a6,0x66f3cc91,0x1fa57bed,0x7e7a7ccd,0xdd7c93fa,
  57800. 0x88c5d1d3,0x70e8cf6a,0x3f251f1e,0xb257997a,0xe3554cf5,0x0a5ec58e,
  57801. 0x065a7109,0x68d268d7,0x085089ea,0x7c23d4d2,0x0000004c },
  57802. { 0xbd52d132,0x63ae575b,0x38c81cc5,0x0fb8daa7,0xe4e63b99,0x096a6e51,
  57803. 0xb239d387,0x51d6b366,0xa5d49fed,0xed5f8874,0x43a8c07a,0x025091d9,
  57804. 0xe4686ae2,0x100f845a,0x7eb4ef5a,0x1af59d74,0x000001c2 } },
  57805. /* 95 */
  57806. { { 0xdd441308,0x5f7bc01e,0x86308890,0x0dc34944,0x759611cd,0x2af38a74,
  57807. 0x4c23ce66,0x11a71261,0xf8bafed2,0x37f317b5,0x4c93e079,0x4efbb9ff,
  57808. 0x8ecc52cf,0x880f0edd,0xddc9d82a,0x480cdd2c,0x00000028 },
  57809. { 0xc3f807ac,0xe8f1ca0d,0xbd070549,0x6a3e4fc2,0x91f8bb6c,0xad3d0a14,
  57810. 0x3d6dfacd,0xe3ee1cfd,0x5fb46ffb,0xee46b1b9,0x7dd5cfbc,0x5207b3ac,
  57811. 0xb1b8e8b7,0xd580c0d9,0xc7bdd11a,0x52c669f4,0x00000084 } },
  57812. /* 96 */
  57813. { { 0xc0ace6d5,0xa42b4747,0xbe7287ad,0xd5acb64b,0x89bc2614,0xf3304899,
  57814. 0xff05c71e,0x817fe836,0xd35ac450,0x772eb246,0x375a9c3c,0x7f5fc216,
  57815. 0xcbc0d6fd,0xfb6f9e1a,0x720e9733,0x7643c315,0x0000009a },
  57816. { 0xf3845ccf,0x4b2216b4,0x90bc05bd,0x9c174e80,0xd6049037,0x7a550c74,
  57817. 0x6358c806,0xbd7220a1,0xaa677b6d,0x838f9c41,0x66e2e08e,0x37332c19,
  57818. 0x496f6da5,0xb032875e,0x9c30630d,0x52b274cf,0x0000000c } },
  57819. /* 97 */
  57820. { { 0x8ea58beb,0x6ec2e782,0x3665fa48,0x2b404c1d,0x20b40ff0,0x546d5fad,
  57821. 0x29d3e6a5,0xfb5df7b6,0x66c81991,0xf186846d,0x6e2cfe3e,0xbe690bde,
  57822. 0x1410d16b,0x97aeb9a0,0xbacc8e92,0x59d81548,0x000000cb },
  57823. { 0xbaf66a23,0xd905d3ad,0x40dfb081,0xc3337387,0x4b00f432,0x6d5535de,
  57824. 0x07d3a03e,0xe17fe8e8,0x066bca80,0x29544ff7,0xbadffa55,0x60c2b96c,
  57825. 0x45a26ea4,0x9f018d94,0x24a34ffc,0xd5438167,0x0000011e } },
  57826. /* 98 */
  57827. { { 0xbd7f8a61,0x62a873fb,0xbbe580bb,0x5e18cd71,0x667f6980,0xfd5c9eb3,
  57828. 0x571d3dc0,0xab8d4f61,0x783f9bc8,0xe2e45215,0x24398b14,0x36c3774b,
  57829. 0x74d811b5,0x2db4a363,0x2debe3c3,0x9f7f1297,0x00000138 },
  57830. { 0x798fefb2,0xbb97f21c,0x107baa72,0x9c76fcb5,0xfadbb568,0x12fbf760,
  57831. 0xd33ea6c5,0x1a648be7,0x236134a5,0x412a2993,0x8985893b,0x4a3d8169,
  57832. 0x3e66ada4,0x6144958f,0x7687b457,0xb4dfc79b,0x00000140 } },
  57833. /* 99 */
  57834. { { 0x7abe5bb9,0x83b14570,0xe51d81be,0xae0cbfd8,0xc9827aff,0x20dadf49,
  57835. 0xa687b554,0xc3a72548,0xeeb41733,0x080263fb,0xd3827c63,0x7014fdc3,
  57836. 0xb5e3b70e,0x7d018f84,0xfbcf7168,0x1d483e00,0x00000015 },
  57837. { 0x6b578aa3,0x154e3c7c,0xd3043dae,0x511ce9b5,0xb6008101,0x55f89e9b,
  57838. 0xf405ac6f,0x4ec31112,0x2008ac7b,0x7e66a4d8,0x25c52fa6,0x73c00d39,
  57839. 0x8acac2eb,0xee1b9998,0x60b57453,0xdfa31d95,0x0000008f } },
  57840. /* 100 */
  57841. { { 0x251cf8d8,0xcc74a0e0,0x041f2bd2,0xd4d8949d,0x33ebce52,0x0b734a49,
  57842. 0x5c5bcdae,0xe1ac5f51,0x16200b93,0xd3ecdfcc,0xa793736e,0x2506a266,
  57843. 0xea6e6940,0x585a1c8b,0x9190f935,0x081cdd53,0x0000000e },
  57844. { 0x53e28412,0x055f9956,0xdb27164b,0x0d1526f2,0x1df3adc7,0xcd5625eb,
  57845. 0xdd35dedd,0xd2c453ca,0xa838ffe2,0xed442849,0x5c0ce589,0xad20c137,
  57846. 0xbd99b609,0x2d5fba81,0x622efb07,0x5be41dcc,0x000001ad } },
  57847. /* 101 */
  57848. { { 0x8f850756,0x563af667,0x52f3b597,0x86d37aae,0x796842f5,0x10d38a53,
  57849. 0xf743f997,0xcdaaf99f,0x93f1a8ba,0x2fa755e5,0x409f7cd9,0x1af04e15,
  57850. 0xd6d0650b,0x63bf9a0a,0x55abfd9a,0x67b1cead,0x0000000e },
  57851. { 0xb5f43178,0x3660a8e0,0x9cc35b33,0x56bd412d,0x880f6808,0x3d7bfa63,
  57852. 0x2e622c71,0x7f372d66,0x6ff82445,0xad7b7be7,0x8db04e51,0x0f2bde80,
  57853. 0x4bd15c8d,0xe1e781fe,0xb8e502f2,0x1f475bfb,0x00000194 } },
  57854. /* 102 */
  57855. { { 0xd63543ec,0x79482bf9,0xa117ef3e,0x985cb67c,0x160ccc63,0x8ac50638,
  57856. 0x729bdc1e,0x556cbed5,0xa22686df,0xd62ed97d,0xc81eb77c,0xb124cb5f,
  57857. 0x72fa2ed9,0x4d7b4f66,0x78335b96,0x60b29aa7,0x00000172 },
  57858. { 0xa43df7c6,0x21bfc7b6,0xbc20706c,0x85acac23,0x345d9580,0xeb6f37bc,
  57859. 0xa32a08bc,0x9d8f20d2,0xd1953c5e,0xf08924f6,0xc4f680d0,0x7d25d7c6,
  57860. 0x2de9912c,0x64e6a237,0x52ce644c,0xda1c06c4,0x000000eb } },
  57861. /* 103 */
  57862. { { 0x411dd110,0x26677c5c,0x2c991c4a,0x0d6787aa,0xa45666d6,0x53be6a41,
  57863. 0xc15f9f15,0x73e716aa,0x0e0cc7b2,0xa93b863f,0x2a624ab0,0xa4057117,
  57864. 0x1a39c260,0xe5e7656e,0x2ef6f130,0xaf8d78b5,0x00000046 },
  57865. { 0x70f38dff,0x796214b1,0x123a1105,0x3e35d828,0x957ed812,0x046a44d4,
  57866. 0x0da60161,0x618fa9ba,0x54f84413,0xe7cdd2a5,0x19ea95ab,0xf1c2563e,
  57867. 0xcb2a30b4,0xc4459e14,0x61ff9aa9,0xc748add6,0x00000183 } },
  57868. /* 104 */
  57869. { { 0x9de58caf,0x32981f39,0x8753ea64,0x05bb80fd,0x2d119486,0xc83f9f24,
  57870. 0x03eeb00a,0xf490cf06,0x7c73d79c,0x4037f251,0x724d461b,0x844209fd,
  57871. 0x272420cf,0x6b03f6d2,0xb3438fa2,0x6f4bd29e,0x00000152 },
  57872. { 0xc389e51c,0x964d034a,0x6db7d98e,0xacda55e9,0xe913c583,0xb2ae97de,
  57873. 0xfeb03440,0x0793077b,0x9d461e29,0xaa16e378,0x043bf8be,0xb0a67533,
  57874. 0xba7d8c3f,0x9d749a42,0x6bb925dc,0x7c41e6d6,0x000000ec } },
  57875. /* 105 */
  57876. { { 0xc5da8398,0x2e9b345d,0xbb38c430,0xbc66841f,0x7c3bb47a,0xce3ac562,
  57877. 0x738d2cdd,0x8fbeb12b,0x68731185,0xd4bc2ad7,0xbbd4f4f4,0x9521db1c,
  57878. 0xfe4e1b0e,0x2a690cae,0x7bfebe3e,0x375215eb,0x00000194 },
  57879. { 0x2edfd661,0x4cb234f1,0xed52c1f4,0x0149984e,0xd8f8f98c,0x32d27260,
  57880. 0x7be38590,0xfe76e4e4,0x95e8b672,0x5435873d,0xf2b00e82,0x916c397f,
  57881. 0xbad61eb8,0x3b9bf705,0xae131bbe,0x7ee90182,0x00000000 } },
  57882. /* 106 */
  57883. { { 0x93fbcb5c,0xd36fea9e,0x9fa8529b,0x382be583,0xfd611ba0,0x0b243125,
  57884. 0xcd8a2637,0xa59ae37f,0x3d8d4704,0xab78c60e,0x44c41b79,0x1bac243d,
  57885. 0xeda49cc5,0xc4001fea,0x83dc7e9f,0x988ea44a,0x000000f6 },
  57886. { 0xf077f79e,0x4d90caa4,0xd9e2590d,0xf4d17601,0xd21b4b77,0x11debbb3,
  57887. 0x9037e1b6,0x031b3f60,0x135becf0,0xf113ed82,0xf2903dda,0xf6c01379,
  57888. 0xa6f19296,0x36bde7ca,0x9dbbad85,0x57d3b684,0x0000006c } },
  57889. /* 107 */
  57890. { { 0x9abfccb0,0x963fee38,0xb9676e63,0x6c6e2a24,0x84ba6d27,0xf8768f02,
  57891. 0x465853d1,0xc38ba3ba,0x1b8ab9b6,0x6e3ab36d,0x47a07331,0x01fc9742,
  57892. 0x25233f32,0xfdd41718,0xac61de7a,0x4dacfa81,0x00000021 },
  57893. { 0xeaa3198c,0x365a9f37,0xfc8b99d5,0xcbe8a345,0xd4f5ecbc,0xa427f12a,
  57894. 0x0c237514,0xe841ff60,0x28a27b05,0x5d9e8c5a,0x62859ff3,0x2d377444,
  57895. 0xea8bde37,0x1c0460ff,0x29cf5bf8,0x0a0e49a1,0x00000181 } },
  57896. /* 108 */
  57897. { { 0x45843c3e,0x688203af,0xaabebae7,0x4601e303,0x624df62b,0x397b08f3,
  57898. 0xd21e5aa8,0x5687348a,0x9a242b0e,0x2cf12c73,0x32a76c6d,0xc848ed01,
  57899. 0xf52751a2,0xb72aa1c2,0x92c02d05,0xb63296c3,0x000000f3 },
  57900. { 0xc6f3d1f0,0xce4b42ad,0x2f532b94,0x2f0dcc53,0x83443d9c,0x57813335,
  57901. 0xdc8dd9cb,0xb50118ee,0xee87192f,0x3039e1a5,0x557419c2,0x9977267d,
  57902. 0x30f96b0c,0x462efa4c,0x3cd3c35a,0x454fb796,0x000001f7 } },
  57903. /* 109 */
  57904. { { 0x9d153926,0x10f28194,0x82b57548,0x42e28c91,0x509e94c9,0x4b423b30,
  57905. 0xde9d6b57,0xc5acc52a,0x8b3ca314,0xaa746c39,0xc63d5bc5,0x0f4ea307,
  57906. 0xe1ccc989,0x425553a2,0xf76d9194,0x271198bf,0x0000008e },
  57907. { 0x3c8e672b,0xc7900e46,0x3f2dfc27,0x703675cd,0xaf2163c9,0x704951f7,
  57908. 0x7aceaab0,0x74d69908,0x7e8d2369,0x482f21a9,0x813dc115,0xdcfbc1dc,
  57909. 0x04f6cd13,0x0ce2bc80,0x82bfaff2,0x2a54662c,0x0000003f } },
  57910. /* 110 */
  57911. { { 0x1588a8bc,0x0dcf41e6,0x210c52cb,0x6f48cd0e,0x758e7a45,0x338562bd,
  57912. 0x48b9b957,0x1600d54b,0xa6b89b9e,0x461df80b,0x098cc82f,0xf7fd4f17,
  57913. 0x14977147,0x167f01cd,0x6116c5f9,0xb1338511,0x00000048 },
  57914. { 0x5d2617f0,0xdeb76333,0x6ecb8606,0x3f9a5772,0x1b91fce9,0xa93c032d,
  57915. 0x6c84b997,0xf7a4388b,0x823ca5be,0xbfe80225,0x35a32f6b,0x6f19c028,
  57916. 0xe3cb5c58,0xf26cd5ad,0x6d0c1dd9,0x7f5ddc77,0x000001e7 } },
  57917. /* 111 */
  57918. { { 0x6ee764c9,0x3c9feec8,0xb07c82cc,0xd1bec836,0xa005b142,0x6bf1b2e6,
  57919. 0x29e8a5ea,0x70ef51a3,0x3ffe241c,0x517d298e,0x72966c28,0xbb389e28,
  57920. 0x2c7acc76,0x3a2da8a9,0x732a21b5,0x902c9126,0x0000004a },
  57921. { 0x8f7ce110,0x96c51b9c,0xaeb036f1,0xdcc33a87,0x0a6a59e2,0x82695098,
  57922. 0xe78db500,0xceaf26a7,0xc95bb030,0x82f3c384,0x24c42f42,0x6dd6e9f7,
  57923. 0x70ac4a0a,0x768dde29,0x03d22efc,0x4aedce4b,0x0000016f } },
  57924. /* 112 */
  57925. { { 0xeded03c0,0x077f032a,0x588ddd4d,0x2684a052,0x9a85be0f,0x6d09bc4f,
  57926. 0xe0b9b6bb,0xbdda0c7f,0xf2fb5887,0x19689c7e,0xec3cce7e,0xf8a96960,
  57927. 0x768d2ae5,0xb043d9d5,0xdb21219a,0x29c8081b,0x00000068 },
  57928. { 0xde59f006,0x6bf872fa,0xcb97ef5a,0xc2b9ffc6,0x58ae7ef8,0x371915db,
  57929. 0xf4ccaa1f,0xc2e23ca1,0x89c27cc4,0x1af8c60e,0xc86bdcc6,0xeee5d7e7,
  57930. 0x9bd8de43,0x9225b47f,0x4b24f08b,0x53e7f463,0x000000b4 } },
  57931. /* 113 */
  57932. { { 0xe3048bda,0x54c496d0,0x43c3de4e,0xe2b67499,0x4c2d509e,0xac2049f7,
  57933. 0x543c5089,0xb01f691e,0x105a365b,0xcd9960a3,0x78b17049,0x34d93ffe,
  57934. 0xf82c9467,0x029f99b3,0x0161a755,0x785c5ea2,0x00000091 },
  57935. { 0x953dbdb6,0xb455f978,0x97eca19f,0xea9e84d9,0x36d4d75a,0x473bd029,
  57936. 0xc15276fa,0xa9c17ca8,0x47c76356,0x9cf66133,0x039738d2,0x4a68360b,
  57937. 0x69733609,0xd3e430a8,0xe2b27f21,0x0ae532de,0x000001b4 } },
  57938. /* 114 */
  57939. { { 0x5164cb8b,0x68110e82,0x2552a67d,0x6979af4f,0x8d185527,0xe10d6d0e,
  57940. 0xfb64eac4,0xcf6c5787,0xac424592,0x8408163b,0xfce0d810,0x5d8fff37,
  57941. 0xda84c15c,0x8b284e49,0x32663ec9,0xed805567,0x00000010 },
  57942. { 0x51f3ee9e,0x106f4030,0xb38adf1e,0x2e8e3ee9,0xa13d6449,0xd3c87a6e,
  57943. 0x80e1abb1,0x27b49f45,0x0bfd7298,0xc283d179,0xafc7a35f,0x8fe50fa5,
  57944. 0xade3ad4f,0x773da545,0xd9a21df2,0x78bfaae4,0x000001f8 } },
  57945. /* 115 */
  57946. { { 0xabad5678,0xae60d8e8,0xe600c25b,0x0afa72ce,0x4c288e21,0xb9d4e0b4,
  57947. 0xd254cf9f,0x64447f76,0x959e2ba5,0x1fb36bc4,0x2961132c,0x393c44d7,
  57948. 0xfc140f19,0xd7a8881f,0x8d096648,0x27a86128,0x00000091 },
  57949. { 0x8a9e690c,0xb536c021,0xeab4fa15,0x85dcc521,0xb00ee54c,0x09af4423,
  57950. 0xaf3a8e48,0xb3793525,0xb7731d85,0xe1f36308,0x141cfb55,0xb5361d78,
  57951. 0xeffc4529,0xea41f29e,0x9f7d2634,0xcf5755b1,0x000000e8 } },
  57952. /* 116 */
  57953. { { 0xd212b398,0x01edb80d,0xd53dd373,0xd0396181,0x8a52fa95,0x0e086047,
  57954. 0xa7825e6d,0xad1e6432,0x330ece4f,0xe0185bc5,0xb078936f,0x508f7313,
  57955. 0x9e7f6ea3,0x1dc982fd,0xd5556b60,0xdbf3a602,0x000000e8 },
  57956. { 0x279e05bc,0xc3763234,0xf44453d3,0x7f5f40ec,0x7fa30793,0x310c5f4d,
  57957. 0x108d7e22,0x5cffad36,0xc2a98bbc,0xf2f01ef3,0xd7d47f80,0x30ab1719,
  57958. 0xa9b22e1c,0x7bc9f918,0xe834df94,0xf53dc52a,0x000001f9 } },
  57959. /* 117 */
  57960. { { 0xc183f89b,0xf266b49e,0x5f5806d4,0xd3fb5f02,0x94ec3080,0xd30a42b5,
  57961. 0x371cd917,0x4b6b1940,0xb7f7e26d,0xf7541aab,0x2d5b7b64,0xe55269eb,
  57962. 0x7f8036c5,0x0e1a85c1,0xda5f2675,0xa0ff0f22,0x000001ce },
  57963. { 0x3a8e11f8,0x602bd56a,0xf5f9ab54,0x29864021,0x0ccc92d7,0xc6742c5a,
  57964. 0x523f650b,0xd64569e6,0xf7fabfb4,0xc8e4681b,0xc3c9e6cb,0xb4275947,
  57965. 0x38f5ff20,0x2b3952d5,0x1f04aea2,0x818f8e38,0x000001b0 } },
  57966. /* 118 */
  57967. { { 0xe50d90f0,0x3be5bffa,0xf5011cdc,0x4cb3b11b,0xa691dfac,0xe10ca711,
  57968. 0x4ea1a773,0x62ec211d,0xe586eeb6,0x5a979ebb,0xa0c2f1fd,0x4df16ab1,
  57969. 0xc57bbfea,0xfe9e3f7e,0x5ae526f6,0x1b05960e,0x0000015e },
  57970. { 0x8630e62e,0x1c8e04a5,0x6447e1b7,0x3d00310e,0x43b4447a,0xcf1e6b61,
  57971. 0x7462e7a3,0x92abb851,0x0002724d,0x8309ea08,0xe45296df,0x1d805d70,
  57972. 0x3d4ed812,0x0f3849b3,0x6834d44e,0x2d6bffbc,0x00000096 } },
  57973. /* 119 */
  57974. { { 0x48e07711,0xd13fe58d,0xd270a3b2,0x70f83648,0x8cdff04c,0x1517892d,
  57975. 0x51411f14,0x15bb6578,0x3e4f8a55,0x6c31cd90,0x0413362f,0x73f87152,
  57976. 0xeca06d4d,0x2fe025ee,0x954e317f,0x32a6e417,0x000000ad },
  57977. { 0x69d147df,0x7e38c63f,0x710bf37b,0xb69bb06e,0x28d514de,0xb94debef,
  57978. 0x8d11c3d9,0x4b2307fb,0x0385c604,0x3b369df9,0xe7800e83,0x68ea2f49,
  57979. 0x7d501c1c,0xf028b258,0x5cef7818,0x97078221,0x00000055 } },
  57980. /* 120 */
  57981. { { 0x54c1d751,0x10c351db,0xba0f9512,0x81445301,0xbfdc8bed,0xa77eb34f,
  57982. 0xcf23680a,0x498d8138,0xe04f2860,0x928c14a4,0x16a5b6da,0x96192dba,
  57983. 0x5f9a9103,0x49dea95b,0x01724102,0x80dd4578,0x00000085 },
  57984. { 0x0e09221c,0xe9072500,0xf21de056,0x62e05b21,0xe0e60950,0x448cafa1,
  57985. 0x6f775129,0x657fb97b,0xf1f34aca,0x5d2991bd,0x49ff15d6,0xa66cd5ac,
  57986. 0xd049ec79,0xdc1d6897,0xe72baea8,0x388fca84,0x00000067 } },
  57987. /* 121 */
  57988. { { 0xa6ef1dd3,0x6520b49d,0x3ba6cd76,0x391a045e,0xf33d5f48,0x9c84980a,
  57989. 0xef07474a,0xe53cf5b2,0x78bfb1ea,0xa35b2e9a,0xeda906fa,0xeca97fd6,
  57990. 0x1b9f2cf4,0xf1a93789,0x3ab28589,0x66753369,0x0000010d },
  57991. { 0x73691faf,0x5b510496,0xd57ec618,0xdc73d3a9,0x930a8525,0x7e2921bb,
  57992. 0x40b05b69,0x094f571e,0x413bedca,0x5e96a017,0x8d1a6b98,0x9e7d4f72,
  57993. 0x3eade8b7,0x55143fda,0xd16e454d,0x859b8444,0x000000fb } },
  57994. /* 122 */
  57995. { { 0x7c667aaf,0x7c22083e,0x4a91ccba,0x33545cb9,0x8ca0e94a,0xca1e9931,
  57996. 0xe4eaa0c7,0xc3afff23,0x42f56844,0xa21ac436,0x60d52d0b,0xfcc68a8b,
  57997. 0x6a9301d4,0x401a585b,0x907abce1,0x547f762c,0x000000a3 },
  57998. { 0xfbe260ce,0x63dd3ed3,0x80dc01fa,0x2717752d,0x6f1da3e4,0xd5fab75d,
  57999. 0x5261f10e,0x5f16864a,0xd20cd6bb,0xbe7b1f63,0x221ac656,0x9d638c10,
  58000. 0x673b918e,0x3137b8f6,0x4ada2fb8,0x23eb4438,0x00000174 } },
  58001. /* 123 */
  58002. { { 0x2a1fbcf4,0x194e27c4,0x5facd5ee,0x4c0d285b,0x915e6607,0x75c2ebdd,
  58003. 0xef0a6a9a,0x1e696510,0x067cf458,0x13c5afa1,0x7bee1fba,0x2be013c1,
  58004. 0xdad279e7,0x85a406d6,0x5142cf59,0x0042951d,0x00000031 },
  58005. { 0xa22bbc45,0x6a735ec1,0x7f56f4d8,0x4ee5391a,0x236001de,0x305af9d0,
  58006. 0xaa2f8d25,0xa8b21851,0x187db78a,0x0e2c36d8,0xa1a888c3,0xcfcc083f,
  58007. 0xbd3e7d5b,0xb91dab7f,0xf4fdd023,0x62d85460,0x000000f4 } },
  58008. /* 124 */
  58009. { { 0x4972d703,0xf568ba02,0x39098a03,0xfc44ca1d,0xae28c855,0xe9b8e542,
  58010. 0x5b1b4536,0x4fd4f360,0x4c7f7e48,0x2e08b07b,0x2230823d,0x042f3b98,
  58011. 0x1889fd13,0xc9ffd313,0xc6c68359,0x56af0652,0x000001bb },
  58012. { 0x06e0f16a,0xedbf05e2,0xd74644a5,0xfc1ac2fa,0x0f92c71a,0xe59a0a98,
  58013. 0x36c800a1,0x13ae37d7,0x236178dc,0x5f20efc6,0x2b46ef10,0x443a58b8,
  58014. 0x442509e4,0xc9517dcf,0x640ed9b0,0x7d0bb415,0x00000166 } },
  58015. /* 125 */
  58016. { { 0x3d22842d,0x3aa30a61,0xb3c4ece0,0x8c6e00f5,0x6df82b79,0x8764cf87,
  58017. 0x78d208c5,0xda92d86d,0xe788854a,0x0a52d391,0xa59b0994,0x499b26fb,
  58018. 0x04c5fc9a,0x5dc133ad,0x34e3f134,0xa5c09269,0x000001dd },
  58019. { 0xfad6d673,0x6f0dcac2,0x00f3b3fe,0x6d8fdf05,0x631756e9,0xece71941,
  58020. 0x0a4d80e3,0x3990f493,0x31d13001,0xf2aca936,0x75581638,0xee91966c,
  58021. 0xe6dd5679,0x6df0f574,0xccd71cda,0xbe124868,0x00000111 } },
  58022. /* 126 */
  58023. { { 0x475cc1b4,0xf644c726,0x2b73978c,0x915fc2f9,0x0e3d7eb7,0x65a7e6d1,
  58024. 0xf40c38e0,0xbb44e21a,0xe1ad24fc,0x988662b9,0xc35606e5,0x270ba4dd,
  58025. 0x1a4f93f7,0xc3834a2c,0x3362a4d7,0x93d0c9a2,0x00000021 },
  58026. { 0xf769fd7f,0xe2cb7b8c,0x89a213b9,0x1815da97,0x6b910fef,0x7b4f8c56,
  58027. 0x26931438,0x2088b309,0x925b37c0,0x477b71bd,0x26a640e5,0xa049a921,
  58028. 0xfd21c6ef,0xd3ddf1bd,0x232a56b2,0x9b5f9d7d,0x00000064 } },
  58029. /* 127 */
  58030. { { 0x679a9c35,0xd640adf8,0xcb74d796,0xcdad98e3,0x5f8e9daf,0x464b8ebb,
  58031. 0xad4a073c,0x4738614e,0x2edde557,0xbd86c0ee,0x576ce0b9,0x77331738,
  58032. 0x4095fb96,0x9b5d3327,0xee09aead,0x72f0aeb3,0x00000136 },
  58033. { 0x64e54ba5,0xa388c76d,0xdc474d21,0x63fe7af1,0xb2a77081,0x7fa3e9d1,
  58034. 0xde1240ad,0x0447b49e,0xc720303a,0xd9f64b66,0xe6bd0213,0xb1c78029,
  58035. 0x0aa03ea5,0x1caf1c70,0x3bb85d2b,0x179180eb,0x00000103 } },
  58036. /* 128 */
  58037. { { 0xaf2ed12f,0xadbf4f9f,0xf380fd8a,0xce1d19e4,0xa39e81ae,0x0957bdb5,
  58038. 0x626ef6bc,0xf9833321,0x0cf5b28d,0x110ae5ea,0x20392cd4,0xab159450,
  58039. 0x6bc67855,0x67c49887,0xa3fd61c6,0xce7e5938,0x0000004a },
  58040. { 0x28c7dea9,0x59c5b9ef,0x0a6a7184,0xd02f95ba,0x8202769c,0x034dc257,
  58041. 0x94dd6896,0x213b0b08,0xb5dea95a,0x03730b7f,0x617ca889,0xfe243ed0,
  58042. 0xfb1ba052,0x16cf4d17,0x226f96da,0xd8691d6b,0x000001c0 } },
  58043. /* 129 */
  58044. { { 0xbf8015c2,0xaa2edf3f,0xc49502d8,0xe7f8236d,0xa6a43157,0xe890f6e0,
  58045. 0xa2d04b0c,0x318ef325,0xa809dbab,0x9cc0668d,0xda67ca21,0xdd26937a,
  58046. 0x83febc49,0x8f27c12c,0x3c9b9844,0x87b3db2f,0x00000029 },
  58047. { 0xfd2e3dc7,0x37e7aed0,0x7415fd55,0x498e8bdb,0x58a45f25,0xfc0d6c9a,
  58048. 0x209c85d0,0x83d5baba,0xd579e1ee,0x31ec8dc6,0xa502bfed,0x1f4cad0b,
  58049. 0x1f41bef1,0xc432e6ce,0xbbffca65,0x3b10afaa,0x00000191 } },
  58050. /* 130 */
  58051. { { 0x53053af7,0xbd9f7df0,0xb28a1cf4,0x60304765,0x7ce90438,0x441778fc,
  58052. 0xac8c5ddd,0x8fbed36e,0xfb59ec61,0x27b1313b,0xa1b1becf,0x9d2656ff,
  58053. 0x945973a9,0x334e1345,0xc362b595,0x3261888c,0x0000018c },
  58054. { 0xaa7f6ff8,0xf413a414,0x3fab7c7a,0x092aeb88,0x7cc307ba,0xfa1d886b,
  58055. 0x2346100e,0xdc81c125,0x02140c93,0x93d4d273,0xe6104835,0xa1ed7e3c,
  58056. 0xdf1795f3,0xe2b91ecf,0x369ed416,0x160dc11a,0x00000191 } },
  58057. /* 131 */
  58058. { { 0x8b57d7cc,0x9a72f46e,0x4bf02386,0x3140b0e5,0x05b3a91d,0x886c396e,
  58059. 0xa4ec26e0,0x1b9ab3a9,0xc50f58e9,0x742feaeb,0x55e26af0,0x1592c608,
  58060. 0xbb1cd9f7,0x943cd476,0xc7f02c89,0x3ed97fd4,0x0000017c },
  58061. { 0xe6d54964,0x53b02503,0xc6a318c0,0xd9bd1162,0x9cc28c22,0x18ff6cf4,
  58062. 0x03534640,0xa45c7840,0xb4cc0668,0x8ea3335e,0xf42dbe03,0x7ad727f8,
  58063. 0xfdf6c3cd,0xb157e911,0xec992d76,0xa7f894c9,0x000001b3 } },
  58064. /* 132 */
  58065. { { 0xaf09ea77,0x91e6e397,0x75dc25c5,0x26a760b9,0xb94a197b,0x8c040c08,
  58066. 0xb68ce619,0x041baca8,0x5bd23564,0xa19a0d15,0xd977b33f,0x86ca5b94,
  58067. 0xe5fbd029,0xf31f87f8,0xb1901f99,0xf76c55a6,0x000000b8 },
  58068. { 0x3846ec9f,0x175bf8c3,0x9deaca46,0xf462205c,0xa3108df0,0x92cb5ec0,
  58069. 0xcfaed928,0x879db283,0x65049fb2,0x477dc004,0x96ee5031,0x48d24bac,
  58070. 0x56adce45,0xa7db6b16,0xab1c684f,0x0110cdab,0x000000fc } },
  58071. /* 133 */
  58072. { { 0x4d308bf2,0x151b66d8,0xd6638004,0x99013c9f,0xfd383bf9,0x6892df92,
  58073. 0x3ffc8efc,0xa10efd84,0x313ea287,0x527e316c,0x3a0df740,0x8ef6e3cd,
  58074. 0xf6ebd2a1,0xcb96e430,0xa70ee4ce,0xc1ebecf2,0x0000018c },
  58075. { 0x1a70404c,0x80d14ad7,0xf9ce2a30,0x6ad21dd0,0x3aa3e072,0xb94cbcde,
  58076. 0x6363a690,0x0ab59611,0xc6b1e2b4,0xe70bff45,0x66ceec5b,0x1296dd0b,
  58077. 0x747757c0,0xd4cb2a74,0x3d7d91e8,0x08988ca6,0x000000aa } },
  58078. /* 134 */
  58079. { { 0xf8db0396,0xaa2dcfca,0xb422da76,0xe8ae8f37,0x96485724,0x652f8349,
  58080. 0x7bf1493f,0xf647c3c4,0xb0247a4e,0x8b600b46,0x7aebda8e,0xabf3e439,
  58081. 0xa7958df0,0x2e1d231f,0xf881bab2,0x38e692b1,0x000000ef },
  58082. { 0x26cf3047,0x1f3c1689,0x59539858,0xdad14f94,0x293f20b6,0xfde85d1c,
  58083. 0xf57abb17,0x2ea5436e,0x1794de38,0x0d1a8ffc,0x2bfecd2f,0x9ba508e2,
  58084. 0xdb786042,0x110f0a7f,0x7cde31f8,0x2ade6f64,0x00000196 } },
  58085. /* 135 */
  58086. { { 0xfec78898,0xc996a537,0xde0fa77f,0x0b39de72,0xd34cb08f,0xf6d076ac,
  58087. 0xda78d353,0xacd8bb82,0xa0392cc1,0x5fe804d3,0xe581549d,0xab7adede,
  58088. 0xc067c6d9,0x883901a0,0x4ed93f37,0x5855ffa2,0x00000191 },
  58089. { 0xbf9ebef3,0x29570e36,0xdf4b3177,0xe21046a5,0xa6816b5c,0xf9b89a95,
  58090. 0x288d0e11,0xadf39281,0x3979159a,0xd6baabe5,0x5c8fabb2,0x411afee0,
  58091. 0xe5c7af10,0xf192c3af,0xd7dce37b,0xaa72e81c,0x000000f7 } },
  58092. /* 136 */
  58093. { { 0x16c386ee,0x20fa3c0f,0xd4c09839,0xb33b0469,0x876a3136,0x79e0d722,
  58094. 0x3c406c06,0x343c0a92,0x4debe27d,0xef220e3e,0x196f00ea,0x09d7b1e1,
  58095. 0x24a9dcff,0x4a0f5dd8,0x99c1d085,0x53582ec5,0x000001e2 },
  58096. { 0x5138c7ed,0xcc8ef262,0x6547f88d,0xdec43194,0xdd0a9488,0x2b6e53ad,
  58097. 0x8257ebdc,0xeb9f1efa,0x1f08c989,0xc583c6eb,0x40163768,0xf1736911,
  58098. 0xdbc20e3d,0x6282ff8b,0x9cbd514e,0x26b81005,0x000000d5 } },
  58099. /* 137 */
  58100. { { 0xa0025949,0x2449522f,0x0bbd8945,0xb26d888f,0xe637216f,0x33442f5f,
  58101. 0x472827f6,0xd8ec3b64,0x99fc2681,0x91d8a1a3,0x68c7710d,0x6d232ead,
  58102. 0xe51b2762,0x8e5bfe2f,0xfd109fa7,0x0f9f4fed,0x00000004 },
  58103. { 0x6b4a05e0,0x1952ea51,0xf21c78eb,0xcb0d48ee,0x1997dfdb,0x64d36619,
  58104. 0x8b4c21fd,0x0d11b204,0xbe92303a,0xa6f569b6,0x78c5e809,0x2b8f6096,
  58105. 0x36805d8e,0x7226b5ab,0xdb349ca2,0xd6cff180,0x000001bd } },
  58106. /* 138 */
  58107. { { 0x943cc612,0xa49f8576,0x832b31c7,0xc914319e,0xcccadebd,0x9225e297,
  58108. 0xb0619821,0x4918fb42,0x25b1cc7c,0xaccb3084,0xa646e5f0,0x751d3347,
  58109. 0x590e3e22,0xeafb4aae,0x2c4a0008,0x82146038,0x00000151 },
  58110. { 0xbf96a461,0x3c2481db,0xb52a3ba4,0x51c122e9,0x464db08b,0x21c2858e,
  58111. 0x6d6a081d,0xb1014b78,0xf533cef7,0x167d3ed4,0x81545f7c,0x6cfb3294,
  58112. 0x449b7b9f,0xea46d31c,0x9621c299,0xcfad7613,0x00000081 } },
  58113. /* 139 */
  58114. { { 0x478a7f0e,0xef796327,0xde17705d,0x914183e2,0x572117e8,0xd24a26df,
  58115. 0xb7cd52cf,0x3cdb1b09,0xad83c160,0x9e42b9fb,0x709ef8c9,0x6971d2ea,
  58116. 0x8ee54ccd,0x1894fc5b,0x34a520fc,0xf757b4e5,0x000000fc },
  58117. { 0x86b62347,0x5a5518cc,0x7bc2a928,0xec51c9d2,0x2966727f,0x2eea2b05,
  58118. 0x0ae43e6f,0xbc8a8e3a,0x05ca066b,0x80535b5e,0x8833986d,0x91ffcdb1,
  58119. 0x32374cdd,0x2f4a5bba,0x0d202243,0x08763a49,0x00000124 } },
  58120. /* 140 */
  58121. { { 0x4efac14d,0xe498b972,0xa79a9d3c,0xb6f4bf8d,0xd6e07c29,0x0f1e8dbd,
  58122. 0x71771538,0xfac30cfd,0x71b03263,0x4c91ed22,0x19b455f5,0xbf938335,
  58123. 0x127092bf,0x76a5e789,0xb4813bd9,0xa97674e1,0x00000128 },
  58124. { 0x583e5924,0x29b63c41,0x8f171d06,0x61f9aff1,0xab227a28,0x2b45b3cd,
  58125. 0x8a11ab70,0x939d5dda,0xe8db6971,0x2bfb47b0,0x0ec10805,0x562379df,
  58126. 0x24ce1801,0xaf5a6481,0x34f94aba,0x8d98c434,0x00000150 } },
  58127. /* 141 */
  58128. { { 0xcfffc80f,0xdea9fe73,0xd43473f6,0xe23e2e9b,0xc9d37ba7,0x27fb3ed3,
  58129. 0x7a3fc357,0x733766d2,0x8e04a03d,0xd0db4cf3,0x2bbe0f43,0x8ce01752,
  58130. 0xda986f4f,0xd87eb719,0x2fe6b037,0x6d1b50ae,0x00000153 },
  58131. { 0xda40bab1,0x371f5def,0x9b2bda63,0x07d6a8af,0x0d4aca87,0x5e8a5c89,
  58132. 0x643ff8ab,0x4d72f0ff,0x4bf8ec2f,0x9c4c10d9,0x0eb93e22,0x36b0eaba,
  58133. 0x1d2dfd01,0xbc4b0e8f,0x9d34a082,0x9f252e5a,0x00000142 } },
  58134. /* 142 */
  58135. { { 0x7d0e7020,0x4affd4c1,0xb5482168,0x9b169aaa,0x588f348f,0xdbe01708,
  58136. 0x885986bb,0xdaebf6ff,0x15f9c381,0xb33987f5,0x04a94a7b,0x7e455f2c,
  58137. 0xa0ed6849,0x39a41442,0x1ef7798c,0x1c1ad4a6,0x00000154 },
  58138. { 0x072709c4,0x7647b628,0x8810e5fe,0xb330d68b,0xe92e0f63,0xd1bd8874,
  58139. 0xf8bea9ba,0x144e4fb9,0x8318981a,0xc15afc18,0xb68c6a07,0xe19c5c82,
  58140. 0x36e00b66,0x858c57a2,0x07cb7aec,0x9b255110,0x00000011 } },
  58141. /* 143 */
  58142. { { 0xc887027d,0x121ced27,0x2bfab286,0x6050f335,0x19d511e2,0x6e373c1c,
  58143. 0x7f4c69f5,0x02d4c3a9,0x25226bb4,0xe6f356af,0x83e7ac30,0x3b9011c3,
  58144. 0x33d8fdfb,0x43b0c23d,0xaf2ea363,0xa8c390f7,0x0000000b },
  58145. { 0x7e851bac,0xc430c3d6,0xa5f544fc,0x8991c389,0x67fba061,0x006bbc64,
  58146. 0x97cbdbf4,0xd49d024e,0x7734adad,0x4539b7dd,0x28cb6d2a,0x90ba8f9f,
  58147. 0x4de4b3ad,0x7a921830,0xa7b96928,0xb28732ef,0x0000006a } },
  58148. /* 144 */
  58149. { { 0x22ed5986,0x71dab52d,0x58533e06,0xdeee627a,0xcf155fe3,0xe8fee37a,
  58150. 0x7ae8b132,0xcd61490d,0x34a08b94,0x2706e185,0xf9c15c30,0xa85ffd52,
  58151. 0x51a5ad46,0xd5a224f3,0x54d700bb,0x44d1b6d5,0x000001e6 },
  58152. { 0x862e4e9c,0x96830686,0x48763fe4,0xfe5cd76c,0xc0839caa,0x60309679,
  58153. 0x8d83d62d,0xc0e4cbeb,0x11bc4ae2,0x911e254e,0x64fca062,0x96a0d7c8,
  58154. 0xe9a27045,0xf5785dd5,0xf3e0412c,0x2f4677d0,0x000001be } },
  58155. /* 145 */
  58156. { { 0xab01a6dc,0x4c0012dd,0xae1adb69,0x391bd6c1,0xb9b05079,0x3ae7daec,
  58157. 0x62a1061f,0xc2714f9e,0xa96536b7,0x71978ee7,0x5e17654b,0xeec11bd0,
  58158. 0xefab3dd4,0xc71166e0,0x87edbf61,0x0f7aa572,0x000001d7 },
  58159. { 0x51eb5932,0x26ea6f7d,0x5f882ca4,0x354ea0aa,0x7739f7dc,0x175b6097,
  58160. 0x9be57934,0xd335192a,0x78545ecc,0x9801f423,0x7b643c9d,0x32b8e256,
  58161. 0x23e3abec,0xb9411dd7,0xcf1c6509,0x656dea68,0x000000ee } },
  58162. /* 146 */
  58163. { { 0xa0890deb,0x4d38e140,0xbceb84bd,0xbf7bd87d,0xba041dec,0x51f0ff72,
  58164. 0xa6820be9,0xafeec70a,0x8c486298,0x755190a3,0xe7010ec4,0xecdba558,
  58165. 0x8c7879b1,0xced91db8,0xef5e215c,0x08de3e4c,0x0000014c },
  58166. { 0x16266da2,0x9c1534ed,0x7b4c9009,0x9ce322eb,0x69927688,0x37decaef,
  58167. 0x05c2844d,0x6525097f,0x1ac519ab,0xd23b7e13,0x65a3cc86,0x682ebb72,
  58168. 0x628c4575,0x0c531db9,0x73805373,0x2e00e8b8,0x000000be } },
  58169. /* 147 */
  58170. { { 0x57ed32e9,0x3807c800,0x7c024997,0x427e40cf,0xabb54830,0x58506abb,
  58171. 0xce820bf4,0x5649776f,0xb2c43e81,0xb5353293,0xcfef6648,0x671e8353,
  58172. 0x903bdca5,0x27217d3f,0xa813fd79,0x40a9c109,0x000001dc },
  58173. { 0x3db21a38,0x6beaa6c3,0xd73ef7e4,0xcae222e1,0xbd1d507f,0x1ff684e7,
  58174. 0x587a77ab,0xf5bac664,0x0c64a4d6,0x58c74f62,0x6a7c378a,0x4ca837d9,
  58175. 0x3e42e409,0xf43df531,0xfb49e14f,0x8a9a4347,0x0000013f } },
  58176. /* 148 */
  58177. { { 0x992f8923,0x85ab4edf,0x6fd209f3,0xe24aa5e0,0x1b1340ee,0x27be9b87,
  58178. 0x91e0bb40,0x2957d11f,0xf3d4c62c,0x425afad2,0xc7ff7aaf,0x2d231286,
  58179. 0x0114cbe9,0x96412b2b,0xc3e23529,0x6706a231,0x0000019f },
  58180. { 0x225c02af,0x06b3bbd2,0x3fa3e98d,0x53ebc166,0xb84f482e,0xa6df2b75,
  58181. 0x2bfc55df,0x912b4521,0x512a73da,0x30bdbd40,0x3d53eaa4,0xac0f43d9,
  58182. 0x0c27fd53,0xfc358fe4,0x919424b4,0x2cb183be,0x000000a3 } },
  58183. /* 149 */
  58184. { { 0x3fa6a746,0xe39b0c2d,0x1d5a24a8,0xe84a7922,0x78cdf2b5,0x70a58914,
  58185. 0x30666cb3,0x8a88067d,0xf6d71d06,0xb09a709e,0x0065d184,0x50007a3e,
  58186. 0xb8dc9448,0x7046af4b,0xc65493ac,0x2b6a3129,0x000001fd },
  58187. { 0xe45f2771,0xd3d5d5bd,0xf432ed95,0x8542b08a,0xf232a6bb,0x2ecd40fb,
  58188. 0xe8beccb2,0x0fcb6143,0xbf8e247f,0xcecc513a,0x8da3039b,0x955d56f7,
  58189. 0x56c2a0df,0x9157c619,0x3031fe2a,0xa6d35cbf,0x0000018c } },
  58190. /* 150 */
  58191. { { 0xbe0c4923,0xdd800b1b,0x6902907b,0x046ae740,0x957bd0c7,0x2398b37f,
  58192. 0x9655f8b8,0xaa8e1a9d,0x500f4150,0xcd2927fa,0x202e7aee,0x826a9c6d,
  58193. 0x9f29692e,0xb4cf58b3,0xbf41577c,0x3093868c,0x0000011f },
  58194. { 0x333ed442,0xadcb5e7a,0x906fef7b,0xae5c8e2f,0x3d98f228,0x2d9b0123,
  58195. 0x7ffe125c,0x4632f2da,0xba231835,0x59487731,0x12d2c512,0xa0caae5b,
  58196. 0x9857d9c4,0xbf00e658,0x54f200f6,0xc5d10086,0x00000172 } },
  58197. /* 151 */
  58198. { { 0x2fc283e0,0x58954046,0x7ee0880e,0xf7633984,0xb7fd1622,0xfaf1b40e,
  58199. 0xf598c5ed,0xecf5151e,0x7e00d9bb,0x6b4d92f7,0xa8c43fd4,0x7543e3b3,
  58200. 0x6511d1d2,0x3994e12c,0xaf05b6d3,0xdd841a1d,0x000000c6 },
  58201. { 0x23b991ad,0x23da17e0,0x71fba514,0xaab2b213,0x0ddc1879,0xb417ec5a,
  58202. 0x5f63acdc,0x173bc8ad,0x1e2a7d50,0x2fcf5210,0x6106d008,0x63373fd0,
  58203. 0x7db012cf,0x1e8211de,0x576545ef,0xa07766d9,0x0000018c } },
  58204. /* 152 */
  58205. { { 0xaf80dfaf,0x8e4347b9,0x9c4667f3,0xa80b631f,0x6ddbc238,0x6ff1db26,
  58206. 0xaa8718a0,0x6161e365,0xaf31c35f,0xe7f7ac90,0xfc6846e8,0xc03831d1,
  58207. 0x684175b4,0x1e669d10,0x934b731a,0x6da9d620,0x000000c7 },
  58208. { 0xa3e4e78b,0x981f597b,0x55099f9a,0x2c14dedc,0x93088c61,0xbf373995,
  58209. 0x9b207458,0x7c568307,0xa2276900,0xc4440c47,0xf7e6daf3,0xb6df23c8,
  58210. 0x42929103,0x4f662c25,0x8b3b7963,0xf4ea6db1,0x000000f9 } },
  58211. /* 153 */
  58212. { { 0xced36049,0xc669eb88,0xf41b99f8,0x87a4ffe1,0x6a72e108,0x690b7563,
  58213. 0x65a0bb8a,0x67dd6a8c,0x96e42955,0x42cf8c58,0x1aabffad,0x5286b5f3,
  58214. 0x8f6f26a4,0x1f7dfaf2,0x0e1ae503,0xc5d9e0ac,0x00000120 },
  58215. { 0xacc10da7,0xafbee3ff,0x944946e5,0x67e2d5f9,0x3c4220ff,0x8ec17e86,
  58216. 0xbd6f632e,0xfe6f7414,0xc3fc9ef4,0x4a9e3c0f,0x03bfb870,0x25ff3cba,
  58217. 0xbb03342d,0x18fd3600,0x0050cd2e,0x1e63e753,0x000001ac } },
  58218. /* 154 */
  58219. { { 0x8f3d6a02,0xdd83d07c,0x7ef4d0d1,0x71fc143c,0xd4c7af61,0xca994bf0,
  58220. 0x827c5cf0,0xc8a93e98,0x2b697882,0x4a102c7b,0x8a55e8ba,0x633c87d5,
  58221. 0xcc2d64f0,0x1ae8822f,0x986d01fc,0x2ce9b53f,0x000001c1 },
  58222. { 0x95dc1b79,0x859639fd,0x3f4e616a,0x2728f754,0xede2fb9f,0x6e703c4c,
  58223. 0xd50fae9e,0x042f7680,0xc2d530ed,0x0546bc3b,0xcdd598ac,0x00a4006b,
  58224. 0xe1294910,0x3f3286c9,0xb6bf9629,0x77782255,0x00000146 } },
  58225. /* 155 */
  58226. { { 0xe30c98fe,0xaf81421e,0xfc2cd705,0xdeb0feb0,0x14df6ad2,0x9b2c4ca6,
  58227. 0x9ba314e8,0xd38134de,0x4f04b16d,0xa443deb8,0xf07f8ca8,0xfc556ee0,
  58228. 0x3a4f3917,0x3c1c83bb,0xb1adcd41,0x8397dd24,0x00000199 },
  58229. { 0xdf4781e6,0xca01e17e,0x46f1f901,0x32d7c319,0xb53090da,0xa227a613,
  58230. 0xa7c8c607,0x2495b1dc,0xddc69709,0x1cf2fbee,0x45608098,0x1d3d82bb,
  58231. 0x085134d7,0xcfcddda3,0x96798c41,0x3dd171b5,0x000000d2 } },
  58232. /* 156 */
  58233. { { 0xd4dd7e96,0x97a40f84,0x8409fc0c,0x7114c8ea,0xa9d11393,0xc56f29e6,
  58234. 0x8fd8c6d6,0x3b606621,0x00269e7c,0xad3baa86,0x05929d5f,0x1413c6b0,
  58235. 0x222e365b,0xc1ad7e40,0x4798aaec,0x6a82621a,0x000001d3 },
  58236. { 0xc1003c81,0xaeac45c4,0xf43d8602,0x9ef9ef5a,0x60f77469,0x36a65f5e,
  58237. 0xbf5d2858,0xf312e7ab,0xc84acef1,0x2f53ec81,0x9d248b52,0x63e32ca2,
  58238. 0x81e65c60,0xfe9aa7c5,0x52841973,0xe3686c9a,0x00000017 } },
  58239. /* 157 */
  58240. { { 0x9e90de99,0x0b2efe65,0xad05ab63,0xbe4485bc,0xe14e4892,0xc48a6a52,
  58241. 0x22628687,0x2ad85430,0x5eb3db54,0x261f0e95,0xd45e5841,0x48e81863,
  58242. 0x8ed75739,0xcfe1ce0f,0x7d84ade4,0xbd6f1ff5,0x0000003f },
  58243. { 0xd1bf968c,0xd43711dd,0x48dfa472,0xd558d7cd,0xe425a566,0x49f09223,
  58244. 0x5c26d041,0x0cf83338,0x7c2c1743,0xbe7b81f1,0x5143d9d9,0xe3bdc33e,
  58245. 0x94fd3fae,0xf385ac35,0x9fd1811a,0x7551cf42,0x00000113 } },
  58246. /* 158 */
  58247. { { 0x20193bb2,0x4928f55b,0x7310b872,0x96e579d0,0xd345d276,0x5ee06309,
  58248. 0xa871868a,0x9a43e432,0x11038683,0x28c113e1,0xa332f108,0x8286ecf3,
  58249. 0x0385cbb4,0x3348aa37,0xef158daf,0x698ffcaa,0x000000c6 },
  58250. { 0xf6908745,0xa044c54a,0x6a3353fb,0xa6b336e4,0xd561e821,0x694c2852,
  58251. 0x3634917f,0x1b297970,0x81f61315,0x6e1023b9,0xef46a5ef,0x6817dc2b,
  58252. 0x8e114f7f,0x93dea0af,0xed72c5bf,0xc3cf3cd5,0x00000136 } },
  58253. /* 159 */
  58254. { { 0x7b080de4,0xbb8799ab,0xd69d8396,0x3b8f781d,0x986f8f63,0x76b42aaa,
  58255. 0xa54bc5ca,0x5d74c038,0xa9c2fbb9,0x76fcb605,0x80178930,0x8451b440,
  58256. 0x9d286f0d,0x40f00c38,0x0c543263,0x3038e952,0x0000014c },
  58257. { 0x6977aad9,0xc94bc381,0xd7087be3,0xadbfd082,0x875fed08,0x06d0820c,
  58258. 0x345656fc,0xe1ce84d4,0x0fd6dd4e,0x71c4d8e0,0x6a5fab40,0x23338b22,
  58259. 0x0baeeb6f,0xd477eac1,0x5f80c26c,0xe4db08bb,0x00000078 } },
  58260. /* 160 */
  58261. { { 0x1078342a,0x0111d12a,0x559a1064,0x0534725e,0x0fd3ffdd,0xea459d59,
  58262. 0x06f0ac1f,0xcf694a9f,0x3e19bc69,0xf6d24adb,0xb9ddcd00,0x3ce38f5e,
  58263. 0xb632dd4e,0x38400f66,0xe15e1c55,0xcab8fdfb,0x00000085 },
  58264. { 0x8d09422f,0x0a943f6b,0x0f988c3b,0x17d29756,0x2ef2e4d9,0x55a441fa,
  58265. 0x35f7c13f,0x6743523b,0xedaad3ff,0x274d3407,0x9347242d,0x59411435,
  58266. 0x3bb8615d,0x1cb27301,0xbd7794cd,0xa0437004,0x0000007d } },
  58267. /* 161 */
  58268. { { 0x2d712c44,0x824b99a6,0xa6962577,0x148368f8,0xd65e2287,0x8ed68432,
  58269. 0x6f5bc5f8,0x14028306,0x4ec3479d,0xe6cf3121,0x9326db70,0x96db6f44,
  58270. 0xca32936b,0xca5ac098,0x2fea21af,0x69e248c7,0x0000004d },
  58271. { 0xa71269fb,0x0aa89092,0x18650b60,0x2f6bdba8,0x9fb55db2,0x1d9cc2a3,
  58272. 0x6311e9d0,0x0fceb0df,0x90ac2c1d,0x6faeb79c,0xcb1f372a,0x2393b222,
  58273. 0xbc8c4193,0x62a6f3df,0x2fe8e674,0x9dea30b2,0x00000001 } },
  58274. /* 162 */
  58275. { { 0x12b3118b,0x7df689ac,0x6cb6ea56,0xd06ee39d,0x187cd978,0xcfcc22c2,
  58276. 0x8d537d87,0xb985b681,0xe9f56db2,0x75845152,0x5e098c15,0x0f839871,
  58277. 0x3b212cd2,0xbe96a5c8,0xd9ac1c47,0x3dda0338,0x000001fb },
  58278. { 0xcfa0a9b8,0xf06b7fe0,0xe22dcf75,0x9478bac7,0x136887c8,0xf3815e04,
  58279. 0x914c54bc,0xed811dde,0x0f51ea64,0xc8c24160,0x4c870577,0x63914d83,
  58280. 0xa8abbcb4,0xed24e552,0x2644f52e,0x9e5eb9e8,0x00000001 } },
  58281. /* 163 */
  58282. { { 0x66d52313,0x1f65a04e,0x4d3f72bd,0xfd694545,0xa6b7ae11,0x2bc0ddaf,
  58283. 0x571ab247,0x921f79d8,0xae5a8d68,0xd4c5f966,0xaec5ce13,0xfde17716,
  58284. 0xb764bd39,0x70e6eda4,0x990d6783,0xffe94085,0x000001ef },
  58285. { 0xd88f92e8,0xf3fa0e27,0x9c77123c,0xa21ef0fd,0x89274dba,0x6259974c,
  58286. 0xb9ba2762,0xd4cfa4a5,0x46ebcaf6,0x10c909d2,0x8f8e2870,0x0317a10d,
  58287. 0x453aeea2,0xb0771de1,0x68c6b0a3,0xdf0c4791,0x000000ea } },
  58288. /* 164 */
  58289. { { 0x4c854477,0x11bc1e48,0x8638e47c,0x2bec25b4,0x869c54d9,0x43d4e02b,
  58290. 0xbe1e7ed2,0xe318de32,0x6b460c4a,0xf5471eb0,0xaa426afe,0x38ae7bf3,
  58291. 0xd8452dc1,0x23ae26dd,0x5782de9d,0x9d3fc1d5,0x00000164 },
  58292. { 0x0ade1979,0xd87cae31,0x3b4bc728,0xa847041d,0x56c3c9be,0x38923c40,
  58293. 0xd74ae467,0x36fe182a,0xecbe49ae,0x92bff6f4,0xdc41f9f5,0x6680db80,
  58294. 0xe4630715,0x35bac06f,0xd6d07307,0x6d68b4c7,0x000000c0 } },
  58295. /* 165 */
  58296. { { 0x854dfcf2,0xdbe22be7,0xa6ae3bd0,0xee21a7df,0xa521ec46,0xf4633ad1,
  58297. 0x41a9484c,0xee94527a,0x2aa123f3,0x1145eb9b,0xcae3ca92,0x5634a82a,
  58298. 0xfc85d925,0xe176aca0,0x19082d8c,0x504cf7fc,0x00000078 },
  58299. { 0x3799793c,0xd74ce7c4,0xb5519fb5,0x74ddd618,0x95ff9808,0x2cf6df93,
  58300. 0xb8bf61e6,0x00ea45d1,0xdcfcf54f,0x26863613,0x030035b0,0x67423b76,
  58301. 0x4028a9cb,0x9fbc7534,0x051a077e,0x7b52ce37,0x000000f4 } },
  58302. /* 166 */
  58303. { { 0x96bec962,0xebf7d8ad,0x17e0107a,0xd1cc81f6,0x214e1058,0x64c44509,
  58304. 0x42394c9f,0x6c298c43,0x1a660513,0xd910052d,0x90df8243,0xc3643754,
  58305. 0xfe5cdea4,0x2313be1e,0xd27fb7b1,0x249a60f7,0x00000076 },
  58306. { 0x1cf593a0,0x74975838,0x8364c59e,0x0c9ceefb,0xe05c9991,0x2f5a1333,
  58307. 0x421808e3,0x30ea5e1f,0x4f5e8f4f,0x56fb3a4f,0xb6c0cb47,0x2cae6e2e,
  58308. 0x08bdcc6a,0x60b307fd,0x0ff8c117,0xee17901c,0x0000001a } },
  58309. /* 167 */
  58310. { { 0x89aa9e14,0xc048336b,0xf676700f,0x66634271,0x906b6980,0x4daa0433,
  58311. 0xebb7ab23,0x30247ee1,0xeb59a053,0x969b4aa7,0x8000f4d5,0xd78ef825,
  58312. 0x46026b5b,0xe5db38eb,0x7d6856c4,0x06a43e5d,0x0000003b },
  58313. { 0xed2a0ee7,0xaa0ae838,0xf16e8813,0x04bbe528,0x4ea64137,0x8ab6df5c,
  58314. 0x06e29867,0x5be80cb6,0xf459ed2b,0xf19b1b72,0x1761521a,0x7a9cce4d,
  58315. 0xaa516f3b,0x39aff994,0xb3416925,0x97d92e86,0x00000007 } },
  58316. /* 168 */
  58317. { { 0x5af3a8ca,0x25aeede1,0xa5c351ec,0x33924782,0xf93ec080,0x41e7a3fb,
  58318. 0xe6f425b4,0xb04f93c4,0x81e76009,0xe4ec12ec,0x5180ffc6,0x797366d4,
  58319. 0x0e0aef3a,0xd293cbb5,0x68d71d91,0xa1496944,0x00000061 },
  58320. { 0x675a67a1,0xf52c541c,0x8f5fe906,0x67d38d30,0xf6be988e,0x2a70bccc,
  58321. 0x18589886,0xae03ecbe,0x7067045b,0xecd02616,0x10ca8d96,0x1facdd99,
  58322. 0x30c0735d,0x7aa10a82,0x3328f21c,0x2a27e554,0x00000015 } },
  58323. /* 169 */
  58324. { { 0xe6057e27,0x3dd609e0,0xc7a454da,0x87e8b6a7,0x1f32dd5b,0xff599145,
  58325. 0xd0ef51e2,0xea397a88,0x25567546,0xc49866a1,0x3228b480,0xea45c8b1,
  58326. 0xdd01997a,0x3dbe0e77,0xc51867d2,0x0e2ea28f,0x000001f8 },
  58327. { 0x69d0820b,0x6295412d,0x1ea65a18,0x03173127,0xeb06380d,0xc27c8221,
  58328. 0x75fe9706,0x7ffd4efc,0x5a71d250,0x7b396a57,0xc7cb7543,0x61c80051,
  58329. 0xad4dbee3,0xe07db4d7,0x9b192d45,0x1c7481f4,0x00000143 } },
  58330. /* 170 */
  58331. { { 0x08e1cc4d,0x5eab2d04,0xad2dc1ee,0xe93758d3,0x5c9c7393,0x0ceb7dfe,
  58332. 0xd3379683,0x530d86a9,0xe24f86d7,0xef5283ca,0xf0b1bb0b,0xab5d1a64,
  58333. 0x54db4e3c,0x96aabc1f,0x3bc00c59,0x3e3d87cc,0x00000144 },
  58334. { 0x1d60e7b0,0xe50a8213,0x5d33d018,0xfc9b629b,0xfd05338d,0xc54aee42,
  58335. 0xe821c6ea,0x0678f2c0,0x06ac09cb,0xe5c9d75f,0x53018df6,0x83357513,
  58336. 0x0bf8c667,0x81ca6fac,0x9d0ae2dd,0x7fc8020e,0x000000e1 } },
  58337. /* 171 */
  58338. { { 0x1baaa5eb,0x8add4741,0x79bd8036,0x02cbb759,0xcdffed22,0xd8680c40,
  58339. 0x4e091141,0x1c23a8f0,0x20748b87,0x65d141ed,0x659e9289,0x586a1575,
  58340. 0x5006dbfe,0x7c68d7cd,0x22569a74,0xda0ad0df,0x00000148 },
  58341. { 0x7f9069d7,0xc8fcc5db,0x5c0531a4,0x2487d245,0xe9a2db3a,0xc5ab4899,
  58342. 0xb4fe9720,0x52bfd538,0xd27f35e4,0x73a04ca4,0xee2dac93,0x7cbbc549,
  58343. 0xff3ee7e2,0x0287229d,0x28da9360,0x3179878d,0x000000d0 } },
  58344. /* 172 */
  58345. { { 0x3b66c047,0x89b7e9bb,0x602a3e1d,0x22e65869,0xc8db9c00,0x44f82297,
  58346. 0xd08a74a3,0x0e76aca3,0xfcd398de,0xfbf1a71d,0x8320e66a,0x2fbb6eaa,
  58347. 0x179c9fc5,0xa82d0ebc,0x4e7ab2b4,0x4e00cf6f,0x0000000f },
  58348. { 0x4890c439,0x424c0e9a,0xbc35a6b2,0x37564a2b,0xd9b7497d,0x95a4479d,
  58349. 0x612de942,0xa1ff3f0d,0xe60d0033,0x358627fc,0x522417da,0x815da8c0,
  58350. 0xef6b8385,0x506104d4,0xf16e96aa,0x800728d2,0x00000120 } },
  58351. /* 173 */
  58352. { { 0xab039042,0x976f2372,0x9fa084ed,0x10e6978c,0x58bec143,0xd03fdd2f,
  58353. 0xfe2045c3,0x3200c101,0xb0a5a928,0xe6868f7a,0xe61faff8,0x26c95d1d,
  58354. 0xb7b12265,0xa1e20127,0xc2a5ed17,0x8e63dd78,0x00000089 },
  58355. { 0x22bba4ee,0xbb6533da,0xf496a574,0x3eff6397,0x14f2a6b9,0x409329f7,
  58356. 0x1dfdd73f,0xa08248bd,0x69bca1b1,0x62f33f2e,0xba2e0327,0x9a177e64,
  58357. 0x75ddf741,0xbc50e993,0x4a56bd1c,0xb87a979f,0x00000095 } },
  58358. /* 174 */
  58359. { { 0x67c1f177,0xe83736a9,0x600133c9,0x1b6d3508,0x6eac9a5b,0x9424bb92,
  58360. 0xc27ef31c,0x7a9c01a6,0x122b4870,0xad93bba5,0x9d1ac985,0x9eb94e2a,
  58361. 0xd53f175b,0x511c0206,0x5102d914,0xd13eb252,0x000000b1 },
  58362. { 0x675a1171,0xcfe7dbeb,0x16c0d2b1,0xb228295c,0x057c88ca,0x8db25b5a,
  58363. 0xd300e9cf,0x73ea9e96,0x269552eb,0xb0e0037f,0x9e0f98df,0xea9d035c,
  58364. 0xd290480f,0x860e49b8,0xc036b319,0xa35e9512,0x00000037 } },
  58365. /* 175 */
  58366. { { 0x8f00df48,0xc56729ee,0x11ac8304,0xb89ca7b6,0x8b3a8123,0x497a57f9,
  58367. 0xc21ca3ea,0xe0431b19,0xe2bb3ce7,0x45a73deb,0xadc77819,0x2f86cc2b,
  58368. 0xe5eb3df1,0x5ff005e4,0xdd27dcf0,0xf955dd7a,0x0000005e },
  58369. { 0x00ee402f,0xe0c22ffa,0x3b30bb4c,0x5b335e2a,0x643cb101,0x542551d0,
  58370. 0x3cd19688,0xc6183f45,0xf0be54b4,0xc6664f22,0x4c20cde4,0xa5f4cfee,
  58371. 0x80a4c475,0xdcaa972f,0x59111ed9,0xde4af200,0x0000019c } },
  58372. /* 176 */
  58373. { { 0xd771f428,0x9e9d0bc8,0xe43ca382,0x3ac1ecd9,0xeb93acf0,0x8d5ee480,
  58374. 0x065a2a3f,0x16232f81,0x2f0b8a73,0x1fc04faa,0x025474a2,0x4a8df7e7,
  58375. 0x3bb15f6f,0x51ac4ff2,0xe0950e52,0x66e21b73,0x0000006b },
  58376. { 0x67a41dee,0x59c98480,0x7b3e2b3f,0x2cfa95ae,0x891454e1,0x54d98386,
  58377. 0xeefca6a4,0xf0dddbdf,0x11e9cb75,0x5f691b24,0xfef208c3,0xa9b9e766,
  58378. 0x18b33cf6,0xe8df1000,0xd1c174a9,0xb8a55ac9,0x000001c4 } },
  58379. /* 177 */
  58380. { { 0x5c4cccb8,0xa99f5862,0x2ef4d3ef,0x70bf5209,0x89efc878,0x28f4e576,
  58381. 0xda14206e,0xa2366f96,0x7c52107d,0x90331a00,0xd4a0f0f0,0x478d4cea,
  58382. 0x472a47b0,0xb2899ee2,0x64207549,0xae96534e,0x00000110 },
  58383. { 0xcced05b0,0x2cc1d655,0x01759543,0xabac3f09,0x8e577cd7,0xbaeb70a4,
  58384. 0x40e98d6d,0x84b00893,0x603d24f1,0x26983653,0x2572173d,0x6e145883,
  58385. 0x611141de,0x1d348b26,0xefa27f34,0xe52257dc,0x0000006b } },
  58386. /* 178 */
  58387. { { 0xc947e655,0x92678f33,0x08923795,0xff0fb76a,0x790239d1,0xb2dfe745,
  58388. 0x3cdbb7ce,0xea087492,0x05f6d41c,0x21326db9,0x79dc5588,0x5b1ae9ae,
  58389. 0xe9c31702,0xe145340c,0xa2c38a9c,0x07502c29,0x000000c3 },
  58390. { 0xc156ace2,0x0c124f11,0x79ff2529,0x2c170fe7,0x6e1171b2,0x60df9a81,
  58391. 0x55de2797,0xa19bca83,0x7c6cc79d,0x1ad927ea,0x1d61f770,0x28590112,
  58392. 0x261c06bb,0xfe80c826,0xaa2642bb,0x4050d338,0x0000015e } },
  58393. /* 179 */
  58394. { { 0xeaad87bc,0xc9397829,0x81e84cbd,0xe0ac9367,0x6ade4fde,0xb579c24d,
  58395. 0x690d7f56,0x50b9aba5,0xd14fb0b9,0xf09b29d3,0x25a0e7b6,0xd0684f23,
  58396. 0x606f4ff3,0x0514e9d3,0xe8ad733b,0xe63bdd26,0x00000077 },
  58397. { 0xe0d25c6d,0x0afd06ec,0x00ba2dcf,0xdd90021a,0x8c5bb398,0x1b025770,
  58398. 0x198ff8fc,0x077f06d8,0xb7e2cd68,0x87d50ff1,0x263a3572,0xef75e057,
  58399. 0xfa925a9a,0xbf257892,0x739d0e95,0x847d3df0,0x00000111 } },
  58400. /* 180 */
  58401. { { 0xfec82924,0x52ab9cc7,0xa7220d69,0x1c76dd69,0xa06ef0e2,0xa63527de,
  58402. 0x27183904,0xab3e51c2,0x716807c8,0xf4db35ea,0x748f1246,0x8f3ede0a,
  58403. 0x41156095,0xf1493644,0x874b38de,0x5f6583d1,0x000000f7 },
  58404. { 0x0b927eb7,0xa39189e1,0xc2e2f127,0xa87c6359,0x7fe966f4,0x0b72c233,
  58405. 0x105e5585,0x102b8382,0xe58c39f9,0x63fee006,0x991b5329,0x3f052ee3,
  58406. 0xcbaff97b,0x7f5b854c,0x5f805060,0x935e5f6c,0x0000016a } },
  58407. /* 181 */
  58408. { { 0xdfd88d38,0xf19a0355,0xc549df40,0x555cd8e3,0x04d006e1,0x322729e3,
  58409. 0xfd0b0ce6,0xf16b706c,0x35f2ad31,0xf156dc09,0xf7a3df9f,0xb30c5213,
  58410. 0xa55e5fb5,0x9f29cc92,0x2b858da2,0xa0ecfdd4,0x00000144 },
  58411. { 0x52658a92,0xb5c115df,0xc4281616,0xbce3ed17,0x7fd92a91,0xa5595f70,
  58412. 0x9cd5d896,0x663c8bfd,0x5a9472b1,0x0776343f,0xb033e1bd,0x14e44ca8,
  58413. 0x1e5c02fb,0x27a1c986,0xcc4ffb32,0xece0f2c4,0x000001b5 } },
  58414. /* 182 */
  58415. { { 0x31211943,0x17127bab,0x5684325c,0x44a8cac6,0xd855fc3e,0xd2fe0b88,
  58416. 0xce91eea5,0x47abab0c,0x78ec7d12,0x5d23ddc4,0x0cd9fefa,0xa3986de7,
  58417. 0x82655766,0x32c7b867,0xeeaec7fa,0x3e54018b,0x00000087 },
  58418. { 0xb38d17c1,0xc96e86f2,0x71fa040d,0x9cbfbd0c,0xf88499cb,0xe111ab79,
  58419. 0xf71ec80b,0x1d47c5ce,0x46c89692,0xacaa3bc1,0x3d316331,0x5f921c0e,
  58420. 0xe768765b,0x31fa081e,0x41eff270,0xd5dafd5f,0x000000fe } },
  58421. /* 183 */
  58422. { { 0x4cda1348,0x8af10b9d,0x25c3013a,0xb0769fd2,0x8957c22b,0x450aa5b1,
  58423. 0xf5acf1c4,0x5cafd6c7,0x9fef8029,0xcf71a140,0xee089f5d,0xe12029f5,
  58424. 0x0fbd2ba8,0x9752a8fb,0x6f70cb58,0x61e2275f,0x00000090 },
  58425. { 0x1fbda16a,0xb70a4ac5,0xf1dfa2a2,0x79910e79,0xd9945f6f,0xba2ce132,
  58426. 0xeb4ba4ef,0x450d59ae,0x4bf2d53d,0x6a8e09b3,0xe620c7a8,0x76010204,
  58427. 0x0a53c6f4,0x63f8943d,0x87eaf56a,0x14c91d19,0x00000132 } },
  58428. /* 184 */
  58429. { { 0x490d66c3,0xe54fb120,0xa0dc8204,0xeaed7328,0x04b4294d,0xba014c38,
  58430. 0x31ddc467,0x3f2fa2ab,0x8342ed11,0x70ff55ea,0x23034e0e,0xb18da72f,
  58431. 0xbd8ae3c1,0xadc30dbe,0x3e945a02,0x179bdf6f,0x0000009c },
  58432. { 0x7484c26f,0x46c928ef,0xef2adbb1,0x206b7db1,0x3f58dda7,0x0887f548,
  58433. 0x4bc7edb6,0xfde4e20c,0x975cafdc,0x484d121d,0x86beec20,0xc5b59670,
  58434. 0xa6d6db67,0xb579aa88,0x41187488,0x22c6d87e,0x00000015 } },
  58435. /* 185 */
  58436. { { 0xc471d4ae,0x0a890757,0x43a1da76,0xfef4b1a5,0x6aa701a1,0xb892b182,
  58437. 0x59c65f93,0xbf4d4e52,0xd789df35,0x923af929,0x0b79c3f2,0x3ccb46c6,
  58438. 0xcf4cf130,0x95582ce7,0x257f0ec4,0x7da081b4,0x0000011c },
  58439. { 0x9aeef274,0xf92c6ae5,0x1437c083,0xe6c5bf4f,0xe13c86af,0xaa74b023,
  58440. 0x2a225360,0xd21dace6,0x22589fa5,0xb3d572b8,0xdfa74b0f,0x3d4a3916,
  58441. 0xb12891a9,0xe76cd8dc,0x59f4cfbd,0xa0391a3f,0x0000019a } },
  58442. /* 186 */
  58443. { { 0x203fc3f1,0x054ba69e,0x62106a29,0x09168ccb,0xaad5fa9f,0xb0818540,
  58444. 0xbff7ed6f,0xecb8f20e,0xbef94afd,0x2c80a618,0xb0abd1db,0xe25d8ca0,
  58445. 0x028e0a7c,0x75e67a41,0xd6e95b9a,0xdd7662dd,0x000001b2 },
  58446. { 0xf289d7ee,0x87dff279,0xeea2205c,0x4d755d59,0xc18adac6,0xaeb0fd54,
  58447. 0x7ec01019,0x3a8c46cf,0xb48d70a4,0x6fc90e7e,0x10b39ef8,0x965c53c1,
  58448. 0x38545a20,0x455777cc,0x57dd023e,0xa33430f7,0x0000016e } },
  58449. /* 187 */
  58450. { { 0x0ff53d2c,0xfa9f3949,0xb00349b9,0x8dc91596,0xd5997967,0xf10a5014,
  58451. 0xa8a6b78a,0x4dd72dab,0x8b517b10,0xef5de540,0xa6d39be0,0x142b90bc,
  58452. 0xeda17f70,0xcaeaa3e9,0x06b31118,0xa01689d6,0x0000016d },
  58453. { 0xf46afff7,0xea6ca563,0x34a5e5f3,0x3945c7ba,0xaa998fd8,0xc1ffe4c8,
  58454. 0xb63f535e,0x42a60146,0xd1f509e5,0x50816888,0x9f8cd0db,0xd1918daa,
  58455. 0x78a36772,0x6505e6bb,0x9cc6dc66,0x4ab03a81,0x000001ef } },
  58456. /* 188 */
  58457. { { 0xd376d986,0x06089d14,0xa2dc35b0,0xd0f4e077,0x53ff2c86,0x1c11709a,
  58458. 0x123c3fc8,0xfef4ba45,0x1b656fc2,0x852cd5a7,0x1fefa8bb,0xb57c7489,
  58459. 0x48110b77,0x8f05383e,0x52c5a129,0x4b55d3ad,0x0000004c },
  58460. { 0xf3827633,0x5110cff3,0xe00afe96,0x086784d5,0x3ead32fa,0xcb387882,
  58461. 0x2b91cd86,0x3dcf4d16,0xe6f3638a,0x078b6a58,0xe8b7fd42,0x33792112,
  58462. 0xee5683e7,0x6964044d,0x28e28433,0x3b84210f,0x00000122 } },
  58463. /* 189 */
  58464. { { 0xc3ebeb27,0x6c28a9a9,0x3ef590f8,0xd7bcdcb5,0x4dae7f37,0xe88a2e11,
  58465. 0x726ea7c9,0x033522e4,0x8c141388,0x99d50386,0x61621575,0x59b1aeca,
  58466. 0xfcc564d8,0x719fcfeb,0x1aeb8e36,0x3a577af1,0x00000043 },
  58467. { 0x6feba922,0xc3f26ce0,0x475a5693,0x5f6c83ee,0x28bf378e,0x7f796740,
  58468. 0xbdc3f6f1,0xd2a5e368,0xa6ed90ae,0x3d034a0a,0x4a47cbd5,0x3b1c3a4c,
  58469. 0x4dce2bc8,0xa4f0aa6e,0x74ca00eb,0x97c7af43,0x000001c0 } },
  58470. /* 190 */
  58471. { { 0x79c28de7,0x00377178,0xab9c330c,0x617aa2aa,0x66bc61eb,0x43081826,
  58472. 0x4d78b504,0xe0b5b5cf,0x9870fc72,0xd76a752d,0xd40b7bc5,0x3b4689f5,
  58473. 0x87f2d03a,0xa97fd867,0xfd6060a9,0x6ab7b5ee,0x000001c0 },
  58474. { 0xffb71704,0xe99eadb1,0x390fe3b1,0x436e58bb,0xab4f19aa,0xeecab82c,
  58475. 0xe0f3d9dc,0xda492dfa,0x6e20ad12,0x2a0f54bd,0x7dbbd262,0xaf89fa0f,
  58476. 0xe8d2eb54,0xdcc50a1a,0xef7d0758,0x9799f816,0x000000b7 } },
  58477. /* 191 */
  58478. { { 0x104f98cc,0x9ec46462,0x72aedeae,0x45115922,0x7e62186f,0x7ae93dd0,
  58479. 0x8d6d69b6,0xd17ce026,0xfd43a8f3,0xb5347608,0x7c0ab797,0xe87f1c13,
  58480. 0x139f991d,0x3bf597a8,0xe547e0d6,0xe293a85b,0x0000008d },
  58481. { 0x8ef668b1,0x0982add3,0x611c9764,0xc54e6b2d,0x1c1d4263,0x3ce76b12,
  58482. 0xeff64e73,0x3134b28e,0x2871612a,0xaf71a9ac,0xba093594,0x31c88af2,
  58483. 0xba9108e8,0x0b649112,0x5cf437da,0x8febc5c5,0x00000113 } },
  58484. /* 192 */
  58485. { { 0xc4a2daa2,0x7e9ca589,0x400f608c,0x18ea703c,0xd5175103,0x6f8cd058,
  58486. 0x4abb6f29,0x26493472,0x94296ab4,0x0be553e1,0xac51657d,0x9af9398f,
  58487. 0x4f880ea8,0xe232deec,0x67b1e1b1,0x2f81761e,0x00000137 },
  58488. { 0x3a20f662,0x51014bc7,0x49ed9502,0x1fb7e77c,0xb62b9652,0x89f5096f,
  58489. 0xa2e8d37e,0x3a659c67,0x5804170e,0x0f2b2a26,0x9ed50a34,0x1674fce6,
  58490. 0xfdc3c00f,0xaaa4537e,0x4ce99d93,0xf3c3bfda,0x00000198 } },
  58491. /* 193 */
  58492. { { 0x81614189,0xbab1f5cd,0x24b259f7,0xc7d56c45,0x45fb415e,0xc7baa4b2,
  58493. 0x7af6bef9,0x302bc8dc,0x74b48e82,0x91b770e0,0x9b6d1b1f,0x4a1336e0,
  58494. 0xe6680c97,0x285c1357,0xc7ccb625,0x59bcb813,0x0000012d },
  58495. { 0x7c019927,0xddad83b4,0x630dfd5b,0xe10f2667,0x31e05d23,0x15dbec5a,
  58496. 0x456ac460,0x2aa6e5fa,0x243cac82,0x46956529,0x4dc8c9e9,0xc69c9c7f,
  58497. 0xe24a4065,0xadb27e09,0xae41301b,0xdfa7a34e,0x000001cc } },
  58498. /* 194 */
  58499. { { 0x59cb1a7d,0x176a864d,0x6aefb8ee,0x4d864ca3,0x1c22b0d8,0x0ee83acb,
  58500. 0xd980df1d,0x7e80a6eb,0x7f94ced9,0xf582acc4,0x3a72c115,0xa29cd123,
  58501. 0xc7107bb7,0xce12a2a8,0x4ed80a30,0x0229ca56,0x00000150 },
  58502. { 0x2f1c180b,0x9774bad5,0xd749aa10,0xd08be998,0x56dbd1ba,0x978c48ab,
  58503. 0x0afbea9a,0x6ed3e3e4,0x153dc5fc,0x8a8be97b,0x9be93ed0,0xadc7f095,
  58504. 0x2cee23bd,0x8d242908,0xdc2729de,0x417523c6,0x00000016 } },
  58505. /* 195 */
  58506. { { 0x6c14a31e,0x74eeccf1,0xb2de3c2d,0x488e2534,0x7cec43c3,0xf9bb3599,
  58507. 0x916ac936,0x4210459d,0x9f7e4400,0x71d15c02,0x44553583,0x8c9c7c12,
  58508. 0xec94a467,0xcc97548d,0x3167bad9,0x4ca67818,0x0000014e },
  58509. { 0x8d0312bf,0x033af055,0x54161e66,0xbd1bf4f5,0xfa41781d,0x259945a7,
  58510. 0x00eef1d5,0x33494da8,0x79c3b8d0,0x6c505ec0,0x1c9f6e69,0x70ae1ade,
  58511. 0x76830aaa,0x0288f0c1,0xa62a060c,0x7f4cfe3b,0x0000000c } },
  58512. /* 196 */
  58513. { { 0x057d6006,0x0d8b447d,0xfd71c8b0,0x38b976e6,0xabcf40f5,0x5e77e029,
  58514. 0xf103a783,0x13bee386,0x5e472c4b,0x20a6ac20,0x31fcb194,0x43b045f6,
  58515. 0xc00abf49,0xe5dc1d9f,0xa5556b79,0x28c0bc70,0x000001b5 },
  58516. { 0x8a8640b8,0xba9d07ee,0xd0e34012,0x25611023,0xbe24ae89,0xc7ce655b,
  58517. 0xfa579dcd,0xe358e524,0x377bbfe5,0x57ce2715,0x3c0947e4,0x64651c6c,
  58518. 0xf4a97826,0x5fbd8d50,0xe2e1c15a,0x6fcdd28f,0x0000008d } },
  58519. /* 197 */
  58520. { { 0x5c7202c8,0xb564a2f6,0x5a54b0d8,0x7d634052,0x1434fbf5,0x8414d672,
  58521. 0x1d9830a3,0x8114215e,0x5ef0fbe1,0xc7a758d5,0xe6f57f9f,0x5705dcf8,
  58522. 0xd92269d3,0x5dd49a56,0xbdb49f97,0x8f015d7a,0x000000f1 },
  58523. { 0xb4799ce6,0x07131110,0x2cbcb7db,0x35bbfb99,0xf7ba21e2,0xc1f00c9f,
  58524. 0xb18f49fe,0x009d6913,0xabcf959b,0x8da61951,0x0d42146e,0x0e687213,
  58525. 0xae5f23f1,0x55832817,0x9ae7386b,0xc9b5bb68,0x00000143 } },
  58526. /* 198 */
  58527. { { 0x48c74424,0x423328db,0xd19cb2eb,0x32616e11,0x40d6e217,0xe534192a,
  58528. 0x0cbdc752,0xdd83a94c,0xd733bb01,0x5c623050,0x5b7a4520,0xcd0d631a,
  58529. 0x9a4011c8,0xccdc0a25,0x646e7cd5,0x22f112cc,0x000001e6 },
  58530. { 0x3e1e4c4b,0x47d6e29a,0x9fb1548a,0xd5f82538,0x4fd3e319,0x7e3705b5,
  58531. 0x0a08b966,0x8c4ce59a,0xd8cbe8db,0xbca749e7,0xaeec3d75,0xcc4496ea,
  58532. 0x8a1a313d,0x17dc723a,0x8ceb9360,0x250ff77a,0x000001a5 } },
  58533. /* 199 */
  58534. { { 0xfe29bd79,0xa55a0726,0x4f990b34,0x6574a810,0xaad56983,0x6906946d,
  58535. 0x50d41fef,0x0e580ab9,0x6e6f7f45,0xbc75b514,0xf0f3718a,0x508cc97b,
  58536. 0xa5634087,0x51ba2ca4,0xe64d8910,0x75c39077,0x00000172 },
  58537. { 0xf77ca6bd,0xf37cccaf,0xbdb18df5,0xe0a0df41,0x019e01f7,0x9f46cff8,
  58538. 0xaa65d72b,0xbe4f3d44,0x6e3663e9,0x7822d8ac,0x3ef9db6d,0x5f37f922,
  58539. 0xabe4a9aa,0x7f0ad39d,0xf69cc8ba,0xa0a57c70,0x00000098 } },
  58540. /* 200 */
  58541. { { 0x00fd5286,0xd9c50cf4,0x72a4b03c,0x1ea5b9d5,0x051ae73e,0xf5e60f9e,
  58542. 0x951b3824,0xfe9b5142,0x9fb4d667,0xb034b2d0,0xedc50856,0x4b537a80,
  58543. 0x8cb0022e,0x69ee1012,0x6a548aee,0x7c8b9e5c,0x000000ed },
  58544. { 0xd933619b,0x746007bc,0x2b9dfe19,0x0ce7668e,0xcc6e2a2e,0xa9eed5d3,
  58545. 0x7eebf32f,0x35a14f5f,0x67cc4f64,0x75cb898d,0x7850c16c,0xcb2185fc,
  58546. 0x45f79c96,0x09874a76,0x27db4744,0x7468f8ae,0x00000139 } },
  58547. /* 201 */
  58548. { { 0xc88684f6,0xc5de68ad,0x619a7dbf,0x7c1edaab,0xb27a18f5,0x258d1735,
  58549. 0x8ecd89eb,0xb27e7b65,0xd879f7ea,0x3d8889c6,0x67d5befb,0xa8fdc96d,
  58550. 0x37bad73c,0xc84d86ae,0xce8e56d7,0xc7e91976,0x000001a4 },
  58551. { 0x6319ffa6,0x5001a540,0x134ec04c,0x0cae64ec,0xd541242c,0x1f69a96c,
  58552. 0xbf2caeee,0x9da259ee,0x28bee805,0x88e7978c,0xb8e890e4,0xe9484beb,
  58553. 0xfb227fd9,0x0e5246d0,0x625d6318,0x8be2a54a,0x000001b7 } },
  58554. /* 202 */
  58555. { { 0xf472f13a,0xa223554a,0x5733e91c,0xfac993b7,0x96c168a2,0x26afe9f0,
  58556. 0x4b127535,0x7cfe761d,0xe77070ca,0x84301873,0xc7e7cdf6,0x66b6aaad,
  58557. 0xa1562ed4,0xda2dd5ea,0x39faf8d8,0xa81a2e00,0x00000016 },
  58558. { 0x4e3de3bf,0xa880759c,0x52f3088a,0x0c1e2e11,0xaa7eba5b,0xcb2ded9a,
  58559. 0x9f9c11ca,0x4c65d553,0xb0dc5c19,0x0ab9bd87,0xca3f4b61,0xd32f8c96,
  58560. 0x28cb5f9f,0x49842fcc,0xb90e21df,0x31ae27cc,0x000000f4 } },
  58561. /* 203 */
  58562. { { 0x6a0ccd0a,0x3b2a0a0d,0x5993b555,0xa3eeec82,0x9de672a6,0xb13486fd,
  58563. 0x0da05dcf,0x8d9c5148,0x6739874d,0xc4aa444d,0xe29a35c9,0xd9cf35b2,
  58564. 0x89177ead,0xd6bd9b5f,0x2a0470a1,0x9af0f59d,0x000001d6 },
  58565. { 0xba7535fd,0xb2f844c7,0xa842ff39,0x45bd4c3d,0xe951974b,0x5fe149ed,
  58566. 0xfd4453ec,0x6982e997,0xe6c37c0e,0xa63f705d,0xd2c3ef6a,0x09b0f6a9,
  58567. 0x1776a8d6,0xbedd3586,0xede11b78,0x4048a46a,0x00000176 } },
  58568. /* 204 */
  58569. { { 0x51a251d1,0xa47c6ee5,0x0d279dfd,0xbef4bf12,0xec518a28,0x4c2d538c,
  58570. 0x3880be6e,0x1b2b7887,0x1be9b20b,0xc69ccf8e,0x3796a19e,0xe41dfeae,
  58571. 0xfb50bdea,0x25676fc9,0x03e180c0,0x8b815a05,0x0000016a },
  58572. { 0x53f5ef65,0x2ca085f6,0x77b25105,0x61dfbbf9,0xa3346fe6,0x88ea87e3,
  58573. 0x1b95f7ef,0x25ddfdee,0x5b65eaec,0x22074e69,0x4c2e023b,0x11869a15,
  58574. 0x42e83bb5,0x8601b577,0xfa877e7d,0x1464652c,0x00000015 } },
  58575. /* 205 */
  58576. { { 0x57fa58f1,0x250853c8,0x4ca4c670,0xb58a4e68,0x1b81f40d,0x07b96d0a,
  58577. 0x558e8cbd,0xa4651e10,0x42e388cf,0x1a64046e,0x44436088,0x51b0d539,
  58578. 0xe26b8fd0,0xc2bf35b3,0x5702cfce,0x4ae78709,0x000000fd },
  58579. { 0xdf53d498,0x3c79bc29,0x1137f624,0x4cf31c4e,0x17a3cedf,0x93b6856c,
  58580. 0x6cd9115d,0x2461131c,0x9228cddb,0xab30a453,0x8d202bf1,0xe97757b6,
  58581. 0xe6108612,0xa666de7c,0x4f6026b4,0xc200fe65,0x00000051 } },
  58582. /* 206 */
  58583. { { 0xb1a2b4b5,0xea96103c,0x843c0968,0x98dccbfe,0x986ffb5b,0x6a37072d,
  58584. 0x169d3ac2,0x2fa07af2,0x771371f1,0x8bb85b9a,0xe7c299ef,0xeae10d34,
  58585. 0xe2372efc,0x3d4bdc69,0x8dd856f1,0x378df75d,0x00000039 },
  58586. { 0xde7ff5d9,0x31e902ff,0x325a09ca,0x0e9a85d2,0xf4192fcd,0xd71b93a6,
  58587. 0x15b076b3,0xf52a5737,0x6e711d1c,0xd726aa86,0x2c292819,0x0b61b1df,
  58588. 0xc8015de6,0x224e575c,0x18b79e47,0x68e893e1,0x000001dc } },
  58589. /* 207 */
  58590. { { 0x6ffeda73,0xb7924ff9,0xa0da2018,0xe709f406,0xf89584df,0x368e20ea,
  58591. 0x8355a040,0x0095112e,0xfd777d7c,0x259d4528,0x2bf8f2c8,0xb0c49565,
  58592. 0x44c5311b,0x7f631928,0x8466d9d5,0x698d0e4f,0x000000d5 },
  58593. { 0x015d204d,0xe10d64fa,0x6dd10c53,0x7b626bfa,0xa7698c94,0x087f8e63,
  58594. 0x05337a56,0x525a6547,0xdf5c782f,0x558e2244,0x855fbaff,0x48aa1e41,
  58595. 0x47ee3830,0x48f2218e,0x138463d3,0xf2523959,0x0000004d } },
  58596. /* 208 */
  58597. { { 0xd8695310,0x76f4fd69,0x7e8768ea,0xe28eb09f,0xe0d532a8,0x039c1812,
  58598. 0xc572ac79,0xdda67744,0x785d6293,0x1f9800e0,0x3da76bb2,0x2bfe2a5a,
  58599. 0xa2bc7217,0x6ed15b90,0xd1788a8e,0xd80e61bf,0x0000004c },
  58600. { 0x16730056,0xb9f40370,0xdced3d43,0x46f45fef,0x1aa50742,0x0afd763c,
  58601. 0xff92ae73,0x21e5c652,0x1bb2063f,0x6ef0830d,0x12d22540,0x18306ecc,
  58602. 0x1f15001c,0x4edd9b3a,0xc0cc5424,0xe4eb25b8,0x000001f4 } },
  58603. /* 209 */
  58604. { { 0xa1db5c18,0xed61a714,0x7677074c,0x9454e61e,0x7bf685de,0xe970fbe5,
  58605. 0xd2145be5,0x221b0c53,0xee49a5f2,0xb931881b,0x14b11d03,0x00b91afa,
  58606. 0x3ec22137,0xc6aefe49,0x526200af,0x50554e94,0x0000013c },
  58607. { 0x7364c92e,0xd42c45e7,0x735218e8,0xe0500265,0x84d3f3c5,0xd281da02,
  58608. 0xdbf7646b,0x312f8424,0x485f304f,0xe1a88f2a,0x1127a513,0x583f5631,
  58609. 0x1a60e0bc,0xed7950c7,0x4b7b70a4,0x92855e10,0x000000c6 } },
  58610. /* 210 */
  58611. { { 0x644614e7,0x8d06185c,0x4749a424,0x2e906cae,0x2587e528,0x585412ea,
  58612. 0xd12857cd,0x3763990a,0xba5593b5,0x770c7f70,0xdd5d2a46,0xc2cf6dc4,
  58613. 0x3b69a1ba,0x564da456,0x187895da,0x639f7e14,0x000001c8 },
  58614. { 0xf8589620,0x05c96b02,0x41e44054,0x2fe468a3,0x096ad09c,0xbf22da11,
  58615. 0x9c652aee,0xbc73c298,0x547e1b8f,0xcdef9f8b,0x977dbf73,0x7073785a,
  58616. 0x7e13552d,0x0a92a1aa,0x3a393d3f,0x22761140,0x0000015b } },
  58617. /* 211 */
  58618. { { 0x1fbfaf32,0x89a5a7b0,0xbe661d21,0x5c5a62d0,0xf5e3b44d,0x47970f5e,
  58619. 0xf43bbf62,0x3ea001ed,0x260ae5a0,0xa8e74285,0x2697c62c,0xeb899ebd,
  58620. 0x751a7643,0x36a003e6,0xba0725a6,0xef178c51,0x000000ea },
  58621. { 0x9bd51f28,0xaacf8e9f,0xa8712044,0x39febbdb,0x5bfc8365,0x8780ad3a,
  58622. 0x10e6f08f,0x408a34cd,0x8241ab0e,0x8104ca10,0x98a662a1,0x843e71ce,
  58623. 0x232048d6,0x9dce8514,0x1cf3d187,0x5cba23be,0x000001fa } },
  58624. /* 212 */
  58625. { { 0x2973a15c,0x2fe8c9d2,0xd42979f3,0x66fec8dd,0x0b6afb3e,0x39af4a39,
  58626. 0xab65ef22,0x0bb1e436,0x66c5fcdb,0x8f26201e,0x5af4870b,0x3cffe8a3,
  58627. 0x2bb44e24,0x65ae286f,0x51dd1722,0xda2e283a,0x00000114 },
  58628. { 0xc1e3d708,0x4a9c9a56,0x1cb0efa6,0x4fe62d3f,0x97e87540,0xf0702984,
  58629. 0x3cea46fa,0x138b7d6b,0x83886263,0x0780634e,0x71c30909,0x27e84280,
  58630. 0xe5838647,0xf0af79d7,0xb236a267,0xc1b86582,0x00000104 } },
  58631. /* 213 */
  58632. { { 0xa526c894,0x32ff09ed,0x14ac7d23,0x95abf120,0x3cd92934,0xb6f94dcd,
  58633. 0x92e6b556,0xffaaeb12,0x1036c31b,0x193796ea,0x707ff32e,0xa9d237e7,
  58634. 0x829d67b8,0xd65a5b0d,0xdb29248b,0x48edb556,0x000001b3 },
  58635. { 0xded46575,0x6ee9f9b2,0xffa69acf,0x496ca08a,0xf16d37d1,0xd5aeb3a1,
  58636. 0x789e5d01,0x4a507db1,0xc827cc45,0x05e2ce29,0x2964e677,0x29b6e4a5,
  58637. 0x4c0e46f2,0x0563b0ba,0x4bc46485,0xe75c2448,0x000000a3 } },
  58638. /* 214 */
  58639. { { 0xd2f6615d,0x0fcb476f,0xd98da9a9,0x4b7f9b78,0xd2bdf107,0xe2fddf1c,
  58640. 0x9b956f31,0x2bda3086,0xb596eadf,0xf3cca2f7,0x355b2538,0x91c09f8b,
  58641. 0xc6c846db,0x46f3f6f3,0x2a14642e,0x9bb9398e,0x000001ff },
  58642. { 0xa17bd645,0x5118d4f5,0xdbd6d552,0x57033eab,0x734d0957,0x007e86fc,
  58643. 0x5f53c435,0x98ca065f,0xfd27dd19,0x9949d9bf,0x6952d1ca,0xddc4e304,
  58644. 0x81ac101c,0x84cab4fb,0x4a56b007,0x46d079f9,0x00000003 } },
  58645. /* 215 */
  58646. { { 0xa6bfdedd,0x95eb8e4f,0x7a74c6f9,0x993a285e,0x3d09a252,0x8bd5d4d1,
  58647. 0x19a5f767,0xeaa10be6,0x0cebb340,0xd3db083e,0x1dbf7a83,0xc633a78b,
  58648. 0xc30f23e1,0x2664bc3e,0x07a08379,0x6630f8f1,0x000001c9 },
  58649. { 0xdef86a80,0xbbf4cb4b,0x3f8259ab,0x1fa4ec78,0x609532c8,0xa4bf7604,
  58650. 0x8b909e92,0x71bb7acc,0x17884160,0xca1d7317,0xca1ab928,0x7f7f14be,
  58651. 0x5f8455a5,0xbfea016e,0xbf21e899,0x7b8c76b9,0x0000002d } },
  58652. /* 216 */
  58653. { { 0x4b9f8e7d,0x46860563,0x63fc58a8,0x201176b7,0x2feed68a,0xe7a5da7e,
  58654. 0x65183190,0xcc67763e,0xe9377ad6,0x7d7d0102,0x77032321,0xccfc4720,
  58655. 0x534bb505,0x573ee031,0x0f1a2769,0x1bf1ef8c,0x000000f3 },
  58656. { 0x0c935667,0x635f5c4b,0x060d2b8b,0x74152c39,0x37c3a574,0xeffaac2e,
  58657. 0x0b72e0cd,0xfd5fcc4c,0xf4f60247,0xb743f9b9,0x79e16f33,0x05c2e354,
  58658. 0x3074ef9c,0xa2234c47,0x495aace3,0x4092f279,0x00000124 } },
  58659. /* 217 */
  58660. { { 0xb30f9170,0x5bfd7851,0x37fce5b1,0x715aa1e9,0x928437b9,0xcffd55e0,
  58661. 0xc32f1273,0x88acd259,0x48be1e34,0x5a145cf2,0x7a5bc62b,0x3a340860,
  58662. 0x18156f46,0x6296eb15,0x2774e1c3,0x397fad19,0x000001e7 },
  58663. { 0x9c8225b5,0x362f99f4,0x46b77c4d,0x33efce49,0x8541e91b,0x451df530,
  58664. 0x38f3d693,0x0bd2d934,0xe727b54e,0x0b5de2d6,0x7622d940,0x42d929c2,
  58665. 0x56f6a94b,0x36ace723,0xfccaf205,0x64a18cd5,0x00000044 } },
  58666. /* 218 */
  58667. { { 0xaba95d63,0x8dbe0aab,0x7b4b346d,0x92780c61,0x0e0d8142,0x6430f863,
  58668. 0xb56ef04c,0x875be02a,0x785e3633,0xc28feb95,0xc12c93e4,0xd5401795,
  58669. 0xe36f82a3,0x89ff51c1,0x10eeafd6,0x3c48c895,0x0000016b },
  58670. { 0xd4f064be,0x79287eba,0x54ebda99,0x1a77d555,0x623727ea,0x46745ef2,
  58671. 0x89f366c6,0xa911f591,0xc59d6ebd,0x7e5435cd,0x7524d213,0x3a84daea,
  58672. 0x4395b38d,0xc7b1dd1c,0x1a823c49,0xca13e704,0x0000001c } },
  58673. /* 219 */
  58674. { { 0x874d64b0,0x6399860c,0x1653ce0c,0x3375b092,0xeaa11986,0x16700000,
  58675. 0x621cd15d,0x62c67909,0x77d70dcd,0xbe1d7dd6,0x305bd4cd,0xeff0f270,
  58676. 0x362f8f30,0x076ec621,0x7e445b78,0x81204816,0x000001d8 },
  58677. { 0x161f9758,0x81749a0e,0xa3c4fce2,0xe60915fe,0x911dd8af,0xf537ce41,
  58678. 0x79a51a09,0xfe36a8ac,0x2ca5cf8e,0x67fb54b4,0xe49057f5,0x1bdcae07,
  58679. 0xa4244b64,0xb71ff0c5,0x4b606583,0x4815a536,0x00000106 } },
  58680. /* 220 */
  58681. { { 0xef39cc39,0x78c69c3e,0xfa6356d1,0x98304564,0x412fb990,0xbd3c3542,
  58682. 0x79dbb2a5,0xa1d531d3,0xe7e75e3d,0x4865f188,0x0b0147b1,0x2dac4e22,
  58683. 0x33d29ab0,0xf59e51ca,0x37b074ef,0xc964f7fe,0x000000f1 },
  58684. { 0x0e301262,0x7080c0a6,0x5390a22d,0x9a458060,0xcc8a9029,0xda677f9a,
  58685. 0x14c0f1c2,0xdfae9057,0x6e66d9f7,0x3665ff16,0x47846924,0xc866dd8c,
  58686. 0xc4cc307c,0xc5afe98f,0xe0bf50e4,0x60e3ba63,0x00000039 } },
  58687. /* 221 */
  58688. { { 0x959ecdb3,0x1a785136,0xf9e959be,0x289af617,0xcde0dc88,0x5145b2b8,
  58689. 0x7c079e15,0xfe9070b0,0x50e22415,0xf77f04d3,0x358d6d42,0xb3ab7372,
  58690. 0xba7b629a,0x14fd41b9,0x7400fd25,0x7b32d80e,0x00000193 },
  58691. { 0x7147886f,0xe5d80d4d,0x576c81ca,0xe08ced61,0x642717bb,0xe14e8692,
  58692. 0xabb4bd21,0x9dcdf198,0x6530308b,0x658be646,0xd99d19c7,0xfbf192da,
  58693. 0x304ab126,0x55a3d1b3,0xfa24de31,0x943f4be5,0x0000000e } },
  58694. /* 222 */
  58695. { { 0x7fe9ea48,0xc5424058,0x61b57486,0xaf24f825,0x78719740,0x9d2c413c,
  58696. 0x70eb874d,0x27a9be79,0xb62ba3aa,0x43fef8e0,0x2c1bf0ac,0x0a23f286,
  58697. 0x4af130e1,0x51c276f3,0xae55cebf,0xf6cd1e9a,0x00000185 },
  58698. { 0x40369093,0x24defa7f,0x58581e0a,0x11f1d9d6,0xe512ed9e,0x9900bf33,
  58699. 0xed120896,0xbf8a8459,0x8b73c399,0x8324555e,0x8f6f54fe,0x54a30569,
  58700. 0x3c252355,0x2a9d6da5,0x2a093b31,0xe6a6f904,0x0000016a } },
  58701. /* 223 */
  58702. { { 0x152cdd35,0xb2e123c9,0x86402ef1,0xae6e43a8,0xb9ce5bd5,0x892bf0df,
  58703. 0x75804914,0xb4acb84a,0xf502eec2,0x8c7f55ff,0xaa33ef4e,0x9c8a7b93,
  58704. 0xfd9d2001,0x06b10357,0x0ba3bceb,0x3e319ff0,0x00000027 },
  58705. { 0xabe360a3,0x182c2f77,0xadfefca6,0x57ef5c84,0x650b6fcc,0x9a4f0ca6,
  58706. 0xaaf0b202,0x3f4f8e56,0xa24ef156,0x5c8508a0,0x1ea45f13,0xd8f62fd9,
  58707. 0x28036dbe,0xf2c923a0,0x1a4d103b,0x4a9ca4c0,0x0000018a } },
  58708. /* 224 */
  58709. { { 0x5448e339,0x2a3fb798,0x18a39976,0xde8770cf,0x7a69170c,0x1160574d,
  58710. 0x2b6067ac,0x4bb05c59,0x848138ab,0xde0d2db0,0x4909e794,0x149dab92,
  58711. 0x790315f7,0x83a336b6,0xa335a258,0xcd9074d9,0x0000013c },
  58712. { 0xac1b784d,0xe839c5e0,0xee527ae1,0xab65c8c6,0xa1c88ec0,0xd3c86146,
  58713. 0x46c1bf58,0x2201f790,0x3fda502a,0x71cec627,0x225b9065,0xff3f88eb,
  58714. 0xc556dfcd,0x6c1f0c98,0x484fa5cc,0xaa3222aa,0x000000ac } },
  58715. /* 225 */
  58716. { { 0xc9b4dfd6,0x17e74bc3,0xf8e76293,0x25ba8053,0x9d8c3520,0x0307dc05,
  58717. 0xb85a20b4,0x1c9036cc,0x23871359,0xf2c63f0a,0xca95fb4e,0x1a99d9d8,
  58718. 0x9850c6c6,0x3d7c4f39,0x68299668,0x162969c9,0x00000169 },
  58719. { 0xcb63ee53,0x7d13c267,0x75eac353,0x67b12e61,0x191abfca,0xb3369a11,
  58720. 0xee1af69f,0x5ad0649d,0x11dc11e7,0x4d7a6f00,0xdb9f9765,0x80f030b8,
  58721. 0xf0ab1332,0xa20001a3,0x39d8cc62,0xe17c98d2,0x00000194 } },
  58722. /* 226 */
  58723. { { 0x1d8fe898,0x720d80b4,0x32184534,0x8d7a28b7,0x04f21740,0xf1f3c385,
  58724. 0x166aa6af,0x5d381cd5,0xcc560e35,0x9cde6084,0x5e61e2cd,0xcb041f0a,
  58725. 0xd9b4951a,0x621116f5,0x7ee2ac2c,0x509e16d3,0x000000c4 },
  58726. { 0x2c6fd79e,0xb82a20c4,0x3af78b0e,0x95b7ee4e,0xbad819ca,0x3d9b63c1,
  58727. 0x98552569,0x10d674de,0xf9c19d0f,0x17de64b2,0x47c5e6a9,0xa03fabaf,
  58728. 0x2ce2db6f,0x858bc4ad,0x1fc9d18e,0x76c2380a,0x000000c9 } },
  58729. /* 227 */
  58730. { { 0xb064f114,0x91171ef8,0x4f2f0f4c,0x83cb1565,0x57b262b7,0x30525854,
  58731. 0x0f34936c,0x468c6701,0x99a41fed,0xef26d2fe,0xa7f7f6a9,0xf6da2267,
  58732. 0xa01bfc1b,0x2563b8db,0xc340ed40,0x14b36c85,0x0000000e },
  58733. { 0x25db67e6,0x5e57e264,0x7f2e905f,0x85df4e89,0x026c4268,0x7832e514,
  58734. 0x3e875093,0x312be262,0x3c538691,0x856b5bd8,0x95734f9d,0x5b1cae55,
  58735. 0xd5aa4861,0x5a07bfe2,0xce8abb58,0x7a4c96f0,0x000001d0 } },
  58736. /* 228 */
  58737. { { 0x523aa2e9,0x7bf54d05,0xed3d0860,0xc8841e0c,0x7f9bfb69,0x5683f6e2,
  58738. 0x162bdf85,0xdcb07f44,0x07b0dcc9,0x62d17839,0x657a536e,0xa2cbb8ab,
  58739. 0x7cf47d3c,0x98b9a0d2,0x5eea6370,0xff154d68,0x000001f2 },
  58740. { 0x56b232ac,0x568b768a,0x3f2a52ab,0x4e8d6e36,0x8837fc60,0xbae87a16,
  58741. 0xd10a7691,0xebc58a83,0xf9455fbe,0xad5e4af0,0x7d654e2e,0x1a20d6c3,
  58742. 0xda7c8255,0x8c40fcb9,0x60d9b931,0x6d7b3cd7,0x000000b2 } },
  58743. /* 229 */
  58744. { { 0xbb2eaf45,0x7b090c3e,0x62ffb92f,0xed24d91c,0xa736f23d,0xbf2a3ea4,
  58745. 0x6ff0fde3,0xb5b99ebd,0xca1102f5,0xbca2b55d,0x07e032a8,0xf6203cd8,
  58746. 0xa8bf17a8,0x5410b448,0xe1dc55b1,0xb86660a7,0x00000109 },
  58747. { 0x02a2fbd8,0xb148b1da,0x3b22e8a5,0xfed85e8b,0x8712b509,0x1378a0e4,
  58748. 0xc6a3e516,0x68560148,0x1633b503,0x7100921c,0x25512711,0x93925143,
  58749. 0x07d31047,0x7b4931d2,0x8542e0bb,0x623e722b,0x000000ea } },
  58750. /* 230 */
  58751. { { 0x24972688,0x084823d3,0x003f5762,0x58b83c12,0x6d0d4528,0x194d6690,
  58752. 0x2c6f747e,0x84219584,0x0146d89a,0xc8f8a2e9,0x7451bbc2,0x29ec1de7,
  58753. 0xf7f284fa,0xf622b6b8,0x7b71e44f,0x83f1dbe9,0x00000060 },
  58754. { 0x999dd56b,0x99649333,0x97a47de9,0x2cfac0ba,0xbbe8fb20,0x6660d8ae,
  58755. 0xf61d7bca,0x47c29dd8,0x85adc14d,0x6f5fb51d,0x4f9fd41c,0xe65ac788,
  58756. 0xff513e6c,0x1ce69dd4,0xffe59d3e,0x1ace591e,0x00000023 } },
  58757. /* 231 */
  58758. { { 0xa9fda771,0x2e67a438,0x8663100e,0x626f652c,0xe133f23b,0xdfb19e48,
  58759. 0x035d2d1f,0x599f88f2,0x8d13e878,0x1723a112,0xfb51ce07,0x890aa292,
  58760. 0xbbd9ba82,0xe5f3a70e,0x374514b4,0xdde82673,0x00000155 },
  58761. { 0xd6f59a95,0x08b2b77e,0x02020420,0x93f853e3,0xebac7797,0x52252ac1,
  58762. 0xb56b6676,0x6ecdcb99,0x9722a500,0x4abdb9f9,0x04e2bad0,0x26210f3f,
  58763. 0x3034dd4d,0x0ca5a0ff,0xdac0b80d,0x333d8080,0x00000041 } },
  58764. /* 232 */
  58765. { { 0x35a85a06,0xe8510709,0x42ef1b44,0x4e166e76,0xa07b3a6d,0x84a90b71,
  58766. 0x30329e6a,0xd6dd6c00,0x3d555259,0x20c4ba65,0x6f8ad05e,0xee3b26af,
  58767. 0x2ab4cccd,0x20e3d541,0xa9406424,0x79798934,0x000001bd },
  58768. { 0x8e0c7ff0,0xf2a1d184,0x9543b340,0xbae85efc,0xf51d318b,0xe96431ae,
  58769. 0x75878fa6,0xe5d3ed4e,0xc2895f52,0x4d2a29db,0x1f11067c,0x3af27877,
  58770. 0x9e7f4ee5,0x6ccde964,0xa56d74da,0x35188da1,0x00000192 } },
  58771. /* 233 */
  58772. { { 0x03d310ed,0xb0832120,0x987b0311,0xd20ee8cc,0x84c558a8,0x9e549d26,
  58773. 0xb7167ec8,0x5e25f3ce,0x4bf55bb5,0xacf114f4,0x061c9017,0x819edc77,
  58774. 0xdeb343c0,0x759a44e6,0x04c9b5ed,0x58df9f7e,0x00000078 },
  58775. { 0x3bf13222,0x4fa47ebb,0xea07da11,0x1e451dcd,0xc0d8242f,0x1be9fac3,
  58776. 0x36eb871e,0x93257d4d,0xbea3190d,0xf49e775a,0x4ebe2b33,0x406d191f,
  58777. 0x0c110096,0x67aac53c,0xd381ac78,0x5215cf8b,0x000001f4 } },
  58778. /* 234 */
  58779. { { 0xfa493b79,0x387e8a8e,0x4eb1c2ac,0xb20e270b,0x9ff22320,0x9f393fa0,
  58780. 0xa91c393d,0x5ee1baae,0x138a8d96,0xdeda961a,0x97bd50e4,0x69ab238c,
  58781. 0x2363c8e0,0xff68d48a,0xce4c4c16,0xaf8e00e5,0x00000158 },
  58782. { 0xcfc509a1,0x6ccdcf06,0xc26cc075,0x60f411ef,0x4d9c57f0,0x6d0cdfd6,
  58783. 0x32e99cac,0xa9514853,0x8b8e9510,0x58f9ab3d,0xb10dc3fd,0xa7e98709,
  58784. 0x75ef3509,0x8390843d,0x5a9312c7,0x28ccc9d0,0x000001b6 } },
  58785. /* 235 */
  58786. { { 0xe341463f,0x1d934f00,0x150da7a0,0x14c8a6ce,0x4109553f,0xdb4860fc,
  58787. 0xa93f4a91,0xc23bde5a,0x2cd58067,0x9f47c787,0x8433dc80,0x1d330054,
  58788. 0x75a32a7d,0x0c0be7f9,0x88c75da9,0x08b777d5,0x0000012e },
  58789. { 0x61a10d37,0xdfc12817,0x5c50f5a5,0xed7b6181,0x79477c60,0x28af95db,
  58790. 0x33c5310b,0xa0aa2b77,0x53118267,0x905faab8,0x6b41959f,0xf40e9816,
  58791. 0x16b37784,0x9ccb4252,0x69866acc,0x6835d77c,0x000000c5 } },
  58792. /* 236 */
  58793. { { 0x2b450a66,0xe9d714cb,0x7dbfdc14,0x1318885c,0xb466a0c0,0x655a8d85,
  58794. 0x5bdfc1a6,0x02a21e99,0xe67792d1,0x7a0d7c98,0xb550a797,0x2a01bb57,
  58795. 0x5d74d337,0x42c46233,0x88dad495,0x7be4e1c0,0x0000008b },
  58796. { 0x95812273,0x1873b03f,0xee3f757f,0x2e26ed32,0x6da6217a,0x2c710eae,
  58797. 0x261d9f4f,0x9b50b574,0xb7c1da2d,0x43971fa9,0xc4a85de7,0x22c4fb87,
  58798. 0xec22137b,0xf72c3451,0x77ba1926,0x1345668c,0x00000173 } },
  58799. /* 237 */
  58800. { { 0x8a3ba183,0x3e3e8c7a,0xfe389fa7,0x4e8cebbb,0x0f9ba60f,0x8ea44687,
  58801. 0xcb601a83,0x55176e35,0x12e52db4,0xf90bdc26,0x8f712bf1,0x95f9e459,
  58802. 0xbea054cd,0x9bd3200f,0xdd5fd40b,0x2cf19bf6,0x0000017a },
  58803. { 0x66736feb,0x71cf6ca2,0xde7cfe2f,0xbde86f49,0xfc290563,0xc60abce8,
  58804. 0x726b6e4f,0xaae8a3ce,0x3f29235b,0xd2382445,0x650ffa5e,0xa4b557f5,
  58805. 0x113ef744,0xa1453e54,0x3e426dd2,0x7c676a53,0x000001b0 } },
  58806. /* 238 */
  58807. { { 0x35d96872,0xf5e603f2,0x3fa5b8ca,0xab1a23cc,0xe988dc5f,0x5459871b,
  58808. 0xd430c0bd,0xe32e8489,0x764d9cc3,0x7ec269e0,0xf2c0c40d,0xf7238212,
  58809. 0x887b83b4,0x2d946183,0x2f18a411,0x281fa671,0x00000010 },
  58810. { 0x64858b37,0x8028048f,0x357de5d9,0xe0e149af,0x619ebb18,0xb2218791,
  58811. 0x9f2b0ba0,0x210200b3,0x1039cbae,0x5a87eae6,0x39579d1d,0x4efdcddb,
  58812. 0x2788515e,0x1b388eaa,0xc81878aa,0x1a552c3c,0x0000002c } },
  58813. /* 239 */
  58814. { { 0x0ea723dc,0x7ac7f500,0x42b15231,0x0a5f04f4,0xbe885c86,0x63d49445,
  58815. 0xff119702,0x61f9993f,0xc4c58cea,0xc3fba45c,0xb9cd6036,0xe6d151e6,
  58816. 0x57b923bb,0x75a3ab15,0xceb2fd46,0x4ec07c52,0x00000147 },
  58817. { 0xed88239d,0xc46a3d32,0x835ae694,0x0d1b8ae6,0x9feeb2e7,0xf4fde325,
  58818. 0x43bc0bb5,0x223bf71c,0x8f62a705,0x3cd220b7,0x9fe799a5,0x2224860e,
  58819. 0x24ab7f93,0xd8558703,0xb594958b,0x8e0f7330,0x0000010f } },
  58820. /* 240 */
  58821. { { 0x3c67d520,0xaf35c7bb,0x23fca9ec,0xd8f4958b,0x8bbaa808,0x0778f194,
  58822. 0x2135e8ae,0x418c30ce,0xc888eff7,0xcdd8d9a9,0xf73144ab,0x72075df0,
  58823. 0x4506a534,0xb549c895,0x5fbb7fc5,0x4ef38979,0x0000011c },
  58824. { 0x43f5e698,0x3fe2c9ac,0xe38a5e3a,0xce77fcbc,0x3089c2e1,0x6d05c90e,
  58825. 0xac1d5801,0x5a74f3ff,0x381b9d2a,0xaeeda220,0xf5f3960b,0xd958b143,
  58826. 0x0db7abbe,0x65ffd051,0x7a05b718,0x8e97e680,0x000000ce } },
  58827. /* 241 */
  58828. { { 0x8ce86a83,0x2251e61b,0xbf7e7160,0x8604159f,0x48f03377,0xfc127dd7,
  58829. 0x45052242,0x87cb2c37,0x934ea09b,0xbd4950f4,0xc4679441,0x5146c403,
  58830. 0x23ba416a,0xe8ad4710,0xaf638eb1,0x89b81a60,0x000001b3 },
  58831. { 0xe8150c69,0xe699934e,0xe27c14bc,0x74f75908,0x6a0194ff,0x5dc0a891,
  58832. 0x1bd51b76,0x38f49d32,0x18779630,0x6bc3305e,0xfd3b4a68,0xfe2f3fbf,
  58833. 0xd7caf189,0x1409b377,0x9b8f109b,0x029ea13b,0x000001b3 } },
  58834. /* 242 */
  58835. { { 0x25a2fd88,0xef7938d2,0xceba0603,0x890f2f7c,0xd7a6dff4,0x4c3e1c80,
  58836. 0x2883f986,0x00c78f36,0x998e5305,0xed92b592,0x325ddc73,0x018a8f1b,
  58837. 0xd5d3708a,0x6dffd987,0x0d1f28bb,0xdcd3554f,0x00000059 },
  58838. { 0x23a74e7d,0x17c6e41d,0x5db32df6,0x94b61ebe,0x9e7ffa0b,0x3c2fffa7,
  58839. 0x2ebb7a0d,0x473662b7,0x01adf9c3,0xa86415ee,0x54679264,0x1502c326,
  58840. 0x2fa09c57,0x16911349,0x24749086,0x897f34aa,0x00000195 } },
  58841. /* 243 */
  58842. { { 0xabadc253,0x4845d359,0xc797c95e,0xe054b92c,0x9a218212,0x22a9b5bd,
  58843. 0xa52b8827,0x9bb80a5e,0x2e61c676,0xea38e78e,0x08b0f8b3,0xfb274b1a,
  58844. 0xdb9d854c,0xb6aa42e3,0x56012d73,0x8ba22523,0x00000163 },
  58845. { 0x75c8c576,0x7cec0e6f,0xe4bc7dd2,0xabb20e7c,0x69d80726,0x0958a0c8,
  58846. 0x8a023eb7,0xa908c66a,0x76110b15,0xca9f50ea,0x186f61a6,0x668c9994,
  58847. 0x2a0a69d8,0x9ddf22ed,0xbbf8a10f,0xbfee1897,0x000001e0 } },
  58848. /* 244 */
  58849. { { 0x48319e4f,0x26d86818,0x5a586fa0,0x6be6f6b5,0x26713265,0xbef5d886,
  58850. 0x98529cfa,0xac252ac5,0x62b29cfb,0xe7cc45f1,0xa2a6358d,0xee050609,
  58851. 0x2940ac70,0xf7cb9ca4,0xa885b1f0,0xfb44aaec,0x000001ad },
  58852. { 0xe798678e,0x66b7a936,0x99540438,0xca01e103,0x816860b7,0xf2491e37,
  58853. 0xb745d857,0xeeffd483,0xa4705ed6,0x5dbb3628,0xb2a5d0f7,0x57d68d49,
  58854. 0x2389fee3,0xd1a8529a,0x1a7fd686,0xdbbc2549,0x000001ad } },
  58855. /* 245 */
  58856. { { 0x969686a3,0xe10cba20,0xe3c053f5,0x308b1c55,0x26f47102,0x1712b134,
  58857. 0x49033038,0x1f9165b1,0x2d01527b,0x45b72017,0xaa9a34e2,0x6fcf6647,
  58858. 0xb0be35c8,0x51f54b94,0x5a15e382,0xfccb22a5,0x000000e3 },
  58859. { 0x5b4dc0be,0xaa71e4ec,0xdb1cd5c4,0xbb136248,0x046e1007,0xf36bff43,
  58860. 0xda9c99a3,0x5a6806d7,0x8349bc50,0x9cbfc6ee,0xe13e0850,0x26871e73,
  58861. 0x67f448c1,0x5e6aa227,0x2da7baf9,0xba77787c,0x000001b9 } },
  58862. /* 246 */
  58863. { { 0xc5a73375,0x1abe58ee,0x7a8ac438,0x175df69d,0xceca835a,0x2cf3150a,
  58864. 0xf507d30f,0xb87b0609,0xc60b0424,0x9ae53a2b,0x410f90ec,0x4931e182,
  58865. 0xadd689bb,0x452c7d0f,0x47631a8e,0xab453491,0x00000013 },
  58866. { 0x8c84f3af,0xaf2dd856,0x1baae33e,0x829dc092,0x8b96b070,0x46542a85,
  58867. 0xe8a82516,0x42260d40,0x5c35322b,0xb9e5edac,0x39eda0d2,0xbca79560,
  58868. 0xb962b90a,0x86bd07c6,0xb1ec5302,0x2e22dac7,0x0000010a } },
  58869. /* 247 */
  58870. { { 0x239d8f0a,0x665fc09d,0xab8a1021,0x92b2e03c,0x0173477b,0xe4369768,
  58871. 0x8e361604,0xab38ed9f,0x9eb061be,0x79b0091d,0x3e845670,0xcd422654,
  58872. 0x2fe1a2e0,0xa0f77ec7,0x760a030f,0x1d242162,0x00000093 },
  58873. { 0xf8646bc3,0xfa9f834c,0x40ae96f9,0x7df94a52,0x379177d1,0x901c3890,
  58874. 0xffeb66cd,0x9dfd0644,0x77b92465,0x81aec2ec,0xcd981d4f,0x2df3b7f2,
  58875. 0xf377b093,0xc9bc3f69,0xdd859d8b,0xdaef34f3,0x00000125 } },
  58876. /* 248 */
  58877. { { 0xa2c123bc,0xac08451b,0x0818fa54,0xd1e83a68,0x98957b8a,0x56dd5702,
  58878. 0xf0f12f16,0xcc7f2e34,0x0a9fa14d,0x1f6a9c33,0xb2fe782c,0xefc9a2bb,
  58879. 0x709f54dd,0xd319c697,0xd6460a53,0x0b8238cb,0x000001dc },
  58880. { 0x44dfb6f6,0xf6492901,0x6e401d26,0x270d7cb4,0x48537ad8,0x1a70a40e,
  58881. 0x70d8dbd9,0x84d661b5,0xf170d58b,0xca27223a,0x6344e1d2,0xeeb4cf14,
  58882. 0xab9de1fa,0x2255fc95,0xdbdc5ea7,0xcd6e110a,0x000001f8 } },
  58883. /* 249 */
  58884. { { 0x78b8a0a7,0x2a57c6b9,0xe833edea,0x24b4aeb6,0x4bd13fe7,0x9e4617c1,
  58885. 0xfc2e8ee4,0xc4186888,0xfb147eef,0x8d398a49,0x2e662cfb,0xe9f191f1,
  58886. 0x958ba2ec,0x61872289,0x00b8d50d,0xbd6d0f1b,0x0000002d },
  58887. { 0x24c93cc9,0x895cfdfe,0xb9e718e7,0x29ed7780,0x38baf7eb,0x01c8ba58,
  58888. 0x4ddcbf69,0x0225387e,0xa180d6bb,0x64b250bf,0xc947c7c2,0x6d68e548,
  58889. 0x9923f3cd,0x82a7b632,0x2d103cd2,0xb8f03613,0x0000000f } },
  58890. /* 250 */
  58891. { { 0x8cd9d494,0x8198b3f0,0x94f4f9f3,0x9b2065b9,0x3c738fa9,0x7664a220,
  58892. 0xd8d229cb,0x199f4c14,0xc51c54b3,0xddad75c4,0xd213a332,0x9a32ce0b,
  58893. 0x888c7b2f,0xf3a21085,0x5b1ff20a,0x6defa362,0x000000d1 },
  58894. { 0x19a296eb,0x44e00548,0xd1a91313,0x1d94ff15,0xfeaa454f,0xd7dead2b,
  58895. 0x4d40bd7f,0xae65a803,0x1801a4af,0x604f147e,0xa5e0de77,0x983048f9,
  58896. 0xff572ca0,0xa3b19ca5,0x1821d117,0xa237dba7,0x000000e0 } },
  58897. /* 251 */
  58898. { { 0x91630ee8,0xedbabf84,0x05eb5301,0xde6589c2,0xa051f47b,0x9f7d2b2d,
  58899. 0x212bbe81,0xaeaa9f96,0x94292124,0xdced3d5e,0xf4435e5b,0x691f5b89,
  58900. 0x9411f66f,0x19604c33,0x4356f0da,0xb7fc09ca,0x000000e6 },
  58901. { 0xf74f811c,0x1294e413,0xdf8d8ddb,0x1a42d831,0x963418c9,0x27f57217,
  58902. 0x88ebcdec,0x5fde5218,0xea305bc9,0xfdd5e06e,0xac668b61,0xed1e6088,
  58903. 0xeb811861,0x333af016,0x15ddcebc,0x5ecb192d,0x000001c9 } },
  58904. /* 252 */
  58905. { { 0xe0bde442,0x927b37a3,0x66f7a73e,0xe0543fe8,0x8ed10c2e,0xd30d9d20,
  58906. 0xa6617a32,0xaf79c341,0xd1d5cf8b,0xe7367870,0xe3abcf8b,0x02d0dce9,
  58907. 0x772b5e7b,0xfe23d2dd,0x1ffc70c5,0x29fceea0,0x0000010b },
  58908. { 0x62d803ff,0x31bcae4d,0xdbc306a9,0x93ee913f,0xd8c10662,0xaf1de7ab,
  58909. 0xe7a6d658,0xd485782a,0x102f4e06,0x9126592e,0x136fafe6,0x91a3127f,
  58910. 0x88371213,0x46b93440,0xa31e1634,0x53bb4380,0x000000ba } },
  58911. /* 253 */
  58912. { { 0xca5636b0,0x62e517fc,0x6aba15c7,0x4296e021,0x212e7b2d,0x5aa8fd7c,
  58913. 0x5717ad84,0x9517ce6d,0x98b2f357,0xe762b85b,0xdf59b07c,0x42f996b5,
  58914. 0xf37ef6f0,0xf3732abb,0x4542b489,0xa5d145ea,0x0000015d },
  58915. { 0xaa7f6e3f,0x1e77c55e,0xaa4a05bc,0x3f4d99a7,0x45828227,0xa56d7d77,
  58916. 0x77b748fb,0xdb0895fb,0x0629f5d1,0x1c484cce,0x359803fb,0xf5b1c90a,
  58917. 0x1720b8d0,0x43ac4f29,0x72ac13f2,0x8c10bfe8,0x000000e9 } },
  58918. /* 254 */
  58919. { { 0xc06c4fd6,0x9d1c4785,0xd25c2b9d,0xbf4b9025,0xd4982f24,0x04135eb1,
  58920. 0xba4fef2b,0x3ab3edc2,0x98de07ab,0x55a5239f,0x096f4b7d,0xd5fc49ab,
  58921. 0x3844c815,0xc50a2960,0x15676b2b,0xdb1148d0,0x00000047 },
  58922. { 0x10f3bad9,0xc49f9cc5,0x022901d4,0x490888fc,0xc47b44df,0x917a55eb,
  58923. 0xf39f2b68,0x20b2ebc6,0x04e9962a,0x0c58e3af,0x573dd5b7,0x52ab7c1b,
  58924. 0xa329f76c,0x2b54add6,0x82f4ca3b,0x59dad1eb,0x00000108 } },
  58925. /* 255 */
  58926. { { 0xa182d1ad,0x662c4128,0x20916c45,0x7751796e,0xba681647,0xa7704272,
  58927. 0xb92c85c1,0xfac8b0fa,0xaefb2e07,0x207ab2df,0x7861b32d,0xc73530a0,
  58928. 0x88aed145,0x63dbed65,0x0a53a49d,0x547bcdca,0x000000bd },
  58929. { 0x87056b51,0xa7c1382f,0x130f9912,0xc3d91edb,0xd3805b42,0xf7c7de46,
  58930. 0xfd31a995,0x456101eb,0xcd3fb8aa,0x1efd22b4,0x9eb17bce,0xfe391df7,
  58931. 0x616c0c32,0xb4d4c0c6,0x711beef4,0x19f023be,0x00000112 } },
  58932. };
  58933. /* Multiply the base point of P521 by the scalar and return the result.
  58934. * If map is true then convert result to affine coordinates.
  58935. *
  58936. * Stripe implementation.
  58937. * Pre-generated: 2^0, 2^65, ...
  58938. * Pre-generated: products of all combinations of above.
  58939. * 8 doubles and adds (with qz=1)
  58940. *
  58941. * r Resulting point.
  58942. * k Scalar to multiply by.
  58943. * map Indicates whether to convert result to affine.
  58944. * ct Constant time required.
  58945. * heap Heap to use for allocation.
  58946. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  58947. */
  58948. static int sp_521_ecc_mulmod_base_17(sp_point_521* r, const sp_digit* k,
  58949. int map, int ct, void* heap)
  58950. {
  58951. return sp_521_ecc_mulmod_stripe_17(r, &p521_base, p521_table,
  58952. k, map, ct, heap);
  58953. }
  58954. #endif
  58955. /* Multiply the base point of P521 by the scalar and return the result.
  58956. * If map is true then convert result to affine coordinates.
  58957. *
  58958. * km Scalar to multiply by.
  58959. * r Resulting point.
  58960. * map Indicates whether to convert result to affine.
  58961. * heap Heap to use for allocation.
  58962. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  58963. */
  58964. int sp_ecc_mulmod_base_521(const mp_int* km, ecc_point* r, int map, void* heap)
  58965. {
  58966. #ifdef WOLFSSL_SP_SMALL_STACK
  58967. sp_point_521* point = NULL;
  58968. sp_digit* k = NULL;
  58969. #else
  58970. sp_point_521 point[1];
  58971. sp_digit k[17];
  58972. #endif
  58973. int err = MP_OKAY;
  58974. #ifdef WOLFSSL_SP_SMALL_STACK
  58975. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  58976. DYNAMIC_TYPE_ECC);
  58977. if (point == NULL)
  58978. err = MEMORY_E;
  58979. if (err == MP_OKAY) {
  58980. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 17, heap,
  58981. DYNAMIC_TYPE_ECC);
  58982. if (k == NULL)
  58983. err = MEMORY_E;
  58984. }
  58985. #endif
  58986. if (err == MP_OKAY) {
  58987. sp_521_from_mp(k, 17, km);
  58988. err = sp_521_ecc_mulmod_base_17(point, k, map, 1, heap);
  58989. }
  58990. if (err == MP_OKAY) {
  58991. err = sp_521_point_to_ecc_point_17(point, r);
  58992. }
  58993. #ifdef WOLFSSL_SP_SMALL_STACK
  58994. if (k != NULL)
  58995. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  58996. if (point != NULL)
  58997. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  58998. #endif
  58999. return err;
  59000. }
  59001. /* Multiply the base point of P521 by the scalar, add point a and return
  59002. * the result. If map is true then convert result to affine coordinates.
  59003. *
  59004. * km Scalar to multiply by.
  59005. * am Point to add to scalar multiply result.
  59006. * inMont Point to add is in montgomery form.
  59007. * r Resulting point.
  59008. * map Indicates whether to convert result to affine.
  59009. * heap Heap to use for allocation.
  59010. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  59011. */
  59012. int sp_ecc_mulmod_base_add_521(const mp_int* km, const ecc_point* am,
  59013. int inMont, ecc_point* r, int map, void* heap)
  59014. {
  59015. #ifdef WOLFSSL_SP_SMALL_STACK
  59016. sp_point_521* point = NULL;
  59017. sp_digit* k = NULL;
  59018. #else
  59019. sp_point_521 point[2];
  59020. sp_digit k[17 + 17 * 2 * 6];
  59021. #endif
  59022. sp_point_521* addP = NULL;
  59023. sp_digit* tmp = NULL;
  59024. int err = MP_OKAY;
  59025. #ifdef WOLFSSL_SP_SMALL_STACK
  59026. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  59027. DYNAMIC_TYPE_ECC);
  59028. if (point == NULL)
  59029. err = MEMORY_E;
  59030. if (err == MP_OKAY) {
  59031. k = (sp_digit*)XMALLOC(
  59032. sizeof(sp_digit) * (17 + 17 * 2 * 6),
  59033. heap, DYNAMIC_TYPE_ECC);
  59034. if (k == NULL)
  59035. err = MEMORY_E;
  59036. }
  59037. #endif
  59038. if (err == MP_OKAY) {
  59039. addP = point + 1;
  59040. tmp = k + 17;
  59041. sp_521_from_mp(k, 17, km);
  59042. sp_521_point_from_ecc_point_17(addP, am);
  59043. }
  59044. if ((err == MP_OKAY) && (!inMont)) {
  59045. err = sp_521_mod_mul_norm_17(addP->x, addP->x, p521_mod);
  59046. }
  59047. if ((err == MP_OKAY) && (!inMont)) {
  59048. err = sp_521_mod_mul_norm_17(addP->y, addP->y, p521_mod);
  59049. }
  59050. if ((err == MP_OKAY) && (!inMont)) {
  59051. err = sp_521_mod_mul_norm_17(addP->z, addP->z, p521_mod);
  59052. }
  59053. if (err == MP_OKAY) {
  59054. err = sp_521_ecc_mulmod_base_17(point, k, 0, 0, heap);
  59055. }
  59056. if (err == MP_OKAY) {
  59057. sp_521_proj_point_add_17(point, point, addP, tmp);
  59058. if (map) {
  59059. sp_521_map_17(point, point, tmp);
  59060. }
  59061. err = sp_521_point_to_ecc_point_17(point, r);
  59062. }
  59063. #ifdef WOLFSSL_SP_SMALL_STACK
  59064. if (k != NULL)
  59065. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  59066. if (point)
  59067. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  59068. #endif
  59069. return err;
  59070. }
  59071. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  59072. defined(HAVE_ECC_VERIFY)
  59073. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  59074. /* Add 1 to a. (a = a + 1)
  59075. *
  59076. * a A single precision integer.
  59077. */
  59078. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59079. static void sp_521_add_one_17(sp_digit* a_p)
  59080. #else
  59081. static void sp_521_add_one_17(sp_digit* a)
  59082. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59083. {
  59084. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59085. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  59086. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59087. __asm__ __volatile__ (
  59088. "LDM %[a], {r1, r2, r3, r4}\n\t"
  59089. "ADDS r1, r1, #0x1\n\t"
  59090. "ADCS r2, r2, #0x0\n\t"
  59091. "ADCS r3, r3, #0x0\n\t"
  59092. "ADCS r4, r4, #0x0\n\t"
  59093. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  59094. "LDM %[a], {r1, r2, r3, r4}\n\t"
  59095. "ADCS r1, r1, #0x0\n\t"
  59096. "ADCS r2, r2, #0x0\n\t"
  59097. "ADCS r3, r3, #0x0\n\t"
  59098. "ADCS r4, r4, #0x0\n\t"
  59099. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  59100. "LDM %[a], {r1, r2, r3, r4}\n\t"
  59101. "ADCS r1, r1, #0x0\n\t"
  59102. "ADCS r2, r2, #0x0\n\t"
  59103. "ADCS r3, r3, #0x0\n\t"
  59104. "ADCS r4, r4, #0x0\n\t"
  59105. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  59106. "LDM %[a], {r1, r2, r3, r4}\n\t"
  59107. "ADCS r1, r1, #0x0\n\t"
  59108. "ADCS r2, r2, #0x0\n\t"
  59109. "ADCS r3, r3, #0x0\n\t"
  59110. "ADCS r4, r4, #0x0\n\t"
  59111. "STM %[a]!, {r1, r2, r3, r4}\n\t"
  59112. "LDM %[a], {r1}\n\t"
  59113. "ADCS r1, r1, #0x0\n\t"
  59114. "STM %[a]!, {r1}\n\t"
  59115. : [a] "+r" (a)
  59116. :
  59117. : "memory", "r1", "r2", "r3", "r4", "cc"
  59118. );
  59119. }
  59120. /* Read big endian unsigned byte array into r.
  59121. *
  59122. * r A single precision integer.
  59123. * size Maximum number of bytes to convert
  59124. * a Byte array.
  59125. * n Number of bytes in array to read.
  59126. */
  59127. static void sp_521_from_bin(sp_digit* r, int size, const byte* a, int n)
  59128. {
  59129. int i;
  59130. int j;
  59131. byte* d;
  59132. for (i = n - 1,j = 0; i >= 3; i -= 4) {
  59133. r[j] = ((sp_digit)a[i - 0] << 0) |
  59134. ((sp_digit)a[i - 1] << 8) |
  59135. ((sp_digit)a[i - 2] << 16) |
  59136. ((sp_digit)a[i - 3] << 24);
  59137. j++;
  59138. }
  59139. if (i >= 0) {
  59140. r[j] = 0;
  59141. d = (byte*)r;
  59142. switch (i) {
  59143. case 2: d[n - 1 - 2] = a[2]; //fallthrough
  59144. case 1: d[n - 1 - 1] = a[1]; //fallthrough
  59145. case 0: d[n - 1 - 0] = a[0]; //fallthrough
  59146. }
  59147. j++;
  59148. }
  59149. for (; j < size; j++) {
  59150. r[j] = 0;
  59151. }
  59152. }
  59153. /* Generates a scalar that is in the range 1..order-1.
  59154. *
  59155. * rng Random number generator.
  59156. * k Scalar value.
  59157. * returns RNG failures, MEMORY_E when memory allocation fails and
  59158. * MP_OKAY on success.
  59159. */
  59160. static int sp_521_ecc_gen_k_17(WC_RNG* rng, sp_digit* k)
  59161. {
  59162. int err;
  59163. byte buf[66];
  59164. do {
  59165. err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
  59166. if (err == 0) {
  59167. buf[0] &= 0x1;
  59168. sp_521_from_bin(k, 17, buf, (int)sizeof(buf));
  59169. if (sp_521_cmp_17(k, p521_order2) <= 0) {
  59170. sp_521_add_one_17(k);
  59171. break;
  59172. }
  59173. }
  59174. }
  59175. while (err == 0);
  59176. return err;
  59177. }
  59178. /* Makes a random EC key pair.
  59179. *
  59180. * rng Random number generator.
  59181. * priv Generated private value.
  59182. * pub Generated public point.
  59183. * heap Heap to use for allocation.
  59184. * returns ECC_INF_E when the point does not have the correct order, RNG
  59185. * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
  59186. */
  59187. int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
  59188. {
  59189. #ifdef WOLFSSL_SP_SMALL_STACK
  59190. sp_point_521* point = NULL;
  59191. sp_digit* k = NULL;
  59192. #else
  59193. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59194. sp_point_521 point[2];
  59195. #else
  59196. sp_point_521 point[1];
  59197. #endif
  59198. sp_digit k[17];
  59199. #endif
  59200. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59201. sp_point_521* infinity = NULL;
  59202. #endif
  59203. int err = MP_OKAY;
  59204. (void)heap;
  59205. #ifdef WOLFSSL_SP_SMALL_STACK
  59206. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59207. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, DYNAMIC_TYPE_ECC);
  59208. #else
  59209. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, DYNAMIC_TYPE_ECC);
  59210. #endif
  59211. if (point == NULL)
  59212. err = MEMORY_E;
  59213. if (err == MP_OKAY) {
  59214. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 17, heap,
  59215. DYNAMIC_TYPE_ECC);
  59216. if (k == NULL)
  59217. err = MEMORY_E;
  59218. }
  59219. #endif
  59220. if (err == MP_OKAY) {
  59221. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59222. infinity = point + 1;
  59223. #endif
  59224. err = sp_521_ecc_gen_k_17(rng, k);
  59225. }
  59226. if (err == MP_OKAY) {
  59227. err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, NULL);
  59228. }
  59229. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59230. if (err == MP_OKAY) {
  59231. err = sp_521_ecc_mulmod_17(infinity, point, p521_order, 1, 1, NULL);
  59232. }
  59233. if (err == MP_OKAY) {
  59234. if (sp_521_iszero_17(point->x) || sp_521_iszero_17(point->y)) {
  59235. err = ECC_INF_E;
  59236. }
  59237. }
  59238. #endif
  59239. if (err == MP_OKAY) {
  59240. err = sp_521_to_mp(k, priv);
  59241. }
  59242. if (err == MP_OKAY) {
  59243. err = sp_521_point_to_ecc_point_17(point, pub);
  59244. }
  59245. #ifdef WOLFSSL_SP_SMALL_STACK
  59246. if (k != NULL)
  59247. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  59248. if (point != NULL) {
  59249. /* point is not sensitive, so no need to zeroize */
  59250. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  59251. }
  59252. #endif
  59253. return err;
  59254. }
  59255. #ifdef WOLFSSL_SP_NONBLOCK
  59256. typedef struct sp_ecc_key_gen_521_ctx {
  59257. int state;
  59258. sp_521_ecc_mulmod_17_ctx mulmod_ctx;
  59259. sp_digit k[17];
  59260. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59261. sp_point_521 point[2];
  59262. #else
  59263. sp_point_521 point[1];
  59264. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  59265. } sp_ecc_key_gen_521_ctx;
  59266. int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv,
  59267. ecc_point* pub, void* heap)
  59268. {
  59269. int err = FP_WOULDBLOCK;
  59270. sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data;
  59271. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59272. sp_point_521* infinity = ctx->point + 1;
  59273. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  59274. typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx)
  59275. >= sizeof(*sp_ctx) ? -1 : 1];
  59276. (void)sizeof(ctx_size_test);
  59277. switch (ctx->state) {
  59278. case 0:
  59279. err = sp_521_ecc_gen_k_17(rng, ctx->k);
  59280. if (err == MP_OKAY) {
  59281. err = FP_WOULDBLOCK;
  59282. ctx->state = 1;
  59283. }
  59284. break;
  59285. case 1:
  59286. err = sp_521_ecc_mulmod_base_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  59287. ctx->point, ctx->k, 1, 1, heap);
  59288. if (err == MP_OKAY) {
  59289. err = FP_WOULDBLOCK;
  59290. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59291. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  59292. ctx->state = 2;
  59293. #else
  59294. ctx->state = 3;
  59295. #endif
  59296. }
  59297. break;
  59298. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  59299. case 2:
  59300. err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  59301. infinity, ctx->point, p521_order, 1, 1);
  59302. if (err == MP_OKAY) {
  59303. if (sp_521_iszero_17(ctx->point->x) ||
  59304. sp_521_iszero_17(ctx->point->y)) {
  59305. err = ECC_INF_E;
  59306. }
  59307. else {
  59308. err = FP_WOULDBLOCK;
  59309. ctx->state = 3;
  59310. }
  59311. }
  59312. break;
  59313. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
  59314. case 3:
  59315. err = sp_521_to_mp(ctx->k, priv);
  59316. if (err == MP_OKAY) {
  59317. err = sp_521_point_to_ecc_point_17(ctx->point, pub);
  59318. }
  59319. break;
  59320. }
  59321. if (err != FP_WOULDBLOCK) {
  59322. XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx));
  59323. }
  59324. return err;
  59325. }
  59326. #endif /* WOLFSSL_SP_NONBLOCK */
  59327. #ifdef HAVE_ECC_DHE
  59328. /* Write r as big endian to byte array.
  59329. * Fixed length number of bytes written: 66
  59330. *
  59331. * r A single precision integer.
  59332. * a Byte array.
  59333. */
  59334. static void sp_521_to_bin_17(sp_digit* r, byte* a)
  59335. {
  59336. int i;
  59337. int j = 0;
  59338. a[j++] = r[16] >> 8;
  59339. a[j++] = r[16] >> 0;
  59340. for (i = 15; i >= 0; i--) {
  59341. a[j++] = r[i] >> 24;
  59342. a[j++] = r[i] >> 16;
  59343. a[j++] = r[i] >> 8;
  59344. a[j++] = r[i] >> 0;
  59345. }
  59346. }
  59347. /* Multiply the point by the scalar and serialize the X ordinate.
  59348. * The number is 0 padded to maximum size on output.
  59349. *
  59350. * priv Scalar to multiply the point by.
  59351. * pub Point to multiply.
  59352. * out Buffer to hold X ordinate.
  59353. * outLen On entry, size of the buffer in bytes.
  59354. * On exit, length of data in buffer in bytes.
  59355. * heap Heap to use for allocation.
  59356. * returns BUFFER_E if the buffer is to small for output size,
  59357. * MEMORY_E when memory allocation fails and MP_OKAY on success.
  59358. */
  59359. int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
  59360. word32* outLen, void* heap)
  59361. {
  59362. #ifdef WOLFSSL_SP_SMALL_STACK
  59363. sp_point_521* point = NULL;
  59364. sp_digit* k = NULL;
  59365. #else
  59366. sp_point_521 point[1];
  59367. sp_digit k[17];
  59368. #endif
  59369. int err = MP_OKAY;
  59370. if (*outLen < 65U) {
  59371. err = BUFFER_E;
  59372. }
  59373. #ifdef WOLFSSL_SP_SMALL_STACK
  59374. if (err == MP_OKAY) {
  59375. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  59376. DYNAMIC_TYPE_ECC);
  59377. if (point == NULL)
  59378. err = MEMORY_E;
  59379. }
  59380. if (err == MP_OKAY) {
  59381. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 17, heap,
  59382. DYNAMIC_TYPE_ECC);
  59383. if (k == NULL)
  59384. err = MEMORY_E;
  59385. }
  59386. #endif
  59387. if (err == MP_OKAY) {
  59388. sp_521_from_mp(k, 17, priv);
  59389. sp_521_point_from_ecc_point_17(point, pub);
  59390. err = sp_521_ecc_mulmod_17(point, point, k, 1, 1, heap);
  59391. }
  59392. if (err == MP_OKAY) {
  59393. sp_521_to_bin_17(point->x, out);
  59394. *outLen = 66;
  59395. }
  59396. #ifdef WOLFSSL_SP_SMALL_STACK
  59397. if (k != NULL)
  59398. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  59399. if (point != NULL)
  59400. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  59401. #endif
  59402. return err;
  59403. }
  59404. #ifdef WOLFSSL_SP_NONBLOCK
  59405. typedef struct sp_ecc_sec_gen_521_ctx {
  59406. int state;
  59407. union {
  59408. sp_521_ecc_mulmod_17_ctx mulmod_ctx;
  59409. };
  59410. sp_digit k[17];
  59411. sp_point_521 point;
  59412. } sp_ecc_sec_gen_521_ctx;
  59413. int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
  59414. const ecc_point* pub, byte* out, word32* outLen, void* heap)
  59415. {
  59416. int err = FP_WOULDBLOCK;
  59417. sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data;
  59418. typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  59419. (void)sizeof(ctx_size_test);
  59420. if (*outLen < 32U) {
  59421. err = BUFFER_E;
  59422. }
  59423. switch (ctx->state) {
  59424. case 0:
  59425. sp_521_from_mp(ctx->k, 17, priv);
  59426. sp_521_point_from_ecc_point_17(&ctx->point, pub);
  59427. ctx->state = 1;
  59428. break;
  59429. case 1:
  59430. err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  59431. &ctx->point, &ctx->point, ctx->k, 1, 1, heap);
  59432. if (err == MP_OKAY) {
  59433. sp_521_to_bin_17(ctx->point.x, out);
  59434. *outLen = 66;
  59435. }
  59436. break;
  59437. }
  59438. if (err == MP_OKAY && ctx->state != 1) {
  59439. err = FP_WOULDBLOCK;
  59440. }
  59441. if (err != FP_WOULDBLOCK) {
  59442. XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx));
  59443. }
  59444. return err;
  59445. }
  59446. #endif /* WOLFSSL_SP_NONBLOCK */
  59447. #endif /* HAVE_ECC_DHE */
  59448. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  59449. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59450. static void sp_521_rshift_17(sp_digit* r_p, const sp_digit* a_p, byte n_p)
  59451. #else
  59452. static void sp_521_rshift_17(sp_digit* r, const sp_digit* a, byte n)
  59453. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59454. {
  59455. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59456. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  59457. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  59458. register byte n __asm__ ("r2") = (byte)n_p;
  59459. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59460. __asm__ __volatile__ (
  59461. "RSB r7, %[n], #0x20\n\t"
  59462. "LDRD r4, r5, [%[a]]\n\t"
  59463. "LSR r4, r4, %[n]\n\t"
  59464. "LSL r3, r5, r7\n\t"
  59465. "LSR r5, r5, %[n]\n\t"
  59466. "ORR r4, r4, r3\n\t"
  59467. "LDR r6, [%[a], #8]\n\t"
  59468. "STR r4, [%[a]]\n\t"
  59469. "LSL r3, r6, r7\n\t"
  59470. "LSR r6, r6, %[n]\n\t"
  59471. "ORR r5, r5, r3\n\t"
  59472. "LDR r4, [%[a], #12]\n\t"
  59473. "STR r5, [%[a], #4]\n\t"
  59474. "LSL r3, r4, r7\n\t"
  59475. "LSR r4, r4, %[n]\n\t"
  59476. "ORR r6, r6, r3\n\t"
  59477. "LDR r5, [%[a], #16]\n\t"
  59478. "STR r6, [%[a], #8]\n\t"
  59479. "LSL r3, r5, r7\n\t"
  59480. "LSR r5, r5, %[n]\n\t"
  59481. "ORR r4, r4, r3\n\t"
  59482. "LDR r6, [%[a], #20]\n\t"
  59483. "STR r4, [%[a], #12]\n\t"
  59484. "LSL r3, r6, r7\n\t"
  59485. "LSR r6, r6, %[n]\n\t"
  59486. "ORR r5, r5, r3\n\t"
  59487. "LDR r4, [%[a], #24]\n\t"
  59488. "STR r5, [%[a], #16]\n\t"
  59489. "LSL r3, r4, r7\n\t"
  59490. "LSR r4, r4, %[n]\n\t"
  59491. "ORR r6, r6, r3\n\t"
  59492. "LDR r5, [%[a], #28]\n\t"
  59493. "STR r6, [%[a], #20]\n\t"
  59494. "LSL r3, r5, r7\n\t"
  59495. "LSR r5, r5, %[n]\n\t"
  59496. "ORR r4, r4, r3\n\t"
  59497. "LDR r6, [%[a], #32]\n\t"
  59498. "STR r4, [%[a], #24]\n\t"
  59499. "LSL r3, r6, r7\n\t"
  59500. "LSR r6, r6, %[n]\n\t"
  59501. "ORR r5, r5, r3\n\t"
  59502. "LDR r4, [%[a], #36]\n\t"
  59503. "STR r5, [%[a], #28]\n\t"
  59504. "LSL r3, r4, r7\n\t"
  59505. "LSR r4, r4, %[n]\n\t"
  59506. "ORR r6, r6, r3\n\t"
  59507. "LDR r5, [%[a], #40]\n\t"
  59508. "STR r6, [%[a], #32]\n\t"
  59509. "LSL r3, r5, r7\n\t"
  59510. "LSR r5, r5, %[n]\n\t"
  59511. "ORR r4, r4, r3\n\t"
  59512. "LDR r6, [%[a], #44]\n\t"
  59513. "STR r4, [%[a], #36]\n\t"
  59514. "LSL r3, r6, r7\n\t"
  59515. "LSR r6, r6, %[n]\n\t"
  59516. "ORR r5, r5, r3\n\t"
  59517. "LDR r4, [%[a], #48]\n\t"
  59518. "STR r5, [%[a], #40]\n\t"
  59519. "LSL r3, r4, r7\n\t"
  59520. "LSR r4, r4, %[n]\n\t"
  59521. "ORR r6, r6, r3\n\t"
  59522. "LDR r5, [%[a], #52]\n\t"
  59523. "STR r6, [%[a], #44]\n\t"
  59524. "LSL r3, r5, r7\n\t"
  59525. "LSR r5, r5, %[n]\n\t"
  59526. "ORR r4, r4, r3\n\t"
  59527. "LDR r6, [%[a], #56]\n\t"
  59528. "STR r4, [%[a], #48]\n\t"
  59529. "LSL r3, r6, r7\n\t"
  59530. "LSR r6, r6, %[n]\n\t"
  59531. "ORR r5, r5, r3\n\t"
  59532. "LDR r4, [%[a], #60]\n\t"
  59533. "STR r5, [%[a], #52]\n\t"
  59534. "LSL r3, r4, r7\n\t"
  59535. "LSR r4, r4, %[n]\n\t"
  59536. "ORR r6, r6, r3\n\t"
  59537. "LDR r5, [%[a], #64]\n\t"
  59538. "STR r6, [%[a], #56]\n\t"
  59539. "LSL r3, r5, r7\n\t"
  59540. "LSR r5, r5, %[n]\n\t"
  59541. "ORR r4, r4, r3\n\t"
  59542. "STRD r4, r5, [%[r], #60]\n\t"
  59543. : [r] "+r" (r), [a] "+r" (a), [n] "+r" (n)
  59544. :
  59545. : "memory", "r4", "r5", "r6", "r3", "r7", "cc"
  59546. );
  59547. }
  59548. #endif
  59549. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  59550. #endif
  59551. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  59552. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59553. static void sp_521_lshift_17(sp_digit* r_p, const sp_digit* a_p, byte n_p)
  59554. #else
  59555. static void sp_521_lshift_17(sp_digit* r, const sp_digit* a, byte n)
  59556. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59557. {
  59558. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59559. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  59560. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  59561. register byte n __asm__ ("r2") = (byte)n_p;
  59562. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59563. __asm__ __volatile__ (
  59564. "RSB r7, %[n], #0x1f\n\t"
  59565. "LDR r5, [%[a], #64]\n\t"
  59566. "LSR r6, r5, #1\n\t"
  59567. "LSL r5, r5, %[n]\n\t"
  59568. "LSR r6, r6, r7\n\t"
  59569. "LDR r4, [%[a], #60]\n\t"
  59570. "STR r6, [%[r], #68]\n\t"
  59571. "LSR r3, r4, #1\n\t"
  59572. "LSL r4, r4, %[n]\n\t"
  59573. "LSR r3, r3, r7\n\t"
  59574. "ORR r5, r5, r3\n\t"
  59575. "LDR r6, [%[a], #56]\n\t"
  59576. "STR r5, [%[r], #64]\n\t"
  59577. "LSR r3, r6, #1\n\t"
  59578. "LSL r6, r6, %[n]\n\t"
  59579. "LSR r3, r3, r7\n\t"
  59580. "ORR r4, r4, r3\n\t"
  59581. "LDR r5, [%[a], #52]\n\t"
  59582. "STR r4, [%[r], #60]\n\t"
  59583. "LSR r3, r5, #1\n\t"
  59584. "LSL r5, r5, %[n]\n\t"
  59585. "LSR r3, r3, r7\n\t"
  59586. "ORR r6, r6, r3\n\t"
  59587. "LDR r4, [%[a], #48]\n\t"
  59588. "STR r6, [%[r], #56]\n\t"
  59589. "LSR r3, r4, #1\n\t"
  59590. "LSL r4, r4, %[n]\n\t"
  59591. "LSR r3, r3, r7\n\t"
  59592. "ORR r5, r5, r3\n\t"
  59593. "LDR r6, [%[a], #44]\n\t"
  59594. "STR r5, [%[r], #52]\n\t"
  59595. "LSR r3, r6, #1\n\t"
  59596. "LSL r6, r6, %[n]\n\t"
  59597. "LSR r3, r3, r7\n\t"
  59598. "ORR r4, r4, r3\n\t"
  59599. "LDR r5, [%[a], #40]\n\t"
  59600. "STR r4, [%[r], #48]\n\t"
  59601. "LSR r3, r5, #1\n\t"
  59602. "LSL r5, r5, %[n]\n\t"
  59603. "LSR r3, r3, r7\n\t"
  59604. "ORR r6, r6, r3\n\t"
  59605. "LDR r4, [%[a], #36]\n\t"
  59606. "STR r6, [%[r], #44]\n\t"
  59607. "LSR r3, r4, #1\n\t"
  59608. "LSL r4, r4, %[n]\n\t"
  59609. "LSR r3, r3, r7\n\t"
  59610. "ORR r5, r5, r3\n\t"
  59611. "LDR r6, [%[a], #32]\n\t"
  59612. "STR r5, [%[r], #40]\n\t"
  59613. "LSR r3, r6, #1\n\t"
  59614. "LSL r6, r6, %[n]\n\t"
  59615. "LSR r3, r3, r7\n\t"
  59616. "ORR r4, r4, r3\n\t"
  59617. "LDR r5, [%[a], #28]\n\t"
  59618. "STR r4, [%[r], #36]\n\t"
  59619. "LSR r3, r5, #1\n\t"
  59620. "LSL r5, r5, %[n]\n\t"
  59621. "LSR r3, r3, r7\n\t"
  59622. "ORR r6, r6, r3\n\t"
  59623. "LDR r4, [%[a], #24]\n\t"
  59624. "STR r6, [%[r], #32]\n\t"
  59625. "LSR r3, r4, #1\n\t"
  59626. "LSL r4, r4, %[n]\n\t"
  59627. "LSR r3, r3, r7\n\t"
  59628. "ORR r5, r5, r3\n\t"
  59629. "LDR r6, [%[a], #20]\n\t"
  59630. "STR r5, [%[r], #28]\n\t"
  59631. "LSR r3, r6, #1\n\t"
  59632. "LSL r6, r6, %[n]\n\t"
  59633. "LSR r3, r3, r7\n\t"
  59634. "ORR r4, r4, r3\n\t"
  59635. "LDR r5, [%[a], #16]\n\t"
  59636. "STR r4, [%[r], #24]\n\t"
  59637. "LSR r3, r5, #1\n\t"
  59638. "LSL r5, r5, %[n]\n\t"
  59639. "LSR r3, r3, r7\n\t"
  59640. "ORR r6, r6, r3\n\t"
  59641. "LDR r4, [%[a], #12]\n\t"
  59642. "STR r6, [%[r], #20]\n\t"
  59643. "LSR r3, r4, #1\n\t"
  59644. "LSL r4, r4, %[n]\n\t"
  59645. "LSR r3, r3, r7\n\t"
  59646. "ORR r5, r5, r3\n\t"
  59647. "LDR r6, [%[a], #8]\n\t"
  59648. "STR r5, [%[r], #16]\n\t"
  59649. "LSR r3, r6, #1\n\t"
  59650. "LSL r6, r6, %[n]\n\t"
  59651. "LSR r3, r3, r7\n\t"
  59652. "ORR r4, r4, r3\n\t"
  59653. "LDR r5, [%[a], #4]\n\t"
  59654. "STR r4, [%[r], #12]\n\t"
  59655. "LSR r3, r5, #1\n\t"
  59656. "LSL r5, r5, %[n]\n\t"
  59657. "LSR r3, r3, r7\n\t"
  59658. "ORR r6, r6, r3\n\t"
  59659. "LDR r4, [%[a]]\n\t"
  59660. "STR r6, [%[r], #8]\n\t"
  59661. "LSR r3, r4, #1\n\t"
  59662. "LSL r4, r4, %[n]\n\t"
  59663. "LSR r3, r3, r7\n\t"
  59664. "ORR r5, r5, r3\n\t"
  59665. "STR r4, [%[r]]\n\t"
  59666. "STR r5, [%[r], #4]\n\t"
  59667. : [r] "+r" (r), [a] "+r" (a), [n] "+r" (n)
  59668. :
  59669. : "memory", "r4", "r5", "r6", "r3", "r7", "cc"
  59670. );
  59671. }
  59672. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59673. static void sp_521_lshift_34(sp_digit* r_p, const sp_digit* a_p, byte n_p)
  59674. #else
  59675. static void sp_521_lshift_34(sp_digit* r, const sp_digit* a, byte n)
  59676. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59677. {
  59678. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59679. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  59680. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  59681. register byte n __asm__ ("r2") = (byte)n_p;
  59682. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59683. __asm__ __volatile__ (
  59684. "RSB r7, %[n], #0x1f\n\t"
  59685. "LDR r5, [%[a], #132]\n\t"
  59686. "LSR r6, r5, #1\n\t"
  59687. "LSL r5, r5, %[n]\n\t"
  59688. "LSR r6, r6, r7\n\t"
  59689. "LDR r4, [%[a], #128]\n\t"
  59690. "STR r6, [%[r], #136]\n\t"
  59691. "LSR r3, r4, #1\n\t"
  59692. "LSL r4, r4, %[n]\n\t"
  59693. "LSR r3, r3, r7\n\t"
  59694. "ORR r5, r5, r3\n\t"
  59695. "LDR r6, [%[a], #124]\n\t"
  59696. "STR r5, [%[r], #132]\n\t"
  59697. "LSR r3, r6, #1\n\t"
  59698. "LSL r6, r6, %[n]\n\t"
  59699. "LSR r3, r3, r7\n\t"
  59700. "ORR r4, r4, r3\n\t"
  59701. "LDR r5, [%[a], #120]\n\t"
  59702. "STR r4, [%[r], #128]\n\t"
  59703. "LSR r3, r5, #1\n\t"
  59704. "LSL r5, r5, %[n]\n\t"
  59705. "LSR r3, r3, r7\n\t"
  59706. "ORR r6, r6, r3\n\t"
  59707. "LDR r4, [%[a], #116]\n\t"
  59708. "STR r6, [%[r], #124]\n\t"
  59709. "LSR r3, r4, #1\n\t"
  59710. "LSL r4, r4, %[n]\n\t"
  59711. "LSR r3, r3, r7\n\t"
  59712. "ORR r5, r5, r3\n\t"
  59713. "LDR r6, [%[a], #112]\n\t"
  59714. "STR r5, [%[r], #120]\n\t"
  59715. "LSR r3, r6, #1\n\t"
  59716. "LSL r6, r6, %[n]\n\t"
  59717. "LSR r3, r3, r7\n\t"
  59718. "ORR r4, r4, r3\n\t"
  59719. "LDR r5, [%[a], #108]\n\t"
  59720. "STR r4, [%[r], #116]\n\t"
  59721. "LSR r3, r5, #1\n\t"
  59722. "LSL r5, r5, %[n]\n\t"
  59723. "LSR r3, r3, r7\n\t"
  59724. "ORR r6, r6, r3\n\t"
  59725. "LDR r4, [%[a], #104]\n\t"
  59726. "STR r6, [%[r], #112]\n\t"
  59727. "LSR r3, r4, #1\n\t"
  59728. "LSL r4, r4, %[n]\n\t"
  59729. "LSR r3, r3, r7\n\t"
  59730. "ORR r5, r5, r3\n\t"
  59731. "LDR r6, [%[a], #100]\n\t"
  59732. "STR r5, [%[r], #108]\n\t"
  59733. "LSR r3, r6, #1\n\t"
  59734. "LSL r6, r6, %[n]\n\t"
  59735. "LSR r3, r3, r7\n\t"
  59736. "ORR r4, r4, r3\n\t"
  59737. "LDR r5, [%[a], #96]\n\t"
  59738. "STR r4, [%[r], #104]\n\t"
  59739. "LSR r3, r5, #1\n\t"
  59740. "LSL r5, r5, %[n]\n\t"
  59741. "LSR r3, r3, r7\n\t"
  59742. "ORR r6, r6, r3\n\t"
  59743. "LDR r4, [%[a], #92]\n\t"
  59744. "STR r6, [%[r], #100]\n\t"
  59745. "LSR r3, r4, #1\n\t"
  59746. "LSL r4, r4, %[n]\n\t"
  59747. "LSR r3, r3, r7\n\t"
  59748. "ORR r5, r5, r3\n\t"
  59749. "LDR r6, [%[a], #88]\n\t"
  59750. "STR r5, [%[r], #96]\n\t"
  59751. "LSR r3, r6, #1\n\t"
  59752. "LSL r6, r6, %[n]\n\t"
  59753. "LSR r3, r3, r7\n\t"
  59754. "ORR r4, r4, r3\n\t"
  59755. "LDR r5, [%[a], #84]\n\t"
  59756. "STR r4, [%[r], #92]\n\t"
  59757. "LSR r3, r5, #1\n\t"
  59758. "LSL r5, r5, %[n]\n\t"
  59759. "LSR r3, r3, r7\n\t"
  59760. "ORR r6, r6, r3\n\t"
  59761. "LDR r4, [%[a], #80]\n\t"
  59762. "STR r6, [%[r], #88]\n\t"
  59763. "LSR r3, r4, #1\n\t"
  59764. "LSL r4, r4, %[n]\n\t"
  59765. "LSR r3, r3, r7\n\t"
  59766. "ORR r5, r5, r3\n\t"
  59767. "LDR r6, [%[a], #76]\n\t"
  59768. "STR r5, [%[r], #84]\n\t"
  59769. "LSR r3, r6, #1\n\t"
  59770. "LSL r6, r6, %[n]\n\t"
  59771. "LSR r3, r3, r7\n\t"
  59772. "ORR r4, r4, r3\n\t"
  59773. "LDR r5, [%[a], #72]\n\t"
  59774. "STR r4, [%[r], #80]\n\t"
  59775. "LSR r3, r5, #1\n\t"
  59776. "LSL r5, r5, %[n]\n\t"
  59777. "LSR r3, r3, r7\n\t"
  59778. "ORR r6, r6, r3\n\t"
  59779. "LDR r4, [%[a], #68]\n\t"
  59780. "STR r6, [%[r], #76]\n\t"
  59781. "LSR r3, r4, #1\n\t"
  59782. "LSL r4, r4, %[n]\n\t"
  59783. "LSR r3, r3, r7\n\t"
  59784. "ORR r5, r5, r3\n\t"
  59785. "LDR r6, [%[a], #64]\n\t"
  59786. "STR r5, [%[r], #72]\n\t"
  59787. "LSR r3, r6, #1\n\t"
  59788. "LSL r6, r6, %[n]\n\t"
  59789. "LSR r3, r3, r7\n\t"
  59790. "ORR r4, r4, r3\n\t"
  59791. "LDR r5, [%[a], #60]\n\t"
  59792. "STR r4, [%[r], #68]\n\t"
  59793. "LSR r3, r5, #1\n\t"
  59794. "LSL r5, r5, %[n]\n\t"
  59795. "LSR r3, r3, r7\n\t"
  59796. "ORR r6, r6, r3\n\t"
  59797. "LDR r4, [%[a], #56]\n\t"
  59798. "STR r6, [%[r], #64]\n\t"
  59799. "LSR r3, r4, #1\n\t"
  59800. "LSL r4, r4, %[n]\n\t"
  59801. "LSR r3, r3, r7\n\t"
  59802. "ORR r5, r5, r3\n\t"
  59803. "LDR r6, [%[a], #52]\n\t"
  59804. "STR r5, [%[r], #60]\n\t"
  59805. "LSR r3, r6, #1\n\t"
  59806. "LSL r6, r6, %[n]\n\t"
  59807. "LSR r3, r3, r7\n\t"
  59808. "ORR r4, r4, r3\n\t"
  59809. "LDR r5, [%[a], #48]\n\t"
  59810. "STR r4, [%[r], #56]\n\t"
  59811. "LSR r3, r5, #1\n\t"
  59812. "LSL r5, r5, %[n]\n\t"
  59813. "LSR r3, r3, r7\n\t"
  59814. "ORR r6, r6, r3\n\t"
  59815. "LDR r4, [%[a], #44]\n\t"
  59816. "STR r6, [%[r], #52]\n\t"
  59817. "LSR r3, r4, #1\n\t"
  59818. "LSL r4, r4, %[n]\n\t"
  59819. "LSR r3, r3, r7\n\t"
  59820. "ORR r5, r5, r3\n\t"
  59821. "LDR r6, [%[a], #40]\n\t"
  59822. "STR r5, [%[r], #48]\n\t"
  59823. "LSR r3, r6, #1\n\t"
  59824. "LSL r6, r6, %[n]\n\t"
  59825. "LSR r3, r3, r7\n\t"
  59826. "ORR r4, r4, r3\n\t"
  59827. "LDR r5, [%[a], #36]\n\t"
  59828. "STR r4, [%[r], #44]\n\t"
  59829. "LSR r3, r5, #1\n\t"
  59830. "LSL r5, r5, %[n]\n\t"
  59831. "LSR r3, r3, r7\n\t"
  59832. "ORR r6, r6, r3\n\t"
  59833. "LDR r4, [%[a], #32]\n\t"
  59834. "STR r6, [%[r], #40]\n\t"
  59835. "LSR r3, r4, #1\n\t"
  59836. "LSL r4, r4, %[n]\n\t"
  59837. "LSR r3, r3, r7\n\t"
  59838. "ORR r5, r5, r3\n\t"
  59839. "LDR r6, [%[a], #28]\n\t"
  59840. "STR r5, [%[r], #36]\n\t"
  59841. "LSR r3, r6, #1\n\t"
  59842. "LSL r6, r6, %[n]\n\t"
  59843. "LSR r3, r3, r7\n\t"
  59844. "ORR r4, r4, r3\n\t"
  59845. "LDR r5, [%[a], #24]\n\t"
  59846. "STR r4, [%[r], #32]\n\t"
  59847. "LSR r3, r5, #1\n\t"
  59848. "LSL r5, r5, %[n]\n\t"
  59849. "LSR r3, r3, r7\n\t"
  59850. "ORR r6, r6, r3\n\t"
  59851. "LDR r4, [%[a], #20]\n\t"
  59852. "STR r6, [%[r], #28]\n\t"
  59853. "LSR r3, r4, #1\n\t"
  59854. "LSL r4, r4, %[n]\n\t"
  59855. "LSR r3, r3, r7\n\t"
  59856. "ORR r5, r5, r3\n\t"
  59857. "LDR r6, [%[a], #16]\n\t"
  59858. "STR r5, [%[r], #24]\n\t"
  59859. "LSR r3, r6, #1\n\t"
  59860. "LSL r6, r6, %[n]\n\t"
  59861. "LSR r3, r3, r7\n\t"
  59862. "ORR r4, r4, r3\n\t"
  59863. "LDR r5, [%[a], #12]\n\t"
  59864. "STR r4, [%[r], #20]\n\t"
  59865. "LSR r3, r5, #1\n\t"
  59866. "LSL r5, r5, %[n]\n\t"
  59867. "LSR r3, r3, r7\n\t"
  59868. "ORR r6, r6, r3\n\t"
  59869. "LDR r4, [%[a], #8]\n\t"
  59870. "STR r6, [%[r], #16]\n\t"
  59871. "LSR r3, r4, #1\n\t"
  59872. "LSL r4, r4, %[n]\n\t"
  59873. "LSR r3, r3, r7\n\t"
  59874. "ORR r5, r5, r3\n\t"
  59875. "LDR r6, [%[a], #4]\n\t"
  59876. "STR r5, [%[r], #12]\n\t"
  59877. "LSR r3, r6, #1\n\t"
  59878. "LSL r6, r6, %[n]\n\t"
  59879. "LSR r3, r3, r7\n\t"
  59880. "ORR r4, r4, r3\n\t"
  59881. "LDR r5, [%[a]]\n\t"
  59882. "STR r4, [%[r], #8]\n\t"
  59883. "LSR r3, r5, #1\n\t"
  59884. "LSL r5, r5, %[n]\n\t"
  59885. "LSR r3, r3, r7\n\t"
  59886. "ORR r6, r6, r3\n\t"
  59887. "STR r5, [%[r]]\n\t"
  59888. "STR r6, [%[r], #4]\n\t"
  59889. : [r] "+r" (r), [a] "+r" (a), [n] "+r" (n)
  59890. :
  59891. : "memory", "r4", "r5", "r6", "r3", "r7", "cc"
  59892. );
  59893. }
  59894. #ifdef WOLFSSL_SP_SMALL
  59895. /* Sub b from a into a. (a -= b)
  59896. *
  59897. * a A single precision integer.
  59898. * b A single precision integer.
  59899. */
  59900. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59901. static sp_digit sp_521_sub_in_place_17(sp_digit* a_p, const sp_digit* b_p)
  59902. #else
  59903. static sp_digit sp_521_sub_in_place_17(sp_digit* a, const sp_digit* b)
  59904. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59905. {
  59906. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59907. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  59908. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  59909. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59910. __asm__ __volatile__ (
  59911. "MOV r10, #0x0\n\t"
  59912. "ADD r11, %[a], #0x40\n\t"
  59913. "\n"
  59914. "L_sp_521_sub_in_pkace_17_word:\n\t"
  59915. "RSBS r10, r10, #0x0\n\t"
  59916. "LDM %[a], {r2, r3, r4, r5}\n\t"
  59917. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  59918. "SBCS r2, r2, r6\n\t"
  59919. "SBCS r3, r3, r7\n\t"
  59920. "SBCS r4, r4, r8\n\t"
  59921. "SBCS r5, r5, r9\n\t"
  59922. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  59923. "SBC r10, r10, r10\n\t"
  59924. "CMP %[a], r11\n\t"
  59925. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  59926. "BNE L_sp_521_sub_in_pkace_17_word\n\t"
  59927. #else
  59928. "BNE.N L_sp_521_sub_in_pkace_17_word\n\t"
  59929. #endif
  59930. "RSBS r10, r10, #0x0\n\t"
  59931. "LDM %[a], {r2}\n\t"
  59932. "LDM %[b]!, {r6}\n\t"
  59933. "SBCS r2, r2, r6\n\t"
  59934. "STM %[a]!, {r2}\n\t"
  59935. "SBC %[a], %[a], %[a]\n\t"
  59936. : [a] "+r" (a), [b] "+r" (b)
  59937. :
  59938. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  59939. );
  59940. return (uint32_t)(size_t)a;
  59941. }
  59942. #else
  59943. /* Sub b from a into a. (a -= b)
  59944. *
  59945. * a A single precision integer and result.
  59946. * b A single precision integer.
  59947. */
  59948. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59949. static sp_digit sp_521_sub_in_place_17(sp_digit* a_p, const sp_digit* b_p)
  59950. #else
  59951. static sp_digit sp_521_sub_in_place_17(sp_digit* a, const sp_digit* b)
  59952. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59953. {
  59954. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  59955. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  59956. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  59957. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  59958. __asm__ __volatile__ (
  59959. "LDM %[a], {r2, r3, r4, r5}\n\t"
  59960. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  59961. "SUBS r2, r2, r6\n\t"
  59962. "SBCS r3, r3, r7\n\t"
  59963. "SBCS r4, r4, r8\n\t"
  59964. "SBCS r5, r5, r9\n\t"
  59965. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  59966. "LDM %[a], {r2, r3, r4, r5}\n\t"
  59967. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  59968. "SBCS r2, r2, r6\n\t"
  59969. "SBCS r3, r3, r7\n\t"
  59970. "SBCS r4, r4, r8\n\t"
  59971. "SBCS r5, r5, r9\n\t"
  59972. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  59973. "LDM %[a], {r2, r3, r4, r5}\n\t"
  59974. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  59975. "SBCS r2, r2, r6\n\t"
  59976. "SBCS r3, r3, r7\n\t"
  59977. "SBCS r4, r4, r8\n\t"
  59978. "SBCS r5, r5, r9\n\t"
  59979. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  59980. "LDM %[a], {r2, r3, r4, r5}\n\t"
  59981. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  59982. "SBCS r2, r2, r6\n\t"
  59983. "SBCS r3, r3, r7\n\t"
  59984. "SBCS r4, r4, r8\n\t"
  59985. "SBCS r5, r5, r9\n\t"
  59986. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  59987. "LDM %[a], {r2}\n\t"
  59988. "LDM %[b]!, {r6}\n\t"
  59989. "SBCS r2, r2, r6\n\t"
  59990. "STM %[a]!, {r2}\n\t"
  59991. "SBC %[a], r9, r9\n\t"
  59992. : [a] "+r" (a), [b] "+r" (b)
  59993. :
  59994. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  59995. );
  59996. return (uint32_t)(size_t)a;
  59997. }
  59998. #endif /* WOLFSSL_SP_SMALL */
  59999. #ifdef WOLFSSL_SP_SMALL
  60000. /* Mul a by digit b into r. (r = a * b)
  60001. *
  60002. * r A single precision integer.
  60003. * a A single precision integer.
  60004. * b A single precision digit.
  60005. */
  60006. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60007. static void sp_521_mul_d_17(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  60008. #else
  60009. static void sp_521_mul_d_17(sp_digit* r, const sp_digit* a, sp_digit b)
  60010. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60011. {
  60012. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60013. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  60014. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  60015. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  60016. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60017. __asm__ __volatile__ (
  60018. /* A[0] * B */
  60019. "LDR r8, [%[a]]\n\t"
  60020. "UMULL r5, r3, %[b], r8\n\t"
  60021. "MOV r4, #0x0\n\t"
  60022. "STR r5, [%[r]]\n\t"
  60023. "MOV r5, #0x0\n\t"
  60024. "MOV r9, #0x4\n\t"
  60025. "\n"
  60026. "L_sp_521_mul_d_17_word:\n\t"
  60027. /* A[i] * B */
  60028. "LDR r8, [%[a], r9]\n\t"
  60029. "UMULL r6, r7, %[b], r8\n\t"
  60030. "ADDS r3, r3, r6\n\t"
  60031. "ADCS r4, r4, r7\n\t"
  60032. "ADC r5, r5, #0x0\n\t"
  60033. "STR r3, [%[r], r9]\n\t"
  60034. "MOV r3, r4\n\t"
  60035. "MOV r4, r5\n\t"
  60036. "MOV r5, #0x0\n\t"
  60037. "ADD r9, r9, #0x4\n\t"
  60038. "CMP r9, #0x44\n\t"
  60039. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  60040. "BLT L_sp_521_mul_d_17_word\n\t"
  60041. #else
  60042. "BLT.N L_sp_521_mul_d_17_word\n\t"
  60043. #endif
  60044. "STR r3, [%[r], #68]\n\t"
  60045. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  60046. :
  60047. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  60048. );
  60049. }
  60050. #else
  60051. /* Mul a by digit b into r. (r = a * b)
  60052. *
  60053. * r A single precision integer.
  60054. * a A single precision integer.
  60055. * b A single precision digit.
  60056. */
  60057. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60058. static void sp_521_mul_d_17(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  60059. #else
  60060. static void sp_521_mul_d_17(sp_digit* r, const sp_digit* a, sp_digit b)
  60061. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60062. {
  60063. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60064. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  60065. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  60066. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  60067. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60068. __asm__ __volatile__ (
  60069. /* A[0] * B */
  60070. "LDM %[a]!, {r8}\n\t"
  60071. "UMULL r3, r4, %[b], r8\n\t"
  60072. "STM %[r]!, {r3}\n\t"
  60073. "MOV r5, #0x0\n\t"
  60074. /* A[1] * B */
  60075. "LDM %[a]!, {r8}\n\t"
  60076. "UMLAL r4, r5, %[b], r8\n\t"
  60077. "STM %[r]!, {r4}\n\t"
  60078. "MOV r3, #0x0\n\t"
  60079. /* A[2] * B */
  60080. "LDM %[a]!, {r8}\n\t"
  60081. "UMLAL r5, r3, %[b], r8\n\t"
  60082. "STM %[r]!, {r5}\n\t"
  60083. "MOV r4, #0x0\n\t"
  60084. /* A[3] * B */
  60085. "LDM %[a]!, {r8}\n\t"
  60086. "UMLAL r3, r4, %[b], r8\n\t"
  60087. "STM %[r]!, {r3}\n\t"
  60088. "MOV r5, #0x0\n\t"
  60089. /* A[4] * B */
  60090. "LDM %[a]!, {r8}\n\t"
  60091. "UMLAL r4, r5, %[b], r8\n\t"
  60092. "STM %[r]!, {r4}\n\t"
  60093. "MOV r3, #0x0\n\t"
  60094. /* A[5] * B */
  60095. "LDM %[a]!, {r8}\n\t"
  60096. "UMLAL r5, r3, %[b], r8\n\t"
  60097. "STM %[r]!, {r5}\n\t"
  60098. "MOV r4, #0x0\n\t"
  60099. /* A[6] * B */
  60100. "LDM %[a]!, {r8}\n\t"
  60101. "UMLAL r3, r4, %[b], r8\n\t"
  60102. "STM %[r]!, {r3}\n\t"
  60103. "MOV r5, #0x0\n\t"
  60104. /* A[7] * B */
  60105. "LDM %[a]!, {r8}\n\t"
  60106. "UMLAL r4, r5, %[b], r8\n\t"
  60107. "STM %[r]!, {r4}\n\t"
  60108. "MOV r3, #0x0\n\t"
  60109. /* A[8] * B */
  60110. "LDM %[a]!, {r8}\n\t"
  60111. "UMLAL r5, r3, %[b], r8\n\t"
  60112. "STM %[r]!, {r5}\n\t"
  60113. "MOV r4, #0x0\n\t"
  60114. /* A[9] * B */
  60115. "LDM %[a]!, {r8}\n\t"
  60116. "UMLAL r3, r4, %[b], r8\n\t"
  60117. "STM %[r]!, {r3}\n\t"
  60118. "MOV r5, #0x0\n\t"
  60119. /* A[10] * B */
  60120. "LDM %[a]!, {r8}\n\t"
  60121. "UMLAL r4, r5, %[b], r8\n\t"
  60122. "STM %[r]!, {r4}\n\t"
  60123. "MOV r3, #0x0\n\t"
  60124. /* A[11] * B */
  60125. "LDM %[a]!, {r8}\n\t"
  60126. "UMLAL r5, r3, %[b], r8\n\t"
  60127. "STM %[r]!, {r5}\n\t"
  60128. "MOV r4, #0x0\n\t"
  60129. /* A[12] * B */
  60130. "LDM %[a]!, {r8}\n\t"
  60131. "UMLAL r3, r4, %[b], r8\n\t"
  60132. "STM %[r]!, {r3}\n\t"
  60133. "MOV r5, #0x0\n\t"
  60134. /* A[13] * B */
  60135. "LDM %[a]!, {r8}\n\t"
  60136. "UMLAL r4, r5, %[b], r8\n\t"
  60137. "STM %[r]!, {r4}\n\t"
  60138. "MOV r3, #0x0\n\t"
  60139. /* A[14] * B */
  60140. "LDM %[a]!, {r8}\n\t"
  60141. "UMLAL r5, r3, %[b], r8\n\t"
  60142. "STM %[r]!, {r5}\n\t"
  60143. "MOV r4, #0x0\n\t"
  60144. /* A[15] * B */
  60145. "LDM %[a]!, {r8}\n\t"
  60146. "UMLAL r3, r4, %[b], r8\n\t"
  60147. "STM %[r]!, {r3}\n\t"
  60148. "MOV r5, #0x0\n\t"
  60149. /* A[16] * B */
  60150. "LDM %[a]!, {r8}\n\t"
  60151. "UMLAL r4, r5, %[b], r8\n\t"
  60152. "STM %[r]!, {r4}\n\t"
  60153. "STR r5, [%[r]]\n\t"
  60154. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  60155. :
  60156. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  60157. );
  60158. }
  60159. #endif /* WOLFSSL_SP_SMALL */
  60160. #ifdef WOLFSSL_SP_USE_UDIV
  60161. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  60162. *
  60163. * d1 The high order half of the number to divide.
  60164. * d0 The low order half of the number to divide.
  60165. * div The divisor.
  60166. * returns the result of the division.
  60167. *
  60168. * Note that this is an approximate div. It may give an answer 1 larger.
  60169. */
  60170. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60171. SP_NOINLINE static sp_digit div_521_word_17(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  60172. #else
  60173. SP_NOINLINE static sp_digit div_521_word_17(sp_digit d1, sp_digit d0, sp_digit div)
  60174. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60175. {
  60176. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60177. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  60178. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  60179. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  60180. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60181. __asm__ __volatile__ (
  60182. "LSR r8, %[div], #16\n\t"
  60183. "ADD r5, r8, #0x1\n\t"
  60184. "UDIV r6, %[d1], r5\n\t"
  60185. "LSL r7, %[div], #16\n\t"
  60186. "LSL r6, r6, #16\n\t"
  60187. "UMULL r3, r4, %[div], r6\n\t"
  60188. "SUBS %[d0], %[d0], r3\n\t"
  60189. "SBC %[d1], %[d1], r4\n\t"
  60190. "SUBS r3, %[d1], r5\n\t"
  60191. "SBC r9, r9, r9\n\t"
  60192. "ADD r9, r9, #0x1\n\t"
  60193. "RSB r10, r9, #0x0\n\t"
  60194. "LSL r9, r9, #16\n\t"
  60195. "AND r7, r7, r10\n\t"
  60196. "AND r8, r8, r10\n\t"
  60197. "SUBS %[d0], %[d0], r7\n\t"
  60198. "ADD r6, r6, r9\n\t"
  60199. "SBC %[d1], %[d1], r8\n\t"
  60200. "LSL r4, %[d1], #16\n\t"
  60201. "LSR r3, %[d0], #16\n\t"
  60202. "ORR r3, r3, r4\n\t"
  60203. "UDIV r3, r3, r5\n\t"
  60204. "ADD r6, r6, r3\n\t"
  60205. "UMULL r3, r4, %[div], r3\n\t"
  60206. "SUBS %[d0], %[d0], r3\n\t"
  60207. "SBC %[d1], %[d1], r4\n\t"
  60208. "LSL r4, %[d1], #16\n\t"
  60209. "LSR r3, %[d0], #16\n\t"
  60210. "ORR r3, r3, r4\n\t"
  60211. "UDIV r3, r3, r5\n\t"
  60212. "ADD r6, r6, r3\n\t"
  60213. "MUL r3, %[div], r3\n\t"
  60214. "SUB %[d0], %[d0], r3\n\t"
  60215. "UDIV r3, %[d0], %[div]\n\t"
  60216. "ADD %[d1], r6, r3\n\t"
  60217. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  60218. :
  60219. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  60220. );
  60221. return (uint32_t)(size_t)d1;
  60222. }
  60223. #else
  60224. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  60225. *
  60226. * d1 The high order half of the number to divide.
  60227. * d0 The low order half of the number to divide.
  60228. * div The divisor.
  60229. * returns the result of the division.
  60230. *
  60231. * Note that this is an approximate div. It may give an answer 1 larger.
  60232. */
  60233. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60234. SP_NOINLINE static sp_digit div_521_word_17(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  60235. #else
  60236. SP_NOINLINE static sp_digit div_521_word_17(sp_digit d1, sp_digit d0, sp_digit div)
  60237. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60238. {
  60239. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60240. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  60241. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  60242. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  60243. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60244. __asm__ __volatile__ (
  60245. "LSR r5, %[div], #1\n\t"
  60246. "ADD r5, r5, #0x1\n\t"
  60247. "MOV r6, %[d0]\n\t"
  60248. "MOV r7, %[d1]\n\t"
  60249. /* Do top 32 */
  60250. "SUBS r8, r5, r7\n\t"
  60251. "SBC r8, r8, r8\n\t"
  60252. "MOV r3, #0x0\n\t"
  60253. "SUB r3, r3, r8\n\t"
  60254. "AND r8, r8, r5\n\t"
  60255. "SUBS r7, r7, r8\n\t"
  60256. /* Next 30 bits */
  60257. "MOV r4, #0x1d\n\t"
  60258. "\n"
  60259. "L_div_521_word_17_bit:\n\t"
  60260. "LSLS r6, r6, #1\n\t"
  60261. "ADC r7, r7, r7\n\t"
  60262. "SUBS r8, r5, r7\n\t"
  60263. "SBC r8, r8, r8\n\t"
  60264. "ADD r3, r3, r3\n\t"
  60265. "SUB r3, r3, r8\n\t"
  60266. "AND r8, r8, r5\n\t"
  60267. "SUBS r7, r7, r8\n\t"
  60268. "SUBS r4, r4, #0x1\n\t"
  60269. "bpl L_div_521_word_17_bit\n\t"
  60270. "ADD r3, r3, r3\n\t"
  60271. "ADD r3, r3, #0x1\n\t"
  60272. "UMULL r6, r7, r3, %[div]\n\t"
  60273. "SUBS r9, %[d0], r6\n\t"
  60274. "SBC r10, %[d1], r7\n\t"
  60275. "ADD r3, r3, r10\n\t"
  60276. "UMULL r6, r7, r3, %[div]\n\t"
  60277. "SUBS r9, %[d0], r6\n\t"
  60278. "SBC r10, %[d1], r7\n\t"
  60279. "ADD r3, r3, r10\n\t"
  60280. "UMULL r6, r7, r3, %[div]\n\t"
  60281. "SUBS r9, %[d0], r6\n\t"
  60282. "SBC r10, %[d1], r7\n\t"
  60283. "ADD r3, r3, r10\n\t"
  60284. "SUBS r8, %[div], r9\n\t"
  60285. "SBC r8, r8, r8\n\t"
  60286. "SUB %[d1], r3, r8\n\t"
  60287. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  60288. :
  60289. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  60290. );
  60291. return (uint32_t)(size_t)d1;
  60292. }
  60293. #endif
  60294. /* AND m into each word of a and store in r.
  60295. *
  60296. * r A single precision integer.
  60297. * a A single precision integer.
  60298. * m Mask to AND against each digit.
  60299. */
  60300. static void sp_521_mask_17(sp_digit* r, const sp_digit* a, sp_digit m)
  60301. {
  60302. #ifdef WOLFSSL_SP_SMALL
  60303. int i;
  60304. for (i=0; i<17; i++) {
  60305. r[i] = a[i] & m;
  60306. }
  60307. #else
  60308. int i;
  60309. for (i = 0; i < 16; i += 8) {
  60310. r[i+0] = a[i+0] & m;
  60311. r[i+1] = a[i+1] & m;
  60312. r[i+2] = a[i+2] & m;
  60313. r[i+3] = a[i+3] & m;
  60314. r[i+4] = a[i+4] & m;
  60315. r[i+5] = a[i+5] & m;
  60316. r[i+6] = a[i+6] & m;
  60317. r[i+7] = a[i+7] & m;
  60318. }
  60319. r[16] = a[16] & m;
  60320. #endif
  60321. }
  60322. /* Divide d in a and put remainder into r (m*d + r = a)
  60323. * m is not calculated as it is not needed at this time.
  60324. *
  60325. * a Number to be divided.
  60326. * d Number to divide with.
  60327. * m Multiplier result.
  60328. * r Remainder from the division.
  60329. * returns MP_OKAY indicating success.
  60330. */
  60331. static WC_INLINE int sp_521_div_17(const sp_digit* a, const sp_digit* d,
  60332. sp_digit* m, sp_digit* r)
  60333. {
  60334. sp_digit t1[35];
  60335. sp_digit t2[18];
  60336. sp_digit sd[18];
  60337. sp_digit div;
  60338. sp_digit r1;
  60339. int i;
  60340. ASSERT_SAVED_VECTOR_REGISTERS();
  60341. (void)m;
  60342. div = (d[16] << 23) | (d[15] >> 9);
  60343. XMEMCPY(t1, a, sizeof(*t1) * 2 * 17);
  60344. r1 = sp_521_cmp_17(&t1[17], d) >= 0;
  60345. sp_521_cond_sub_17(&t1[17], &t1[17], d, (sp_digit)0 - r1);
  60346. sp_521_lshift_17(sd, d, 23);
  60347. sp_521_lshift_34(t1, t1, 23);
  60348. for (i = 16; i >= 0; i--) {
  60349. sp_digit hi = t1[17 + i] - (t1[17 + i] == div);
  60350. r1 = div_521_word_17(hi, t1[17 + i - 1], div);
  60351. sp_521_mul_d_17(t2, sd, r1);
  60352. t1[17 + i] += sp_521_sub_in_place_17(&t1[i], t2);
  60353. t1[17 + i] -= t2[17];
  60354. sp_521_mask_17(t2, sd, t1[17 + i]);
  60355. t1[17 + i] += sp_521_add_17(&t1[i], &t1[i], t2);
  60356. sp_521_mask_17(t2, sd, t1[17 + i]);
  60357. t1[17 + i] += sp_521_add_17(&t1[i], &t1[i], t2);
  60358. }
  60359. r1 = sp_521_cmp_17(t1, sd) >= 0;
  60360. sp_521_cond_sub_17(r, t1, sd, (sp_digit)0 - r1);
  60361. sp_521_rshift_17(r, r, 23);
  60362. return MP_OKAY;
  60363. }
  60364. /* Reduce a modulo m into r. (r = a mod m)
  60365. *
  60366. * r A single precision number that is the reduced result.
  60367. * a A single precision number that is to be reduced.
  60368. * m A single precision number that is the modulus to reduce with.
  60369. * returns MP_OKAY indicating success.
  60370. */
  60371. static WC_INLINE int sp_521_mod_17(sp_digit* r, const sp_digit* a, const sp_digit* m)
  60372. {
  60373. return sp_521_div_17(a, m, NULL, r);
  60374. }
  60375. #endif
  60376. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  60377. /* Multiply two number mod the order of P521 curve. (r = a * b mod order)
  60378. *
  60379. * r Result of the multiplication.
  60380. * a First operand of the multiplication.
  60381. * b Second operand of the multiplication.
  60382. */
  60383. static void sp_521_mont_mul_order_17(sp_digit* r, const sp_digit* a, const sp_digit* b)
  60384. {
  60385. sp_521_mul_17(r, a, b);
  60386. sp_521_mont_reduce_order_17(r, p521_order, p521_mp_order);
  60387. }
  60388. #if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
  60389. #ifdef WOLFSSL_SP_SMALL
  60390. /* Order-2 for the P521 curve. */
  60391. static const uint32_t p521_order_minus_2[17] = {
  60392. 0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U,
  60393. 0xbf2f966bU,0x51868783U,0xfffffffaU,0xffffffffU,0xffffffffU,0xffffffffU,
  60394. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU
  60395. };
  60396. #else
  60397. /* The low half of the order-2 of the P521 curve. */
  60398. static const uint32_t p521_order_low[9] = {
  60399. 0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U,
  60400. 0xbf2f966bU,0x51868783U,0xfffffffaU
  60401. };
  60402. #endif /* WOLFSSL_SP_SMALL */
  60403. /* Square number mod the order of P521 curve. (r = a * a mod order)
  60404. *
  60405. * r Result of the squaring.
  60406. * a Number to square.
  60407. */
  60408. static void sp_521_mont_sqr_order_17(sp_digit* r, const sp_digit* a)
  60409. {
  60410. sp_521_sqr_17(r, a);
  60411. sp_521_mont_reduce_order_17(r, p521_order, p521_mp_order);
  60412. }
  60413. #ifndef WOLFSSL_SP_SMALL
  60414. /* Square number mod the order of P521 curve a number of times.
  60415. * (r = a ^ n mod order)
  60416. *
  60417. * r Result of the squaring.
  60418. * a Number to square.
  60419. */
  60420. static void sp_521_mont_sqr_n_order_17(sp_digit* r, const sp_digit* a, int n)
  60421. {
  60422. int i;
  60423. sp_521_mont_sqr_order_17(r, a);
  60424. for (i=1; i<n; i++) {
  60425. sp_521_mont_sqr_order_17(r, r);
  60426. }
  60427. }
  60428. #endif /* !WOLFSSL_SP_SMALL */
  60429. /* Invert the number, in Montgomery form, modulo the order of the P521 curve.
  60430. * (r = 1 / a mod order)
  60431. *
  60432. * r Inverse result.
  60433. * a Number to invert.
  60434. * td Temporary data.
  60435. */
  60436. #ifdef WOLFSSL_SP_NONBLOCK
  60437. typedef struct sp_521_mont_inv_order_17_ctx {
  60438. int state;
  60439. int i;
  60440. } sp_521_mont_inv_order_17_ctx;
  60441. static int sp_521_mont_inv_order_17_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
  60442. sp_digit* t)
  60443. {
  60444. int err = FP_WOULDBLOCK;
  60445. sp_521_mont_inv_order_17_ctx* ctx = (sp_521_mont_inv_order_17_ctx*)sp_ctx;
  60446. typedef char ctx_size_test[sizeof(sp_521_mont_inv_order_17_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  60447. (void)sizeof(ctx_size_test);
  60448. switch (ctx->state) {
  60449. case 0:
  60450. XMEMCPY(t, a, sizeof(sp_digit) * 17);
  60451. ctx->i = 519;
  60452. ctx->state = 1;
  60453. break;
  60454. case 1:
  60455. sp_521_mont_sqr_order_17(t, t);
  60456. ctx->state = 2;
  60457. break;
  60458. case 2:
  60459. if ((p521_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
  60460. sp_521_mont_mul_order_17(t, t, a);
  60461. }
  60462. ctx->i--;
  60463. ctx->state = (ctx->i == 0) ? 3 : 1;
  60464. break;
  60465. case 3:
  60466. XMEMCPY(r, t, sizeof(sp_digit) * 17U);
  60467. err = MP_OKAY;
  60468. break;
  60469. }
  60470. return err;
  60471. }
  60472. #endif /* WOLFSSL_SP_NONBLOCK */
  60473. static void sp_521_mont_inv_order_17(sp_digit* r, const sp_digit* a,
  60474. sp_digit* td)
  60475. {
  60476. #ifdef WOLFSSL_SP_SMALL
  60477. sp_digit* t = td;
  60478. int i;
  60479. XMEMCPY(t, a, sizeof(sp_digit) * 17);
  60480. for (i=519; i>=0; i--) {
  60481. sp_521_mont_sqr_order_17(t, t);
  60482. if ((p521_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  60483. sp_521_mont_mul_order_17(t, t, a);
  60484. }
  60485. }
  60486. XMEMCPY(r, t, sizeof(sp_digit) * 17U);
  60487. #else
  60488. sp_digit* t = td;
  60489. sp_digit* t2 = td + 2 * 17;
  60490. sp_digit* t3 = td + 4 * 17;
  60491. int i;
  60492. /* t = a^2 */
  60493. sp_521_mont_sqr_order_17(t, a);
  60494. /* t = a^3 = t * a */
  60495. sp_521_mont_mul_order_17(t, t, a);
  60496. /* t= a^c = t ^ 2 ^ 2 */
  60497. sp_521_mont_sqr_n_order_17(t2, t, 2);
  60498. /* t = a^f = t2 * t */
  60499. sp_521_mont_mul_order_17(t, t2, t);
  60500. /* t3 = a^1e */
  60501. sp_521_mont_sqr_order_17(t3, t);
  60502. /* t3 = a^1f = t3 * a */
  60503. sp_521_mont_mul_order_17(t3, t3, a);
  60504. /* t2= a^f0 = t ^ 2 ^ 4 */
  60505. sp_521_mont_sqr_n_order_17(t2, t, 4);
  60506. /* t = a^ff = t2 * t */
  60507. sp_521_mont_mul_order_17(t, t2, t);
  60508. /* t2= a^ff00 = t ^ 2 ^ 8 */
  60509. sp_521_mont_sqr_n_order_17(t2, t, 8);
  60510. /* t3= a^ffff = t2 * t */
  60511. sp_521_mont_mul_order_17(t, t2, t);
  60512. /* t2= a^ffff0000 = t ^ 2 ^ 16 */
  60513. sp_521_mont_sqr_n_order_17(t2, t, 16);
  60514. /* t = a^ffffffff = t2 * t */
  60515. sp_521_mont_mul_order_17(t, t2, t);
  60516. /* t2= a^ffffffff00000000 = t ^ 2 ^ 32 */
  60517. sp_521_mont_sqr_n_order_17(t2, t, 32);
  60518. /* t = a^ffffffffffffffff = t2 * t */
  60519. sp_521_mont_mul_order_17(t, t2, t);
  60520. /* t2= a^ffffffffffffffff0000000000000000 = t ^ 2 ^ 64 */
  60521. sp_521_mont_sqr_n_order_17(t2, t, 64);
  60522. /* t = a^ffffffffffffffffffffffffffffffff = t2 * t */
  60523. sp_521_mont_mul_order_17(t, t2, t);
  60524. /* t2= a^ffffffffffffffffffffffffffffffff00000000000000000000000000000000 = t ^ 2 ^ 128 */
  60525. sp_521_mont_sqr_n_order_17(t2, t, 128);
  60526. /* t = a^ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */
  60527. sp_521_mont_mul_order_17(t, t2, t);
  60528. /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 */
  60529. sp_521_mont_sqr_n_order_17(t2, t, 5);
  60530. /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t * t3 */
  60531. sp_521_mont_mul_order_17(t2, t2, t3);
  60532. for (i=259; i>=1; i--) {
  60533. sp_521_mont_sqr_order_17(t2, t2);
  60534. if ((p521_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  60535. sp_521_mont_mul_order_17(t2, t2, a);
  60536. }
  60537. }
  60538. sp_521_mont_sqr_order_17(t2, t2);
  60539. sp_521_mont_mul_order_17(r, t2, a);
  60540. #endif /* WOLFSSL_SP_SMALL */
  60541. }
  60542. #endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
  60543. #endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  60544. #ifdef HAVE_ECC_SIGN
  60545. #ifndef SP_ECC_MAX_SIG_GEN
  60546. #define SP_ECC_MAX_SIG_GEN 64
  60547. #endif
  60548. /* Calculate second signature value S from R, k and private value.
  60549. *
  60550. * s = (r * x + e) / k
  60551. *
  60552. * s Signature value.
  60553. * r First signature value.
  60554. * k Ephemeral private key.
  60555. * x Private key as a number.
  60556. * e Hash of message as a number.
  60557. * tmp Temporary storage for intermediate numbers.
  60558. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  60559. */
  60560. static int sp_521_calc_s_17(sp_digit* s, const sp_digit* r, sp_digit* k,
  60561. sp_digit* x, const sp_digit* e, sp_digit* tmp)
  60562. {
  60563. int err;
  60564. sp_digit carry;
  60565. sp_int32 c;
  60566. sp_digit* kInv = k;
  60567. /* Conv k to Montgomery form (mod order) */
  60568. sp_521_mul_17(k, k, p521_norm_order);
  60569. err = sp_521_mod_17(k, k, p521_order);
  60570. if (err == MP_OKAY) {
  60571. sp_521_norm_17(k);
  60572. /* kInv = 1/k mod order */
  60573. sp_521_mont_inv_order_17(kInv, k, tmp);
  60574. sp_521_norm_17(kInv);
  60575. /* s = r * x + e */
  60576. sp_521_mul_17(x, x, r);
  60577. err = sp_521_mod_17(x, x, p521_order);
  60578. }
  60579. if (err == MP_OKAY) {
  60580. sp_521_norm_17(x);
  60581. carry = sp_521_add_17(s, e, x);
  60582. sp_521_cond_sub_17(s, s, p521_order, 0 - carry);
  60583. sp_521_norm_17(s);
  60584. c = sp_521_cmp_17(s, p521_order);
  60585. sp_521_cond_sub_17(s, s, p521_order,
  60586. (sp_digit)0 - (sp_digit)(c >= 0));
  60587. sp_521_norm_17(s);
  60588. /* s = s * k^-1 mod order */
  60589. sp_521_mont_mul_order_17(s, s, kInv);
  60590. sp_521_norm_17(s);
  60591. }
  60592. return err;
  60593. }
  60594. /* Sign the hash using the private key.
  60595. * e = [hash, 521 bits] from binary
  60596. * r = (k.G)->x mod order
  60597. * s = (r * x + e) / k mod order
  60598. * The hash is truncated to the first 521 bits.
  60599. *
  60600. * hash Hash to sign.
  60601. * hashLen Length of the hash data.
  60602. * rng Random number generator.
  60603. * priv Private part of key - scalar.
  60604. * rm First part of result as an mp_int.
  60605. * sm Sirst part of result as an mp_int.
  60606. * heap Heap to use for allocation.
  60607. * returns RNG failures, MEMORY_E when memory allocation fails and
  60608. * MP_OKAY on success.
  60609. */
  60610. int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng,
  60611. const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  60612. {
  60613. #ifdef WOLFSSL_SP_SMALL_STACK
  60614. sp_digit* e = NULL;
  60615. sp_point_521* point = NULL;
  60616. #else
  60617. sp_digit e[7 * 2 * 17];
  60618. sp_point_521 point[1];
  60619. #endif
  60620. sp_digit* x = NULL;
  60621. sp_digit* k = NULL;
  60622. sp_digit* r = NULL;
  60623. sp_digit* tmp = NULL;
  60624. sp_digit* s = NULL;
  60625. sp_int32 c;
  60626. int err = MP_OKAY;
  60627. int i;
  60628. (void)heap;
  60629. #ifdef WOLFSSL_SP_SMALL_STACK
  60630. if (err == MP_OKAY) {
  60631. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  60632. DYNAMIC_TYPE_ECC);
  60633. if (point == NULL)
  60634. err = MEMORY_E;
  60635. }
  60636. if (err == MP_OKAY) {
  60637. e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 17, heap,
  60638. DYNAMIC_TYPE_ECC);
  60639. if (e == NULL)
  60640. err = MEMORY_E;
  60641. }
  60642. #endif
  60643. if (err == MP_OKAY) {
  60644. x = e + 2 * 17;
  60645. k = e + 4 * 17;
  60646. r = e + 6 * 17;
  60647. tmp = e + 8 * 17;
  60648. s = e;
  60649. if (hashLen > 66U) {
  60650. hashLen = 66U;
  60651. }
  60652. }
  60653. for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
  60654. /* New random point. */
  60655. if (km == NULL || mp_iszero(km)) {
  60656. err = sp_521_ecc_gen_k_17(rng, k);
  60657. }
  60658. else {
  60659. sp_521_from_mp(k, 17, km);
  60660. mp_zero(km);
  60661. }
  60662. if (err == MP_OKAY) {
  60663. err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, heap);
  60664. }
  60665. if (err == MP_OKAY) {
  60666. /* r = point->x mod order */
  60667. XMEMCPY(r, point->x, sizeof(sp_digit) * 17U);
  60668. sp_521_norm_17(r);
  60669. c = sp_521_cmp_17(r, p521_order);
  60670. sp_521_cond_sub_17(r, r, p521_order,
  60671. (sp_digit)0 - (sp_digit)(c >= 0));
  60672. sp_521_norm_17(r);
  60673. if (!sp_521_iszero_17(r)) {
  60674. /* x is modified in calculation of s. */
  60675. sp_521_from_mp(x, 17, priv);
  60676. /* s ptr == e ptr, e is modified in calculation of s. */
  60677. sp_521_from_bin(e, 17, hash, (int)hashLen);
  60678. /* Take 521 leftmost bits of hash. */
  60679. if (hashLen == 66U) {
  60680. sp_521_rshift_17(e, e, 7);
  60681. }
  60682. err = sp_521_calc_s_17(s, r, k, x, e, tmp);
  60683. /* Check that signature is usable. */
  60684. if ((err == MP_OKAY) && (!sp_521_iszero_17(s))) {
  60685. break;
  60686. }
  60687. }
  60688. }
  60689. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  60690. i = 1;
  60691. #endif
  60692. }
  60693. if (i == 0) {
  60694. err = RNG_FAILURE_E;
  60695. }
  60696. if (err == MP_OKAY) {
  60697. err = sp_521_to_mp(r, rm);
  60698. }
  60699. if (err == MP_OKAY) {
  60700. err = sp_521_to_mp(s, sm);
  60701. }
  60702. #ifdef WOLFSSL_SP_SMALL_STACK
  60703. if (e != NULL)
  60704. #endif
  60705. {
  60706. ForceZero(e, sizeof(sp_digit) * 7 * 2 * 17);
  60707. #ifdef WOLFSSL_SP_SMALL_STACK
  60708. XFREE(e, heap, DYNAMIC_TYPE_ECC);
  60709. #endif
  60710. }
  60711. #ifdef WOLFSSL_SP_SMALL_STACK
  60712. if (point != NULL)
  60713. #endif
  60714. {
  60715. ForceZero(point, sizeof(sp_point_521));
  60716. #ifdef WOLFSSL_SP_SMALL_STACK
  60717. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  60718. #endif
  60719. }
  60720. return err;
  60721. }
  60722. #ifdef WOLFSSL_SP_NONBLOCK
  60723. typedef struct sp_ecc_sign_521_ctx {
  60724. int state;
  60725. union {
  60726. sp_521_ecc_mulmod_17_ctx mulmod_ctx;
  60727. sp_521_mont_inv_order_17_ctx mont_inv_order_ctx;
  60728. };
  60729. sp_digit e[2*17];
  60730. sp_digit x[2*17];
  60731. sp_digit k[2*17];
  60732. sp_digit r[2*17];
  60733. sp_digit tmp[3 * 2*17];
  60734. sp_point_521 point;
  60735. sp_digit* s;
  60736. sp_digit* kInv;
  60737. int i;
  60738. } sp_ecc_sign_521_ctx;
  60739. int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
  60740. mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  60741. {
  60742. int err = FP_WOULDBLOCK;
  60743. sp_ecc_sign_521_ctx* ctx = (sp_ecc_sign_521_ctx*)sp_ctx->data;
  60744. typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  60745. (void)sizeof(ctx_size_test);
  60746. switch (ctx->state) {
  60747. case 0: /* INIT */
  60748. ctx->s = ctx->e;
  60749. ctx->kInv = ctx->k;
  60750. ctx->i = SP_ECC_MAX_SIG_GEN;
  60751. ctx->state = 1;
  60752. break;
  60753. case 1: /* GEN */
  60754. /* New random point. */
  60755. if (km == NULL || mp_iszero(km)) {
  60756. err = sp_521_ecc_gen_k_17(rng, ctx->k);
  60757. }
  60758. else {
  60759. sp_521_from_mp(ctx->k, 17, km);
  60760. mp_zero(km);
  60761. }
  60762. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  60763. ctx->state = 2;
  60764. break;
  60765. case 2: /* MULMOD */
  60766. err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  60767. &ctx->point, &p521_base, ctx->k, 1, 1, heap);
  60768. if (err == MP_OKAY) {
  60769. ctx->state = 3;
  60770. }
  60771. break;
  60772. case 3: /* MODORDER */
  60773. {
  60774. sp_int32 c;
  60775. /* r = point->x mod order */
  60776. XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 17U);
  60777. sp_521_norm_17(ctx->r);
  60778. c = sp_521_cmp_17(ctx->r, p521_order);
  60779. sp_521_cond_sub_17(ctx->r, ctx->r, p521_order,
  60780. (sp_digit)0 - (sp_digit)(c >= 0));
  60781. sp_521_norm_17(ctx->r);
  60782. if (hashLen > 66U) {
  60783. hashLen = 66U;
  60784. }
  60785. sp_521_from_mp(ctx->x, 17, priv);
  60786. sp_521_from_bin(ctx->e, 17, hash, (int)hashLen);
  60787. if (hashLen == 66U) {
  60788. sp_521_rshift_17(ctx->e, ctx->e, 7);
  60789. }
  60790. ctx->state = 4;
  60791. break;
  60792. }
  60793. case 4: /* KMODORDER */
  60794. /* Conv k to Montgomery form (mod order) */
  60795. sp_521_mul_17(ctx->k, ctx->k, p521_norm_order);
  60796. err = sp_521_mod_17(ctx->k, ctx->k, p521_order);
  60797. if (err == MP_OKAY) {
  60798. sp_521_norm_17(ctx->k);
  60799. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  60800. ctx->state = 5;
  60801. }
  60802. break;
  60803. case 5: /* KINV */
  60804. /* kInv = 1/k mod order */
  60805. err = sp_521_mont_inv_order_17_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
  60806. if (err == MP_OKAY) {
  60807. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  60808. ctx->state = 6;
  60809. }
  60810. break;
  60811. case 6: /* KINVNORM */
  60812. sp_521_norm_17(ctx->kInv);
  60813. ctx->state = 7;
  60814. break;
  60815. case 7: /* R */
  60816. /* s = r * x + e */
  60817. sp_521_mul_17(ctx->x, ctx->x, ctx->r);
  60818. ctx->state = 8;
  60819. break;
  60820. case 8: /* S1 */
  60821. err = sp_521_mod_17(ctx->x, ctx->x, p521_order);
  60822. if (err == MP_OKAY)
  60823. ctx->state = 9;
  60824. break;
  60825. case 9: /* S2 */
  60826. {
  60827. sp_digit carry;
  60828. sp_int32 c;
  60829. sp_521_norm_17(ctx->x);
  60830. carry = sp_521_add_17(ctx->s, ctx->e, ctx->x);
  60831. sp_521_cond_sub_17(ctx->s, ctx->s,
  60832. p521_order, 0 - carry);
  60833. sp_521_norm_17(ctx->s);
  60834. c = sp_521_cmp_17(ctx->s, p521_order);
  60835. sp_521_cond_sub_17(ctx->s, ctx->s, p521_order,
  60836. (sp_digit)0 - (sp_digit)(c >= 0));
  60837. sp_521_norm_17(ctx->s);
  60838. /* s = s * k^-1 mod order */
  60839. sp_521_mont_mul_order_17(ctx->s, ctx->s, ctx->kInv);
  60840. sp_521_norm_17(ctx->s);
  60841. /* Check that signature is usable. */
  60842. if (sp_521_iszero_17(ctx->s) == 0) {
  60843. ctx->state = 10;
  60844. break;
  60845. }
  60846. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  60847. ctx->i = 1;
  60848. #endif
  60849. /* not usable gen, try again */
  60850. ctx->i--;
  60851. if (ctx->i == 0) {
  60852. err = RNG_FAILURE_E;
  60853. }
  60854. ctx->state = 1;
  60855. break;
  60856. }
  60857. case 10: /* RES */
  60858. err = sp_521_to_mp(ctx->r, rm);
  60859. if (err == MP_OKAY) {
  60860. err = sp_521_to_mp(ctx->s, sm);
  60861. }
  60862. break;
  60863. }
  60864. if (err == MP_OKAY && ctx->state != 10) {
  60865. err = FP_WOULDBLOCK;
  60866. }
  60867. if (err != FP_WOULDBLOCK) {
  60868. XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 17U);
  60869. XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 17U);
  60870. XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 17U);
  60871. XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 17U);
  60872. XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 17U);
  60873. }
  60874. return err;
  60875. }
  60876. #endif /* WOLFSSL_SP_NONBLOCK */
  60877. #endif /* HAVE_ECC_SIGN */
  60878. #ifndef WOLFSSL_SP_SMALL
  60879. #ifdef WOLFSSL_SP_SMALL
  60880. /* Sub b from a into r. (r = a - b)
  60881. *
  60882. * r A single precision integer.
  60883. * a A single precision integer.
  60884. * b A single precision integer.
  60885. */
  60886. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60887. static sp_digit sp_521_sub_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  60888. #else
  60889. static sp_digit sp_521_sub_17(sp_digit* r, const sp_digit* a, const sp_digit* b)
  60890. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60891. {
  60892. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60893. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  60894. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  60895. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  60896. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60897. __asm__ __volatile__ (
  60898. "MOV r11, #0x0\n\t"
  60899. "ADD r12, %[a], #0x40\n\t"
  60900. "\n"
  60901. "L_sp_521_sub_17_word:\n\t"
  60902. "RSBS r11, r11, #0x0\n\t"
  60903. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  60904. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  60905. "SBCS r3, r3, r7\n\t"
  60906. "SBCS r4, r4, r8\n\t"
  60907. "SBCS r5, r5, r9\n\t"
  60908. "SBCS r6, r6, r10\n\t"
  60909. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  60910. "SBC r11, r3, r3\n\t"
  60911. "CMP %[a], r12\n\t"
  60912. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  60913. "BNE L_sp_521_sub_17_word\n\t"
  60914. #else
  60915. "BNE.N L_sp_521_sub_17_word\n\t"
  60916. #endif
  60917. "RSBS r11, r11, #0x0\n\t"
  60918. "LDM %[a]!, {r3}\n\t"
  60919. "LDM %[b]!, {r7}\n\t"
  60920. "SBCS r3, r3, r7\n\t"
  60921. "STM %[r]!, {r3}\n\t"
  60922. "SBC %[r], r6, r6\n\t"
  60923. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  60924. :
  60925. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  60926. );
  60927. return (uint32_t)(size_t)r;
  60928. }
  60929. #else
  60930. /* Sub b from a into r. (r = a - b)
  60931. *
  60932. * r A single precision integer.
  60933. * a A single precision integer.
  60934. * b A single precision integer.
  60935. */
  60936. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60937. static sp_digit sp_521_sub_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  60938. #else
  60939. static sp_digit sp_521_sub_17(sp_digit* r, const sp_digit* a, const sp_digit* b)
  60940. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60941. {
  60942. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60943. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  60944. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  60945. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  60946. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60947. __asm__ __volatile__ (
  60948. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  60949. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  60950. "SUBS r3, r3, r7\n\t"
  60951. "SBCS r4, r4, r8\n\t"
  60952. "SBCS r5, r5, r9\n\t"
  60953. "SBCS r6, r6, r10\n\t"
  60954. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  60955. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  60956. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  60957. "SBCS r3, r3, r7\n\t"
  60958. "SBCS r4, r4, r8\n\t"
  60959. "SBCS r5, r5, r9\n\t"
  60960. "SBCS r6, r6, r10\n\t"
  60961. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  60962. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  60963. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  60964. "SBCS r3, r3, r7\n\t"
  60965. "SBCS r4, r4, r8\n\t"
  60966. "SBCS r5, r5, r9\n\t"
  60967. "SBCS r6, r6, r10\n\t"
  60968. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  60969. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  60970. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  60971. "SBCS r3, r3, r7\n\t"
  60972. "SBCS r4, r4, r8\n\t"
  60973. "SBCS r5, r5, r9\n\t"
  60974. "SBCS r6, r6, r10\n\t"
  60975. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  60976. "LDM %[a]!, {r3}\n\t"
  60977. "LDM %[b]!, {r7}\n\t"
  60978. "SBCS r3, r3, r7\n\t"
  60979. "STM %[r]!, {r3}\n\t"
  60980. "SBC %[r], r6, r6\n\t"
  60981. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  60982. :
  60983. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  60984. );
  60985. return (uint32_t)(size_t)r;
  60986. }
  60987. #endif /* WOLFSSL_SP_SMALL */
  60988. /* Divide the number by 2 mod the modulus. (r = a / 2 % m)
  60989. *
  60990. * r Result of division by 2.
  60991. * a Number to divide.
  60992. * m Modulus.
  60993. */
  60994. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  60995. static void sp_521_div2_mod_17(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  60996. #else
  60997. static void sp_521_div2_mod_17(sp_digit* r, const sp_digit* a, const sp_digit* m)
  60998. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  60999. {
  61000. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  61001. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  61002. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  61003. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  61004. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  61005. __asm__ __volatile__ (
  61006. "LDM %[a]!, {r4}\n\t"
  61007. "ANDS r3, r4, #0x1\n\t"
  61008. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61009. "BEQ L_sp_521_div2_mod_17_even\n\t"
  61010. #else
  61011. "BEQ.N L_sp_521_div2_mod_17_even\n\t"
  61012. #endif
  61013. "MOV r12, #0x0\n\t"
  61014. "LDM %[a]!, {r5, r6, r7}\n\t"
  61015. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  61016. "ADDS r4, r4, r8\n\t"
  61017. "ADCS r5, r5, r9\n\t"
  61018. "ADCS r6, r6, r10\n\t"
  61019. "ADCS r7, r7, r11\n\t"
  61020. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61021. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  61022. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  61023. "ADCS r4, r4, r8\n\t"
  61024. "ADCS r5, r5, r9\n\t"
  61025. "ADCS r6, r6, r10\n\t"
  61026. "ADCS r7, r7, r11\n\t"
  61027. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61028. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  61029. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  61030. "ADCS r4, r4, r8\n\t"
  61031. "ADCS r5, r5, r9\n\t"
  61032. "ADCS r6, r6, r10\n\t"
  61033. "ADCS r7, r7, r11\n\t"
  61034. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61035. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  61036. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  61037. "ADCS r4, r4, r8\n\t"
  61038. "ADCS r5, r5, r9\n\t"
  61039. "ADCS r6, r6, r10\n\t"
  61040. "ADCS r7, r7, r11\n\t"
  61041. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61042. "LDM %[a]!, {r4}\n\t"
  61043. "LDM %[m]!, {r8}\n\t"
  61044. "ADCS r4, r4, r8\n\t"
  61045. "STM %[r]!, {r4}\n\t"
  61046. "ADC r3, r12, r12\n\t"
  61047. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61048. "B L_sp_521_div2_mod_17_div2\n\t"
  61049. #else
  61050. "B.N L_sp_521_div2_mod_17_div2\n\t"
  61051. #endif
  61052. "\n"
  61053. "L_sp_521_div2_mod_17_even:\n\t"
  61054. "LDM %[a]!, {r5, r6, r7}\n\t"
  61055. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61056. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  61057. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61058. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  61059. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61060. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  61061. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  61062. "LDM %[a]!, {r4}\n\t"
  61063. "STM %[r]!, {r4}\n\t"
  61064. "\n"
  61065. "L_sp_521_div2_mod_17_div2:\n\t"
  61066. "SUB %[r], %[r], #0x44\n\t"
  61067. "LDRD r8, r9, [%[r]]\n\t"
  61068. "LSR r8, r8, #1\n\t"
  61069. "ORR r8, r8, r9, lsl #31\n\t"
  61070. "LSR r9, r9, #1\n\t"
  61071. "LDR r10, [%[r], #8]\n\t"
  61072. "STR r8, [%[r]]\n\t"
  61073. "ORR r9, r9, r10, lsl #31\n\t"
  61074. "LSR r10, r10, #1\n\t"
  61075. "LDR r8, [%[r], #12]\n\t"
  61076. "STR r9, [%[r], #4]\n\t"
  61077. "ORR r10, r10, r8, lsl #31\n\t"
  61078. "LSR r8, r8, #1\n\t"
  61079. "LDR r9, [%[r], #16]\n\t"
  61080. "STR r10, [%[r], #8]\n\t"
  61081. "ORR r8, r8, r9, lsl #31\n\t"
  61082. "LSR r9, r9, #1\n\t"
  61083. "LDR r10, [%[r], #20]\n\t"
  61084. "STR r8, [%[r], #12]\n\t"
  61085. "ORR r9, r9, r10, lsl #31\n\t"
  61086. "LSR r10, r10, #1\n\t"
  61087. "LDR r8, [%[r], #24]\n\t"
  61088. "STR r9, [%[r], #16]\n\t"
  61089. "ORR r10, r10, r8, lsl #31\n\t"
  61090. "LSR r8, r8, #1\n\t"
  61091. "LDR r9, [%[r], #28]\n\t"
  61092. "STR r10, [%[r], #20]\n\t"
  61093. "ORR r8, r8, r9, lsl #31\n\t"
  61094. "LSR r9, r9, #1\n\t"
  61095. "LDR r10, [%[r], #32]\n\t"
  61096. "STR r8, [%[r], #24]\n\t"
  61097. "ORR r9, r9, r10, lsl #31\n\t"
  61098. "LSR r10, r10, #1\n\t"
  61099. "LDR r8, [%[r], #36]\n\t"
  61100. "STR r9, [%[r], #28]\n\t"
  61101. "ORR r10, r10, r8, lsl #31\n\t"
  61102. "LSR r8, r8, #1\n\t"
  61103. "LDR r9, [%[r], #40]\n\t"
  61104. "STR r10, [%[r], #32]\n\t"
  61105. "ORR r8, r8, r9, lsl #31\n\t"
  61106. "LSR r9, r9, #1\n\t"
  61107. "LDR r10, [%[r], #44]\n\t"
  61108. "STR r8, [%[r], #36]\n\t"
  61109. "ORR r9, r9, r10, lsl #31\n\t"
  61110. "LSR r10, r10, #1\n\t"
  61111. "LDR r8, [%[r], #48]\n\t"
  61112. "STR r9, [%[r], #40]\n\t"
  61113. "ORR r10, r10, r8, lsl #31\n\t"
  61114. "LSR r8, r8, #1\n\t"
  61115. "LDR r9, [%[r], #52]\n\t"
  61116. "STR r10, [%[r], #44]\n\t"
  61117. "ORR r8, r8, r9, lsl #31\n\t"
  61118. "LSR r9, r9, #1\n\t"
  61119. "LDR r10, [%[r], #56]\n\t"
  61120. "STR r8, [%[r], #48]\n\t"
  61121. "ORR r9, r9, r10, lsl #31\n\t"
  61122. "LSR r10, r10, #1\n\t"
  61123. "LDR r8, [%[r], #60]\n\t"
  61124. "STR r9, [%[r], #52]\n\t"
  61125. "ORR r10, r10, r8, lsl #31\n\t"
  61126. "LSR r8, r8, #1\n\t"
  61127. "LDR r9, [%[r], #64]\n\t"
  61128. "STR r10, [%[r], #56]\n\t"
  61129. "ORR r8, r8, r9, lsl #31\n\t"
  61130. "LSR r9, r9, #1\n\t"
  61131. "ORR r9, r9, r3, lsl #31\n\t"
  61132. "STR r8, [%[r], #60]\n\t"
  61133. "STR r9, [%[r], #64]\n\t"
  61134. : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
  61135. :
  61136. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  61137. );
  61138. }
  61139. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  61140. static int sp_521_num_bits_17(const sp_digit* a_p)
  61141. #else
  61142. static int sp_521_num_bits_17(const sp_digit* a)
  61143. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  61144. {
  61145. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  61146. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  61147. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  61148. __asm__ __volatile__ (
  61149. "LDR r1, [%[a], #64]\n\t"
  61150. "CMP r1, #0x0\n\t"
  61151. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61152. "BEQ L_sp_521_num_bits_17_16\n\t"
  61153. #else
  61154. "BEQ.N L_sp_521_num_bits_17_16\n\t"
  61155. #endif
  61156. "MOV r2, #0x220\n\t"
  61157. "CLZ r4, r1\n\t"
  61158. "SUB r4, r2, r4\n\t"
  61159. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61160. "B L_sp_521_num_bits_17_18\n\t"
  61161. #else
  61162. "B.N L_sp_521_num_bits_17_18\n\t"
  61163. #endif
  61164. "\n"
  61165. "L_sp_521_num_bits_17_16:\n\t"
  61166. "LDR r1, [%[a], #60]\n\t"
  61167. "CMP r1, #0x0\n\t"
  61168. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61169. "BEQ L_sp_521_num_bits_17_15\n\t"
  61170. #else
  61171. "BEQ.N L_sp_521_num_bits_17_15\n\t"
  61172. #endif
  61173. "MOV r2, #0x200\n\t"
  61174. "CLZ r4, r1\n\t"
  61175. "SUB r4, r2, r4\n\t"
  61176. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61177. "B L_sp_521_num_bits_17_18\n\t"
  61178. #else
  61179. "B.N L_sp_521_num_bits_17_18\n\t"
  61180. #endif
  61181. "\n"
  61182. "L_sp_521_num_bits_17_15:\n\t"
  61183. "LDR r1, [%[a], #56]\n\t"
  61184. "CMP r1, #0x0\n\t"
  61185. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61186. "BEQ L_sp_521_num_bits_17_14\n\t"
  61187. #else
  61188. "BEQ.N L_sp_521_num_bits_17_14\n\t"
  61189. #endif
  61190. "MOV r2, #0x1e0\n\t"
  61191. "CLZ r4, r1\n\t"
  61192. "SUB r4, r2, r4\n\t"
  61193. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61194. "B L_sp_521_num_bits_17_18\n\t"
  61195. #else
  61196. "B.N L_sp_521_num_bits_17_18\n\t"
  61197. #endif
  61198. "\n"
  61199. "L_sp_521_num_bits_17_14:\n\t"
  61200. "LDR r1, [%[a], #52]\n\t"
  61201. "CMP r1, #0x0\n\t"
  61202. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61203. "BEQ L_sp_521_num_bits_17_13\n\t"
  61204. #else
  61205. "BEQ.N L_sp_521_num_bits_17_13\n\t"
  61206. #endif
  61207. "MOV r2, #0x1c0\n\t"
  61208. "CLZ r4, r1\n\t"
  61209. "SUB r4, r2, r4\n\t"
  61210. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61211. "B L_sp_521_num_bits_17_18\n\t"
  61212. #else
  61213. "B.N L_sp_521_num_bits_17_18\n\t"
  61214. #endif
  61215. "\n"
  61216. "L_sp_521_num_bits_17_13:\n\t"
  61217. "LDR r1, [%[a], #48]\n\t"
  61218. "CMP r1, #0x0\n\t"
  61219. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61220. "BEQ L_sp_521_num_bits_17_12\n\t"
  61221. #else
  61222. "BEQ.N L_sp_521_num_bits_17_12\n\t"
  61223. #endif
  61224. "MOV r2, #0x1a0\n\t"
  61225. "CLZ r4, r1\n\t"
  61226. "SUB r4, r2, r4\n\t"
  61227. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61228. "B L_sp_521_num_bits_17_18\n\t"
  61229. #else
  61230. "B.N L_sp_521_num_bits_17_18\n\t"
  61231. #endif
  61232. "\n"
  61233. "L_sp_521_num_bits_17_12:\n\t"
  61234. "LDR r1, [%[a], #44]\n\t"
  61235. "CMP r1, #0x0\n\t"
  61236. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61237. "BEQ L_sp_521_num_bits_17_11\n\t"
  61238. #else
  61239. "BEQ.N L_sp_521_num_bits_17_11\n\t"
  61240. #endif
  61241. "MOV r2, #0x180\n\t"
  61242. "CLZ r4, r1\n\t"
  61243. "SUB r4, r2, r4\n\t"
  61244. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61245. "B L_sp_521_num_bits_17_18\n\t"
  61246. #else
  61247. "B.N L_sp_521_num_bits_17_18\n\t"
  61248. #endif
  61249. "\n"
  61250. "L_sp_521_num_bits_17_11:\n\t"
  61251. "LDR r1, [%[a], #40]\n\t"
  61252. "CMP r1, #0x0\n\t"
  61253. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61254. "BEQ L_sp_521_num_bits_17_10\n\t"
  61255. #else
  61256. "BEQ.N L_sp_521_num_bits_17_10\n\t"
  61257. #endif
  61258. "MOV r2, #0x160\n\t"
  61259. "CLZ r4, r1\n\t"
  61260. "SUB r4, r2, r4\n\t"
  61261. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61262. "B L_sp_521_num_bits_17_18\n\t"
  61263. #else
  61264. "B.N L_sp_521_num_bits_17_18\n\t"
  61265. #endif
  61266. "\n"
  61267. "L_sp_521_num_bits_17_10:\n\t"
  61268. "LDR r1, [%[a], #36]\n\t"
  61269. "CMP r1, #0x0\n\t"
  61270. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61271. "BEQ L_sp_521_num_bits_17_9\n\t"
  61272. #else
  61273. "BEQ.N L_sp_521_num_bits_17_9\n\t"
  61274. #endif
  61275. "MOV r2, #0x140\n\t"
  61276. "CLZ r4, r1\n\t"
  61277. "SUB r4, r2, r4\n\t"
  61278. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61279. "B L_sp_521_num_bits_17_18\n\t"
  61280. #else
  61281. "B.N L_sp_521_num_bits_17_18\n\t"
  61282. #endif
  61283. "\n"
  61284. "L_sp_521_num_bits_17_9:\n\t"
  61285. "LDR r1, [%[a], #32]\n\t"
  61286. "CMP r1, #0x0\n\t"
  61287. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61288. "BEQ L_sp_521_num_bits_17_8\n\t"
  61289. #else
  61290. "BEQ.N L_sp_521_num_bits_17_8\n\t"
  61291. #endif
  61292. "MOV r2, #0x120\n\t"
  61293. "CLZ r4, r1\n\t"
  61294. "SUB r4, r2, r4\n\t"
  61295. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61296. "B L_sp_521_num_bits_17_18\n\t"
  61297. #else
  61298. "B.N L_sp_521_num_bits_17_18\n\t"
  61299. #endif
  61300. "\n"
  61301. "L_sp_521_num_bits_17_8:\n\t"
  61302. "LDR r1, [%[a], #28]\n\t"
  61303. "CMP r1, #0x0\n\t"
  61304. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61305. "BEQ L_sp_521_num_bits_17_7\n\t"
  61306. #else
  61307. "BEQ.N L_sp_521_num_bits_17_7\n\t"
  61308. #endif
  61309. "MOV r2, #0x100\n\t"
  61310. "CLZ r4, r1\n\t"
  61311. "SUB r4, r2, r4\n\t"
  61312. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61313. "B L_sp_521_num_bits_17_18\n\t"
  61314. #else
  61315. "B.N L_sp_521_num_bits_17_18\n\t"
  61316. #endif
  61317. "\n"
  61318. "L_sp_521_num_bits_17_7:\n\t"
  61319. "LDR r1, [%[a], #24]\n\t"
  61320. "CMP r1, #0x0\n\t"
  61321. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61322. "BEQ L_sp_521_num_bits_17_6\n\t"
  61323. #else
  61324. "BEQ.N L_sp_521_num_bits_17_6\n\t"
  61325. #endif
  61326. "MOV r2, #0xe0\n\t"
  61327. "CLZ r4, r1\n\t"
  61328. "SUB r4, r2, r4\n\t"
  61329. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61330. "B L_sp_521_num_bits_17_18\n\t"
  61331. #else
  61332. "B.N L_sp_521_num_bits_17_18\n\t"
  61333. #endif
  61334. "\n"
  61335. "L_sp_521_num_bits_17_6:\n\t"
  61336. "LDR r1, [%[a], #20]\n\t"
  61337. "CMP r1, #0x0\n\t"
  61338. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61339. "BEQ L_sp_521_num_bits_17_5\n\t"
  61340. #else
  61341. "BEQ.N L_sp_521_num_bits_17_5\n\t"
  61342. #endif
  61343. "MOV r2, #0xc0\n\t"
  61344. "CLZ r4, r1\n\t"
  61345. "SUB r4, r2, r4\n\t"
  61346. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61347. "B L_sp_521_num_bits_17_18\n\t"
  61348. #else
  61349. "B.N L_sp_521_num_bits_17_18\n\t"
  61350. #endif
  61351. "\n"
  61352. "L_sp_521_num_bits_17_5:\n\t"
  61353. "LDR r1, [%[a], #16]\n\t"
  61354. "CMP r1, #0x0\n\t"
  61355. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61356. "BEQ L_sp_521_num_bits_17_4\n\t"
  61357. #else
  61358. "BEQ.N L_sp_521_num_bits_17_4\n\t"
  61359. #endif
  61360. "MOV r2, #0xa0\n\t"
  61361. "CLZ r4, r1\n\t"
  61362. "SUB r4, r2, r4\n\t"
  61363. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61364. "B L_sp_521_num_bits_17_18\n\t"
  61365. #else
  61366. "B.N L_sp_521_num_bits_17_18\n\t"
  61367. #endif
  61368. "\n"
  61369. "L_sp_521_num_bits_17_4:\n\t"
  61370. "LDR r1, [%[a], #12]\n\t"
  61371. "CMP r1, #0x0\n\t"
  61372. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61373. "BEQ L_sp_521_num_bits_17_3\n\t"
  61374. #else
  61375. "BEQ.N L_sp_521_num_bits_17_3\n\t"
  61376. #endif
  61377. "MOV r2, #0x80\n\t"
  61378. "CLZ r4, r1\n\t"
  61379. "SUB r4, r2, r4\n\t"
  61380. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61381. "B L_sp_521_num_bits_17_18\n\t"
  61382. #else
  61383. "B.N L_sp_521_num_bits_17_18\n\t"
  61384. #endif
  61385. "\n"
  61386. "L_sp_521_num_bits_17_3:\n\t"
  61387. "LDR r1, [%[a], #8]\n\t"
  61388. "CMP r1, #0x0\n\t"
  61389. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61390. "BEQ L_sp_521_num_bits_17_2\n\t"
  61391. #else
  61392. "BEQ.N L_sp_521_num_bits_17_2\n\t"
  61393. #endif
  61394. "MOV r2, #0x60\n\t"
  61395. "CLZ r4, r1\n\t"
  61396. "SUB r4, r2, r4\n\t"
  61397. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61398. "B L_sp_521_num_bits_17_18\n\t"
  61399. #else
  61400. "B.N L_sp_521_num_bits_17_18\n\t"
  61401. #endif
  61402. "\n"
  61403. "L_sp_521_num_bits_17_2:\n\t"
  61404. "LDR r1, [%[a], #4]\n\t"
  61405. "CMP r1, #0x0\n\t"
  61406. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61407. "BEQ L_sp_521_num_bits_17_1\n\t"
  61408. #else
  61409. "BEQ.N L_sp_521_num_bits_17_1\n\t"
  61410. #endif
  61411. "MOV r2, #0x40\n\t"
  61412. "CLZ r4, r1\n\t"
  61413. "SUB r4, r2, r4\n\t"
  61414. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  61415. "B L_sp_521_num_bits_17_18\n\t"
  61416. #else
  61417. "B.N L_sp_521_num_bits_17_18\n\t"
  61418. #endif
  61419. "\n"
  61420. "L_sp_521_num_bits_17_1:\n\t"
  61421. "LDR r1, [%[a]]\n\t"
  61422. "MOV r2, #0x20\n\t"
  61423. "CLZ r4, r1\n\t"
  61424. "SUB r4, r2, r4\n\t"
  61425. "\n"
  61426. "L_sp_521_num_bits_17_18:\n\t"
  61427. "MOV %[a], r4\n\t"
  61428. : [a] "+r" (a)
  61429. :
  61430. : "memory", "r1", "r2", "r3", "r4", "r5", "cc"
  61431. );
  61432. return (uint32_t)(size_t)a;
  61433. }
  61434. /* Non-constant time modular inversion.
  61435. *
  61436. * @param [out] r Resulting number.
  61437. * @param [in] a Number to invert.
  61438. * @param [in] m Modulus.
  61439. * @return MP_OKAY on success.
  61440. */
  61441. static int sp_521_mod_inv_17(sp_digit* r, const sp_digit* a, const sp_digit* m)
  61442. {
  61443. sp_digit u[17];
  61444. sp_digit v[17];
  61445. sp_digit b[17];
  61446. sp_digit d[17];
  61447. int ut, vt;
  61448. sp_digit o;
  61449. XMEMCPY(u, m, sizeof(u));
  61450. XMEMCPY(v, a, sizeof(v));
  61451. ut = sp_521_num_bits_17(u);
  61452. vt = sp_521_num_bits_17(v);
  61453. XMEMSET(b, 0, sizeof(b));
  61454. if ((v[0] & 1) == 0) {
  61455. sp_521_rshift1_17(v, v);
  61456. XMEMCPY(d, m, sizeof(u));
  61457. d[0] += 1;
  61458. sp_521_rshift1_17(d, d);
  61459. vt--;
  61460. while ((v[0] & 1) == 0) {
  61461. sp_521_rshift1_17(v, v);
  61462. sp_521_div2_mod_17(d, d, m);
  61463. vt--;
  61464. }
  61465. }
  61466. else {
  61467. XMEMSET(d+1, 0, sizeof(d)-sizeof(sp_digit));
  61468. d[0] = 1;
  61469. }
  61470. while (ut > 1 && vt > 1) {
  61471. if ((ut > vt) || ((ut == vt) && (sp_521_cmp_17(u, v) >= 0))) {
  61472. sp_521_sub_17(u, u, v);
  61473. o = sp_521_sub_17(b, b, d);
  61474. if (o != 0)
  61475. sp_521_add_17(b, b, m);
  61476. ut = sp_521_num_bits_17(u);
  61477. do {
  61478. sp_521_rshift1_17(u, u);
  61479. sp_521_div2_mod_17(b, b, m);
  61480. ut--;
  61481. }
  61482. while (ut > 0 && (u[0] & 1) == 0);
  61483. }
  61484. else {
  61485. sp_521_sub_17(v, v, u);
  61486. o = sp_521_sub_17(d, d, b);
  61487. if (o != 0)
  61488. sp_521_add_17(d, d, m);
  61489. vt = sp_521_num_bits_17(v);
  61490. do {
  61491. sp_521_rshift1_17(v, v);
  61492. sp_521_div2_mod_17(d, d, m);
  61493. vt--;
  61494. }
  61495. while (vt > 0 && (v[0] & 1) == 0);
  61496. }
  61497. }
  61498. if (ut == 1)
  61499. XMEMCPY(r, b, sizeof(b));
  61500. else
  61501. XMEMCPY(r, d, sizeof(d));
  61502. return MP_OKAY;
  61503. }
  61504. #endif /* WOLFSSL_SP_SMALL */
  61505. /* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
  61506. *
  61507. * p1 First point to add and holds result.
  61508. * p2 Second point to add.
  61509. * tmp Temporary storage for intermediate numbers.
  61510. */
  61511. static void sp_521_add_points_17(sp_point_521* p1, const sp_point_521* p2,
  61512. sp_digit* tmp)
  61513. {
  61514. sp_521_proj_point_add_17(p1, p1, p2, tmp);
  61515. if (sp_521_iszero_17(p1->z)) {
  61516. if (sp_521_iszero_17(p1->x) && sp_521_iszero_17(p1->y)) {
  61517. sp_521_proj_point_dbl_17(p1, p2, tmp);
  61518. }
  61519. else {
  61520. /* Y ordinate is not used from here - don't set. */
  61521. p1->x[0] = 0;
  61522. p1->x[1] = 0;
  61523. p1->x[2] = 0;
  61524. p1->x[3] = 0;
  61525. p1->x[4] = 0;
  61526. p1->x[5] = 0;
  61527. p1->x[6] = 0;
  61528. p1->x[7] = 0;
  61529. p1->x[8] = 0;
  61530. p1->x[9] = 0;
  61531. p1->x[10] = 0;
  61532. p1->x[11] = 0;
  61533. p1->x[12] = 0;
  61534. p1->x[13] = 0;
  61535. p1->x[14] = 0;
  61536. p1->x[15] = 0;
  61537. p1->x[16] = 0;
  61538. XMEMCPY(p1->z, p521_norm_mod, sizeof(p521_norm_mod));
  61539. }
  61540. }
  61541. }
  61542. /* Calculate the verification point: [e/s]G + [r/s]Q
  61543. *
  61544. * p1 Calculated point.
  61545. * p2 Public point and temporary.
  61546. * s Second part of signature as a number.
  61547. * u1 Temporary number.
  61548. * u2 Temporary number.
  61549. * heap Heap to use for allocation.
  61550. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  61551. */
  61552. static int sp_521_calc_vfy_point_17(sp_point_521* p1, sp_point_521* p2,
  61553. sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
  61554. {
  61555. int err;
  61556. #ifndef WOLFSSL_SP_SMALL
  61557. err = sp_521_mod_inv_17(s, s, p521_order);
  61558. if (err == MP_OKAY)
  61559. #endif /* !WOLFSSL_SP_SMALL */
  61560. {
  61561. sp_521_mul_17(s, s, p521_norm_order);
  61562. err = sp_521_mod_17(s, s, p521_order);
  61563. }
  61564. if (err == MP_OKAY) {
  61565. sp_521_norm_17(s);
  61566. #ifdef WOLFSSL_SP_SMALL
  61567. {
  61568. sp_521_mont_inv_order_17(s, s, tmp);
  61569. sp_521_mont_mul_order_17(u1, u1, s);
  61570. sp_521_mont_mul_order_17(u2, u2, s);
  61571. }
  61572. #else
  61573. {
  61574. sp_521_mont_mul_order_17(u1, u1, s);
  61575. sp_521_mont_mul_order_17(u2, u2, s);
  61576. }
  61577. #endif /* WOLFSSL_SP_SMALL */
  61578. {
  61579. err = sp_521_ecc_mulmod_base_17(p1, u1, 0, 0, heap);
  61580. }
  61581. }
  61582. if ((err == MP_OKAY) && sp_521_iszero_17(p1->z)) {
  61583. p1->infinity = 1;
  61584. }
  61585. if (err == MP_OKAY) {
  61586. err = sp_521_ecc_mulmod_17(p2, p2, u2, 0, 0, heap);
  61587. }
  61588. if ((err == MP_OKAY) && sp_521_iszero_17(p2->z)) {
  61589. p2->infinity = 1;
  61590. }
  61591. if (err == MP_OKAY) {
  61592. sp_521_add_points_17(p1, p2, tmp);
  61593. }
  61594. return err;
  61595. }
  61596. #ifdef HAVE_ECC_VERIFY
  61597. /* Verify the signature values with the hash and public key.
  61598. * e = Truncate(hash, 521)
  61599. * u1 = e/s mod order
  61600. * u2 = r/s mod order
  61601. * r == (u1.G + u2.Q)->x mod order
  61602. * Optimization: Leave point in projective form.
  61603. * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
  61604. * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
  61605. * The hash is truncated to the first 521 bits.
  61606. *
  61607. * hash Hash to sign.
  61608. * hashLen Length of the hash data.
  61609. * rng Random number generator.
  61610. * priv Private part of key - scalar.
  61611. * rm First part of result as an mp_int.
  61612. * sm Sirst part of result as an mp_int.
  61613. * heap Heap to use for allocation.
  61614. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  61615. */
  61616. int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX,
  61617. const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
  61618. int* res, void* heap)
  61619. {
  61620. #ifdef WOLFSSL_SP_SMALL_STACK
  61621. sp_digit* u1 = NULL;
  61622. sp_point_521* p1 = NULL;
  61623. #else
  61624. sp_digit u1[18 * 17];
  61625. sp_point_521 p1[2];
  61626. #endif
  61627. sp_digit* u2 = NULL;
  61628. sp_digit* s = NULL;
  61629. sp_digit* tmp = NULL;
  61630. sp_point_521* p2 = NULL;
  61631. sp_digit carry;
  61632. sp_int32 c = 0;
  61633. int err = MP_OKAY;
  61634. #ifdef WOLFSSL_SP_SMALL_STACK
  61635. if (err == MP_OKAY) {
  61636. p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  61637. DYNAMIC_TYPE_ECC);
  61638. if (p1 == NULL)
  61639. err = MEMORY_E;
  61640. }
  61641. if (err == MP_OKAY) {
  61642. u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 17, heap,
  61643. DYNAMIC_TYPE_ECC);
  61644. if (u1 == NULL)
  61645. err = MEMORY_E;
  61646. }
  61647. #endif
  61648. if (err == MP_OKAY) {
  61649. u2 = u1 + 2 * 17;
  61650. s = u1 + 4 * 17;
  61651. tmp = u1 + 6 * 17;
  61652. p2 = p1 + 1;
  61653. if (hashLen > 66U) {
  61654. hashLen = 66U;
  61655. }
  61656. sp_521_from_bin(u1, 17, hash, (int)hashLen);
  61657. sp_521_from_mp(u2, 17, rm);
  61658. sp_521_from_mp(s, 17, sm);
  61659. sp_521_from_mp(p2->x, 17, pX);
  61660. sp_521_from_mp(p2->y, 17, pY);
  61661. sp_521_from_mp(p2->z, 17, pZ);
  61662. if (hashLen == 66U) {
  61663. sp_521_rshift_17(u1, u1, 7);
  61664. }
  61665. err = sp_521_calc_vfy_point_17(p1, p2, s, u1, u2, tmp, heap);
  61666. }
  61667. if (err == MP_OKAY) {
  61668. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  61669. /* Reload r and convert to Montgomery form. */
  61670. sp_521_from_mp(u2, 17, rm);
  61671. err = sp_521_mod_mul_norm_17(u2, u2, p521_mod);
  61672. }
  61673. if (err == MP_OKAY) {
  61674. /* u1 = r.z'.z' mod prime */
  61675. sp_521_mont_sqr_17(p1->z, p1->z, p521_mod, p521_mp_mod);
  61676. sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod);
  61677. *res = (int)(sp_521_cmp_17(p1->x, u1) == 0);
  61678. if (*res == 0) {
  61679. /* Reload r and add order. */
  61680. sp_521_from_mp(u2, 17, rm);
  61681. carry = sp_521_add_17(u2, u2, p521_order);
  61682. /* Carry means result is greater than mod and is not valid. */
  61683. if (carry == 0) {
  61684. sp_521_norm_17(u2);
  61685. /* Compare with mod and if greater or equal then not valid. */
  61686. c = sp_521_cmp_17(u2, p521_mod);
  61687. }
  61688. }
  61689. if ((*res == 0) && (c < 0)) {
  61690. /* Convert to Montogomery form */
  61691. err = sp_521_mod_mul_norm_17(u2, u2, p521_mod);
  61692. if (err == MP_OKAY) {
  61693. /* u1 = (r + 1*order).z'.z' mod prime */
  61694. {
  61695. sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod);
  61696. }
  61697. *res = (sp_521_cmp_17(p1->x, u1) == 0);
  61698. }
  61699. }
  61700. }
  61701. #ifdef WOLFSSL_SP_SMALL_STACK
  61702. if (u1 != NULL)
  61703. XFREE(u1, heap, DYNAMIC_TYPE_ECC);
  61704. if (p1 != NULL)
  61705. XFREE(p1, heap, DYNAMIC_TYPE_ECC);
  61706. #endif
  61707. return err;
  61708. }
  61709. #ifdef WOLFSSL_SP_NONBLOCK
  61710. typedef struct sp_ecc_verify_521_ctx {
  61711. int state;
  61712. union {
  61713. sp_521_ecc_mulmod_17_ctx mulmod_ctx;
  61714. sp_521_mont_inv_order_17_ctx mont_inv_order_ctx;
  61715. sp_521_proj_point_dbl_17_ctx dbl_ctx;
  61716. sp_521_proj_point_add_17_ctx add_ctx;
  61717. };
  61718. sp_digit u1[2*17];
  61719. sp_digit u2[2*17];
  61720. sp_digit s[2*17];
  61721. sp_digit tmp[2*17 * 6];
  61722. sp_point_521 p1;
  61723. sp_point_521 p2;
  61724. } sp_ecc_verify_521_ctx;
  61725. int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
  61726. word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
  61727. const mp_int* rm, const mp_int* sm, int* res, void* heap)
  61728. {
  61729. int err = FP_WOULDBLOCK;
  61730. sp_ecc_verify_521_ctx* ctx = (sp_ecc_verify_521_ctx*)sp_ctx->data;
  61731. typedef char ctx_size_test[sizeof(sp_ecc_verify_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  61732. (void)sizeof(ctx_size_test);
  61733. switch (ctx->state) {
  61734. case 0: /* INIT */
  61735. if (hashLen > 66U) {
  61736. hashLen = 66U;
  61737. }
  61738. sp_521_from_bin(ctx->u1, 17, hash, (int)hashLen);
  61739. sp_521_from_mp(ctx->u2, 17, rm);
  61740. sp_521_from_mp(ctx->s, 17, sm);
  61741. sp_521_from_mp(ctx->p2.x, 17, pX);
  61742. sp_521_from_mp(ctx->p2.y, 17, pY);
  61743. sp_521_from_mp(ctx->p2.z, 17, pZ);
  61744. if (hashLen == 66U) {
  61745. sp_521_rshift_17(ctx->u1, ctx->u1, 7);
  61746. }
  61747. ctx->state = 1;
  61748. break;
  61749. case 1: /* NORMS0 */
  61750. sp_521_mul_17(ctx->s, ctx->s, p521_norm_order);
  61751. err = sp_521_mod_17(ctx->s, ctx->s, p521_order);
  61752. if (err == MP_OKAY)
  61753. ctx->state = 2;
  61754. break;
  61755. case 2: /* NORMS1 */
  61756. sp_521_norm_17(ctx->s);
  61757. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  61758. ctx->state = 3;
  61759. break;
  61760. case 3: /* NORMS2 */
  61761. err = sp_521_mont_inv_order_17_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
  61762. if (err == MP_OKAY) {
  61763. ctx->state = 4;
  61764. }
  61765. break;
  61766. case 4: /* NORMS3 */
  61767. sp_521_mont_mul_order_17(ctx->u1, ctx->u1, ctx->s);
  61768. ctx->state = 5;
  61769. break;
  61770. case 5: /* NORMS4 */
  61771. sp_521_mont_mul_order_17(ctx->u2, ctx->u2, ctx->s);
  61772. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  61773. ctx->state = 6;
  61774. break;
  61775. case 6: /* MULBASE */
  61776. err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p521_base, ctx->u1, 0, 0, heap);
  61777. if (err == MP_OKAY) {
  61778. if (sp_521_iszero_17(ctx->p1.z)) {
  61779. ctx->p1.infinity = 1;
  61780. }
  61781. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  61782. ctx->state = 7;
  61783. }
  61784. break;
  61785. case 7: /* MULMOD */
  61786. err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
  61787. if (err == MP_OKAY) {
  61788. if (sp_521_iszero_17(ctx->p2.z)) {
  61789. ctx->p2.infinity = 1;
  61790. }
  61791. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  61792. ctx->state = 8;
  61793. }
  61794. break;
  61795. case 8: /* ADD */
  61796. err = sp_521_proj_point_add_17_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
  61797. if (err == MP_OKAY)
  61798. ctx->state = 9;
  61799. break;
  61800. case 9: /* MONT */
  61801. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  61802. /* Reload r and convert to Montgomery form. */
  61803. sp_521_from_mp(ctx->u2, 17, rm);
  61804. err = sp_521_mod_mul_norm_17(ctx->u2, ctx->u2, p521_mod);
  61805. if (err == MP_OKAY)
  61806. ctx->state = 10;
  61807. break;
  61808. case 10: /* SQR */
  61809. /* u1 = r.z'.z' mod prime */
  61810. sp_521_mont_sqr_17(ctx->p1.z, ctx->p1.z, p521_mod, p521_mp_mod);
  61811. ctx->state = 11;
  61812. break;
  61813. case 11: /* MUL */
  61814. sp_521_mont_mul_17(ctx->u1, ctx->u2, ctx->p1.z, p521_mod, p521_mp_mod);
  61815. ctx->state = 12;
  61816. break;
  61817. case 12: /* RES */
  61818. {
  61819. sp_int32 c = 0;
  61820. err = MP_OKAY; /* math okay, now check result */
  61821. *res = (int)(sp_521_cmp_17(ctx->p1.x, ctx->u1) == 0);
  61822. if (*res == 0) {
  61823. sp_digit carry;
  61824. /* Reload r and add order. */
  61825. sp_521_from_mp(ctx->u2, 17, rm);
  61826. carry = sp_521_add_17(ctx->u2, ctx->u2, p521_order);
  61827. /* Carry means result is greater than mod and is not valid. */
  61828. if (carry == 0) {
  61829. sp_521_norm_17(ctx->u2);
  61830. /* Compare with mod and if greater or equal then not valid. */
  61831. c = sp_521_cmp_17(ctx->u2, p521_mod);
  61832. }
  61833. }
  61834. if ((*res == 0) && (c < 0)) {
  61835. /* Convert to Montogomery form */
  61836. err = sp_521_mod_mul_norm_17(ctx->u2, ctx->u2, p521_mod);
  61837. if (err == MP_OKAY) {
  61838. /* u1 = (r + 1*order).z'.z' mod prime */
  61839. sp_521_mont_mul_17(ctx->u1, ctx->u2, ctx->p1.z, p521_mod,
  61840. p521_mp_mod);
  61841. *res = (int)(sp_521_cmp_17(ctx->p1.x, ctx->u1) == 0);
  61842. }
  61843. }
  61844. break;
  61845. }
  61846. } /* switch */
  61847. if (err == MP_OKAY && ctx->state != 12) {
  61848. err = FP_WOULDBLOCK;
  61849. }
  61850. return err;
  61851. }
  61852. #endif /* WOLFSSL_SP_NONBLOCK */
  61853. #endif /* HAVE_ECC_VERIFY */
  61854. #ifdef HAVE_ECC_CHECK_KEY
  61855. /* Check that the x and y ordinates are a valid point on the curve.
  61856. *
  61857. * point EC point.
  61858. * heap Heap to use if dynamically allocating.
  61859. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  61860. * not on the curve and MP_OKAY otherwise.
  61861. */
  61862. static int sp_521_ecc_is_point_17(const sp_point_521* point,
  61863. void* heap)
  61864. {
  61865. #ifdef WOLFSSL_SP_SMALL_STACK
  61866. sp_digit* t1 = NULL;
  61867. #else
  61868. sp_digit t1[17 * 4];
  61869. #endif
  61870. sp_digit* t2 = NULL;
  61871. int err = MP_OKAY;
  61872. #ifdef WOLFSSL_SP_SMALL_STACK
  61873. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 17 * 4, heap, DYNAMIC_TYPE_ECC);
  61874. if (t1 == NULL)
  61875. err = MEMORY_E;
  61876. #endif
  61877. (void)heap;
  61878. if (err == MP_OKAY) {
  61879. t2 = t1 + 2 * 17;
  61880. /* y^2 - x^3 - a.x = b */
  61881. sp_521_sqr_17(t1, point->y);
  61882. (void)sp_521_mod_17(t1, t1, p521_mod);
  61883. sp_521_sqr_17(t2, point->x);
  61884. (void)sp_521_mod_17(t2, t2, p521_mod);
  61885. sp_521_mul_17(t2, t2, point->x);
  61886. (void)sp_521_mod_17(t2, t2, p521_mod);
  61887. sp_521_mont_sub_17(t1, t1, t2, p521_mod);
  61888. /* y^2 - x^3 + 3.x = b, when a = -3 */
  61889. sp_521_mont_add_17(t1, t1, point->x, p521_mod);
  61890. sp_521_mont_add_17(t1, t1, point->x, p521_mod);
  61891. sp_521_mont_add_17(t1, t1, point->x, p521_mod);
  61892. if (sp_521_cmp_17(t1, p521_b) != 0) {
  61893. err = MP_VAL;
  61894. }
  61895. }
  61896. #ifdef WOLFSSL_SP_SMALL_STACK
  61897. if (t1 != NULL)
  61898. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  61899. #endif
  61900. return err;
  61901. }
  61902. /* Check that the x and y ordinates are a valid point on the curve.
  61903. *
  61904. * pX X ordinate of EC point.
  61905. * pY Y ordinate of EC point.
  61906. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  61907. * not on the curve and MP_OKAY otherwise.
  61908. */
  61909. int sp_ecc_is_point_521(const mp_int* pX, const mp_int* pY)
  61910. {
  61911. #ifdef WOLFSSL_SP_SMALL_STACK
  61912. sp_point_521* pub = NULL;
  61913. #else
  61914. sp_point_521 pub[1];
  61915. #endif
  61916. const byte one[1] = { 1 };
  61917. int err = MP_OKAY;
  61918. #ifdef WOLFSSL_SP_SMALL_STACK
  61919. pub = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
  61920. DYNAMIC_TYPE_ECC);
  61921. if (pub == NULL)
  61922. err = MEMORY_E;
  61923. #endif
  61924. if (err == MP_OKAY) {
  61925. sp_521_from_mp(pub->x, 17, pX);
  61926. sp_521_from_mp(pub->y, 17, pY);
  61927. sp_521_from_bin(pub->z, 17, one, (int)sizeof(one));
  61928. err = sp_521_ecc_is_point_17(pub, NULL);
  61929. }
  61930. #ifdef WOLFSSL_SP_SMALL_STACK
  61931. if (pub != NULL)
  61932. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  61933. #endif
  61934. return err;
  61935. }
  61936. /* Check that the private scalar generates the EC point (px, py), the point is
  61937. * on the curve and the point has the correct order.
  61938. *
  61939. * pX X ordinate of EC point.
  61940. * pY Y ordinate of EC point.
  61941. * privm Private scalar that generates EC point.
  61942. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  61943. * not on the curve, ECC_INF_E if the point does not have the correct order,
  61944. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  61945. * MP_OKAY otherwise.
  61946. */
  61947. int sp_ecc_check_key_521(const mp_int* pX, const mp_int* pY,
  61948. const mp_int* privm, void* heap)
  61949. {
  61950. #ifdef WOLFSSL_SP_SMALL_STACK
  61951. sp_digit* priv = NULL;
  61952. sp_point_521* pub = NULL;
  61953. #else
  61954. sp_digit priv[17];
  61955. sp_point_521 pub[2];
  61956. #endif
  61957. sp_point_521* p = NULL;
  61958. const byte one[1] = { 1 };
  61959. int err = MP_OKAY;
  61960. /* Quick check the lengs of public key ordinates and private key are in
  61961. * range. Proper check later.
  61962. */
  61963. if (((mp_count_bits(pX) > 521) ||
  61964. (mp_count_bits(pY) > 521) ||
  61965. ((privm != NULL) && (mp_count_bits(privm) > 521)))) {
  61966. err = ECC_OUT_OF_RANGE_E;
  61967. }
  61968. #ifdef WOLFSSL_SP_SMALL_STACK
  61969. if (err == MP_OKAY) {
  61970. pub = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  61971. DYNAMIC_TYPE_ECC);
  61972. if (pub == NULL)
  61973. err = MEMORY_E;
  61974. }
  61975. if (err == MP_OKAY && privm) {
  61976. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 17, heap,
  61977. DYNAMIC_TYPE_ECC);
  61978. if (priv == NULL)
  61979. err = MEMORY_E;
  61980. }
  61981. #endif
  61982. if (err == MP_OKAY) {
  61983. p = pub + 1;
  61984. sp_521_from_mp(pub->x, 17, pX);
  61985. sp_521_from_mp(pub->y, 17, pY);
  61986. sp_521_from_bin(pub->z, 17, one, (int)sizeof(one));
  61987. if (privm)
  61988. sp_521_from_mp(priv, 17, privm);
  61989. /* Check point at infinitiy. */
  61990. if ((sp_521_iszero_17(pub->x) != 0) &&
  61991. (sp_521_iszero_17(pub->y) != 0)) {
  61992. err = ECC_INF_E;
  61993. }
  61994. }
  61995. /* Check range of X and Y */
  61996. if ((err == MP_OKAY) &&
  61997. ((sp_521_cmp_17(pub->x, p521_mod) >= 0) ||
  61998. (sp_521_cmp_17(pub->y, p521_mod) >= 0))) {
  61999. err = ECC_OUT_OF_RANGE_E;
  62000. }
  62001. if (err == MP_OKAY) {
  62002. /* Check point is on curve */
  62003. err = sp_521_ecc_is_point_17(pub, heap);
  62004. }
  62005. if (err == MP_OKAY) {
  62006. /* Point * order = infinity */
  62007. err = sp_521_ecc_mulmod_17(p, pub, p521_order, 1, 1, heap);
  62008. }
  62009. /* Check result is infinity */
  62010. if ((err == MP_OKAY) && ((sp_521_iszero_17(p->x) == 0) ||
  62011. (sp_521_iszero_17(p->y) == 0))) {
  62012. err = ECC_INF_E;
  62013. }
  62014. if (privm) {
  62015. if (err == MP_OKAY) {
  62016. /* Base * private = point */
  62017. err = sp_521_ecc_mulmod_base_17(p, priv, 1, 1, heap);
  62018. }
  62019. /* Check result is public key */
  62020. if ((err == MP_OKAY) &&
  62021. ((sp_521_cmp_17(p->x, pub->x) != 0) ||
  62022. (sp_521_cmp_17(p->y, pub->y) != 0))) {
  62023. err = ECC_PRIV_KEY_E;
  62024. }
  62025. }
  62026. #ifdef WOLFSSL_SP_SMALL_STACK
  62027. if (pub != NULL)
  62028. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  62029. if (priv != NULL)
  62030. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  62031. #endif
  62032. return err;
  62033. }
  62034. #endif
  62035. #ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
  62036. /* Add two projective EC points together.
  62037. * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
  62038. *
  62039. * pX First EC point's X ordinate.
  62040. * pY First EC point's Y ordinate.
  62041. * pZ First EC point's Z ordinate.
  62042. * qX Second EC point's X ordinate.
  62043. * qY Second EC point's Y ordinate.
  62044. * qZ Second EC point's Z ordinate.
  62045. * rX Resultant EC point's X ordinate.
  62046. * rY Resultant EC point's Y ordinate.
  62047. * rZ Resultant EC point's Z ordinate.
  62048. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  62049. */
  62050. int sp_ecc_proj_add_point_521(mp_int* pX, mp_int* pY, mp_int* pZ,
  62051. mp_int* qX, mp_int* qY, mp_int* qZ,
  62052. mp_int* rX, mp_int* rY, mp_int* rZ)
  62053. {
  62054. #ifdef WOLFSSL_SP_SMALL_STACK
  62055. sp_digit* tmp = NULL;
  62056. sp_point_521* p = NULL;
  62057. #else
  62058. sp_digit tmp[2 * 17 * 6];
  62059. sp_point_521 p[2];
  62060. #endif
  62061. sp_point_521* q = NULL;
  62062. int err = MP_OKAY;
  62063. #ifdef WOLFSSL_SP_SMALL_STACK
  62064. if (err == MP_OKAY) {
  62065. p = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, NULL,
  62066. DYNAMIC_TYPE_ECC);
  62067. if (p == NULL)
  62068. err = MEMORY_E;
  62069. }
  62070. if (err == MP_OKAY) {
  62071. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 6, NULL,
  62072. DYNAMIC_TYPE_ECC);
  62073. if (tmp == NULL) {
  62074. err = MEMORY_E;
  62075. }
  62076. }
  62077. #endif
  62078. if (err == MP_OKAY) {
  62079. q = p + 1;
  62080. sp_521_from_mp(p->x, 17, pX);
  62081. sp_521_from_mp(p->y, 17, pY);
  62082. sp_521_from_mp(p->z, 17, pZ);
  62083. sp_521_from_mp(q->x, 17, qX);
  62084. sp_521_from_mp(q->y, 17, qY);
  62085. sp_521_from_mp(q->z, 17, qZ);
  62086. p->infinity = sp_521_iszero_17(p->x) &
  62087. sp_521_iszero_17(p->y);
  62088. q->infinity = sp_521_iszero_17(q->x) &
  62089. sp_521_iszero_17(q->y);
  62090. sp_521_proj_point_add_17(p, p, q, tmp);
  62091. }
  62092. if (err == MP_OKAY) {
  62093. err = sp_521_to_mp(p->x, rX);
  62094. }
  62095. if (err == MP_OKAY) {
  62096. err = sp_521_to_mp(p->y, rY);
  62097. }
  62098. if (err == MP_OKAY) {
  62099. err = sp_521_to_mp(p->z, rZ);
  62100. }
  62101. #ifdef WOLFSSL_SP_SMALL_STACK
  62102. if (tmp != NULL)
  62103. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  62104. if (p != NULL)
  62105. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  62106. #endif
  62107. return err;
  62108. }
  62109. /* Double a projective EC point.
  62110. * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
  62111. *
  62112. * pX EC point's X ordinate.
  62113. * pY EC point's Y ordinate.
  62114. * pZ EC point's Z ordinate.
  62115. * rX Resultant EC point's X ordinate.
  62116. * rY Resultant EC point's Y ordinate.
  62117. * rZ Resultant EC point's Z ordinate.
  62118. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  62119. */
  62120. int sp_ecc_proj_dbl_point_521(mp_int* pX, mp_int* pY, mp_int* pZ,
  62121. mp_int* rX, mp_int* rY, mp_int* rZ)
  62122. {
  62123. #ifdef WOLFSSL_SP_SMALL_STACK
  62124. sp_digit* tmp = NULL;
  62125. sp_point_521* p = NULL;
  62126. #else
  62127. sp_digit tmp[2 * 17 * 2];
  62128. sp_point_521 p[1];
  62129. #endif
  62130. int err = MP_OKAY;
  62131. #ifdef WOLFSSL_SP_SMALL_STACK
  62132. if (err == MP_OKAY) {
  62133. p = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
  62134. DYNAMIC_TYPE_ECC);
  62135. if (p == NULL)
  62136. err = MEMORY_E;
  62137. }
  62138. if (err == MP_OKAY) {
  62139. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 2, NULL,
  62140. DYNAMIC_TYPE_ECC);
  62141. if (tmp == NULL)
  62142. err = MEMORY_E;
  62143. }
  62144. #endif
  62145. if (err == MP_OKAY) {
  62146. sp_521_from_mp(p->x, 17, pX);
  62147. sp_521_from_mp(p->y, 17, pY);
  62148. sp_521_from_mp(p->z, 17, pZ);
  62149. p->infinity = sp_521_iszero_17(p->x) &
  62150. sp_521_iszero_17(p->y);
  62151. sp_521_proj_point_dbl_17(p, p, tmp);
  62152. }
  62153. if (err == MP_OKAY) {
  62154. err = sp_521_to_mp(p->x, rX);
  62155. }
  62156. if (err == MP_OKAY) {
  62157. err = sp_521_to_mp(p->y, rY);
  62158. }
  62159. if (err == MP_OKAY) {
  62160. err = sp_521_to_mp(p->z, rZ);
  62161. }
  62162. #ifdef WOLFSSL_SP_SMALL_STACK
  62163. if (tmp != NULL)
  62164. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  62165. if (p != NULL)
  62166. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  62167. #endif
  62168. return err;
  62169. }
  62170. /* Map a projective EC point to affine in place.
  62171. * pZ will be one.
  62172. *
  62173. * pX EC point's X ordinate.
  62174. * pY EC point's Y ordinate.
  62175. * pZ EC point's Z ordinate.
  62176. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  62177. */
  62178. int sp_ecc_map_521(mp_int* pX, mp_int* pY, mp_int* pZ)
  62179. {
  62180. #ifdef WOLFSSL_SP_SMALL_STACK
  62181. sp_digit* tmp = NULL;
  62182. sp_point_521* p = NULL;
  62183. #else
  62184. sp_digit tmp[2 * 17 * 5];
  62185. sp_point_521 p[1];
  62186. #endif
  62187. int err = MP_OKAY;
  62188. #ifdef WOLFSSL_SP_SMALL_STACK
  62189. if (err == MP_OKAY) {
  62190. p = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
  62191. DYNAMIC_TYPE_ECC);
  62192. if (p == NULL)
  62193. err = MEMORY_E;
  62194. }
  62195. if (err == MP_OKAY) {
  62196. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17 * 5, NULL,
  62197. DYNAMIC_TYPE_ECC);
  62198. if (tmp == NULL)
  62199. err = MEMORY_E;
  62200. }
  62201. #endif
  62202. if (err == MP_OKAY) {
  62203. sp_521_from_mp(p->x, 17, pX);
  62204. sp_521_from_mp(p->y, 17, pY);
  62205. sp_521_from_mp(p->z, 17, pZ);
  62206. p->infinity = sp_521_iszero_17(p->x) &
  62207. sp_521_iszero_17(p->y);
  62208. sp_521_map_17(p, p, tmp);
  62209. }
  62210. if (err == MP_OKAY) {
  62211. err = sp_521_to_mp(p->x, pX);
  62212. }
  62213. if (err == MP_OKAY) {
  62214. err = sp_521_to_mp(p->y, pY);
  62215. }
  62216. if (err == MP_OKAY) {
  62217. err = sp_521_to_mp(p->z, pZ);
  62218. }
  62219. #ifdef WOLFSSL_SP_SMALL_STACK
  62220. if (tmp != NULL)
  62221. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  62222. if (p != NULL)
  62223. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  62224. #endif
  62225. return err;
  62226. }
  62227. #endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
  62228. #ifdef HAVE_COMP_KEY
  62229. /* Square root power for the P521 curve. */
  62230. static const uint32_t p521_sqrt_power[17] = {
  62231. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  62232. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  62233. 0x00000000,0x00000000,0x00000080
  62234. };
  62235. /* Find the square root of a number mod the prime of the curve.
  62236. *
  62237. * y The number to operate on and the result.
  62238. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  62239. */
  62240. static int sp_521_mont_sqrt_17(sp_digit* y)
  62241. {
  62242. #ifdef WOLFSSL_SP_SMALL_STACK
  62243. sp_digit* t = NULL;
  62244. #else
  62245. sp_digit t[2 * 17];
  62246. #endif
  62247. int err = MP_OKAY;
  62248. #ifdef WOLFSSL_SP_SMALL_STACK
  62249. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 17, NULL, DYNAMIC_TYPE_ECC);
  62250. if (t == NULL)
  62251. err = MEMORY_E;
  62252. #endif
  62253. if (err == MP_OKAY) {
  62254. {
  62255. int i;
  62256. XMEMCPY(t, y, sizeof(sp_digit) * 17);
  62257. for (i=518; i>=0; i--) {
  62258. sp_521_mont_sqr_17(t, t, p521_mod, p521_mp_mod);
  62259. if (p521_sqrt_power[i / 32] & ((sp_digit)1 << (i % 32)))
  62260. sp_521_mont_mul_17(t, t, y, p521_mod, p521_mp_mod);
  62261. }
  62262. XMEMCPY(y, t, sizeof(sp_digit) * 17);
  62263. }
  62264. }
  62265. #ifdef WOLFSSL_SP_SMALL_STACK
  62266. if (t != NULL)
  62267. XFREE(t, NULL, DYNAMIC_TYPE_ECC);
  62268. #endif
  62269. return err;
  62270. }
  62271. /* Uncompress the point given the X ordinate.
  62272. *
  62273. * xm X ordinate.
  62274. * odd Whether the Y ordinate is odd.
  62275. * ym Calculated Y ordinate.
  62276. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  62277. */
  62278. int sp_ecc_uncompress_521(mp_int* xm, int odd, mp_int* ym)
  62279. {
  62280. #ifdef WOLFSSL_SP_SMALL_STACK
  62281. sp_digit* x = NULL;
  62282. #else
  62283. sp_digit x[4 * 17];
  62284. #endif
  62285. sp_digit* y = NULL;
  62286. int err = MP_OKAY;
  62287. #ifdef WOLFSSL_SP_SMALL_STACK
  62288. x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 17, NULL, DYNAMIC_TYPE_ECC);
  62289. if (x == NULL)
  62290. err = MEMORY_E;
  62291. #endif
  62292. if (err == MP_OKAY) {
  62293. y = x + 2 * 17;
  62294. sp_521_from_mp(x, 17, xm);
  62295. err = sp_521_mod_mul_norm_17(x, x, p521_mod);
  62296. }
  62297. if (err == MP_OKAY) {
  62298. /* y = x^3 */
  62299. {
  62300. sp_521_mont_sqr_17(y, x, p521_mod, p521_mp_mod);
  62301. sp_521_mont_mul_17(y, y, x, p521_mod, p521_mp_mod);
  62302. }
  62303. /* y = x^3 - 3x */
  62304. sp_521_mont_sub_17(y, y, x, p521_mod);
  62305. sp_521_mont_sub_17(y, y, x, p521_mod);
  62306. sp_521_mont_sub_17(y, y, x, p521_mod);
  62307. /* y = x^3 - 3x + b */
  62308. err = sp_521_mod_mul_norm_17(x, p521_b, p521_mod);
  62309. }
  62310. if (err == MP_OKAY) {
  62311. sp_521_mont_add_17(y, y, x, p521_mod);
  62312. /* y = sqrt(x^3 - 3x + b) */
  62313. err = sp_521_mont_sqrt_17(y);
  62314. }
  62315. if (err == MP_OKAY) {
  62316. XMEMSET(y + 17, 0, 17U * sizeof(sp_digit));
  62317. sp_521_mont_reduce_17(y, p521_mod, p521_mp_mod);
  62318. if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
  62319. sp_521_mont_sub_17(y, p521_mod, y, p521_mod);
  62320. }
  62321. err = sp_521_to_mp(y, ym);
  62322. }
  62323. #ifdef WOLFSSL_SP_SMALL_STACK
  62324. if (x != NULL)
  62325. XFREE(x, NULL, DYNAMIC_TYPE_ECC);
  62326. #endif
  62327. return err;
  62328. }
  62329. #endif
  62330. #endif /* WOLFSSL_SP_521 */
  62331. #ifdef WOLFCRYPT_HAVE_SAKKE
  62332. #ifdef WOLFSSL_SP_1024
  62333. /* Point structure to use. */
  62334. typedef struct sp_point_1024 {
  62335. /* X ordinate of point. */
  62336. sp_digit x[2 * 32];
  62337. /* Y ordinate of point. */
  62338. sp_digit y[2 * 32];
  62339. /* Z ordinate of point. */
  62340. sp_digit z[2 * 32];
  62341. /* Indicates point is at infinity. */
  62342. int infinity;
  62343. } sp_point_1024;
  62344. #ifndef WOLFSSL_SP_SMALL
  62345. /* Multiply a and b into r. (r = a * b)
  62346. *
  62347. * r A single precision integer.
  62348. * a A single precision integer.
  62349. * b A single precision integer.
  62350. */
  62351. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  62352. static void sp_1024_mul_16(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  62353. #else
  62354. static void sp_1024_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b)
  62355. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  62356. {
  62357. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  62358. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  62359. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  62360. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  62361. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  62362. __asm__ __volatile__ (
  62363. "SUB sp, sp, #0x40\n\t"
  62364. /* A[0] * B[0] */
  62365. "LDR r11, [%[a]]\n\t"
  62366. "LDR r12, [%[b]]\n\t"
  62367. "UMULL r3, r4, r11, r12\n\t"
  62368. "MOV r5, #0x0\n\t"
  62369. "STR r3, [sp]\n\t"
  62370. /* A[0] * B[1] */
  62371. "LDR r9, [%[b], #4]\n\t"
  62372. "UMULL r6, r7, r11, r9\n\t"
  62373. "ADDS r4, r4, r6\n\t"
  62374. "ADCS r5, r5, r7\n\t"
  62375. "MOV r3, #0x0\n\t"
  62376. "ADC r3, r3, #0x0\n\t"
  62377. /* A[1] * B[0] */
  62378. "LDR r8, [%[a], #4]\n\t"
  62379. "UMULL r6, r7, r8, r12\n\t"
  62380. "ADDS r4, r4, r6\n\t"
  62381. "ADCS r5, r5, r7\n\t"
  62382. "ADC r3, r3, #0x0\n\t"
  62383. "STR r4, [sp, #4]\n\t"
  62384. /* A[2] * B[0] */
  62385. "LDR r8, [%[a], #8]\n\t"
  62386. "UMULL r6, r7, r8, r12\n\t"
  62387. "ADDS r5, r5, r6\n\t"
  62388. "ADCS r3, r3, r7\n\t"
  62389. "MOV r4, #0x0\n\t"
  62390. "ADC r4, r4, #0x0\n\t"
  62391. /* A[1] * B[1] */
  62392. "LDR r11, [%[a], #4]\n\t"
  62393. "LDR r12, [%[b], #4]\n\t"
  62394. "UMULL r6, r7, r11, r12\n\t"
  62395. "ADDS r5, r5, r6\n\t"
  62396. "ADCS r3, r3, r7\n\t"
  62397. "ADC r4, r4, #0x0\n\t"
  62398. /* A[0] * B[2] */
  62399. "LDR r8, [%[a]]\n\t"
  62400. "LDR r9, [%[b], #8]\n\t"
  62401. "UMULL r6, r7, r8, r9\n\t"
  62402. "ADDS r5, r5, r6\n\t"
  62403. "ADCS r3, r3, r7\n\t"
  62404. "ADC r4, r4, #0x0\n\t"
  62405. "STR r5, [sp, #8]\n\t"
  62406. /* A[0] * B[3] */
  62407. "LDR r9, [%[b], #12]\n\t"
  62408. "UMULL r6, r7, r8, r9\n\t"
  62409. "ADDS r3, r3, r6\n\t"
  62410. "ADCS r4, r4, r7\n\t"
  62411. "MOV r5, #0x0\n\t"
  62412. "ADC r5, r5, #0x0\n\t"
  62413. /* A[1] * B[2] */
  62414. "LDR r9, [%[b], #8]\n\t"
  62415. "UMULL r6, r7, r11, r9\n\t"
  62416. "ADDS r3, r3, r6\n\t"
  62417. "ADCS r4, r4, r7\n\t"
  62418. "ADC r5, r5, #0x0\n\t"
  62419. /* A[2] * B[1] */
  62420. "LDR r8, [%[a], #8]\n\t"
  62421. "UMULL r6, r7, r8, r12\n\t"
  62422. "ADDS r3, r3, r6\n\t"
  62423. "ADCS r4, r4, r7\n\t"
  62424. "ADC r5, r5, #0x0\n\t"
  62425. /* A[3] * B[0] */
  62426. "LDR r8, [%[a], #12]\n\t"
  62427. "LDR r9, [%[b]]\n\t"
  62428. "UMULL r6, r7, r8, r9\n\t"
  62429. "ADDS r3, r3, r6\n\t"
  62430. "ADCS r4, r4, r7\n\t"
  62431. "ADC r5, r5, #0x0\n\t"
  62432. "STR r3, [sp, #12]\n\t"
  62433. /* A[4] * B[0] */
  62434. "LDR r8, [%[a], #16]\n\t"
  62435. "UMULL r6, r7, r8, r9\n\t"
  62436. "ADDS r4, r4, r6\n\t"
  62437. "ADCS r5, r5, r7\n\t"
  62438. "MOV r3, #0x0\n\t"
  62439. "ADC r3, r3, #0x0\n\t"
  62440. /* A[3] * B[1] */
  62441. "LDR r8, [%[a], #12]\n\t"
  62442. "UMULL r6, r7, r8, r12\n\t"
  62443. "ADDS r4, r4, r6\n\t"
  62444. "ADCS r5, r5, r7\n\t"
  62445. "ADC r3, r3, #0x0\n\t"
  62446. /* A[2] * B[2] */
  62447. "LDR r11, [%[a], #8]\n\t"
  62448. "LDR r12, [%[b], #8]\n\t"
  62449. "UMULL r6, r7, r11, r12\n\t"
  62450. "ADDS r4, r4, r6\n\t"
  62451. "ADCS r5, r5, r7\n\t"
  62452. "ADC r3, r3, #0x0\n\t"
  62453. /* A[1] * B[3] */
  62454. "LDR r8, [%[a], #4]\n\t"
  62455. "LDR r9, [%[b], #12]\n\t"
  62456. "UMULL r6, r7, r8, r9\n\t"
  62457. "ADDS r4, r4, r6\n\t"
  62458. "ADCS r5, r5, r7\n\t"
  62459. "ADC r3, r3, #0x0\n\t"
  62460. /* A[0] * B[4] */
  62461. "LDR r8, [%[a]]\n\t"
  62462. "LDR r9, [%[b], #16]\n\t"
  62463. "UMULL r6, r7, r8, r9\n\t"
  62464. "ADDS r4, r4, r6\n\t"
  62465. "ADCS r5, r5, r7\n\t"
  62466. "ADC r3, r3, #0x0\n\t"
  62467. "STR r4, [sp, #16]\n\t"
  62468. /* A[0] * B[5] */
  62469. "LDR r9, [%[b], #20]\n\t"
  62470. "UMULL r6, r7, r8, r9\n\t"
  62471. "ADDS r5, r5, r6\n\t"
  62472. "ADCS r3, r3, r7\n\t"
  62473. "MOV r4, #0x0\n\t"
  62474. "ADC r4, r4, #0x0\n\t"
  62475. /* A[1] * B[4] */
  62476. "LDR r8, [%[a], #4]\n\t"
  62477. "LDR r9, [%[b], #16]\n\t"
  62478. "UMULL r6, r7, r8, r9\n\t"
  62479. "ADDS r5, r5, r6\n\t"
  62480. "ADCS r3, r3, r7\n\t"
  62481. "ADC r4, r4, #0x0\n\t"
  62482. /* A[2] * B[3] */
  62483. "LDR r9, [%[b], #12]\n\t"
  62484. "UMULL r6, r7, r11, r9\n\t"
  62485. "ADDS r5, r5, r6\n\t"
  62486. "ADCS r3, r3, r7\n\t"
  62487. "ADC r4, r4, #0x0\n\t"
  62488. /* A[3] * B[2] */
  62489. "LDR r8, [%[a], #12]\n\t"
  62490. "UMULL r6, r7, r8, r12\n\t"
  62491. "ADDS r5, r5, r6\n\t"
  62492. "ADCS r3, r3, r7\n\t"
  62493. "ADC r4, r4, #0x0\n\t"
  62494. /* A[4] * B[1] */
  62495. "LDR r8, [%[a], #16]\n\t"
  62496. "LDR r9, [%[b], #4]\n\t"
  62497. "UMULL r6, r7, r8, r9\n\t"
  62498. "ADDS r5, r5, r6\n\t"
  62499. "ADCS r3, r3, r7\n\t"
  62500. "ADC r4, r4, #0x0\n\t"
  62501. /* A[5] * B[0] */
  62502. "LDR r8, [%[a], #20]\n\t"
  62503. "LDR r9, [%[b]]\n\t"
  62504. "UMULL r6, r7, r8, r9\n\t"
  62505. "ADDS r5, r5, r6\n\t"
  62506. "ADCS r3, r3, r7\n\t"
  62507. "ADC r4, r4, #0x0\n\t"
  62508. "STR r5, [sp, #20]\n\t"
  62509. /* A[6] * B[0] */
  62510. "LDR r8, [%[a], #24]\n\t"
  62511. "UMULL r6, r7, r8, r9\n\t"
  62512. "ADDS r3, r3, r6\n\t"
  62513. "ADCS r4, r4, r7\n\t"
  62514. "MOV r5, #0x0\n\t"
  62515. "ADC r5, r5, #0x0\n\t"
  62516. /* A[5] * B[1] */
  62517. "LDR r8, [%[a], #20]\n\t"
  62518. "LDR r9, [%[b], #4]\n\t"
  62519. "UMULL r6, r7, r8, r9\n\t"
  62520. "ADDS r3, r3, r6\n\t"
  62521. "ADCS r4, r4, r7\n\t"
  62522. "ADC r5, r5, #0x0\n\t"
  62523. /* A[4] * B[2] */
  62524. "LDR r8, [%[a], #16]\n\t"
  62525. "UMULL r6, r7, r8, r12\n\t"
  62526. "ADDS r3, r3, r6\n\t"
  62527. "ADCS r4, r4, r7\n\t"
  62528. "ADC r5, r5, #0x0\n\t"
  62529. /* A[3] * B[3] */
  62530. "LDR r11, [%[a], #12]\n\t"
  62531. "LDR r12, [%[b], #12]\n\t"
  62532. "UMULL r6, r7, r11, r12\n\t"
  62533. "ADDS r3, r3, r6\n\t"
  62534. "ADCS r4, r4, r7\n\t"
  62535. "ADC r5, r5, #0x0\n\t"
  62536. /* A[2] * B[4] */
  62537. "LDR r8, [%[a], #8]\n\t"
  62538. "LDR r9, [%[b], #16]\n\t"
  62539. "UMULL r6, r7, r8, r9\n\t"
  62540. "ADDS r3, r3, r6\n\t"
  62541. "ADCS r4, r4, r7\n\t"
  62542. "ADC r5, r5, #0x0\n\t"
  62543. /* A[1] * B[5] */
  62544. "LDR r8, [%[a], #4]\n\t"
  62545. "LDR r9, [%[b], #20]\n\t"
  62546. "UMULL r6, r7, r8, r9\n\t"
  62547. "ADDS r3, r3, r6\n\t"
  62548. "ADCS r4, r4, r7\n\t"
  62549. "ADC r5, r5, #0x0\n\t"
  62550. /* A[0] * B[6] */
  62551. "LDR r8, [%[a]]\n\t"
  62552. "LDR r9, [%[b], #24]\n\t"
  62553. "UMULL r6, r7, r8, r9\n\t"
  62554. "ADDS r3, r3, r6\n\t"
  62555. "ADCS r4, r4, r7\n\t"
  62556. "ADC r5, r5, #0x0\n\t"
  62557. "STR r3, [sp, #24]\n\t"
  62558. /* A[0] * B[7] */
  62559. "LDR r9, [%[b], #28]\n\t"
  62560. "UMULL r6, r7, r8, r9\n\t"
  62561. "ADDS r4, r4, r6\n\t"
  62562. "ADCS r5, r5, r7\n\t"
  62563. "MOV r3, #0x0\n\t"
  62564. "ADC r3, r3, #0x0\n\t"
  62565. /* A[1] * B[6] */
  62566. "LDR r8, [%[a], #4]\n\t"
  62567. "LDR r9, [%[b], #24]\n\t"
  62568. "UMULL r6, r7, r8, r9\n\t"
  62569. "ADDS r4, r4, r6\n\t"
  62570. "ADCS r5, r5, r7\n\t"
  62571. "ADC r3, r3, #0x0\n\t"
  62572. /* A[2] * B[5] */
  62573. "LDR r8, [%[a], #8]\n\t"
  62574. "LDR r9, [%[b], #20]\n\t"
  62575. "UMULL r6, r7, r8, r9\n\t"
  62576. "ADDS r4, r4, r6\n\t"
  62577. "ADCS r5, r5, r7\n\t"
  62578. "ADC r3, r3, #0x0\n\t"
  62579. /* A[3] * B[4] */
  62580. "LDR r9, [%[b], #16]\n\t"
  62581. "UMULL r6, r7, r11, r9\n\t"
  62582. "ADDS r4, r4, r6\n\t"
  62583. "ADCS r5, r5, r7\n\t"
  62584. "ADC r3, r3, #0x0\n\t"
  62585. /* A[4] * B[3] */
  62586. "LDR r8, [%[a], #16]\n\t"
  62587. "UMULL r6, r7, r8, r12\n\t"
  62588. "ADDS r4, r4, r6\n\t"
  62589. "ADCS r5, r5, r7\n\t"
  62590. "ADC r3, r3, #0x0\n\t"
  62591. /* A[5] * B[2] */
  62592. "LDR r8, [%[a], #20]\n\t"
  62593. "LDR r9, [%[b], #8]\n\t"
  62594. "UMULL r6, r7, r8, r9\n\t"
  62595. "ADDS r4, r4, r6\n\t"
  62596. "ADCS r5, r5, r7\n\t"
  62597. "ADC r3, r3, #0x0\n\t"
  62598. /* A[6] * B[1] */
  62599. "LDR r8, [%[a], #24]\n\t"
  62600. "LDR r9, [%[b], #4]\n\t"
  62601. "UMULL r6, r7, r8, r9\n\t"
  62602. "ADDS r4, r4, r6\n\t"
  62603. "ADCS r5, r5, r7\n\t"
  62604. "ADC r3, r3, #0x0\n\t"
  62605. /* A[7] * B[0] */
  62606. "LDR r8, [%[a], #28]\n\t"
  62607. "LDR r9, [%[b]]\n\t"
  62608. "UMULL r6, r7, r8, r9\n\t"
  62609. "ADDS r4, r4, r6\n\t"
  62610. "ADCS r5, r5, r7\n\t"
  62611. "ADC r3, r3, #0x0\n\t"
  62612. "STR r4, [sp, #28]\n\t"
  62613. /* A[8] * B[0] */
  62614. "LDR r8, [%[a], #32]\n\t"
  62615. "UMULL r6, r7, r8, r9\n\t"
  62616. "ADDS r5, r5, r6\n\t"
  62617. "ADCS r3, r3, r7\n\t"
  62618. "MOV r4, #0x0\n\t"
  62619. "ADC r4, r4, #0x0\n\t"
  62620. /* A[7] * B[1] */
  62621. "LDR r8, [%[a], #28]\n\t"
  62622. "LDR r9, [%[b], #4]\n\t"
  62623. "UMULL r6, r7, r8, r9\n\t"
  62624. "ADDS r5, r5, r6\n\t"
  62625. "ADCS r3, r3, r7\n\t"
  62626. "ADC r4, r4, #0x0\n\t"
  62627. /* A[6] * B[2] */
  62628. "LDR r8, [%[a], #24]\n\t"
  62629. "LDR r9, [%[b], #8]\n\t"
  62630. "UMULL r6, r7, r8, r9\n\t"
  62631. "ADDS r5, r5, r6\n\t"
  62632. "ADCS r3, r3, r7\n\t"
  62633. "ADC r4, r4, #0x0\n\t"
  62634. /* A[5] * B[3] */
  62635. "LDR r8, [%[a], #20]\n\t"
  62636. "UMULL r6, r7, r8, r12\n\t"
  62637. "ADDS r5, r5, r6\n\t"
  62638. "ADCS r3, r3, r7\n\t"
  62639. "ADC r4, r4, #0x0\n\t"
  62640. /* A[4] * B[4] */
  62641. "LDR r11, [%[a], #16]\n\t"
  62642. "LDR r12, [%[b], #16]\n\t"
  62643. "UMULL r6, r7, r11, r12\n\t"
  62644. "ADDS r5, r5, r6\n\t"
  62645. "ADCS r3, r3, r7\n\t"
  62646. "ADC r4, r4, #0x0\n\t"
  62647. /* A[3] * B[5] */
  62648. "LDR r8, [%[a], #12]\n\t"
  62649. "LDR r9, [%[b], #20]\n\t"
  62650. "UMULL r6, r7, r8, r9\n\t"
  62651. "ADDS r5, r5, r6\n\t"
  62652. "ADCS r3, r3, r7\n\t"
  62653. "ADC r4, r4, #0x0\n\t"
  62654. /* A[2] * B[6] */
  62655. "LDR r8, [%[a], #8]\n\t"
  62656. "LDR r9, [%[b], #24]\n\t"
  62657. "UMULL r6, r7, r8, r9\n\t"
  62658. "ADDS r5, r5, r6\n\t"
  62659. "ADCS r3, r3, r7\n\t"
  62660. "ADC r4, r4, #0x0\n\t"
  62661. /* A[1] * B[7] */
  62662. "LDR r8, [%[a], #4]\n\t"
  62663. "LDR r9, [%[b], #28]\n\t"
  62664. "UMULL r6, r7, r8, r9\n\t"
  62665. "ADDS r5, r5, r6\n\t"
  62666. "ADCS r3, r3, r7\n\t"
  62667. "ADC r4, r4, #0x0\n\t"
  62668. /* A[0] * B[8] */
  62669. "LDR r8, [%[a]]\n\t"
  62670. "LDR r9, [%[b], #32]\n\t"
  62671. "UMULL r6, r7, r8, r9\n\t"
  62672. "ADDS r5, r5, r6\n\t"
  62673. "ADCS r3, r3, r7\n\t"
  62674. "ADC r4, r4, #0x0\n\t"
  62675. "STR r5, [sp, #32]\n\t"
  62676. /* A[0] * B[9] */
  62677. "LDR r9, [%[b], #36]\n\t"
  62678. "UMULL r6, r7, r8, r9\n\t"
  62679. "ADDS r3, r3, r6\n\t"
  62680. "ADCS r4, r4, r7\n\t"
  62681. "MOV r5, #0x0\n\t"
  62682. "ADC r5, r5, #0x0\n\t"
  62683. /* A[1] * B[8] */
  62684. "LDR r8, [%[a], #4]\n\t"
  62685. "LDR r9, [%[b], #32]\n\t"
  62686. "UMULL r6, r7, r8, r9\n\t"
  62687. "ADDS r3, r3, r6\n\t"
  62688. "ADCS r4, r4, r7\n\t"
  62689. "ADC r5, r5, #0x0\n\t"
  62690. /* A[2] * B[7] */
  62691. "LDR r8, [%[a], #8]\n\t"
  62692. "LDR r9, [%[b], #28]\n\t"
  62693. "UMULL r6, r7, r8, r9\n\t"
  62694. "ADDS r3, r3, r6\n\t"
  62695. "ADCS r4, r4, r7\n\t"
  62696. "ADC r5, r5, #0x0\n\t"
  62697. /* A[3] * B[6] */
  62698. "LDR r8, [%[a], #12]\n\t"
  62699. "LDR r9, [%[b], #24]\n\t"
  62700. "UMULL r6, r7, r8, r9\n\t"
  62701. "ADDS r3, r3, r6\n\t"
  62702. "ADCS r4, r4, r7\n\t"
  62703. "ADC r5, r5, #0x0\n\t"
  62704. /* A[4] * B[5] */
  62705. "LDR r9, [%[b], #20]\n\t"
  62706. "UMULL r6, r7, r11, r9\n\t"
  62707. "ADDS r3, r3, r6\n\t"
  62708. "ADCS r4, r4, r7\n\t"
  62709. "ADC r5, r5, #0x0\n\t"
  62710. /* A[5] * B[4] */
  62711. "LDR r8, [%[a], #20]\n\t"
  62712. "UMULL r6, r7, r8, r12\n\t"
  62713. "ADDS r3, r3, r6\n\t"
  62714. "ADCS r4, r4, r7\n\t"
  62715. "ADC r5, r5, #0x0\n\t"
  62716. /* A[6] * B[3] */
  62717. "LDR r8, [%[a], #24]\n\t"
  62718. "LDR r9, [%[b], #12]\n\t"
  62719. "UMULL r6, r7, r8, r9\n\t"
  62720. "ADDS r3, r3, r6\n\t"
  62721. "ADCS r4, r4, r7\n\t"
  62722. "ADC r5, r5, #0x0\n\t"
  62723. /* A[7] * B[2] */
  62724. "LDR r8, [%[a], #28]\n\t"
  62725. "LDR r9, [%[b], #8]\n\t"
  62726. "UMULL r6, r7, r8, r9\n\t"
  62727. "ADDS r3, r3, r6\n\t"
  62728. "ADCS r4, r4, r7\n\t"
  62729. "ADC r5, r5, #0x0\n\t"
  62730. /* A[8] * B[1] */
  62731. "LDR r8, [%[a], #32]\n\t"
  62732. "LDR r9, [%[b], #4]\n\t"
  62733. "UMULL r6, r7, r8, r9\n\t"
  62734. "ADDS r3, r3, r6\n\t"
  62735. "ADCS r4, r4, r7\n\t"
  62736. "ADC r5, r5, #0x0\n\t"
  62737. /* A[9] * B[0] */
  62738. "LDR r8, [%[a], #36]\n\t"
  62739. "LDR r9, [%[b]]\n\t"
  62740. "UMULL r6, r7, r8, r9\n\t"
  62741. "ADDS r3, r3, r6\n\t"
  62742. "ADCS r4, r4, r7\n\t"
  62743. "ADC r5, r5, #0x0\n\t"
  62744. "STR r3, [sp, #36]\n\t"
  62745. /* A[10] * B[0] */
  62746. "LDR r8, [%[a], #40]\n\t"
  62747. "UMULL r6, r7, r8, r9\n\t"
  62748. "ADDS r4, r4, r6\n\t"
  62749. "ADCS r5, r5, r7\n\t"
  62750. "MOV r3, #0x0\n\t"
  62751. "ADC r3, r3, #0x0\n\t"
  62752. /* A[9] * B[1] */
  62753. "LDR r8, [%[a], #36]\n\t"
  62754. "LDR r9, [%[b], #4]\n\t"
  62755. "UMULL r6, r7, r8, r9\n\t"
  62756. "ADDS r4, r4, r6\n\t"
  62757. "ADCS r5, r5, r7\n\t"
  62758. "ADC r3, r3, #0x0\n\t"
  62759. /* A[8] * B[2] */
  62760. "LDR r8, [%[a], #32]\n\t"
  62761. "LDR r9, [%[b], #8]\n\t"
  62762. "UMULL r6, r7, r8, r9\n\t"
  62763. "ADDS r4, r4, r6\n\t"
  62764. "ADCS r5, r5, r7\n\t"
  62765. "ADC r3, r3, #0x0\n\t"
  62766. /* A[7] * B[3] */
  62767. "LDR r8, [%[a], #28]\n\t"
  62768. "LDR r9, [%[b], #12]\n\t"
  62769. "UMULL r6, r7, r8, r9\n\t"
  62770. "ADDS r4, r4, r6\n\t"
  62771. "ADCS r5, r5, r7\n\t"
  62772. "ADC r3, r3, #0x0\n\t"
  62773. /* A[6] * B[4] */
  62774. "LDR r8, [%[a], #24]\n\t"
  62775. "UMULL r6, r7, r8, r12\n\t"
  62776. "ADDS r4, r4, r6\n\t"
  62777. "ADCS r5, r5, r7\n\t"
  62778. "ADC r3, r3, #0x0\n\t"
  62779. /* A[5] * B[5] */
  62780. "LDR r11, [%[a], #20]\n\t"
  62781. "LDR r12, [%[b], #20]\n\t"
  62782. "UMULL r6, r7, r11, r12\n\t"
  62783. "ADDS r4, r4, r6\n\t"
  62784. "ADCS r5, r5, r7\n\t"
  62785. "ADC r3, r3, #0x0\n\t"
  62786. /* A[4] * B[6] */
  62787. "LDR r8, [%[a], #16]\n\t"
  62788. "LDR r9, [%[b], #24]\n\t"
  62789. "UMULL r6, r7, r8, r9\n\t"
  62790. "ADDS r4, r4, r6\n\t"
  62791. "ADCS r5, r5, r7\n\t"
  62792. "ADC r3, r3, #0x0\n\t"
  62793. /* A[3] * B[7] */
  62794. "LDR r8, [%[a], #12]\n\t"
  62795. "LDR r9, [%[b], #28]\n\t"
  62796. "UMULL r6, r7, r8, r9\n\t"
  62797. "ADDS r4, r4, r6\n\t"
  62798. "ADCS r5, r5, r7\n\t"
  62799. "ADC r3, r3, #0x0\n\t"
  62800. /* A[2] * B[8] */
  62801. "LDR r8, [%[a], #8]\n\t"
  62802. "LDR r9, [%[b], #32]\n\t"
  62803. "UMULL r6, r7, r8, r9\n\t"
  62804. "ADDS r4, r4, r6\n\t"
  62805. "ADCS r5, r5, r7\n\t"
  62806. "ADC r3, r3, #0x0\n\t"
  62807. /* A[1] * B[9] */
  62808. "LDR r8, [%[a], #4]\n\t"
  62809. "LDR r9, [%[b], #36]\n\t"
  62810. "UMULL r6, r7, r8, r9\n\t"
  62811. "ADDS r4, r4, r6\n\t"
  62812. "ADCS r5, r5, r7\n\t"
  62813. "ADC r3, r3, #0x0\n\t"
  62814. /* A[0] * B[10] */
  62815. "LDR r8, [%[a]]\n\t"
  62816. "LDR r9, [%[b], #40]\n\t"
  62817. "UMULL r6, r7, r8, r9\n\t"
  62818. "ADDS r4, r4, r6\n\t"
  62819. "ADCS r5, r5, r7\n\t"
  62820. "ADC r3, r3, #0x0\n\t"
  62821. "STR r4, [sp, #40]\n\t"
  62822. /* A[0] * B[11] */
  62823. "LDR r9, [%[b], #44]\n\t"
  62824. "UMULL r6, r7, r8, r9\n\t"
  62825. "ADDS r5, r5, r6\n\t"
  62826. "ADCS r3, r3, r7\n\t"
  62827. "MOV r4, #0x0\n\t"
  62828. "ADC r4, r4, #0x0\n\t"
  62829. /* A[1] * B[10] */
  62830. "LDR r8, [%[a], #4]\n\t"
  62831. "LDR r9, [%[b], #40]\n\t"
  62832. "UMULL r6, r7, r8, r9\n\t"
  62833. "ADDS r5, r5, r6\n\t"
  62834. "ADCS r3, r3, r7\n\t"
  62835. "ADC r4, r4, #0x0\n\t"
  62836. /* A[2] * B[9] */
  62837. "LDR r8, [%[a], #8]\n\t"
  62838. "LDR r9, [%[b], #36]\n\t"
  62839. "UMULL r6, r7, r8, r9\n\t"
  62840. "ADDS r5, r5, r6\n\t"
  62841. "ADCS r3, r3, r7\n\t"
  62842. "ADC r4, r4, #0x0\n\t"
  62843. /* A[3] * B[8] */
  62844. "LDR r8, [%[a], #12]\n\t"
  62845. "LDR r9, [%[b], #32]\n\t"
  62846. "UMULL r6, r7, r8, r9\n\t"
  62847. "ADDS r5, r5, r6\n\t"
  62848. "ADCS r3, r3, r7\n\t"
  62849. "ADC r4, r4, #0x0\n\t"
  62850. /* A[4] * B[7] */
  62851. "LDR r8, [%[a], #16]\n\t"
  62852. "LDR r9, [%[b], #28]\n\t"
  62853. "UMULL r6, r7, r8, r9\n\t"
  62854. "ADDS r5, r5, r6\n\t"
  62855. "ADCS r3, r3, r7\n\t"
  62856. "ADC r4, r4, #0x0\n\t"
  62857. /* A[5] * B[6] */
  62858. "LDR r9, [%[b], #24]\n\t"
  62859. "UMULL r6, r7, r11, r9\n\t"
  62860. "ADDS r5, r5, r6\n\t"
  62861. "ADCS r3, r3, r7\n\t"
  62862. "ADC r4, r4, #0x0\n\t"
  62863. /* A[6] * B[5] */
  62864. "LDR r8, [%[a], #24]\n\t"
  62865. "UMULL r6, r7, r8, r12\n\t"
  62866. "ADDS r5, r5, r6\n\t"
  62867. "ADCS r3, r3, r7\n\t"
  62868. "ADC r4, r4, #0x0\n\t"
  62869. /* A[7] * B[4] */
  62870. "LDR r8, [%[a], #28]\n\t"
  62871. "LDR r9, [%[b], #16]\n\t"
  62872. "UMULL r6, r7, r8, r9\n\t"
  62873. "ADDS r5, r5, r6\n\t"
  62874. "ADCS r3, r3, r7\n\t"
  62875. "ADC r4, r4, #0x0\n\t"
  62876. /* A[8] * B[3] */
  62877. "LDR r8, [%[a], #32]\n\t"
  62878. "LDR r9, [%[b], #12]\n\t"
  62879. "UMULL r6, r7, r8, r9\n\t"
  62880. "ADDS r5, r5, r6\n\t"
  62881. "ADCS r3, r3, r7\n\t"
  62882. "ADC r4, r4, #0x0\n\t"
  62883. /* A[9] * B[2] */
  62884. "LDR r8, [%[a], #36]\n\t"
  62885. "LDR r9, [%[b], #8]\n\t"
  62886. "UMULL r6, r7, r8, r9\n\t"
  62887. "ADDS r5, r5, r6\n\t"
  62888. "ADCS r3, r3, r7\n\t"
  62889. "ADC r4, r4, #0x0\n\t"
  62890. /* A[10] * B[1] */
  62891. "LDR r8, [%[a], #40]\n\t"
  62892. "LDR r9, [%[b], #4]\n\t"
  62893. "UMULL r6, r7, r8, r9\n\t"
  62894. "ADDS r5, r5, r6\n\t"
  62895. "ADCS r3, r3, r7\n\t"
  62896. "ADC r4, r4, #0x0\n\t"
  62897. /* A[11] * B[0] */
  62898. "LDR r8, [%[a], #44]\n\t"
  62899. "LDR r9, [%[b]]\n\t"
  62900. "UMULL r6, r7, r8, r9\n\t"
  62901. "ADDS r5, r5, r6\n\t"
  62902. "ADCS r3, r3, r7\n\t"
  62903. "ADC r4, r4, #0x0\n\t"
  62904. "STR r5, [sp, #44]\n\t"
  62905. /* A[12] * B[0] */
  62906. "LDR r8, [%[a], #48]\n\t"
  62907. "UMULL r6, r7, r8, r9\n\t"
  62908. "ADDS r3, r3, r6\n\t"
  62909. "ADCS r4, r4, r7\n\t"
  62910. "MOV r5, #0x0\n\t"
  62911. "ADC r5, r5, #0x0\n\t"
  62912. /* A[11] * B[1] */
  62913. "LDR r8, [%[a], #44]\n\t"
  62914. "LDR r9, [%[b], #4]\n\t"
  62915. "UMULL r6, r7, r8, r9\n\t"
  62916. "ADDS r3, r3, r6\n\t"
  62917. "ADCS r4, r4, r7\n\t"
  62918. "ADC r5, r5, #0x0\n\t"
  62919. /* A[10] * B[2] */
  62920. "LDR r8, [%[a], #40]\n\t"
  62921. "LDR r9, [%[b], #8]\n\t"
  62922. "UMULL r6, r7, r8, r9\n\t"
  62923. "ADDS r3, r3, r6\n\t"
  62924. "ADCS r4, r4, r7\n\t"
  62925. "ADC r5, r5, #0x0\n\t"
  62926. /* A[9] * B[3] */
  62927. "LDR r8, [%[a], #36]\n\t"
  62928. "LDR r9, [%[b], #12]\n\t"
  62929. "UMULL r6, r7, r8, r9\n\t"
  62930. "ADDS r3, r3, r6\n\t"
  62931. "ADCS r4, r4, r7\n\t"
  62932. "ADC r5, r5, #0x0\n\t"
  62933. /* A[8] * B[4] */
  62934. "LDR r8, [%[a], #32]\n\t"
  62935. "LDR r9, [%[b], #16]\n\t"
  62936. "UMULL r6, r7, r8, r9\n\t"
  62937. "ADDS r3, r3, r6\n\t"
  62938. "ADCS r4, r4, r7\n\t"
  62939. "ADC r5, r5, #0x0\n\t"
  62940. /* A[7] * B[5] */
  62941. "LDR r8, [%[a], #28]\n\t"
  62942. "UMULL r6, r7, r8, r12\n\t"
  62943. "ADDS r3, r3, r6\n\t"
  62944. "ADCS r4, r4, r7\n\t"
  62945. "ADC r5, r5, #0x0\n\t"
  62946. /* A[6] * B[6] */
  62947. "LDR r11, [%[a], #24]\n\t"
  62948. "LDR r12, [%[b], #24]\n\t"
  62949. "UMULL r6, r7, r11, r12\n\t"
  62950. "ADDS r3, r3, r6\n\t"
  62951. "ADCS r4, r4, r7\n\t"
  62952. "ADC r5, r5, #0x0\n\t"
  62953. /* A[5] * B[7] */
  62954. "LDR r8, [%[a], #20]\n\t"
  62955. "LDR r9, [%[b], #28]\n\t"
  62956. "UMULL r6, r7, r8, r9\n\t"
  62957. "ADDS r3, r3, r6\n\t"
  62958. "ADCS r4, r4, r7\n\t"
  62959. "ADC r5, r5, #0x0\n\t"
  62960. /* A[4] * B[8] */
  62961. "LDR r8, [%[a], #16]\n\t"
  62962. "LDR r9, [%[b], #32]\n\t"
  62963. "UMULL r6, r7, r8, r9\n\t"
  62964. "ADDS r3, r3, r6\n\t"
  62965. "ADCS r4, r4, r7\n\t"
  62966. "ADC r5, r5, #0x0\n\t"
  62967. /* A[3] * B[9] */
  62968. "LDR r8, [%[a], #12]\n\t"
  62969. "LDR r9, [%[b], #36]\n\t"
  62970. "UMULL r6, r7, r8, r9\n\t"
  62971. "ADDS r3, r3, r6\n\t"
  62972. "ADCS r4, r4, r7\n\t"
  62973. "ADC r5, r5, #0x0\n\t"
  62974. /* A[2] * B[10] */
  62975. "LDR r8, [%[a], #8]\n\t"
  62976. "LDR r9, [%[b], #40]\n\t"
  62977. "UMULL r6, r7, r8, r9\n\t"
  62978. "ADDS r3, r3, r6\n\t"
  62979. "ADCS r4, r4, r7\n\t"
  62980. "ADC r5, r5, #0x0\n\t"
  62981. /* A[1] * B[11] */
  62982. "LDR r8, [%[a], #4]\n\t"
  62983. "LDR r9, [%[b], #44]\n\t"
  62984. "UMULL r6, r7, r8, r9\n\t"
  62985. "ADDS r3, r3, r6\n\t"
  62986. "ADCS r4, r4, r7\n\t"
  62987. "ADC r5, r5, #0x0\n\t"
  62988. /* A[0] * B[12] */
  62989. "LDR r8, [%[a]]\n\t"
  62990. "LDR r9, [%[b], #48]\n\t"
  62991. "UMULL r6, r7, r8, r9\n\t"
  62992. "ADDS r3, r3, r6\n\t"
  62993. "ADCS r4, r4, r7\n\t"
  62994. "ADC r5, r5, #0x0\n\t"
  62995. "STR r3, [sp, #48]\n\t"
  62996. /* A[0] * B[13] */
  62997. "LDR r9, [%[b], #52]\n\t"
  62998. "UMULL r6, r7, r8, r9\n\t"
  62999. "ADDS r4, r4, r6\n\t"
  63000. "ADCS r5, r5, r7\n\t"
  63001. "MOV r3, #0x0\n\t"
  63002. "ADC r3, r3, #0x0\n\t"
  63003. /* A[1] * B[12] */
  63004. "LDR r8, [%[a], #4]\n\t"
  63005. "LDR r9, [%[b], #48]\n\t"
  63006. "UMULL r6, r7, r8, r9\n\t"
  63007. "ADDS r4, r4, r6\n\t"
  63008. "ADCS r5, r5, r7\n\t"
  63009. "ADC r3, r3, #0x0\n\t"
  63010. /* A[2] * B[11] */
  63011. "LDR r8, [%[a], #8]\n\t"
  63012. "LDR r9, [%[b], #44]\n\t"
  63013. "UMULL r6, r7, r8, r9\n\t"
  63014. "ADDS r4, r4, r6\n\t"
  63015. "ADCS r5, r5, r7\n\t"
  63016. "ADC r3, r3, #0x0\n\t"
  63017. /* A[3] * B[10] */
  63018. "LDR r8, [%[a], #12]\n\t"
  63019. "LDR r9, [%[b], #40]\n\t"
  63020. "UMULL r6, r7, r8, r9\n\t"
  63021. "ADDS r4, r4, r6\n\t"
  63022. "ADCS r5, r5, r7\n\t"
  63023. "ADC r3, r3, #0x0\n\t"
  63024. /* A[4] * B[9] */
  63025. "LDR r8, [%[a], #16]\n\t"
  63026. "LDR r9, [%[b], #36]\n\t"
  63027. "UMULL r6, r7, r8, r9\n\t"
  63028. "ADDS r4, r4, r6\n\t"
  63029. "ADCS r5, r5, r7\n\t"
  63030. "ADC r3, r3, #0x0\n\t"
  63031. /* A[5] * B[8] */
  63032. "LDR r8, [%[a], #20]\n\t"
  63033. "LDR r9, [%[b], #32]\n\t"
  63034. "UMULL r6, r7, r8, r9\n\t"
  63035. "ADDS r4, r4, r6\n\t"
  63036. "ADCS r5, r5, r7\n\t"
  63037. "ADC r3, r3, #0x0\n\t"
  63038. /* A[6] * B[7] */
  63039. "LDR r9, [%[b], #28]\n\t"
  63040. "UMULL r6, r7, r11, r9\n\t"
  63041. "ADDS r4, r4, r6\n\t"
  63042. "ADCS r5, r5, r7\n\t"
  63043. "ADC r3, r3, #0x0\n\t"
  63044. /* A[7] * B[6] */
  63045. "LDR r8, [%[a], #28]\n\t"
  63046. "UMULL r6, r7, r8, r12\n\t"
  63047. "ADDS r4, r4, r6\n\t"
  63048. "ADCS r5, r5, r7\n\t"
  63049. "ADC r3, r3, #0x0\n\t"
  63050. /* A[8] * B[5] */
  63051. "LDR r8, [%[a], #32]\n\t"
  63052. "LDR r9, [%[b], #20]\n\t"
  63053. "UMULL r6, r7, r8, r9\n\t"
  63054. "ADDS r4, r4, r6\n\t"
  63055. "ADCS r5, r5, r7\n\t"
  63056. "ADC r3, r3, #0x0\n\t"
  63057. /* A[9] * B[4] */
  63058. "LDR r8, [%[a], #36]\n\t"
  63059. "LDR r9, [%[b], #16]\n\t"
  63060. "UMULL r6, r7, r8, r9\n\t"
  63061. "ADDS r4, r4, r6\n\t"
  63062. "ADCS r5, r5, r7\n\t"
  63063. "ADC r3, r3, #0x0\n\t"
  63064. /* A[10] * B[3] */
  63065. "LDR r8, [%[a], #40]\n\t"
  63066. "LDR r9, [%[b], #12]\n\t"
  63067. "UMULL r6, r7, r8, r9\n\t"
  63068. "ADDS r4, r4, r6\n\t"
  63069. "ADCS r5, r5, r7\n\t"
  63070. "ADC r3, r3, #0x0\n\t"
  63071. /* A[11] * B[2] */
  63072. "LDR r8, [%[a], #44]\n\t"
  63073. "LDR r9, [%[b], #8]\n\t"
  63074. "UMULL r6, r7, r8, r9\n\t"
  63075. "ADDS r4, r4, r6\n\t"
  63076. "ADCS r5, r5, r7\n\t"
  63077. "ADC r3, r3, #0x0\n\t"
  63078. /* A[12] * B[1] */
  63079. "LDR r8, [%[a], #48]\n\t"
  63080. "LDR r9, [%[b], #4]\n\t"
  63081. "UMULL r6, r7, r8, r9\n\t"
  63082. "ADDS r4, r4, r6\n\t"
  63083. "ADCS r5, r5, r7\n\t"
  63084. "ADC r3, r3, #0x0\n\t"
  63085. /* A[13] * B[0] */
  63086. "LDR r8, [%[a], #52]\n\t"
  63087. "LDR r9, [%[b]]\n\t"
  63088. "UMULL r6, r7, r8, r9\n\t"
  63089. "ADDS r4, r4, r6\n\t"
  63090. "ADCS r5, r5, r7\n\t"
  63091. "ADC r3, r3, #0x0\n\t"
  63092. "STR r4, [sp, #52]\n\t"
  63093. /* A[14] * B[0] */
  63094. "LDR r8, [%[a], #56]\n\t"
  63095. "UMULL r6, r7, r8, r9\n\t"
  63096. "ADDS r5, r5, r6\n\t"
  63097. "ADCS r3, r3, r7\n\t"
  63098. "MOV r4, #0x0\n\t"
  63099. "ADC r4, r4, #0x0\n\t"
  63100. /* A[13] * B[1] */
  63101. "LDR r8, [%[a], #52]\n\t"
  63102. "LDR r9, [%[b], #4]\n\t"
  63103. "UMULL r6, r7, r8, r9\n\t"
  63104. "ADDS r5, r5, r6\n\t"
  63105. "ADCS r3, r3, r7\n\t"
  63106. "ADC r4, r4, #0x0\n\t"
  63107. /* A[12] * B[2] */
  63108. "LDR r8, [%[a], #48]\n\t"
  63109. "LDR r9, [%[b], #8]\n\t"
  63110. "UMULL r6, r7, r8, r9\n\t"
  63111. "ADDS r5, r5, r6\n\t"
  63112. "ADCS r3, r3, r7\n\t"
  63113. "ADC r4, r4, #0x0\n\t"
  63114. /* A[11] * B[3] */
  63115. "LDR r8, [%[a], #44]\n\t"
  63116. "LDR r9, [%[b], #12]\n\t"
  63117. "UMULL r6, r7, r8, r9\n\t"
  63118. "ADDS r5, r5, r6\n\t"
  63119. "ADCS r3, r3, r7\n\t"
  63120. "ADC r4, r4, #0x0\n\t"
  63121. /* A[10] * B[4] */
  63122. "LDR r8, [%[a], #40]\n\t"
  63123. "LDR r9, [%[b], #16]\n\t"
  63124. "UMULL r6, r7, r8, r9\n\t"
  63125. "ADDS r5, r5, r6\n\t"
  63126. "ADCS r3, r3, r7\n\t"
  63127. "ADC r4, r4, #0x0\n\t"
  63128. /* A[9] * B[5] */
  63129. "LDR r8, [%[a], #36]\n\t"
  63130. "LDR r9, [%[b], #20]\n\t"
  63131. "UMULL r6, r7, r8, r9\n\t"
  63132. "ADDS r5, r5, r6\n\t"
  63133. "ADCS r3, r3, r7\n\t"
  63134. "ADC r4, r4, #0x0\n\t"
  63135. /* A[8] * B[6] */
  63136. "LDR r8, [%[a], #32]\n\t"
  63137. "UMULL r6, r7, r8, r12\n\t"
  63138. "ADDS r5, r5, r6\n\t"
  63139. "ADCS r3, r3, r7\n\t"
  63140. "ADC r4, r4, #0x0\n\t"
  63141. /* A[7] * B[7] */
  63142. "LDR r11, [%[a], #28]\n\t"
  63143. "LDR r12, [%[b], #28]\n\t"
  63144. "UMULL r6, r7, r11, r12\n\t"
  63145. "ADDS r5, r5, r6\n\t"
  63146. "ADCS r3, r3, r7\n\t"
  63147. "ADC r4, r4, #0x0\n\t"
  63148. /* A[6] * B[8] */
  63149. "LDR r8, [%[a], #24]\n\t"
  63150. "LDR r9, [%[b], #32]\n\t"
  63151. "UMULL r6, r7, r8, r9\n\t"
  63152. "ADDS r5, r5, r6\n\t"
  63153. "ADCS r3, r3, r7\n\t"
  63154. "ADC r4, r4, #0x0\n\t"
  63155. /* A[5] * B[9] */
  63156. "LDR r8, [%[a], #20]\n\t"
  63157. "LDR r9, [%[b], #36]\n\t"
  63158. "UMULL r6, r7, r8, r9\n\t"
  63159. "ADDS r5, r5, r6\n\t"
  63160. "ADCS r3, r3, r7\n\t"
  63161. "ADC r4, r4, #0x0\n\t"
  63162. /* A[4] * B[10] */
  63163. "LDR r8, [%[a], #16]\n\t"
  63164. "LDR r9, [%[b], #40]\n\t"
  63165. "UMULL r6, r7, r8, r9\n\t"
  63166. "ADDS r5, r5, r6\n\t"
  63167. "ADCS r3, r3, r7\n\t"
  63168. "ADC r4, r4, #0x0\n\t"
  63169. /* A[3] * B[11] */
  63170. "LDR r8, [%[a], #12]\n\t"
  63171. "LDR r9, [%[b], #44]\n\t"
  63172. "UMULL r6, r7, r8, r9\n\t"
  63173. "ADDS r5, r5, r6\n\t"
  63174. "ADCS r3, r3, r7\n\t"
  63175. "ADC r4, r4, #0x0\n\t"
  63176. /* A[2] * B[12] */
  63177. "LDR r8, [%[a], #8]\n\t"
  63178. "LDR r9, [%[b], #48]\n\t"
  63179. "UMULL r6, r7, r8, r9\n\t"
  63180. "ADDS r5, r5, r6\n\t"
  63181. "ADCS r3, r3, r7\n\t"
  63182. "ADC r4, r4, #0x0\n\t"
  63183. /* A[1] * B[13] */
  63184. "LDR r8, [%[a], #4]\n\t"
  63185. "LDR r9, [%[b], #52]\n\t"
  63186. "UMULL r6, r7, r8, r9\n\t"
  63187. "ADDS r5, r5, r6\n\t"
  63188. "ADCS r3, r3, r7\n\t"
  63189. "ADC r4, r4, #0x0\n\t"
  63190. /* A[0] * B[14] */
  63191. "LDR r8, [%[a]]\n\t"
  63192. "LDR r9, [%[b], #56]\n\t"
  63193. "UMULL r6, r7, r8, r9\n\t"
  63194. "ADDS r5, r5, r6\n\t"
  63195. "ADCS r3, r3, r7\n\t"
  63196. "ADC r4, r4, #0x0\n\t"
  63197. "STR r5, [sp, #56]\n\t"
  63198. /* A[0] * B[15] */
  63199. "LDR r9, [%[b], #60]\n\t"
  63200. "UMULL r6, r7, r8, r9\n\t"
  63201. "ADDS r3, r3, r6\n\t"
  63202. "ADCS r4, r4, r7\n\t"
  63203. "MOV r5, #0x0\n\t"
  63204. "ADC r5, r5, #0x0\n\t"
  63205. /* A[1] * B[14] */
  63206. "LDR r8, [%[a], #4]\n\t"
  63207. "LDR r9, [%[b], #56]\n\t"
  63208. "UMULL r6, r7, r8, r9\n\t"
  63209. "ADDS r3, r3, r6\n\t"
  63210. "ADCS r4, r4, r7\n\t"
  63211. "ADC r5, r5, #0x0\n\t"
  63212. /* A[2] * B[13] */
  63213. "LDR r8, [%[a], #8]\n\t"
  63214. "LDR r9, [%[b], #52]\n\t"
  63215. "UMULL r6, r7, r8, r9\n\t"
  63216. "ADDS r3, r3, r6\n\t"
  63217. "ADCS r4, r4, r7\n\t"
  63218. "ADC r5, r5, #0x0\n\t"
  63219. /* A[3] * B[12] */
  63220. "LDR r8, [%[a], #12]\n\t"
  63221. "LDR r9, [%[b], #48]\n\t"
  63222. "UMULL r6, r7, r8, r9\n\t"
  63223. "ADDS r3, r3, r6\n\t"
  63224. "ADCS r4, r4, r7\n\t"
  63225. "ADC r5, r5, #0x0\n\t"
  63226. /* A[4] * B[11] */
  63227. "LDR r8, [%[a], #16]\n\t"
  63228. "LDR r9, [%[b], #44]\n\t"
  63229. "UMULL r6, r7, r8, r9\n\t"
  63230. "ADDS r3, r3, r6\n\t"
  63231. "ADCS r4, r4, r7\n\t"
  63232. "ADC r5, r5, #0x0\n\t"
  63233. /* A[5] * B[10] */
  63234. "LDR r8, [%[a], #20]\n\t"
  63235. "LDR r9, [%[b], #40]\n\t"
  63236. "UMULL r6, r7, r8, r9\n\t"
  63237. "ADDS r3, r3, r6\n\t"
  63238. "ADCS r4, r4, r7\n\t"
  63239. "ADC r5, r5, #0x0\n\t"
  63240. /* A[6] * B[9] */
  63241. "LDR r8, [%[a], #24]\n\t"
  63242. "LDR r9, [%[b], #36]\n\t"
  63243. "UMULL r6, r7, r8, r9\n\t"
  63244. "ADDS r3, r3, r6\n\t"
  63245. "ADCS r4, r4, r7\n\t"
  63246. "ADC r5, r5, #0x0\n\t"
  63247. /* A[7] * B[8] */
  63248. "LDR r9, [%[b], #32]\n\t"
  63249. "UMULL r6, r7, r11, r9\n\t"
  63250. "ADDS r3, r3, r6\n\t"
  63251. "ADCS r4, r4, r7\n\t"
  63252. "ADC r5, r5, #0x0\n\t"
  63253. /* A[8] * B[7] */
  63254. "LDR r8, [%[a], #32]\n\t"
  63255. "UMULL r6, r7, r8, r12\n\t"
  63256. "ADDS r3, r3, r6\n\t"
  63257. "ADCS r4, r4, r7\n\t"
  63258. "ADC r5, r5, #0x0\n\t"
  63259. /* A[9] * B[6] */
  63260. "LDR r8, [%[a], #36]\n\t"
  63261. "LDR r9, [%[b], #24]\n\t"
  63262. "UMULL r6, r7, r8, r9\n\t"
  63263. "ADDS r3, r3, r6\n\t"
  63264. "ADCS r4, r4, r7\n\t"
  63265. "ADC r5, r5, #0x0\n\t"
  63266. /* A[10] * B[5] */
  63267. "LDR r8, [%[a], #40]\n\t"
  63268. "LDR r9, [%[b], #20]\n\t"
  63269. "UMULL r6, r7, r8, r9\n\t"
  63270. "ADDS r3, r3, r6\n\t"
  63271. "ADCS r4, r4, r7\n\t"
  63272. "ADC r5, r5, #0x0\n\t"
  63273. /* A[11] * B[4] */
  63274. "LDR r8, [%[a], #44]\n\t"
  63275. "LDR r9, [%[b], #16]\n\t"
  63276. "UMULL r6, r7, r8, r9\n\t"
  63277. "ADDS r3, r3, r6\n\t"
  63278. "ADCS r4, r4, r7\n\t"
  63279. "ADC r5, r5, #0x0\n\t"
  63280. /* A[12] * B[3] */
  63281. "LDR r8, [%[a], #48]\n\t"
  63282. "LDR r9, [%[b], #12]\n\t"
  63283. "UMULL r6, r7, r8, r9\n\t"
  63284. "ADDS r3, r3, r6\n\t"
  63285. "ADCS r4, r4, r7\n\t"
  63286. "ADC r5, r5, #0x0\n\t"
  63287. /* A[13] * B[2] */
  63288. "LDR r8, [%[a], #52]\n\t"
  63289. "LDR r9, [%[b], #8]\n\t"
  63290. "UMULL r6, r7, r8, r9\n\t"
  63291. "ADDS r3, r3, r6\n\t"
  63292. "ADCS r4, r4, r7\n\t"
  63293. "ADC r5, r5, #0x0\n\t"
  63294. /* A[14] * B[1] */
  63295. "LDR r8, [%[a], #56]\n\t"
  63296. "LDR r9, [%[b], #4]\n\t"
  63297. "UMULL r6, r7, r8, r9\n\t"
  63298. "ADDS r3, r3, r6\n\t"
  63299. "ADCS r4, r4, r7\n\t"
  63300. "ADC r5, r5, #0x0\n\t"
  63301. /* A[15] * B[0] */
  63302. "LDR r8, [%[a], #60]\n\t"
  63303. "LDR r9, [%[b]]\n\t"
  63304. "UMULL r6, r7, r8, r9\n\t"
  63305. "ADDS r3, r3, r6\n\t"
  63306. "ADCS r4, r4, r7\n\t"
  63307. "ADC r5, r5, #0x0\n\t"
  63308. "STR r3, [sp, #60]\n\t"
  63309. /* A[15] * B[1] */
  63310. "LDR r9, [%[b], #4]\n\t"
  63311. "UMULL r6, r7, r8, r9\n\t"
  63312. "ADDS r4, r4, r6\n\t"
  63313. "ADCS r5, r5, r7\n\t"
  63314. "MOV r3, #0x0\n\t"
  63315. "ADC r3, r3, #0x0\n\t"
  63316. /* A[14] * B[2] */
  63317. "LDR r8, [%[a], #56]\n\t"
  63318. "LDR r9, [%[b], #8]\n\t"
  63319. "UMULL r6, r7, r8, r9\n\t"
  63320. "ADDS r4, r4, r6\n\t"
  63321. "ADCS r5, r5, r7\n\t"
  63322. "ADC r3, r3, #0x0\n\t"
  63323. /* A[13] * B[3] */
  63324. "LDR r8, [%[a], #52]\n\t"
  63325. "LDR r9, [%[b], #12]\n\t"
  63326. "UMULL r6, r7, r8, r9\n\t"
  63327. "ADDS r4, r4, r6\n\t"
  63328. "ADCS r5, r5, r7\n\t"
  63329. "ADC r3, r3, #0x0\n\t"
  63330. /* A[12] * B[4] */
  63331. "LDR r8, [%[a], #48]\n\t"
  63332. "LDR r9, [%[b], #16]\n\t"
  63333. "UMULL r6, r7, r8, r9\n\t"
  63334. "ADDS r4, r4, r6\n\t"
  63335. "ADCS r5, r5, r7\n\t"
  63336. "ADC r3, r3, #0x0\n\t"
  63337. /* A[11] * B[5] */
  63338. "LDR r8, [%[a], #44]\n\t"
  63339. "LDR r9, [%[b], #20]\n\t"
  63340. "UMULL r6, r7, r8, r9\n\t"
  63341. "ADDS r4, r4, r6\n\t"
  63342. "ADCS r5, r5, r7\n\t"
  63343. "ADC r3, r3, #0x0\n\t"
  63344. /* A[10] * B[6] */
  63345. "LDR r8, [%[a], #40]\n\t"
  63346. "LDR r9, [%[b], #24]\n\t"
  63347. "UMULL r6, r7, r8, r9\n\t"
  63348. "ADDS r4, r4, r6\n\t"
  63349. "ADCS r5, r5, r7\n\t"
  63350. "ADC r3, r3, #0x0\n\t"
  63351. /* A[9] * B[7] */
  63352. "LDR r8, [%[a], #36]\n\t"
  63353. "UMULL r6, r7, r8, r12\n\t"
  63354. "ADDS r4, r4, r6\n\t"
  63355. "ADCS r5, r5, r7\n\t"
  63356. "ADC r3, r3, #0x0\n\t"
  63357. /* A[8] * B[8] */
  63358. "LDR r11, [%[a], #32]\n\t"
  63359. "LDR r12, [%[b], #32]\n\t"
  63360. "UMULL r6, r7, r11, r12\n\t"
  63361. "ADDS r4, r4, r6\n\t"
  63362. "ADCS r5, r5, r7\n\t"
  63363. "ADC r3, r3, #0x0\n\t"
  63364. /* A[7] * B[9] */
  63365. "LDR r8, [%[a], #28]\n\t"
  63366. "LDR r9, [%[b], #36]\n\t"
  63367. "UMULL r6, r7, r8, r9\n\t"
  63368. "ADDS r4, r4, r6\n\t"
  63369. "ADCS r5, r5, r7\n\t"
  63370. "ADC r3, r3, #0x0\n\t"
  63371. /* A[6] * B[10] */
  63372. "LDR r8, [%[a], #24]\n\t"
  63373. "LDR r9, [%[b], #40]\n\t"
  63374. "UMULL r6, r7, r8, r9\n\t"
  63375. "ADDS r4, r4, r6\n\t"
  63376. "ADCS r5, r5, r7\n\t"
  63377. "ADC r3, r3, #0x0\n\t"
  63378. /* A[5] * B[11] */
  63379. "LDR r8, [%[a], #20]\n\t"
  63380. "LDR r9, [%[b], #44]\n\t"
  63381. "UMULL r6, r7, r8, r9\n\t"
  63382. "ADDS r4, r4, r6\n\t"
  63383. "ADCS r5, r5, r7\n\t"
  63384. "ADC r3, r3, #0x0\n\t"
  63385. /* A[4] * B[12] */
  63386. "LDR r8, [%[a], #16]\n\t"
  63387. "LDR r9, [%[b], #48]\n\t"
  63388. "UMULL r6, r7, r8, r9\n\t"
  63389. "ADDS r4, r4, r6\n\t"
  63390. "ADCS r5, r5, r7\n\t"
  63391. "ADC r3, r3, #0x0\n\t"
  63392. /* A[3] * B[13] */
  63393. "LDR r8, [%[a], #12]\n\t"
  63394. "LDR r9, [%[b], #52]\n\t"
  63395. "UMULL r6, r7, r8, r9\n\t"
  63396. "ADDS r4, r4, r6\n\t"
  63397. "ADCS r5, r5, r7\n\t"
  63398. "ADC r3, r3, #0x0\n\t"
  63399. /* A[2] * B[14] */
  63400. "LDR r8, [%[a], #8]\n\t"
  63401. "LDR r9, [%[b], #56]\n\t"
  63402. "UMULL r6, r7, r8, r9\n\t"
  63403. "ADDS r4, r4, r6\n\t"
  63404. "ADCS r5, r5, r7\n\t"
  63405. "ADC r3, r3, #0x0\n\t"
  63406. /* A[1] * B[15] */
  63407. "LDR r8, [%[a], #4]\n\t"
  63408. "LDR r9, [%[b], #60]\n\t"
  63409. "UMULL r6, r7, r8, r9\n\t"
  63410. "ADDS r4, r4, r6\n\t"
  63411. "ADCS r5, r5, r7\n\t"
  63412. "ADC r3, r3, #0x0\n\t"
  63413. "STR r4, [%[r], #64]\n\t"
  63414. /* A[2] * B[15] */
  63415. "LDR r8, [%[a], #8]\n\t"
  63416. "UMULL r6, r7, r8, r9\n\t"
  63417. "ADDS r5, r5, r6\n\t"
  63418. "ADCS r3, r3, r7\n\t"
  63419. "MOV r4, #0x0\n\t"
  63420. "ADC r4, r4, #0x0\n\t"
  63421. /* A[3] * B[14] */
  63422. "LDR r8, [%[a], #12]\n\t"
  63423. "LDR r9, [%[b], #56]\n\t"
  63424. "UMULL r6, r7, r8, r9\n\t"
  63425. "ADDS r5, r5, r6\n\t"
  63426. "ADCS r3, r3, r7\n\t"
  63427. "ADC r4, r4, #0x0\n\t"
  63428. /* A[4] * B[13] */
  63429. "LDR r8, [%[a], #16]\n\t"
  63430. "LDR r9, [%[b], #52]\n\t"
  63431. "UMULL r6, r7, r8, r9\n\t"
  63432. "ADDS r5, r5, r6\n\t"
  63433. "ADCS r3, r3, r7\n\t"
  63434. "ADC r4, r4, #0x0\n\t"
  63435. /* A[5] * B[12] */
  63436. "LDR r8, [%[a], #20]\n\t"
  63437. "LDR r9, [%[b], #48]\n\t"
  63438. "UMULL r6, r7, r8, r9\n\t"
  63439. "ADDS r5, r5, r6\n\t"
  63440. "ADCS r3, r3, r7\n\t"
  63441. "ADC r4, r4, #0x0\n\t"
  63442. /* A[6] * B[11] */
  63443. "LDR r8, [%[a], #24]\n\t"
  63444. "LDR r9, [%[b], #44]\n\t"
  63445. "UMULL r6, r7, r8, r9\n\t"
  63446. "ADDS r5, r5, r6\n\t"
  63447. "ADCS r3, r3, r7\n\t"
  63448. "ADC r4, r4, #0x0\n\t"
  63449. /* A[7] * B[10] */
  63450. "LDR r8, [%[a], #28]\n\t"
  63451. "LDR r9, [%[b], #40]\n\t"
  63452. "UMULL r6, r7, r8, r9\n\t"
  63453. "ADDS r5, r5, r6\n\t"
  63454. "ADCS r3, r3, r7\n\t"
  63455. "ADC r4, r4, #0x0\n\t"
  63456. /* A[8] * B[9] */
  63457. "LDR r9, [%[b], #36]\n\t"
  63458. "UMULL r6, r7, r11, r9\n\t"
  63459. "ADDS r5, r5, r6\n\t"
  63460. "ADCS r3, r3, r7\n\t"
  63461. "ADC r4, r4, #0x0\n\t"
  63462. /* A[9] * B[8] */
  63463. "LDR r8, [%[a], #36]\n\t"
  63464. "UMULL r6, r7, r8, r12\n\t"
  63465. "ADDS r5, r5, r6\n\t"
  63466. "ADCS r3, r3, r7\n\t"
  63467. "ADC r4, r4, #0x0\n\t"
  63468. /* A[10] * B[7] */
  63469. "LDR r8, [%[a], #40]\n\t"
  63470. "LDR r9, [%[b], #28]\n\t"
  63471. "UMULL r6, r7, r8, r9\n\t"
  63472. "ADDS r5, r5, r6\n\t"
  63473. "ADCS r3, r3, r7\n\t"
  63474. "ADC r4, r4, #0x0\n\t"
  63475. /* A[11] * B[6] */
  63476. "LDR r8, [%[a], #44]\n\t"
  63477. "LDR r9, [%[b], #24]\n\t"
  63478. "UMULL r6, r7, r8, r9\n\t"
  63479. "ADDS r5, r5, r6\n\t"
  63480. "ADCS r3, r3, r7\n\t"
  63481. "ADC r4, r4, #0x0\n\t"
  63482. /* A[12] * B[5] */
  63483. "LDR r8, [%[a], #48]\n\t"
  63484. "LDR r9, [%[b], #20]\n\t"
  63485. "UMULL r6, r7, r8, r9\n\t"
  63486. "ADDS r5, r5, r6\n\t"
  63487. "ADCS r3, r3, r7\n\t"
  63488. "ADC r4, r4, #0x0\n\t"
  63489. /* A[13] * B[4] */
  63490. "LDR r8, [%[a], #52]\n\t"
  63491. "LDR r9, [%[b], #16]\n\t"
  63492. "UMULL r6, r7, r8, r9\n\t"
  63493. "ADDS r5, r5, r6\n\t"
  63494. "ADCS r3, r3, r7\n\t"
  63495. "ADC r4, r4, #0x0\n\t"
  63496. /* A[14] * B[3] */
  63497. "LDR r8, [%[a], #56]\n\t"
  63498. "LDR r9, [%[b], #12]\n\t"
  63499. "UMULL r6, r7, r8, r9\n\t"
  63500. "ADDS r5, r5, r6\n\t"
  63501. "ADCS r3, r3, r7\n\t"
  63502. "ADC r4, r4, #0x0\n\t"
  63503. /* A[15] * B[2] */
  63504. "LDR r8, [%[a], #60]\n\t"
  63505. "LDR r9, [%[b], #8]\n\t"
  63506. "UMULL r6, r7, r8, r9\n\t"
  63507. "ADDS r5, r5, r6\n\t"
  63508. "ADCS r3, r3, r7\n\t"
  63509. "ADC r4, r4, #0x0\n\t"
  63510. "STR r5, [%[r], #68]\n\t"
  63511. /* A[15] * B[3] */
  63512. "LDR r9, [%[b], #12]\n\t"
  63513. "UMULL r6, r7, r8, r9\n\t"
  63514. "ADDS r3, r3, r6\n\t"
  63515. "ADCS r4, r4, r7\n\t"
  63516. "MOV r5, #0x0\n\t"
  63517. "ADC r5, r5, #0x0\n\t"
  63518. /* A[14] * B[4] */
  63519. "LDR r8, [%[a], #56]\n\t"
  63520. "LDR r9, [%[b], #16]\n\t"
  63521. "UMULL r6, r7, r8, r9\n\t"
  63522. "ADDS r3, r3, r6\n\t"
  63523. "ADCS r4, r4, r7\n\t"
  63524. "ADC r5, r5, #0x0\n\t"
  63525. /* A[13] * B[5] */
  63526. "LDR r8, [%[a], #52]\n\t"
  63527. "LDR r9, [%[b], #20]\n\t"
  63528. "UMULL r6, r7, r8, r9\n\t"
  63529. "ADDS r3, r3, r6\n\t"
  63530. "ADCS r4, r4, r7\n\t"
  63531. "ADC r5, r5, #0x0\n\t"
  63532. /* A[12] * B[6] */
  63533. "LDR r8, [%[a], #48]\n\t"
  63534. "LDR r9, [%[b], #24]\n\t"
  63535. "UMULL r6, r7, r8, r9\n\t"
  63536. "ADDS r3, r3, r6\n\t"
  63537. "ADCS r4, r4, r7\n\t"
  63538. "ADC r5, r5, #0x0\n\t"
  63539. /* A[11] * B[7] */
  63540. "LDR r8, [%[a], #44]\n\t"
  63541. "LDR r9, [%[b], #28]\n\t"
  63542. "UMULL r6, r7, r8, r9\n\t"
  63543. "ADDS r3, r3, r6\n\t"
  63544. "ADCS r4, r4, r7\n\t"
  63545. "ADC r5, r5, #0x0\n\t"
  63546. /* A[10] * B[8] */
  63547. "LDR r8, [%[a], #40]\n\t"
  63548. "UMULL r6, r7, r8, r12\n\t"
  63549. "ADDS r3, r3, r6\n\t"
  63550. "ADCS r4, r4, r7\n\t"
  63551. "ADC r5, r5, #0x0\n\t"
  63552. /* A[9] * B[9] */
  63553. "LDR r11, [%[a], #36]\n\t"
  63554. "LDR r12, [%[b], #36]\n\t"
  63555. "UMULL r6, r7, r11, r12\n\t"
  63556. "ADDS r3, r3, r6\n\t"
  63557. "ADCS r4, r4, r7\n\t"
  63558. "ADC r5, r5, #0x0\n\t"
  63559. /* A[8] * B[10] */
  63560. "LDR r8, [%[a], #32]\n\t"
  63561. "LDR r9, [%[b], #40]\n\t"
  63562. "UMULL r6, r7, r8, r9\n\t"
  63563. "ADDS r3, r3, r6\n\t"
  63564. "ADCS r4, r4, r7\n\t"
  63565. "ADC r5, r5, #0x0\n\t"
  63566. /* A[7] * B[11] */
  63567. "LDR r8, [%[a], #28]\n\t"
  63568. "LDR r9, [%[b], #44]\n\t"
  63569. "UMULL r6, r7, r8, r9\n\t"
  63570. "ADDS r3, r3, r6\n\t"
  63571. "ADCS r4, r4, r7\n\t"
  63572. "ADC r5, r5, #0x0\n\t"
  63573. /* A[6] * B[12] */
  63574. "LDR r8, [%[a], #24]\n\t"
  63575. "LDR r9, [%[b], #48]\n\t"
  63576. "UMULL r6, r7, r8, r9\n\t"
  63577. "ADDS r3, r3, r6\n\t"
  63578. "ADCS r4, r4, r7\n\t"
  63579. "ADC r5, r5, #0x0\n\t"
  63580. /* A[5] * B[13] */
  63581. "LDR r8, [%[a], #20]\n\t"
  63582. "LDR r9, [%[b], #52]\n\t"
  63583. "UMULL r6, r7, r8, r9\n\t"
  63584. "ADDS r3, r3, r6\n\t"
  63585. "ADCS r4, r4, r7\n\t"
  63586. "ADC r5, r5, #0x0\n\t"
  63587. /* A[4] * B[14] */
  63588. "LDR r8, [%[a], #16]\n\t"
  63589. "LDR r9, [%[b], #56]\n\t"
  63590. "UMULL r6, r7, r8, r9\n\t"
  63591. "ADDS r3, r3, r6\n\t"
  63592. "ADCS r4, r4, r7\n\t"
  63593. "ADC r5, r5, #0x0\n\t"
  63594. /* A[3] * B[15] */
  63595. "LDR r8, [%[a], #12]\n\t"
  63596. "LDR r9, [%[b], #60]\n\t"
  63597. "UMULL r6, r7, r8, r9\n\t"
  63598. "ADDS r3, r3, r6\n\t"
  63599. "ADCS r4, r4, r7\n\t"
  63600. "ADC r5, r5, #0x0\n\t"
  63601. "STR r3, [%[r], #72]\n\t"
  63602. /* A[4] * B[15] */
  63603. "LDR r8, [%[a], #16]\n\t"
  63604. "UMULL r6, r7, r8, r9\n\t"
  63605. "ADDS r4, r4, r6\n\t"
  63606. "ADCS r5, r5, r7\n\t"
  63607. "MOV r3, #0x0\n\t"
  63608. "ADC r3, r3, #0x0\n\t"
  63609. /* A[5] * B[14] */
  63610. "LDR r8, [%[a], #20]\n\t"
  63611. "LDR r9, [%[b], #56]\n\t"
  63612. "UMULL r6, r7, r8, r9\n\t"
  63613. "ADDS r4, r4, r6\n\t"
  63614. "ADCS r5, r5, r7\n\t"
  63615. "ADC r3, r3, #0x0\n\t"
  63616. /* A[6] * B[13] */
  63617. "LDR r8, [%[a], #24]\n\t"
  63618. "LDR r9, [%[b], #52]\n\t"
  63619. "UMULL r6, r7, r8, r9\n\t"
  63620. "ADDS r4, r4, r6\n\t"
  63621. "ADCS r5, r5, r7\n\t"
  63622. "ADC r3, r3, #0x0\n\t"
  63623. /* A[7] * B[12] */
  63624. "LDR r8, [%[a], #28]\n\t"
  63625. "LDR r9, [%[b], #48]\n\t"
  63626. "UMULL r6, r7, r8, r9\n\t"
  63627. "ADDS r4, r4, r6\n\t"
  63628. "ADCS r5, r5, r7\n\t"
  63629. "ADC r3, r3, #0x0\n\t"
  63630. /* A[8] * B[11] */
  63631. "LDR r8, [%[a], #32]\n\t"
  63632. "LDR r9, [%[b], #44]\n\t"
  63633. "UMULL r6, r7, r8, r9\n\t"
  63634. "ADDS r4, r4, r6\n\t"
  63635. "ADCS r5, r5, r7\n\t"
  63636. "ADC r3, r3, #0x0\n\t"
  63637. /* A[9] * B[10] */
  63638. "LDR r9, [%[b], #40]\n\t"
  63639. "UMULL r6, r7, r11, r9\n\t"
  63640. "ADDS r4, r4, r6\n\t"
  63641. "ADCS r5, r5, r7\n\t"
  63642. "ADC r3, r3, #0x0\n\t"
  63643. /* A[10] * B[9] */
  63644. "LDR r8, [%[a], #40]\n\t"
  63645. "UMULL r6, r7, r8, r12\n\t"
  63646. "ADDS r4, r4, r6\n\t"
  63647. "ADCS r5, r5, r7\n\t"
  63648. "ADC r3, r3, #0x0\n\t"
  63649. /* A[11] * B[8] */
  63650. "LDR r8, [%[a], #44]\n\t"
  63651. "LDR r9, [%[b], #32]\n\t"
  63652. "UMULL r6, r7, r8, r9\n\t"
  63653. "ADDS r4, r4, r6\n\t"
  63654. "ADCS r5, r5, r7\n\t"
  63655. "ADC r3, r3, #0x0\n\t"
  63656. /* A[12] * B[7] */
  63657. "LDR r8, [%[a], #48]\n\t"
  63658. "LDR r9, [%[b], #28]\n\t"
  63659. "UMULL r6, r7, r8, r9\n\t"
  63660. "ADDS r4, r4, r6\n\t"
  63661. "ADCS r5, r5, r7\n\t"
  63662. "ADC r3, r3, #0x0\n\t"
  63663. /* A[13] * B[6] */
  63664. "LDR r8, [%[a], #52]\n\t"
  63665. "LDR r9, [%[b], #24]\n\t"
  63666. "UMULL r6, r7, r8, r9\n\t"
  63667. "ADDS r4, r4, r6\n\t"
  63668. "ADCS r5, r5, r7\n\t"
  63669. "ADC r3, r3, #0x0\n\t"
  63670. /* A[14] * B[5] */
  63671. "LDR r8, [%[a], #56]\n\t"
  63672. "LDR r9, [%[b], #20]\n\t"
  63673. "UMULL r6, r7, r8, r9\n\t"
  63674. "ADDS r4, r4, r6\n\t"
  63675. "ADCS r5, r5, r7\n\t"
  63676. "ADC r3, r3, #0x0\n\t"
  63677. /* A[15] * B[4] */
  63678. "LDR r8, [%[a], #60]\n\t"
  63679. "LDR r9, [%[b], #16]\n\t"
  63680. "UMULL r6, r7, r8, r9\n\t"
  63681. "ADDS r4, r4, r6\n\t"
  63682. "ADCS r5, r5, r7\n\t"
  63683. "ADC r3, r3, #0x0\n\t"
  63684. "STR r4, [%[r], #76]\n\t"
  63685. /* A[15] * B[5] */
  63686. "LDR r9, [%[b], #20]\n\t"
  63687. "UMULL r6, r7, r8, r9\n\t"
  63688. "ADDS r5, r5, r6\n\t"
  63689. "ADCS r3, r3, r7\n\t"
  63690. "MOV r4, #0x0\n\t"
  63691. "ADC r4, r4, #0x0\n\t"
  63692. /* A[14] * B[6] */
  63693. "LDR r8, [%[a], #56]\n\t"
  63694. "LDR r9, [%[b], #24]\n\t"
  63695. "UMULL r6, r7, r8, r9\n\t"
  63696. "ADDS r5, r5, r6\n\t"
  63697. "ADCS r3, r3, r7\n\t"
  63698. "ADC r4, r4, #0x0\n\t"
  63699. /* A[13] * B[7] */
  63700. "LDR r8, [%[a], #52]\n\t"
  63701. "LDR r9, [%[b], #28]\n\t"
  63702. "UMULL r6, r7, r8, r9\n\t"
  63703. "ADDS r5, r5, r6\n\t"
  63704. "ADCS r3, r3, r7\n\t"
  63705. "ADC r4, r4, #0x0\n\t"
  63706. /* A[12] * B[8] */
  63707. "LDR r8, [%[a], #48]\n\t"
  63708. "LDR r9, [%[b], #32]\n\t"
  63709. "UMULL r6, r7, r8, r9\n\t"
  63710. "ADDS r5, r5, r6\n\t"
  63711. "ADCS r3, r3, r7\n\t"
  63712. "ADC r4, r4, #0x0\n\t"
  63713. /* A[11] * B[9] */
  63714. "LDR r8, [%[a], #44]\n\t"
  63715. "UMULL r6, r7, r8, r12\n\t"
  63716. "ADDS r5, r5, r6\n\t"
  63717. "ADCS r3, r3, r7\n\t"
  63718. "ADC r4, r4, #0x0\n\t"
  63719. /* A[10] * B[10] */
  63720. "LDR r11, [%[a], #40]\n\t"
  63721. "LDR r12, [%[b], #40]\n\t"
  63722. "UMULL r6, r7, r11, r12\n\t"
  63723. "ADDS r5, r5, r6\n\t"
  63724. "ADCS r3, r3, r7\n\t"
  63725. "ADC r4, r4, #0x0\n\t"
  63726. /* A[9] * B[11] */
  63727. "LDR r8, [%[a], #36]\n\t"
  63728. "LDR r9, [%[b], #44]\n\t"
  63729. "UMULL r6, r7, r8, r9\n\t"
  63730. "ADDS r5, r5, r6\n\t"
  63731. "ADCS r3, r3, r7\n\t"
  63732. "ADC r4, r4, #0x0\n\t"
  63733. /* A[8] * B[12] */
  63734. "LDR r8, [%[a], #32]\n\t"
  63735. "LDR r9, [%[b], #48]\n\t"
  63736. "UMULL r6, r7, r8, r9\n\t"
  63737. "ADDS r5, r5, r6\n\t"
  63738. "ADCS r3, r3, r7\n\t"
  63739. "ADC r4, r4, #0x0\n\t"
  63740. /* A[7] * B[13] */
  63741. "LDR r8, [%[a], #28]\n\t"
  63742. "LDR r9, [%[b], #52]\n\t"
  63743. "UMULL r6, r7, r8, r9\n\t"
  63744. "ADDS r5, r5, r6\n\t"
  63745. "ADCS r3, r3, r7\n\t"
  63746. "ADC r4, r4, #0x0\n\t"
  63747. /* A[6] * B[14] */
  63748. "LDR r8, [%[a], #24]\n\t"
  63749. "LDR r9, [%[b], #56]\n\t"
  63750. "UMULL r6, r7, r8, r9\n\t"
  63751. "ADDS r5, r5, r6\n\t"
  63752. "ADCS r3, r3, r7\n\t"
  63753. "ADC r4, r4, #0x0\n\t"
  63754. /* A[5] * B[15] */
  63755. "LDR r8, [%[a], #20]\n\t"
  63756. "LDR r9, [%[b], #60]\n\t"
  63757. "UMULL r6, r7, r8, r9\n\t"
  63758. "ADDS r5, r5, r6\n\t"
  63759. "ADCS r3, r3, r7\n\t"
  63760. "ADC r4, r4, #0x0\n\t"
  63761. "STR r5, [%[r], #80]\n\t"
  63762. /* A[6] * B[15] */
  63763. "LDR r8, [%[a], #24]\n\t"
  63764. "UMULL r6, r7, r8, r9\n\t"
  63765. "ADDS r3, r3, r6\n\t"
  63766. "ADCS r4, r4, r7\n\t"
  63767. "MOV r5, #0x0\n\t"
  63768. "ADC r5, r5, #0x0\n\t"
  63769. /* A[7] * B[14] */
  63770. "LDR r8, [%[a], #28]\n\t"
  63771. "LDR r9, [%[b], #56]\n\t"
  63772. "UMULL r6, r7, r8, r9\n\t"
  63773. "ADDS r3, r3, r6\n\t"
  63774. "ADCS r4, r4, r7\n\t"
  63775. "ADC r5, r5, #0x0\n\t"
  63776. /* A[8] * B[13] */
  63777. "LDR r8, [%[a], #32]\n\t"
  63778. "LDR r9, [%[b], #52]\n\t"
  63779. "UMULL r6, r7, r8, r9\n\t"
  63780. "ADDS r3, r3, r6\n\t"
  63781. "ADCS r4, r4, r7\n\t"
  63782. "ADC r5, r5, #0x0\n\t"
  63783. /* A[9] * B[12] */
  63784. "LDR r8, [%[a], #36]\n\t"
  63785. "LDR r9, [%[b], #48]\n\t"
  63786. "UMULL r6, r7, r8, r9\n\t"
  63787. "ADDS r3, r3, r6\n\t"
  63788. "ADCS r4, r4, r7\n\t"
  63789. "ADC r5, r5, #0x0\n\t"
  63790. /* A[10] * B[11] */
  63791. "LDR r9, [%[b], #44]\n\t"
  63792. "UMULL r6, r7, r11, r9\n\t"
  63793. "ADDS r3, r3, r6\n\t"
  63794. "ADCS r4, r4, r7\n\t"
  63795. "ADC r5, r5, #0x0\n\t"
  63796. /* A[11] * B[10] */
  63797. "LDR r8, [%[a], #44]\n\t"
  63798. "UMULL r6, r7, r8, r12\n\t"
  63799. "ADDS r3, r3, r6\n\t"
  63800. "ADCS r4, r4, r7\n\t"
  63801. "ADC r5, r5, #0x0\n\t"
  63802. /* A[12] * B[9] */
  63803. "LDR r8, [%[a], #48]\n\t"
  63804. "LDR r9, [%[b], #36]\n\t"
  63805. "UMULL r6, r7, r8, r9\n\t"
  63806. "ADDS r3, r3, r6\n\t"
  63807. "ADCS r4, r4, r7\n\t"
  63808. "ADC r5, r5, #0x0\n\t"
  63809. /* A[13] * B[8] */
  63810. "LDR r8, [%[a], #52]\n\t"
  63811. "LDR r9, [%[b], #32]\n\t"
  63812. "UMULL r6, r7, r8, r9\n\t"
  63813. "ADDS r3, r3, r6\n\t"
  63814. "ADCS r4, r4, r7\n\t"
  63815. "ADC r5, r5, #0x0\n\t"
  63816. /* A[14] * B[7] */
  63817. "LDR r8, [%[a], #56]\n\t"
  63818. "LDR r9, [%[b], #28]\n\t"
  63819. "UMULL r6, r7, r8, r9\n\t"
  63820. "ADDS r3, r3, r6\n\t"
  63821. "ADCS r4, r4, r7\n\t"
  63822. "ADC r5, r5, #0x0\n\t"
  63823. /* A[15] * B[6] */
  63824. "LDR r8, [%[a], #60]\n\t"
  63825. "LDR r9, [%[b], #24]\n\t"
  63826. "UMULL r6, r7, r8, r9\n\t"
  63827. "ADDS r3, r3, r6\n\t"
  63828. "ADCS r4, r4, r7\n\t"
  63829. "ADC r5, r5, #0x0\n\t"
  63830. "STR r3, [%[r], #84]\n\t"
  63831. /* A[15] * B[7] */
  63832. "LDR r9, [%[b], #28]\n\t"
  63833. "UMULL r6, r7, r8, r9\n\t"
  63834. "ADDS r4, r4, r6\n\t"
  63835. "ADCS r5, r5, r7\n\t"
  63836. "MOV r3, #0x0\n\t"
  63837. "ADC r3, r3, #0x0\n\t"
  63838. /* A[14] * B[8] */
  63839. "LDR r8, [%[a], #56]\n\t"
  63840. "LDR r9, [%[b], #32]\n\t"
  63841. "UMULL r6, r7, r8, r9\n\t"
  63842. "ADDS r4, r4, r6\n\t"
  63843. "ADCS r5, r5, r7\n\t"
  63844. "ADC r3, r3, #0x0\n\t"
  63845. /* A[13] * B[9] */
  63846. "LDR r8, [%[a], #52]\n\t"
  63847. "LDR r9, [%[b], #36]\n\t"
  63848. "UMULL r6, r7, r8, r9\n\t"
  63849. "ADDS r4, r4, r6\n\t"
  63850. "ADCS r5, r5, r7\n\t"
  63851. "ADC r3, r3, #0x0\n\t"
  63852. /* A[12] * B[10] */
  63853. "LDR r8, [%[a], #48]\n\t"
  63854. "UMULL r6, r7, r8, r12\n\t"
  63855. "ADDS r4, r4, r6\n\t"
  63856. "ADCS r5, r5, r7\n\t"
  63857. "ADC r3, r3, #0x0\n\t"
  63858. /* A[11] * B[11] */
  63859. "LDR r11, [%[a], #44]\n\t"
  63860. "LDR r12, [%[b], #44]\n\t"
  63861. "UMULL r6, r7, r11, r12\n\t"
  63862. "ADDS r4, r4, r6\n\t"
  63863. "ADCS r5, r5, r7\n\t"
  63864. "ADC r3, r3, #0x0\n\t"
  63865. /* A[10] * B[12] */
  63866. "LDR r8, [%[a], #40]\n\t"
  63867. "LDR r9, [%[b], #48]\n\t"
  63868. "UMULL r6, r7, r8, r9\n\t"
  63869. "ADDS r4, r4, r6\n\t"
  63870. "ADCS r5, r5, r7\n\t"
  63871. "ADC r3, r3, #0x0\n\t"
  63872. /* A[9] * B[13] */
  63873. "LDR r8, [%[a], #36]\n\t"
  63874. "LDR r9, [%[b], #52]\n\t"
  63875. "UMULL r6, r7, r8, r9\n\t"
  63876. "ADDS r4, r4, r6\n\t"
  63877. "ADCS r5, r5, r7\n\t"
  63878. "ADC r3, r3, #0x0\n\t"
  63879. /* A[8] * B[14] */
  63880. "LDR r8, [%[a], #32]\n\t"
  63881. "LDR r9, [%[b], #56]\n\t"
  63882. "UMULL r6, r7, r8, r9\n\t"
  63883. "ADDS r4, r4, r6\n\t"
  63884. "ADCS r5, r5, r7\n\t"
  63885. "ADC r3, r3, #0x0\n\t"
  63886. /* A[7] * B[15] */
  63887. "LDR r8, [%[a], #28]\n\t"
  63888. "LDR r9, [%[b], #60]\n\t"
  63889. "UMULL r6, r7, r8, r9\n\t"
  63890. "ADDS r4, r4, r6\n\t"
  63891. "ADCS r5, r5, r7\n\t"
  63892. "ADC r3, r3, #0x0\n\t"
  63893. "STR r4, [%[r], #88]\n\t"
  63894. /* A[8] * B[15] */
  63895. "LDR r8, [%[a], #32]\n\t"
  63896. "UMULL r6, r7, r8, r9\n\t"
  63897. "ADDS r5, r5, r6\n\t"
  63898. "ADCS r3, r3, r7\n\t"
  63899. "MOV r4, #0x0\n\t"
  63900. "ADC r4, r4, #0x0\n\t"
  63901. /* A[9] * B[14] */
  63902. "LDR r8, [%[a], #36]\n\t"
  63903. "LDR r9, [%[b], #56]\n\t"
  63904. "UMULL r6, r7, r8, r9\n\t"
  63905. "ADDS r5, r5, r6\n\t"
  63906. "ADCS r3, r3, r7\n\t"
  63907. "ADC r4, r4, #0x0\n\t"
  63908. /* A[10] * B[13] */
  63909. "LDR r8, [%[a], #40]\n\t"
  63910. "LDR r9, [%[b], #52]\n\t"
  63911. "UMULL r6, r7, r8, r9\n\t"
  63912. "ADDS r5, r5, r6\n\t"
  63913. "ADCS r3, r3, r7\n\t"
  63914. "ADC r4, r4, #0x0\n\t"
  63915. /* A[11] * B[12] */
  63916. "LDR r9, [%[b], #48]\n\t"
  63917. "UMULL r6, r7, r11, r9\n\t"
  63918. "ADDS r5, r5, r6\n\t"
  63919. "ADCS r3, r3, r7\n\t"
  63920. "ADC r4, r4, #0x0\n\t"
  63921. /* A[12] * B[11] */
  63922. "LDR r8, [%[a], #48]\n\t"
  63923. "UMULL r6, r7, r8, r12\n\t"
  63924. "ADDS r5, r5, r6\n\t"
  63925. "ADCS r3, r3, r7\n\t"
  63926. "ADC r4, r4, #0x0\n\t"
  63927. /* A[13] * B[10] */
  63928. "LDR r8, [%[a], #52]\n\t"
  63929. "LDR r9, [%[b], #40]\n\t"
  63930. "UMULL r6, r7, r8, r9\n\t"
  63931. "ADDS r5, r5, r6\n\t"
  63932. "ADCS r3, r3, r7\n\t"
  63933. "ADC r4, r4, #0x0\n\t"
  63934. /* A[14] * B[9] */
  63935. "LDR r8, [%[a], #56]\n\t"
  63936. "LDR r9, [%[b], #36]\n\t"
  63937. "UMULL r6, r7, r8, r9\n\t"
  63938. "ADDS r5, r5, r6\n\t"
  63939. "ADCS r3, r3, r7\n\t"
  63940. "ADC r4, r4, #0x0\n\t"
  63941. /* A[15] * B[8] */
  63942. "LDR r8, [%[a], #60]\n\t"
  63943. "LDR r9, [%[b], #32]\n\t"
  63944. "UMULL r6, r7, r8, r9\n\t"
  63945. "ADDS r5, r5, r6\n\t"
  63946. "ADCS r3, r3, r7\n\t"
  63947. "ADC r4, r4, #0x0\n\t"
  63948. "STR r5, [%[r], #92]\n\t"
  63949. /* A[15] * B[9] */
  63950. "LDR r9, [%[b], #36]\n\t"
  63951. "UMULL r6, r7, r8, r9\n\t"
  63952. "ADDS r3, r3, r6\n\t"
  63953. "ADCS r4, r4, r7\n\t"
  63954. "MOV r5, #0x0\n\t"
  63955. "ADC r5, r5, #0x0\n\t"
  63956. /* A[14] * B[10] */
  63957. "LDR r8, [%[a], #56]\n\t"
  63958. "LDR r9, [%[b], #40]\n\t"
  63959. "UMULL r6, r7, r8, r9\n\t"
  63960. "ADDS r3, r3, r6\n\t"
  63961. "ADCS r4, r4, r7\n\t"
  63962. "ADC r5, r5, #0x0\n\t"
  63963. /* A[13] * B[11] */
  63964. "LDR r8, [%[a], #52]\n\t"
  63965. "UMULL r6, r7, r8, r12\n\t"
  63966. "ADDS r3, r3, r6\n\t"
  63967. "ADCS r4, r4, r7\n\t"
  63968. "ADC r5, r5, #0x0\n\t"
  63969. /* A[12] * B[12] */
  63970. "LDR r11, [%[a], #48]\n\t"
  63971. "LDR r12, [%[b], #48]\n\t"
  63972. "UMULL r6, r7, r11, r12\n\t"
  63973. "ADDS r3, r3, r6\n\t"
  63974. "ADCS r4, r4, r7\n\t"
  63975. "ADC r5, r5, #0x0\n\t"
  63976. /* A[11] * B[13] */
  63977. "LDR r8, [%[a], #44]\n\t"
  63978. "LDR r9, [%[b], #52]\n\t"
  63979. "UMULL r6, r7, r8, r9\n\t"
  63980. "ADDS r3, r3, r6\n\t"
  63981. "ADCS r4, r4, r7\n\t"
  63982. "ADC r5, r5, #0x0\n\t"
  63983. /* A[10] * B[14] */
  63984. "LDR r8, [%[a], #40]\n\t"
  63985. "LDR r9, [%[b], #56]\n\t"
  63986. "UMULL r6, r7, r8, r9\n\t"
  63987. "ADDS r3, r3, r6\n\t"
  63988. "ADCS r4, r4, r7\n\t"
  63989. "ADC r5, r5, #0x0\n\t"
  63990. /* A[9] * B[15] */
  63991. "LDR r8, [%[a], #36]\n\t"
  63992. "LDR r9, [%[b], #60]\n\t"
  63993. "UMULL r6, r7, r8, r9\n\t"
  63994. "ADDS r3, r3, r6\n\t"
  63995. "ADCS r4, r4, r7\n\t"
  63996. "ADC r5, r5, #0x0\n\t"
  63997. "STR r3, [%[r], #96]\n\t"
  63998. /* A[10] * B[15] */
  63999. "LDR r8, [%[a], #40]\n\t"
  64000. "UMULL r6, r7, r8, r9\n\t"
  64001. "ADDS r4, r4, r6\n\t"
  64002. "ADCS r5, r5, r7\n\t"
  64003. "MOV r3, #0x0\n\t"
  64004. "ADC r3, r3, #0x0\n\t"
  64005. /* A[11] * B[14] */
  64006. "LDR r8, [%[a], #44]\n\t"
  64007. "LDR r9, [%[b], #56]\n\t"
  64008. "UMULL r6, r7, r8, r9\n\t"
  64009. "ADDS r4, r4, r6\n\t"
  64010. "ADCS r5, r5, r7\n\t"
  64011. "ADC r3, r3, #0x0\n\t"
  64012. /* A[12] * B[13] */
  64013. "LDR r9, [%[b], #52]\n\t"
  64014. "UMULL r6, r7, r11, r9\n\t"
  64015. "ADDS r4, r4, r6\n\t"
  64016. "ADCS r5, r5, r7\n\t"
  64017. "ADC r3, r3, #0x0\n\t"
  64018. /* A[13] * B[12] */
  64019. "LDR r8, [%[a], #52]\n\t"
  64020. "UMULL r6, r7, r8, r12\n\t"
  64021. "ADDS r4, r4, r6\n\t"
  64022. "ADCS r5, r5, r7\n\t"
  64023. "ADC r3, r3, #0x0\n\t"
  64024. /* A[14] * B[11] */
  64025. "LDR r8, [%[a], #56]\n\t"
  64026. "LDR r9, [%[b], #44]\n\t"
  64027. "UMULL r6, r7, r8, r9\n\t"
  64028. "ADDS r4, r4, r6\n\t"
  64029. "ADCS r5, r5, r7\n\t"
  64030. "ADC r3, r3, #0x0\n\t"
  64031. /* A[15] * B[10] */
  64032. "LDR r8, [%[a], #60]\n\t"
  64033. "LDR r9, [%[b], #40]\n\t"
  64034. "UMULL r6, r7, r8, r9\n\t"
  64035. "ADDS r4, r4, r6\n\t"
  64036. "ADCS r5, r5, r7\n\t"
  64037. "ADC r3, r3, #0x0\n\t"
  64038. "STR r4, [%[r], #100]\n\t"
  64039. /* A[15] * B[11] */
  64040. "LDR r9, [%[b], #44]\n\t"
  64041. "UMULL r6, r7, r8, r9\n\t"
  64042. "ADDS r5, r5, r6\n\t"
  64043. "ADCS r3, r3, r7\n\t"
  64044. "MOV r4, #0x0\n\t"
  64045. "ADC r4, r4, #0x0\n\t"
  64046. /* A[14] * B[12] */
  64047. "LDR r8, [%[a], #56]\n\t"
  64048. "UMULL r6, r7, r8, r12\n\t"
  64049. "ADDS r5, r5, r6\n\t"
  64050. "ADCS r3, r3, r7\n\t"
  64051. "ADC r4, r4, #0x0\n\t"
  64052. /* A[13] * B[13] */
  64053. "LDR r11, [%[a], #52]\n\t"
  64054. "LDR r12, [%[b], #52]\n\t"
  64055. "UMULL r6, r7, r11, r12\n\t"
  64056. "ADDS r5, r5, r6\n\t"
  64057. "ADCS r3, r3, r7\n\t"
  64058. "ADC r4, r4, #0x0\n\t"
  64059. /* A[12] * B[14] */
  64060. "LDR r8, [%[a], #48]\n\t"
  64061. "LDR r9, [%[b], #56]\n\t"
  64062. "UMULL r6, r7, r8, r9\n\t"
  64063. "ADDS r5, r5, r6\n\t"
  64064. "ADCS r3, r3, r7\n\t"
  64065. "ADC r4, r4, #0x0\n\t"
  64066. /* A[11] * B[15] */
  64067. "LDR r8, [%[a], #44]\n\t"
  64068. "LDR r9, [%[b], #60]\n\t"
  64069. "UMULL r6, r7, r8, r9\n\t"
  64070. "ADDS r5, r5, r6\n\t"
  64071. "ADCS r3, r3, r7\n\t"
  64072. "ADC r4, r4, #0x0\n\t"
  64073. "STR r5, [%[r], #104]\n\t"
  64074. /* A[12] * B[15] */
  64075. "LDR r8, [%[a], #48]\n\t"
  64076. "UMULL r6, r7, r8, r9\n\t"
  64077. "ADDS r3, r3, r6\n\t"
  64078. "ADCS r4, r4, r7\n\t"
  64079. "MOV r5, #0x0\n\t"
  64080. "ADC r5, r5, #0x0\n\t"
  64081. /* A[13] * B[14] */
  64082. "LDR r9, [%[b], #56]\n\t"
  64083. "UMULL r6, r7, r11, r9\n\t"
  64084. "ADDS r3, r3, r6\n\t"
  64085. "ADCS r4, r4, r7\n\t"
  64086. "ADC r5, r5, #0x0\n\t"
  64087. /* A[14] * B[13] */
  64088. "LDR r8, [%[a], #56]\n\t"
  64089. "UMULL r6, r7, r8, r12\n\t"
  64090. "ADDS r3, r3, r6\n\t"
  64091. "ADCS r4, r4, r7\n\t"
  64092. "ADC r5, r5, #0x0\n\t"
  64093. /* A[15] * B[12] */
  64094. "LDR r8, [%[a], #60]\n\t"
  64095. "LDR r9, [%[b], #48]\n\t"
  64096. "UMULL r6, r7, r8, r9\n\t"
  64097. "ADDS r3, r3, r6\n\t"
  64098. "ADCS r4, r4, r7\n\t"
  64099. "ADC r5, r5, #0x0\n\t"
  64100. "STR r3, [%[r], #108]\n\t"
  64101. /* A[15] * B[13] */
  64102. "UMULL r6, r7, r8, r12\n\t"
  64103. "ADDS r4, r4, r6\n\t"
  64104. "ADCS r5, r5, r7\n\t"
  64105. "MOV r3, #0x0\n\t"
  64106. "ADC r3, r3, #0x0\n\t"
  64107. /* A[14] * B[14] */
  64108. "LDR r11, [%[a], #56]\n\t"
  64109. "LDR r12, [%[b], #56]\n\t"
  64110. "UMULL r6, r7, r11, r12\n\t"
  64111. "ADDS r4, r4, r6\n\t"
  64112. "ADCS r5, r5, r7\n\t"
  64113. "ADC r3, r3, #0x0\n\t"
  64114. /* A[13] * B[15] */
  64115. "LDR r8, [%[a], #52]\n\t"
  64116. "LDR r9, [%[b], #60]\n\t"
  64117. "UMULL r6, r7, r8, r9\n\t"
  64118. "ADDS r4, r4, r6\n\t"
  64119. "ADCS r5, r5, r7\n\t"
  64120. "ADC r3, r3, #0x0\n\t"
  64121. "STR r4, [%[r], #112]\n\t"
  64122. /* A[14] * B[15] */
  64123. "UMULL r6, r7, r11, r9\n\t"
  64124. "ADDS r5, r5, r6\n\t"
  64125. "ADCS r3, r3, r7\n\t"
  64126. "MOV r4, #0x0\n\t"
  64127. "ADC r4, r4, #0x0\n\t"
  64128. /* A[15] * B[14] */
  64129. "LDR r8, [%[a], #60]\n\t"
  64130. "UMULL r6, r7, r8, r12\n\t"
  64131. "ADDS r5, r5, r6\n\t"
  64132. "ADCS r3, r3, r7\n\t"
  64133. "ADC r4, r4, #0x0\n\t"
  64134. "STR r5, [%[r], #116]\n\t"
  64135. /* A[15] * B[15] */
  64136. "UMLAL r3, r4, r8, r9\n\t"
  64137. "STR r3, [%[r], #120]\n\t"
  64138. "STR r4, [%[r], #124]\n\t"
  64139. "LDM sp!, {r3, r4, r5, r6}\n\t"
  64140. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  64141. "LDM sp!, {r3, r4, r5, r6}\n\t"
  64142. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  64143. "LDM sp!, {r3, r4, r5, r6}\n\t"
  64144. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  64145. "LDM sp!, {r3, r4, r5, r6}\n\t"
  64146. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  64147. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  64148. :
  64149. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r11", "r12", "cc"
  64150. );
  64151. }
  64152. /* Square a and put result in r. (r = a * a)
  64153. *
  64154. * r A single precision integer.
  64155. * a A single precision integer.
  64156. */
  64157. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  64158. static void sp_1024_sqr_16(sp_digit* r_p, const sp_digit* a_p)
  64159. #else
  64160. static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a)
  64161. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  64162. {
  64163. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  64164. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  64165. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  64166. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  64167. __asm__ __volatile__ (
  64168. "SUB sp, sp, #0x40\n\t"
  64169. /* A[0] * A[0] */
  64170. "LDR r10, [%[a]]\n\t"
  64171. "UMULL r8, r3, r10, r10\n\t"
  64172. "MOV r4, #0x0\n\t"
  64173. "STR r8, [sp]\n\t"
  64174. /* A[0] * A[1] */
  64175. "LDR r10, [%[a], #4]\n\t"
  64176. "LDR r12, [%[a]]\n\t"
  64177. "UMULL r8, r9, r10, r12\n\t"
  64178. "ADDS r3, r3, r8\n\t"
  64179. "ADCS r4, r4, r9\n\t"
  64180. "MOV r2, #0x0\n\t"
  64181. "ADC r2, r2, #0x0\n\t"
  64182. "ADDS r3, r3, r8\n\t"
  64183. "ADCS r4, r4, r9\n\t"
  64184. "MOV r2, #0x0\n\t"
  64185. "ADC r2, r2, #0x0\n\t"
  64186. "STR r3, [sp, #4]\n\t"
  64187. /* A[0] * A[2] */
  64188. "LDR r10, [%[a], #8]\n\t"
  64189. "LDR r12, [%[a]]\n\t"
  64190. "UMULL r8, r9, r10, r12\n\t"
  64191. "ADDS r4, r4, r8\n\t"
  64192. "ADCS r2, r2, r9\n\t"
  64193. "MOV r3, #0x0\n\t"
  64194. "ADC r3, r3, #0x0\n\t"
  64195. "ADDS r4, r4, r8\n\t"
  64196. "ADCS r2, r2, r9\n\t"
  64197. "MOV r3, #0x0\n\t"
  64198. "ADC r3, r3, #0x0\n\t"
  64199. /* A[1] * A[1] */
  64200. "LDR r10, [%[a], #4]\n\t"
  64201. "UMULL r8, r9, r10, r10\n\t"
  64202. "ADDS r4, r4, r8\n\t"
  64203. "ADCS r2, r2, r9\n\t"
  64204. "ADC r3, r3, #0x0\n\t"
  64205. "STR r4, [sp, #8]\n\t"
  64206. /* A[0] * A[3] */
  64207. "LDR r10, [%[a], #12]\n\t"
  64208. "LDR r12, [%[a]]\n\t"
  64209. "UMULL r8, r9, r10, r12\n\t"
  64210. "ADDS r2, r2, r8\n\t"
  64211. "ADCS r3, r3, r9\n\t"
  64212. "MOV r4, #0x0\n\t"
  64213. "ADC r4, r4, #0x0\n\t"
  64214. "ADDS r2, r2, r8\n\t"
  64215. "ADCS r3, r3, r9\n\t"
  64216. "MOV r4, #0x0\n\t"
  64217. "ADC r4, r4, #0x0\n\t"
  64218. /* A[1] * A[2] */
  64219. "LDR r10, [%[a], #8]\n\t"
  64220. "LDR r12, [%[a], #4]\n\t"
  64221. "UMULL r8, r9, r10, r12\n\t"
  64222. "ADDS r2, r2, r8\n\t"
  64223. "ADCS r3, r3, r9\n\t"
  64224. "ADC r4, r4, #0x0\n\t"
  64225. "ADDS r2, r2, r8\n\t"
  64226. "ADCS r3, r3, r9\n\t"
  64227. "ADC r4, r4, #0x0\n\t"
  64228. "STR r2, [sp, #12]\n\t"
  64229. /* A[0] * A[4] */
  64230. "LDR r10, [%[a], #16]\n\t"
  64231. "LDR r12, [%[a]]\n\t"
  64232. "UMULL r8, r9, r10, r12\n\t"
  64233. "ADDS r3, r3, r8\n\t"
  64234. "ADCS r4, r4, r9\n\t"
  64235. "MOV r2, #0x0\n\t"
  64236. "ADC r2, r2, #0x0\n\t"
  64237. "ADDS r3, r3, r8\n\t"
  64238. "ADCS r4, r4, r9\n\t"
  64239. "MOV r2, #0x0\n\t"
  64240. "ADC r2, r2, #0x0\n\t"
  64241. /* A[1] * A[3] */
  64242. "LDR r10, [%[a], #12]\n\t"
  64243. "LDR r12, [%[a], #4]\n\t"
  64244. "UMULL r8, r9, r10, r12\n\t"
  64245. "ADDS r3, r3, r8\n\t"
  64246. "ADCS r4, r4, r9\n\t"
  64247. "ADC r2, r2, #0x0\n\t"
  64248. "ADDS r3, r3, r8\n\t"
  64249. "ADCS r4, r4, r9\n\t"
  64250. "ADC r2, r2, #0x0\n\t"
  64251. /* A[2] * A[2] */
  64252. "LDR r10, [%[a], #8]\n\t"
  64253. "UMULL r8, r9, r10, r10\n\t"
  64254. "ADDS r3, r3, r8\n\t"
  64255. "ADCS r4, r4, r9\n\t"
  64256. "ADC r2, r2, #0x0\n\t"
  64257. "STR r3, [sp, #16]\n\t"
  64258. /* A[0] * A[5] */
  64259. "LDR r10, [%[a], #20]\n\t"
  64260. "LDR r12, [%[a]]\n\t"
  64261. "UMULL r5, r6, r10, r12\n\t"
  64262. "MOV r3, #0x0\n\t"
  64263. "MOV r7, #0x0\n\t"
  64264. /* A[1] * A[4] */
  64265. "LDR r10, [%[a], #16]\n\t"
  64266. "LDR r12, [%[a], #4]\n\t"
  64267. "UMULL r8, r9, r10, r12\n\t"
  64268. "ADDS r5, r5, r8\n\t"
  64269. "ADCS r6, r6, r9\n\t"
  64270. "ADC r7, r7, #0x0\n\t"
  64271. /* A[2] * A[3] */
  64272. "LDR r10, [%[a], #12]\n\t"
  64273. "LDR r12, [%[a], #8]\n\t"
  64274. "UMULL r8, r9, r10, r12\n\t"
  64275. "ADDS r5, r5, r8\n\t"
  64276. "ADCS r6, r6, r9\n\t"
  64277. "ADC r7, r7, #0x0\n\t"
  64278. "ADDS r5, r5, r5\n\t"
  64279. "ADCS r6, r6, r6\n\t"
  64280. "ADC r7, r7, r7\n\t"
  64281. "ADDS r4, r4, r5\n\t"
  64282. "ADCS r2, r2, r6\n\t"
  64283. "ADC r3, r3, r7\n\t"
  64284. "STR r4, [sp, #20]\n\t"
  64285. /* A[0] * A[6] */
  64286. "LDR r10, [%[a], #24]\n\t"
  64287. "LDR r12, [%[a]]\n\t"
  64288. "UMULL r5, r6, r10, r12\n\t"
  64289. "MOV r4, #0x0\n\t"
  64290. "MOV r7, #0x0\n\t"
  64291. /* A[1] * A[5] */
  64292. "LDR r10, [%[a], #20]\n\t"
  64293. "LDR r12, [%[a], #4]\n\t"
  64294. "UMULL r8, r9, r10, r12\n\t"
  64295. "ADDS r5, r5, r8\n\t"
  64296. "ADCS r6, r6, r9\n\t"
  64297. "ADC r7, r7, #0x0\n\t"
  64298. /* A[2] * A[4] */
  64299. "LDR r10, [%[a], #16]\n\t"
  64300. "LDR r12, [%[a], #8]\n\t"
  64301. "UMULL r8, r9, r10, r12\n\t"
  64302. "ADDS r5, r5, r8\n\t"
  64303. "ADCS r6, r6, r9\n\t"
  64304. "ADC r7, r7, #0x0\n\t"
  64305. /* A[3] * A[3] */
  64306. "LDR r10, [%[a], #12]\n\t"
  64307. "UMULL r8, r9, r10, r10\n\t"
  64308. "ADDS r5, r5, r5\n\t"
  64309. "ADCS r6, r6, r6\n\t"
  64310. "ADC r7, r7, r7\n\t"
  64311. "ADDS r2, r2, r8\n\t"
  64312. "ADCS r3, r3, r9\n\t"
  64313. "ADC r4, r4, #0x0\n\t"
  64314. "ADDS r2, r2, r5\n\t"
  64315. "ADCS r3, r3, r6\n\t"
  64316. "ADC r4, r4, r7\n\t"
  64317. "STR r2, [sp, #24]\n\t"
  64318. /* A[0] * A[7] */
  64319. "LDR r10, [%[a], #28]\n\t"
  64320. "LDR r12, [%[a]]\n\t"
  64321. "UMULL r5, r6, r10, r12\n\t"
  64322. "MOV r2, #0x0\n\t"
  64323. "MOV r7, #0x0\n\t"
  64324. /* A[1] * A[6] */
  64325. "LDR r10, [%[a], #24]\n\t"
  64326. "LDR r12, [%[a], #4]\n\t"
  64327. "UMULL r8, r9, r10, r12\n\t"
  64328. "ADDS r5, r5, r8\n\t"
  64329. "ADCS r6, r6, r9\n\t"
  64330. "ADC r7, r7, #0x0\n\t"
  64331. /* A[2] * A[5] */
  64332. "LDR r10, [%[a], #20]\n\t"
  64333. "LDR r12, [%[a], #8]\n\t"
  64334. "UMULL r8, r9, r10, r12\n\t"
  64335. "ADDS r5, r5, r8\n\t"
  64336. "ADCS r6, r6, r9\n\t"
  64337. "ADC r7, r7, #0x0\n\t"
  64338. /* A[3] * A[4] */
  64339. "LDR r10, [%[a], #16]\n\t"
  64340. "LDR r12, [%[a], #12]\n\t"
  64341. "UMULL r8, r9, r10, r12\n\t"
  64342. "ADDS r5, r5, r8\n\t"
  64343. "ADCS r6, r6, r9\n\t"
  64344. "ADC r7, r7, #0x0\n\t"
  64345. "ADDS r5, r5, r5\n\t"
  64346. "ADCS r6, r6, r6\n\t"
  64347. "ADC r7, r7, r7\n\t"
  64348. "ADDS r3, r3, r5\n\t"
  64349. "ADCS r4, r4, r6\n\t"
  64350. "ADC r2, r2, r7\n\t"
  64351. "STR r3, [sp, #28]\n\t"
  64352. /* A[0] * A[8] */
  64353. "LDR r10, [%[a], #32]\n\t"
  64354. "LDR r12, [%[a]]\n\t"
  64355. "UMULL r5, r6, r10, r12\n\t"
  64356. "MOV r3, #0x0\n\t"
  64357. "MOV r7, #0x0\n\t"
  64358. /* A[1] * A[7] */
  64359. "LDR r10, [%[a], #28]\n\t"
  64360. "LDR r12, [%[a], #4]\n\t"
  64361. "UMULL r8, r9, r10, r12\n\t"
  64362. "ADDS r5, r5, r8\n\t"
  64363. "ADCS r6, r6, r9\n\t"
  64364. "ADC r7, r7, #0x0\n\t"
  64365. /* A[2] * A[6] */
  64366. "LDR r10, [%[a], #24]\n\t"
  64367. "LDR r12, [%[a], #8]\n\t"
  64368. "UMULL r8, r9, r10, r12\n\t"
  64369. "ADDS r5, r5, r8\n\t"
  64370. "ADCS r6, r6, r9\n\t"
  64371. "ADC r7, r7, #0x0\n\t"
  64372. /* A[3] * A[5] */
  64373. "LDR r10, [%[a], #20]\n\t"
  64374. "LDR r12, [%[a], #12]\n\t"
  64375. "UMULL r8, r9, r10, r12\n\t"
  64376. "ADDS r5, r5, r8\n\t"
  64377. "ADCS r6, r6, r9\n\t"
  64378. "ADC r7, r7, #0x0\n\t"
  64379. /* A[4] * A[4] */
  64380. "LDR r10, [%[a], #16]\n\t"
  64381. "UMULL r8, r9, r10, r10\n\t"
  64382. "ADDS r5, r5, r5\n\t"
  64383. "ADCS r6, r6, r6\n\t"
  64384. "ADC r7, r7, r7\n\t"
  64385. "ADDS r4, r4, r8\n\t"
  64386. "ADCS r2, r2, r9\n\t"
  64387. "ADC r3, r3, #0x0\n\t"
  64388. "ADDS r4, r4, r5\n\t"
  64389. "ADCS r2, r2, r6\n\t"
  64390. "ADC r3, r3, r7\n\t"
  64391. "STR r4, [sp, #32]\n\t"
  64392. /* A[0] * A[9] */
  64393. "LDR r10, [%[a], #36]\n\t"
  64394. "LDR r12, [%[a]]\n\t"
  64395. "UMULL r5, r6, r10, r12\n\t"
  64396. "MOV r4, #0x0\n\t"
  64397. "MOV r7, #0x0\n\t"
  64398. /* A[1] * A[8] */
  64399. "LDR r10, [%[a], #32]\n\t"
  64400. "LDR r12, [%[a], #4]\n\t"
  64401. "UMULL r8, r9, r10, r12\n\t"
  64402. "ADDS r5, r5, r8\n\t"
  64403. "ADCS r6, r6, r9\n\t"
  64404. "ADC r7, r7, #0x0\n\t"
  64405. /* A[2] * A[7] */
  64406. "LDR r10, [%[a], #28]\n\t"
  64407. "LDR r12, [%[a], #8]\n\t"
  64408. "UMULL r8, r9, r10, r12\n\t"
  64409. "ADDS r5, r5, r8\n\t"
  64410. "ADCS r6, r6, r9\n\t"
  64411. "ADC r7, r7, #0x0\n\t"
  64412. /* A[3] * A[6] */
  64413. "LDR r10, [%[a], #24]\n\t"
  64414. "LDR r12, [%[a], #12]\n\t"
  64415. "UMULL r8, r9, r10, r12\n\t"
  64416. "ADDS r5, r5, r8\n\t"
  64417. "ADCS r6, r6, r9\n\t"
  64418. "ADC r7, r7, #0x0\n\t"
  64419. /* A[4] * A[5] */
  64420. "LDR r10, [%[a], #20]\n\t"
  64421. "LDR r12, [%[a], #16]\n\t"
  64422. "UMULL r8, r9, r10, r12\n\t"
  64423. "ADDS r5, r5, r8\n\t"
  64424. "ADCS r6, r6, r9\n\t"
  64425. "ADC r7, r7, #0x0\n\t"
  64426. "ADDS r5, r5, r5\n\t"
  64427. "ADCS r6, r6, r6\n\t"
  64428. "ADC r7, r7, r7\n\t"
  64429. "ADDS r2, r2, r5\n\t"
  64430. "ADCS r3, r3, r6\n\t"
  64431. "ADC r4, r4, r7\n\t"
  64432. "STR r2, [sp, #36]\n\t"
  64433. /* A[0] * A[10] */
  64434. "LDR r10, [%[a], #40]\n\t"
  64435. "LDR r12, [%[a]]\n\t"
  64436. "UMULL r5, r6, r10, r12\n\t"
  64437. "MOV r2, #0x0\n\t"
  64438. "MOV r7, #0x0\n\t"
  64439. /* A[1] * A[9] */
  64440. "LDR r10, [%[a], #36]\n\t"
  64441. "LDR r12, [%[a], #4]\n\t"
  64442. "UMULL r8, r9, r10, r12\n\t"
  64443. "ADDS r5, r5, r8\n\t"
  64444. "ADCS r6, r6, r9\n\t"
  64445. "ADC r7, r7, #0x0\n\t"
  64446. /* A[2] * A[8] */
  64447. "LDR r10, [%[a], #32]\n\t"
  64448. "LDR r12, [%[a], #8]\n\t"
  64449. "UMULL r8, r9, r10, r12\n\t"
  64450. "ADDS r5, r5, r8\n\t"
  64451. "ADCS r6, r6, r9\n\t"
  64452. "ADC r7, r7, #0x0\n\t"
  64453. /* A[3] * A[7] */
  64454. "LDR r10, [%[a], #28]\n\t"
  64455. "LDR r12, [%[a], #12]\n\t"
  64456. "UMULL r8, r9, r10, r12\n\t"
  64457. "ADDS r5, r5, r8\n\t"
  64458. "ADCS r6, r6, r9\n\t"
  64459. "ADC r7, r7, #0x0\n\t"
  64460. /* A[4] * A[6] */
  64461. "LDR r10, [%[a], #24]\n\t"
  64462. "LDR r12, [%[a], #16]\n\t"
  64463. "UMULL r8, r9, r10, r12\n\t"
  64464. "ADDS r5, r5, r8\n\t"
  64465. "ADCS r6, r6, r9\n\t"
  64466. "ADC r7, r7, #0x0\n\t"
  64467. /* A[5] * A[5] */
  64468. "LDR r10, [%[a], #20]\n\t"
  64469. "UMULL r8, r9, r10, r10\n\t"
  64470. "ADDS r5, r5, r5\n\t"
  64471. "ADCS r6, r6, r6\n\t"
  64472. "ADC r7, r7, r7\n\t"
  64473. "ADDS r3, r3, r8\n\t"
  64474. "ADCS r4, r4, r9\n\t"
  64475. "ADC r2, r2, #0x0\n\t"
  64476. "ADDS r3, r3, r5\n\t"
  64477. "ADCS r4, r4, r6\n\t"
  64478. "ADC r2, r2, r7\n\t"
  64479. "STR r3, [sp, #40]\n\t"
  64480. /* A[0] * A[11] */
  64481. "LDR r10, [%[a], #44]\n\t"
  64482. "LDR r12, [%[a]]\n\t"
  64483. "UMULL r5, r6, r10, r12\n\t"
  64484. "MOV r3, #0x0\n\t"
  64485. "MOV r7, #0x0\n\t"
  64486. /* A[1] * A[10] */
  64487. "LDR r10, [%[a], #40]\n\t"
  64488. "LDR r12, [%[a], #4]\n\t"
  64489. "UMULL r8, r9, r10, r12\n\t"
  64490. "ADDS r5, r5, r8\n\t"
  64491. "ADCS r6, r6, r9\n\t"
  64492. "ADC r7, r7, #0x0\n\t"
  64493. /* A[2] * A[9] */
  64494. "LDR r10, [%[a], #36]\n\t"
  64495. "LDR r12, [%[a], #8]\n\t"
  64496. "UMULL r8, r9, r10, r12\n\t"
  64497. "ADDS r5, r5, r8\n\t"
  64498. "ADCS r6, r6, r9\n\t"
  64499. "ADC r7, r7, #0x0\n\t"
  64500. /* A[3] * A[8] */
  64501. "LDR r10, [%[a], #32]\n\t"
  64502. "LDR r12, [%[a], #12]\n\t"
  64503. "UMULL r8, r9, r10, r12\n\t"
  64504. "ADDS r5, r5, r8\n\t"
  64505. "ADCS r6, r6, r9\n\t"
  64506. "ADC r7, r7, #0x0\n\t"
  64507. /* A[4] * A[7] */
  64508. "LDR r10, [%[a], #28]\n\t"
  64509. "LDR r12, [%[a], #16]\n\t"
  64510. "UMULL r8, r9, r10, r12\n\t"
  64511. "ADDS r5, r5, r8\n\t"
  64512. "ADCS r6, r6, r9\n\t"
  64513. "ADC r7, r7, #0x0\n\t"
  64514. /* A[5] * A[6] */
  64515. "LDR r10, [%[a], #24]\n\t"
  64516. "LDR r12, [%[a], #20]\n\t"
  64517. "UMULL r8, r9, r10, r12\n\t"
  64518. "ADDS r5, r5, r8\n\t"
  64519. "ADCS r6, r6, r9\n\t"
  64520. "ADC r7, r7, #0x0\n\t"
  64521. "ADDS r5, r5, r5\n\t"
  64522. "ADCS r6, r6, r6\n\t"
  64523. "ADC r7, r7, r7\n\t"
  64524. "ADDS r4, r4, r5\n\t"
  64525. "ADCS r2, r2, r6\n\t"
  64526. "ADC r3, r3, r7\n\t"
  64527. "STR r4, [sp, #44]\n\t"
  64528. /* A[0] * A[12] */
  64529. "LDR r10, [%[a], #48]\n\t"
  64530. "LDR r12, [%[a]]\n\t"
  64531. "UMULL r5, r6, r10, r12\n\t"
  64532. "MOV r4, #0x0\n\t"
  64533. "MOV r7, #0x0\n\t"
  64534. /* A[1] * A[11] */
  64535. "LDR r10, [%[a], #44]\n\t"
  64536. "LDR r12, [%[a], #4]\n\t"
  64537. "UMULL r8, r9, r10, r12\n\t"
  64538. "ADDS r5, r5, r8\n\t"
  64539. "ADCS r6, r6, r9\n\t"
  64540. "ADC r7, r7, #0x0\n\t"
  64541. /* A[2] * A[10] */
  64542. "LDR r10, [%[a], #40]\n\t"
  64543. "LDR r12, [%[a], #8]\n\t"
  64544. "UMULL r8, r9, r10, r12\n\t"
  64545. "ADDS r5, r5, r8\n\t"
  64546. "ADCS r6, r6, r9\n\t"
  64547. "ADC r7, r7, #0x0\n\t"
  64548. /* A[3] * A[9] */
  64549. "LDR r10, [%[a], #36]\n\t"
  64550. "LDR r12, [%[a], #12]\n\t"
  64551. "UMULL r8, r9, r10, r12\n\t"
  64552. "ADDS r5, r5, r8\n\t"
  64553. "ADCS r6, r6, r9\n\t"
  64554. "ADC r7, r7, #0x0\n\t"
  64555. /* A[4] * A[8] */
  64556. "LDR r10, [%[a], #32]\n\t"
  64557. "LDR r12, [%[a], #16]\n\t"
  64558. "UMULL r8, r9, r10, r12\n\t"
  64559. "ADDS r5, r5, r8\n\t"
  64560. "ADCS r6, r6, r9\n\t"
  64561. "ADC r7, r7, #0x0\n\t"
  64562. /* A[5] * A[7] */
  64563. "LDR r10, [%[a], #28]\n\t"
  64564. "LDR r12, [%[a], #20]\n\t"
  64565. "UMULL r8, r9, r10, r12\n\t"
  64566. "ADDS r5, r5, r8\n\t"
  64567. "ADCS r6, r6, r9\n\t"
  64568. "ADC r7, r7, #0x0\n\t"
  64569. /* A[6] * A[6] */
  64570. "LDR r10, [%[a], #24]\n\t"
  64571. "UMULL r8, r9, r10, r10\n\t"
  64572. "ADDS r5, r5, r5\n\t"
  64573. "ADCS r6, r6, r6\n\t"
  64574. "ADC r7, r7, r7\n\t"
  64575. "ADDS r2, r2, r8\n\t"
  64576. "ADCS r3, r3, r9\n\t"
  64577. "ADC r4, r4, #0x0\n\t"
  64578. "ADDS r2, r2, r5\n\t"
  64579. "ADCS r3, r3, r6\n\t"
  64580. "ADC r4, r4, r7\n\t"
  64581. "STR r2, [sp, #48]\n\t"
  64582. /* A[0] * A[13] */
  64583. "LDR r10, [%[a], #52]\n\t"
  64584. "LDR r12, [%[a]]\n\t"
  64585. "UMULL r5, r6, r10, r12\n\t"
  64586. "MOV r2, #0x0\n\t"
  64587. "MOV r7, #0x0\n\t"
  64588. /* A[1] * A[12] */
  64589. "LDR r10, [%[a], #48]\n\t"
  64590. "LDR r12, [%[a], #4]\n\t"
  64591. "UMULL r8, r9, r10, r12\n\t"
  64592. "ADDS r5, r5, r8\n\t"
  64593. "ADCS r6, r6, r9\n\t"
  64594. "ADC r7, r7, #0x0\n\t"
  64595. /* A[2] * A[11] */
  64596. "LDR r10, [%[a], #44]\n\t"
  64597. "LDR r12, [%[a], #8]\n\t"
  64598. "UMULL r8, r9, r10, r12\n\t"
  64599. "ADDS r5, r5, r8\n\t"
  64600. "ADCS r6, r6, r9\n\t"
  64601. "ADC r7, r7, #0x0\n\t"
  64602. /* A[3] * A[10] */
  64603. "LDR r10, [%[a], #40]\n\t"
  64604. "LDR r12, [%[a], #12]\n\t"
  64605. "UMULL r8, r9, r10, r12\n\t"
  64606. "ADDS r5, r5, r8\n\t"
  64607. "ADCS r6, r6, r9\n\t"
  64608. "ADC r7, r7, #0x0\n\t"
  64609. /* A[4] * A[9] */
  64610. "LDR r10, [%[a], #36]\n\t"
  64611. "LDR r12, [%[a], #16]\n\t"
  64612. "UMULL r8, r9, r10, r12\n\t"
  64613. "ADDS r5, r5, r8\n\t"
  64614. "ADCS r6, r6, r9\n\t"
  64615. "ADC r7, r7, #0x0\n\t"
  64616. /* A[5] * A[8] */
  64617. "LDR r10, [%[a], #32]\n\t"
  64618. "LDR r12, [%[a], #20]\n\t"
  64619. "UMULL r8, r9, r10, r12\n\t"
  64620. "ADDS r5, r5, r8\n\t"
  64621. "ADCS r6, r6, r9\n\t"
  64622. "ADC r7, r7, #0x0\n\t"
  64623. /* A[6] * A[7] */
  64624. "LDR r10, [%[a], #28]\n\t"
  64625. "LDR r12, [%[a], #24]\n\t"
  64626. "UMULL r8, r9, r10, r12\n\t"
  64627. "ADDS r5, r5, r8\n\t"
  64628. "ADCS r6, r6, r9\n\t"
  64629. "ADC r7, r7, #0x0\n\t"
  64630. "ADDS r5, r5, r5\n\t"
  64631. "ADCS r6, r6, r6\n\t"
  64632. "ADC r7, r7, r7\n\t"
  64633. "ADDS r3, r3, r5\n\t"
  64634. "ADCS r4, r4, r6\n\t"
  64635. "ADC r2, r2, r7\n\t"
  64636. "STR r3, [sp, #52]\n\t"
  64637. /* A[0] * A[14] */
  64638. "LDR r10, [%[a], #56]\n\t"
  64639. "LDR r12, [%[a]]\n\t"
  64640. "UMULL r5, r6, r10, r12\n\t"
  64641. "MOV r3, #0x0\n\t"
  64642. "MOV r7, #0x0\n\t"
  64643. /* A[1] * A[13] */
  64644. "LDR r10, [%[a], #52]\n\t"
  64645. "LDR r12, [%[a], #4]\n\t"
  64646. "UMULL r8, r9, r10, r12\n\t"
  64647. "ADDS r5, r5, r8\n\t"
  64648. "ADCS r6, r6, r9\n\t"
  64649. "ADC r7, r7, #0x0\n\t"
  64650. /* A[2] * A[12] */
  64651. "LDR r10, [%[a], #48]\n\t"
  64652. "LDR r12, [%[a], #8]\n\t"
  64653. "UMULL r8, r9, r10, r12\n\t"
  64654. "ADDS r5, r5, r8\n\t"
  64655. "ADCS r6, r6, r9\n\t"
  64656. "ADC r7, r7, #0x0\n\t"
  64657. /* A[3] * A[11] */
  64658. "LDR r10, [%[a], #44]\n\t"
  64659. "LDR r12, [%[a], #12]\n\t"
  64660. "UMULL r8, r9, r10, r12\n\t"
  64661. "ADDS r5, r5, r8\n\t"
  64662. "ADCS r6, r6, r9\n\t"
  64663. "ADC r7, r7, #0x0\n\t"
  64664. /* A[4] * A[10] */
  64665. "LDR r10, [%[a], #40]\n\t"
  64666. "LDR r12, [%[a], #16]\n\t"
  64667. "UMULL r8, r9, r10, r12\n\t"
  64668. "ADDS r5, r5, r8\n\t"
  64669. "ADCS r6, r6, r9\n\t"
  64670. "ADC r7, r7, #0x0\n\t"
  64671. /* A[5] * A[9] */
  64672. "LDR r10, [%[a], #36]\n\t"
  64673. "LDR r12, [%[a], #20]\n\t"
  64674. "UMULL r8, r9, r10, r12\n\t"
  64675. "ADDS r5, r5, r8\n\t"
  64676. "ADCS r6, r6, r9\n\t"
  64677. "ADC r7, r7, #0x0\n\t"
  64678. /* A[6] * A[8] */
  64679. "LDR r10, [%[a], #32]\n\t"
  64680. "LDR r12, [%[a], #24]\n\t"
  64681. "UMULL r8, r9, r10, r12\n\t"
  64682. "ADDS r5, r5, r8\n\t"
  64683. "ADCS r6, r6, r9\n\t"
  64684. "ADC r7, r7, #0x0\n\t"
  64685. /* A[7] * A[7] */
  64686. "LDR r10, [%[a], #28]\n\t"
  64687. "UMULL r8, r9, r10, r10\n\t"
  64688. "ADDS r5, r5, r5\n\t"
  64689. "ADCS r6, r6, r6\n\t"
  64690. "ADC r7, r7, r7\n\t"
  64691. "ADDS r4, r4, r8\n\t"
  64692. "ADCS r2, r2, r9\n\t"
  64693. "ADC r3, r3, #0x0\n\t"
  64694. "ADDS r4, r4, r5\n\t"
  64695. "ADCS r2, r2, r6\n\t"
  64696. "ADC r3, r3, r7\n\t"
  64697. "STR r4, [sp, #56]\n\t"
  64698. /* A[0] * A[15] */
  64699. "LDR r10, [%[a], #60]\n\t"
  64700. "LDR r12, [%[a]]\n\t"
  64701. "UMULL r5, r6, r10, r12\n\t"
  64702. "MOV r4, #0x0\n\t"
  64703. "MOV r7, #0x0\n\t"
  64704. /* A[1] * A[14] */
  64705. "LDR r10, [%[a], #56]\n\t"
  64706. "LDR r12, [%[a], #4]\n\t"
  64707. "UMULL r8, r9, r10, r12\n\t"
  64708. "ADDS r5, r5, r8\n\t"
  64709. "ADCS r6, r6, r9\n\t"
  64710. "ADC r7, r7, #0x0\n\t"
  64711. /* A[2] * A[13] */
  64712. "LDR r10, [%[a], #52]\n\t"
  64713. "LDR r12, [%[a], #8]\n\t"
  64714. "UMULL r8, r9, r10, r12\n\t"
  64715. "ADDS r5, r5, r8\n\t"
  64716. "ADCS r6, r6, r9\n\t"
  64717. "ADC r7, r7, #0x0\n\t"
  64718. /* A[3] * A[12] */
  64719. "LDR r10, [%[a], #48]\n\t"
  64720. "LDR r12, [%[a], #12]\n\t"
  64721. "UMULL r8, r9, r10, r12\n\t"
  64722. "ADDS r5, r5, r8\n\t"
  64723. "ADCS r6, r6, r9\n\t"
  64724. "ADC r7, r7, #0x0\n\t"
  64725. /* A[4] * A[11] */
  64726. "LDR r10, [%[a], #44]\n\t"
  64727. "LDR r12, [%[a], #16]\n\t"
  64728. "UMULL r8, r9, r10, r12\n\t"
  64729. "ADDS r5, r5, r8\n\t"
  64730. "ADCS r6, r6, r9\n\t"
  64731. "ADC r7, r7, #0x0\n\t"
  64732. /* A[5] * A[10] */
  64733. "LDR r10, [%[a], #40]\n\t"
  64734. "LDR r12, [%[a], #20]\n\t"
  64735. "UMULL r8, r9, r10, r12\n\t"
  64736. "ADDS r5, r5, r8\n\t"
  64737. "ADCS r6, r6, r9\n\t"
  64738. "ADC r7, r7, #0x0\n\t"
  64739. /* A[6] * A[9] */
  64740. "LDR r10, [%[a], #36]\n\t"
  64741. "LDR r12, [%[a], #24]\n\t"
  64742. "UMULL r8, r9, r10, r12\n\t"
  64743. "ADDS r5, r5, r8\n\t"
  64744. "ADCS r6, r6, r9\n\t"
  64745. "ADC r7, r7, #0x0\n\t"
  64746. /* A[7] * A[8] */
  64747. "LDR r10, [%[a], #32]\n\t"
  64748. "LDR r12, [%[a], #28]\n\t"
  64749. "UMULL r8, r9, r10, r12\n\t"
  64750. "ADDS r5, r5, r8\n\t"
  64751. "ADCS r6, r6, r9\n\t"
  64752. "ADC r7, r7, #0x0\n\t"
  64753. "ADDS r5, r5, r5\n\t"
  64754. "ADCS r6, r6, r6\n\t"
  64755. "ADC r7, r7, r7\n\t"
  64756. "ADDS r2, r2, r5\n\t"
  64757. "ADCS r3, r3, r6\n\t"
  64758. "ADC r4, r4, r7\n\t"
  64759. "STR r2, [sp, #60]\n\t"
  64760. /* A[1] * A[15] */
  64761. "LDR r10, [%[a], #60]\n\t"
  64762. "LDR r12, [%[a], #4]\n\t"
  64763. "UMULL r5, r6, r10, r12\n\t"
  64764. "MOV r2, #0x0\n\t"
  64765. "MOV r7, #0x0\n\t"
  64766. /* A[2] * A[14] */
  64767. "LDR r10, [%[a], #56]\n\t"
  64768. "LDR r12, [%[a], #8]\n\t"
  64769. "UMULL r8, r9, r10, r12\n\t"
  64770. "ADDS r5, r5, r8\n\t"
  64771. "ADCS r6, r6, r9\n\t"
  64772. "ADC r7, r7, #0x0\n\t"
  64773. /* A[3] * A[13] */
  64774. "LDR r10, [%[a], #52]\n\t"
  64775. "LDR r12, [%[a], #12]\n\t"
  64776. "UMULL r8, r9, r10, r12\n\t"
  64777. "ADDS r5, r5, r8\n\t"
  64778. "ADCS r6, r6, r9\n\t"
  64779. "ADC r7, r7, #0x0\n\t"
  64780. /* A[4] * A[12] */
  64781. "LDR r10, [%[a], #48]\n\t"
  64782. "LDR r12, [%[a], #16]\n\t"
  64783. "UMULL r8, r9, r10, r12\n\t"
  64784. "ADDS r5, r5, r8\n\t"
  64785. "ADCS r6, r6, r9\n\t"
  64786. "ADC r7, r7, #0x0\n\t"
  64787. /* A[5] * A[11] */
  64788. "LDR r10, [%[a], #44]\n\t"
  64789. "LDR r12, [%[a], #20]\n\t"
  64790. "UMULL r8, r9, r10, r12\n\t"
  64791. "ADDS r5, r5, r8\n\t"
  64792. "ADCS r6, r6, r9\n\t"
  64793. "ADC r7, r7, #0x0\n\t"
  64794. /* A[6] * A[10] */
  64795. "LDR r10, [%[a], #40]\n\t"
  64796. "LDR r12, [%[a], #24]\n\t"
  64797. "UMULL r8, r9, r10, r12\n\t"
  64798. "ADDS r5, r5, r8\n\t"
  64799. "ADCS r6, r6, r9\n\t"
  64800. "ADC r7, r7, #0x0\n\t"
  64801. /* A[7] * A[9] */
  64802. "LDR r10, [%[a], #36]\n\t"
  64803. "LDR r12, [%[a], #28]\n\t"
  64804. "UMULL r8, r9, r10, r12\n\t"
  64805. "ADDS r5, r5, r8\n\t"
  64806. "ADCS r6, r6, r9\n\t"
  64807. "ADC r7, r7, #0x0\n\t"
  64808. /* A[8] * A[8] */
  64809. "LDR r10, [%[a], #32]\n\t"
  64810. "UMULL r8, r9, r10, r10\n\t"
  64811. "ADDS r5, r5, r5\n\t"
  64812. "ADCS r6, r6, r6\n\t"
  64813. "ADC r7, r7, r7\n\t"
  64814. "ADDS r3, r3, r8\n\t"
  64815. "ADCS r4, r4, r9\n\t"
  64816. "ADC r2, r2, #0x0\n\t"
  64817. "ADDS r3, r3, r5\n\t"
  64818. "ADCS r4, r4, r6\n\t"
  64819. "ADC r2, r2, r7\n\t"
  64820. "STR r3, [%[r], #64]\n\t"
  64821. /* A[2] * A[15] */
  64822. "LDR r10, [%[a], #60]\n\t"
  64823. "LDR r12, [%[a], #8]\n\t"
  64824. "UMULL r5, r6, r10, r12\n\t"
  64825. "MOV r3, #0x0\n\t"
  64826. "MOV r7, #0x0\n\t"
  64827. /* A[3] * A[14] */
  64828. "LDR r10, [%[a], #56]\n\t"
  64829. "LDR r12, [%[a], #12]\n\t"
  64830. "UMULL r8, r9, r10, r12\n\t"
  64831. "ADDS r5, r5, r8\n\t"
  64832. "ADCS r6, r6, r9\n\t"
  64833. "ADC r7, r7, #0x0\n\t"
  64834. /* A[4] * A[13] */
  64835. "LDR r10, [%[a], #52]\n\t"
  64836. "LDR r12, [%[a], #16]\n\t"
  64837. "UMULL r8, r9, r10, r12\n\t"
  64838. "ADDS r5, r5, r8\n\t"
  64839. "ADCS r6, r6, r9\n\t"
  64840. "ADC r7, r7, #0x0\n\t"
  64841. /* A[5] * A[12] */
  64842. "LDR r10, [%[a], #48]\n\t"
  64843. "LDR r12, [%[a], #20]\n\t"
  64844. "UMULL r8, r9, r10, r12\n\t"
  64845. "ADDS r5, r5, r8\n\t"
  64846. "ADCS r6, r6, r9\n\t"
  64847. "ADC r7, r7, #0x0\n\t"
  64848. /* A[6] * A[11] */
  64849. "LDR r10, [%[a], #44]\n\t"
  64850. "LDR r12, [%[a], #24]\n\t"
  64851. "UMULL r8, r9, r10, r12\n\t"
  64852. "ADDS r5, r5, r8\n\t"
  64853. "ADCS r6, r6, r9\n\t"
  64854. "ADC r7, r7, #0x0\n\t"
  64855. /* A[7] * A[10] */
  64856. "LDR r10, [%[a], #40]\n\t"
  64857. "LDR r12, [%[a], #28]\n\t"
  64858. "UMULL r8, r9, r10, r12\n\t"
  64859. "ADDS r5, r5, r8\n\t"
  64860. "ADCS r6, r6, r9\n\t"
  64861. "ADC r7, r7, #0x0\n\t"
  64862. /* A[8] * A[9] */
  64863. "LDR r10, [%[a], #36]\n\t"
  64864. "LDR r12, [%[a], #32]\n\t"
  64865. "UMULL r8, r9, r10, r12\n\t"
  64866. "ADDS r5, r5, r8\n\t"
  64867. "ADCS r6, r6, r9\n\t"
  64868. "ADC r7, r7, #0x0\n\t"
  64869. "ADDS r5, r5, r5\n\t"
  64870. "ADCS r6, r6, r6\n\t"
  64871. "ADC r7, r7, r7\n\t"
  64872. "ADDS r4, r4, r5\n\t"
  64873. "ADCS r2, r2, r6\n\t"
  64874. "ADC r3, r3, r7\n\t"
  64875. "STR r4, [%[r], #68]\n\t"
  64876. /* A[3] * A[15] */
  64877. "LDR r10, [%[a], #60]\n\t"
  64878. "LDR r12, [%[a], #12]\n\t"
  64879. "UMULL r5, r6, r10, r12\n\t"
  64880. "MOV r4, #0x0\n\t"
  64881. "MOV r7, #0x0\n\t"
  64882. /* A[4] * A[14] */
  64883. "LDR r10, [%[a], #56]\n\t"
  64884. "LDR r12, [%[a], #16]\n\t"
  64885. "UMULL r8, r9, r10, r12\n\t"
  64886. "ADDS r5, r5, r8\n\t"
  64887. "ADCS r6, r6, r9\n\t"
  64888. "ADC r7, r7, #0x0\n\t"
  64889. /* A[5] * A[13] */
  64890. "LDR r10, [%[a], #52]\n\t"
  64891. "LDR r12, [%[a], #20]\n\t"
  64892. "UMULL r8, r9, r10, r12\n\t"
  64893. "ADDS r5, r5, r8\n\t"
  64894. "ADCS r6, r6, r9\n\t"
  64895. "ADC r7, r7, #0x0\n\t"
  64896. /* A[6] * A[12] */
  64897. "LDR r10, [%[a], #48]\n\t"
  64898. "LDR r12, [%[a], #24]\n\t"
  64899. "UMULL r8, r9, r10, r12\n\t"
  64900. "ADDS r5, r5, r8\n\t"
  64901. "ADCS r6, r6, r9\n\t"
  64902. "ADC r7, r7, #0x0\n\t"
  64903. /* A[7] * A[11] */
  64904. "LDR r10, [%[a], #44]\n\t"
  64905. "LDR r12, [%[a], #28]\n\t"
  64906. "UMULL r8, r9, r10, r12\n\t"
  64907. "ADDS r5, r5, r8\n\t"
  64908. "ADCS r6, r6, r9\n\t"
  64909. "ADC r7, r7, #0x0\n\t"
  64910. /* A[8] * A[10] */
  64911. "LDR r10, [%[a], #40]\n\t"
  64912. "LDR r12, [%[a], #32]\n\t"
  64913. "UMULL r8, r9, r10, r12\n\t"
  64914. "ADDS r5, r5, r8\n\t"
  64915. "ADCS r6, r6, r9\n\t"
  64916. "ADC r7, r7, #0x0\n\t"
  64917. /* A[9] * A[9] */
  64918. "LDR r10, [%[a], #36]\n\t"
  64919. "UMULL r8, r9, r10, r10\n\t"
  64920. "ADDS r5, r5, r5\n\t"
  64921. "ADCS r6, r6, r6\n\t"
  64922. "ADC r7, r7, r7\n\t"
  64923. "ADDS r2, r2, r8\n\t"
  64924. "ADCS r3, r3, r9\n\t"
  64925. "ADC r4, r4, #0x0\n\t"
  64926. "ADDS r2, r2, r5\n\t"
  64927. "ADCS r3, r3, r6\n\t"
  64928. "ADC r4, r4, r7\n\t"
  64929. "STR r2, [%[r], #72]\n\t"
  64930. /* A[4] * A[15] */
  64931. "LDR r10, [%[a], #60]\n\t"
  64932. "LDR r12, [%[a], #16]\n\t"
  64933. "UMULL r5, r6, r10, r12\n\t"
  64934. "MOV r2, #0x0\n\t"
  64935. "MOV r7, #0x0\n\t"
  64936. /* A[5] * A[14] */
  64937. "LDR r10, [%[a], #56]\n\t"
  64938. "LDR r12, [%[a], #20]\n\t"
  64939. "UMULL r8, r9, r10, r12\n\t"
  64940. "ADDS r5, r5, r8\n\t"
  64941. "ADCS r6, r6, r9\n\t"
  64942. "ADC r7, r7, #0x0\n\t"
  64943. /* A[6] * A[13] */
  64944. "LDR r10, [%[a], #52]\n\t"
  64945. "LDR r12, [%[a], #24]\n\t"
  64946. "UMULL r8, r9, r10, r12\n\t"
  64947. "ADDS r5, r5, r8\n\t"
  64948. "ADCS r6, r6, r9\n\t"
  64949. "ADC r7, r7, #0x0\n\t"
  64950. /* A[7] * A[12] */
  64951. "LDR r10, [%[a], #48]\n\t"
  64952. "LDR r12, [%[a], #28]\n\t"
  64953. "UMULL r8, r9, r10, r12\n\t"
  64954. "ADDS r5, r5, r8\n\t"
  64955. "ADCS r6, r6, r9\n\t"
  64956. "ADC r7, r7, #0x0\n\t"
  64957. /* A[8] * A[11] */
  64958. "LDR r10, [%[a], #44]\n\t"
  64959. "LDR r12, [%[a], #32]\n\t"
  64960. "UMULL r8, r9, r10, r12\n\t"
  64961. "ADDS r5, r5, r8\n\t"
  64962. "ADCS r6, r6, r9\n\t"
  64963. "ADC r7, r7, #0x0\n\t"
  64964. /* A[9] * A[10] */
  64965. "LDR r10, [%[a], #40]\n\t"
  64966. "LDR r12, [%[a], #36]\n\t"
  64967. "UMULL r8, r9, r10, r12\n\t"
  64968. "ADDS r5, r5, r8\n\t"
  64969. "ADCS r6, r6, r9\n\t"
  64970. "ADC r7, r7, #0x0\n\t"
  64971. "ADDS r5, r5, r5\n\t"
  64972. "ADCS r6, r6, r6\n\t"
  64973. "ADC r7, r7, r7\n\t"
  64974. "ADDS r3, r3, r5\n\t"
  64975. "ADCS r4, r4, r6\n\t"
  64976. "ADC r2, r2, r7\n\t"
  64977. "STR r3, [%[r], #76]\n\t"
  64978. /* A[5] * A[15] */
  64979. "LDR r10, [%[a], #60]\n\t"
  64980. "LDR r12, [%[a], #20]\n\t"
  64981. "UMULL r5, r6, r10, r12\n\t"
  64982. "MOV r3, #0x0\n\t"
  64983. "MOV r7, #0x0\n\t"
  64984. /* A[6] * A[14] */
  64985. "LDR r10, [%[a], #56]\n\t"
  64986. "LDR r12, [%[a], #24]\n\t"
  64987. "UMULL r8, r9, r10, r12\n\t"
  64988. "ADDS r5, r5, r8\n\t"
  64989. "ADCS r6, r6, r9\n\t"
  64990. "ADC r7, r7, #0x0\n\t"
  64991. /* A[7] * A[13] */
  64992. "LDR r10, [%[a], #52]\n\t"
  64993. "LDR r12, [%[a], #28]\n\t"
  64994. "UMULL r8, r9, r10, r12\n\t"
  64995. "ADDS r5, r5, r8\n\t"
  64996. "ADCS r6, r6, r9\n\t"
  64997. "ADC r7, r7, #0x0\n\t"
  64998. /* A[8] * A[12] */
  64999. "LDR r10, [%[a], #48]\n\t"
  65000. "LDR r12, [%[a], #32]\n\t"
  65001. "UMULL r8, r9, r10, r12\n\t"
  65002. "ADDS r5, r5, r8\n\t"
  65003. "ADCS r6, r6, r9\n\t"
  65004. "ADC r7, r7, #0x0\n\t"
  65005. /* A[9] * A[11] */
  65006. "LDR r10, [%[a], #44]\n\t"
  65007. "LDR r12, [%[a], #36]\n\t"
  65008. "UMULL r8, r9, r10, r12\n\t"
  65009. "ADDS r5, r5, r8\n\t"
  65010. "ADCS r6, r6, r9\n\t"
  65011. "ADC r7, r7, #0x0\n\t"
  65012. /* A[10] * A[10] */
  65013. "LDR r10, [%[a], #40]\n\t"
  65014. "UMULL r8, r9, r10, r10\n\t"
  65015. "ADDS r5, r5, r5\n\t"
  65016. "ADCS r6, r6, r6\n\t"
  65017. "ADC r7, r7, r7\n\t"
  65018. "ADDS r4, r4, r8\n\t"
  65019. "ADCS r2, r2, r9\n\t"
  65020. "ADC r3, r3, #0x0\n\t"
  65021. "ADDS r4, r4, r5\n\t"
  65022. "ADCS r2, r2, r6\n\t"
  65023. "ADC r3, r3, r7\n\t"
  65024. "STR r4, [%[r], #80]\n\t"
  65025. /* A[6] * A[15] */
  65026. "LDR r10, [%[a], #60]\n\t"
  65027. "LDR r12, [%[a], #24]\n\t"
  65028. "UMULL r5, r6, r10, r12\n\t"
  65029. "MOV r4, #0x0\n\t"
  65030. "MOV r7, #0x0\n\t"
  65031. /* A[7] * A[14] */
  65032. "LDR r10, [%[a], #56]\n\t"
  65033. "LDR r12, [%[a], #28]\n\t"
  65034. "UMULL r8, r9, r10, r12\n\t"
  65035. "ADDS r5, r5, r8\n\t"
  65036. "ADCS r6, r6, r9\n\t"
  65037. "ADC r7, r7, #0x0\n\t"
  65038. /* A[8] * A[13] */
  65039. "LDR r10, [%[a], #52]\n\t"
  65040. "LDR r12, [%[a], #32]\n\t"
  65041. "UMULL r8, r9, r10, r12\n\t"
  65042. "ADDS r5, r5, r8\n\t"
  65043. "ADCS r6, r6, r9\n\t"
  65044. "ADC r7, r7, #0x0\n\t"
  65045. /* A[9] * A[12] */
  65046. "LDR r10, [%[a], #48]\n\t"
  65047. "LDR r12, [%[a], #36]\n\t"
  65048. "UMULL r8, r9, r10, r12\n\t"
  65049. "ADDS r5, r5, r8\n\t"
  65050. "ADCS r6, r6, r9\n\t"
  65051. "ADC r7, r7, #0x0\n\t"
  65052. /* A[10] * A[11] */
  65053. "LDR r10, [%[a], #44]\n\t"
  65054. "LDR r12, [%[a], #40]\n\t"
  65055. "UMULL r8, r9, r10, r12\n\t"
  65056. "ADDS r5, r5, r8\n\t"
  65057. "ADCS r6, r6, r9\n\t"
  65058. "ADC r7, r7, #0x0\n\t"
  65059. "ADDS r5, r5, r5\n\t"
  65060. "ADCS r6, r6, r6\n\t"
  65061. "ADC r7, r7, r7\n\t"
  65062. "ADDS r2, r2, r5\n\t"
  65063. "ADCS r3, r3, r6\n\t"
  65064. "ADC r4, r4, r7\n\t"
  65065. "STR r2, [%[r], #84]\n\t"
  65066. /* A[7] * A[15] */
  65067. "LDR r10, [%[a], #60]\n\t"
  65068. "LDR r12, [%[a], #28]\n\t"
  65069. "UMULL r5, r6, r10, r12\n\t"
  65070. "MOV r2, #0x0\n\t"
  65071. "MOV r7, #0x0\n\t"
  65072. /* A[8] * A[14] */
  65073. "LDR r10, [%[a], #56]\n\t"
  65074. "LDR r12, [%[a], #32]\n\t"
  65075. "UMULL r8, r9, r10, r12\n\t"
  65076. "ADDS r5, r5, r8\n\t"
  65077. "ADCS r6, r6, r9\n\t"
  65078. "ADC r7, r7, #0x0\n\t"
  65079. /* A[9] * A[13] */
  65080. "LDR r10, [%[a], #52]\n\t"
  65081. "LDR r12, [%[a], #36]\n\t"
  65082. "UMULL r8, r9, r10, r12\n\t"
  65083. "ADDS r5, r5, r8\n\t"
  65084. "ADCS r6, r6, r9\n\t"
  65085. "ADC r7, r7, #0x0\n\t"
  65086. /* A[10] * A[12] */
  65087. "LDR r10, [%[a], #48]\n\t"
  65088. "LDR r12, [%[a], #40]\n\t"
  65089. "UMULL r8, r9, r10, r12\n\t"
  65090. "ADDS r5, r5, r8\n\t"
  65091. "ADCS r6, r6, r9\n\t"
  65092. "ADC r7, r7, #0x0\n\t"
  65093. /* A[11] * A[11] */
  65094. "LDR r10, [%[a], #44]\n\t"
  65095. "UMULL r8, r9, r10, r10\n\t"
  65096. "ADDS r5, r5, r5\n\t"
  65097. "ADCS r6, r6, r6\n\t"
  65098. "ADC r7, r7, r7\n\t"
  65099. "ADDS r3, r3, r8\n\t"
  65100. "ADCS r4, r4, r9\n\t"
  65101. "ADC r2, r2, #0x0\n\t"
  65102. "ADDS r3, r3, r5\n\t"
  65103. "ADCS r4, r4, r6\n\t"
  65104. "ADC r2, r2, r7\n\t"
  65105. "STR r3, [%[r], #88]\n\t"
  65106. /* A[8] * A[15] */
  65107. "LDR r10, [%[a], #60]\n\t"
  65108. "LDR r12, [%[a], #32]\n\t"
  65109. "UMULL r5, r6, r10, r12\n\t"
  65110. "MOV r3, #0x0\n\t"
  65111. "MOV r7, #0x0\n\t"
  65112. /* A[9] * A[14] */
  65113. "LDR r10, [%[a], #56]\n\t"
  65114. "LDR r12, [%[a], #36]\n\t"
  65115. "UMULL r8, r9, r10, r12\n\t"
  65116. "ADDS r5, r5, r8\n\t"
  65117. "ADCS r6, r6, r9\n\t"
  65118. "ADC r7, r7, #0x0\n\t"
  65119. /* A[10] * A[13] */
  65120. "LDR r10, [%[a], #52]\n\t"
  65121. "LDR r12, [%[a], #40]\n\t"
  65122. "UMULL r8, r9, r10, r12\n\t"
  65123. "ADDS r5, r5, r8\n\t"
  65124. "ADCS r6, r6, r9\n\t"
  65125. "ADC r7, r7, #0x0\n\t"
  65126. /* A[11] * A[12] */
  65127. "LDR r10, [%[a], #48]\n\t"
  65128. "LDR r12, [%[a], #44]\n\t"
  65129. "UMULL r8, r9, r10, r12\n\t"
  65130. "ADDS r5, r5, r8\n\t"
  65131. "ADCS r6, r6, r9\n\t"
  65132. "ADC r7, r7, #0x0\n\t"
  65133. "ADDS r5, r5, r5\n\t"
  65134. "ADCS r6, r6, r6\n\t"
  65135. "ADC r7, r7, r7\n\t"
  65136. "ADDS r4, r4, r5\n\t"
  65137. "ADCS r2, r2, r6\n\t"
  65138. "ADC r3, r3, r7\n\t"
  65139. "STR r4, [%[r], #92]\n\t"
  65140. /* A[9] * A[15] */
  65141. "LDR r10, [%[a], #60]\n\t"
  65142. "LDR r12, [%[a], #36]\n\t"
  65143. "UMULL r5, r6, r10, r12\n\t"
  65144. "MOV r4, #0x0\n\t"
  65145. "MOV r7, #0x0\n\t"
  65146. /* A[10] * A[14] */
  65147. "LDR r10, [%[a], #56]\n\t"
  65148. "LDR r12, [%[a], #40]\n\t"
  65149. "UMULL r8, r9, r10, r12\n\t"
  65150. "ADDS r5, r5, r8\n\t"
  65151. "ADCS r6, r6, r9\n\t"
  65152. "ADC r7, r7, #0x0\n\t"
  65153. /* A[11] * A[13] */
  65154. "LDR r10, [%[a], #52]\n\t"
  65155. "LDR r12, [%[a], #44]\n\t"
  65156. "UMULL r8, r9, r10, r12\n\t"
  65157. "ADDS r5, r5, r8\n\t"
  65158. "ADCS r6, r6, r9\n\t"
  65159. "ADC r7, r7, #0x0\n\t"
  65160. /* A[12] * A[12] */
  65161. "LDR r10, [%[a], #48]\n\t"
  65162. "UMULL r8, r9, r10, r10\n\t"
  65163. "ADDS r5, r5, r5\n\t"
  65164. "ADCS r6, r6, r6\n\t"
  65165. "ADC r7, r7, r7\n\t"
  65166. "ADDS r2, r2, r8\n\t"
  65167. "ADCS r3, r3, r9\n\t"
  65168. "ADC r4, r4, #0x0\n\t"
  65169. "ADDS r2, r2, r5\n\t"
  65170. "ADCS r3, r3, r6\n\t"
  65171. "ADC r4, r4, r7\n\t"
  65172. "STR r2, [%[r], #96]\n\t"
  65173. /* A[10] * A[15] */
  65174. "LDR r10, [%[a], #60]\n\t"
  65175. "LDR r12, [%[a], #40]\n\t"
  65176. "UMULL r5, r6, r10, r12\n\t"
  65177. "MOV r2, #0x0\n\t"
  65178. "MOV r7, #0x0\n\t"
  65179. /* A[11] * A[14] */
  65180. "LDR r10, [%[a], #56]\n\t"
  65181. "LDR r12, [%[a], #44]\n\t"
  65182. "UMULL r8, r9, r10, r12\n\t"
  65183. "ADDS r5, r5, r8\n\t"
  65184. "ADCS r6, r6, r9\n\t"
  65185. "ADC r7, r7, #0x0\n\t"
  65186. /* A[12] * A[13] */
  65187. "LDR r10, [%[a], #52]\n\t"
  65188. "LDR r12, [%[a], #48]\n\t"
  65189. "UMULL r8, r9, r10, r12\n\t"
  65190. "ADDS r5, r5, r8\n\t"
  65191. "ADCS r6, r6, r9\n\t"
  65192. "ADC r7, r7, #0x0\n\t"
  65193. "ADDS r5, r5, r5\n\t"
  65194. "ADCS r6, r6, r6\n\t"
  65195. "ADC r7, r7, r7\n\t"
  65196. "ADDS r3, r3, r5\n\t"
  65197. "ADCS r4, r4, r6\n\t"
  65198. "ADC r2, r2, r7\n\t"
  65199. "STR r3, [%[r], #100]\n\t"
  65200. /* A[11] * A[15] */
  65201. "LDR r10, [%[a], #60]\n\t"
  65202. "LDR r12, [%[a], #44]\n\t"
  65203. "UMULL r8, r9, r10, r12\n\t"
  65204. "ADDS r4, r4, r8\n\t"
  65205. "ADCS r2, r2, r9\n\t"
  65206. "MOV r3, #0x0\n\t"
  65207. "ADC r3, r3, #0x0\n\t"
  65208. "ADDS r4, r4, r8\n\t"
  65209. "ADCS r2, r2, r9\n\t"
  65210. "MOV r3, #0x0\n\t"
  65211. "ADC r3, r3, #0x0\n\t"
  65212. /* A[12] * A[14] */
  65213. "LDR r10, [%[a], #56]\n\t"
  65214. "LDR r12, [%[a], #48]\n\t"
  65215. "UMULL r8, r9, r10, r12\n\t"
  65216. "ADDS r4, r4, r8\n\t"
  65217. "ADCS r2, r2, r9\n\t"
  65218. "ADC r3, r3, #0x0\n\t"
  65219. "ADDS r4, r4, r8\n\t"
  65220. "ADCS r2, r2, r9\n\t"
  65221. "ADC r3, r3, #0x0\n\t"
  65222. /* A[13] * A[13] */
  65223. "LDR r10, [%[a], #52]\n\t"
  65224. "UMULL r8, r9, r10, r10\n\t"
  65225. "ADDS r4, r4, r8\n\t"
  65226. "ADCS r2, r2, r9\n\t"
  65227. "ADC r3, r3, #0x0\n\t"
  65228. "STR r4, [%[r], #104]\n\t"
  65229. /* A[12] * A[15] */
  65230. "LDR r10, [%[a], #60]\n\t"
  65231. "LDR r12, [%[a], #48]\n\t"
  65232. "UMULL r8, r9, r10, r12\n\t"
  65233. "ADDS r2, r2, r8\n\t"
  65234. "ADCS r3, r3, r9\n\t"
  65235. "MOV r4, #0x0\n\t"
  65236. "ADC r4, r4, #0x0\n\t"
  65237. "ADDS r2, r2, r8\n\t"
  65238. "ADCS r3, r3, r9\n\t"
  65239. "MOV r4, #0x0\n\t"
  65240. "ADC r4, r4, #0x0\n\t"
  65241. /* A[13] * A[14] */
  65242. "LDR r10, [%[a], #56]\n\t"
  65243. "LDR r12, [%[a], #52]\n\t"
  65244. "UMULL r8, r9, r10, r12\n\t"
  65245. "ADDS r2, r2, r8\n\t"
  65246. "ADCS r3, r3, r9\n\t"
  65247. "ADC r4, r4, #0x0\n\t"
  65248. "ADDS r2, r2, r8\n\t"
  65249. "ADCS r3, r3, r9\n\t"
  65250. "ADC r4, r4, #0x0\n\t"
  65251. "STR r2, [%[r], #108]\n\t"
  65252. /* A[13] * A[15] */
  65253. "LDR r10, [%[a], #60]\n\t"
  65254. "LDR r12, [%[a], #52]\n\t"
  65255. "UMULL r8, r9, r10, r12\n\t"
  65256. "ADDS r3, r3, r8\n\t"
  65257. "ADCS r4, r4, r9\n\t"
  65258. "MOV r2, #0x0\n\t"
  65259. "ADC r2, r2, #0x0\n\t"
  65260. "ADDS r3, r3, r8\n\t"
  65261. "ADCS r4, r4, r9\n\t"
  65262. "MOV r2, #0x0\n\t"
  65263. "ADC r2, r2, #0x0\n\t"
  65264. /* A[14] * A[14] */
  65265. "LDR r10, [%[a], #56]\n\t"
  65266. "UMULL r8, r9, r10, r10\n\t"
  65267. "ADDS r3, r3, r8\n\t"
  65268. "ADCS r4, r4, r9\n\t"
  65269. "ADC r2, r2, #0x0\n\t"
  65270. "STR r3, [%[r], #112]\n\t"
  65271. /* A[14] * A[15] */
  65272. "LDR r10, [%[a], #60]\n\t"
  65273. "LDR r12, [%[a], #56]\n\t"
  65274. "UMULL r8, r9, r10, r12\n\t"
  65275. "ADDS r4, r4, r8\n\t"
  65276. "ADCS r2, r2, r9\n\t"
  65277. "MOV r3, #0x0\n\t"
  65278. "ADC r3, r3, #0x0\n\t"
  65279. "ADDS r4, r4, r8\n\t"
  65280. "ADCS r2, r2, r9\n\t"
  65281. "MOV r3, #0x0\n\t"
  65282. "ADC r3, r3, #0x0\n\t"
  65283. "STR r4, [%[r], #116]\n\t"
  65284. /* A[15] * A[15] */
  65285. "LDR r10, [%[a], #60]\n\t"
  65286. "UMLAL r2, r3, r10, r10\n\t"
  65287. "STR r2, [%[r], #120]\n\t"
  65288. "STR r3, [%[r], #124]\n\t"
  65289. "LDM sp!, {r2, r3, r4, r8}\n\t"
  65290. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  65291. "LDM sp!, {r2, r3, r4, r8}\n\t"
  65292. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  65293. "LDM sp!, {r2, r3, r4, r8}\n\t"
  65294. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  65295. "LDM sp!, {r2, r3, r4, r8}\n\t"
  65296. "STM %[r]!, {r2, r3, r4, r8}\n\t"
  65297. : [r] "+r" (r), [a] "+r" (a)
  65298. :
  65299. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "cc"
  65300. );
  65301. }
  65302. /* Add b to a into r. (r = a + b)
  65303. *
  65304. * r A single precision integer.
  65305. * a A single precision integer.
  65306. * b A single precision integer.
  65307. */
  65308. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65309. static sp_digit sp_1024_add_16(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  65310. #else
  65311. static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b)
  65312. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65313. {
  65314. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65315. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  65316. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  65317. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  65318. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65319. __asm__ __volatile__ (
  65320. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65321. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65322. "ADDS r3, r3, r7\n\t"
  65323. "ADCS r4, r4, r8\n\t"
  65324. "ADCS r5, r5, r9\n\t"
  65325. "ADCS r6, r6, r10\n\t"
  65326. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65327. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65328. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65329. "ADCS r3, r3, r7\n\t"
  65330. "ADCS r4, r4, r8\n\t"
  65331. "ADCS r5, r5, r9\n\t"
  65332. "ADCS r6, r6, r10\n\t"
  65333. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65334. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65335. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65336. "ADCS r3, r3, r7\n\t"
  65337. "ADCS r4, r4, r8\n\t"
  65338. "ADCS r5, r5, r9\n\t"
  65339. "ADCS r6, r6, r10\n\t"
  65340. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65341. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65342. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65343. "ADCS r3, r3, r7\n\t"
  65344. "ADCS r4, r4, r8\n\t"
  65345. "ADCS r5, r5, r9\n\t"
  65346. "ADCS r6, r6, r10\n\t"
  65347. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65348. "MOV %[r], #0x0\n\t"
  65349. "ADC %[r], %[r], #0x0\n\t"
  65350. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  65351. :
  65352. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  65353. );
  65354. return (uint32_t)(size_t)r;
  65355. }
  65356. /* Sub b from a into a. (a -= b)
  65357. *
  65358. * a A single precision integer and result.
  65359. * b A single precision integer.
  65360. */
  65361. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65362. static sp_digit sp_1024_sub_in_place_32(sp_digit* a_p, const sp_digit* b_p)
  65363. #else
  65364. static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b)
  65365. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65366. {
  65367. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65368. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  65369. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  65370. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65371. __asm__ __volatile__ (
  65372. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65373. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65374. "SUBS r2, r2, r6\n\t"
  65375. "SBCS r3, r3, r7\n\t"
  65376. "SBCS r4, r4, r8\n\t"
  65377. "SBCS r5, r5, r9\n\t"
  65378. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65379. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65380. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65381. "SBCS r2, r2, r6\n\t"
  65382. "SBCS r3, r3, r7\n\t"
  65383. "SBCS r4, r4, r8\n\t"
  65384. "SBCS r5, r5, r9\n\t"
  65385. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65386. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65387. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65388. "SBCS r2, r2, r6\n\t"
  65389. "SBCS r3, r3, r7\n\t"
  65390. "SBCS r4, r4, r8\n\t"
  65391. "SBCS r5, r5, r9\n\t"
  65392. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65393. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65394. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65395. "SBCS r2, r2, r6\n\t"
  65396. "SBCS r3, r3, r7\n\t"
  65397. "SBCS r4, r4, r8\n\t"
  65398. "SBCS r5, r5, r9\n\t"
  65399. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65400. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65401. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65402. "SBCS r2, r2, r6\n\t"
  65403. "SBCS r3, r3, r7\n\t"
  65404. "SBCS r4, r4, r8\n\t"
  65405. "SBCS r5, r5, r9\n\t"
  65406. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65407. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65408. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65409. "SBCS r2, r2, r6\n\t"
  65410. "SBCS r3, r3, r7\n\t"
  65411. "SBCS r4, r4, r8\n\t"
  65412. "SBCS r5, r5, r9\n\t"
  65413. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65414. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65415. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65416. "SBCS r2, r2, r6\n\t"
  65417. "SBCS r3, r3, r7\n\t"
  65418. "SBCS r4, r4, r8\n\t"
  65419. "SBCS r5, r5, r9\n\t"
  65420. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65421. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65422. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65423. "SBCS r2, r2, r6\n\t"
  65424. "SBCS r3, r3, r7\n\t"
  65425. "SBCS r4, r4, r8\n\t"
  65426. "SBCS r5, r5, r9\n\t"
  65427. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65428. "SBC %[a], r9, r9\n\t"
  65429. : [a] "+r" (a), [b] "+r" (b)
  65430. :
  65431. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  65432. );
  65433. return (uint32_t)(size_t)a;
  65434. }
  65435. /* Add b to a into r. (r = a + b)
  65436. *
  65437. * r A single precision integer.
  65438. * a A single precision integer.
  65439. * b A single precision integer.
  65440. */
  65441. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65442. static sp_digit sp_1024_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  65443. #else
  65444. static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
  65445. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65446. {
  65447. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65448. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  65449. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  65450. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  65451. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65452. __asm__ __volatile__ (
  65453. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65454. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65455. "ADDS r3, r3, r7\n\t"
  65456. "ADCS r4, r4, r8\n\t"
  65457. "ADCS r5, r5, r9\n\t"
  65458. "ADCS r6, r6, r10\n\t"
  65459. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65460. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65461. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65462. "ADCS r3, r3, r7\n\t"
  65463. "ADCS r4, r4, r8\n\t"
  65464. "ADCS r5, r5, r9\n\t"
  65465. "ADCS r6, r6, r10\n\t"
  65466. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65467. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65468. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65469. "ADCS r3, r3, r7\n\t"
  65470. "ADCS r4, r4, r8\n\t"
  65471. "ADCS r5, r5, r9\n\t"
  65472. "ADCS r6, r6, r10\n\t"
  65473. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65474. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65475. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65476. "ADCS r3, r3, r7\n\t"
  65477. "ADCS r4, r4, r8\n\t"
  65478. "ADCS r5, r5, r9\n\t"
  65479. "ADCS r6, r6, r10\n\t"
  65480. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65481. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65482. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65483. "ADCS r3, r3, r7\n\t"
  65484. "ADCS r4, r4, r8\n\t"
  65485. "ADCS r5, r5, r9\n\t"
  65486. "ADCS r6, r6, r10\n\t"
  65487. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65488. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65489. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65490. "ADCS r3, r3, r7\n\t"
  65491. "ADCS r4, r4, r8\n\t"
  65492. "ADCS r5, r5, r9\n\t"
  65493. "ADCS r6, r6, r10\n\t"
  65494. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65495. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65496. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65497. "ADCS r3, r3, r7\n\t"
  65498. "ADCS r4, r4, r8\n\t"
  65499. "ADCS r5, r5, r9\n\t"
  65500. "ADCS r6, r6, r10\n\t"
  65501. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65502. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65503. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65504. "ADCS r3, r3, r7\n\t"
  65505. "ADCS r4, r4, r8\n\t"
  65506. "ADCS r5, r5, r9\n\t"
  65507. "ADCS r6, r6, r10\n\t"
  65508. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65509. "MOV %[r], #0x0\n\t"
  65510. "ADC %[r], %[r], #0x0\n\t"
  65511. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  65512. :
  65513. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  65514. );
  65515. return (uint32_t)(size_t)r;
  65516. }
  65517. /* AND m into each word of a and store in r.
  65518. *
  65519. * r A single precision integer.
  65520. * a A single precision integer.
  65521. * m Mask to AND against each digit.
  65522. */
  65523. static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m)
  65524. {
  65525. #ifdef WOLFSSL_SP_SMALL
  65526. int i;
  65527. for (i=0; i<16; i++) {
  65528. r[i] = a[i] & m;
  65529. }
  65530. #else
  65531. int i;
  65532. for (i = 0; i < 16; i += 8) {
  65533. r[i+0] = a[i+0] & m;
  65534. r[i+1] = a[i+1] & m;
  65535. r[i+2] = a[i+2] & m;
  65536. r[i+3] = a[i+3] & m;
  65537. r[i+4] = a[i+4] & m;
  65538. r[i+5] = a[i+5] & m;
  65539. r[i+6] = a[i+6] & m;
  65540. r[i+7] = a[i+7] & m;
  65541. }
  65542. #endif
  65543. }
  65544. /* Multiply a and b into r. (r = a * b)
  65545. *
  65546. * r A single precision integer.
  65547. * a A single precision integer.
  65548. * b A single precision integer.
  65549. */
  65550. SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a,
  65551. const sp_digit* b)
  65552. {
  65553. sp_digit* z0 = r;
  65554. sp_digit z1[32];
  65555. sp_digit a1[16];
  65556. sp_digit b1[16];
  65557. sp_digit* z2 = r + 32;
  65558. sp_digit u;
  65559. sp_digit ca;
  65560. sp_digit cb;
  65561. ca = sp_1024_add_16(a1, a, &a[16]);
  65562. cb = sp_1024_add_16(b1, b, &b[16]);
  65563. u = ca & cb;
  65564. sp_1024_mul_16(z2, &a[16], &b[16]);
  65565. sp_1024_mul_16(z0, a, b);
  65566. sp_1024_mul_16(z1, a1, b1);
  65567. u += sp_1024_sub_in_place_32(z1, z0);
  65568. u += sp_1024_sub_in_place_32(z1, z2);
  65569. sp_1024_mask_16(a1, a1, 0 - cb);
  65570. u += sp_1024_add_16(z1 + 16, z1 + 16, a1);
  65571. sp_1024_mask_16(b1, b1, 0 - ca);
  65572. u += sp_1024_add_16(z1 + 16, z1 + 16, b1);
  65573. u += sp_1024_add_32(r + 16, r + 16, z1);
  65574. XMEMSET(a1 + 1, 0, sizeof(sp_digit) * (16 - 1));
  65575. a1[0] = u;
  65576. (void)sp_1024_add_16(r + 48, r + 48, a1);
  65577. }
  65578. /* Sub b from a into r. (r = a - b)
  65579. *
  65580. * r A single precision integer.
  65581. * a A single precision integer.
  65582. * b A single precision integer.
  65583. */
  65584. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65585. static sp_digit sp_1024_sub_16(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  65586. #else
  65587. static sp_digit sp_1024_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b)
  65588. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65589. {
  65590. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65591. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  65592. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  65593. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  65594. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65595. __asm__ __volatile__ (
  65596. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65597. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65598. "SUBS r3, r3, r7\n\t"
  65599. "SBCS r4, r4, r8\n\t"
  65600. "SBCS r5, r5, r9\n\t"
  65601. "SBCS r6, r6, r10\n\t"
  65602. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65603. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65604. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65605. "SBCS r3, r3, r7\n\t"
  65606. "SBCS r4, r4, r8\n\t"
  65607. "SBCS r5, r5, r9\n\t"
  65608. "SBCS r6, r6, r10\n\t"
  65609. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65610. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65611. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65612. "SBCS r3, r3, r7\n\t"
  65613. "SBCS r4, r4, r8\n\t"
  65614. "SBCS r5, r5, r9\n\t"
  65615. "SBCS r6, r6, r10\n\t"
  65616. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65617. "LDM %[a]!, {r3, r4, r5, r6}\n\t"
  65618. "LDM %[b]!, {r7, r8, r9, r10}\n\t"
  65619. "SBCS r3, r3, r7\n\t"
  65620. "SBCS r4, r4, r8\n\t"
  65621. "SBCS r5, r5, r9\n\t"
  65622. "SBCS r6, r6, r10\n\t"
  65623. "STM %[r]!, {r3, r4, r5, r6}\n\t"
  65624. "SBC %[r], r6, r6\n\t"
  65625. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  65626. :
  65627. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  65628. );
  65629. return (uint32_t)(size_t)r;
  65630. }
  65631. /* Square a and put result in r. (r = a * a)
  65632. *
  65633. * r A single precision integer.
  65634. * a A single precision integer.
  65635. */
  65636. SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
  65637. {
  65638. sp_digit* z0 = r;
  65639. sp_digit* z2 = r + 32;
  65640. sp_digit z1[32];
  65641. sp_digit* a1 = z1;
  65642. sp_digit zero[16];
  65643. sp_digit u;
  65644. sp_digit mask;
  65645. sp_digit* p1;
  65646. sp_digit* p2;
  65647. XMEMSET(zero, 0, sizeof(sp_digit) * 16);
  65648. mask = sp_1024_sub_16(a1, a, &a[16]);
  65649. p1 = (sp_digit*)(((sp_digit)zero & mask ) | ((sp_digit)a1 & (~mask)));
  65650. p2 = (sp_digit*)(((sp_digit)zero & (~mask)) | ((sp_digit)a1 & mask ));
  65651. (void)sp_1024_sub_16(a1, p1, p2);
  65652. sp_1024_sqr_16(z2, &a[16]);
  65653. sp_1024_sqr_16(z0, a);
  65654. sp_1024_sqr_16(z1, a1);
  65655. u = 0;
  65656. u -= sp_1024_sub_in_place_32(z1, z2);
  65657. u -= sp_1024_sub_in_place_32(z1, z0);
  65658. u += sp_1024_sub_in_place_32(r + 16, z1);
  65659. zero[0] = u;
  65660. (void)sp_1024_add_16(r + 48, r + 48, zero);
  65661. }
  65662. #else
  65663. /* Multiply a and b into r. (r = a * b)
  65664. *
  65665. * r A single precision integer.
  65666. * a A single precision integer.
  65667. * b A single precision integer.
  65668. */
  65669. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65670. static void sp_1024_mul_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  65671. #else
  65672. static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
  65673. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65674. {
  65675. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65676. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  65677. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  65678. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  65679. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65680. __asm__ __volatile__ (
  65681. "SUB sp, sp, #0x100\n\t"
  65682. "LDR lr, [%[a]]\n\t"
  65683. "LDR r11, [%[b]]\n\t"
  65684. "UMULL r8, r6, lr, r11\n\t"
  65685. "STR r8, [sp]\n\t"
  65686. "MOV r7, #0x0\n\t"
  65687. "MOV r8, #0x0\n\t"
  65688. "MOV r5, #0x4\n\t"
  65689. "\n"
  65690. "L_sp_1024_mul_32_outer:\n\t"
  65691. "SUBS r3, r5, #0x7c\n\t"
  65692. "IT cc\n\t"
  65693. "MOVCC r3, #0x0\n\t"
  65694. "SUB r4, r5, r3\n\t"
  65695. "\n"
  65696. "L_sp_1024_mul_32_inner:\n\t"
  65697. "LDR lr, [%[a], r3]\n\t"
  65698. "LDR r11, [%[b], r4]\n\t"
  65699. "UMULL r9, r10, lr, r11\n\t"
  65700. "ADDS r6, r6, r9\n\t"
  65701. "ADCS r7, r7, r10\n\t"
  65702. "ADC r8, r8, #0x0\n\t"
  65703. "LDR lr, [%[a], r4]\n\t"
  65704. "LDR r11, [%[b], r3]\n\t"
  65705. "UMULL r9, r10, lr, r11\n\t"
  65706. "ADDS r6, r6, r9\n\t"
  65707. "ADCS r7, r7, r10\n\t"
  65708. "ADC r8, r8, #0x0\n\t"
  65709. "ADD r3, r3, #0x4\n\t"
  65710. "SUB r4, r4, #0x4\n\t"
  65711. "CMP r3, r4\n\t"
  65712. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65713. "BGT L_sp_1024_mul_32_inner_done\n\t"
  65714. #else
  65715. "BGT.N L_sp_1024_mul_32_inner_done\n\t"
  65716. #endif
  65717. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65718. "BLT L_sp_1024_mul_32_inner\n\t"
  65719. #else
  65720. "BLT.N L_sp_1024_mul_32_inner\n\t"
  65721. #endif
  65722. "LDR lr, [%[a], r3]\n\t"
  65723. "LDR r11, [%[b], r3]\n\t"
  65724. "UMULL r9, r10, lr, r11\n\t"
  65725. "ADDS r6, r6, r9\n\t"
  65726. "ADCS r7, r7, r10\n\t"
  65727. "ADC r8, r8, #0x0\n\t"
  65728. "\n"
  65729. "L_sp_1024_mul_32_inner_done:\n\t"
  65730. "STR r6, [sp, r5]\n\t"
  65731. "MOV r6, r7\n\t"
  65732. "MOV r7, r8\n\t"
  65733. "MOV r8, #0x0\n\t"
  65734. "ADD r5, r5, #0x4\n\t"
  65735. "CMP r5, #0xf4\n\t"
  65736. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65737. "BLE L_sp_1024_mul_32_outer\n\t"
  65738. #else
  65739. "BLE.N L_sp_1024_mul_32_outer\n\t"
  65740. #endif
  65741. "LDR lr, [%[a], #124]\n\t"
  65742. "LDR r11, [%[b], #124]\n\t"
  65743. "UMLAL r6, r7, lr, r11\n\t"
  65744. "STR r6, [sp, r5]\n\t"
  65745. "ADD r5, r5, #0x4\n\t"
  65746. "STR r7, [sp, r5]\n\t"
  65747. "\n"
  65748. "L_sp_1024_mul_32_store:\n\t"
  65749. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  65750. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  65751. "SUBS r5, r5, #0x20\n\t"
  65752. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65753. "BGT L_sp_1024_mul_32_store\n\t"
  65754. #else
  65755. "BGT.N L_sp_1024_mul_32_store\n\t"
  65756. #endif
  65757. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  65758. :
  65759. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  65760. );
  65761. }
  65762. /* Square a and put result in r. (r = a * a)
  65763. *
  65764. * r A single precision integer.
  65765. * a A single precision integer.
  65766. */
  65767. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65768. static void sp_1024_sqr_32(sp_digit* r_p, const sp_digit* a_p)
  65769. #else
  65770. static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a)
  65771. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65772. {
  65773. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65774. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  65775. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  65776. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65777. __asm__ __volatile__ (
  65778. "SUB sp, sp, #0x100\n\t"
  65779. "LDR lr, [%[a]]\n\t"
  65780. "UMULL r8, r6, lr, lr\n\t"
  65781. "STR r8, [sp]\n\t"
  65782. "MOV r7, #0x0\n\t"
  65783. "MOV r8, #0x0\n\t"
  65784. "MOV r5, #0x4\n\t"
  65785. "\n"
  65786. "L_sp_1024_sqr_32_outer:\n\t"
  65787. "SUBS r3, r5, #0x7c\n\t"
  65788. "IT cc\n\t"
  65789. "MOVCC r3, #0x0\n\t"
  65790. "SUB r4, r5, r3\n\t"
  65791. "\n"
  65792. "L_sp_1024_sqr_32_inner:\n\t"
  65793. "LDR lr, [%[a], r3]\n\t"
  65794. "LDR r11, [%[a], r4]\n\t"
  65795. "UMULL r9, r10, lr, r11\n\t"
  65796. "ADDS r6, r6, r9\n\t"
  65797. "ADCS r7, r7, r10\n\t"
  65798. "ADC r8, r8, #0x0\n\t"
  65799. "ADDS r6, r6, r9\n\t"
  65800. "ADCS r7, r7, r10\n\t"
  65801. "ADC r8, r8, #0x0\n\t"
  65802. "ADD r3, r3, #0x4\n\t"
  65803. "SUB r4, r4, #0x4\n\t"
  65804. "CMP r3, r4\n\t"
  65805. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65806. "BGT L_sp_1024_sqr_32_inner_done\n\t"
  65807. #else
  65808. "BGT.N L_sp_1024_sqr_32_inner_done\n\t"
  65809. #endif
  65810. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65811. "BLT L_sp_1024_sqr_32_inner\n\t"
  65812. #else
  65813. "BLT.N L_sp_1024_sqr_32_inner\n\t"
  65814. #endif
  65815. "LDR lr, [%[a], r3]\n\t"
  65816. "UMULL r9, r10, lr, lr\n\t"
  65817. "ADDS r6, r6, r9\n\t"
  65818. "ADCS r7, r7, r10\n\t"
  65819. "ADC r8, r8, #0x0\n\t"
  65820. "\n"
  65821. "L_sp_1024_sqr_32_inner_done:\n\t"
  65822. "STR r6, [sp, r5]\n\t"
  65823. "MOV r6, r7\n\t"
  65824. "MOV r7, r8\n\t"
  65825. "MOV r8, #0x0\n\t"
  65826. "ADD r5, r5, #0x4\n\t"
  65827. "CMP r5, #0xf4\n\t"
  65828. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65829. "BLE L_sp_1024_sqr_32_outer\n\t"
  65830. #else
  65831. "BLE.N L_sp_1024_sqr_32_outer\n\t"
  65832. #endif
  65833. "LDR lr, [%[a], #124]\n\t"
  65834. "UMLAL r6, r7, lr, lr\n\t"
  65835. "STR r6, [sp, r5]\n\t"
  65836. "ADD r5, r5, #0x4\n\t"
  65837. "STR r7, [sp, r5]\n\t"
  65838. "\n"
  65839. "L_sp_1024_sqr_32_store:\n\t"
  65840. "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  65841. "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t"
  65842. "SUBS r5, r5, #0x20\n\t"
  65843. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65844. "BGT L_sp_1024_sqr_32_store\n\t"
  65845. #else
  65846. "BGT.N L_sp_1024_sqr_32_store\n\t"
  65847. #endif
  65848. : [r] "+r" (r), [a] "+r" (a)
  65849. :
  65850. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr", "r11", "cc"
  65851. );
  65852. }
  65853. #endif /* !WOLFSSL_SP_SMALL */
  65854. /* The modulus (prime) of the curve P1024. */
  65855. static const sp_digit p1024_mod[32] = {
  65856. 0xfea85feb,0x666d807a,0xac7ace87,0x80c5df10,0x89857db0,0xfce3e823,
  65857. 0x56971f1f,0x9f94d6af,0x1c3c09aa,0xa7cf3c52,0x31852a82,0xb6aff4a8,
  65858. 0x65681ce1,0x512ac5cd,0x326b4cd4,0xe26c6487,0xa666a6d0,0x356d27f4,
  65859. 0xf7c88a19,0xe791b39f,0x31a59cb0,0x228730d5,0xe2fc0f1b,0xf40aab27,
  65860. 0xb3e01a2e,0xbe9ae358,0x9cb48261,0x416c0ce1,0xdad0657a,0x65c61198,
  65861. 0x0a563fda,0x997abb1f
  65862. };
  65863. /* The Montgomery normalizer for modulus of the curve P1024. */
  65864. static const sp_digit p1024_norm_mod[32] = {
  65865. 0x0157a015,0x99927f85,0x53853178,0x7f3a20ef,0x767a824f,0x031c17dc,
  65866. 0xa968e0e0,0x606b2950,0xe3c3f655,0x5830c3ad,0xce7ad57d,0x49500b57,
  65867. 0x9a97e31e,0xaed53a32,0xcd94b32b,0x1d939b78,0x5999592f,0xca92d80b,
  65868. 0x083775e6,0x186e4c60,0xce5a634f,0xdd78cf2a,0x1d03f0e4,0x0bf554d8,
  65869. 0x4c1fe5d1,0x41651ca7,0x634b7d9e,0xbe93f31e,0x252f9a85,0x9a39ee67,
  65870. 0xf5a9c025,0x668544e0
  65871. };
  65872. /* The Montgomery multiplier for modulus of the curve P1024. */
  65873. static sp_digit p1024_mp_mod = 0x7c8f2f3d;
  65874. #if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY)
  65875. /* The order of the curve P1024. */
  65876. static const sp_digit p1024_order[32] = {
  65877. 0xbfaa17fb,0xd99b601e,0x2b1eb3a1,0x203177c4,0xe2615f6c,0xff38fa08,
  65878. 0xd5a5c7c7,0xa7e535ab,0x870f026a,0xa9f3cf14,0x0c614aa0,0x6dabfd2a,
  65879. 0x595a0738,0x144ab173,0xcc9ad335,0x389b1921,0x2999a9b4,0x4d5b49fd,
  65880. 0xfdf22286,0x39e46ce7,0x4c69672c,0xc8a1cc35,0xf8bf03c6,0xbd02aac9,
  65881. 0x2cf8068b,0x6fa6b8d6,0x672d2098,0x905b0338,0x36b4195e,0x99718466,
  65882. 0xc2958ff6,0x265eaec7
  65883. };
  65884. #endif
  65885. /* The base point of curve P1024. */
  65886. static const sp_point_1024 p1024_base = {
  65887. /* X ordinate */
  65888. {
  65889. 0xeae63895,0x880dc8ab,0x967e0979,0x80ec46c4,0xb63f73ec,0xee9163a5,
  65890. 0x80728d87,0xd5cfb4cc,0xba66910d,0xa7c1514d,0x7a60de74,0xa702c339,
  65891. 0x8b72f2e1,0x337c8654,0x5dd5bccb,0x9760af76,0x406ce890,0x718bd9e7,
  65892. 0xdb9dfa55,0x43d5f22c,0x30b09e10,0xab10db90,0xf6ce2308,0xb5edb6c0,
  65893. 0xb6ff7cbf,0x98b2f204,0x0aec69c6,0x2b1a2fd6,0x3ed9b52a,0x0a799005,
  65894. 0x332c29ad,0x53fc09ee,
  65895. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65896. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65897. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65898. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65899. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65900. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65901. (sp_digit)0, (sp_digit)0
  65902. },
  65903. /* Y ordinate */
  65904. {
  65905. 0x1bef16d7,0x75573fd7,0x6a67dcde,0xadb9b570,0xd5bb4636,0x80bdad5a,
  65906. 0xe9cb99a9,0x13515ad7,0xc5a4d5f2,0x492d979f,0x164aa989,0xac6f1e80,
  65907. 0xb7652fe0,0xcad696b5,0xad547c6c,0x70dae117,0xa9e032b9,0x416cff0c,
  65908. 0x9a140b2e,0x6b598ccf,0xf0de55f6,0xe7f7f5e5,0x654ec2b9,0xf5ea69f4,
  65909. 0x1e141178,0x3d778d82,0x02990696,0xd3e82016,0x3634a135,0xf9f1f053,
  65910. 0x3f6009f1,0x0a824906,
  65911. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65912. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65913. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65914. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65915. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65916. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65917. (sp_digit)0, (sp_digit)0
  65918. },
  65919. /* Z ordinate */
  65920. {
  65921. 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  65922. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  65923. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  65924. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  65925. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  65926. 0x00000000,0x00000000,
  65927. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65928. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65929. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65930. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65931. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65932. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  65933. (sp_digit)0, (sp_digit)0
  65934. },
  65935. /* infinity */
  65936. 0
  65937. };
  65938. #ifdef WOLFSSL_SP_SMALL
  65939. /* Sub b from a into a. (a -= b)
  65940. *
  65941. * a A single precision integer.
  65942. * b A single precision integer.
  65943. */
  65944. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65945. static sp_digit sp_1024_sub_in_place_32(sp_digit* a_p, const sp_digit* b_p)
  65946. #else
  65947. static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b)
  65948. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65949. {
  65950. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65951. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  65952. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  65953. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65954. __asm__ __volatile__ (
  65955. "MOV r10, #0x0\n\t"
  65956. "ADD r11, %[a], #0x80\n\t"
  65957. "\n"
  65958. "L_sp_1024_sub_in_pkace_32_word:\n\t"
  65959. "RSBS r10, r10, #0x0\n\t"
  65960. "LDM %[a], {r2, r3, r4, r5}\n\t"
  65961. "LDM %[b]!, {r6, r7, r8, r9}\n\t"
  65962. "SBCS r2, r2, r6\n\t"
  65963. "SBCS r3, r3, r7\n\t"
  65964. "SBCS r4, r4, r8\n\t"
  65965. "SBCS r5, r5, r9\n\t"
  65966. "STM %[a]!, {r2, r3, r4, r5}\n\t"
  65967. "SBC r10, r10, r10\n\t"
  65968. "CMP %[a], r11\n\t"
  65969. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  65970. "BNE L_sp_1024_sub_in_pkace_32_word\n\t"
  65971. #else
  65972. "BNE.N L_sp_1024_sub_in_pkace_32_word\n\t"
  65973. #endif
  65974. "MOV %[a], r10\n\t"
  65975. : [a] "+r" (a), [b] "+r" (b)
  65976. :
  65977. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "cc"
  65978. );
  65979. return (uint32_t)(size_t)a;
  65980. }
  65981. #endif /* WOLFSSL_SP_SMALL */
  65982. #ifdef WOLFSSL_SP_SMALL
  65983. /* Conditionally subtract b from a using the mask m.
  65984. * m is -1 to subtract and 0 when not copying.
  65985. *
  65986. * r A single precision number representing condition subtract result.
  65987. * a A single precision number to subtract from.
  65988. * b A single precision number to subtract.
  65989. * m Mask value to apply.
  65990. */
  65991. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65992. static sp_digit sp_1024_cond_sub_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  65993. #else
  65994. static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  65995. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  65996. {
  65997. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  65998. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  65999. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  66000. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  66001. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  66002. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66003. __asm__ __volatile__ (
  66004. "MOV r8, #0x0\n\t"
  66005. "MOV r4, #0x0\n\t"
  66006. "MOV r5, #0x0\n\t"
  66007. "\n"
  66008. "L_sp_1024_cond_sub_32_words:\n\t"
  66009. "SUBS r4, r8, r4\n\t"
  66010. "LDR r6, [%[a], r5]\n\t"
  66011. "LDR r7, [%[b], r5]\n\t"
  66012. "AND r7, r7, %[m]\n\t"
  66013. "SBCS r6, r6, r7\n\t"
  66014. "SBC r4, r8, r8\n\t"
  66015. "STR r6, [%[r], r5]\n\t"
  66016. "ADD r5, r5, #0x4\n\t"
  66017. "CMP r5, #0x80\n\t"
  66018. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  66019. "BLT L_sp_1024_cond_sub_32_words\n\t"
  66020. #else
  66021. "BLT.N L_sp_1024_cond_sub_32_words\n\t"
  66022. #endif
  66023. "MOV %[r], r4\n\t"
  66024. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  66025. :
  66026. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  66027. );
  66028. return (uint32_t)(size_t)r;
  66029. }
  66030. #else
  66031. /* Conditionally subtract b from a using the mask m.
  66032. * m is -1 to subtract and 0 when not copying.
  66033. *
  66034. * r A single precision number representing condition subtract result.
  66035. * a A single precision number to subtract from.
  66036. * b A single precision number to subtract.
  66037. * m Mask value to apply.
  66038. */
  66039. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66040. static sp_digit sp_1024_cond_sub_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  66041. #else
  66042. static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  66043. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66044. {
  66045. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66046. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  66047. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  66048. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  66049. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  66050. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66051. __asm__ __volatile__ (
  66052. "MOV r5, #0x0\n\t"
  66053. "LDM %[a]!, {r6, r7}\n\t"
  66054. "LDM %[b]!, {r8, r9}\n\t"
  66055. "AND r8, r8, %[m]\n\t"
  66056. "AND r9, r9, %[m]\n\t"
  66057. "SUBS r6, r6, r8\n\t"
  66058. "SBCS r7, r7, r9\n\t"
  66059. "STM %[r]!, {r6, r7}\n\t"
  66060. "LDM %[a]!, {r6, r7}\n\t"
  66061. "LDM %[b]!, {r8, r9}\n\t"
  66062. "AND r8, r8, %[m]\n\t"
  66063. "AND r9, r9, %[m]\n\t"
  66064. "SBCS r6, r6, r8\n\t"
  66065. "SBCS r7, r7, r9\n\t"
  66066. "STM %[r]!, {r6, r7}\n\t"
  66067. "LDM %[a]!, {r6, r7}\n\t"
  66068. "LDM %[b]!, {r8, r9}\n\t"
  66069. "AND r8, r8, %[m]\n\t"
  66070. "AND r9, r9, %[m]\n\t"
  66071. "SBCS r6, r6, r8\n\t"
  66072. "SBCS r7, r7, r9\n\t"
  66073. "STM %[r]!, {r6, r7}\n\t"
  66074. "LDM %[a]!, {r6, r7}\n\t"
  66075. "LDM %[b]!, {r8, r9}\n\t"
  66076. "AND r8, r8, %[m]\n\t"
  66077. "AND r9, r9, %[m]\n\t"
  66078. "SBCS r6, r6, r8\n\t"
  66079. "SBCS r7, r7, r9\n\t"
  66080. "STM %[r]!, {r6, r7}\n\t"
  66081. "LDM %[a]!, {r6, r7}\n\t"
  66082. "LDM %[b]!, {r8, r9}\n\t"
  66083. "AND r8, r8, %[m]\n\t"
  66084. "AND r9, r9, %[m]\n\t"
  66085. "SBCS r6, r6, r8\n\t"
  66086. "SBCS r7, r7, r9\n\t"
  66087. "STM %[r]!, {r6, r7}\n\t"
  66088. "LDM %[a]!, {r6, r7}\n\t"
  66089. "LDM %[b]!, {r8, r9}\n\t"
  66090. "AND r8, r8, %[m]\n\t"
  66091. "AND r9, r9, %[m]\n\t"
  66092. "SBCS r6, r6, r8\n\t"
  66093. "SBCS r7, r7, r9\n\t"
  66094. "STM %[r]!, {r6, r7}\n\t"
  66095. "LDM %[a]!, {r6, r7}\n\t"
  66096. "LDM %[b]!, {r8, r9}\n\t"
  66097. "AND r8, r8, %[m]\n\t"
  66098. "AND r9, r9, %[m]\n\t"
  66099. "SBCS r6, r6, r8\n\t"
  66100. "SBCS r7, r7, r9\n\t"
  66101. "STM %[r]!, {r6, r7}\n\t"
  66102. "LDM %[a]!, {r6, r7}\n\t"
  66103. "LDM %[b]!, {r8, r9}\n\t"
  66104. "AND r8, r8, %[m]\n\t"
  66105. "AND r9, r9, %[m]\n\t"
  66106. "SBCS r6, r6, r8\n\t"
  66107. "SBCS r7, r7, r9\n\t"
  66108. "STM %[r]!, {r6, r7}\n\t"
  66109. "LDM %[a]!, {r6, r7}\n\t"
  66110. "LDM %[b]!, {r8, r9}\n\t"
  66111. "AND r8, r8, %[m]\n\t"
  66112. "AND r9, r9, %[m]\n\t"
  66113. "SBCS r6, r6, r8\n\t"
  66114. "SBCS r7, r7, r9\n\t"
  66115. "STM %[r]!, {r6, r7}\n\t"
  66116. "LDM %[a]!, {r6, r7}\n\t"
  66117. "LDM %[b]!, {r8, r9}\n\t"
  66118. "AND r8, r8, %[m]\n\t"
  66119. "AND r9, r9, %[m]\n\t"
  66120. "SBCS r6, r6, r8\n\t"
  66121. "SBCS r7, r7, r9\n\t"
  66122. "STM %[r]!, {r6, r7}\n\t"
  66123. "LDM %[a]!, {r6, r7}\n\t"
  66124. "LDM %[b]!, {r8, r9}\n\t"
  66125. "AND r8, r8, %[m]\n\t"
  66126. "AND r9, r9, %[m]\n\t"
  66127. "SBCS r6, r6, r8\n\t"
  66128. "SBCS r7, r7, r9\n\t"
  66129. "STM %[r]!, {r6, r7}\n\t"
  66130. "LDM %[a]!, {r6, r7}\n\t"
  66131. "LDM %[b]!, {r8, r9}\n\t"
  66132. "AND r8, r8, %[m]\n\t"
  66133. "AND r9, r9, %[m]\n\t"
  66134. "SBCS r6, r6, r8\n\t"
  66135. "SBCS r7, r7, r9\n\t"
  66136. "STM %[r]!, {r6, r7}\n\t"
  66137. "LDM %[a]!, {r6, r7}\n\t"
  66138. "LDM %[b]!, {r8, r9}\n\t"
  66139. "AND r8, r8, %[m]\n\t"
  66140. "AND r9, r9, %[m]\n\t"
  66141. "SBCS r6, r6, r8\n\t"
  66142. "SBCS r7, r7, r9\n\t"
  66143. "STM %[r]!, {r6, r7}\n\t"
  66144. "LDM %[a]!, {r6, r7}\n\t"
  66145. "LDM %[b]!, {r8, r9}\n\t"
  66146. "AND r8, r8, %[m]\n\t"
  66147. "AND r9, r9, %[m]\n\t"
  66148. "SBCS r6, r6, r8\n\t"
  66149. "SBCS r7, r7, r9\n\t"
  66150. "STM %[r]!, {r6, r7}\n\t"
  66151. "LDM %[a]!, {r6, r7}\n\t"
  66152. "LDM %[b]!, {r8, r9}\n\t"
  66153. "AND r8, r8, %[m]\n\t"
  66154. "AND r9, r9, %[m]\n\t"
  66155. "SBCS r6, r6, r8\n\t"
  66156. "SBCS r7, r7, r9\n\t"
  66157. "STM %[r]!, {r6, r7}\n\t"
  66158. "LDM %[a]!, {r6, r7}\n\t"
  66159. "LDM %[b]!, {r8, r9}\n\t"
  66160. "AND r8, r8, %[m]\n\t"
  66161. "AND r9, r9, %[m]\n\t"
  66162. "SBCS r6, r6, r8\n\t"
  66163. "SBCS r7, r7, r9\n\t"
  66164. "STM %[r]!, {r6, r7}\n\t"
  66165. "SBC %[r], r5, r5\n\t"
  66166. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  66167. :
  66168. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  66169. );
  66170. return (uint32_t)(size_t)r;
  66171. }
  66172. #endif /* WOLFSSL_SP_SMALL */
  66173. #ifdef WOLFSSL_SP_SMALL
  66174. /* Add b to a into r. (r = a + b)
  66175. *
  66176. * r A single precision integer.
  66177. * a A single precision integer.
  66178. * b A single precision integer.
  66179. */
  66180. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66181. static sp_digit sp_1024_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p)
  66182. #else
  66183. static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
  66184. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66185. {
  66186. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66187. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  66188. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  66189. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  66190. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66191. __asm__ __volatile__ (
  66192. "MOV r3, #0x0\n\t"
  66193. "ADD r12, %[a], #0x80\n\t"
  66194. "\n"
  66195. "L_sp_1024_add_32_word:\n\t"
  66196. "ADDS r3, r3, #0xffffffff\n\t"
  66197. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  66198. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  66199. "ADCS r4, r4, r8\n\t"
  66200. "ADCS r5, r5, r9\n\t"
  66201. "ADCS r6, r6, r10\n\t"
  66202. "ADCS r7, r7, r11\n\t"
  66203. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  66204. "MOV r4, #0x0\n\t"
  66205. "ADC r3, r4, #0x0\n\t"
  66206. "CMP %[a], r12\n\t"
  66207. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  66208. "BNE L_sp_1024_add_32_word\n\t"
  66209. #else
  66210. "BNE.N L_sp_1024_add_32_word\n\t"
  66211. #endif
  66212. "MOV %[r], r3\n\t"
  66213. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  66214. :
  66215. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r3", "r12", "cc"
  66216. );
  66217. return (uint32_t)(size_t)r;
  66218. }
  66219. #endif /* WOLFSSL_SP_SMALL */
  66220. #ifdef WOLFSSL_SP_SMALL
  66221. /* Mul a by digit b into r. (r = a * b)
  66222. *
  66223. * r A single precision integer.
  66224. * a A single precision integer.
  66225. * b A single precision digit.
  66226. */
  66227. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66228. static void sp_1024_mul_d_32(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  66229. #else
  66230. static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b)
  66231. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66232. {
  66233. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66234. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  66235. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  66236. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  66237. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66238. __asm__ __volatile__ (
  66239. /* A[0] * B */
  66240. "LDR r8, [%[a]]\n\t"
  66241. "UMULL r5, r3, %[b], r8\n\t"
  66242. "MOV r4, #0x0\n\t"
  66243. "STR r5, [%[r]]\n\t"
  66244. "MOV r5, #0x0\n\t"
  66245. "MOV r9, #0x4\n\t"
  66246. "\n"
  66247. "L_sp_1024_mul_d_32_word:\n\t"
  66248. /* A[i] * B */
  66249. "LDR r8, [%[a], r9]\n\t"
  66250. "UMULL r6, r7, %[b], r8\n\t"
  66251. "ADDS r3, r3, r6\n\t"
  66252. "ADCS r4, r4, r7\n\t"
  66253. "ADC r5, r5, #0x0\n\t"
  66254. "STR r3, [%[r], r9]\n\t"
  66255. "MOV r3, r4\n\t"
  66256. "MOV r4, r5\n\t"
  66257. "MOV r5, #0x0\n\t"
  66258. "ADD r9, r9, #0x4\n\t"
  66259. "CMP r9, #0x80\n\t"
  66260. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  66261. "BLT L_sp_1024_mul_d_32_word\n\t"
  66262. #else
  66263. "BLT.N L_sp_1024_mul_d_32_word\n\t"
  66264. #endif
  66265. "STR r3, [%[r], #128]\n\t"
  66266. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  66267. :
  66268. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
  66269. );
  66270. }
  66271. #else
  66272. /* Mul a by digit b into r. (r = a * b)
  66273. *
  66274. * r A single precision integer.
  66275. * a A single precision integer.
  66276. * b A single precision digit.
  66277. */
  66278. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66279. static void sp_1024_mul_d_32(sp_digit* r_p, const sp_digit* a_p, sp_digit b_p)
  66280. #else
  66281. static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b)
  66282. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66283. {
  66284. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66285. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  66286. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  66287. register sp_digit b __asm__ ("r2") = (sp_digit)b_p;
  66288. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66289. __asm__ __volatile__ (
  66290. /* A[0] * B */
  66291. "LDM %[a]!, {r8}\n\t"
  66292. "UMULL r3, r4, %[b], r8\n\t"
  66293. "STM %[r]!, {r3}\n\t"
  66294. "MOV r5, #0x0\n\t"
  66295. /* A[1] * B */
  66296. "LDM %[a]!, {r8}\n\t"
  66297. "UMLAL r4, r5, %[b], r8\n\t"
  66298. "STM %[r]!, {r4}\n\t"
  66299. "MOV r3, #0x0\n\t"
  66300. /* A[2] * B */
  66301. "LDM %[a]!, {r8}\n\t"
  66302. "UMLAL r5, r3, %[b], r8\n\t"
  66303. "STM %[r]!, {r5}\n\t"
  66304. "MOV r4, #0x0\n\t"
  66305. /* A[3] * B */
  66306. "LDM %[a]!, {r8}\n\t"
  66307. "UMLAL r3, r4, %[b], r8\n\t"
  66308. "STM %[r]!, {r3}\n\t"
  66309. "MOV r5, #0x0\n\t"
  66310. /* A[4] * B */
  66311. "LDM %[a]!, {r8}\n\t"
  66312. "UMLAL r4, r5, %[b], r8\n\t"
  66313. "STM %[r]!, {r4}\n\t"
  66314. "MOV r3, #0x0\n\t"
  66315. /* A[5] * B */
  66316. "LDM %[a]!, {r8}\n\t"
  66317. "UMLAL r5, r3, %[b], r8\n\t"
  66318. "STM %[r]!, {r5}\n\t"
  66319. "MOV r4, #0x0\n\t"
  66320. /* A[6] * B */
  66321. "LDM %[a]!, {r8}\n\t"
  66322. "UMLAL r3, r4, %[b], r8\n\t"
  66323. "STM %[r]!, {r3}\n\t"
  66324. "MOV r5, #0x0\n\t"
  66325. /* A[7] * B */
  66326. "LDM %[a]!, {r8}\n\t"
  66327. "UMLAL r4, r5, %[b], r8\n\t"
  66328. "STM %[r]!, {r4}\n\t"
  66329. "MOV r3, #0x0\n\t"
  66330. /* A[8] * B */
  66331. "LDM %[a]!, {r8}\n\t"
  66332. "UMLAL r5, r3, %[b], r8\n\t"
  66333. "STM %[r]!, {r5}\n\t"
  66334. "MOV r4, #0x0\n\t"
  66335. /* A[9] * B */
  66336. "LDM %[a]!, {r8}\n\t"
  66337. "UMLAL r3, r4, %[b], r8\n\t"
  66338. "STM %[r]!, {r3}\n\t"
  66339. "MOV r5, #0x0\n\t"
  66340. /* A[10] * B */
  66341. "LDM %[a]!, {r8}\n\t"
  66342. "UMLAL r4, r5, %[b], r8\n\t"
  66343. "STM %[r]!, {r4}\n\t"
  66344. "MOV r3, #0x0\n\t"
  66345. /* A[11] * B */
  66346. "LDM %[a]!, {r8}\n\t"
  66347. "UMLAL r5, r3, %[b], r8\n\t"
  66348. "STM %[r]!, {r5}\n\t"
  66349. "MOV r4, #0x0\n\t"
  66350. /* A[12] * B */
  66351. "LDM %[a]!, {r8}\n\t"
  66352. "UMLAL r3, r4, %[b], r8\n\t"
  66353. "STM %[r]!, {r3}\n\t"
  66354. "MOV r5, #0x0\n\t"
  66355. /* A[13] * B */
  66356. "LDM %[a]!, {r8}\n\t"
  66357. "UMLAL r4, r5, %[b], r8\n\t"
  66358. "STM %[r]!, {r4}\n\t"
  66359. "MOV r3, #0x0\n\t"
  66360. /* A[14] * B */
  66361. "LDM %[a]!, {r8}\n\t"
  66362. "UMLAL r5, r3, %[b], r8\n\t"
  66363. "STM %[r]!, {r5}\n\t"
  66364. "MOV r4, #0x0\n\t"
  66365. /* A[15] * B */
  66366. "LDM %[a]!, {r8}\n\t"
  66367. "UMLAL r3, r4, %[b], r8\n\t"
  66368. "STM %[r]!, {r3}\n\t"
  66369. "MOV r5, #0x0\n\t"
  66370. /* A[16] * B */
  66371. "LDM %[a]!, {r8}\n\t"
  66372. "UMLAL r4, r5, %[b], r8\n\t"
  66373. "STM %[r]!, {r4}\n\t"
  66374. "MOV r3, #0x0\n\t"
  66375. /* A[17] * B */
  66376. "LDM %[a]!, {r8}\n\t"
  66377. "UMLAL r5, r3, %[b], r8\n\t"
  66378. "STM %[r]!, {r5}\n\t"
  66379. "MOV r4, #0x0\n\t"
  66380. /* A[18] * B */
  66381. "LDM %[a]!, {r8}\n\t"
  66382. "UMLAL r3, r4, %[b], r8\n\t"
  66383. "STM %[r]!, {r3}\n\t"
  66384. "MOV r5, #0x0\n\t"
  66385. /* A[19] * B */
  66386. "LDM %[a]!, {r8}\n\t"
  66387. "UMLAL r4, r5, %[b], r8\n\t"
  66388. "STM %[r]!, {r4}\n\t"
  66389. "MOV r3, #0x0\n\t"
  66390. /* A[20] * B */
  66391. "LDM %[a]!, {r8}\n\t"
  66392. "UMLAL r5, r3, %[b], r8\n\t"
  66393. "STM %[r]!, {r5}\n\t"
  66394. "MOV r4, #0x0\n\t"
  66395. /* A[21] * B */
  66396. "LDM %[a]!, {r8}\n\t"
  66397. "UMLAL r3, r4, %[b], r8\n\t"
  66398. "STM %[r]!, {r3}\n\t"
  66399. "MOV r5, #0x0\n\t"
  66400. /* A[22] * B */
  66401. "LDM %[a]!, {r8}\n\t"
  66402. "UMLAL r4, r5, %[b], r8\n\t"
  66403. "STM %[r]!, {r4}\n\t"
  66404. "MOV r3, #0x0\n\t"
  66405. /* A[23] * B */
  66406. "LDM %[a]!, {r8}\n\t"
  66407. "UMLAL r5, r3, %[b], r8\n\t"
  66408. "STM %[r]!, {r5}\n\t"
  66409. "MOV r4, #0x0\n\t"
  66410. /* A[24] * B */
  66411. "LDM %[a]!, {r8}\n\t"
  66412. "UMLAL r3, r4, %[b], r8\n\t"
  66413. "STM %[r]!, {r3}\n\t"
  66414. "MOV r5, #0x0\n\t"
  66415. /* A[25] * B */
  66416. "LDM %[a]!, {r8}\n\t"
  66417. "UMLAL r4, r5, %[b], r8\n\t"
  66418. "STM %[r]!, {r4}\n\t"
  66419. "MOV r3, #0x0\n\t"
  66420. /* A[26] * B */
  66421. "LDM %[a]!, {r8}\n\t"
  66422. "UMLAL r5, r3, %[b], r8\n\t"
  66423. "STM %[r]!, {r5}\n\t"
  66424. "MOV r4, #0x0\n\t"
  66425. /* A[27] * B */
  66426. "LDM %[a]!, {r8}\n\t"
  66427. "UMLAL r3, r4, %[b], r8\n\t"
  66428. "STM %[r]!, {r3}\n\t"
  66429. "MOV r5, #0x0\n\t"
  66430. /* A[28] * B */
  66431. "LDM %[a]!, {r8}\n\t"
  66432. "UMLAL r4, r5, %[b], r8\n\t"
  66433. "STM %[r]!, {r4}\n\t"
  66434. "MOV r3, #0x0\n\t"
  66435. /* A[29] * B */
  66436. "LDM %[a]!, {r8}\n\t"
  66437. "UMLAL r5, r3, %[b], r8\n\t"
  66438. "STM %[r]!, {r5}\n\t"
  66439. "MOV r4, #0x0\n\t"
  66440. /* A[30] * B */
  66441. "LDM %[a]!, {r8}\n\t"
  66442. "UMLAL r3, r4, %[b], r8\n\t"
  66443. "STM %[r]!, {r3}\n\t"
  66444. "MOV r5, #0x0\n\t"
  66445. /* A[31] * B */
  66446. "LDM %[a]!, {r8}\n\t"
  66447. "UMLAL r4, r5, %[b], r8\n\t"
  66448. "STM %[r]!, {r4}\n\t"
  66449. "STR r5, [%[r]]\n\t"
  66450. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
  66451. :
  66452. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  66453. );
  66454. }
  66455. #endif /* WOLFSSL_SP_SMALL */
  66456. #ifdef WOLFSSL_SP_USE_UDIV
  66457. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  66458. *
  66459. * d1 The high order half of the number to divide.
  66460. * d0 The low order half of the number to divide.
  66461. * div The divisor.
  66462. * returns the result of the division.
  66463. *
  66464. * Note that this is an approximate div. It may give an answer 1 larger.
  66465. */
  66466. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66467. SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  66468. #else
  66469. SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, sp_digit div)
  66470. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66471. {
  66472. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66473. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  66474. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  66475. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  66476. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66477. __asm__ __volatile__ (
  66478. "LSR r8, %[div], #16\n\t"
  66479. "ADD r5, r8, #0x1\n\t"
  66480. "UDIV r6, %[d1], r5\n\t"
  66481. "LSL r7, %[div], #16\n\t"
  66482. "LSL r6, r6, #16\n\t"
  66483. "UMULL r3, r4, %[div], r6\n\t"
  66484. "SUBS %[d0], %[d0], r3\n\t"
  66485. "SBC %[d1], %[d1], r4\n\t"
  66486. "SUBS r3, %[d1], r5\n\t"
  66487. "SBC r9, r9, r9\n\t"
  66488. "ADD r9, r9, #0x1\n\t"
  66489. "RSB r10, r9, #0x0\n\t"
  66490. "LSL r9, r9, #16\n\t"
  66491. "AND r7, r7, r10\n\t"
  66492. "AND r8, r8, r10\n\t"
  66493. "SUBS %[d0], %[d0], r7\n\t"
  66494. "ADD r6, r6, r9\n\t"
  66495. "SBC %[d1], %[d1], r8\n\t"
  66496. "LSL r4, %[d1], #16\n\t"
  66497. "LSR r3, %[d0], #16\n\t"
  66498. "ORR r3, r3, r4\n\t"
  66499. "UDIV r3, r3, r5\n\t"
  66500. "ADD r6, r6, r3\n\t"
  66501. "UMULL r3, r4, %[div], r3\n\t"
  66502. "SUBS %[d0], %[d0], r3\n\t"
  66503. "SBC %[d1], %[d1], r4\n\t"
  66504. "LSL r4, %[d1], #16\n\t"
  66505. "LSR r3, %[d0], #16\n\t"
  66506. "ORR r3, r3, r4\n\t"
  66507. "UDIV r3, r3, r5\n\t"
  66508. "ADD r6, r6, r3\n\t"
  66509. "MUL r3, %[div], r3\n\t"
  66510. "SUB %[d0], %[d0], r3\n\t"
  66511. "UDIV r3, %[d0], %[div]\n\t"
  66512. "ADD %[d1], r6, r3\n\t"
  66513. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  66514. :
  66515. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  66516. );
  66517. return (uint32_t)(size_t)d1;
  66518. }
  66519. #else
  66520. /* Divide the double width number (d1|d0) by the divisor. (d1|d0 / div)
  66521. *
  66522. * d1 The high order half of the number to divide.
  66523. * d0 The low order half of the number to divide.
  66524. * div The divisor.
  66525. * returns the result of the division.
  66526. *
  66527. * Note that this is an approximate div. It may give an answer 1 larger.
  66528. */
  66529. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66530. SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1_p, sp_digit d0_p, sp_digit div_p)
  66531. #else
  66532. SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, sp_digit div)
  66533. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66534. {
  66535. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66536. register sp_digit d1 __asm__ ("r0") = (sp_digit)d1_p;
  66537. register sp_digit d0 __asm__ ("r1") = (sp_digit)d0_p;
  66538. register sp_digit div __asm__ ("r2") = (sp_digit)div_p;
  66539. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66540. __asm__ __volatile__ (
  66541. "LSR r5, %[div], #1\n\t"
  66542. "ADD r5, r5, #0x1\n\t"
  66543. "MOV r6, %[d0]\n\t"
  66544. "MOV r7, %[d1]\n\t"
  66545. /* Do top 32 */
  66546. "SUBS r8, r5, r7\n\t"
  66547. "SBC r8, r8, r8\n\t"
  66548. "MOV r3, #0x0\n\t"
  66549. "SUB r3, r3, r8\n\t"
  66550. "AND r8, r8, r5\n\t"
  66551. "SUBS r7, r7, r8\n\t"
  66552. /* Next 30 bits */
  66553. "MOV r4, #0x1d\n\t"
  66554. "\n"
  66555. "L_div_1024_word_32_bit:\n\t"
  66556. "LSLS r6, r6, #1\n\t"
  66557. "ADC r7, r7, r7\n\t"
  66558. "SUBS r8, r5, r7\n\t"
  66559. "SBC r8, r8, r8\n\t"
  66560. "ADD r3, r3, r3\n\t"
  66561. "SUB r3, r3, r8\n\t"
  66562. "AND r8, r8, r5\n\t"
  66563. "SUBS r7, r7, r8\n\t"
  66564. "SUBS r4, r4, #0x1\n\t"
  66565. "bpl L_div_1024_word_32_bit\n\t"
  66566. "ADD r3, r3, r3\n\t"
  66567. "ADD r3, r3, #0x1\n\t"
  66568. "UMULL r6, r7, r3, %[div]\n\t"
  66569. "SUBS r9, %[d0], r6\n\t"
  66570. "SBC r10, %[d1], r7\n\t"
  66571. "ADD r3, r3, r10\n\t"
  66572. "UMULL r6, r7, r3, %[div]\n\t"
  66573. "SUBS r9, %[d0], r6\n\t"
  66574. "SBC r10, %[d1], r7\n\t"
  66575. "ADD r3, r3, r10\n\t"
  66576. "UMULL r6, r7, r3, %[div]\n\t"
  66577. "SUBS r9, %[d0], r6\n\t"
  66578. "SBC r10, %[d1], r7\n\t"
  66579. "ADD r3, r3, r10\n\t"
  66580. "SUBS r8, %[div], r9\n\t"
  66581. "SBC r8, r8, r8\n\t"
  66582. "SUB %[d1], r3, r8\n\t"
  66583. : [d1] "+r" (d1), [d0] "+r" (d0), [div] "+r" (div)
  66584. :
  66585. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  66586. );
  66587. return (uint32_t)(size_t)d1;
  66588. }
  66589. #endif
  66590. /* AND m into each word of a and store in r.
  66591. *
  66592. * r A single precision integer.
  66593. * a A single precision integer.
  66594. * m Mask to AND against each digit.
  66595. */
  66596. static void sp_1024_mask_32(sp_digit* r, const sp_digit* a, sp_digit m)
  66597. {
  66598. #ifdef WOLFSSL_SP_SMALL
  66599. int i;
  66600. for (i=0; i<32; i++) {
  66601. r[i] = a[i] & m;
  66602. }
  66603. #else
  66604. int i;
  66605. for (i = 0; i < 32; i += 8) {
  66606. r[i+0] = a[i+0] & m;
  66607. r[i+1] = a[i+1] & m;
  66608. r[i+2] = a[i+2] & m;
  66609. r[i+3] = a[i+3] & m;
  66610. r[i+4] = a[i+4] & m;
  66611. r[i+5] = a[i+5] & m;
  66612. r[i+6] = a[i+6] & m;
  66613. r[i+7] = a[i+7] & m;
  66614. }
  66615. #endif
  66616. }
  66617. /* Compare a with b in constant time.
  66618. *
  66619. * a A single precision integer.
  66620. * b A single precision integer.
  66621. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  66622. * respectively.
  66623. */
  66624. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66625. static sp_int32 sp_1024_cmp_32(const sp_digit* a_p, const sp_digit* b_p)
  66626. #else
  66627. static sp_int32 sp_1024_cmp_32(const sp_digit* a, const sp_digit* b)
  66628. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66629. {
  66630. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  66631. register const sp_digit* a __asm__ ("r0") = (const sp_digit*)a_p;
  66632. register const sp_digit* b __asm__ ("r1") = (const sp_digit*)b_p;
  66633. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  66634. __asm__ __volatile__ (
  66635. "MOV r2, #0xffffffff\n\t"
  66636. "MOV r8, #0x1\n\t"
  66637. "MOV r7, #0x0\n\t"
  66638. "MOV r3, #0xffffffff\n\t"
  66639. #ifdef WOLFSSL_SP_SMALL
  66640. "MOV r6, #0x7c\n\t"
  66641. "\n"
  66642. "L_sp_1024_cmp_32_words:\n\t"
  66643. "LDR r4, [%[a], r6]\n\t"
  66644. "LDR r5, [%[b], r6]\n\t"
  66645. "AND r4, r4, r3\n\t"
  66646. "AND r5, r5, r3\n\t"
  66647. "SUBS r4, r4, r5\n\t"
  66648. "IT hi\n\t"
  66649. "movhi r2, r8\n\t"
  66650. "IT lo\n\t"
  66651. "movlo r2, r3\n\t"
  66652. "IT ne\n\t"
  66653. "movne r3, r7\n\t"
  66654. "SUBS r6, r6, #0x4\n\t"
  66655. "bcs L_sp_1024_cmp_32_words\n\t"
  66656. "EOR r2, r2, r3\n\t"
  66657. #else
  66658. "LDR r4, [%[a], #124]\n\t"
  66659. "LDR r5, [%[b], #124]\n\t"
  66660. "AND r4, r4, r3\n\t"
  66661. "AND r5, r5, r3\n\t"
  66662. "SUBS r4, r4, r5\n\t"
  66663. "IT hi\n\t"
  66664. "movhi r2, r8\n\t"
  66665. "IT lo\n\t"
  66666. "movlo r2, r3\n\t"
  66667. "IT ne\n\t"
  66668. "movne r3, r7\n\t"
  66669. "LDR r4, [%[a], #120]\n\t"
  66670. "LDR r5, [%[b], #120]\n\t"
  66671. "AND r4, r4, r3\n\t"
  66672. "AND r5, r5, r3\n\t"
  66673. "SUBS r4, r4, r5\n\t"
  66674. "IT hi\n\t"
  66675. "movhi r2, r8\n\t"
  66676. "IT lo\n\t"
  66677. "movlo r2, r3\n\t"
  66678. "IT ne\n\t"
  66679. "movne r3, r7\n\t"
  66680. "LDR r4, [%[a], #116]\n\t"
  66681. "LDR r5, [%[b], #116]\n\t"
  66682. "AND r4, r4, r3\n\t"
  66683. "AND r5, r5, r3\n\t"
  66684. "SUBS r4, r4, r5\n\t"
  66685. "IT hi\n\t"
  66686. "movhi r2, r8\n\t"
  66687. "IT lo\n\t"
  66688. "movlo r2, r3\n\t"
  66689. "IT ne\n\t"
  66690. "movne r3, r7\n\t"
  66691. "LDR r4, [%[a], #112]\n\t"
  66692. "LDR r5, [%[b], #112]\n\t"
  66693. "AND r4, r4, r3\n\t"
  66694. "AND r5, r5, r3\n\t"
  66695. "SUBS r4, r4, r5\n\t"
  66696. "IT hi\n\t"
  66697. "movhi r2, r8\n\t"
  66698. "IT lo\n\t"
  66699. "movlo r2, r3\n\t"
  66700. "IT ne\n\t"
  66701. "movne r3, r7\n\t"
  66702. "LDR r4, [%[a], #108]\n\t"
  66703. "LDR r5, [%[b], #108]\n\t"
  66704. "AND r4, r4, r3\n\t"
  66705. "AND r5, r5, r3\n\t"
  66706. "SUBS r4, r4, r5\n\t"
  66707. "IT hi\n\t"
  66708. "movhi r2, r8\n\t"
  66709. "IT lo\n\t"
  66710. "movlo r2, r3\n\t"
  66711. "IT ne\n\t"
  66712. "movne r3, r7\n\t"
  66713. "LDR r4, [%[a], #104]\n\t"
  66714. "LDR r5, [%[b], #104]\n\t"
  66715. "AND r4, r4, r3\n\t"
  66716. "AND r5, r5, r3\n\t"
  66717. "SUBS r4, r4, r5\n\t"
  66718. "IT hi\n\t"
  66719. "movhi r2, r8\n\t"
  66720. "IT lo\n\t"
  66721. "movlo r2, r3\n\t"
  66722. "IT ne\n\t"
  66723. "movne r3, r7\n\t"
  66724. "LDR r4, [%[a], #100]\n\t"
  66725. "LDR r5, [%[b], #100]\n\t"
  66726. "AND r4, r4, r3\n\t"
  66727. "AND r5, r5, r3\n\t"
  66728. "SUBS r4, r4, r5\n\t"
  66729. "IT hi\n\t"
  66730. "movhi r2, r8\n\t"
  66731. "IT lo\n\t"
  66732. "movlo r2, r3\n\t"
  66733. "IT ne\n\t"
  66734. "movne r3, r7\n\t"
  66735. "LDR r4, [%[a], #96]\n\t"
  66736. "LDR r5, [%[b], #96]\n\t"
  66737. "AND r4, r4, r3\n\t"
  66738. "AND r5, r5, r3\n\t"
  66739. "SUBS r4, r4, r5\n\t"
  66740. "IT hi\n\t"
  66741. "movhi r2, r8\n\t"
  66742. "IT lo\n\t"
  66743. "movlo r2, r3\n\t"
  66744. "IT ne\n\t"
  66745. "movne r3, r7\n\t"
  66746. "LDR r4, [%[a], #92]\n\t"
  66747. "LDR r5, [%[b], #92]\n\t"
  66748. "AND r4, r4, r3\n\t"
  66749. "AND r5, r5, r3\n\t"
  66750. "SUBS r4, r4, r5\n\t"
  66751. "IT hi\n\t"
  66752. "movhi r2, r8\n\t"
  66753. "IT lo\n\t"
  66754. "movlo r2, r3\n\t"
  66755. "IT ne\n\t"
  66756. "movne r3, r7\n\t"
  66757. "LDR r4, [%[a], #88]\n\t"
  66758. "LDR r5, [%[b], #88]\n\t"
  66759. "AND r4, r4, r3\n\t"
  66760. "AND r5, r5, r3\n\t"
  66761. "SUBS r4, r4, r5\n\t"
  66762. "IT hi\n\t"
  66763. "movhi r2, r8\n\t"
  66764. "IT lo\n\t"
  66765. "movlo r2, r3\n\t"
  66766. "IT ne\n\t"
  66767. "movne r3, r7\n\t"
  66768. "LDR r4, [%[a], #84]\n\t"
  66769. "LDR r5, [%[b], #84]\n\t"
  66770. "AND r4, r4, r3\n\t"
  66771. "AND r5, r5, r3\n\t"
  66772. "SUBS r4, r4, r5\n\t"
  66773. "IT hi\n\t"
  66774. "movhi r2, r8\n\t"
  66775. "IT lo\n\t"
  66776. "movlo r2, r3\n\t"
  66777. "IT ne\n\t"
  66778. "movne r3, r7\n\t"
  66779. "LDR r4, [%[a], #80]\n\t"
  66780. "LDR r5, [%[b], #80]\n\t"
  66781. "AND r4, r4, r3\n\t"
  66782. "AND r5, r5, r3\n\t"
  66783. "SUBS r4, r4, r5\n\t"
  66784. "IT hi\n\t"
  66785. "movhi r2, r8\n\t"
  66786. "IT lo\n\t"
  66787. "movlo r2, r3\n\t"
  66788. "IT ne\n\t"
  66789. "movne r3, r7\n\t"
  66790. "LDR r4, [%[a], #76]\n\t"
  66791. "LDR r5, [%[b], #76]\n\t"
  66792. "AND r4, r4, r3\n\t"
  66793. "AND r5, r5, r3\n\t"
  66794. "SUBS r4, r4, r5\n\t"
  66795. "IT hi\n\t"
  66796. "movhi r2, r8\n\t"
  66797. "IT lo\n\t"
  66798. "movlo r2, r3\n\t"
  66799. "IT ne\n\t"
  66800. "movne r3, r7\n\t"
  66801. "LDR r4, [%[a], #72]\n\t"
  66802. "LDR r5, [%[b], #72]\n\t"
  66803. "AND r4, r4, r3\n\t"
  66804. "AND r5, r5, r3\n\t"
  66805. "SUBS r4, r4, r5\n\t"
  66806. "IT hi\n\t"
  66807. "movhi r2, r8\n\t"
  66808. "IT lo\n\t"
  66809. "movlo r2, r3\n\t"
  66810. "IT ne\n\t"
  66811. "movne r3, r7\n\t"
  66812. "LDR r4, [%[a], #68]\n\t"
  66813. "LDR r5, [%[b], #68]\n\t"
  66814. "AND r4, r4, r3\n\t"
  66815. "AND r5, r5, r3\n\t"
  66816. "SUBS r4, r4, r5\n\t"
  66817. "IT hi\n\t"
  66818. "movhi r2, r8\n\t"
  66819. "IT lo\n\t"
  66820. "movlo r2, r3\n\t"
  66821. "IT ne\n\t"
  66822. "movne r3, r7\n\t"
  66823. "LDR r4, [%[a], #64]\n\t"
  66824. "LDR r5, [%[b], #64]\n\t"
  66825. "AND r4, r4, r3\n\t"
  66826. "AND r5, r5, r3\n\t"
  66827. "SUBS r4, r4, r5\n\t"
  66828. "IT hi\n\t"
  66829. "movhi r2, r8\n\t"
  66830. "IT lo\n\t"
  66831. "movlo r2, r3\n\t"
  66832. "IT ne\n\t"
  66833. "movne r3, r7\n\t"
  66834. "LDR r4, [%[a], #60]\n\t"
  66835. "LDR r5, [%[b], #60]\n\t"
  66836. "AND r4, r4, r3\n\t"
  66837. "AND r5, r5, r3\n\t"
  66838. "SUBS r4, r4, r5\n\t"
  66839. "IT hi\n\t"
  66840. "movhi r2, r8\n\t"
  66841. "IT lo\n\t"
  66842. "movlo r2, r3\n\t"
  66843. "IT ne\n\t"
  66844. "movne r3, r7\n\t"
  66845. "LDR r4, [%[a], #56]\n\t"
  66846. "LDR r5, [%[b], #56]\n\t"
  66847. "AND r4, r4, r3\n\t"
  66848. "AND r5, r5, r3\n\t"
  66849. "SUBS r4, r4, r5\n\t"
  66850. "IT hi\n\t"
  66851. "movhi r2, r8\n\t"
  66852. "IT lo\n\t"
  66853. "movlo r2, r3\n\t"
  66854. "IT ne\n\t"
  66855. "movne r3, r7\n\t"
  66856. "LDR r4, [%[a], #52]\n\t"
  66857. "LDR r5, [%[b], #52]\n\t"
  66858. "AND r4, r4, r3\n\t"
  66859. "AND r5, r5, r3\n\t"
  66860. "SUBS r4, r4, r5\n\t"
  66861. "IT hi\n\t"
  66862. "movhi r2, r8\n\t"
  66863. "IT lo\n\t"
  66864. "movlo r2, r3\n\t"
  66865. "IT ne\n\t"
  66866. "movne r3, r7\n\t"
  66867. "LDR r4, [%[a], #48]\n\t"
  66868. "LDR r5, [%[b], #48]\n\t"
  66869. "AND r4, r4, r3\n\t"
  66870. "AND r5, r5, r3\n\t"
  66871. "SUBS r4, r4, r5\n\t"
  66872. "IT hi\n\t"
  66873. "movhi r2, r8\n\t"
  66874. "IT lo\n\t"
  66875. "movlo r2, r3\n\t"
  66876. "IT ne\n\t"
  66877. "movne r3, r7\n\t"
  66878. "LDR r4, [%[a], #44]\n\t"
  66879. "LDR r5, [%[b], #44]\n\t"
  66880. "AND r4, r4, r3\n\t"
  66881. "AND r5, r5, r3\n\t"
  66882. "SUBS r4, r4, r5\n\t"
  66883. "IT hi\n\t"
  66884. "movhi r2, r8\n\t"
  66885. "IT lo\n\t"
  66886. "movlo r2, r3\n\t"
  66887. "IT ne\n\t"
  66888. "movne r3, r7\n\t"
  66889. "LDR r4, [%[a], #40]\n\t"
  66890. "LDR r5, [%[b], #40]\n\t"
  66891. "AND r4, r4, r3\n\t"
  66892. "AND r5, r5, r3\n\t"
  66893. "SUBS r4, r4, r5\n\t"
  66894. "IT hi\n\t"
  66895. "movhi r2, r8\n\t"
  66896. "IT lo\n\t"
  66897. "movlo r2, r3\n\t"
  66898. "IT ne\n\t"
  66899. "movne r3, r7\n\t"
  66900. "LDR r4, [%[a], #36]\n\t"
  66901. "LDR r5, [%[b], #36]\n\t"
  66902. "AND r4, r4, r3\n\t"
  66903. "AND r5, r5, r3\n\t"
  66904. "SUBS r4, r4, r5\n\t"
  66905. "IT hi\n\t"
  66906. "movhi r2, r8\n\t"
  66907. "IT lo\n\t"
  66908. "movlo r2, r3\n\t"
  66909. "IT ne\n\t"
  66910. "movne r3, r7\n\t"
  66911. "LDR r4, [%[a], #32]\n\t"
  66912. "LDR r5, [%[b], #32]\n\t"
  66913. "AND r4, r4, r3\n\t"
  66914. "AND r5, r5, r3\n\t"
  66915. "SUBS r4, r4, r5\n\t"
  66916. "IT hi\n\t"
  66917. "movhi r2, r8\n\t"
  66918. "IT lo\n\t"
  66919. "movlo r2, r3\n\t"
  66920. "IT ne\n\t"
  66921. "movne r3, r7\n\t"
  66922. "LDR r4, [%[a], #28]\n\t"
  66923. "LDR r5, [%[b], #28]\n\t"
  66924. "AND r4, r4, r3\n\t"
  66925. "AND r5, r5, r3\n\t"
  66926. "SUBS r4, r4, r5\n\t"
  66927. "IT hi\n\t"
  66928. "movhi r2, r8\n\t"
  66929. "IT lo\n\t"
  66930. "movlo r2, r3\n\t"
  66931. "IT ne\n\t"
  66932. "movne r3, r7\n\t"
  66933. "LDR r4, [%[a], #24]\n\t"
  66934. "LDR r5, [%[b], #24]\n\t"
  66935. "AND r4, r4, r3\n\t"
  66936. "AND r5, r5, r3\n\t"
  66937. "SUBS r4, r4, r5\n\t"
  66938. "IT hi\n\t"
  66939. "movhi r2, r8\n\t"
  66940. "IT lo\n\t"
  66941. "movlo r2, r3\n\t"
  66942. "IT ne\n\t"
  66943. "movne r3, r7\n\t"
  66944. "LDR r4, [%[a], #20]\n\t"
  66945. "LDR r5, [%[b], #20]\n\t"
  66946. "AND r4, r4, r3\n\t"
  66947. "AND r5, r5, r3\n\t"
  66948. "SUBS r4, r4, r5\n\t"
  66949. "IT hi\n\t"
  66950. "movhi r2, r8\n\t"
  66951. "IT lo\n\t"
  66952. "movlo r2, r3\n\t"
  66953. "IT ne\n\t"
  66954. "movne r3, r7\n\t"
  66955. "LDR r4, [%[a], #16]\n\t"
  66956. "LDR r5, [%[b], #16]\n\t"
  66957. "AND r4, r4, r3\n\t"
  66958. "AND r5, r5, r3\n\t"
  66959. "SUBS r4, r4, r5\n\t"
  66960. "IT hi\n\t"
  66961. "movhi r2, r8\n\t"
  66962. "IT lo\n\t"
  66963. "movlo r2, r3\n\t"
  66964. "IT ne\n\t"
  66965. "movne r3, r7\n\t"
  66966. "LDR r4, [%[a], #12]\n\t"
  66967. "LDR r5, [%[b], #12]\n\t"
  66968. "AND r4, r4, r3\n\t"
  66969. "AND r5, r5, r3\n\t"
  66970. "SUBS r4, r4, r5\n\t"
  66971. "IT hi\n\t"
  66972. "movhi r2, r8\n\t"
  66973. "IT lo\n\t"
  66974. "movlo r2, r3\n\t"
  66975. "IT ne\n\t"
  66976. "movne r3, r7\n\t"
  66977. "LDR r4, [%[a], #8]\n\t"
  66978. "LDR r5, [%[b], #8]\n\t"
  66979. "AND r4, r4, r3\n\t"
  66980. "AND r5, r5, r3\n\t"
  66981. "SUBS r4, r4, r5\n\t"
  66982. "IT hi\n\t"
  66983. "movhi r2, r8\n\t"
  66984. "IT lo\n\t"
  66985. "movlo r2, r3\n\t"
  66986. "IT ne\n\t"
  66987. "movne r3, r7\n\t"
  66988. "LDR r4, [%[a], #4]\n\t"
  66989. "LDR r5, [%[b], #4]\n\t"
  66990. "AND r4, r4, r3\n\t"
  66991. "AND r5, r5, r3\n\t"
  66992. "SUBS r4, r4, r5\n\t"
  66993. "IT hi\n\t"
  66994. "movhi r2, r8\n\t"
  66995. "IT lo\n\t"
  66996. "movlo r2, r3\n\t"
  66997. "IT ne\n\t"
  66998. "movne r3, r7\n\t"
  66999. "LDR r4, [%[a]]\n\t"
  67000. "LDR r5, [%[b]]\n\t"
  67001. "AND r4, r4, r3\n\t"
  67002. "AND r5, r5, r3\n\t"
  67003. "SUBS r4, r4, r5\n\t"
  67004. "IT hi\n\t"
  67005. "movhi r2, r8\n\t"
  67006. "IT lo\n\t"
  67007. "movlo r2, r3\n\t"
  67008. "IT ne\n\t"
  67009. "movne r3, r7\n\t"
  67010. "EOR r2, r2, r3\n\t"
  67011. #endif /*WOLFSSL_SP_SMALL */
  67012. "MOV %[a], r2\n\t"
  67013. : [a] "+r" (a), [b] "+r" (b)
  67014. :
  67015. : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "cc"
  67016. );
  67017. return (uint32_t)(size_t)a;
  67018. }
  67019. /* Divide d in a and put remainder into r (m*d + r = a)
  67020. * m is not calculated as it is not needed at this time.
  67021. *
  67022. * a Number to be divided.
  67023. * d Number to divide with.
  67024. * m Multiplier result.
  67025. * r Remainder from the division.
  67026. * returns MP_OKAY indicating success.
  67027. */
  67028. static WC_INLINE int sp_1024_div_32(const sp_digit* a, const sp_digit* d,
  67029. sp_digit* m, sp_digit* r)
  67030. {
  67031. sp_digit t1[64], t2[33];
  67032. sp_digit div, r1;
  67033. int i;
  67034. (void)m;
  67035. div = d[31];
  67036. XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
  67037. r1 = sp_1024_cmp_32(&t1[32], d) >= 0;
  67038. sp_1024_cond_sub_32(&t1[32], &t1[32], d, (sp_digit)0 - r1);
  67039. for (i = 31; i >= 0; i--) {
  67040. volatile sp_digit mask = (sp_digit)0 - (t1[32 + i] == div);
  67041. sp_digit hi = t1[32 + i] + mask;
  67042. r1 = div_1024_word_32(hi, t1[32 + i - 1], div);
  67043. r1 |= mask;
  67044. sp_1024_mul_d_32(t2, d, r1);
  67045. t1[32 + i] += sp_1024_sub_in_place_32(&t1[i], t2);
  67046. t1[32 + i] -= t2[32];
  67047. sp_1024_mask_32(t2, d, t1[32 + i]);
  67048. t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
  67049. sp_1024_mask_32(t2, d, t1[32 + i]);
  67050. t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2);
  67051. }
  67052. r1 = sp_1024_cmp_32(t1, d) >= 0;
  67053. sp_1024_cond_sub_32(r, t1, d, (sp_digit)0 - r1);
  67054. return MP_OKAY;
  67055. }
  67056. /* Reduce a modulo m into r. (r = a mod m)
  67057. *
  67058. * r A single precision number that is the reduced result.
  67059. * a A single precision number that is to be reduced.
  67060. * m A single precision number that is the modulus to reduce with.
  67061. * returns MP_OKAY indicating success.
  67062. */
  67063. static WC_INLINE int sp_1024_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
  67064. {
  67065. return sp_1024_div_32(a, m, NULL, r);
  67066. }
  67067. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  67068. *
  67069. * r The resulting Montgomery form number.
  67070. * a The number to convert.
  67071. * m The modulus (prime).
  67072. * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
  67073. */
  67074. static int sp_1024_mod_mul_norm_32(sp_digit* r, const sp_digit* a,
  67075. const sp_digit* m)
  67076. {
  67077. sp_1024_mul_32(r, a, p1024_norm_mod);
  67078. return sp_1024_mod_32(r, r, m);
  67079. }
  67080. #ifdef WOLFCRYPT_HAVE_SAKKE
  67081. /* Create a new point.
  67082. *
  67083. * heap [in] Buffer to allocate dynamic memory from.
  67084. * sp [in] Data for point - only if not allocating.
  67085. * p [out] New point.
  67086. * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
  67087. */
  67088. static int sp_1024_point_new_ex_32(void* heap, sp_point_1024* sp,
  67089. sp_point_1024** p)
  67090. {
  67091. int ret = MP_OKAY;
  67092. (void)heap;
  67093. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  67094. defined(WOLFSSL_SP_SMALL_STACK)
  67095. (void)sp;
  67096. *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC);
  67097. #else
  67098. *p = sp;
  67099. #endif
  67100. if (*p == NULL) {
  67101. ret = MEMORY_E;
  67102. }
  67103. return ret;
  67104. }
  67105. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  67106. defined(WOLFSSL_SP_SMALL_STACK)
  67107. /* Allocate memory for point and return error. */
  67108. #define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), NULL, &(p))
  67109. #else
  67110. /* Set pointer to data and return no error. */
  67111. #define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), &(sp), &(p))
  67112. #endif
  67113. #endif /* WOLFCRYPT_HAVE_SAKKE */
  67114. #ifdef WOLFCRYPT_HAVE_SAKKE
  67115. /* Free the point.
  67116. *
  67117. * p [in,out] Point to free.
  67118. * clear [in] Indicates whether to zeroize point.
  67119. * heap [in] Buffer from which dynamic memory was allocate from.
  67120. */
  67121. static void sp_1024_point_free_32(sp_point_1024* p, int clear, void* heap)
  67122. {
  67123. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  67124. defined(WOLFSSL_SP_SMALL_STACK)
  67125. /* If valid pointer then clear point data if requested and free data. */
  67126. if (p != NULL) {
  67127. if (clear != 0) {
  67128. XMEMSET(p, 0, sizeof(*p));
  67129. }
  67130. XFREE(p, heap, DYNAMIC_TYPE_ECC);
  67131. }
  67132. #else
  67133. /* Clear point data if requested. */
  67134. if ((p != NULL) && (clear != 0)) {
  67135. XMEMSET(p, 0, sizeof(*p));
  67136. }
  67137. #endif
  67138. (void)heap;
  67139. }
  67140. #endif /* WOLFCRYPT_HAVE_SAKKE */
  67141. /* Convert an mp_int to an array of sp_digit.
  67142. *
  67143. * r A single precision integer.
  67144. * size Maximum number of bytes to convert
  67145. * a A multi-precision integer.
  67146. */
  67147. static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
  67148. {
  67149. #if DIGIT_BIT == 32
  67150. int i;
  67151. sp_digit j = (sp_digit)0 - (sp_digit)a->used;
  67152. int o = 0;
  67153. for (i = 0; i < size; i++) {
  67154. sp_digit mask = (sp_digit)0 - (j >> 31);
  67155. r[i] = a->dp[o] & mask;
  67156. j++;
  67157. o += (int)(j >> 31);
  67158. }
  67159. #elif DIGIT_BIT > 32
  67160. unsigned int i;
  67161. int j = 0;
  67162. word32 s = 0;
  67163. r[0] = 0;
  67164. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  67165. r[j] |= ((sp_digit)a->dp[i] << s);
  67166. r[j] &= 0xffffffff;
  67167. s = 32U - s;
  67168. if (j + 1 >= size) {
  67169. break;
  67170. }
  67171. /* lint allow cast of mismatch word32 and mp_digit */
  67172. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  67173. while ((s + 32U) <= (word32)DIGIT_BIT) {
  67174. s += 32U;
  67175. r[j] &= 0xffffffff;
  67176. if (j + 1 >= size) {
  67177. break;
  67178. }
  67179. if (s < (word32)DIGIT_BIT) {
  67180. /* lint allow cast of mismatch word32 and mp_digit */
  67181. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  67182. }
  67183. else {
  67184. r[++j] = (sp_digit)0;
  67185. }
  67186. }
  67187. s = (word32)DIGIT_BIT - s;
  67188. }
  67189. for (j++; j < size; j++) {
  67190. r[j] = 0;
  67191. }
  67192. #else
  67193. unsigned int i;
  67194. int j = 0;
  67195. int s = 0;
  67196. r[0] = 0;
  67197. for (i = 0; i < (unsigned int)a->used && j < size; i++) {
  67198. r[j] |= ((sp_digit)a->dp[i]) << s;
  67199. if (s + DIGIT_BIT >= 32) {
  67200. r[j] &= 0xffffffff;
  67201. if (j + 1 >= size) {
  67202. break;
  67203. }
  67204. s = 32 - s;
  67205. if (s == DIGIT_BIT) {
  67206. r[++j] = 0;
  67207. s = 0;
  67208. }
  67209. else {
  67210. r[++j] = a->dp[i] >> s;
  67211. s = DIGIT_BIT - s;
  67212. }
  67213. }
  67214. else {
  67215. s += DIGIT_BIT;
  67216. }
  67217. }
  67218. for (j++; j < size; j++) {
  67219. r[j] = 0;
  67220. }
  67221. #endif
  67222. }
  67223. /* Convert a point of type ecc_point to type sp_point_1024.
  67224. *
  67225. * p Point of type sp_point_1024 (result).
  67226. * pm Point of type ecc_point.
  67227. */
  67228. static void sp_1024_point_from_ecc_point_32(sp_point_1024* p,
  67229. const ecc_point* pm)
  67230. {
  67231. XMEMSET(p->x, 0, sizeof(p->x));
  67232. XMEMSET(p->y, 0, sizeof(p->y));
  67233. XMEMSET(p->z, 0, sizeof(p->z));
  67234. sp_1024_from_mp(p->x, 32, pm->x);
  67235. sp_1024_from_mp(p->y, 32, pm->y);
  67236. sp_1024_from_mp(p->z, 32, pm->z);
  67237. p->infinity = 0;
  67238. }
  67239. /* Convert an array of sp_digit to an mp_int.
  67240. *
  67241. * a A single precision integer.
  67242. * r A multi-precision integer.
  67243. */
  67244. static int sp_1024_to_mp(const sp_digit* a, mp_int* r)
  67245. {
  67246. int err;
  67247. err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT);
  67248. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  67249. #if DIGIT_BIT == 32
  67250. XMEMCPY(r->dp, a, sizeof(sp_digit) * 32);
  67251. r->used = 32;
  67252. mp_clamp(r);
  67253. #elif DIGIT_BIT < 32
  67254. int i;
  67255. int j = 0;
  67256. int s = 0;
  67257. r->dp[0] = 0;
  67258. for (i = 0; i < 32; i++) {
  67259. r->dp[j] |= (mp_digit)(a[i] << s);
  67260. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  67261. s = DIGIT_BIT - s;
  67262. r->dp[++j] = (mp_digit)(a[i] >> s);
  67263. while (s + DIGIT_BIT <= 32) {
  67264. s += DIGIT_BIT;
  67265. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  67266. if (s == SP_WORD_SIZE) {
  67267. r->dp[j] = 0;
  67268. }
  67269. else {
  67270. r->dp[j] = (mp_digit)(a[i] >> s);
  67271. }
  67272. }
  67273. s = 32 - s;
  67274. }
  67275. r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
  67276. mp_clamp(r);
  67277. #else
  67278. int i;
  67279. int j = 0;
  67280. int s = 0;
  67281. r->dp[0] = 0;
  67282. for (i = 0; i < 32; i++) {
  67283. r->dp[j] |= ((mp_digit)a[i]) << s;
  67284. if (s + 32 >= DIGIT_BIT) {
  67285. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  67286. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  67287. #endif
  67288. s = DIGIT_BIT - s;
  67289. r->dp[++j] = a[i] >> s;
  67290. s = 32 - s;
  67291. }
  67292. else {
  67293. s += 32;
  67294. }
  67295. }
  67296. r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
  67297. mp_clamp(r);
  67298. #endif
  67299. }
  67300. return err;
  67301. }
  67302. /* Convert a point of type sp_point_1024 to type ecc_point.
  67303. *
  67304. * p Point of type sp_point_1024.
  67305. * pm Point of type ecc_point (result).
  67306. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  67307. * MP_OKAY.
  67308. */
  67309. static int sp_1024_point_to_ecc_point_32(const sp_point_1024* p, ecc_point* pm)
  67310. {
  67311. int err;
  67312. err = sp_1024_to_mp(p->x, pm->x);
  67313. if (err == MP_OKAY) {
  67314. err = sp_1024_to_mp(p->y, pm->y);
  67315. }
  67316. if (err == MP_OKAY) {
  67317. err = sp_1024_to_mp(p->z, pm->z);
  67318. }
  67319. return err;
  67320. }
  67321. #ifdef WOLFSSL_SP_NO_UMAAL
  67322. /* Reduce the number back to 1024 bits using Montgomery reduction.
  67323. *
  67324. * a A single precision number to reduce in place.
  67325. * m The single precision number representing the modulus.
  67326. * mp The digit representing the negative inverse of m mod 2^n.
  67327. */
  67328. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  67329. SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  67330. #else
  67331. SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp)
  67332. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  67333. {
  67334. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  67335. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  67336. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  67337. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  67338. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  67339. __asm__ __volatile__ (
  67340. "LDR lr, [%[m]]\n\t"
  67341. /* i = 0 */
  67342. "MOV r11, #0x0\n\t"
  67343. "MOV r3, #0x0\n\t"
  67344. "LDR r4, [%[a]]\n\t"
  67345. "LDR r5, [%[a], #4]\n\t"
  67346. "\n"
  67347. "L_sp_1024_mont_reduce_32_word:\n\t"
  67348. /* mu = a[i] * mp */
  67349. "MUL r10, %[mp], r4\n\t"
  67350. /* a[i+0] += m[0] * mu */
  67351. "MOV r7, #0x0\n\t"
  67352. "UMLAL r4, r7, r10, lr\n\t"
  67353. /* a[i+1] += m[1] * mu */
  67354. "LDR r9, [%[m], #4]\n\t"
  67355. "MOV r6, #0x0\n\t"
  67356. "UMLAL r5, r6, r10, r9\n\t"
  67357. "MOV r4, r5\n\t"
  67358. "ADDS r4, r4, r7\n\t"
  67359. "ADC r6, r6, #0x0\n\t"
  67360. /* a[i+2] += m[2] * mu */
  67361. "LDR r9, [%[m], #8]\n\t"
  67362. "LDR r5, [%[a], #8]\n\t"
  67363. "MOV r7, #0x0\n\t"
  67364. "UMLAL r5, r7, r10, r9\n\t"
  67365. "ADDS r5, r5, r6\n\t"
  67366. "ADC r7, r7, #0x0\n\t"
  67367. /* a[i+3] += m[3] * mu */
  67368. "LDR r9, [%[m], #12]\n\t"
  67369. "LDR r12, [%[a], #12]\n\t"
  67370. "MOV r6, #0x0\n\t"
  67371. "UMLAL r12, r6, r10, r9\n\t"
  67372. "ADDS r12, r12, r7\n\t"
  67373. "STR r12, [%[a], #12]\n\t"
  67374. "ADC r6, r6, #0x0\n\t"
  67375. /* a[i+4] += m[4] * mu */
  67376. "LDR r9, [%[m], #16]\n\t"
  67377. "LDR r12, [%[a], #16]\n\t"
  67378. "MOV r7, #0x0\n\t"
  67379. "UMLAL r12, r7, r10, r9\n\t"
  67380. "ADDS r12, r12, r6\n\t"
  67381. "STR r12, [%[a], #16]\n\t"
  67382. "ADC r7, r7, #0x0\n\t"
  67383. /* a[i+5] += m[5] * mu */
  67384. "LDR r9, [%[m], #20]\n\t"
  67385. "LDR r12, [%[a], #20]\n\t"
  67386. "MOV r6, #0x0\n\t"
  67387. "UMLAL r12, r6, r10, r9\n\t"
  67388. "ADDS r12, r12, r7\n\t"
  67389. "STR r12, [%[a], #20]\n\t"
  67390. "ADC r6, r6, #0x0\n\t"
  67391. /* a[i+6] += m[6] * mu */
  67392. "LDR r9, [%[m], #24]\n\t"
  67393. "LDR r12, [%[a], #24]\n\t"
  67394. "MOV r7, #0x0\n\t"
  67395. "UMLAL r12, r7, r10, r9\n\t"
  67396. "ADDS r12, r12, r6\n\t"
  67397. "STR r12, [%[a], #24]\n\t"
  67398. "ADC r7, r7, #0x0\n\t"
  67399. /* a[i+7] += m[7] * mu */
  67400. "LDR r9, [%[m], #28]\n\t"
  67401. "LDR r12, [%[a], #28]\n\t"
  67402. "MOV r6, #0x0\n\t"
  67403. "UMLAL r12, r6, r10, r9\n\t"
  67404. "ADDS r12, r12, r7\n\t"
  67405. "STR r12, [%[a], #28]\n\t"
  67406. "ADC r6, r6, #0x0\n\t"
  67407. /* a[i+8] += m[8] * mu */
  67408. "LDR r9, [%[m], #32]\n\t"
  67409. "LDR r12, [%[a], #32]\n\t"
  67410. "MOV r7, #0x0\n\t"
  67411. "UMLAL r12, r7, r10, r9\n\t"
  67412. "ADDS r12, r12, r6\n\t"
  67413. "STR r12, [%[a], #32]\n\t"
  67414. "ADC r7, r7, #0x0\n\t"
  67415. /* a[i+9] += m[9] * mu */
  67416. "LDR r9, [%[m], #36]\n\t"
  67417. "LDR r12, [%[a], #36]\n\t"
  67418. "MOV r6, #0x0\n\t"
  67419. "UMLAL r12, r6, r10, r9\n\t"
  67420. "ADDS r12, r12, r7\n\t"
  67421. "STR r12, [%[a], #36]\n\t"
  67422. "ADC r6, r6, #0x0\n\t"
  67423. /* a[i+10] += m[10] * mu */
  67424. "LDR r9, [%[m], #40]\n\t"
  67425. "LDR r12, [%[a], #40]\n\t"
  67426. "MOV r7, #0x0\n\t"
  67427. "UMLAL r12, r7, r10, r9\n\t"
  67428. "ADDS r12, r12, r6\n\t"
  67429. "STR r12, [%[a], #40]\n\t"
  67430. "ADC r7, r7, #0x0\n\t"
  67431. /* a[i+11] += m[11] * mu */
  67432. "LDR r9, [%[m], #44]\n\t"
  67433. "LDR r12, [%[a], #44]\n\t"
  67434. "MOV r6, #0x0\n\t"
  67435. "UMLAL r12, r6, r10, r9\n\t"
  67436. "ADDS r12, r12, r7\n\t"
  67437. "STR r12, [%[a], #44]\n\t"
  67438. "ADC r6, r6, #0x0\n\t"
  67439. /* a[i+12] += m[12] * mu */
  67440. "LDR r9, [%[m], #48]\n\t"
  67441. "LDR r12, [%[a], #48]\n\t"
  67442. "MOV r7, #0x0\n\t"
  67443. "UMLAL r12, r7, r10, r9\n\t"
  67444. "ADDS r12, r12, r6\n\t"
  67445. "STR r12, [%[a], #48]\n\t"
  67446. "ADC r7, r7, #0x0\n\t"
  67447. /* a[i+13] += m[13] * mu */
  67448. "LDR r9, [%[m], #52]\n\t"
  67449. "LDR r12, [%[a], #52]\n\t"
  67450. "MOV r6, #0x0\n\t"
  67451. "UMLAL r12, r6, r10, r9\n\t"
  67452. "ADDS r12, r12, r7\n\t"
  67453. "STR r12, [%[a], #52]\n\t"
  67454. "ADC r6, r6, #0x0\n\t"
  67455. /* a[i+14] += m[14] * mu */
  67456. "LDR r9, [%[m], #56]\n\t"
  67457. "LDR r12, [%[a], #56]\n\t"
  67458. "MOV r7, #0x0\n\t"
  67459. "UMLAL r12, r7, r10, r9\n\t"
  67460. "ADDS r12, r12, r6\n\t"
  67461. "STR r12, [%[a], #56]\n\t"
  67462. "ADC r7, r7, #0x0\n\t"
  67463. /* a[i+15] += m[15] * mu */
  67464. "LDR r9, [%[m], #60]\n\t"
  67465. "LDR r12, [%[a], #60]\n\t"
  67466. "MOV r6, #0x0\n\t"
  67467. "UMLAL r12, r6, r10, r9\n\t"
  67468. "ADDS r12, r12, r7\n\t"
  67469. "STR r12, [%[a], #60]\n\t"
  67470. "ADC r6, r6, #0x0\n\t"
  67471. /* a[i+16] += m[16] * mu */
  67472. "LDR r9, [%[m], #64]\n\t"
  67473. "LDR r12, [%[a], #64]\n\t"
  67474. "MOV r7, #0x0\n\t"
  67475. "UMLAL r12, r7, r10, r9\n\t"
  67476. "ADDS r12, r12, r6\n\t"
  67477. "STR r12, [%[a], #64]\n\t"
  67478. "ADC r7, r7, #0x0\n\t"
  67479. /* a[i+17] += m[17] * mu */
  67480. "LDR r9, [%[m], #68]\n\t"
  67481. "LDR r12, [%[a], #68]\n\t"
  67482. "MOV r6, #0x0\n\t"
  67483. "UMLAL r12, r6, r10, r9\n\t"
  67484. "ADDS r12, r12, r7\n\t"
  67485. "STR r12, [%[a], #68]\n\t"
  67486. "ADC r6, r6, #0x0\n\t"
  67487. /* a[i+18] += m[18] * mu */
  67488. "LDR r9, [%[m], #72]\n\t"
  67489. "LDR r12, [%[a], #72]\n\t"
  67490. "MOV r7, #0x0\n\t"
  67491. "UMLAL r12, r7, r10, r9\n\t"
  67492. "ADDS r12, r12, r6\n\t"
  67493. "STR r12, [%[a], #72]\n\t"
  67494. "ADC r7, r7, #0x0\n\t"
  67495. /* a[i+19] += m[19] * mu */
  67496. "LDR r9, [%[m], #76]\n\t"
  67497. "LDR r12, [%[a], #76]\n\t"
  67498. "MOV r6, #0x0\n\t"
  67499. "UMLAL r12, r6, r10, r9\n\t"
  67500. "ADDS r12, r12, r7\n\t"
  67501. "STR r12, [%[a], #76]\n\t"
  67502. "ADC r6, r6, #0x0\n\t"
  67503. /* a[i+20] += m[20] * mu */
  67504. "LDR r9, [%[m], #80]\n\t"
  67505. "LDR r12, [%[a], #80]\n\t"
  67506. "MOV r7, #0x0\n\t"
  67507. "UMLAL r12, r7, r10, r9\n\t"
  67508. "ADDS r12, r12, r6\n\t"
  67509. "STR r12, [%[a], #80]\n\t"
  67510. "ADC r7, r7, #0x0\n\t"
  67511. /* a[i+21] += m[21] * mu */
  67512. "LDR r9, [%[m], #84]\n\t"
  67513. "LDR r12, [%[a], #84]\n\t"
  67514. "MOV r6, #0x0\n\t"
  67515. "UMLAL r12, r6, r10, r9\n\t"
  67516. "ADDS r12, r12, r7\n\t"
  67517. "STR r12, [%[a], #84]\n\t"
  67518. "ADC r6, r6, #0x0\n\t"
  67519. /* a[i+22] += m[22] * mu */
  67520. "LDR r9, [%[m], #88]\n\t"
  67521. "LDR r12, [%[a], #88]\n\t"
  67522. "MOV r7, #0x0\n\t"
  67523. "UMLAL r12, r7, r10, r9\n\t"
  67524. "ADDS r12, r12, r6\n\t"
  67525. "STR r12, [%[a], #88]\n\t"
  67526. "ADC r7, r7, #0x0\n\t"
  67527. /* a[i+23] += m[23] * mu */
  67528. "LDR r9, [%[m], #92]\n\t"
  67529. "LDR r12, [%[a], #92]\n\t"
  67530. "MOV r6, #0x0\n\t"
  67531. "UMLAL r12, r6, r10, r9\n\t"
  67532. "ADDS r12, r12, r7\n\t"
  67533. "STR r12, [%[a], #92]\n\t"
  67534. "ADC r6, r6, #0x0\n\t"
  67535. /* a[i+24] += m[24] * mu */
  67536. "LDR r9, [%[m], #96]\n\t"
  67537. "LDR r12, [%[a], #96]\n\t"
  67538. "MOV r7, #0x0\n\t"
  67539. "UMLAL r12, r7, r10, r9\n\t"
  67540. "ADDS r12, r12, r6\n\t"
  67541. "STR r12, [%[a], #96]\n\t"
  67542. "ADC r7, r7, #0x0\n\t"
  67543. /* a[i+25] += m[25] * mu */
  67544. "LDR r9, [%[m], #100]\n\t"
  67545. "LDR r12, [%[a], #100]\n\t"
  67546. "MOV r6, #0x0\n\t"
  67547. "UMLAL r12, r6, r10, r9\n\t"
  67548. "ADDS r12, r12, r7\n\t"
  67549. "STR r12, [%[a], #100]\n\t"
  67550. "ADC r6, r6, #0x0\n\t"
  67551. /* a[i+26] += m[26] * mu */
  67552. "LDR r9, [%[m], #104]\n\t"
  67553. "LDR r12, [%[a], #104]\n\t"
  67554. "MOV r7, #0x0\n\t"
  67555. "UMLAL r12, r7, r10, r9\n\t"
  67556. "ADDS r12, r12, r6\n\t"
  67557. "STR r12, [%[a], #104]\n\t"
  67558. "ADC r7, r7, #0x0\n\t"
  67559. /* a[i+27] += m[27] * mu */
  67560. "LDR r9, [%[m], #108]\n\t"
  67561. "LDR r12, [%[a], #108]\n\t"
  67562. "MOV r6, #0x0\n\t"
  67563. "UMLAL r12, r6, r10, r9\n\t"
  67564. "ADDS r12, r12, r7\n\t"
  67565. "STR r12, [%[a], #108]\n\t"
  67566. "ADC r6, r6, #0x0\n\t"
  67567. /* a[i+28] += m[28] * mu */
  67568. "LDR r9, [%[m], #112]\n\t"
  67569. "LDR r12, [%[a], #112]\n\t"
  67570. "MOV r7, #0x0\n\t"
  67571. "UMLAL r12, r7, r10, r9\n\t"
  67572. "ADDS r12, r12, r6\n\t"
  67573. "STR r12, [%[a], #112]\n\t"
  67574. "ADC r7, r7, #0x0\n\t"
  67575. /* a[i+29] += m[29] * mu */
  67576. "LDR r9, [%[m], #116]\n\t"
  67577. "LDR r12, [%[a], #116]\n\t"
  67578. "MOV r6, #0x0\n\t"
  67579. "UMLAL r12, r6, r10, r9\n\t"
  67580. "ADDS r12, r12, r7\n\t"
  67581. "STR r12, [%[a], #116]\n\t"
  67582. "ADC r6, r6, #0x0\n\t"
  67583. /* a[i+30] += m[30] * mu */
  67584. "LDR r9, [%[m], #120]\n\t"
  67585. "LDR r12, [%[a], #120]\n\t"
  67586. "MOV r7, #0x0\n\t"
  67587. "UMLAL r12, r7, r10, r9\n\t"
  67588. "ADDS r12, r12, r6\n\t"
  67589. "STR r12, [%[a], #120]\n\t"
  67590. "ADC r7, r7, #0x0\n\t"
  67591. /* a[i+31] += m[31] * mu */
  67592. "LDR r9, [%[m], #124]\n\t"
  67593. "LDR r12, [%[a], #124]\n\t"
  67594. "UMULL r8, r9, r10, r9\n\t"
  67595. "ADDS r7, r7, r8\n\t"
  67596. "ADCS r6, r9, r3\n\t"
  67597. "MOV r3, #0x0\n\t"
  67598. "ADC r3, r3, r3\n\t"
  67599. "ADDS r12, r12, r7\n\t"
  67600. "STR r12, [%[a], #124]\n\t"
  67601. "LDR r12, [%[a], #128]\n\t"
  67602. "ADCS r12, r12, r6\n\t"
  67603. "STR r12, [%[a], #128]\n\t"
  67604. "ADC r3, r3, #0x0\n\t"
  67605. /* i += 1 */
  67606. "ADD r11, r11, #0x4\n\t"
  67607. "ADD %[a], %[a], #0x4\n\t"
  67608. "CMP r11, #0x80\n\t"
  67609. #ifdef __GNUC__
  67610. "BLT L_sp_1024_mont_reduce_32_word\n\t"
  67611. #else
  67612. "BLT.W L_sp_1024_mont_reduce_32_word\n\t"
  67613. #endif
  67614. /* Loop Done */
  67615. "STR r4, [%[a]]\n\t"
  67616. "STR r5, [%[a], #4]\n\t"
  67617. "LDR r8, [%[m], #124]\n\t"
  67618. "SUBS r12, r8, r12\n\t"
  67619. "neg r3, r3\n\t"
  67620. "SBC r12, r12, r12\n\t"
  67621. "ORR r3, r3, r12\n\t"
  67622. "MOV %[mp], r3\n\t"
  67623. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  67624. :
  67625. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  67626. );
  67627. sp_1024_cond_sub_32(a - 32, a, m, mp);
  67628. }
  67629. #else
  67630. /* Reduce the number back to 1024 bits using Montgomery reduction.
  67631. *
  67632. * a A single precision number to reduce in place.
  67633. * m The single precision number representing the modulus.
  67634. * mp The digit representing the negative inverse of m mod 2^n.
  67635. */
  67636. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  67637. SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a_p, const sp_digit* m_p, sp_digit mp_p)
  67638. #else
  67639. SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp)
  67640. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  67641. {
  67642. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  67643. register sp_digit* a __asm__ ("r0") = (sp_digit*)a_p;
  67644. register const sp_digit* m __asm__ ("r1") = (const sp_digit*)m_p;
  67645. register sp_digit mp __asm__ ("r2") = (sp_digit)mp_p;
  67646. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  67647. __asm__ __volatile__ (
  67648. /* i = 0 */
  67649. "MOV r4, #0x0\n\t"
  67650. "MOV r5, #0x0\n\t"
  67651. "LDR r6, [%[a]]\n\t"
  67652. "LDR r7, [%[a], #4]\n\t"
  67653. "LDR r8, [%[a], #8]\n\t"
  67654. "LDR r9, [%[a], #12]\n\t"
  67655. "LDR r10, [%[a], #16]\n\t"
  67656. "\n"
  67657. "L_sp_1024_mont_reduce_32_word:\n\t"
  67658. /* mu = a[i] * mp */
  67659. "MUL lr, %[mp], r6\n\t"
  67660. /* a[i+0] += m[0] * mu */
  67661. "LDR r12, [%[m]]\n\t"
  67662. "MOV r3, #0x0\n\t"
  67663. "UMAAL r6, r3, lr, r12\n\t"
  67664. /* a[i+1] += m[1] * mu */
  67665. "LDR r12, [%[m], #4]\n\t"
  67666. "MOV r6, r7\n\t"
  67667. "UMAAL r6, r3, lr, r12\n\t"
  67668. /* a[i+2] += m[2] * mu */
  67669. "LDR r12, [%[m], #8]\n\t"
  67670. "MOV r7, r8\n\t"
  67671. "UMAAL r7, r3, lr, r12\n\t"
  67672. /* a[i+3] += m[3] * mu */
  67673. "LDR r12, [%[m], #12]\n\t"
  67674. "MOV r8, r9\n\t"
  67675. "UMAAL r8, r3, lr, r12\n\t"
  67676. /* a[i+4] += m[4] * mu */
  67677. "LDR r12, [%[m], #16]\n\t"
  67678. "MOV r9, r10\n\t"
  67679. "UMAAL r9, r3, lr, r12\n\t"
  67680. /* a[i+5] += m[5] * mu */
  67681. "LDR r12, [%[m], #20]\n\t"
  67682. "LDR r10, [%[a], #20]\n\t"
  67683. "UMAAL r10, r3, lr, r12\n\t"
  67684. /* a[i+6] += m[6] * mu */
  67685. "LDR r12, [%[m], #24]\n\t"
  67686. "LDR r11, [%[a], #24]\n\t"
  67687. "UMAAL r11, r3, lr, r12\n\t"
  67688. "STR r11, [%[a], #24]\n\t"
  67689. /* a[i+7] += m[7] * mu */
  67690. "LDR r12, [%[m], #28]\n\t"
  67691. "LDR r11, [%[a], #28]\n\t"
  67692. "UMAAL r11, r3, lr, r12\n\t"
  67693. "STR r11, [%[a], #28]\n\t"
  67694. /* a[i+8] += m[8] * mu */
  67695. "LDR r12, [%[m], #32]\n\t"
  67696. "LDR r11, [%[a], #32]\n\t"
  67697. "UMAAL r11, r3, lr, r12\n\t"
  67698. "STR r11, [%[a], #32]\n\t"
  67699. /* a[i+9] += m[9] * mu */
  67700. "LDR r12, [%[m], #36]\n\t"
  67701. "LDR r11, [%[a], #36]\n\t"
  67702. "UMAAL r11, r3, lr, r12\n\t"
  67703. "STR r11, [%[a], #36]\n\t"
  67704. /* a[i+10] += m[10] * mu */
  67705. "LDR r12, [%[m], #40]\n\t"
  67706. "LDR r11, [%[a], #40]\n\t"
  67707. "UMAAL r11, r3, lr, r12\n\t"
  67708. "STR r11, [%[a], #40]\n\t"
  67709. /* a[i+11] += m[11] * mu */
  67710. "LDR r12, [%[m], #44]\n\t"
  67711. "LDR r11, [%[a], #44]\n\t"
  67712. "UMAAL r11, r3, lr, r12\n\t"
  67713. "STR r11, [%[a], #44]\n\t"
  67714. /* a[i+12] += m[12] * mu */
  67715. "LDR r12, [%[m], #48]\n\t"
  67716. "LDR r11, [%[a], #48]\n\t"
  67717. "UMAAL r11, r3, lr, r12\n\t"
  67718. "STR r11, [%[a], #48]\n\t"
  67719. /* a[i+13] += m[13] * mu */
  67720. "LDR r12, [%[m], #52]\n\t"
  67721. "LDR r11, [%[a], #52]\n\t"
  67722. "UMAAL r11, r3, lr, r12\n\t"
  67723. "STR r11, [%[a], #52]\n\t"
  67724. /* a[i+14] += m[14] * mu */
  67725. "LDR r12, [%[m], #56]\n\t"
  67726. "LDR r11, [%[a], #56]\n\t"
  67727. "UMAAL r11, r3, lr, r12\n\t"
  67728. "STR r11, [%[a], #56]\n\t"
  67729. /* a[i+15] += m[15] * mu */
  67730. "LDR r12, [%[m], #60]\n\t"
  67731. "LDR r11, [%[a], #60]\n\t"
  67732. "UMAAL r11, r3, lr, r12\n\t"
  67733. "STR r11, [%[a], #60]\n\t"
  67734. /* a[i+16] += m[16] * mu */
  67735. "LDR r12, [%[m], #64]\n\t"
  67736. "LDR r11, [%[a], #64]\n\t"
  67737. "UMAAL r11, r3, lr, r12\n\t"
  67738. "STR r11, [%[a], #64]\n\t"
  67739. /* a[i+17] += m[17] * mu */
  67740. "LDR r12, [%[m], #68]\n\t"
  67741. "LDR r11, [%[a], #68]\n\t"
  67742. "UMAAL r11, r3, lr, r12\n\t"
  67743. "STR r11, [%[a], #68]\n\t"
  67744. /* a[i+18] += m[18] * mu */
  67745. "LDR r12, [%[m], #72]\n\t"
  67746. "LDR r11, [%[a], #72]\n\t"
  67747. "UMAAL r11, r3, lr, r12\n\t"
  67748. "STR r11, [%[a], #72]\n\t"
  67749. /* a[i+19] += m[19] * mu */
  67750. "LDR r12, [%[m], #76]\n\t"
  67751. "LDR r11, [%[a], #76]\n\t"
  67752. "UMAAL r11, r3, lr, r12\n\t"
  67753. "STR r11, [%[a], #76]\n\t"
  67754. /* a[i+20] += m[20] * mu */
  67755. "LDR r12, [%[m], #80]\n\t"
  67756. "LDR r11, [%[a], #80]\n\t"
  67757. "UMAAL r11, r3, lr, r12\n\t"
  67758. "STR r11, [%[a], #80]\n\t"
  67759. /* a[i+21] += m[21] * mu */
  67760. "LDR r12, [%[m], #84]\n\t"
  67761. "LDR r11, [%[a], #84]\n\t"
  67762. "UMAAL r11, r3, lr, r12\n\t"
  67763. "STR r11, [%[a], #84]\n\t"
  67764. /* a[i+22] += m[22] * mu */
  67765. "LDR r12, [%[m], #88]\n\t"
  67766. "LDR r11, [%[a], #88]\n\t"
  67767. "UMAAL r11, r3, lr, r12\n\t"
  67768. "STR r11, [%[a], #88]\n\t"
  67769. /* a[i+23] += m[23] * mu */
  67770. "LDR r12, [%[m], #92]\n\t"
  67771. "LDR r11, [%[a], #92]\n\t"
  67772. "UMAAL r11, r3, lr, r12\n\t"
  67773. "STR r11, [%[a], #92]\n\t"
  67774. /* a[i+24] += m[24] * mu */
  67775. "LDR r12, [%[m], #96]\n\t"
  67776. "LDR r11, [%[a], #96]\n\t"
  67777. "UMAAL r11, r3, lr, r12\n\t"
  67778. "STR r11, [%[a], #96]\n\t"
  67779. /* a[i+25] += m[25] * mu */
  67780. "LDR r12, [%[m], #100]\n\t"
  67781. "LDR r11, [%[a], #100]\n\t"
  67782. "UMAAL r11, r3, lr, r12\n\t"
  67783. "STR r11, [%[a], #100]\n\t"
  67784. /* a[i+26] += m[26] * mu */
  67785. "LDR r12, [%[m], #104]\n\t"
  67786. "LDR r11, [%[a], #104]\n\t"
  67787. "UMAAL r11, r3, lr, r12\n\t"
  67788. "STR r11, [%[a], #104]\n\t"
  67789. /* a[i+27] += m[27] * mu */
  67790. "LDR r12, [%[m], #108]\n\t"
  67791. "LDR r11, [%[a], #108]\n\t"
  67792. "UMAAL r11, r3, lr, r12\n\t"
  67793. "STR r11, [%[a], #108]\n\t"
  67794. /* a[i+28] += m[28] * mu */
  67795. "LDR r12, [%[m], #112]\n\t"
  67796. "LDR r11, [%[a], #112]\n\t"
  67797. "UMAAL r11, r3, lr, r12\n\t"
  67798. "STR r11, [%[a], #112]\n\t"
  67799. /* a[i+29] += m[29] * mu */
  67800. "LDR r12, [%[m], #116]\n\t"
  67801. "LDR r11, [%[a], #116]\n\t"
  67802. "UMAAL r11, r3, lr, r12\n\t"
  67803. "STR r11, [%[a], #116]\n\t"
  67804. /* a[i+30] += m[30] * mu */
  67805. "LDR r12, [%[m], #120]\n\t"
  67806. "LDR r11, [%[a], #120]\n\t"
  67807. "UMAAL r11, r3, lr, r12\n\t"
  67808. "STR r11, [%[a], #120]\n\t"
  67809. /* a[i+31] += m[31] * mu */
  67810. "LDR r12, [%[m], #124]\n\t"
  67811. "LDR r11, [%[a], #124]\n\t"
  67812. "UMAAL r11, r3, lr, r12\n\t"
  67813. "LDR lr, [%[a], #128]\n\t"
  67814. "MOV r12, #0x0\n\t"
  67815. "UMAAL r3, lr, r12, r12\n\t"
  67816. "STR r11, [%[a], #124]\n\t"
  67817. "ADDS r3, r3, r5\n\t"
  67818. "ADC r5, lr, #0x0\n\t"
  67819. "STR r3, [%[a], #128]\n\t"
  67820. /* i += 1 */
  67821. "ADD r4, r4, #0x4\n\t"
  67822. "ADD %[a], %[a], #0x4\n\t"
  67823. "CMP r4, #0x80\n\t"
  67824. #ifdef __GNUC__
  67825. "BLT L_sp_1024_mont_reduce_32_word\n\t"
  67826. #else
  67827. "BLT.W L_sp_1024_mont_reduce_32_word\n\t"
  67828. #endif
  67829. /* Loop Done */
  67830. "STR r6, [%[a]]\n\t"
  67831. "STR r7, [%[a], #4]\n\t"
  67832. "STR r8, [%[a], #8]\n\t"
  67833. "STR r9, [%[a], #12]\n\t"
  67834. "STR r10, [%[a], #16]\n\t"
  67835. "LDR r12, [%[m], #124]\n\t"
  67836. "SUBS r3, r12, r3\n\t"
  67837. "neg r5, r5\n\t"
  67838. "SBC r3, r3, r3\n\t"
  67839. "ORR r5, r5, r3\n\t"
  67840. "MOV %[mp], r5\n\t"
  67841. : [a] "+r" (a), [m] "+r" (m), [mp] "+r" (mp)
  67842. :
  67843. : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc"
  67844. );
  67845. sp_1024_cond_sub_32(a - 32, a, m, mp);
  67846. }
  67847. #endif
  67848. /* Multiply two Montgomery form numbers mod the modulus (prime).
  67849. * (r = a * b mod m)
  67850. *
  67851. * r Result of multiplication.
  67852. * a First number to multiply in Montgomery form.
  67853. * b Second number to multiply in Montgomery form.
  67854. * m Modulus (prime).
  67855. * mp Montgomery multiplier.
  67856. */
  67857. SP_NOINLINE static void sp_1024_mont_mul_32(sp_digit* r, const sp_digit* a,
  67858. const sp_digit* b, const sp_digit* m, sp_digit mp)
  67859. {
  67860. sp_1024_mul_32(r, a, b);
  67861. sp_1024_mont_reduce_32(r, m, mp);
  67862. }
  67863. /* Square the Montgomery form number. (r = a * a mod m)
  67864. *
  67865. * r Result of squaring.
  67866. * a Number to square in Montgomery form.
  67867. * m Modulus (prime).
  67868. * mp Montgomery multiplier.
  67869. */
  67870. SP_NOINLINE static void sp_1024_mont_sqr_32(sp_digit* r, const sp_digit* a,
  67871. const sp_digit* m, sp_digit mp)
  67872. {
  67873. sp_1024_sqr_32(r, a);
  67874. sp_1024_mont_reduce_32(r, m, mp);
  67875. }
  67876. /* Mod-2 for the P1024 curve. */
  67877. static const uint8_t p1024_mod_minus_2[] = {
  67878. 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f,
  67879. 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14,
  67880. 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07,
  67881. 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b,
  67882. 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07,
  67883. 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13,
  67884. 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19,
  67885. 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04,
  67886. 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09,
  67887. 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06,
  67888. 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15,
  67889. 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14,
  67890. 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c,
  67891. 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19,
  67892. 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f,
  67893. 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b,
  67894. 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c,
  67895. 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f,
  67896. 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01
  67897. };
  67898. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  67899. * P1024 curve. (r = 1 / a mod m)
  67900. *
  67901. * r Inverse result.
  67902. * a Number to invert.
  67903. * td Temporary data.
  67904. */
  67905. static void sp_1024_mont_inv_32(sp_digit* r, const sp_digit* a,
  67906. sp_digit* td)
  67907. {
  67908. sp_digit* t = &td[32 * 2 * 32];
  67909. int i;
  67910. int j;
  67911. sp_digit* table[32];
  67912. for (i = 0; i < 32; i++) {
  67913. table[i] = &td[2 * 32 * i];
  67914. }
  67915. XMEMCPY(table[0], a, sizeof(sp_digit) * 32);
  67916. for (i = 1; i < 6; i++) {
  67917. sp_1024_mont_sqr_32(table[0], table[0], p1024_mod, p1024_mp_mod);
  67918. }
  67919. for (i = 1; i < 32; i++) {
  67920. sp_1024_mont_mul_32(table[i], table[i-1], a, p1024_mod, p1024_mp_mod);
  67921. }
  67922. XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 32);
  67923. for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) {
  67924. for (j = 0; j < p1024_mod_minus_2[i]; j++) {
  67925. sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
  67926. }
  67927. sp_1024_mont_mul_32(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod,
  67928. p1024_mp_mod);
  67929. }
  67930. sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod);
  67931. sp_1024_mont_mul_32(r, t, a, p1024_mod, p1024_mp_mod);
  67932. }
  67933. /* Normalize the values in each word to 32.
  67934. *
  67935. * a Array of sp_digit to normalize.
  67936. */
  67937. #define sp_1024_norm_32(a)
  67938. /* Map the Montgomery form projective coordinate point to an affine point.
  67939. *
  67940. * r Resulting affine coordinate point.
  67941. * p Montgomery form projective coordinate point.
  67942. * t Temporary ordinate data.
  67943. */
  67944. static void sp_1024_map_32(sp_point_1024* r, const sp_point_1024* p,
  67945. sp_digit* t)
  67946. {
  67947. sp_digit* t1 = t;
  67948. sp_digit* t2 = t + 2*32;
  67949. sp_int32 n;
  67950. sp_1024_mont_inv_32(t1, p->z, t + 2*32);
  67951. sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
  67952. sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
  67953. /* x /= z^2 */
  67954. sp_1024_mont_mul_32(r->x, p->x, t2, p1024_mod, p1024_mp_mod);
  67955. XMEMSET(r->x + 32, 0, sizeof(sp_digit) * 32U);
  67956. sp_1024_mont_reduce_32(r->x, p1024_mod, p1024_mp_mod);
  67957. /* Reduce x to less than modulus */
  67958. n = sp_1024_cmp_32(r->x, p1024_mod);
  67959. sp_1024_cond_sub_32(r->x, r->x, p1024_mod, ~(n >> 31));
  67960. sp_1024_norm_32(r->x);
  67961. /* y /= z^3 */
  67962. sp_1024_mont_mul_32(r->y, p->y, t1, p1024_mod, p1024_mp_mod);
  67963. XMEMSET(r->y + 32, 0, sizeof(sp_digit) * 32U);
  67964. sp_1024_mont_reduce_32(r->y, p1024_mod, p1024_mp_mod);
  67965. /* Reduce y to less than modulus */
  67966. n = sp_1024_cmp_32(r->y, p1024_mod);
  67967. sp_1024_cond_sub_32(r->y, r->y, p1024_mod, ~(n >> 31));
  67968. sp_1024_norm_32(r->y);
  67969. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  67970. r->z[0] = 1;
  67971. }
  67972. /* Add two Montgomery form numbers (r = a + b % m).
  67973. *
  67974. * r Result of addition.
  67975. * a First number to add in Montgomery form.
  67976. * b Second number to add in Montgomery form.
  67977. * m Modulus (prime).
  67978. */
  67979. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  67980. SP_NOINLINE static void sp_1024_mont_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  67981. #else
  67982. SP_NOINLINE static void sp_1024_mont_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  67983. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  67984. {
  67985. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  67986. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  67987. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  67988. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  67989. register const sp_digit* m __asm__ ("r3") = (const sp_digit*)m_p;
  67990. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  67991. __asm__ __volatile__ (
  67992. "MOV r12, #0x0\n\t"
  67993. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  67994. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  67995. "ADDS r4, r4, r8\n\t"
  67996. "ADCS r5, r5, r9\n\t"
  67997. "ADCS r6, r6, r10\n\t"
  67998. "ADCS r7, r7, r11\n\t"
  67999. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68000. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68001. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68002. "ADCS r4, r4, r8\n\t"
  68003. "ADCS r5, r5, r9\n\t"
  68004. "ADCS r6, r6, r10\n\t"
  68005. "ADCS r7, r7, r11\n\t"
  68006. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68007. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68008. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68009. "ADCS r4, r4, r8\n\t"
  68010. "ADCS r5, r5, r9\n\t"
  68011. "ADCS r6, r6, r10\n\t"
  68012. "ADCS r7, r7, r11\n\t"
  68013. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68014. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68015. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68016. "ADCS r4, r4, r8\n\t"
  68017. "ADCS r5, r5, r9\n\t"
  68018. "ADCS r6, r6, r10\n\t"
  68019. "ADCS r7, r7, r11\n\t"
  68020. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68021. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68022. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68023. "ADCS r4, r4, r8\n\t"
  68024. "ADCS r5, r5, r9\n\t"
  68025. "ADCS r6, r6, r10\n\t"
  68026. "ADCS r7, r7, r11\n\t"
  68027. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68028. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68029. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68030. "ADCS r4, r4, r8\n\t"
  68031. "ADCS r5, r5, r9\n\t"
  68032. "ADCS r6, r6, r10\n\t"
  68033. "ADCS r7, r7, r11\n\t"
  68034. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68035. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68036. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68037. "ADCS r4, r4, r8\n\t"
  68038. "ADCS r5, r5, r9\n\t"
  68039. "ADCS r6, r6, r10\n\t"
  68040. "ADCS r7, r7, r11\n\t"
  68041. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68042. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68043. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68044. "ADCS r4, r4, r8\n\t"
  68045. "ADCS r5, r5, r9\n\t"
  68046. "ADCS r6, r6, r10\n\t"
  68047. "ADCS r7, r7, r11\n\t"
  68048. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68049. "LDR r11, [%[m], #124]\n\t"
  68050. "ADC r12, r12, #0x0\n\t"
  68051. "SUBS r11, r11, r7\n\t"
  68052. "neg r12, r12\n\t"
  68053. "SBC r11, r11, r11\n\t"
  68054. "SUB %[r], %[r], #0x80\n\t"
  68055. "ORR r12, r12, r11\n\t"
  68056. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68057. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68058. "AND r8, r8, r12\n\t"
  68059. "AND r9, r9, r12\n\t"
  68060. "AND r10, r10, r12\n\t"
  68061. "AND r11, r11, r12\n\t"
  68062. "SUBS r4, r4, r8\n\t"
  68063. "SBCS r5, r5, r9\n\t"
  68064. "SBCS r6, r6, r10\n\t"
  68065. "SBCS r7, r7, r11\n\t"
  68066. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68067. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68068. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68069. "AND r8, r8, r12\n\t"
  68070. "AND r9, r9, r12\n\t"
  68071. "AND r10, r10, r12\n\t"
  68072. "AND r11, r11, r12\n\t"
  68073. "SBCS r4, r4, r8\n\t"
  68074. "SBCS r5, r5, r9\n\t"
  68075. "SBCS r6, r6, r10\n\t"
  68076. "SBCS r7, r7, r11\n\t"
  68077. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68078. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68079. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68080. "AND r8, r8, r12\n\t"
  68081. "AND r9, r9, r12\n\t"
  68082. "AND r10, r10, r12\n\t"
  68083. "AND r11, r11, r12\n\t"
  68084. "SBCS r4, r4, r8\n\t"
  68085. "SBCS r5, r5, r9\n\t"
  68086. "SBCS r6, r6, r10\n\t"
  68087. "SBCS r7, r7, r11\n\t"
  68088. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68089. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68090. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68091. "AND r8, r8, r12\n\t"
  68092. "AND r9, r9, r12\n\t"
  68093. "AND r10, r10, r12\n\t"
  68094. "AND r11, r11, r12\n\t"
  68095. "SBCS r4, r4, r8\n\t"
  68096. "SBCS r5, r5, r9\n\t"
  68097. "SBCS r6, r6, r10\n\t"
  68098. "SBCS r7, r7, r11\n\t"
  68099. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68100. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68101. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68102. "AND r8, r8, r12\n\t"
  68103. "AND r9, r9, r12\n\t"
  68104. "AND r10, r10, r12\n\t"
  68105. "AND r11, r11, r12\n\t"
  68106. "SBCS r4, r4, r8\n\t"
  68107. "SBCS r5, r5, r9\n\t"
  68108. "SBCS r6, r6, r10\n\t"
  68109. "SBCS r7, r7, r11\n\t"
  68110. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68111. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68112. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68113. "AND r8, r8, r12\n\t"
  68114. "AND r9, r9, r12\n\t"
  68115. "AND r10, r10, r12\n\t"
  68116. "AND r11, r11, r12\n\t"
  68117. "SBCS r4, r4, r8\n\t"
  68118. "SBCS r5, r5, r9\n\t"
  68119. "SBCS r6, r6, r10\n\t"
  68120. "SBCS r7, r7, r11\n\t"
  68121. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68122. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68123. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68124. "AND r8, r8, r12\n\t"
  68125. "AND r9, r9, r12\n\t"
  68126. "AND r10, r10, r12\n\t"
  68127. "AND r11, r11, r12\n\t"
  68128. "SBCS r4, r4, r8\n\t"
  68129. "SBCS r5, r5, r9\n\t"
  68130. "SBCS r6, r6, r10\n\t"
  68131. "SBCS r7, r7, r11\n\t"
  68132. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68133. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68134. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68135. "AND r8, r8, r12\n\t"
  68136. "AND r9, r9, r12\n\t"
  68137. "AND r10, r10, r12\n\t"
  68138. "AND r11, r11, r12\n\t"
  68139. "SBCS r4, r4, r8\n\t"
  68140. "SBCS r5, r5, r9\n\t"
  68141. "SBCS r6, r6, r10\n\t"
  68142. "SBC r7, r7, r11\n\t"
  68143. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68144. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  68145. :
  68146. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  68147. );
  68148. }
  68149. /* Double a Montgomery form number (r = a + a % m).
  68150. *
  68151. * r Result of doubling.
  68152. * a Number to double in Montgomery form.
  68153. * m Modulus (prime).
  68154. */
  68155. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68156. SP_NOINLINE static void sp_1024_mont_dbl_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  68157. #else
  68158. SP_NOINLINE static void sp_1024_mont_dbl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
  68159. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68160. {
  68161. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68162. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  68163. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  68164. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  68165. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68166. __asm__ __volatile__ (
  68167. "MOV r12, #0x0\n\t"
  68168. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68169. "ADDS r4, r4, r4\n\t"
  68170. "ADCS r5, r5, r5\n\t"
  68171. "ADCS r6, r6, r6\n\t"
  68172. "ADCS r7, r7, r7\n\t"
  68173. "ADCS r8, r8, r8\n\t"
  68174. "ADCS r9, r9, r9\n\t"
  68175. "ADCS r10, r10, r10\n\t"
  68176. "ADCS r11, r11, r11\n\t"
  68177. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68178. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68179. "ADCS r4, r4, r4\n\t"
  68180. "ADCS r5, r5, r5\n\t"
  68181. "ADCS r6, r6, r6\n\t"
  68182. "ADCS r7, r7, r7\n\t"
  68183. "ADCS r8, r8, r8\n\t"
  68184. "ADCS r9, r9, r9\n\t"
  68185. "ADCS r10, r10, r10\n\t"
  68186. "ADCS r11, r11, r11\n\t"
  68187. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68188. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68189. "ADCS r4, r4, r4\n\t"
  68190. "ADCS r5, r5, r5\n\t"
  68191. "ADCS r6, r6, r6\n\t"
  68192. "ADCS r7, r7, r7\n\t"
  68193. "ADCS r8, r8, r8\n\t"
  68194. "ADCS r9, r9, r9\n\t"
  68195. "ADCS r10, r10, r10\n\t"
  68196. "ADCS r11, r11, r11\n\t"
  68197. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68198. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68199. "ADCS r4, r4, r4\n\t"
  68200. "ADCS r5, r5, r5\n\t"
  68201. "ADCS r6, r6, r6\n\t"
  68202. "ADCS r7, r7, r7\n\t"
  68203. "ADCS r8, r8, r8\n\t"
  68204. "ADCS r9, r9, r9\n\t"
  68205. "ADCS r10, r10, r10\n\t"
  68206. "ADCS r11, r11, r11\n\t"
  68207. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68208. "LDR r4, [%[m], #124]\n\t"
  68209. "ADC r12, r12, #0x0\n\t"
  68210. "SUBS r4, r4, r11\n\t"
  68211. "neg r12, r12\n\t"
  68212. "SBC r4, r4, r4\n\t"
  68213. "SUB %[r], %[r], #0x80\n\t"
  68214. "ORR r12, r12, r4\n\t"
  68215. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68216. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68217. "AND r8, r8, r12\n\t"
  68218. "AND r9, r9, r12\n\t"
  68219. "AND r10, r10, r12\n\t"
  68220. "AND r11, r11, r12\n\t"
  68221. "SUBS r4, r4, r8\n\t"
  68222. "SBCS r5, r5, r9\n\t"
  68223. "SBCS r6, r6, r10\n\t"
  68224. "SBCS r7, r7, r11\n\t"
  68225. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68226. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68227. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68228. "AND r8, r8, r12\n\t"
  68229. "AND r9, r9, r12\n\t"
  68230. "AND r10, r10, r12\n\t"
  68231. "AND r11, r11, r12\n\t"
  68232. "SBCS r4, r4, r8\n\t"
  68233. "SBCS r5, r5, r9\n\t"
  68234. "SBCS r6, r6, r10\n\t"
  68235. "SBCS r7, r7, r11\n\t"
  68236. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68237. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68238. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68239. "AND r8, r8, r12\n\t"
  68240. "AND r9, r9, r12\n\t"
  68241. "AND r10, r10, r12\n\t"
  68242. "AND r11, r11, r12\n\t"
  68243. "SBCS r4, r4, r8\n\t"
  68244. "SBCS r5, r5, r9\n\t"
  68245. "SBCS r6, r6, r10\n\t"
  68246. "SBCS r7, r7, r11\n\t"
  68247. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68248. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68249. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68250. "AND r8, r8, r12\n\t"
  68251. "AND r9, r9, r12\n\t"
  68252. "AND r10, r10, r12\n\t"
  68253. "AND r11, r11, r12\n\t"
  68254. "SBCS r4, r4, r8\n\t"
  68255. "SBCS r5, r5, r9\n\t"
  68256. "SBCS r6, r6, r10\n\t"
  68257. "SBCS r7, r7, r11\n\t"
  68258. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68259. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68260. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68261. "AND r8, r8, r12\n\t"
  68262. "AND r9, r9, r12\n\t"
  68263. "AND r10, r10, r12\n\t"
  68264. "AND r11, r11, r12\n\t"
  68265. "SBCS r4, r4, r8\n\t"
  68266. "SBCS r5, r5, r9\n\t"
  68267. "SBCS r6, r6, r10\n\t"
  68268. "SBCS r7, r7, r11\n\t"
  68269. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68270. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68271. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68272. "AND r8, r8, r12\n\t"
  68273. "AND r9, r9, r12\n\t"
  68274. "AND r10, r10, r12\n\t"
  68275. "AND r11, r11, r12\n\t"
  68276. "SBCS r4, r4, r8\n\t"
  68277. "SBCS r5, r5, r9\n\t"
  68278. "SBCS r6, r6, r10\n\t"
  68279. "SBCS r7, r7, r11\n\t"
  68280. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68281. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68282. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68283. "AND r8, r8, r12\n\t"
  68284. "AND r9, r9, r12\n\t"
  68285. "AND r10, r10, r12\n\t"
  68286. "AND r11, r11, r12\n\t"
  68287. "SBCS r4, r4, r8\n\t"
  68288. "SBCS r5, r5, r9\n\t"
  68289. "SBCS r6, r6, r10\n\t"
  68290. "SBCS r7, r7, r11\n\t"
  68291. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68292. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68293. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68294. "AND r8, r8, r12\n\t"
  68295. "AND r9, r9, r12\n\t"
  68296. "AND r10, r10, r12\n\t"
  68297. "AND r11, r11, r12\n\t"
  68298. "SBCS r4, r4, r8\n\t"
  68299. "SBCS r5, r5, r9\n\t"
  68300. "SBCS r6, r6, r10\n\t"
  68301. "SBC r7, r7, r11\n\t"
  68302. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68303. : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
  68304. :
  68305. : "memory", "r8", "r9", "r10", "r11", "r4", "r5", "r6", "r7", "r12", "cc"
  68306. );
  68307. }
  68308. /* Triple a Montgomery form number (r = a + a + a % m).
  68309. *
  68310. * r Result of Tripling.
  68311. * a Number to triple in Montgomery form.
  68312. * m Modulus (prime).
  68313. */
  68314. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68315. SP_NOINLINE static void sp_1024_mont_tpl_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* m_p)
  68316. #else
  68317. SP_NOINLINE static void sp_1024_mont_tpl_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
  68318. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68319. {
  68320. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68321. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  68322. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  68323. register const sp_digit* m __asm__ ("r2") = (const sp_digit*)m_p;
  68324. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68325. __asm__ __volatile__ (
  68326. "MOV r12, #0x0\n\t"
  68327. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68328. "ADDS r4, r4, r4\n\t"
  68329. "ADCS r5, r5, r5\n\t"
  68330. "ADCS r6, r6, r6\n\t"
  68331. "ADCS r7, r7, r7\n\t"
  68332. "ADCS r8, r8, r8\n\t"
  68333. "ADCS r9, r9, r9\n\t"
  68334. "ADCS r10, r10, r10\n\t"
  68335. "ADCS r11, r11, r11\n\t"
  68336. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68337. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68338. "ADCS r4, r4, r4\n\t"
  68339. "ADCS r5, r5, r5\n\t"
  68340. "ADCS r6, r6, r6\n\t"
  68341. "ADCS r7, r7, r7\n\t"
  68342. "ADCS r8, r8, r8\n\t"
  68343. "ADCS r9, r9, r9\n\t"
  68344. "ADCS r10, r10, r10\n\t"
  68345. "ADCS r11, r11, r11\n\t"
  68346. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68347. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68348. "ADCS r4, r4, r4\n\t"
  68349. "ADCS r5, r5, r5\n\t"
  68350. "ADCS r6, r6, r6\n\t"
  68351. "ADCS r7, r7, r7\n\t"
  68352. "ADCS r8, r8, r8\n\t"
  68353. "ADCS r9, r9, r9\n\t"
  68354. "ADCS r10, r10, r10\n\t"
  68355. "ADCS r11, r11, r11\n\t"
  68356. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68357. "LDM %[a]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68358. "ADCS r4, r4, r4\n\t"
  68359. "ADCS r5, r5, r5\n\t"
  68360. "ADCS r6, r6, r6\n\t"
  68361. "ADCS r7, r7, r7\n\t"
  68362. "ADCS r8, r8, r8\n\t"
  68363. "ADCS r9, r9, r9\n\t"
  68364. "ADCS r10, r10, r10\n\t"
  68365. "ADCS r11, r11, r11\n\t"
  68366. "STM %[r]!, {r4, r5, r6, r7, r8, r9, r10, r11}\n\t"
  68367. "LDR r4, [%[m], #124]\n\t"
  68368. "ADC r12, r12, #0x0\n\t"
  68369. "SUBS r4, r4, r11\n\t"
  68370. "neg r12, r12\n\t"
  68371. "SBC r4, r4, r4\n\t"
  68372. "SUB %[r], %[r], #0x80\n\t"
  68373. "ORR r12, r12, r4\n\t"
  68374. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68375. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68376. "AND r8, r8, r12\n\t"
  68377. "AND r9, r9, r12\n\t"
  68378. "AND r10, r10, r12\n\t"
  68379. "AND r11, r11, r12\n\t"
  68380. "SUBS r4, r4, r8\n\t"
  68381. "SBCS r5, r5, r9\n\t"
  68382. "SBCS r6, r6, r10\n\t"
  68383. "SBCS r7, r7, r11\n\t"
  68384. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68385. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68386. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68387. "AND r8, r8, r12\n\t"
  68388. "AND r9, r9, r12\n\t"
  68389. "AND r10, r10, r12\n\t"
  68390. "AND r11, r11, r12\n\t"
  68391. "SBCS r4, r4, r8\n\t"
  68392. "SBCS r5, r5, r9\n\t"
  68393. "SBCS r6, r6, r10\n\t"
  68394. "SBCS r7, r7, r11\n\t"
  68395. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68396. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68397. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68398. "AND r8, r8, r12\n\t"
  68399. "AND r9, r9, r12\n\t"
  68400. "AND r10, r10, r12\n\t"
  68401. "AND r11, r11, r12\n\t"
  68402. "SBCS r4, r4, r8\n\t"
  68403. "SBCS r5, r5, r9\n\t"
  68404. "SBCS r6, r6, r10\n\t"
  68405. "SBCS r7, r7, r11\n\t"
  68406. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68407. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68408. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68409. "AND r8, r8, r12\n\t"
  68410. "AND r9, r9, r12\n\t"
  68411. "AND r10, r10, r12\n\t"
  68412. "AND r11, r11, r12\n\t"
  68413. "SBCS r4, r4, r8\n\t"
  68414. "SBCS r5, r5, r9\n\t"
  68415. "SBCS r6, r6, r10\n\t"
  68416. "SBCS r7, r7, r11\n\t"
  68417. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68418. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68419. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68420. "AND r8, r8, r12\n\t"
  68421. "AND r9, r9, r12\n\t"
  68422. "AND r10, r10, r12\n\t"
  68423. "AND r11, r11, r12\n\t"
  68424. "SBCS r4, r4, r8\n\t"
  68425. "SBCS r5, r5, r9\n\t"
  68426. "SBCS r6, r6, r10\n\t"
  68427. "SBCS r7, r7, r11\n\t"
  68428. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68429. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68430. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68431. "AND r8, r8, r12\n\t"
  68432. "AND r9, r9, r12\n\t"
  68433. "AND r10, r10, r12\n\t"
  68434. "AND r11, r11, r12\n\t"
  68435. "SBCS r4, r4, r8\n\t"
  68436. "SBCS r5, r5, r9\n\t"
  68437. "SBCS r6, r6, r10\n\t"
  68438. "SBCS r7, r7, r11\n\t"
  68439. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68440. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68441. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68442. "AND r8, r8, r12\n\t"
  68443. "AND r9, r9, r12\n\t"
  68444. "AND r10, r10, r12\n\t"
  68445. "AND r11, r11, r12\n\t"
  68446. "SBCS r4, r4, r8\n\t"
  68447. "SBCS r5, r5, r9\n\t"
  68448. "SBCS r6, r6, r10\n\t"
  68449. "SBCS r7, r7, r11\n\t"
  68450. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68451. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68452. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68453. "AND r8, r8, r12\n\t"
  68454. "AND r9, r9, r12\n\t"
  68455. "AND r10, r10, r12\n\t"
  68456. "AND r11, r11, r12\n\t"
  68457. "SBCS r4, r4, r8\n\t"
  68458. "SBCS r5, r5, r9\n\t"
  68459. "SBCS r6, r6, r10\n\t"
  68460. "SBC r7, r7, r11\n\t"
  68461. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68462. "SUB %[r], %[r], #0x80\n\t"
  68463. "SUB %[m], %[m], #0x80\n\t"
  68464. "SUB %[a], %[a], #0x80\n\t"
  68465. "MOV r12, #0x0\n\t"
  68466. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68467. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68468. "ADDS r8, r8, r4\n\t"
  68469. "ADCS r9, r9, r5\n\t"
  68470. "ADCS r10, r10, r6\n\t"
  68471. "ADCS r11, r11, r7\n\t"
  68472. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68473. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68474. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68475. "ADCS r8, r8, r4\n\t"
  68476. "ADCS r9, r9, r5\n\t"
  68477. "ADCS r10, r10, r6\n\t"
  68478. "ADCS r11, r11, r7\n\t"
  68479. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68480. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68481. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68482. "ADCS r8, r8, r4\n\t"
  68483. "ADCS r9, r9, r5\n\t"
  68484. "ADCS r10, r10, r6\n\t"
  68485. "ADCS r11, r11, r7\n\t"
  68486. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68487. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68488. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68489. "ADCS r8, r8, r4\n\t"
  68490. "ADCS r9, r9, r5\n\t"
  68491. "ADCS r10, r10, r6\n\t"
  68492. "ADCS r11, r11, r7\n\t"
  68493. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68494. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68495. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68496. "ADCS r8, r8, r4\n\t"
  68497. "ADCS r9, r9, r5\n\t"
  68498. "ADCS r10, r10, r6\n\t"
  68499. "ADCS r11, r11, r7\n\t"
  68500. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68501. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68502. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68503. "ADCS r8, r8, r4\n\t"
  68504. "ADCS r9, r9, r5\n\t"
  68505. "ADCS r10, r10, r6\n\t"
  68506. "ADCS r11, r11, r7\n\t"
  68507. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68508. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68509. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68510. "ADCS r8, r8, r4\n\t"
  68511. "ADCS r9, r9, r5\n\t"
  68512. "ADCS r10, r10, r6\n\t"
  68513. "ADCS r11, r11, r7\n\t"
  68514. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68515. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68516. "LDM %[r], {r8, r9, r10, r11}\n\t"
  68517. "ADCS r8, r8, r4\n\t"
  68518. "ADCS r9, r9, r5\n\t"
  68519. "ADCS r10, r10, r6\n\t"
  68520. "ADCS r11, r11, r7\n\t"
  68521. "STM %[r]!, {r8, r9, r10, r11}\n\t"
  68522. "LDR r7, [%[m], #124]\n\t"
  68523. "ADC r12, r12, #0x0\n\t"
  68524. "SUBS r7, r7, r11\n\t"
  68525. "neg r12, r12\n\t"
  68526. "SBC r7, r7, r7\n\t"
  68527. "SUB %[r], %[r], #0x80\n\t"
  68528. "ORR r12, r12, r7\n\t"
  68529. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68530. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68531. "AND r8, r8, r12\n\t"
  68532. "AND r9, r9, r12\n\t"
  68533. "AND r10, r10, r12\n\t"
  68534. "AND r11, r11, r12\n\t"
  68535. "SUBS r4, r4, r8\n\t"
  68536. "SBCS r5, r5, r9\n\t"
  68537. "SBCS r6, r6, r10\n\t"
  68538. "SBCS r7, r7, r11\n\t"
  68539. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68540. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68541. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68542. "AND r8, r8, r12\n\t"
  68543. "AND r9, r9, r12\n\t"
  68544. "AND r10, r10, r12\n\t"
  68545. "AND r11, r11, r12\n\t"
  68546. "SBCS r4, r4, r8\n\t"
  68547. "SBCS r5, r5, r9\n\t"
  68548. "SBCS r6, r6, r10\n\t"
  68549. "SBCS r7, r7, r11\n\t"
  68550. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68551. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68552. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68553. "AND r8, r8, r12\n\t"
  68554. "AND r9, r9, r12\n\t"
  68555. "AND r10, r10, r12\n\t"
  68556. "AND r11, r11, r12\n\t"
  68557. "SBCS r4, r4, r8\n\t"
  68558. "SBCS r5, r5, r9\n\t"
  68559. "SBCS r6, r6, r10\n\t"
  68560. "SBCS r7, r7, r11\n\t"
  68561. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68562. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68563. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68564. "AND r8, r8, r12\n\t"
  68565. "AND r9, r9, r12\n\t"
  68566. "AND r10, r10, r12\n\t"
  68567. "AND r11, r11, r12\n\t"
  68568. "SBCS r4, r4, r8\n\t"
  68569. "SBCS r5, r5, r9\n\t"
  68570. "SBCS r6, r6, r10\n\t"
  68571. "SBCS r7, r7, r11\n\t"
  68572. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68573. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68574. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68575. "AND r8, r8, r12\n\t"
  68576. "AND r9, r9, r12\n\t"
  68577. "AND r10, r10, r12\n\t"
  68578. "AND r11, r11, r12\n\t"
  68579. "SBCS r4, r4, r8\n\t"
  68580. "SBCS r5, r5, r9\n\t"
  68581. "SBCS r6, r6, r10\n\t"
  68582. "SBCS r7, r7, r11\n\t"
  68583. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68584. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68585. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68586. "AND r8, r8, r12\n\t"
  68587. "AND r9, r9, r12\n\t"
  68588. "AND r10, r10, r12\n\t"
  68589. "AND r11, r11, r12\n\t"
  68590. "SBCS r4, r4, r8\n\t"
  68591. "SBCS r5, r5, r9\n\t"
  68592. "SBCS r6, r6, r10\n\t"
  68593. "SBCS r7, r7, r11\n\t"
  68594. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68595. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68596. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68597. "AND r8, r8, r12\n\t"
  68598. "AND r9, r9, r12\n\t"
  68599. "AND r10, r10, r12\n\t"
  68600. "AND r11, r11, r12\n\t"
  68601. "SBCS r4, r4, r8\n\t"
  68602. "SBCS r5, r5, r9\n\t"
  68603. "SBCS r6, r6, r10\n\t"
  68604. "SBCS r7, r7, r11\n\t"
  68605. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68606. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68607. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68608. "AND r8, r8, r12\n\t"
  68609. "AND r9, r9, r12\n\t"
  68610. "AND r10, r10, r12\n\t"
  68611. "AND r11, r11, r12\n\t"
  68612. "SBCS r4, r4, r8\n\t"
  68613. "SBCS r5, r5, r9\n\t"
  68614. "SBCS r6, r6, r10\n\t"
  68615. "SBC r7, r7, r11\n\t"
  68616. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68617. : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m)
  68618. :
  68619. : "memory", "r8", "r9", "r10", "r11", "r4", "r5", "r6", "r7", "r12", "cc"
  68620. );
  68621. }
  68622. /* Subtract two Montgomery form numbers (r = a - b % m).
  68623. *
  68624. * r Result of subtration.
  68625. * a Number to subtract from in Montgomery form.
  68626. * b Number to subtract with in Montgomery form.
  68627. * m Modulus (prime).
  68628. */
  68629. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68630. SP_NOINLINE static void sp_1024_mont_sub_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, const sp_digit* m_p)
  68631. #else
  68632. SP_NOINLINE static void sp_1024_mont_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m)
  68633. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68634. {
  68635. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68636. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  68637. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  68638. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  68639. register const sp_digit* m __asm__ ("r3") = (const sp_digit*)m_p;
  68640. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68641. __asm__ __volatile__ (
  68642. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68643. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68644. "SUBS r4, r4, r8\n\t"
  68645. "SBCS r5, r5, r9\n\t"
  68646. "SBCS r6, r6, r10\n\t"
  68647. "SBCS r7, r7, r11\n\t"
  68648. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68649. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68650. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68651. "SBCS r4, r4, r8\n\t"
  68652. "SBCS r5, r5, r9\n\t"
  68653. "SBCS r6, r6, r10\n\t"
  68654. "SBCS r7, r7, r11\n\t"
  68655. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68656. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68657. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68658. "SBCS r4, r4, r8\n\t"
  68659. "SBCS r5, r5, r9\n\t"
  68660. "SBCS r6, r6, r10\n\t"
  68661. "SBCS r7, r7, r11\n\t"
  68662. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68663. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68664. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68665. "SBCS r4, r4, r8\n\t"
  68666. "SBCS r5, r5, r9\n\t"
  68667. "SBCS r6, r6, r10\n\t"
  68668. "SBCS r7, r7, r11\n\t"
  68669. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68670. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68671. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68672. "SBCS r4, r4, r8\n\t"
  68673. "SBCS r5, r5, r9\n\t"
  68674. "SBCS r6, r6, r10\n\t"
  68675. "SBCS r7, r7, r11\n\t"
  68676. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68677. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68678. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68679. "SBCS r4, r4, r8\n\t"
  68680. "SBCS r5, r5, r9\n\t"
  68681. "SBCS r6, r6, r10\n\t"
  68682. "SBCS r7, r7, r11\n\t"
  68683. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68684. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68685. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68686. "SBCS r4, r4, r8\n\t"
  68687. "SBCS r5, r5, r9\n\t"
  68688. "SBCS r6, r6, r10\n\t"
  68689. "SBCS r7, r7, r11\n\t"
  68690. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68691. "LDM %[a]!, {r4, r5, r6, r7}\n\t"
  68692. "LDM %[b]!, {r8, r9, r10, r11}\n\t"
  68693. "SBCS r4, r4, r8\n\t"
  68694. "SBCS r5, r5, r9\n\t"
  68695. "SBCS r6, r6, r10\n\t"
  68696. "SBCS r7, r7, r11\n\t"
  68697. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68698. "SBC r12, r12, r12\n\t"
  68699. "SUB %[r], %[r], #0x80\n\t"
  68700. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68701. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68702. "AND r8, r8, r12\n\t"
  68703. "AND r9, r9, r12\n\t"
  68704. "AND r10, r10, r12\n\t"
  68705. "AND r11, r11, r12\n\t"
  68706. "ADDS r4, r4, r8\n\t"
  68707. "ADCS r5, r5, r9\n\t"
  68708. "ADCS r6, r6, r10\n\t"
  68709. "ADCS r7, r7, r11\n\t"
  68710. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68711. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68712. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68713. "AND r8, r8, r12\n\t"
  68714. "AND r9, r9, r12\n\t"
  68715. "AND r10, r10, r12\n\t"
  68716. "AND r11, r11, r12\n\t"
  68717. "ADCS r4, r4, r8\n\t"
  68718. "ADCS r5, r5, r9\n\t"
  68719. "ADCS r6, r6, r10\n\t"
  68720. "ADCS r7, r7, r11\n\t"
  68721. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68722. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68723. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68724. "AND r8, r8, r12\n\t"
  68725. "AND r9, r9, r12\n\t"
  68726. "AND r10, r10, r12\n\t"
  68727. "AND r11, r11, r12\n\t"
  68728. "ADCS r4, r4, r8\n\t"
  68729. "ADCS r5, r5, r9\n\t"
  68730. "ADCS r6, r6, r10\n\t"
  68731. "ADCS r7, r7, r11\n\t"
  68732. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68733. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68734. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68735. "AND r8, r8, r12\n\t"
  68736. "AND r9, r9, r12\n\t"
  68737. "AND r10, r10, r12\n\t"
  68738. "AND r11, r11, r12\n\t"
  68739. "ADCS r4, r4, r8\n\t"
  68740. "ADCS r5, r5, r9\n\t"
  68741. "ADCS r6, r6, r10\n\t"
  68742. "ADCS r7, r7, r11\n\t"
  68743. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68744. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68745. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68746. "AND r8, r8, r12\n\t"
  68747. "AND r9, r9, r12\n\t"
  68748. "AND r10, r10, r12\n\t"
  68749. "AND r11, r11, r12\n\t"
  68750. "ADCS r4, r4, r8\n\t"
  68751. "ADCS r5, r5, r9\n\t"
  68752. "ADCS r6, r6, r10\n\t"
  68753. "ADCS r7, r7, r11\n\t"
  68754. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68755. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68756. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68757. "AND r8, r8, r12\n\t"
  68758. "AND r9, r9, r12\n\t"
  68759. "AND r10, r10, r12\n\t"
  68760. "AND r11, r11, r12\n\t"
  68761. "ADCS r4, r4, r8\n\t"
  68762. "ADCS r5, r5, r9\n\t"
  68763. "ADCS r6, r6, r10\n\t"
  68764. "ADCS r7, r7, r11\n\t"
  68765. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68766. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68767. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68768. "AND r8, r8, r12\n\t"
  68769. "AND r9, r9, r12\n\t"
  68770. "AND r10, r10, r12\n\t"
  68771. "AND r11, r11, r12\n\t"
  68772. "ADCS r4, r4, r8\n\t"
  68773. "ADCS r5, r5, r9\n\t"
  68774. "ADCS r6, r6, r10\n\t"
  68775. "ADCS r7, r7, r11\n\t"
  68776. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68777. "LDM %[r], {r4, r5, r6, r7}\n\t"
  68778. "LDM %[m]!, {r8, r9, r10, r11}\n\t"
  68779. "AND r8, r8, r12\n\t"
  68780. "AND r9, r9, r12\n\t"
  68781. "AND r10, r10, r12\n\t"
  68782. "AND r11, r11, r12\n\t"
  68783. "ADCS r4, r4, r8\n\t"
  68784. "ADCS r5, r5, r9\n\t"
  68785. "ADCS r6, r6, r10\n\t"
  68786. "ADC r7, r7, r11\n\t"
  68787. "STM %[r]!, {r4, r5, r6, r7}\n\t"
  68788. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  68789. :
  68790. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cc"
  68791. );
  68792. }
  68793. #ifdef WOLFSSL_SP_SMALL
  68794. /* Conditionally add a and b using the mask m.
  68795. * m is -1 to add and 0 when not.
  68796. *
  68797. * r A single precision number representing conditional add result.
  68798. * a A single precision number to add with.
  68799. * b A single precision number to add.
  68800. * m Mask value to apply.
  68801. */
  68802. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68803. static sp_digit sp_1024_cond_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  68804. #else
  68805. static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  68806. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68807. {
  68808. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68809. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  68810. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  68811. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  68812. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  68813. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68814. __asm__ __volatile__ (
  68815. "MOV r5, #0x0\n\t"
  68816. "MOV r8, #0x0\n\t"
  68817. "MOV r4, #0x0\n\t"
  68818. "\n"
  68819. "L_sp_1024_cond_add_32_words:\n\t"
  68820. "ADDS r5, r5, #0xffffffff\n\t"
  68821. "LDR r6, [%[a], r4]\n\t"
  68822. "LDR r7, [%[b], r4]\n\t"
  68823. "AND r7, r7, %[m]\n\t"
  68824. "ADCS r6, r6, r7\n\t"
  68825. "ADC r5, r8, r8\n\t"
  68826. "STR r6, [%[r], r4]\n\t"
  68827. "ADD r4, r4, #0x4\n\t"
  68828. "CMP r4, #0x80\n\t"
  68829. #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
  68830. "BLT L_sp_1024_cond_add_32_words\n\t"
  68831. #else
  68832. "BLT.N L_sp_1024_cond_add_32_words\n\t"
  68833. #endif
  68834. "MOV %[r], r5\n\t"
  68835. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  68836. :
  68837. : "memory", "r4", "r5", "r6", "r7", "r8", "cc"
  68838. );
  68839. return (uint32_t)(size_t)r;
  68840. }
  68841. #else
  68842. /* Conditionally add a and b using the mask m.
  68843. * m is -1 to add and 0 when not.
  68844. *
  68845. * r A single precision number representing conditional add result.
  68846. * a A single precision number to add with.
  68847. * b A single precision number to add.
  68848. * m Mask value to apply.
  68849. */
  68850. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68851. static sp_digit sp_1024_cond_add_32(sp_digit* r_p, const sp_digit* a_p, const sp_digit* b_p, sp_digit m_p)
  68852. #else
  68853. static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m)
  68854. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68855. {
  68856. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68857. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  68858. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  68859. register const sp_digit* b __asm__ ("r2") = (const sp_digit*)b_p;
  68860. register sp_digit m __asm__ ("r3") = (sp_digit)m_p;
  68861. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68862. __asm__ __volatile__ (
  68863. "MOV r10, #0x0\n\t"
  68864. "LDM %[a]!, {r6, r7}\n\t"
  68865. "LDM %[b]!, {r8, r9}\n\t"
  68866. "AND r8, r8, %[m]\n\t"
  68867. "AND r9, r9, %[m]\n\t"
  68868. "ADDS r6, r6, r8\n\t"
  68869. "ADCS r7, r7, r9\n\t"
  68870. "STM %[r]!, {r6, r7}\n\t"
  68871. "LDM %[a]!, {r6, r7}\n\t"
  68872. "LDM %[b]!, {r8, r9}\n\t"
  68873. "AND r8, r8, %[m]\n\t"
  68874. "AND r9, r9, %[m]\n\t"
  68875. "ADCS r6, r6, r8\n\t"
  68876. "ADCS r7, r7, r9\n\t"
  68877. "STM %[r]!, {r6, r7}\n\t"
  68878. "LDM %[a]!, {r6, r7}\n\t"
  68879. "LDM %[b]!, {r8, r9}\n\t"
  68880. "AND r8, r8, %[m]\n\t"
  68881. "AND r9, r9, %[m]\n\t"
  68882. "ADCS r6, r6, r8\n\t"
  68883. "ADCS r7, r7, r9\n\t"
  68884. "STM %[r]!, {r6, r7}\n\t"
  68885. "LDM %[a]!, {r6, r7}\n\t"
  68886. "LDM %[b]!, {r8, r9}\n\t"
  68887. "AND r8, r8, %[m]\n\t"
  68888. "AND r9, r9, %[m]\n\t"
  68889. "ADCS r6, r6, r8\n\t"
  68890. "ADCS r7, r7, r9\n\t"
  68891. "STM %[r]!, {r6, r7}\n\t"
  68892. "LDM %[a]!, {r6, r7}\n\t"
  68893. "LDM %[b]!, {r8, r9}\n\t"
  68894. "AND r8, r8, %[m]\n\t"
  68895. "AND r9, r9, %[m]\n\t"
  68896. "ADCS r6, r6, r8\n\t"
  68897. "ADCS r7, r7, r9\n\t"
  68898. "STM %[r]!, {r6, r7}\n\t"
  68899. "LDM %[a]!, {r6, r7}\n\t"
  68900. "LDM %[b]!, {r8, r9}\n\t"
  68901. "AND r8, r8, %[m]\n\t"
  68902. "AND r9, r9, %[m]\n\t"
  68903. "ADCS r6, r6, r8\n\t"
  68904. "ADCS r7, r7, r9\n\t"
  68905. "STM %[r]!, {r6, r7}\n\t"
  68906. "LDM %[a]!, {r6, r7}\n\t"
  68907. "LDM %[b]!, {r8, r9}\n\t"
  68908. "AND r8, r8, %[m]\n\t"
  68909. "AND r9, r9, %[m]\n\t"
  68910. "ADCS r6, r6, r8\n\t"
  68911. "ADCS r7, r7, r9\n\t"
  68912. "STM %[r]!, {r6, r7}\n\t"
  68913. "LDM %[a]!, {r6, r7}\n\t"
  68914. "LDM %[b]!, {r8, r9}\n\t"
  68915. "AND r8, r8, %[m]\n\t"
  68916. "AND r9, r9, %[m]\n\t"
  68917. "ADCS r6, r6, r8\n\t"
  68918. "ADCS r7, r7, r9\n\t"
  68919. "STM %[r]!, {r6, r7}\n\t"
  68920. "LDM %[a]!, {r6, r7}\n\t"
  68921. "LDM %[b]!, {r8, r9}\n\t"
  68922. "AND r8, r8, %[m]\n\t"
  68923. "AND r9, r9, %[m]\n\t"
  68924. "ADCS r6, r6, r8\n\t"
  68925. "ADCS r7, r7, r9\n\t"
  68926. "STM %[r]!, {r6, r7}\n\t"
  68927. "LDM %[a]!, {r6, r7}\n\t"
  68928. "LDM %[b]!, {r8, r9}\n\t"
  68929. "AND r8, r8, %[m]\n\t"
  68930. "AND r9, r9, %[m]\n\t"
  68931. "ADCS r6, r6, r8\n\t"
  68932. "ADCS r7, r7, r9\n\t"
  68933. "STM %[r]!, {r6, r7}\n\t"
  68934. "LDM %[a]!, {r6, r7}\n\t"
  68935. "LDM %[b]!, {r8, r9}\n\t"
  68936. "AND r8, r8, %[m]\n\t"
  68937. "AND r9, r9, %[m]\n\t"
  68938. "ADCS r6, r6, r8\n\t"
  68939. "ADCS r7, r7, r9\n\t"
  68940. "STM %[r]!, {r6, r7}\n\t"
  68941. "LDM %[a]!, {r6, r7}\n\t"
  68942. "LDM %[b]!, {r8, r9}\n\t"
  68943. "AND r8, r8, %[m]\n\t"
  68944. "AND r9, r9, %[m]\n\t"
  68945. "ADCS r6, r6, r8\n\t"
  68946. "ADCS r7, r7, r9\n\t"
  68947. "STM %[r]!, {r6, r7}\n\t"
  68948. "LDM %[a]!, {r6, r7}\n\t"
  68949. "LDM %[b]!, {r8, r9}\n\t"
  68950. "AND r8, r8, %[m]\n\t"
  68951. "AND r9, r9, %[m]\n\t"
  68952. "ADCS r6, r6, r8\n\t"
  68953. "ADCS r7, r7, r9\n\t"
  68954. "STM %[r]!, {r6, r7}\n\t"
  68955. "LDM %[a]!, {r6, r7}\n\t"
  68956. "LDM %[b]!, {r8, r9}\n\t"
  68957. "AND r8, r8, %[m]\n\t"
  68958. "AND r9, r9, %[m]\n\t"
  68959. "ADCS r6, r6, r8\n\t"
  68960. "ADCS r7, r7, r9\n\t"
  68961. "STM %[r]!, {r6, r7}\n\t"
  68962. "LDM %[a]!, {r6, r7}\n\t"
  68963. "LDM %[b]!, {r8, r9}\n\t"
  68964. "AND r8, r8, %[m]\n\t"
  68965. "AND r9, r9, %[m]\n\t"
  68966. "ADCS r6, r6, r8\n\t"
  68967. "ADCS r7, r7, r9\n\t"
  68968. "STM %[r]!, {r6, r7}\n\t"
  68969. "LDM %[a]!, {r6, r7}\n\t"
  68970. "LDM %[b]!, {r8, r9}\n\t"
  68971. "AND r8, r8, %[m]\n\t"
  68972. "AND r9, r9, %[m]\n\t"
  68973. "ADCS r6, r6, r8\n\t"
  68974. "ADCS r7, r7, r9\n\t"
  68975. "STM %[r]!, {r6, r7}\n\t"
  68976. "ADC %[r], r10, r10\n\t"
  68977. : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m)
  68978. :
  68979. : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc"
  68980. );
  68981. return (uint32_t)(size_t)r;
  68982. }
  68983. #endif /* WOLFSSL_SP_SMALL */
  68984. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68985. static void sp_1024_rshift1_32(sp_digit* r_p, const sp_digit* a_p)
  68986. #else
  68987. static void sp_1024_rshift1_32(sp_digit* r, const sp_digit* a)
  68988. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68989. {
  68990. #ifndef WOLFSSL_NO_VAR_ASSIGN_REG
  68991. register sp_digit* r __asm__ ("r0") = (sp_digit*)r_p;
  68992. register const sp_digit* a __asm__ ("r1") = (const sp_digit*)a_p;
  68993. #endif /* !WOLFSSL_NO_VAR_ASSIGN_REG */
  68994. __asm__ __volatile__ (
  68995. "LDM %[a], {r2, r3}\n\t"
  68996. "LSR r2, r2, #1\n\t"
  68997. "ORR r2, r2, r3, lsl #31\n\t"
  68998. "LSR r3, r3, #1\n\t"
  68999. "LDR r4, [%[a], #8]\n\t"
  69000. "STR r2, [%[r]]\n\t"
  69001. "ORR r3, r3, r4, lsl #31\n\t"
  69002. "LSR r4, r4, #1\n\t"
  69003. "LDR r2, [%[a], #12]\n\t"
  69004. "STR r3, [%[r], #4]\n\t"
  69005. "ORR r4, r4, r2, lsl #31\n\t"
  69006. "LSR r2, r2, #1\n\t"
  69007. "LDR r3, [%[a], #16]\n\t"
  69008. "STR r4, [%[r], #8]\n\t"
  69009. "ORR r2, r2, r3, lsl #31\n\t"
  69010. "LSR r3, r3, #1\n\t"
  69011. "LDR r4, [%[a], #20]\n\t"
  69012. "STR r2, [%[r], #12]\n\t"
  69013. "ORR r3, r3, r4, lsl #31\n\t"
  69014. "LSR r4, r4, #1\n\t"
  69015. "LDR r2, [%[a], #24]\n\t"
  69016. "STR r3, [%[r], #16]\n\t"
  69017. "ORR r4, r4, r2, lsl #31\n\t"
  69018. "LSR r2, r2, #1\n\t"
  69019. "LDR r3, [%[a], #28]\n\t"
  69020. "STR r4, [%[r], #20]\n\t"
  69021. "ORR r2, r2, r3, lsl #31\n\t"
  69022. "LSR r3, r3, #1\n\t"
  69023. "LDR r4, [%[a], #32]\n\t"
  69024. "STR r2, [%[r], #24]\n\t"
  69025. "ORR r3, r3, r4, lsl #31\n\t"
  69026. "LSR r4, r4, #1\n\t"
  69027. "LDR r2, [%[a], #36]\n\t"
  69028. "STR r3, [%[r], #28]\n\t"
  69029. "ORR r4, r4, r2, lsl #31\n\t"
  69030. "LSR r2, r2, #1\n\t"
  69031. "LDR r3, [%[a], #40]\n\t"
  69032. "STR r4, [%[r], #32]\n\t"
  69033. "ORR r2, r2, r3, lsl #31\n\t"
  69034. "LSR r3, r3, #1\n\t"
  69035. "LDR r4, [%[a], #44]\n\t"
  69036. "STR r2, [%[r], #36]\n\t"
  69037. "ORR r3, r3, r4, lsl #31\n\t"
  69038. "LSR r4, r4, #1\n\t"
  69039. "LDR r2, [%[a], #48]\n\t"
  69040. "STR r3, [%[r], #40]\n\t"
  69041. "ORR r4, r4, r2, lsl #31\n\t"
  69042. "LSR r2, r2, #1\n\t"
  69043. "LDR r3, [%[a], #52]\n\t"
  69044. "STR r4, [%[r], #44]\n\t"
  69045. "ORR r2, r2, r3, lsl #31\n\t"
  69046. "LSR r3, r3, #1\n\t"
  69047. "LDR r4, [%[a], #56]\n\t"
  69048. "STR r2, [%[r], #48]\n\t"
  69049. "ORR r3, r3, r4, lsl #31\n\t"
  69050. "LSR r4, r4, #1\n\t"
  69051. "LDR r2, [%[a], #60]\n\t"
  69052. "STR r3, [%[r], #52]\n\t"
  69053. "ORR r4, r4, r2, lsl #31\n\t"
  69054. "LSR r2, r2, #1\n\t"
  69055. "LDR r3, [%[a], #64]\n\t"
  69056. "STR r4, [%[r], #56]\n\t"
  69057. "ORR r2, r2, r3, lsl #31\n\t"
  69058. "LSR r3, r3, #1\n\t"
  69059. "LDR r4, [%[a], #68]\n\t"
  69060. "STR r2, [%[r], #60]\n\t"
  69061. "ORR r3, r3, r4, lsl #31\n\t"
  69062. "LSR r4, r4, #1\n\t"
  69063. "LDR r2, [%[a], #72]\n\t"
  69064. "STR r3, [%[r], #64]\n\t"
  69065. "ORR r4, r4, r2, lsl #31\n\t"
  69066. "LSR r2, r2, #1\n\t"
  69067. "LDR r3, [%[a], #76]\n\t"
  69068. "STR r4, [%[r], #68]\n\t"
  69069. "ORR r2, r2, r3, lsl #31\n\t"
  69070. "LSR r3, r3, #1\n\t"
  69071. "LDR r4, [%[a], #80]\n\t"
  69072. "STR r2, [%[r], #72]\n\t"
  69073. "ORR r3, r3, r4, lsl #31\n\t"
  69074. "LSR r4, r4, #1\n\t"
  69075. "LDR r2, [%[a], #84]\n\t"
  69076. "STR r3, [%[r], #76]\n\t"
  69077. "ORR r4, r4, r2, lsl #31\n\t"
  69078. "LSR r2, r2, #1\n\t"
  69079. "LDR r3, [%[a], #88]\n\t"
  69080. "STR r4, [%[r], #80]\n\t"
  69081. "ORR r2, r2, r3, lsl #31\n\t"
  69082. "LSR r3, r3, #1\n\t"
  69083. "LDR r4, [%[a], #92]\n\t"
  69084. "STR r2, [%[r], #84]\n\t"
  69085. "ORR r3, r3, r4, lsl #31\n\t"
  69086. "LSR r4, r4, #1\n\t"
  69087. "LDR r2, [%[a], #96]\n\t"
  69088. "STR r3, [%[r], #88]\n\t"
  69089. "ORR r4, r4, r2, lsl #31\n\t"
  69090. "LSR r2, r2, #1\n\t"
  69091. "LDR r3, [%[a], #100]\n\t"
  69092. "STR r4, [%[r], #92]\n\t"
  69093. "ORR r2, r2, r3, lsl #31\n\t"
  69094. "LSR r3, r3, #1\n\t"
  69095. "LDR r4, [%[a], #104]\n\t"
  69096. "STR r2, [%[r], #96]\n\t"
  69097. "ORR r3, r3, r4, lsl #31\n\t"
  69098. "LSR r4, r4, #1\n\t"
  69099. "LDR r2, [%[a], #108]\n\t"
  69100. "STR r3, [%[r], #100]\n\t"
  69101. "ORR r4, r4, r2, lsl #31\n\t"
  69102. "LSR r2, r2, #1\n\t"
  69103. "LDR r3, [%[a], #112]\n\t"
  69104. "STR r4, [%[r], #104]\n\t"
  69105. "ORR r2, r2, r3, lsl #31\n\t"
  69106. "LSR r3, r3, #1\n\t"
  69107. "LDR r4, [%[a], #116]\n\t"
  69108. "STR r2, [%[r], #108]\n\t"
  69109. "ORR r3, r3, r4, lsl #31\n\t"
  69110. "LSR r4, r4, #1\n\t"
  69111. "LDR r2, [%[a], #120]\n\t"
  69112. "STR r3, [%[r], #112]\n\t"
  69113. "ORR r4, r4, r2, lsl #31\n\t"
  69114. "LSR r2, r2, #1\n\t"
  69115. "LDR r3, [%[a], #124]\n\t"
  69116. "STR r4, [%[r], #116]\n\t"
  69117. "ORR r2, r2, r3, lsl #31\n\t"
  69118. "LSR r3, r3, #1\n\t"
  69119. "STR r2, [%[r], #120]\n\t"
  69120. "STR r3, [%[r], #124]\n\t"
  69121. : [r] "+r" (r), [a] "+r" (a)
  69122. :
  69123. : "memory", "r2", "r3", "r4", "cc"
  69124. );
  69125. }
  69126. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  69127. *
  69128. * r Result of division by 2.
  69129. * a Number to divide.
  69130. * m Modulus (prime).
  69131. */
  69132. static void sp_1024_mont_div2_32(sp_digit* r, const sp_digit* a, const sp_digit* m)
  69133. {
  69134. sp_digit o;
  69135. o = sp_1024_cond_add_32(r, a, m, 0 - (a[0] & 1));
  69136. sp_1024_rshift1_32(r, r);
  69137. r[31] |= o << 31;
  69138. }
  69139. /* Double the Montgomery form projective point p.
  69140. *
  69141. * r Result of doubling point.
  69142. * p Point to double.
  69143. * t Temporary ordinate data.
  69144. */
  69145. static void sp_1024_proj_point_dbl_32(sp_point_1024* r, const sp_point_1024* p,
  69146. sp_digit* t)
  69147. {
  69148. sp_digit* t1 = t;
  69149. sp_digit* t2 = t + 2*32;
  69150. sp_digit* x;
  69151. sp_digit* y;
  69152. sp_digit* z;
  69153. x = r->x;
  69154. y = r->y;
  69155. z = r->z;
  69156. /* Put infinity into result. */
  69157. if (r != p) {
  69158. r->infinity = p->infinity;
  69159. }
  69160. /* T1 = Z * Z */
  69161. sp_1024_mont_sqr_32(t1, p->z, p1024_mod, p1024_mp_mod);
  69162. /* Z = Y * Z */
  69163. sp_1024_mont_mul_32(z, p->y, p->z, p1024_mod, p1024_mp_mod);
  69164. /* Z = 2Z */
  69165. sp_1024_mont_dbl_32(z, z, p1024_mod);
  69166. /* T2 = X - T1 */
  69167. sp_1024_mont_sub_32(t2, p->x, t1, p1024_mod);
  69168. /* T1 = X + T1 */
  69169. sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
  69170. /* T2 = T1 * T2 */
  69171. sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod);
  69172. /* T1 = 3T2 */
  69173. sp_1024_mont_tpl_32(t1, t2, p1024_mod);
  69174. /* Y = 2Y */
  69175. sp_1024_mont_dbl_32(y, p->y, p1024_mod);
  69176. /* Y = Y * Y */
  69177. sp_1024_mont_sqr_32(y, y, p1024_mod, p1024_mp_mod);
  69178. /* T2 = Y * Y */
  69179. sp_1024_mont_sqr_32(t2, y, p1024_mod, p1024_mp_mod);
  69180. /* T2 = T2/2 */
  69181. sp_1024_mont_div2_32(t2, t2, p1024_mod);
  69182. /* Y = Y * X */
  69183. sp_1024_mont_mul_32(y, y, p->x, p1024_mod, p1024_mp_mod);
  69184. /* X = T1 * T1 */
  69185. sp_1024_mont_sqr_32(x, t1, p1024_mod, p1024_mp_mod);
  69186. /* X = X - Y */
  69187. sp_1024_mont_sub_32(x, x, y, p1024_mod);
  69188. /* X = X - Y */
  69189. sp_1024_mont_sub_32(x, x, y, p1024_mod);
  69190. /* Y = Y - X */
  69191. sp_1024_mont_sub_32(y, y, x, p1024_mod);
  69192. /* Y = Y * T1 */
  69193. sp_1024_mont_mul_32(y, y, t1, p1024_mod, p1024_mp_mod);
  69194. /* Y = Y - T2 */
  69195. sp_1024_mont_sub_32(y, y, t2, p1024_mod);
  69196. }
  69197. #ifdef WOLFSSL_SP_NONBLOCK
  69198. typedef struct sp_1024_proj_point_dbl_32_ctx {
  69199. int state;
  69200. sp_digit* t1;
  69201. sp_digit* t2;
  69202. sp_digit* x;
  69203. sp_digit* y;
  69204. sp_digit* z;
  69205. } sp_1024_proj_point_dbl_32_ctx;
  69206. /* Double the Montgomery form projective point p.
  69207. *
  69208. * r Result of doubling point.
  69209. * p Point to double.
  69210. * t Temporary ordinate data.
  69211. */
  69212. static int sp_1024_proj_point_dbl_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
  69213. const sp_point_1024* p, sp_digit* t)
  69214. {
  69215. int err = FP_WOULDBLOCK;
  69216. sp_1024_proj_point_dbl_32_ctx* ctx = (sp_1024_proj_point_dbl_32_ctx*)sp_ctx->data;
  69217. typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  69218. (void)sizeof(ctx_size_test);
  69219. switch (ctx->state) {
  69220. case 0:
  69221. ctx->t1 = t;
  69222. ctx->t2 = t + 2*32;
  69223. ctx->x = r->x;
  69224. ctx->y = r->y;
  69225. ctx->z = r->z;
  69226. /* Put infinity into result. */
  69227. if (r != p) {
  69228. r->infinity = p->infinity;
  69229. }
  69230. ctx->state = 1;
  69231. break;
  69232. case 1:
  69233. /* T1 = Z * Z */
  69234. sp_1024_mont_sqr_32(ctx->t1, p->z, p1024_mod, p1024_mp_mod);
  69235. ctx->state = 2;
  69236. break;
  69237. case 2:
  69238. /* Z = Y * Z */
  69239. sp_1024_mont_mul_32(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod);
  69240. ctx->state = 3;
  69241. break;
  69242. case 3:
  69243. /* Z = 2Z */
  69244. sp_1024_mont_dbl_32(ctx->z, ctx->z, p1024_mod);
  69245. ctx->state = 4;
  69246. break;
  69247. case 4:
  69248. /* T2 = X - T1 */
  69249. sp_1024_mont_sub_32(ctx->t2, p->x, ctx->t1, p1024_mod);
  69250. ctx->state = 5;
  69251. break;
  69252. case 5:
  69253. /* T1 = X + T1 */
  69254. sp_1024_mont_add_32(ctx->t1, p->x, ctx->t1, p1024_mod);
  69255. ctx->state = 6;
  69256. break;
  69257. case 6:
  69258. /* T2 = T1 * T2 */
  69259. sp_1024_mont_mul_32(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod);
  69260. ctx->state = 7;
  69261. break;
  69262. case 7:
  69263. /* T1 = 3T2 */
  69264. sp_1024_mont_tpl_32(ctx->t1, ctx->t2, p1024_mod);
  69265. ctx->state = 8;
  69266. break;
  69267. case 8:
  69268. /* Y = 2Y */
  69269. sp_1024_mont_dbl_32(ctx->y, p->y, p1024_mod);
  69270. ctx->state = 9;
  69271. break;
  69272. case 9:
  69273. /* Y = Y * Y */
  69274. sp_1024_mont_sqr_32(ctx->y, ctx->y, p1024_mod, p1024_mp_mod);
  69275. ctx->state = 10;
  69276. break;
  69277. case 10:
  69278. /* T2 = Y * Y */
  69279. sp_1024_mont_sqr_32(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod);
  69280. ctx->state = 11;
  69281. break;
  69282. case 11:
  69283. /* T2 = T2/2 */
  69284. sp_1024_mont_div2_32(ctx->t2, ctx->t2, p1024_mod);
  69285. ctx->state = 12;
  69286. break;
  69287. case 12:
  69288. /* Y = Y * X */
  69289. sp_1024_mont_mul_32(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod);
  69290. ctx->state = 13;
  69291. break;
  69292. case 13:
  69293. /* X = T1 * T1 */
  69294. sp_1024_mont_sqr_32(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod);
  69295. ctx->state = 14;
  69296. break;
  69297. case 14:
  69298. /* X = X - Y */
  69299. sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
  69300. ctx->state = 15;
  69301. break;
  69302. case 15:
  69303. /* X = X - Y */
  69304. sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod);
  69305. ctx->state = 16;
  69306. break;
  69307. case 16:
  69308. /* Y = Y - X */
  69309. sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
  69310. ctx->state = 17;
  69311. break;
  69312. case 17:
  69313. /* Y = Y * T1 */
  69314. sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod);
  69315. ctx->state = 18;
  69316. break;
  69317. case 18:
  69318. /* Y = Y - T2 */
  69319. sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t2, p1024_mod);
  69320. ctx->state = 19;
  69321. /* fall-through */
  69322. case 19:
  69323. err = MP_OKAY;
  69324. break;
  69325. }
  69326. if (err == MP_OKAY && ctx->state != 19) {
  69327. err = FP_WOULDBLOCK;
  69328. }
  69329. return err;
  69330. }
  69331. #endif /* WOLFSSL_SP_NONBLOCK */
  69332. /* Compare two numbers to determine if they are equal.
  69333. * Constant time implementation.
  69334. *
  69335. * a First number to compare.
  69336. * b Second number to compare.
  69337. * returns 1 when equal and 0 otherwise.
  69338. */
  69339. static int sp_1024_cmp_equal_32(const sp_digit* a, const sp_digit* b)
  69340. {
  69341. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  69342. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  69343. (a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
  69344. (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
  69345. (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) |
  69346. (a[15] ^ b[15]) | (a[16] ^ b[16]) | (a[17] ^ b[17]) |
  69347. (a[18] ^ b[18]) | (a[19] ^ b[19]) | (a[20] ^ b[20]) |
  69348. (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) |
  69349. (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) |
  69350. (a[27] ^ b[27]) | (a[28] ^ b[28]) | (a[29] ^ b[29]) |
  69351. (a[30] ^ b[30]) | (a[31] ^ b[31])) == 0;
  69352. }
  69353. /* Returns 1 if the number of zero.
  69354. * Implementation is constant time.
  69355. *
  69356. * a Number to check.
  69357. * returns 1 if the number is zero and 0 otherwise.
  69358. */
  69359. static int sp_1024_iszero_32(const sp_digit* a)
  69360. {
  69361. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
  69362. a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
  69363. a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] |
  69364. a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31]) == 0;
  69365. }
  69366. /* Add two Montgomery form projective points.
  69367. *
  69368. * r Result of addition.
  69369. * p First point to add.
  69370. * q Second point to add.
  69371. * t Temporary ordinate data.
  69372. */
  69373. static void sp_1024_proj_point_add_32(sp_point_1024* r,
  69374. const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
  69375. {
  69376. sp_digit* t6 = t;
  69377. sp_digit* t1 = t + 2*32;
  69378. sp_digit* t2 = t + 4*32;
  69379. sp_digit* t3 = t + 6*32;
  69380. sp_digit* t4 = t + 8*32;
  69381. sp_digit* t5 = t + 10*32;
  69382. /* U1 = X1*Z2^2 */
  69383. sp_1024_mont_sqr_32(t1, q->z, p1024_mod, p1024_mp_mod);
  69384. sp_1024_mont_mul_32(t3, t1, q->z, p1024_mod, p1024_mp_mod);
  69385. sp_1024_mont_mul_32(t1, t1, p->x, p1024_mod, p1024_mp_mod);
  69386. /* U2 = X2*Z1^2 */
  69387. sp_1024_mont_sqr_32(t2, p->z, p1024_mod, p1024_mp_mod);
  69388. sp_1024_mont_mul_32(t4, t2, p->z, p1024_mod, p1024_mp_mod);
  69389. sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
  69390. /* S1 = Y1*Z2^3 */
  69391. sp_1024_mont_mul_32(t3, t3, p->y, p1024_mod, p1024_mp_mod);
  69392. /* S2 = Y2*Z1^3 */
  69393. sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
  69394. /* Check double */
  69395. if ((~p->infinity) & (~q->infinity) &
  69396. sp_1024_cmp_equal_32(t2, t1) &
  69397. sp_1024_cmp_equal_32(t4, t3)) {
  69398. sp_1024_proj_point_dbl_32(r, p, t);
  69399. }
  69400. else {
  69401. sp_digit* x = t6;
  69402. sp_digit* y = t1;
  69403. sp_digit* z = t2;
  69404. /* H = U2 - U1 */
  69405. sp_1024_mont_sub_32(t2, t2, t1, p1024_mod);
  69406. /* R = S2 - S1 */
  69407. sp_1024_mont_sub_32(t4, t4, t3, p1024_mod);
  69408. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  69409. sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod);
  69410. sp_1024_mont_mul_32(y, t1, t5, p1024_mod, p1024_mp_mod);
  69411. sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod);
  69412. /* Z3 = H*Z1*Z2 */
  69413. sp_1024_mont_mul_32(z, p->z, t2, p1024_mod, p1024_mp_mod);
  69414. sp_1024_mont_mul_32(z, z, q->z, p1024_mod, p1024_mp_mod);
  69415. sp_1024_mont_sqr_32(x, t4, p1024_mod, p1024_mp_mod);
  69416. sp_1024_mont_sub_32(x, x, t5, p1024_mod);
  69417. sp_1024_mont_mul_32(t5, t5, t3, p1024_mod, p1024_mp_mod);
  69418. sp_1024_mont_dbl_32(t3, y, p1024_mod);
  69419. sp_1024_mont_sub_32(x, x, t3, p1024_mod);
  69420. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  69421. sp_1024_mont_sub_32(y, y, x, p1024_mod);
  69422. sp_1024_mont_mul_32(y, y, t4, p1024_mod, p1024_mp_mod);
  69423. sp_1024_mont_sub_32(y, y, t5, p1024_mod);
  69424. {
  69425. int i;
  69426. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  69427. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  69428. sp_digit maskt = ~(maskp | maskq);
  69429. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  69430. for (i = 0; i < 32; i++) {
  69431. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  69432. (x[i] & maskt);
  69433. }
  69434. for (i = 0; i < 32; i++) {
  69435. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  69436. (y[i] & maskt);
  69437. }
  69438. for (i = 0; i < 32; i++) {
  69439. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  69440. (z[i] & maskt);
  69441. }
  69442. r->z[0] |= inf;
  69443. r->infinity = (word32)inf;
  69444. }
  69445. }
  69446. }
  69447. #ifdef WOLFSSL_SP_NONBLOCK
  69448. typedef struct sp_1024_proj_point_add_32_ctx {
  69449. int state;
  69450. sp_1024_proj_point_dbl_32_ctx dbl_ctx;
  69451. const sp_point_1024* ap[2];
  69452. sp_point_1024* rp[2];
  69453. sp_digit* t1;
  69454. sp_digit* t2;
  69455. sp_digit* t3;
  69456. sp_digit* t4;
  69457. sp_digit* t5;
  69458. sp_digit* t6;
  69459. sp_digit* x;
  69460. sp_digit* y;
  69461. sp_digit* z;
  69462. } sp_1024_proj_point_add_32_ctx;
  69463. /* Add two Montgomery form projective points.
  69464. *
  69465. * r Result of addition.
  69466. * p First point to add.
  69467. * q Second point to add.
  69468. * t Temporary ordinate data.
  69469. */
  69470. static int sp_1024_proj_point_add_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
  69471. const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
  69472. {
  69473. int err = FP_WOULDBLOCK;
  69474. sp_1024_proj_point_add_32_ctx* ctx = (sp_1024_proj_point_add_32_ctx*)sp_ctx->data;
  69475. /* Ensure only the first point is the same as the result. */
  69476. if (q == r) {
  69477. const sp_point_1024* a = p;
  69478. p = q;
  69479. q = a;
  69480. }
  69481. typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  69482. (void)sizeof(ctx_size_test);
  69483. switch (ctx->state) {
  69484. case 0: /* INIT */
  69485. ctx->t6 = t;
  69486. ctx->t1 = t + 2*32;
  69487. ctx->t2 = t + 4*32;
  69488. ctx->t3 = t + 6*32;
  69489. ctx->t4 = t + 8*32;
  69490. ctx->t5 = t + 10*32;
  69491. ctx->x = ctx->t6;
  69492. ctx->y = ctx->t1;
  69493. ctx->z = ctx->t2;
  69494. ctx->state = 1;
  69495. break;
  69496. case 1:
  69497. /* U1 = X1*Z2^2 */
  69498. sp_1024_mont_sqr_32(ctx->t1, q->z, p1024_mod, p1024_mp_mod);
  69499. ctx->state = 2;
  69500. break;
  69501. case 2:
  69502. sp_1024_mont_mul_32(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod);
  69503. ctx->state = 3;
  69504. break;
  69505. case 3:
  69506. sp_1024_mont_mul_32(ctx->t1, ctx->t1, p->x, p1024_mod, p1024_mp_mod);
  69507. ctx->state = 4;
  69508. break;
  69509. case 4:
  69510. /* U2 = X2*Z1^2 */
  69511. sp_1024_mont_sqr_32(ctx->t2, p->z, p1024_mod, p1024_mp_mod);
  69512. ctx->state = 5;
  69513. break;
  69514. case 5:
  69515. sp_1024_mont_mul_32(ctx->t4, ctx->t2, p->z, p1024_mod, p1024_mp_mod);
  69516. ctx->state = 6;
  69517. break;
  69518. case 6:
  69519. sp_1024_mont_mul_32(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod);
  69520. ctx->state = 7;
  69521. break;
  69522. case 7:
  69523. /* S1 = Y1*Z2^3 */
  69524. sp_1024_mont_mul_32(ctx->t3, ctx->t3, p->y, p1024_mod, p1024_mp_mod);
  69525. ctx->state = 8;
  69526. break;
  69527. case 8:
  69528. /* S2 = Y2*Z1^3 */
  69529. sp_1024_mont_mul_32(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod);
  69530. ctx->state = 9;
  69531. break;
  69532. case 9:
  69533. /* Check double */
  69534. if ((~p->infinity) & (~q->infinity) &
  69535. sp_1024_cmp_equal_32(ctx->t2, ctx->t1) &
  69536. sp_1024_cmp_equal_32(ctx->t4, ctx->t3)) {
  69537. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  69538. sp_1024_proj_point_dbl_32(r, p, t);
  69539. ctx->state = 25;
  69540. }
  69541. else {
  69542. ctx->state = 10;
  69543. }
  69544. break;
  69545. case 10:
  69546. /* H = U2 - U1 */
  69547. sp_1024_mont_sub_32(ctx->t2, ctx->t2, ctx->t1, p1024_mod);
  69548. ctx->state = 11;
  69549. break;
  69550. case 11:
  69551. /* R = S2 - S1 */
  69552. sp_1024_mont_sub_32(ctx->t4, ctx->t4, ctx->t3, p1024_mod);
  69553. ctx->state = 12;
  69554. break;
  69555. case 12:
  69556. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  69557. sp_1024_mont_sqr_32(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
  69558. ctx->state = 13;
  69559. break;
  69560. case 13:
  69561. sp_1024_mont_mul_32(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod);
  69562. ctx->state = 14;
  69563. break;
  69564. case 14:
  69565. sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
  69566. ctx->state = 15;
  69567. break;
  69568. case 15:
  69569. /* Z3 = H*Z1*Z2 */
  69570. sp_1024_mont_mul_32(ctx->z, p->z, ctx->t2, p1024_mod, p1024_mp_mod);
  69571. ctx->state = 16;
  69572. break;
  69573. case 16:
  69574. sp_1024_mont_mul_32(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod);
  69575. ctx->state = 17;
  69576. break;
  69577. case 17:
  69578. sp_1024_mont_sqr_32(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod);
  69579. ctx->state = 18;
  69580. break;
  69581. case 18:
  69582. sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t5, p1024_mod);
  69583. ctx->state = 19;
  69584. break;
  69585. case 19:
  69586. sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod);
  69587. ctx->state = 20;
  69588. break;
  69589. case 20:
  69590. sp_1024_mont_dbl_32(ctx->t3, ctx->y, p1024_mod);
  69591. sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t3, p1024_mod);
  69592. ctx->state = 21;
  69593. break;
  69594. case 21:
  69595. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  69596. sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod);
  69597. ctx->state = 22;
  69598. break;
  69599. case 22:
  69600. sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod);
  69601. ctx->state = 23;
  69602. break;
  69603. case 23:
  69604. sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t5, p1024_mod);
  69605. ctx->state = 24;
  69606. break;
  69607. case 24:
  69608. {
  69609. {
  69610. int i;
  69611. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  69612. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  69613. sp_digit maskt = ~(maskp | maskq);
  69614. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  69615. for (i = 0; i < 32; i++) {
  69616. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  69617. (ctx->x[i] & maskt);
  69618. }
  69619. for (i = 0; i < 32; i++) {
  69620. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  69621. (ctx->y[i] & maskt);
  69622. }
  69623. for (i = 0; i < 32; i++) {
  69624. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  69625. (ctx->z[i] & maskt);
  69626. }
  69627. r->z[0] |= inf;
  69628. r->infinity = (word32)inf;
  69629. }
  69630. ctx->state = 25;
  69631. break;
  69632. }
  69633. case 25:
  69634. err = MP_OKAY;
  69635. break;
  69636. }
  69637. if (err == MP_OKAY && ctx->state != 25) {
  69638. err = FP_WOULDBLOCK;
  69639. }
  69640. return err;
  69641. }
  69642. #endif /* WOLFSSL_SP_NONBLOCK */
  69643. /* Multiply the point by the scalar and return the result.
  69644. * If map is true then convert result to affine coordinates.
  69645. *
  69646. * Fast implementation that generates a pre-computation table.
  69647. * 4 bits of window (no sliding!).
  69648. * Uses add and double for calculating table.
  69649. * 1024 doubles.
  69650. * 268 adds.
  69651. *
  69652. * r Resulting point.
  69653. * g Point to multiply.
  69654. * k Scalar to multiply by.
  69655. * map Indicates whether to convert result to affine.
  69656. * ct Constant time required.
  69657. * heap Heap to use for allocation.
  69658. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  69659. */
  69660. static int sp_1024_ecc_mulmod_fast_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k,
  69661. int map, int ct, void* heap)
  69662. {
  69663. #ifdef WOLFSSL_SP_SMALL_STACK
  69664. sp_point_1024* t = NULL;
  69665. sp_digit* tmp = NULL;
  69666. #else
  69667. sp_point_1024 t[16 + 1];
  69668. sp_digit tmp[2 * 32 * 37];
  69669. #endif
  69670. sp_point_1024* rt = NULL;
  69671. sp_digit n;
  69672. int i;
  69673. int c;
  69674. int y;
  69675. int err = MP_OKAY;
  69676. /* Constant time used for cache attack resistance implementation. */
  69677. (void)ct;
  69678. (void)heap;
  69679. #ifdef WOLFSSL_SP_SMALL_STACK
  69680. t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * (16 + 1),
  69681. heap, DYNAMIC_TYPE_ECC);
  69682. if (t == NULL)
  69683. err = MEMORY_E;
  69684. if (err == MP_OKAY) {
  69685. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 37, heap,
  69686. DYNAMIC_TYPE_ECC);
  69687. if (tmp == NULL)
  69688. err = MEMORY_E;
  69689. }
  69690. #endif
  69691. if (err == MP_OKAY) {
  69692. rt = t + 16;
  69693. /* t[0] = {0, 0, 1} * norm */
  69694. XMEMSET(&t[0], 0, sizeof(t[0]));
  69695. t[0].infinity = 1;
  69696. /* t[1] = {g->x, g->y, g->z} * norm */
  69697. (void)sp_1024_mod_mul_norm_32(t[1].x, g->x, p1024_mod);
  69698. (void)sp_1024_mod_mul_norm_32(t[1].y, g->y, p1024_mod);
  69699. (void)sp_1024_mod_mul_norm_32(t[1].z, g->z, p1024_mod);
  69700. t[1].infinity = 0;
  69701. sp_1024_proj_point_dbl_32(&t[ 2], &t[ 1], tmp);
  69702. t[ 2].infinity = 0;
  69703. sp_1024_proj_point_add_32(&t[ 3], &t[ 2], &t[ 1], tmp);
  69704. t[ 3].infinity = 0;
  69705. sp_1024_proj_point_dbl_32(&t[ 4], &t[ 2], tmp);
  69706. t[ 4].infinity = 0;
  69707. sp_1024_proj_point_add_32(&t[ 5], &t[ 3], &t[ 2], tmp);
  69708. t[ 5].infinity = 0;
  69709. sp_1024_proj_point_dbl_32(&t[ 6], &t[ 3], tmp);
  69710. t[ 6].infinity = 0;
  69711. sp_1024_proj_point_add_32(&t[ 7], &t[ 4], &t[ 3], tmp);
  69712. t[ 7].infinity = 0;
  69713. sp_1024_proj_point_dbl_32(&t[ 8], &t[ 4], tmp);
  69714. t[ 8].infinity = 0;
  69715. sp_1024_proj_point_add_32(&t[ 9], &t[ 5], &t[ 4], tmp);
  69716. t[ 9].infinity = 0;
  69717. sp_1024_proj_point_dbl_32(&t[10], &t[ 5], tmp);
  69718. t[10].infinity = 0;
  69719. sp_1024_proj_point_add_32(&t[11], &t[ 6], &t[ 5], tmp);
  69720. t[11].infinity = 0;
  69721. sp_1024_proj_point_dbl_32(&t[12], &t[ 6], tmp);
  69722. t[12].infinity = 0;
  69723. sp_1024_proj_point_add_32(&t[13], &t[ 7], &t[ 6], tmp);
  69724. t[13].infinity = 0;
  69725. sp_1024_proj_point_dbl_32(&t[14], &t[ 7], tmp);
  69726. t[14].infinity = 0;
  69727. sp_1024_proj_point_add_32(&t[15], &t[ 8], &t[ 7], tmp);
  69728. t[15].infinity = 0;
  69729. i = 30;
  69730. n = k[i+1] << 0;
  69731. c = 28;
  69732. y = (int)(n >> 28);
  69733. XMEMCPY(rt, &t[y], sizeof(sp_point_1024));
  69734. n <<= 4;
  69735. for (; i>=0 || c>=4; ) {
  69736. if (c < 4) {
  69737. n |= k[i--];
  69738. c += 32;
  69739. }
  69740. y = (n >> 28) & 0xf;
  69741. n <<= 4;
  69742. c -= 4;
  69743. sp_1024_proj_point_dbl_32(rt, rt, tmp);
  69744. sp_1024_proj_point_dbl_32(rt, rt, tmp);
  69745. sp_1024_proj_point_dbl_32(rt, rt, tmp);
  69746. sp_1024_proj_point_dbl_32(rt, rt, tmp);
  69747. sp_1024_proj_point_add_32(rt, rt, &t[y], tmp);
  69748. }
  69749. if (map != 0) {
  69750. sp_1024_map_32(r, rt, tmp);
  69751. }
  69752. else {
  69753. XMEMCPY(r, rt, sizeof(sp_point_1024));
  69754. }
  69755. }
  69756. #ifdef WOLFSSL_SP_SMALL_STACK
  69757. if (tmp != NULL)
  69758. #endif
  69759. {
  69760. ForceZero(tmp, sizeof(sp_digit) * 2 * 32 * 37);
  69761. #ifdef WOLFSSL_SP_SMALL_STACK
  69762. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  69763. #endif
  69764. }
  69765. #ifdef WOLFSSL_SP_SMALL_STACK
  69766. if (t != NULL)
  69767. #endif
  69768. {
  69769. ForceZero(t, sizeof(sp_point_1024) * 17);
  69770. #ifdef WOLFSSL_SP_SMALL_STACK
  69771. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  69772. #endif
  69773. }
  69774. return err;
  69775. }
  69776. #if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
  69777. /* Double the Montgomery form projective point p a number of times.
  69778. *
  69779. * r Result of repeated doubling of point.
  69780. * p Point to double.
  69781. * n Number of times to double
  69782. * t Temporary ordinate data.
  69783. */
  69784. static void sp_1024_proj_point_dbl_n_32(sp_point_1024* p, int i,
  69785. sp_digit* t)
  69786. {
  69787. sp_digit* w = t;
  69788. sp_digit* a = t + 2*32;
  69789. sp_digit* b = t + 4*32;
  69790. sp_digit* t1 = t + 6*32;
  69791. sp_digit* t2 = t + 8*32;
  69792. sp_digit* x;
  69793. sp_digit* y;
  69794. sp_digit* z;
  69795. volatile int n = i;
  69796. x = p->x;
  69797. y = p->y;
  69798. z = p->z;
  69799. /* Y = 2*Y */
  69800. sp_1024_mont_dbl_32(y, y, p1024_mod);
  69801. /* W = Z^4 */
  69802. sp_1024_mont_sqr_32(w, z, p1024_mod, p1024_mp_mod);
  69803. sp_1024_mont_sqr_32(w, w, p1024_mod, p1024_mp_mod);
  69804. #ifndef WOLFSSL_SP_SMALL
  69805. while (--n > 0)
  69806. #else
  69807. while (--n >= 0)
  69808. #endif
  69809. {
  69810. /* A = 3*(X^2 - W) */
  69811. sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
  69812. sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
  69813. sp_1024_mont_tpl_32(a, t1, p1024_mod);
  69814. /* B = X*Y^2 */
  69815. sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
  69816. sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
  69817. /* X = A^2 - 2B */
  69818. sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
  69819. sp_1024_mont_dbl_32(t2, b, p1024_mod);
  69820. sp_1024_mont_sub_32(x, x, t2, p1024_mod);
  69821. /* B = 2.(B - X) */
  69822. sp_1024_mont_sub_32(t2, b, x, p1024_mod);
  69823. sp_1024_mont_dbl_32(b, t2, p1024_mod);
  69824. /* Z = Z*Y */
  69825. sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
  69826. /* t1 = Y^4 */
  69827. sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
  69828. #ifdef WOLFSSL_SP_SMALL
  69829. if (n != 0)
  69830. #endif
  69831. {
  69832. /* W = W*Y^4 */
  69833. sp_1024_mont_mul_32(w, w, t1, p1024_mod, p1024_mp_mod);
  69834. }
  69835. /* y = 2*A*(B - X) - Y^4 */
  69836. sp_1024_mont_mul_32(y, b, a, p1024_mod, p1024_mp_mod);
  69837. sp_1024_mont_sub_32(y, y, t1, p1024_mod);
  69838. }
  69839. #ifndef WOLFSSL_SP_SMALL
  69840. /* A = 3*(X^2 - W) */
  69841. sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod);
  69842. sp_1024_mont_sub_32(t1, t1, w, p1024_mod);
  69843. sp_1024_mont_tpl_32(a, t1, p1024_mod);
  69844. /* B = X*Y^2 */
  69845. sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod);
  69846. sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod);
  69847. /* X = A^2 - 2B */
  69848. sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod);
  69849. sp_1024_mont_dbl_32(t2, b, p1024_mod);
  69850. sp_1024_mont_sub_32(x, x, t2, p1024_mod);
  69851. /* B = 2.(B - X) */
  69852. sp_1024_mont_sub_32(t2, b, x, p1024_mod);
  69853. sp_1024_mont_dbl_32(b, t2, p1024_mod);
  69854. /* Z = Z*Y */
  69855. sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod);
  69856. /* t1 = Y^4 */
  69857. sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod);
  69858. /* y = 2*A*(B - X) - Y^4 */
  69859. sp_1024_mont_mul_32(y, b, a, p1024_mod, p1024_mp_mod);
  69860. sp_1024_mont_sub_32(y, y, t1, p1024_mod);
  69861. #endif /* WOLFSSL_SP_SMALL */
  69862. /* Y = Y/2 */
  69863. sp_1024_mont_div2_32(y, y, p1024_mod);
  69864. }
  69865. /* Convert the projective point to affine.
  69866. * Ordinates are in Montgomery form.
  69867. *
  69868. * a Point to convert.
  69869. * t Temporary data.
  69870. */
  69871. static void sp_1024_proj_to_affine_32(sp_point_1024* a, sp_digit* t)
  69872. {
  69873. sp_digit* t1 = t;
  69874. sp_digit* t2 = t + 2 * 32;
  69875. sp_digit* tmp = t + 4 * 32;
  69876. sp_1024_mont_inv_32(t1, a->z, tmp);
  69877. sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
  69878. sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
  69879. sp_1024_mont_mul_32(a->x, a->x, t2, p1024_mod, p1024_mp_mod);
  69880. sp_1024_mont_mul_32(a->y, a->y, t1, p1024_mod, p1024_mp_mod);
  69881. XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  69882. }
  69883. #endif /* FP_ECC || !WOLFSSL_SP_SMALL */
  69884. /* A table entry for pre-computed points. */
  69885. typedef struct sp_table_entry_1024 {
  69886. sp_digit x[32];
  69887. sp_digit y[32];
  69888. } sp_table_entry_1024;
  69889. #ifdef FP_ECC
  69890. #endif /* FP_ECC */
  69891. /* Add two Montgomery form projective points. The second point has a q value of
  69892. * one.
  69893. * Only the first point can be the same pointer as the result point.
  69894. *
  69895. * r Result of addition.
  69896. * p First point to add.
  69897. * q Second point to add.
  69898. * t Temporary ordinate data.
  69899. */
  69900. static void sp_1024_proj_point_add_qz1_32(sp_point_1024* r,
  69901. const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
  69902. {
  69903. sp_digit* t2 = t;
  69904. sp_digit* t3 = t + 2*32;
  69905. sp_digit* t6 = t + 4*32;
  69906. sp_digit* t1 = t + 6*32;
  69907. sp_digit* t4 = t + 8*32;
  69908. sp_digit* t5 = t + 10*32;
  69909. /* Calculate values to subtract from P->x and P->y. */
  69910. /* U2 = X2*Z1^2 */
  69911. sp_1024_mont_sqr_32(t2, p->z, p1024_mod, p1024_mp_mod);
  69912. sp_1024_mont_mul_32(t4, t2, p->z, p1024_mod, p1024_mp_mod);
  69913. sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod);
  69914. /* S2 = Y2*Z1^3 */
  69915. sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod);
  69916. if ((~p->infinity) & (~q->infinity) &
  69917. sp_1024_cmp_equal_32(p->x, t2) &
  69918. sp_1024_cmp_equal_32(p->y, t4)) {
  69919. sp_1024_proj_point_dbl_32(r, p, t);
  69920. }
  69921. else {
  69922. sp_digit* x = t2;
  69923. sp_digit* y = t3;
  69924. sp_digit* z = t6;
  69925. /* H = U2 - X1 */
  69926. sp_1024_mont_sub_32(t2, t2, p->x, p1024_mod);
  69927. /* R = S2 - Y1 */
  69928. sp_1024_mont_sub_32(t4, t4, p->y, p1024_mod);
  69929. /* Z3 = H*Z1 */
  69930. sp_1024_mont_mul_32(z, p->z, t2, p1024_mod, p1024_mp_mod);
  69931. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  69932. sp_1024_mont_sqr_32(t1, t2, p1024_mod, p1024_mp_mod);
  69933. sp_1024_mont_mul_32(t3, p->x, t1, p1024_mod, p1024_mp_mod);
  69934. sp_1024_mont_mul_32(t1, t1, t2, p1024_mod, p1024_mp_mod);
  69935. sp_1024_mont_sqr_32(t2, t4, p1024_mod, p1024_mp_mod);
  69936. sp_1024_mont_sub_32(t2, t2, t1, p1024_mod);
  69937. sp_1024_mont_dbl_32(t5, t3, p1024_mod);
  69938. sp_1024_mont_sub_32(x, t2, t5, p1024_mod);
  69939. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  69940. sp_1024_mont_sub_32(t3, t3, x, p1024_mod);
  69941. sp_1024_mont_mul_32(t3, t3, t4, p1024_mod, p1024_mp_mod);
  69942. sp_1024_mont_mul_32(t1, t1, p->y, p1024_mod, p1024_mp_mod);
  69943. sp_1024_mont_sub_32(y, t3, t1, p1024_mod);
  69944. {
  69945. int i;
  69946. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  69947. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  69948. sp_digit maskt = ~(maskp | maskq);
  69949. sp_digit inf = (sp_digit)(p->infinity & q->infinity);
  69950. for (i = 0; i < 32; i++) {
  69951. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  69952. (x[i] & maskt);
  69953. }
  69954. for (i = 0; i < 32; i++) {
  69955. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  69956. (y[i] & maskt);
  69957. }
  69958. for (i = 0; i < 32; i++) {
  69959. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  69960. (z[i] & maskt);
  69961. }
  69962. r->z[0] |= inf;
  69963. r->infinity = (word32)inf;
  69964. }
  69965. }
  69966. }
  69967. #ifdef WOLFSSL_SP_SMALL
  69968. #if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
  69969. /* Generate the pre-computed table of points for the base point.
  69970. *
  69971. * width = 4
  69972. * 16 entries
  69973. * 256 bits between
  69974. *
  69975. * a The base point.
  69976. * table Place to store generated point data.
  69977. * tmp Temporary data.
  69978. * heap Heap to use for allocation.
  69979. */
  69980. static int sp_1024_gen_stripe_table_32(const sp_point_1024* a,
  69981. sp_table_entry_1024* table, sp_digit* tmp, void* heap)
  69982. {
  69983. #ifdef WOLFSSL_SP_SMALL_STACK
  69984. sp_point_1024* t = NULL;
  69985. #else
  69986. sp_point_1024 t[3];
  69987. #endif
  69988. sp_point_1024* s1 = NULL;
  69989. sp_point_1024* s2 = NULL;
  69990. int i;
  69991. int j;
  69992. int err = MP_OKAY;
  69993. (void)heap;
  69994. #ifdef WOLFSSL_SP_SMALL_STACK
  69995. t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap,
  69996. DYNAMIC_TYPE_ECC);
  69997. if (t == NULL)
  69998. err = MEMORY_E;
  69999. #endif
  70000. if (err == MP_OKAY) {
  70001. s1 = t + 1;
  70002. s2 = t + 2;
  70003. err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod);
  70004. }
  70005. if (err == MP_OKAY) {
  70006. err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod);
  70007. }
  70008. if (err == MP_OKAY) {
  70009. err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod);
  70010. }
  70011. if (err == MP_OKAY) {
  70012. t->infinity = 0;
  70013. sp_1024_proj_to_affine_32(t, tmp);
  70014. XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70015. s1->infinity = 0;
  70016. XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70017. s2->infinity = 0;
  70018. /* table[0] = {0, 0, infinity} */
  70019. XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024));
  70020. /* table[1] = Affine version of 'a' in Montgomery form */
  70021. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  70022. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  70023. for (i=1; i<4; i++) {
  70024. sp_1024_proj_point_dbl_n_32(t, 256, tmp);
  70025. sp_1024_proj_to_affine_32(t, tmp);
  70026. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  70027. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  70028. }
  70029. for (i=1; i<4; i++) {
  70030. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  70031. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  70032. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  70033. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  70034. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  70035. sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp);
  70036. sp_1024_proj_to_affine_32(t, tmp);
  70037. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  70038. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  70039. }
  70040. }
  70041. }
  70042. #ifdef WOLFSSL_SP_SMALL_STACK
  70043. if (t != NULL)
  70044. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  70045. #endif
  70046. return err;
  70047. }
  70048. #endif /* FP_ECC || !WOLFSSL_SP_SMALL */
  70049. /* Multiply the point by the scalar and return the result.
  70050. * If map is true then convert result to affine coordinates.
  70051. *
  70052. * Stripe implementation.
  70053. * Pre-generated: 2^0, 2^256, ...
  70054. * Pre-generated: products of all combinations of above.
  70055. * 4 doubles and adds (with qz=1)
  70056. *
  70057. * r Resulting point.
  70058. * k Scalar to multiply by.
  70059. * table Pre-computed table.
  70060. * map Indicates whether to convert result to affine.
  70061. * ct Constant time required.
  70062. * heap Heap to use for allocation.
  70063. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  70064. */
  70065. static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g,
  70066. const sp_table_entry_1024* table, const sp_digit* k, int map,
  70067. int ct, void* heap)
  70068. {
  70069. #ifdef WOLFSSL_SP_SMALL_STACK
  70070. sp_point_1024* rt = NULL;
  70071. sp_digit* t = NULL;
  70072. #else
  70073. sp_point_1024 rt[2];
  70074. sp_digit t[2 * 32 * 37];
  70075. #endif
  70076. sp_point_1024* p = NULL;
  70077. int i;
  70078. int j;
  70079. int y;
  70080. int x;
  70081. int err = MP_OKAY;
  70082. (void)g;
  70083. /* Constant time used for cache attack resistance implementation. */
  70084. (void)ct;
  70085. (void)heap;
  70086. #ifdef WOLFSSL_SP_SMALL_STACK
  70087. rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
  70088. DYNAMIC_TYPE_ECC);
  70089. if (rt == NULL)
  70090. err = MEMORY_E;
  70091. if (err == MP_OKAY) {
  70092. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 37, heap,
  70093. DYNAMIC_TYPE_ECC);
  70094. if (t == NULL)
  70095. err = MEMORY_E;
  70096. }
  70097. #endif
  70098. if (err == MP_OKAY) {
  70099. p = rt + 1;
  70100. XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70101. XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70102. y = 0;
  70103. x = 255;
  70104. for (j=0; j<4; j++) {
  70105. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  70106. x += 256;
  70107. }
  70108. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  70109. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  70110. rt->infinity = !y;
  70111. for (i=254; i>=0; i--) {
  70112. y = 0;
  70113. x = i;
  70114. for (j=0; j<4; j++) {
  70115. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  70116. x += 256;
  70117. }
  70118. sp_1024_proj_point_dbl_32(rt, rt, t);
  70119. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  70120. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  70121. p->infinity = !y;
  70122. sp_1024_proj_point_add_qz1_32(rt, rt, p, t);
  70123. }
  70124. if (map != 0) {
  70125. sp_1024_map_32(r, rt, t);
  70126. }
  70127. else {
  70128. XMEMCPY(r, rt, sizeof(sp_point_1024));
  70129. }
  70130. }
  70131. #ifdef WOLFSSL_SP_SMALL_STACK
  70132. if (t != NULL)
  70133. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  70134. if (rt != NULL)
  70135. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  70136. #endif
  70137. return err;
  70138. }
  70139. #ifdef FP_ECC
  70140. #ifndef FP_ENTRIES
  70141. #define FP_ENTRIES 16
  70142. #endif
  70143. /* Cache entry - holds precomputation tables for a point. */
  70144. typedef struct sp_cache_1024_t {
  70145. /* X ordinate of point that table was generated from. */
  70146. sp_digit x[32];
  70147. /* Y ordinate of point that table was generated from. */
  70148. sp_digit y[32];
  70149. /* Precomputation table for point. */
  70150. sp_table_entry_1024 table[16];
  70151. /* Count of entries in table. */
  70152. uint32_t cnt;
  70153. /* Point and table set in entry. */
  70154. int set;
  70155. } sp_cache_1024_t;
  70156. /* Cache of tables. */
  70157. static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES];
  70158. /* Index of last entry in cache. */
  70159. static THREAD_LS_T int sp_cache_1024_last = -1;
  70160. /* Cache has been initialized. */
  70161. static THREAD_LS_T int sp_cache_1024_inited = 0;
  70162. #ifndef HAVE_THREAD_LS
  70163. static volatile int initCacheMutex_1024 = 0;
  70164. static wolfSSL_Mutex sp_cache_1024_lock;
  70165. #endif
  70166. /* Get the cache entry for the point.
  70167. *
  70168. * g [in] Point scalar multiplying.
  70169. * cache [out] Cache table to use.
  70170. */
  70171. static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache)
  70172. {
  70173. int i;
  70174. int j;
  70175. uint32_t least;
  70176. if (sp_cache_1024_inited == 0) {
  70177. for (i=0; i<FP_ENTRIES; i++) {
  70178. sp_cache_1024[i].set = 0;
  70179. }
  70180. sp_cache_1024_inited = 1;
  70181. }
  70182. /* Compare point with those in cache. */
  70183. for (i=0; i<FP_ENTRIES; i++) {
  70184. if (!sp_cache_1024[i].set)
  70185. continue;
  70186. if (sp_1024_cmp_equal_32(g->x, sp_cache_1024[i].x) &
  70187. sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) {
  70188. sp_cache_1024[i].cnt++;
  70189. break;
  70190. }
  70191. }
  70192. /* No match. */
  70193. if (i == FP_ENTRIES) {
  70194. /* Find empty entry. */
  70195. i = (sp_cache_1024_last + 1) % FP_ENTRIES;
  70196. for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) {
  70197. if (!sp_cache_1024[i].set) {
  70198. break;
  70199. }
  70200. }
  70201. /* Evict least used. */
  70202. if (i == sp_cache_1024_last) {
  70203. least = sp_cache_1024[0].cnt;
  70204. for (j=1; j<FP_ENTRIES; j++) {
  70205. if (sp_cache_1024[j].cnt < least) {
  70206. i = j;
  70207. least = sp_cache_1024[i].cnt;
  70208. }
  70209. }
  70210. }
  70211. XMEMCPY(sp_cache_1024[i].x, g->x, sizeof(sp_cache_1024[i].x));
  70212. XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y));
  70213. sp_cache_1024[i].set = 1;
  70214. sp_cache_1024[i].cnt = 1;
  70215. }
  70216. *cache = &sp_cache_1024[i];
  70217. sp_cache_1024_last = i;
  70218. }
  70219. #endif /* FP_ECC */
  70220. /* Multiply the base point of P1024 by the scalar and return the result.
  70221. * If map is true then convert result to affine coordinates.
  70222. *
  70223. * r Resulting point.
  70224. * g Point to multiply.
  70225. * k Scalar to multiply by.
  70226. * map Indicates whether to convert result to affine.
  70227. * ct Constant time required.
  70228. * heap Heap to use for allocation.
  70229. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  70230. */
  70231. static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g,
  70232. const sp_digit* k, int map, int ct, void* heap)
  70233. {
  70234. #ifndef FP_ECC
  70235. return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap);
  70236. #else
  70237. #ifdef WOLFSSL_SP_SMALL_STACK
  70238. sp_digit* tmp;
  70239. #else
  70240. sp_digit tmp[2 * 32 * 38];
  70241. #endif
  70242. sp_cache_1024_t* cache;
  70243. int err = MP_OKAY;
  70244. #ifdef WOLFSSL_SP_SMALL_STACK
  70245. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 38, heap, DYNAMIC_TYPE_ECC);
  70246. if (tmp == NULL) {
  70247. err = MEMORY_E;
  70248. }
  70249. #endif
  70250. #ifndef HAVE_THREAD_LS
  70251. if (err == MP_OKAY) {
  70252. if (initCacheMutex_1024 == 0) {
  70253. wc_InitMutex(&sp_cache_1024_lock);
  70254. initCacheMutex_1024 = 1;
  70255. }
  70256. if (wc_LockMutex(&sp_cache_1024_lock) != 0) {
  70257. err = BAD_MUTEX_E;
  70258. }
  70259. }
  70260. #endif /* HAVE_THREAD_LS */
  70261. if (err == MP_OKAY) {
  70262. sp_ecc_get_cache_1024(g, &cache);
  70263. if (cache->cnt == 2)
  70264. sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap);
  70265. #ifndef HAVE_THREAD_LS
  70266. wc_UnLockMutex(&sp_cache_1024_lock);
  70267. #endif /* HAVE_THREAD_LS */
  70268. if (cache->cnt < 2) {
  70269. err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap);
  70270. }
  70271. else {
  70272. err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k,
  70273. map, ct, heap);
  70274. }
  70275. }
  70276. #ifdef WOLFSSL_SP_SMALL_STACK
  70277. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  70278. #endif
  70279. return err;
  70280. #endif
  70281. }
  70282. #else
  70283. #if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
  70284. /* Generate the pre-computed table of points for the base point.
  70285. *
  70286. * width = 8
  70287. * 256 entries
  70288. * 128 bits between
  70289. *
  70290. * a The base point.
  70291. * table Place to store generated point data.
  70292. * tmp Temporary data.
  70293. * heap Heap to use for allocation.
  70294. */
  70295. static int sp_1024_gen_stripe_table_32(const sp_point_1024* a,
  70296. sp_table_entry_1024* table, sp_digit* tmp, void* heap)
  70297. {
  70298. #ifdef WOLFSSL_SP_SMALL_STACK
  70299. sp_point_1024* t = NULL;
  70300. #else
  70301. sp_point_1024 t[3];
  70302. #endif
  70303. sp_point_1024* s1 = NULL;
  70304. sp_point_1024* s2 = NULL;
  70305. int i;
  70306. int j;
  70307. int err = MP_OKAY;
  70308. (void)heap;
  70309. #ifdef WOLFSSL_SP_SMALL_STACK
  70310. t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap,
  70311. DYNAMIC_TYPE_ECC);
  70312. if (t == NULL)
  70313. err = MEMORY_E;
  70314. #endif
  70315. if (err == MP_OKAY) {
  70316. s1 = t + 1;
  70317. s2 = t + 2;
  70318. err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod);
  70319. }
  70320. if (err == MP_OKAY) {
  70321. err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod);
  70322. }
  70323. if (err == MP_OKAY) {
  70324. err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod);
  70325. }
  70326. if (err == MP_OKAY) {
  70327. t->infinity = 0;
  70328. sp_1024_proj_to_affine_32(t, tmp);
  70329. XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70330. s1->infinity = 0;
  70331. XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70332. s2->infinity = 0;
  70333. /* table[0] = {0, 0, infinity} */
  70334. XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024));
  70335. /* table[1] = Affine version of 'a' in Montgomery form */
  70336. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  70337. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  70338. for (i=1; i<8; i++) {
  70339. sp_1024_proj_point_dbl_n_32(t, 128, tmp);
  70340. sp_1024_proj_to_affine_32(t, tmp);
  70341. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  70342. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  70343. }
  70344. for (i=1; i<8; i++) {
  70345. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  70346. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  70347. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  70348. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  70349. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  70350. sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp);
  70351. sp_1024_proj_to_affine_32(t, tmp);
  70352. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  70353. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  70354. }
  70355. }
  70356. }
  70357. #ifdef WOLFSSL_SP_SMALL_STACK
  70358. if (t != NULL)
  70359. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  70360. #endif
  70361. return err;
  70362. }
  70363. #endif /* FP_ECC || !WOLFSSL_SP_SMALL */
  70364. /* Multiply the point by the scalar and return the result.
  70365. * If map is true then convert result to affine coordinates.
  70366. *
  70367. * Stripe implementation.
  70368. * Pre-generated: 2^0, 2^128, ...
  70369. * Pre-generated: products of all combinations of above.
  70370. * 8 doubles and adds (with qz=1)
  70371. *
  70372. * r Resulting point.
  70373. * k Scalar to multiply by.
  70374. * table Pre-computed table.
  70375. * map Indicates whether to convert result to affine.
  70376. * ct Constant time required.
  70377. * heap Heap to use for allocation.
  70378. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  70379. */
  70380. static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g,
  70381. const sp_table_entry_1024* table, const sp_digit* k, int map,
  70382. int ct, void* heap)
  70383. {
  70384. #ifdef WOLFSSL_SP_SMALL_STACK
  70385. sp_point_1024* rt = NULL;
  70386. sp_digit* t = NULL;
  70387. #else
  70388. sp_point_1024 rt[2];
  70389. sp_digit t[2 * 32 * 37];
  70390. #endif
  70391. sp_point_1024* p = NULL;
  70392. int i;
  70393. int j;
  70394. int y;
  70395. int x;
  70396. int err = MP_OKAY;
  70397. (void)g;
  70398. /* Constant time used for cache attack resistance implementation. */
  70399. (void)ct;
  70400. (void)heap;
  70401. #ifdef WOLFSSL_SP_SMALL_STACK
  70402. rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
  70403. DYNAMIC_TYPE_ECC);
  70404. if (rt == NULL)
  70405. err = MEMORY_E;
  70406. if (err == MP_OKAY) {
  70407. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 37, heap,
  70408. DYNAMIC_TYPE_ECC);
  70409. if (t == NULL)
  70410. err = MEMORY_E;
  70411. }
  70412. #endif
  70413. if (err == MP_OKAY) {
  70414. p = rt + 1;
  70415. XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70416. XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  70417. y = 0;
  70418. x = 127;
  70419. for (j=0; j<8; j++) {
  70420. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  70421. x += 128;
  70422. }
  70423. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  70424. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  70425. rt->infinity = !y;
  70426. for (i=126; i>=0; i--) {
  70427. y = 0;
  70428. x = i;
  70429. for (j=0; j<8; j++) {
  70430. y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j);
  70431. x += 128;
  70432. }
  70433. sp_1024_proj_point_dbl_32(rt, rt, t);
  70434. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  70435. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  70436. p->infinity = !y;
  70437. sp_1024_proj_point_add_qz1_32(rt, rt, p, t);
  70438. }
  70439. if (map != 0) {
  70440. sp_1024_map_32(r, rt, t);
  70441. }
  70442. else {
  70443. XMEMCPY(r, rt, sizeof(sp_point_1024));
  70444. }
  70445. }
  70446. #ifdef WOLFSSL_SP_SMALL_STACK
  70447. if (t != NULL)
  70448. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  70449. if (rt != NULL)
  70450. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  70451. #endif
  70452. return err;
  70453. }
  70454. #ifdef FP_ECC
  70455. #ifndef FP_ENTRIES
  70456. #define FP_ENTRIES 16
  70457. #endif
  70458. /* Cache entry - holds precomputation tables for a point. */
  70459. typedef struct sp_cache_1024_t {
  70460. /* X ordinate of point that table was generated from. */
  70461. sp_digit x[32];
  70462. /* Y ordinate of point that table was generated from. */
  70463. sp_digit y[32];
  70464. /* Precomputation table for point. */
  70465. sp_table_entry_1024 table[256];
  70466. /* Count of entries in table. */
  70467. uint32_t cnt;
  70468. /* Point and table set in entry. */
  70469. int set;
  70470. } sp_cache_1024_t;
  70471. /* Cache of tables. */
  70472. static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES];
  70473. /* Index of last entry in cache. */
  70474. static THREAD_LS_T int sp_cache_1024_last = -1;
  70475. /* Cache has been initialized. */
  70476. static THREAD_LS_T int sp_cache_1024_inited = 0;
  70477. #ifndef HAVE_THREAD_LS
  70478. static volatile int initCacheMutex_1024 = 0;
  70479. static wolfSSL_Mutex sp_cache_1024_lock;
  70480. #endif
  70481. /* Get the cache entry for the point.
  70482. *
  70483. * g [in] Point scalar multiplying.
  70484. * cache [out] Cache table to use.
  70485. */
  70486. static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache)
  70487. {
  70488. int i;
  70489. int j;
  70490. uint32_t least;
  70491. if (sp_cache_1024_inited == 0) {
  70492. for (i=0; i<FP_ENTRIES; i++) {
  70493. sp_cache_1024[i].set = 0;
  70494. }
  70495. sp_cache_1024_inited = 1;
  70496. }
  70497. /* Compare point with those in cache. */
  70498. for (i=0; i<FP_ENTRIES; i++) {
  70499. if (!sp_cache_1024[i].set)
  70500. continue;
  70501. if (sp_1024_cmp_equal_32(g->x, sp_cache_1024[i].x) &
  70502. sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) {
  70503. sp_cache_1024[i].cnt++;
  70504. break;
  70505. }
  70506. }
  70507. /* No match. */
  70508. if (i == FP_ENTRIES) {
  70509. /* Find empty entry. */
  70510. i = (sp_cache_1024_last + 1) % FP_ENTRIES;
  70511. for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) {
  70512. if (!sp_cache_1024[i].set) {
  70513. break;
  70514. }
  70515. }
  70516. /* Evict least used. */
  70517. if (i == sp_cache_1024_last) {
  70518. least = sp_cache_1024[0].cnt;
  70519. for (j=1; j<FP_ENTRIES; j++) {
  70520. if (sp_cache_1024[j].cnt < least) {
  70521. i = j;
  70522. least = sp_cache_1024[i].cnt;
  70523. }
  70524. }
  70525. }
  70526. XMEMCPY(sp_cache_1024[i].x, g->x, sizeof(sp_cache_1024[i].x));
  70527. XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y));
  70528. sp_cache_1024[i].set = 1;
  70529. sp_cache_1024[i].cnt = 1;
  70530. }
  70531. *cache = &sp_cache_1024[i];
  70532. sp_cache_1024_last = i;
  70533. }
  70534. #endif /* FP_ECC */
  70535. /* Multiply the base point of P1024 by the scalar and return the result.
  70536. * If map is true then convert result to affine coordinates.
  70537. *
  70538. * r Resulting point.
  70539. * g Point to multiply.
  70540. * k Scalar to multiply by.
  70541. * map Indicates whether to convert result to affine.
  70542. * ct Constant time required.
  70543. * heap Heap to use for allocation.
  70544. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  70545. */
  70546. static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g,
  70547. const sp_digit* k, int map, int ct, void* heap)
  70548. {
  70549. #ifndef FP_ECC
  70550. return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap);
  70551. #else
  70552. #ifdef WOLFSSL_SP_SMALL_STACK
  70553. sp_digit* tmp;
  70554. #else
  70555. sp_digit tmp[2 * 32 * 38];
  70556. #endif
  70557. sp_cache_1024_t* cache;
  70558. int err = MP_OKAY;
  70559. #ifdef WOLFSSL_SP_SMALL_STACK
  70560. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 38, heap, DYNAMIC_TYPE_ECC);
  70561. if (tmp == NULL) {
  70562. err = MEMORY_E;
  70563. }
  70564. #endif
  70565. #ifndef HAVE_THREAD_LS
  70566. if (err == MP_OKAY) {
  70567. if (initCacheMutex_1024 == 0) {
  70568. wc_InitMutex(&sp_cache_1024_lock);
  70569. initCacheMutex_1024 = 1;
  70570. }
  70571. if (wc_LockMutex(&sp_cache_1024_lock) != 0) {
  70572. err = BAD_MUTEX_E;
  70573. }
  70574. }
  70575. #endif /* HAVE_THREAD_LS */
  70576. if (err == MP_OKAY) {
  70577. sp_ecc_get_cache_1024(g, &cache);
  70578. if (cache->cnt == 2)
  70579. sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap);
  70580. #ifndef HAVE_THREAD_LS
  70581. wc_UnLockMutex(&sp_cache_1024_lock);
  70582. #endif /* HAVE_THREAD_LS */
  70583. if (cache->cnt < 2) {
  70584. err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap);
  70585. }
  70586. else {
  70587. err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k,
  70588. map, ct, heap);
  70589. }
  70590. }
  70591. #ifdef WOLFSSL_SP_SMALL_STACK
  70592. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  70593. #endif
  70594. return err;
  70595. #endif
  70596. }
  70597. #endif /* WOLFSSL_SP_SMALL */
  70598. /* Multiply the point by the scalar and return the result.
  70599. * If map is true then convert result to affine coordinates.
  70600. *
  70601. * km Scalar to multiply by.
  70602. * p Point to multiply.
  70603. * r Resulting point.
  70604. * map Indicates whether to convert result to affine.
  70605. * heap Heap to use for allocation.
  70606. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  70607. */
  70608. int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r,
  70609. int map, void* heap)
  70610. {
  70611. #ifdef WOLFSSL_SP_SMALL_STACK
  70612. sp_point_1024* point = NULL;
  70613. sp_digit* k = NULL;
  70614. #else
  70615. sp_point_1024 point[1];
  70616. sp_digit k[32];
  70617. #endif
  70618. int err = MP_OKAY;
  70619. #ifdef WOLFSSL_SP_SMALL_STACK
  70620. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  70621. DYNAMIC_TYPE_ECC);
  70622. if (point == NULL)
  70623. err = MEMORY_E;
  70624. if (err == MP_OKAY) {
  70625. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap,
  70626. DYNAMIC_TYPE_ECC);
  70627. if (k == NULL)
  70628. err = MEMORY_E;
  70629. }
  70630. #endif
  70631. if (err == MP_OKAY) {
  70632. sp_1024_from_mp(k, 32, km);
  70633. sp_1024_point_from_ecc_point_32(point, gm);
  70634. err = sp_1024_ecc_mulmod_32(point, point, k, map, 1, heap);
  70635. }
  70636. if (err == MP_OKAY) {
  70637. err = sp_1024_point_to_ecc_point_32(point, r);
  70638. }
  70639. #ifdef WOLFSSL_SP_SMALL_STACK
  70640. if (k != NULL)
  70641. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  70642. if (point != NULL)
  70643. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  70644. #endif
  70645. return err;
  70646. }
  70647. #ifdef WOLFSSL_SP_SMALL
  70648. /* Striping precomputation table.
  70649. * 4 points combined into a table of 16 points.
  70650. * Distance of 256 between points.
  70651. */
  70652. static const sp_table_entry_1024 p1024_table[16] = {
  70653. /* 0 */
  70654. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70655. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70656. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  70657. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70658. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70659. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  70660. /* 1 */
  70661. { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0,
  70662. 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995,
  70663. 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867,
  70664. 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173,
  70665. 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc,
  70666. 0x1c49f80b,0x8dfff96a },
  70667. { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88,
  70668. 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16,
  70669. 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e,
  70670. 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf,
  70671. 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329,
  70672. 0xde3c01f3,0x2aa1207b } },
  70673. /* 2 */
  70674. { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f,
  70675. 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab,
  70676. 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa,
  70677. 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9,
  70678. 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec,
  70679. 0xdf9398a4,0x40247985 },
  70680. { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb,
  70681. 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861,
  70682. 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36,
  70683. 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd,
  70684. 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb,
  70685. 0xc8b79d80,0x1a6fd1e6 } },
  70686. /* 3 */
  70687. { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452,
  70688. 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e,
  70689. 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d,
  70690. 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37,
  70691. 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4,
  70692. 0x15614750,0x29b7d4dc },
  70693. { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54,
  70694. 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7,
  70695. 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a,
  70696. 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903,
  70697. 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310,
  70698. 0x5382497e,0x5d092802 } },
  70699. /* 4 */
  70700. { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6,
  70701. 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd,
  70702. 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd,
  70703. 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521,
  70704. 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494,
  70705. 0x0f1fa7d7,0x2ab3bd47 },
  70706. { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135,
  70707. 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2,
  70708. 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f,
  70709. 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c,
  70710. 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1,
  70711. 0x4c27d229,0x93a4b416 } },
  70712. /* 5 */
  70713. { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1,
  70714. 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519,
  70715. 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e,
  70716. 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30,
  70717. 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6,
  70718. 0x32ee7763,0x342ce0d7 },
  70719. { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a,
  70720. 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858,
  70721. 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66,
  70722. 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433,
  70723. 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb,
  70724. 0xe156fd20,0x455f4af3 } },
  70725. /* 6 */
  70726. { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9,
  70727. 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee,
  70728. 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d,
  70729. 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8,
  70730. 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead,
  70731. 0x5c37c334,0x65713c29 },
  70732. { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6,
  70733. 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424,
  70734. 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862,
  70735. 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1,
  70736. 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5,
  70737. 0x3bae3c38,0x6b0e996c } },
  70738. /* 7 */
  70739. { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269,
  70740. 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7,
  70741. 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da,
  70742. 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e,
  70743. 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342,
  70744. 0x678223f8,0x4022a205 },
  70745. { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d,
  70746. 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6,
  70747. 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd,
  70748. 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21,
  70749. 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11,
  70750. 0x24a6a956,0x312179cb } },
  70751. /* 8 */
  70752. { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41,
  70753. 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7,
  70754. 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b,
  70755. 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5,
  70756. 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1,
  70757. 0x04ecf056,0x325d2796 },
  70758. { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1,
  70759. 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153,
  70760. 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c,
  70761. 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9,
  70762. 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e,
  70763. 0xe32a79d3,0x19d48546 } },
  70764. /* 9 */
  70765. { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0,
  70766. 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea,
  70767. 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df,
  70768. 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634,
  70769. 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d,
  70770. 0xb4e453b0,0x1b3ace6c },
  70771. { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35,
  70772. 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630,
  70773. 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824,
  70774. 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387,
  70775. 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64,
  70776. 0x192f0a14,0x538ec33e } },
  70777. /* 10 */
  70778. { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8,
  70779. 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699,
  70780. 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984,
  70781. 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32,
  70782. 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076,
  70783. 0xb6f8aa25,0x13cbee76 },
  70784. { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23,
  70785. 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492,
  70786. 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e,
  70787. 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50,
  70788. 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c,
  70789. 0xe02e8967,0x4e0a1ada } },
  70790. /* 11 */
  70791. { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67,
  70792. 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198,
  70793. 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7,
  70794. 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d,
  70795. 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6,
  70796. 0x9f99c999,0x733e30d9 },
  70797. { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7,
  70798. 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a,
  70799. 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a,
  70800. 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0,
  70801. 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492,
  70802. 0xb79a5c0c,0x56facb39 } },
  70803. /* 12 */
  70804. { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6,
  70805. 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c,
  70806. 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e,
  70807. 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb,
  70808. 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52,
  70809. 0xf18c2b91,0x57ea2b4b },
  70810. { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a,
  70811. 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee,
  70812. 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069,
  70813. 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b,
  70814. 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927,
  70815. 0xea7935c9,0x60480b46 } },
  70816. /* 13 */
  70817. { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7,
  70818. 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117,
  70819. 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5,
  70820. 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0,
  70821. 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb,
  70822. 0x9a8f88cc,0x0774a0d3 },
  70823. { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f,
  70824. 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61,
  70825. 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91,
  70826. 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df,
  70827. 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303,
  70828. 0x2432014b,0x08151954 } },
  70829. /* 14 */
  70830. { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28,
  70831. 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20,
  70832. 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1,
  70833. 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55,
  70834. 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7,
  70835. 0xf0860497,0x1fe09f94 },
  70836. { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c,
  70837. 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a,
  70838. 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994,
  70839. 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa,
  70840. 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c,
  70841. 0xdb62526a,0x4de95786 } },
  70842. /* 15 */
  70843. { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96,
  70844. 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5,
  70845. 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5,
  70846. 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc,
  70847. 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e,
  70848. 0xe636980c,0x1c94418b },
  70849. { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a,
  70850. 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4,
  70851. 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98,
  70852. 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474,
  70853. 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422,
  70854. 0xb55235ba,0x611bfbb2 } },
  70855. };
  70856. /* Multiply the base point of P1024 by the scalar and return the result.
  70857. * If map is true then convert result to affine coordinates.
  70858. *
  70859. * Stripe implementation.
  70860. * Pre-generated: 2^0, 2^256, ...
  70861. * Pre-generated: products of all combinations of above.
  70862. * 4 doubles and adds (with qz=1)
  70863. *
  70864. * r Resulting point.
  70865. * k Scalar to multiply by.
  70866. * map Indicates whether to convert result to affine.
  70867. * ct Constant time required.
  70868. * heap Heap to use for allocation.
  70869. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  70870. */
  70871. static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k,
  70872. int map, int ct, void* heap)
  70873. {
  70874. return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table,
  70875. k, map, ct, heap);
  70876. }
  70877. #else
  70878. /* Striping precomputation table.
  70879. * 8 points combined into a table of 256 points.
  70880. * Distance of 128 between points.
  70881. */
  70882. static const sp_table_entry_1024 p1024_table[256] = {
  70883. /* 0 */
  70884. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70885. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70886. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  70887. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70888. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70889. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  70890. /* 1 */
  70891. { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0,
  70892. 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995,
  70893. 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867,
  70894. 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173,
  70895. 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc,
  70896. 0x1c49f80b,0x8dfff96a },
  70897. { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88,
  70898. 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16,
  70899. 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e,
  70900. 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf,
  70901. 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329,
  70902. 0xde3c01f3,0x2aa1207b } },
  70903. /* 2 */
  70904. { { 0x01900955,0xa95b6dae,0xceb4656d,0xa5dc9cc1,0xe72fe95b,0x50c78907,
  70905. 0xa040c334,0xa1ae5447,0x7952ea6e,0x91191370,0x6d097305,0x54ff7343,
  70906. 0xbda4d10f,0xa4db0074,0x91644070,0xfd5306f1,0x8b24522c,0x14b9fe73,
  70907. 0x7849f762,0x1468dad6,0xb0dcd2e4,0x87b29a18,0x5e1ad492,0xadd7f1a1,
  70908. 0xdbba2a1a,0x9ac63a81,0x81223379,0x01379c5b,0xb0e53bc8,0xf402b2f0,
  70909. 0x0bf13b61,0x8c3eb27f },
  70910. { 0xe513696f,0x9a4ad3e1,0x18c81ffa,0x0350ba5c,0x3c033d13,0x1e2fc136,
  70911. 0x17a531bc,0x53da6e71,0x1aed610d,0x42ec6490,0xe99ff567,0xd33e8df7,
  70912. 0x3deed12a,0xe4aad73e,0x180f4deb,0xd983b465,0x502f30b4,0x99365269,
  70913. 0xa8918d7f,0x7e2799ab,0x700fc79a,0x0ffe84b6,0x40bfd8c2,0x7b4400d6,
  70914. 0x5d2641bd,0xc3a21d21,0xc32621cb,0x79839442,0xb1401e83,0xace6500b,
  70915. 0x251c4310,0x7bf4163e } },
  70916. /* 3 */
  70917. { { 0xe3fd589e,0x1c174f88,0xdf974a03,0xdb501790,0x3e70549f,0xd09623e3,
  70918. 0x15924f34,0x8d091eff,0xf9b65ac5,0xeef79cad,0x3f69c2cf,0xd2cc4262,
  70919. 0x52cd82bc,0x817d9032,0xa5f1dddd,0xacf4f4d9,0x5011b6bd,0xd0612635,
  70920. 0x2ed140c9,0x9f74490d,0x4db686d2,0x64092e8c,0x776b0fcc,0x225eef16,
  70921. 0xdf16aeb6,0x0e8c01e9,0x84bbd82a,0x62836741,0x8956e337,0x757574e2,
  70922. 0x705a7f07,0x9871edc6 },
  70923. { 0x776535f7,0xbd0b76d5,0x2635b3b8,0x5214d602,0x9d216f64,0xc0c25ad9,
  70924. 0x5515bf75,0xfd4df3a7,0x5e9f1675,0x24a625bc,0x406873e7,0x3c35efb7,
  70925. 0xbb2e5c4a,0xef5c9a33,0x806b198a,0xa971b35e,0xa3c690ed,0x9f5c0ca5,
  70926. 0x8e1e2341,0xa8d5dd89,0x955ad9e4,0x4cecbcce,0x248d3416,0x2ecf4407,
  70927. 0x45c0af6e,0x1abb3811,0x1c780fff,0x3f4bee82,0xc272ed57,0xd14df768,
  70928. 0x371637ad,0x397ed10a } },
  70929. /* 4 */
  70930. { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f,
  70931. 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab,
  70932. 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa,
  70933. 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9,
  70934. 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec,
  70935. 0xdf9398a4,0x40247985 },
  70936. { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb,
  70937. 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861,
  70938. 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36,
  70939. 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd,
  70940. 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb,
  70941. 0xc8b79d80,0x1a6fd1e6 } },
  70942. /* 5 */
  70943. { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452,
  70944. 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e,
  70945. 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d,
  70946. 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37,
  70947. 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4,
  70948. 0x15614750,0x29b7d4dc },
  70949. { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54,
  70950. 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7,
  70951. 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a,
  70952. 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903,
  70953. 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310,
  70954. 0x5382497e,0x5d092802 } },
  70955. /* 6 */
  70956. { { 0xff2f780d,0x583a2b7e,0xd7d76b1d,0x34d26820,0x86f74aec,0xe3c32847,
  70957. 0x10823feb,0x0fd42212,0xfb5e7bf4,0x227e417e,0xa568f8cd,0x510d49b6,
  70958. 0x1781bbec,0x53bce7d6,0x2f3718b7,0x9cfe3f22,0xd9de6c1f,0x7f44e89f,
  70959. 0x3fac9b55,0xf1cc553f,0xe6f300bc,0x9d2d0846,0x9f0ae6b1,0x976c82a2,
  70960. 0x24b8bbe0,0xe63dbf5e,0x973a5aa7,0x4cac7f45,0x84dd33c7,0xc6eb6237,
  70961. 0x142fee5d,0x0a26e434 },
  70962. { 0xacaa9a08,0x8081339f,0x5246ece1,0x40f31105,0x61393747,0x892c8170,
  70963. 0x242f02e1,0x8d8d4103,0x3b5de98a,0x482bfd20,0x5abbe952,0x89ef946b,
  70964. 0x37698249,0xb8d218b9,0x66617c7a,0xd5268e89,0x8b7d2b91,0x962e7551,
  70965. 0xfe8d67c3,0x2c5c7973,0x2b017c51,0x42e3150a,0xc1a29469,0x6f4e5ebc,
  70966. 0x531c7083,0xa39910ce,0xb77b9e50,0xaf4f6eb4,0xda120ad0,0x68cbb175,
  70967. 0xb92636ec,0x19497c61 } },
  70968. /* 7 */
  70969. { { 0x417659a8,0x6920b0c6,0x92cb28ff,0xc77ab9c7,0xb687797f,0x55b67180,
  70970. 0xe7759363,0x4caf58c1,0x5561b186,0x5155bdb6,0x780f4946,0x2e64e355,
  70971. 0x229a8b20,0xeb0ac9b7,0x2571bd60,0x88594d78,0xe3fa78f9,0x5dcc0939,
  70972. 0x2ac2d379,0x7b8b4830,0xb90f1444,0x505fbf60,0x3ce4b3c1,0xac610e81,
  70973. 0xd59b5c18,0x39a4f27a,0x7cea0222,0x5fa33973,0x8dff1c7b,0xe578730b,
  70974. 0x517bf7a6,0x96b91b8b },
  70975. { 0x9aac087c,0xc1a991f4,0x6cfdb28d,0xce62f74e,0x5f7600d6,0x08d6ff9a,
  70976. 0xf917f9c9,0xd781cd04,0x3de52dbf,0x7796f5f6,0x2ed72180,0xe7db64e0,
  70977. 0x6fa4137d,0x0f0876f6,0x3ca1f716,0x3271ee64,0x7c4ab8a3,0xcb9b2058,
  70978. 0x39481047,0xcba17107,0x598c5c37,0xdf9a190d,0x6f20e125,0x0cb6e72a,
  70979. 0xf4f2902d,0xa3142204,0x7ce2dcfb,0x42d28cb9,0xa3d3c351,0xdf261b8a,
  70980. 0xcffc249d,0x73f3d315 } },
  70981. /* 8 */
  70982. { { 0xe6fd3673,0x5d86855b,0x9d214b7b,0x309b70af,0xdcc46cd3,0x8d332f90,
  70983. 0x595510de,0xe553c015,0x38c1251c,0x5746a096,0x85cc1bc9,0xcd7cea5b,
  70984. 0x002eba8f,0x4ffa1468,0x22fcd77c,0x10a3cb70,0xc4ea05e3,0xb6999dfb,
  70985. 0x4efa756e,0x3375a0d0,0xdced5fd8,0x4d90279e,0x251fd56e,0x48192403,
  70986. 0x82a4c5f1,0xe87633a4,0x1b34105b,0x3170d130,0x7247e578,0x93998b0f,
  70987. 0x436ba1fa,0x88934f64 },
  70988. { 0x4713eabc,0xf09f43b0,0xaccdc517,0x4ca7dd91,0xef13ca7c,0x27daa63b,
  70989. 0x2588184b,0x8b2e5a7a,0xd95dc269,0x0a8cb612,0xe1f2f14c,0x346975a2,
  70990. 0xe172935c,0x1f29b8ed,0xd40bc1e3,0xc3cbfd6e,0x132623da,0xd3f46b3f,
  70991. 0xfb0b7681,0xc115be6d,0x56da4344,0x5e31c345,0xa8e43d98,0xa7c63f18,
  70992. 0x4bddb4ea,0x55cb2083,0x4a54f58c,0xb16a0c38,0x46fd69d9,0x74eacca2,
  70993. 0x153548e1,0x0d1898bb } },
  70994. /* 9 */
  70995. { { 0xe35ef043,0x4ea73461,0x3496b564,0x107b67d9,0xd0f83a3c,0xd62c173b,
  70996. 0x51d29c35,0xfad4b038,0x71b1c1a4,0x3f42882a,0x54b43b9e,0x5d2bcf66,
  70997. 0x2abdf543,0xc77b15aa,0xdabe3dc1,0x5cb38a80,0xa481673b,0x15fda0ae,
  70998. 0xe7b90ebe,0x86996b4d,0x2bc8f3d8,0x84f87e25,0x37c4e424,0xaded03d6,
  70999. 0xd7a7afd8,0xe5ede666,0xa1ccb93a,0x80dd95a2,0x46fba391,0xa55cfd25,
  71000. 0x46f82e60,0x2bdab1dc },
  71001. { 0xfa6fed61,0x7a4de22b,0xcc8dd94e,0xca458aa5,0x071222f5,0x3e372df1,
  71002. 0xe5aff377,0x06a4b44f,0x4a738e6d,0xbc2d0ba7,0x5f31f136,0x1a470e1d,
  71003. 0xe102a911,0x77ff933a,0x310c7885,0x8b380a50,0x783fc5ac,0x9f3c0228,
  71004. 0x44725d06,0xec668925,0x5ac84221,0x878f0e16,0xcfda6e8a,0x9a3af1af,
  71005. 0x78cd2aba,0x0183ed37,0x826d0eae,0x32cdbd60,0xcbee6415,0xb3234661,
  71006. 0xb9c10120,0x353eb892 } },
  71007. /* 10 */
  71008. { { 0x10b5521e,0xc8fdcad6,0x52e702f0,0x1a11b440,0x8ffda49c,0x6302680d,
  71009. 0xcbf36bad,0xcdb9654a,0x4c10a2d7,0x7b58ce11,0xe630e7e0,0x1e5d1f7d,
  71010. 0x6760a813,0x8cbe3d7d,0x6480d77f,0xeb35866b,0x7f036219,0x58728cf3,
  71011. 0x42a8a757,0xdd5865ed,0x906a2870,0x283f1f1d,0xa51f906b,0x79e23fa4,
  71012. 0x543b20a8,0xf2ac6e83,0xb81e7754,0x4f0b6379,0x840016ee,0x57fbc0d4,
  71013. 0xe621b67d,0x8da20771 },
  71014. { 0xecce65ec,0x3c855004,0xb748185e,0x76d10d1f,0x78797ad2,0x64be7bca,
  71015. 0x77e54aad,0x43444db0,0xbe0df0ff,0x17b6b0c9,0x055086a4,0x8fc4256c,
  71016. 0xfd74d5a3,0xf952c43b,0x01c4edb8,0x501e005a,0x4a57e328,0xd5172dfc,
  71017. 0x535d6ee3,0xdb40ce4e,0x0c650918,0xbaef1e5c,0x857561fc,0xe85145e7,
  71018. 0x34a224c6,0xe468536a,0x0ec0e0a2,0x69a8e227,0x242b03fc,0xb3f52247,
  71019. 0xc3bebd5f,0x862f55e2 } },
  71020. /* 11 */
  71021. { { 0x226049fe,0x2d6a390f,0xdcbbc9fb,0xcc92a578,0x97634fb7,0xa52feca4,
  71022. 0x3dea5893,0x2b340cb6,0x2a49e916,0xa39f338a,0x949e41f3,0x26b2df3d,
  71023. 0x065a7e40,0xc71c7cdb,0x468281a2,0x4a9b84a0,0x731eeeca,0x63eeb503,
  71024. 0x76cbb725,0xe6d09134,0xb94a678c,0x0cf979a9,0x808fd9f1,0xb44d8c3b,
  71025. 0xe0afc5b9,0xe60da613,0x3ea5be69,0x52dce7de,0xdc1ee74f,0x3a5d6864,
  71026. 0x3bc80790,0x71ab2891 },
  71027. { 0x3b5b60ad,0xcf618fc4,0x4a0c3184,0x0afb5e30,0xbc403302,0xd22381cc,
  71028. 0xdb1c0c66,0x33cf8953,0xa6112a8d,0x9c994e4d,0xd1967a86,0xd7aae2c3,
  71029. 0x5b7acd29,0xc28d5493,0x6c9a57fb,0x8075bd13,0x9c8427f9,0xc9c0373e,
  71030. 0x193225f5,0x2cbca18d,0x442c018c,0x73777d13,0xfbb3a727,0xebe5ed47,
  71031. 0x1962dc18,0x70437d49,0x2dc08806,0xf39c1e09,0x15fff35c,0x03e9c6f7,
  71032. 0x5e360a65,0x8d087bb6 } },
  71033. /* 12 */
  71034. { { 0x3fdc1844,0xbe212302,0x105eac56,0x6eca27ef,0xf168a348,0x2183a606,
  71035. 0xe1d7a4cb,0x295f807d,0x7ef5d43e,0x7246a632,0xc77025c7,0xae143205,
  71036. 0xf3484e3e,0x4bdfc7ca,0xdf52c075,0xec939895,0xd7a9cac0,0x82e655f6,
  71037. 0x8baeddb0,0x985dfe20,0x527de731,0x79c817e4,0x313de1ea,0x30ce0fbc,
  71038. 0xcc4f6cbb,0x9df95b89,0xf5bb20cd,0xf2aedf1e,0x1a8cfb01,0xfc1e0a89,
  71039. 0x63edb7ec,0x225ed34a },
  71040. { 0xbabb1a85,0x3e13154d,0x1e6a565a,0xd3d8dae7,0xab4b100f,0xd3217d56,
  71041. 0xebc78e1a,0xd44d934e,0x48e73d37,0x0215321b,0x201e43cb,0xbbc90bfa,
  71042. 0x27500905,0x3c23f1d0,0xc86691a1,0x2a2e5000,0x6065841c,0x08b2bad2,
  71043. 0x30026b60,0x15d41caf,0x5276ce61,0x1712c2f4,0x15932ffb,0x01c4c3e7,
  71044. 0x6a74caf2,0x7894e13d,0x0c0537a4,0x02d6f5df,0xc2b1c97e,0xa8fb7602,
  71045. 0xd0887c7b,0x612b60e5 } },
  71046. /* 13 */
  71047. { { 0xba245d6b,0xefd495cf,0xa2ce3ff6,0x5cf0cbb7,0xdff5feee,0x24da2ac0,
  71048. 0xcf28c6a3,0x90c914f8,0x4308a56b,0x72fdb50d,0x13d72034,0x03dbf779,
  71049. 0x822ac9e9,0xcfa5ec91,0x3aea3e81,0x0dde73c8,0x66289139,0x545ba962,
  71050. 0xca6acbd3,0xa52f648b,0x98a0683a,0xff6f276e,0xa378ed52,0x2536d3ac,
  71051. 0x885ac1d9,0x353c2c54,0x00bc84a7,0xcaff52da,0x37684167,0x3971f81c,
  71052. 0xd2d7986e,0x0f7334e1 },
  71053. { 0x6596067e,0xafbb5c83,0x38c19806,0x33e54e19,0x39cb0dcc,0x8285d967,
  71054. 0x424035f9,0x2b53f43d,0xdfef9095,0x38c531f8,0xdb0f571a,0x90fbe8e4,
  71055. 0xa39ca787,0x9a0c1ed2,0x606f2620,0x2fecc1d6,0x72b7cb4a,0x9dc890b1,
  71056. 0xccbb7868,0xc33ca6fb,0xfe73ee49,0xd1b11082,0xfcb66c48,0x590b7d17,
  71057. 0x86e14573,0x9356b0a6,0x053ead85,0x75d682c4,0xc54d30fb,0xb2ae55fa,
  71058. 0xf8aee949,0x67636a72 } },
  71059. /* 14 */
  71060. { { 0xb91d6bea,0x638063bc,0x923ecb96,0xae263a2e,0xc627aca6,0x9d7b0992,
  71061. 0x77af9e7e,0xc6ed001a,0x24aafebb,0x9214accf,0x78055a90,0xa3564b96,
  71062. 0xe027499d,0x00999b1c,0xe46a06a5,0xe413a4e1,0x2e51efe7,0xa05d13f6,
  71063. 0x9ba843be,0x35e87d34,0x3183159e,0x0a633825,0x54601923,0x6023e8ba,
  71064. 0xb7fd1cf2,0x9b107721,0xfdf2fd53,0x46b5542b,0x1c18af38,0xb314f4f8,
  71065. 0x60ac8965,0x086f9876 },
  71066. { 0x8cbb9850,0x76701954,0xa20d2c8c,0x6210b730,0x5335670c,0x4084d057,
  71067. 0x0324baea,0x3ecdc595,0xc76ee9b4,0x607fc5f2,0x440ffa64,0xf393d00f,
  71068. 0x2dc1463c,0xe0111796,0x9c7725e7,0xf00b8251,0x5bd1d186,0x35e60736,
  71069. 0x2cf72aac,0xf3d8554c,0xefa3497d,0xb4dd0fde,0xf646ad11,0xd712268c,
  71070. 0x9f7b8ead,0x07c20afb,0xfc06dfe5,0x630969d4,0x7245549a,0x76b7df1c,
  71071. 0xe61ae810,0x681f9403 } },
  71072. /* 15 */
  71073. { { 0xc9a0623b,0x7cad5163,0x67fab8d4,0xdbf82957,0x81af7c7c,0x2ccab0ec,
  71074. 0xe966d5c2,0x469e38c8,0xf0d4e41c,0x34430d52,0xa52b359c,0x426075a2,
  71075. 0x33bd0127,0x242dd3e3,0x9fed2341,0xcda3f635,0xd7d52ffa,0x4df33730,
  71076. 0x7640c3ef,0x5fff56f0,0x1bbde57c,0x4783c21c,0xeb8bb336,0xd8784a2a,
  71077. 0xead08405,0x1ec7c533,0xf9b62bd4,0x4b7f1423,0x7075d4af,0x5543145c,
  71078. 0xba60590a,0x0c9de94a },
  71079. { 0x95d5682b,0x8ed72735,0x2ec276ed,0x711c4283,0x8b36a0d2,0xd1f4aed5,
  71080. 0x8498a88f,0x62ab40c4,0x4480f451,0x58c8fc62,0xb79cffe2,0x8bc8ca4b,
  71081. 0x701a359d,0x90ab583c,0x3fd5d15d,0xaee31a73,0xc912333c,0x02a5597b,
  71082. 0xb6c3e3c2,0x1019cae4,0x29938088,0xe513042c,0xf47c8199,0x0e00283d,
  71083. 0xf2a00e92,0x90d68e58,0xa775ae3b,0x69e2df41,0x871c30b2,0xb8d2eca5,
  71084. 0xbb1de396,0x733dca0e } },
  71085. /* 16 */
  71086. { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6,
  71087. 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd,
  71088. 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd,
  71089. 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521,
  71090. 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494,
  71091. 0x0f1fa7d7,0x2ab3bd47 },
  71092. { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135,
  71093. 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2,
  71094. 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f,
  71095. 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c,
  71096. 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1,
  71097. 0x4c27d229,0x93a4b416 } },
  71098. /* 17 */
  71099. { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1,
  71100. 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519,
  71101. 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e,
  71102. 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30,
  71103. 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6,
  71104. 0x32ee7763,0x342ce0d7 },
  71105. { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a,
  71106. 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858,
  71107. 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66,
  71108. 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433,
  71109. 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb,
  71110. 0xe156fd20,0x455f4af3 } },
  71111. /* 18 */
  71112. { { 0x754ec21c,0xc057f262,0xe3a1ba38,0x3eacd4c9,0x116c1fe9,0x3a0210d1,
  71113. 0xeacc8ab6,0xe4ea4e94,0xea6f32ca,0x31c00c9a,0x86b975ce,0x5cb6239d,
  71114. 0xa14ea1e9,0x654d5d8c,0x5067fc8b,0x230d31f4,0x6355fecb,0x48bb90cb,
  71115. 0xdc172e8e,0x78f81ece,0xcb006737,0x288380a8,0xe162d012,0x19b02e01,
  71116. 0xc5af145c,0x0e087a06,0xb72dc354,0xf04dc8b7,0x8de3c066,0xf70ef214,
  71117. 0x13009fb7,0x4f148243 },
  71118. { 0x6e2055e2,0x5e004fce,0x86c32067,0x89e247ea,0x5f9daaa2,0x4ebcbd95,
  71119. 0xceb7f63b,0xd15f212f,0x863784a0,0x5ecc5c1f,0x75760251,0x53b3800b,
  71120. 0x8a6a2954,0xeb9301c3,0xa13cdd19,0x0f16ba18,0x887c2d24,0x8313d251,
  71121. 0x9a9413f6,0xf9923585,0xfe3fd7c5,0x423405e6,0x16e0ee05,0x678aeb34,
  71122. 0x3fadaab0,0x1f3be7bb,0x82884471,0x7901fa2c,0x4d662ff6,0xc950db30,
  71123. 0x3c01170b,0x74d5d2d4 } },
  71124. /* 19 */
  71125. { { 0x2b5bfe11,0xa3002dc0,0x52d321e7,0x0733410d,0x9679ba89,0x15920f65,
  71126. 0x685b236e,0x0e248c14,0x346f6040,0x8cfab594,0x40c717f0,0x9f57afb7,
  71127. 0x66044576,0x0dbab28c,0x9cdc3247,0x0fa09968,0xc230ed05,0x41e02ae2,
  71128. 0xe45bef74,0x0d961554,0xce4d7b6f,0x9688a982,0x5e62d22e,0xfadefac7,
  71129. 0xbd2cba28,0xaf1512a6,0xbe7c749f,0x78868e62,0xae9f5a6b,0x88048d81,
  71130. 0xc5857a29,0x6b1a5442 },
  71131. { 0x43242066,0x9f5ab9ad,0x2ccca2ae,0x0afef1b5,0x988edc4e,0xb1b43ec7,
  71132. 0x0341b0d5,0x0d0c00f1,0xb50aab37,0x4d68b8f7,0xf3a64a99,0x9a8e4e6f,
  71133. 0x7f1a684e,0x198338fb,0x351a0f5c,0x8bc0e748,0xdac44515,0x2cacf2cd,
  71134. 0x5e9ff76b,0xc14d3999,0x16393055,0x54a01b3f,0x888d8376,0x6ac3eea5,
  71135. 0x723277b1,0xb84d9a9a,0xe11dbbbf,0x99132691,0xabb67178,0x597717ae,
  71136. 0x8bb14ac8,0x4c213526 } },
  71137. /* 20 */
  71138. { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9,
  71139. 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee,
  71140. 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d,
  71141. 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8,
  71142. 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead,
  71143. 0x5c37c334,0x65713c29 },
  71144. { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6,
  71145. 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424,
  71146. 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862,
  71147. 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1,
  71148. 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5,
  71149. 0x3bae3c38,0x6b0e996c } },
  71150. /* 21 */
  71151. { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269,
  71152. 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7,
  71153. 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da,
  71154. 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e,
  71155. 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342,
  71156. 0x678223f8,0x4022a205 },
  71157. { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d,
  71158. 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6,
  71159. 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd,
  71160. 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21,
  71161. 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11,
  71162. 0x24a6a956,0x312179cb } },
  71163. /* 22 */
  71164. { { 0x07615ac2,0xa94cc3ca,0x121ad581,0x85865e64,0xa7986b79,0xae47616f,
  71165. 0x9d5e0f1d,0x395a40eb,0x3d9457ea,0xa9143264,0xfa2865d9,0x8de6d6a3,
  71166. 0x1014ae8c,0x0771db96,0x976a87cb,0x77a7cce6,0x143a0f60,0xa7de42e1,
  71167. 0xd993d934,0xe203cc09,0x98ec4c3d,0x92018693,0x3a25df4b,0xd77546d8,
  71168. 0x62b02d6b,0x0ad9eb47,0xd05a7189,0xfaaaf208,0x431221bb,0x5238181f,
  71169. 0x733511ea,0x417d6c78 },
  71170. { 0x0e91e9a8,0x3cbd81b7,0xc370d6b3,0x73340418,0x8eaa2373,0x825db10a,
  71171. 0x6c7d6756,0x8f2b09e4,0x94c33ded,0xe288ee9b,0x1695e3fb,0xcd8426bb,
  71172. 0xdce9e888,0xa6176c86,0x6165e362,0x3f4c8922,0x6063fb09,0x514e411f,
  71173. 0xc8f9e04c,0x6907ac20,0xdfd2ad61,0xcef7469c,0x8452199a,0xba30bae4,
  71174. 0x12ac3462,0x30681293,0xc92d482d,0x011be873,0xe8330995,0xff4cbf89,
  71175. 0xd1470a0a,0x02189d52 } },
  71176. /* 23 */
  71177. { { 0x92599c69,0x73e419dd,0x7fec32ca,0x5b94221b,0x09bbfbfd,0xb2bf9bd2,
  71178. 0x63ed895b,0x61ea97a4,0x3f486f79,0x6609146b,0xfd141a39,0xbd1c7a05,
  71179. 0x83d64135,0xc79ec8cf,0x9883507b,0x7f8fd42f,0x17b3d027,0xafcb53b7,
  71180. 0x67ca5a21,0x86658dcd,0xcd149786,0xa6a6c0ac,0x34b95067,0x16f3d70e,
  71181. 0xdf44958c,0x371208e3,0xec280212,0xd2dd64e6,0x30782c71,0x33b2c4ab,
  71182. 0x521176fa,0x7bbf8abd },
  71183. { 0xa78b981a,0xbe9e4aaf,0x304ec828,0x788b4e36,0x3959dea3,0x0c45cf39,
  71184. 0x240b39c7,0x70a9bdd3,0x28383b7d,0x499cd7dd,0x307a1026,0x30690b2e,
  71185. 0xee92f1b3,0x2262d598,0xb4725a48,0xc62d77de,0x7bc3aa0e,0xa16f25bc,
  71186. 0xd15ef7fa,0x62dd8b65,0x0b96d68f,0xd979221d,0xa00f1906,0xb92885c3,
  71187. 0xeb74c740,0xfa476b9b,0xc7576222,0x217ddbb5,0x5788504f,0xc2782c30,
  71188. 0xf812716b,0x860d096c } },
  71189. /* 24 */
  71190. { { 0x4d79bbf9,0xfebc337d,0x69f74f80,0x5d53eab8,0x33104d53,0xff36a095,
  71191. 0x196f8b97,0x2ab820da,0x75ce6909,0x961d3d1f,0x04683754,0xb197ec04,
  71192. 0x93a6cb9b,0xa68ce1bf,0xc5f021a3,0x503456ff,0x8940ffdb,0xb50a2db1,
  71193. 0xef004209,0x77c50f8f,0x04965875,0xd635d177,0x8bb8770a,0x725766d9,
  71194. 0xa078e53e,0x8e19b028,0xf9fc8378,0x364d4cca,0xf0dd39a0,0x1a3df411,
  71195. 0x03adf920,0x7e80e442 },
  71196. { 0x539a1ddf,0x4b5f8a57,0xee486562,0xd248e7ae,0x816021e1,0x1c7b491d,
  71197. 0xfd36d2c4,0x2e7b871b,0x0aec00d9,0xda38b504,0x6193f1b3,0xf2827612,
  71198. 0xfb1f78d6,0x69c3fe86,0xe827ac33,0x56c8b786,0x3487c8f7,0x1687f6c7,
  71199. 0x19dee5bc,0xab8f2217,0xff399418,0x04e8473f,0xa9027c80,0xf384c014,
  71200. 0xaa1d2e28,0x9967be9a,0xe065eef1,0x869686d3,0xc7bd837c,0x737c6b08,
  71201. 0x9e8bd863,0x5dcab5d1 } },
  71202. /* 25 */
  71203. { { 0x9a7d772b,0x0784283a,0xe540959b,0x6b49e525,0x86414ab5,0x546bb008,
  71204. 0x9d74b2a9,0xd4448162,0x203b0b1b,0x267890ad,0xc8d3f86b,0x1e7a82bc,
  71205. 0xd85a83c7,0x1352bfb5,0xfad07ccf,0xf29f16e3,0x41e0c43f,0xc02a63b8,
  71206. 0x6b379fef,0x904f22c5,0xb1244f26,0x19d8a653,0x3a28bdea,0x6635b6df,
  71207. 0xf6d455ce,0x18b68851,0x9cff3735,0x74ac2818,0x8b2cbdab,0xad40f9df,
  71208. 0xadc9d498,0x08cc2d9e },
  71209. { 0xc170c84b,0x2e6a6866,0x5a49a484,0xbb989e8b,0xd04c8992,0x7b0e00e0,
  71210. 0x61b3a423,0x55ad3478,0xb0d01899,0x3c952450,0xe3100cb3,0xe3922155,
  71211. 0xf03276d0,0x19265b6e,0x76d42b53,0x0fe8595a,0xfc6353b6,0x0a96dee0,
  71212. 0x246f893e,0x761e0dc8,0xf0a74cba,0x4ec902be,0x3fdfad9b,0x61008684,
  71213. 0x4fdb6975,0x5d6a60e4,0x7ef7590a,0x3f53aac8,0x12870a37,0xd29e6be0,
  71214. 0x55aa55b0,0x991fadc1 } },
  71215. /* 26 */
  71216. { { 0xb4844ffe,0x82bc4b0f,0x60f8b871,0x73922714,0x4ce3f1f3,0x8ac000e2,
  71217. 0x163519ec,0xf0d548b4,0x88288b5f,0x7aaf842b,0x2bdc9a70,0x9e8b0c4c,
  71218. 0x4ba5fd67,0xa06d5152,0xf93cdec3,0xd0b1afa0,0xdf89f8f0,0x280955ba,
  71219. 0xeea32c92,0x86cbe92d,0x3fe05be4,0x0cae3f99,0xfa6919aa,0xf2607095,
  71220. 0x6e0f1b8b,0x0f54741e,0x30ecf988,0x2aed1f74,0x734991d7,0x9296f76b,
  71221. 0x259f0fe9,0x66cf8d28 },
  71222. { 0x226f5868,0x9b01905b,0x16909e9e,0xc102e88c,0x4a37eb54,0x2bd08916,
  71223. 0xc9816323,0xf72253e8,0x86bac53c,0x37f84e9d,0xafeaaaf7,0x2e352454,
  71224. 0x2ca0046e,0x67c86f77,0x6663372e,0x86bce50e,0xb6950a04,0xf6a3a960,
  71225. 0xfc1aba93,0x61f994d7,0xc1326e6e,0x1957c12b,0x2e56b005,0x9b658fe4,
  71226. 0x8592740c,0x9cd297fc,0x177f26a5,0x7654ce9b,0xa79d2ebb,0xaaa699db,
  71227. 0x0ecb6448,0x5fca0c5a } },
  71228. /* 27 */
  71229. { { 0x569a6663,0xe26e25f3,0xe6aa4ca7,0x09597ee7,0x8d18b80c,0x25a4cda6,
  71230. 0x22926730,0x450602b5,0x07387209,0x9af5f650,0x26733a53,0xfeeedb34,
  71231. 0x86572951,0x0f5ce768,0x8398ae9a,0x872a360b,0x2b30f6c3,0x60347a80,
  71232. 0x1a162158,0xd2113b23,0xee6c6dec,0x6fd9cf92,0x5cbcf9e6,0x85f0a5a8,
  71233. 0x2ba3fe84,0xd7a5a6e4,0x51ecd727,0xaafe6720,0xa2081a10,0xe09c6bb2,
  71234. 0xb973b0b4,0x657acbf0 },
  71235. { 0xc274c8d4,0x3130466f,0x30a994d1,0x42765176,0x7079435f,0x217258ca,
  71236. 0xeb897a06,0x44850406,0x561ee130,0xf38dfeee,0xaa1778bb,0x11f4facf,
  71237. 0xb9abb9e9,0x765c6617,0xd8f10932,0xb135499b,0xa73b9159,0xc0eb6337,
  71238. 0x6f7e8b6a,0xf2c1ccf1,0x187def53,0x5b32c03a,0x830b9c62,0x89ad1d49,
  71239. 0x2f10e538,0x1735eae3,0x9d5f55bc,0xb1cbd9c2,0xe539db0d,0x42428c47,
  71240. 0xc852b3bb,0x3d2da412 } },
  71241. /* 28 */
  71242. { { 0x871f2865,0x97702b6e,0x142920d6,0x56cb639f,0x45b58611,0x328522a0,
  71243. 0xf3b13812,0xf3943ad1,0x712206e8,0xe6c2200a,0xa34d59ea,0xc2890e5a,
  71244. 0xf6b7f759,0xab52fd40,0x180bf567,0xf522c8de,0xaccee396,0x181e97b2,
  71245. 0xc4ea5cbb,0xe0375819,0xab51d3ef,0x0d9985e8,0xbcb50fd8,0xe26c96ca,
  71246. 0x97e1c80d,0xfb9d6b13,0xf796357d,0x582b1814,0x07f4c7fb,0x89a78221,
  71247. 0xc0357e61,0x02aeef2d },
  71248. { 0x2c7ec9be,0x2ba7926f,0x7258b201,0x292f307e,0xc6fa6b4a,0x74e62a10,
  71249. 0xe2bcc5ab,0x80c08549,0x7bb8c073,0xb4160db8,0x329f194d,0xd5ef0529,
  71250. 0x6dda4a9c,0x0eb8da14,0x15ea23d1,0x0b5d43d2,0xfc34bfae,0x6cebef02,
  71251. 0x848757a7,0xacd364d0,0x2d34cca3,0xc1401368,0x1d2d95e2,0x09ca6742,
  71252. 0x786eaa28,0xc3fd1d6e,0xa2965fec,0x9eb1136d,0xc0779203,0x48871baa,
  71253. 0x4b15aeb0,0x6b446c01 } },
  71254. /* 29 */
  71255. { { 0x25e8fe80,0xc819eb2e,0x98238a17,0x2b5f7906,0x81e41849,0xd6f1e996,
  71256. 0x98ea6d45,0x58ad8ad6,0xbfd02e40,0x5bae5ad4,0xa812416d,0x016dc327,
  71257. 0xa3347ca1,0x8b31a985,0x82a65391,0x0b4da610,0xb48c35fb,0x1cb91b2d,
  71258. 0xd2aaf8c4,0x9e96817c,0xcdfdcdc0,0x1a630483,0x12b69254,0x70559361,
  71259. 0xf8a2a097,0x5fdcd712,0x35cc5281,0x59ab623a,0x932b6095,0x30c8ebe0,
  71260. 0xb08e052f,0x8613424b },
  71261. { 0xb2231d8a,0x28902063,0xd9a61667,0xb0f62329,0x071a9f27,0xaafa0fe7,
  71262. 0x603f047e,0x6bcd8960,0xfd92a1c3,0x118cca76,0x71d483b6,0x3414e62b,
  71263. 0xba705262,0xa123ccdd,0xfd9b5c5a,0x1a576437,0x4c8d0fa3,0xa5301bc2,
  71264. 0x102427cd,0x96f0ad44,0xd3aa6c02,0x0e6fb5e0,0x072a3996,0xcd8c4880,
  71265. 0x840d3fad,0x4dafca12,0xde91d541,0x29f4ca3d,0x8441734d,0x0037c598,
  71266. 0x9ccfe57c,0x86333a99 } },
  71267. /* 30 */
  71268. { { 0xecf53b40,0xd213a751,0x2f78a542,0xcff2c6f2,0xf13ae56d,0x0f59f0e2,
  71269. 0x0e61748e,0x91f8ccbf,0xd72c4145,0x0aadecb9,0x4c9cdcb7,0x6b2ed852,
  71270. 0x1eaffc70,0x8e00b72c,0xaa728102,0x89b24285,0xb679cafa,0xaa7ea7e0,
  71271. 0x4f0a6f6f,0x5d2b8c26,0x0e804397,0x7ed7b173,0xc8573049,0x5a93eb45,
  71272. 0x0986e93e,0xc92bf5d4,0x6a20c0af,0x526b5a9c,0xb99dc3af,0x0adf47c9,
  71273. 0xba202cc9,0x12b25fe2 },
  71274. { 0x33eea395,0x09b8d78a,0xf633fc5c,0xc7a93618,0x270eceef,0x7e821629,
  71275. 0xc628ed0c,0x524779b8,0xa1d68939,0x91db5ca1,0x586edc90,0x8626e18e,
  71276. 0xfeb3f3bf,0xfe023e8b,0x0250171c,0x6279fde1,0x55e172de,0xe52ec7dc,
  71277. 0xc6d4ca45,0x445e8695,0xbdbc10f1,0x42de3878,0x6fc3835e,0x2b114de8,
  71278. 0x7e10b652,0x9faba456,0x390e78fe,0x4111d82a,0xaedf0aca,0x576b61c2,
  71279. 0x74accb74,0x216279a9 } },
  71280. /* 31 */
  71281. { { 0x4047f747,0xc14cdabf,0xc1315a1e,0x03ca233d,0x40e5d0a7,0x59e7cbd3,
  71282. 0xbb413869,0x1fd0c4e9,0x0f01fbd8,0x189d08b1,0xa76b823d,0x50449c42,
  71283. 0x398b00a1,0x81c224a1,0x8e8179e4,0x08084e4f,0x698e41e9,0xfd8af994,
  71284. 0x5610bf2e,0x1e30e37c,0xa7d2790f,0x4e6a043f,0xb3195388,0x9d96e60c,
  71285. 0x03799dfd,0xe75f986d,0xf8ff902f,0x3b4a8f11,0x7588416e,0xfa945378,
  71286. 0x9827535e,0x20683e3f },
  71287. { 0xd0378878,0xcb582e26,0xa7945787,0x9e214c23,0x8f6688b3,0x13d000bf,
  71288. 0x40515270,0x7548d4f5,0x40111f5d,0x7113c15d,0xa8bff902,0x3bf5a526,
  71289. 0x9b4945cc,0xbda6b010,0xbc2f3a05,0x83dcc74e,0x43efdfa1,0x2aef6284,
  71290. 0x565c5bf4,0xd2e60ee9,0x592f243a,0x4f0fa10d,0x1bc3bf51,0x6ae58b32,
  71291. 0x60576a74,0x813b0868,0x4d73081a,0x0bc023f8,0x32dcee59,0x9fd03aa0,
  71292. 0x27d6c795,0x5e416bf5 } },
  71293. /* 32 */
  71294. { { 0x026cc23c,0x24313760,0xb5b29058,0xf819aaee,0xc5d2ee17,0xa92272f8,
  71295. 0xee5cc402,0x8048e7cb,0x77def07d,0xdbc7d6ee,0xf6af821e,0x61d69244,
  71296. 0x996cbb89,0x5f7966ed,0x96a155a4,0xf81b17ea,0x03f3ed56,0xb2d9ef70,
  71297. 0xe882a5b2,0x5e6e5906,0xae947180,0x86fa1072,0x658c76f4,0x34d9fc51,
  71298. 0xcb035aa0,0x9f603dc0,0x75be6481,0xb7b39feb,0xcf04a9ef,0xca87554a,
  71299. 0x87b4fde3,0x4ff682ec },
  71300. { 0xd0a10ad5,0x3125627f,0x968e6f45,0x7fd45c72,0x806a1163,0x2981bd6b,
  71301. 0xde5033e3,0xb92de1cd,0xbf4f8988,0x3b44b45e,0xdae7e1dc,0xca1b9896,
  71302. 0x0778d878,0x52166e5a,0xa5116847,0x82d472be,0xf2895445,0xfbdd382a,
  71303. 0x5d6ec4c9,0x22ed1602,0xb6552b02,0x3614eb1c,0xa1e6210f,0x63c5df73,
  71304. 0x021a74a7,0xe9160285,0xc65cbd4d,0xa44ca400,0x0f15e299,0x48cb187e,
  71305. 0x3402507c,0x51eb818e } },
  71306. /* 33 */
  71307. { { 0xb92100ab,0x1fc1d178,0x9605b839,0xdf2e3d60,0xb71e59d0,0x12a7c255,
  71308. 0x14fcbe04,0x3f8b6675,0x59fd06af,0x0e8a3935,0x12020d07,0x56326502,
  71309. 0x528e7be5,0x6696fcd1,0x0c7b7654,0x6588514b,0x5912a5b5,0x0cd80f8c,
  71310. 0xf324cb7f,0x8bafef04,0xc6da3d75,0x6b53eecf,0x31d1df2f,0xedef48d8,
  71311. 0x73812b6d,0xf336b965,0xee626031,0xc82eae4a,0xd244f09b,0x300abd32,
  71312. 0x31d9647f,0x8b0af955 },
  71313. { 0x2e603544,0xb770180a,0x221acd9e,0x2b573ac3,0x62407032,0x3a17f665,
  71314. 0xb89abc3d,0xad3e74ad,0xd793225a,0x8a3d2e3a,0xef02564b,0x457bba04,
  71315. 0xfc2dd2b5,0x8875652f,0xe67143e8,0xd2905d15,0x02e48d70,0x6d884b42,
  71316. 0xc7636a57,0x06f99219,0x35e378df,0xa8dc3421,0x10c64a02,0x95c1d73d,
  71317. 0xcc157a66,0xcd6a4ece,0x8e24a354,0xbadcc1c8,0x9839329d,0x8024f1b2,
  71318. 0x4da48ad0,0x5363e549 } },
  71319. /* 34 */
  71320. { { 0xe23fc641,0x1f5523b7,0x86667063,0xfe54e72f,0x8e009d2f,0x294a15f5,
  71321. 0x8c57f5e1,0xf203997f,0xb16d64dc,0xa229724c,0x4baa2ffb,0x697be4fd,
  71322. 0x0a6e8ed6,0x3f507e46,0x78508536,0x0afe3a5d,0x95408208,0xeeef6cdd,
  71323. 0xf2c4237c,0x701fd889,0x5c385253,0x496d883a,0x72a212f1,0xe25c67ed,
  71324. 0x1ff78fcd,0x4b416783,0xc16f4146,0xe9967004,0xc45b0697,0xfa45c3a1,
  71325. 0x3fbd30c3,0x63334018 },
  71326. { 0xa2fbbbce,0x39c9a0cc,0xaa0cb744,0x876f6e5c,0x3438ece3,0x9ce6010e,
  71327. 0x13802d82,0x0aad148e,0x9cd45a1b,0x9c3e5c60,0x7bcfc1e0,0x875cb859,
  71328. 0xd8584dd0,0xb19ff790,0xd81c2a2b,0x2598b81e,0x02be07e3,0x118bdf2f,
  71329. 0xb9765ce9,0x074fc8ee,0xb24f95ae,0x125e9d88,0x0c98f09d,0x3bb12cdc,
  71330. 0xa0b74b27,0x4a6aee07,0xc08077ce,0x4723d2f9,0xbea8026f,0x959447d6,
  71331. 0x16280b73,0x93a7075c } },
  71332. /* 35 */
  71333. { { 0x715b27f9,0x26bbefe2,0x2a280923,0xa935a5e2,0xfd58a26a,0x5ddf23af,
  71334. 0x7c138694,0x54c83e16,0x892a2153,0x44799bc9,0x9b8d09f5,0x4e6e4710,
  71335. 0xd588ea68,0xc63af616,0x883ab1b6,0x5e896706,0x3d209336,0x3c1393a0,
  71336. 0x92c23dda,0xd02f2921,0xdcf6ea43,0xab70cb7a,0x791559e1,0x12434ea8,
  71337. 0x6d70ff0b,0x040680db,0x2832ba45,0x1a10fe52,0xe5f0cb8f,0xd69f9c08,
  71338. 0x44b141fd,0x1a7422ac },
  71339. { 0x9f40b675,0xc3a9dd2e,0xfcc71f39,0x2a7c6603,0x1948e342,0x18939a61,
  71340. 0xed0ab484,0x8f3b6158,0xee31ca6b,0xa3aa7d97,0xf7a8db63,0xbc1e865e,
  71341. 0x2c7c62e4,0x315f8c09,0x9f5c6d0f,0xa260788f,0x4b6f3ec5,0xb1833129,
  71342. 0x36b4d849,0x73adbcd6,0xbc699a9b,0x66e14890,0x2a1175e7,0xbf3790d8,
  71343. 0xfc53ca4f,0x7f43605a,0x87ff6091,0x577f6c47,0x600c82b6,0x827c7552,
  71344. 0x9d25599c,0x0944d630 } },
  71345. /* 36 */
  71346. { { 0xe6ab9620,0xcfdeb63e,0x786cd808,0xdff4fa6d,0x456320b3,0x145edd82,
  71347. 0xc4943915,0x2ae5f862,0xb73b3f87,0x9508e813,0xe52f97a9,0x3bd805f3,
  71348. 0xc9829b62,0xf71b5c28,0x86e0cefc,0xb394c70e,0x23bdb36e,0x534fb1a9,
  71349. 0xdbe27e5a,0xd64f5862,0x83ab6169,0xbae23df3,0x27c828cb,0xdd6df1b1,
  71350. 0x3a307a8a,0x1901899f,0x811ddf66,0x36cc8659,0x79943b77,0xa3cb7774,
  71351. 0x6fd86576,0x7d89f383 },
  71352. { 0xc9f92b2b,0xf8564242,0xc46e32bd,0x700c6a75,0x7f99a5c5,0x93e768b7,
  71353. 0x03149568,0xb6efe858,0xc2ce6709,0xbbfe8a19,0xee6ec493,0x721a3b1b,
  71354. 0xc371c28d,0x26eeeea9,0x15177e1d,0xd798115e,0xb068a5a5,0xd7bf3bce,
  71355. 0x46d2b4b2,0xdf8da220,0x59be9dfc,0x3df0995b,0x77640b79,0xc96897bc,
  71356. 0x5a2bd3c5,0xce0cf4c2,0x89afe744,0x16f45d6e,0x3a8509bb,0xb53f3acb,
  71357. 0x63f2a6e6,0x449af81f } },
  71358. /* 37 */
  71359. { { 0xa16d9377,0xc2fcf132,0x7e1a2f9e,0x9ab377b3,0x86d19ae5,0x72e1a12e,
  71360. 0xd013bbb1,0xd2b12e66,0xcb5f66ba,0x0972e055,0x399eab50,0xd11de1c0,
  71361. 0xc65f5ec2,0xc1f314fd,0x8a9ff593,0xfc311841,0xe05246e6,0xdf73c1ec,
  71362. 0x1625056d,0xc28d1363,0x6fb25e19,0x30a9dbd7,0x845cd2d7,0x049ed244,
  71363. 0xd36e852d,0xc779b83f,0xf68c8a83,0x85a35fc7,0xc95e8033,0x299bf1e1,
  71364. 0x20891af5,0x0e8617c3 },
  71365. { 0x67c81b5c,0x53720602,0xe737873c,0x2fa89dcd,0xa8144fd0,0x2a7430b0,
  71366. 0x26208c83,0x3006c5a7,0xd8ea40f5,0x4e066660,0x896413a4,0x9dd025f9,
  71367. 0x46b9149f,0xbdf380cc,0x0a125cc2,0x80156619,0x52793c37,0x04d6a3b7,
  71368. 0x6b7a62f2,0xb6001374,0x585d5978,0xa9cfe268,0x8395fe66,0xdcad0cb8,
  71369. 0x46b261f6,0xbab468fc,0x9d9d9218,0xca0ef5ef,0x5e452402,0xc507d4a8,
  71370. 0x326cf687,0x6f4404f1 } },
  71371. /* 38 */
  71372. { { 0x4febd3ff,0xa3e1920b,0xfdfd2bba,0xca6234d8,0xe19a9829,0xb7d1af2a,
  71373. 0xc6f5bc20,0x23de1610,0xdaa39ca9,0xe204dbf3,0x6d8c70ab,0x2a2de9b8,
  71374. 0x7c9d370b,0x272e0c37,0xe565510e,0x80914c06,0x57cbb6b0,0xb611e7a8,
  71375. 0xd8266a6e,0x076fc6ef,0x3095801c,0xdfac34ee,0xb9e24063,0x69ff40a2,
  71376. 0x787aa5c5,0xa7ba31a9,0x33c70cd2,0x0e4d1fdf,0x6895f074,0x903e3132,
  71377. 0x7fb671e2,0x905771f8 },
  71378. { 0xa4062bee,0x5199ba0d,0x94d7d9f9,0x18e7238c,0x1e0922c0,0xf53f29bc,
  71379. 0xb12d855f,0xde9b2a81,0x6d68ca29,0x649f3eed,0xc50c097f,0x64adfc34,
  71380. 0x9db398a0,0x81964ab9,0x7a587224,0x00d59c47,0x74c5903a,0x09fea396,
  71381. 0x15043dd0,0x6aafd8ee,0x5f1ecc20,0xc5721a6e,0x0db9b7b4,0xb6d6a483,
  71382. 0x66c8d52a,0x06ffc617,0xacc82a27,0x3de241d6,0x27f2f7a8,0x0605f052,
  71383. 0x6404decc,0x6a22953b } },
  71384. /* 39 */
  71385. { { 0x74fce389,0x92452d8f,0x2afa5564,0x059634c0,0xf0ed7825,0x9377ccbb,
  71386. 0x37718e0d,0x89f4045b,0x9fa69a4d,0x11074e7d,0x7295b0ba,0x5d70bb07,
  71387. 0xf107ede6,0xb22d54ad,0xa1a29c7b,0x5c39a3d8,0xd795e3ab,0x37236c02,
  71388. 0x2b589951,0xf7282d00,0x5790bee2,0x5e2265be,0xa8e65ea2,0x91e0ea11,
  71389. 0x6001cebd,0x0e71a708,0x2c1c5402,0x16900f5a,0x357f6981,0xc3b2d5c0,
  71390. 0x619e3427,0x528c9ea0 },
  71391. { 0x5f26c577,0x1edc86b4,0x9438bd45,0xf8074708,0x792582a7,0x2dfe1013,
  71392. 0xde1e569f,0xe08eaca0,0x9a55a356,0x5f952efa,0xe4976216,0xa4d80b53,
  71393. 0xcd5d71f2,0xd2b65855,0x66cea3f0,0x246704bf,0x492323ca,0x193f641f,
  71394. 0x9adb1325,0xa681855c,0x2d19d652,0x86d522ce,0x5b82ed7b,0x53609f10,
  71395. 0x8e150d29,0x3b0f0094,0x0b13e891,0x23ad8bfb,0xf794b449,0xcbb1556c,
  71396. 0x738bcf57,0x200f9093 } },
  71397. /* 40 */
  71398. { { 0x8388387f,0xf9b22fc5,0x28e883c5,0xcf26f170,0xd1b7973c,0x447cab90,
  71399. 0xf6ec9171,0x8d5d4ea2,0xc30cdbc0,0x2e16f498,0x48623c2b,0xdc92910c,
  71400. 0x30dbc545,0xeb1491b0,0x14de21b0,0x631deb2e,0x2fe830f4,0x04a21066,
  71401. 0x379c1f3f,0xa4c6979c,0xfb06a795,0x8a732b68,0x1619dfa9,0x3a44327a,
  71402. 0x8dbe2c9b,0x91a307d3,0x03989fea,0x939bc8d2,0x0f4a331f,0x3daabaf2,
  71403. 0xdd0f55dc,0x5c307e98 },
  71404. { 0x35b233da,0xbbc4e0c4,0x22f6f985,0xe3d29085,0xa8b02468,0x99dd2d21,
  71405. 0xa96916e7,0x978f40e9,0x614bcced,0x0327d86c,0xb290762c,0x95e95502,
  71406. 0xa879f2ed,0x0ffd2197,0x50e0bd33,0xc4365137,0x0827c4c4,0x26c3148a,
  71407. 0x3fcfc0b2,0xc79812a8,0x31928589,0xc3d8d17e,0x8830f42d,0x8b572cfe,
  71408. 0x4b07f83f,0x7cd9ff92,0x0a51148f,0x331ca950,0x4c59f9ac,0xd0c53968,
  71409. 0xc1434785,0x1df16dfa } },
  71410. /* 41 */
  71411. { { 0x68bcacc3,0xcc7bb4ac,0x430f58cf,0x06ded34f,0xd461855a,0xc59f9f4f,
  71412. 0x45c9f0bc,0xf5491994,0x4375c892,0xdc5f7ec6,0x3c85983a,0x1b8708f1,
  71413. 0x82fcd087,0xb32a5cc4,0x2d6b4c0f,0xefdcdc35,0x8ac6fb2d,0x4bb24f04,
  71414. 0x33906471,0x5982d4f5,0xb83a3ac4,0x162eb52f,0x2337a223,0x7130df28,
  71415. 0xcbc3dbd3,0xdce7b802,0x2467ac0e,0x8b395959,0x1b56717e,0x21d3d2e8,
  71416. 0x46512617,0x729a7f50 },
  71417. { 0x8420f90a,0x874ed1aa,0x0fe4c855,0x6368e19e,0xb0be74af,0xb62d4aaa,
  71418. 0x8ca60ca9,0x76fcc480,0x7645a867,0xf310b5a5,0xddb1b24c,0x131bac9b,
  71419. 0x2dea5b44,0xef77d71d,0x72fcc64e,0x4706d210,0x673d77f0,0x29b92691,
  71420. 0xe89e0663,0x22e00bf3,0x74077d40,0x472d0cd3,0x829232e2,0x3e21040d,
  71421. 0x38dc8533,0x2f916dfb,0x14b8f667,0x48bbb59b,0xd44be19d,0x19de9f4a,
  71422. 0x232d9d5c,0x7f6d3649 } },
  71423. /* 42 */
  71424. { { 0x6e794819,0x3bd064de,0xf82ebda1,0x5a6b694e,0xb91e2804,0x1f017fe0,
  71425. 0x07a43cd2,0x190d31f3,0x630433e9,0x6c26f226,0x0abfdcb4,0xba488aa7,
  71426. 0xa46411c0,0x418d9085,0xbffb5880,0x1b934fe6,0xe200f849,0x75d1e237,
  71427. 0xa55413db,0xdf04d63f,0xe23b3f77,0xe216ed75,0x0f91bd30,0xa05866cb,
  71428. 0x7729c509,0x84c395d9,0x452ab2d7,0xec97e188,0x0093d686,0x8cb7c1f9,
  71429. 0x628f086c,0x2d032395 },
  71430. { 0x4a44b4c5,0xa81c9407,0xcc702c98,0xb9846879,0xceb0dc97,0xcb502287,
  71431. 0x6e3aa321,0x30301126,0xe4c256c2,0xc0ac8763,0xe55b4845,0x65034d20,
  71432. 0xf240f35b,0xaa96a040,0x7cf7eedc,0x046d26d3,0x3b810656,0x62a5a8e1,
  71433. 0x83d70c2b,0x86044b97,0x59e4da8f,0x2fbaff88,0x5457f5d1,0x929d901a,
  71434. 0xb531b757,0xd29e1eb2,0x9e4e9739,0x214dabdc,0x4eaa9bd9,0x5bd724fc,
  71435. 0x1ef9bb9b,0x734c12b3 } },
  71436. /* 43 */
  71437. { { 0x92f9b086,0x98fe3c2e,0xb3fd4544,0x4641b93e,0x5c02c65c,0x47ce208b,
  71438. 0xc4f03242,0x8a52dca1,0x679d29f6,0xb5ec17d9,0x9406f5f4,0x11d2fed0,
  71439. 0x0d9ba811,0x260f63dc,0x15472a3f,0xde2b056f,0x007290e6,0x1b170d9f,
  71440. 0xb6b5c8f9,0xa2e23e8d,0xcf34c3ee,0x345a2839,0x1b973ee2,0x9bdc5461,
  71441. 0xbb24d1c5,0x65bda6c2,0x3c6141a1,0x97d52ba3,0x9d2eb201,0x47bb1612,
  71442. 0x21fbe49f,0x7c558a87 },
  71443. { 0x3f350fec,0xb9485a52,0x6a38d4c0,0x016678c5,0x0d5aa64d,0x8ef346a2,
  71444. 0xd96da2e4,0xb85daa02,0x4f647b3c,0x845ec4ea,0x0d5e946c,0xc0d1a6ca,
  71445. 0x4fa9f4ab,0x41d8d1c1,0x9c8b1303,0x43972cc5,0x434ffbfb,0x67e1f48d,
  71446. 0x819d2318,0x350ce93a,0x6ddef23f,0x49f53090,0x200cf12c,0x3c2e6cf9,
  71447. 0x640432fc,0x42691cc1,0x72496b52,0xbfff74b4,0x020a97be,0x44527c9f,
  71448. 0x7b3c4348,0x34cd7dca } },
  71449. /* 44 */
  71450. { { 0x59e7fe87,0xf031761a,0x0047cd72,0xb1eae31a,0xfae30f62,0x27902e68,
  71451. 0xb71db143,0xa666f48d,0x0e0038f4,0x75ee6678,0x02bdd76d,0x3b45ac67,
  71452. 0xa0d6cd5c,0x0d2fb828,0x9d8c5b11,0x27ce7f1d,0x120b5e96,0x141fe0e4,
  71453. 0xb9267c37,0x95a1b984,0xd60312cd,0x5206e589,0xda549356,0x1867342e,
  71454. 0x070c74ac,0x374520b9,0x9557b0b3,0x2703cbb5,0xa6ed8c14,0xf621f59c,
  71455. 0xabf7b887,0x7ceb1cc2 },
  71456. { 0xdb7fd65b,0x0647a5bb,0x36c9457c,0xd8d45cc0,0x9e12718a,0xc6da99db,
  71457. 0xe93a7fb1,0xed1dbbf4,0xbd1566a1,0x4512c95c,0xdbc0c919,0x4861ba00,
  71458. 0x9e7f5269,0x3c6cc298,0x0941aaae,0x67196150,0xc8c538e3,0xbfcf5d0f,
  71459. 0xa25a551f,0xad6e9929,0x17ca0f26,0x90710985,0xfa89ef7e,0x743b78ea,
  71460. 0x71ab4549,0x39d5ea31,0xe6d1c36d,0x7442f3f3,0x059d568d,0x25a683e0,
  71461. 0x227ced5c,0x1f629a99 } },
  71462. /* 45 */
  71463. { { 0xe45a1c3e,0x8925ddac,0x41f7545f,0x72d29365,0x37e7f828,0x45622fcb,
  71464. 0x3e4c79d2,0x88234513,0x9c2645d6,0x5dffaf84,0x994802b9,0x3078f4dd,
  71465. 0x9d339fa0,0x566927f0,0x9fd91dcc,0x9a500a1e,0x0ab0abd7,0xce008180,
  71466. 0x8194e5df,0xd97135a3,0x98adf088,0x9e876307,0x9a45a2a7,0x3baf01b8,
  71467. 0x788b4399,0x6fed6154,0xe77a997d,0x980e5722,0x2a378eed,0xaac90ffa,
  71468. 0x8bd805a2,0x4a75fda2 },
  71469. { 0x55e74cbc,0xd09a8fbb,0xfab18f25,0x737738ce,0x9764ec3a,0x0fc23ad6,
  71470. 0xe7e0ad31,0xc5a7d35b,0xe481cc9b,0xe75e068e,0x3d4aec34,0xf0c2ea99,
  71471. 0x0d4a63c4,0xf1324fe8,0x99b0592c,0x5dbb7c16,0xa7e0f46b,0x442d674d,
  71472. 0xa300faea,0x5a5d66c7,0x3333ac83,0xe83dc821,0x8c408496,0x70ef812e,
  71473. 0x99ef5fc1,0x96e1dcb6,0x1734e862,0x6e2b771b,0x583507d8,0x04629cdc,
  71474. 0x23d8179a,0x5819f9ae } },
  71475. /* 46 */
  71476. { { 0x6aa78811,0xd9969121,0x2103e7c3,0xf64ee8f4,0x22b9e698,0xddf01070,
  71477. 0x4f582cde,0xe6001f9e,0x2ecfac1a,0x24a608af,0x06393009,0x6ef4c784,
  71478. 0xebf72911,0x5262eae6,0x8c4ee5a0,0xddbd0af5,0xecd87bc7,0x875aff90,
  71479. 0x6f24f114,0x2fddb34c,0xe865f172,0x48104281,0x886c1b9a,0x95692426,
  71480. 0x9ef4231f,0x6f5f3208,0xd0a7e82e,0xaf587acf,0x9ac395c8,0xd6571917,
  71481. 0x1364a750,0x7459603c },
  71482. { 0xf41ae519,0x1c2475bf,0x4af8f251,0x34401fb1,0xaefb2c3d,0x70ddfcd2,
  71483. 0x51cdaf08,0x9b2d385b,0x8208bb19,0x8531c256,0x4c33f3f6,0x16c89df6,
  71484. 0x24571769,0xc23cfa99,0x86d010ba,0x2339b51e,0x22638313,0x08db0e8d,
  71485. 0x00fedeb7,0xf769e179,0xa3687ef1,0x3fd96dcb,0x91476475,0xcd046b23,
  71486. 0x0c45c8dd,0xf3ff2064,0xb8343d78,0xefd167bd,0x4b77ee90,0x493ccb6d,
  71487. 0xb3cf7b45,0x33025513 } },
  71488. /* 47 */
  71489. { { 0x35eaaca1,0x36f00469,0x89119102,0x0c384b75,0xe6d2954c,0xcb375665,
  71490. 0xb1e9d6d7,0xcb9199b9,0xc29c2757,0x75852349,0xb8e738d0,0x89cbd1ba,
  71491. 0x5923a427,0x9b8dbe90,0x18fe1889,0xa237793e,0xa742e083,0xa4271757,
  71492. 0x4eebd613,0x8c4979d2,0xd4f2cf77,0x40325054,0x958705de,0xa3b8a091,
  71493. 0x33d999ba,0x1b191bd9,0x3b0fee1e,0xbafefba4,0x3facdf14,0xb3bad184,
  71494. 0x4387561c,0x9328adb0 },
  71495. { 0xf906b872,0xabe84e80,0x78262665,0x705523a0,0x3398ccf7,0xd89c6a7e,
  71496. 0xf55b5323,0x2fab551d,0x0554dea8,0xa0578eca,0x375589cd,0xef26523d,
  71497. 0x864ad750,0xd8fd6242,0x178fe1fe,0x93f27fc5,0x9df87422,0x7b3e6f30,
  71498. 0x3750d054,0x2862e49e,0x5dc038a1,0x7d90c6b2,0x84db682b,0xc1a1ae22,
  71499. 0x9881930a,0x47f3dab7,0xbaf3e0a4,0x30e6bd52,0xf62d25c5,0x0680025b,
  71500. 0xadd0d5e7,0x0aa1f3cf } },
  71501. /* 48 */
  71502. { { 0x22a10453,0xa9822190,0x2a03a10b,0xdd1eb91c,0x96646f3b,0xafbb5d95,
  71503. 0xf38b6fc6,0xa58de344,0xb8cfca1d,0xce47c3e5,0x0f70da04,0xfcd8e16d,
  71504. 0xda262ed6,0xac44349b,0xc56e2f8e,0x9320d87b,0x19138e58,0x9ce3ea08,
  71505. 0xa2b236c0,0xa5862dff,0x8e7efb0d,0x6b0f9a5c,0x16ac78eb,0x4b53432b,
  71506. 0x709b51af,0x6ff43105,0x8f519628,0x08e236f8,0xeed403ad,0x1f93f176,
  71507. 0x9636545e,0x559337e0 },
  71508. { 0xd8fd807a,0x30ddf738,0xab131222,0xf4e0ec9d,0x625afbc3,0x14a2f4db,
  71509. 0x9f12f895,0xd5b70604,0xac3044fd,0xb46f3c23,0xf540148f,0x1b232d1f,
  71510. 0x39b4e554,0x61b458f5,0x0dd70b75,0xf694b24a,0x289581d9,0x0fc64299,
  71511. 0xee5fe22d,0xc05d49be,0x6a18bf63,0x7af3447f,0x7f1929d6,0xe96a1dc2,
  71512. 0xc1551e8c,0x6afe6028,0x2b5d4fa2,0x27dacaf3,0x545c2cb4,0x4a1631bc,
  71513. 0xb0c914d3,0x930070f9 } },
  71514. /* 49 */
  71515. { { 0x69a9bc05,0xd2f32c5e,0x589c4b73,0x0a5c19c6,0x94665f9c,0x095c9e5e,
  71516. 0xbcfb4c39,0x8ab0f293,0x1ddb7c31,0xb9070877,0x66b38048,0x894e9658,
  71517. 0x606bd9bd,0xf19a90cf,0xb6fd2d69,0xcc1d58df,0x461d8a69,0x886dcc4e,
  71518. 0xf9ce4831,0xc455c277,0x765f8a82,0x749a5996,0xc3badc8d,0x2ffc668c,
  71519. 0x9112cdab,0x38018396,0xb243c7cb,0xa98795c3,0x010a2224,0x8775f310,
  71520. 0x587b5e14,0x043a2141 },
  71521. { 0x3a873752,0x7bbe9dbc,0x2f442fee,0xee1493f4,0xc18c2181,0x981ca2c8,
  71522. 0xe29769e7,0x00ce3090,0xde768c5f,0xb4626ac8,0x34d7677e,0x33e9ce46,
  71523. 0xe0fa94e6,0xf89c2cad,0x41f5b5bf,0x04f5cc11,0x2228c12c,0x2565f736,
  71524. 0x0c05cce5,0xf1bf706a,0xbe487c4f,0x5d07ffff,0xa499f1a4,0x3ec43c09,
  71525. 0x98d94800,0x4f4e79bb,0x073f12f8,0x8a335a16,0x0f970d6d,0x4bb5eaf7,
  71526. 0xf24d0ae8,0x18d0747b } },
  71527. /* 50 */
  71528. { { 0x84601faf,0x58d3c77c,0xaf1c1f72,0xc9465be2,0xd116d806,0xff626798,
  71529. 0xd5b0d93c,0x3996c0c6,0x5ec6723a,0x2fa1ad75,0x03ba5349,0x966a8144,
  71530. 0x2ac34d8a,0xdc4c9422,0xed675865,0xddf471de,0x953d528f,0xd8aca597,
  71531. 0x24ebf67d,0xb2e463b5,0x7e25b4d3,0x25824871,0x43159daa,0x23c5adba,
  71532. 0x83357540,0x5458f9c6,0xf938b1a6,0xcf685da7,0xcefed231,0x981a4fda,
  71533. 0x08bb5e59,0x711093ed },
  71534. { 0x401f161a,0x12aa3fc6,0x974c5e87,0xf7358560,0x17b5df82,0x4aa252fb,
  71535. 0xa48e6299,0xb0b82b07,0x29dd847d,0x00234157,0x4529c5a6,0xf1e54d00,
  71536. 0x6d98f538,0xcc1c539e,0x28d3abcb,0x36162b53,0x2a84f0cd,0x75a37938,
  71537. 0x4dee7484,0xf717a81b,0x4c23bf1b,0x16cf35fb,0x787e8b3e,0x7fd1c29f,
  71538. 0x59b79ab0,0xb7da7e68,0x85f6c60b,0x072100a0,0xe7ed48b5,0x31840159,
  71539. 0x4d9c97d4,0x17898bda } },
  71540. /* 51 */
  71541. { { 0xae1b8cf8,0xcd8483d8,0xe9a28856,0x323d4b42,0x204a4bc2,0x7633584f,
  71542. 0xca7a69fa,0x4e0b2228,0xf757bab2,0x8afbda8b,0x6cc5f9ca,0x85b24088,
  71543. 0xd41a95c3,0x47fb4813,0xc2aabe6b,0x3f1bc53c,0x1ad1599d,0xf22cda3f,
  71544. 0xc31ea9b1,0x1b2ec081,0x01614ac1,0x048f304b,0xc6afa7ab,0xce31cee9,
  71545. 0x4140dc3d,0x55af7633,0xdce8abba,0x84b7ab37,0xc7cf3efe,0x50de7648,
  71546. 0x15356ab2,0x73a88dcf },
  71547. { 0x06e83b39,0x3f868288,0x9f44037d,0x477a4413,0x17dbc841,0xf9058b0f,
  71548. 0x54d17549,0x2db64f4f,0xf2307ffe,0xa23cea6a,0x4f126261,0x393efd55,
  71549. 0x10f37f26,0x2f4e658a,0xf4ee1e35,0xa4437ce3,0xa93cde8b,0x64ef42a7,
  71550. 0x939aa901,0x1debc9f4,0x3d7b5cd4,0x44223d6a,0xf88a3acc,0x789a6a11,
  71551. 0x2c608a2d,0x56fb9df8,0xbbf56c06,0xe79db8e3,0x668fa300,0x73c56af2,
  71552. 0xae396a1e,0x52f32b17 } },
  71553. /* 52 */
  71554. { { 0xe714f71a,0x56f524c1,0x9add8519,0xc1be1262,0x65cadbe3,0xad9189d8,
  71555. 0x5a0fb649,0xd88bf5c8,0x21d192d9,0x9efa6a92,0x6f724b6f,0xe3fe8389,
  71556. 0xb250119c,0xec3fae24,0x2ae0d3c0,0x4b6af9f6,0xd619624d,0x8fceba0b,
  71557. 0x2fdb6e3a,0x7dc3092b,0x3263cd29,0xc91da376,0xf95c43bd,0x30c0761e,
  71558. 0xcdeb44d9,0x89136400,0x43c0d31d,0xfd7dce84,0x9871899f,0x78fec3b1,
  71559. 0xefdf58c1,0x79e14d28 },
  71560. { 0x9bb40c55,0xe3822235,0x0ed07a42,0x0a27202d,0x4838c1f4,0x48e6c1a9,
  71561. 0xd864a78e,0x2b5f24a7,0x0c6c55c9,0x7e7f140a,0xce12d508,0xe62c104a,
  71562. 0xc11b1e10,0x9b0a1a7e,0xafbb3dd5,0xfd8a275f,0x9a3b6b30,0xdff354fe,
  71563. 0x46602a01,0x5a105d9e,0x93bb65f7,0x3d371b4d,0x0f82fdeb,0xda5cbf0b,
  71564. 0xde468545,0x4601229b,0xc73d517e,0x505e10b9,0x672ff492,0x77cfa541,
  71565. 0x99566ce2,0x0d8ec28a } },
  71566. /* 53 */
  71567. { { 0xcbeee995,0x014cf73e,0xd491e80c,0xb2eb88bc,0xd9aba5d4,0x615a6cad,
  71568. 0x9304c84d,0x2f7d4633,0x8ab03c9a,0xba0501d2,0x91babb94,0xc8f723de,
  71569. 0x50405772,0xc885f977,0xc7fcb094,0xb5e1d2b3,0xdf96c71a,0x61ee7995,
  71570. 0x3464499e,0xb8c8daab,0x5f607932,0xdb425ddd,0xb1243587,0x70251ca1,
  71571. 0x9fc74340,0x26d7d3be,0xc902ac89,0x8c179310,0x4559a74f,0x72522c15,
  71572. 0xc3734afc,0x86001e27 },
  71573. { 0xe7693947,0x13b00ba5,0x012c062b,0x6478641e,0xe85490a8,0xe1a438e0,
  71574. 0xd9574d5e,0x5173dbbf,0x9bd3ba61,0x9532eb8c,0x5f3ea075,0x1f41bcb8,
  71575. 0x8cbb92b9,0xac1cc247,0x1ef901b4,0x0f34648e,0xd2b3b2ee,0xdd929d1e,
  71576. 0xc3d75bfc,0x470f1eab,0x139cf4d2,0x5cdbc6f7,0xf0424953,0xcd86454d,
  71577. 0x47fcb383,0x1e079812,0x17df930c,0xb9f209b4,0x114ebc00,0x4225fc31,
  71578. 0x347946c1,0x020591cb } },
  71579. /* 54 */
  71580. { { 0x275e0af4,0xe3003721,0xe78a4a4b,0x721141ef,0xd1757485,0x666cfcf6,
  71581. 0x168e659e,0x5fa1d737,0x0e2842ee,0x263e3e54,0x948bd5f6,0xadecc3d4,
  71582. 0x246b104a,0x019de03d,0xf343d818,0xf8a9e903,0x5b0c0d31,0xcb57ba4a,
  71583. 0x51e2765f,0x8246c506,0x6519bf67,0x80c5751f,0xf2119a01,0x5f05c200,
  71584. 0x7821d4f4,0x7e6487b8,0x261c3a06,0x262f94aa,0x72146052,0x56cfe489,
  71585. 0xa1df05ef,0x5119985f },
  71586. { 0xb18586c0,0x5819497d,0xc6eeaa62,0x004415d6,0x97cda28b,0x7c6a46b6,
  71587. 0x7c194594,0x9a149b28,0x4ed3a506,0xb56369fa,0x43c94cb4,0x7092aa66,
  71588. 0xa9e9eee2,0x55bce73a,0x77893509,0x34bb2870,0x06eb5326,0x8af95fb0,
  71589. 0x9638f485,0x87cd0323,0x5ba75bf8,0x29376268,0x9d42d581,0xf32d6f3d,
  71590. 0x65c6d64d,0xa4cad574,0xb2cded41,0x985f50fb,0x9006a067,0xcf34ce0e,
  71591. 0x58a57f9a,0x59eaf265 } },
  71592. /* 55 */
  71593. { { 0x6ec3876f,0x7b407efb,0xf0f48648,0x780c6123,0xbf893039,0x2abb56ff,
  71594. 0x45a91ab0,0x9592eaa0,0x78811b82,0xce5b84d7,0x1f9f3fc9,0x86a71a34,
  71595. 0xf0e7e13b,0xc17fdd86,0x655a0880,0x88ed8297,0x81d5e666,0x75d6dc74,
  71596. 0x1d171797,0xeffc9df6,0xe3f79e1f,0x36ad4c8d,0x2046192e,0xdb15317d,
  71597. 0x274fda62,0x78c9fa7a,0x82dd9914,0x04ec924f,0x3a64971c,0x059d1e38,
  71598. 0x2620bbfb,0x3b4450ea },
  71599. { 0xc776dcdb,0x3db7a955,0x81c8ba47,0x35c4a57c,0x505760fb,0xae285003,
  71600. 0xb3aec353,0xe3e80691,0x47117be5,0x380335be,0x056ccf61,0xe1c47e3a,
  71601. 0x33977916,0x253cfdeb,0xf5cb7ee1,0x3decdfba,0x7cf4b704,0xf3c9794f,
  71602. 0x9ff81462,0x2401680c,0xbe3daa9f,0x4e440e11,0x69f91d8a,0xc5d04377,
  71603. 0xcb5e9c5d,0x4106c7a8,0x33b7d24d,0x191909a1,0x3764b4a2,0xe893c838,
  71604. 0xc429b614,0x4a7fe30c } },
  71605. /* 56 */
  71606. { { 0x2455c7c5,0xe78f3a70,0x70157754,0x5b7636e8,0x7623262c,0xf32c4524,
  71607. 0x1bc780c7,0x2c98b11e,0x915ed877,0xd48eaeac,0x199265f4,0xbb04d3c0,
  71608. 0xcfa5200f,0x6b52b19b,0x93ea3fe8,0xc46a0981,0xba758059,0xd82c733d,
  71609. 0x1896aacc,0xd324bbd6,0xce8ecd51,0xac09a2fc,0x02fc44b3,0x529918fd,
  71610. 0xaaa1784b,0xf0c45e4a,0xfe22085c,0x35626340,0xc50c7d61,0x53cbb676,
  71611. 0x65126b23,0x83fa1ea3 },
  71612. { 0x10ccc646,0x60ac86da,0x7b0451e9,0x2ce0637f,0x8a088610,0xbbbcf630,
  71613. 0x20349982,0x23c19019,0xfc0bcda0,0x707fc39c,0x1bd4fd7d,0x7f4d1f15,
  71614. 0x44713bbb,0xd6a64e74,0xc5ac9e60,0x57bdc676,0x37b61169,0x456c5303,
  71615. 0xdcf40a1d,0xd3451396,0x4997d2c7,0xf3edec25,0xc2c4a739,0x534ae9a4,
  71616. 0x6a6ad2e2,0x1401397e,0x23e95f81,0x20769d4d,0xde98fabf,0xcee007c6,
  71617. 0x931c51e0,0x61409779 } },
  71618. /* 57 */
  71619. { { 0x15156623,0x3ddb32db,0xab7a67c2,0x68137fbc,0x6f19e3c2,0x26011f50,
  71620. 0x89924c61,0x34218b02,0xc6804c1c,0x492a0b0f,0xafaae6a7,0xd65be706,
  71621. 0x0d01be61,0x3b13d23e,0xf87f4c69,0x44545b47,0x04dc1aa3,0xd42236e2,
  71622. 0x3c5161ec,0x6135261d,0xbd88bc07,0x1eb46a63,0x1599d720,0x78c6d836,
  71623. 0x69baf0f3,0xf6955fe1,0x17072820,0x467eebd6,0x3e3a340a,0x2f1b8a2a,
  71624. 0x2d0b5f88,0x636dac76 },
  71625. { 0xb4c80af3,0x94280db9,0x4e3892ab,0x9a189cd1,0xd1477ddc,0x26e702e0,
  71626. 0x68f9f14f,0xe91aee38,0x80baa0b2,0x2864f63a,0x8b714a29,0xacd81f73,
  71627. 0xc5fe7cb6,0x30e1b870,0xb10837fd,0x883ea1c3,0x6b20489f,0x2da27953,
  71628. 0x58a2da5f,0x3aeb2a68,0x03a8fa14,0xe2330bf2,0xdc70b1c4,0xb5c488b5,
  71629. 0x299678f4,0x0a78c4d9,0x25df675c,0x233bd098,0x7b67d368,0x37b5c076,
  71630. 0x4d0bef3f,0x2f6dbdfe } },
  71631. /* 58 */
  71632. { { 0x2e4da7c7,0x2f8472fd,0xae677932,0x708cfc91,0x3dc268e2,0x364af08a,
  71633. 0x799a2424,0x0f10dfe0,0x71d58bff,0xef912d58,0x988962e6,0x6bf35dfc,
  71634. 0x5f47ea0a,0x28b96fa9,0xaad308c1,0x734a79ea,0x9f437bba,0x95730337,
  71635. 0x6cf54f75,0x002cbd8e,0xe7632eec,0x47606dcf,0x53193104,0x404b5ecb,
  71636. 0x0acf729d,0x0ae0897c,0x3bddf1de,0x89628b86,0xf87d7448,0xeced154e,
  71637. 0x458d5d4e,0x5cb6e197 },
  71638. { 0x008c75ed,0x98cef197,0xf6eeaaf8,0x7cf49d3e,0x1875e96d,0x1d6f9e02,
  71639. 0xdd9b0d8a,0xfcec2cfe,0xb9576daa,0x38a61cfe,0x36a7dbb8,0x10003f39,
  71640. 0x23b814f4,0xb37c3868,0xb80e3153,0x9fb66dcb,0x059847a8,0x9e7e2eba,
  71641. 0x35a72770,0xa4ec63fd,0xfc9e0ed0,0x311f3d91,0xd515baa4,0x3c1dc094,
  71642. 0xa08cd4e3,0x75a06ebc,0x2ed5eeaa,0xab617238,0xe1f52c1f,0x2e82bbb0,
  71643. 0x5175d6e5,0x2149d630 } },
  71644. /* 59 */
  71645. { { 0x5f9311f6,0xee1a8e6f,0xbabc1f85,0xc97e3c9f,0xb494209a,0x4fa7c52e,
  71646. 0x19774fe1,0x04c2f51c,0x8555844f,0x5cefd122,0xb5873ab3,0xb53862a3,
  71647. 0xcbed19fc,0x768efdd6,0xee58469a,0xcdc12479,0x3d80c09c,0x11237e31,
  71648. 0xc044c28c,0xdd74a290,0xbd47e287,0x9ee6517a,0xad0ffeef,0xc2421228,
  71649. 0x818d281f,0x4273088f,0x43ec0de1,0xebc744bc,0xb415bd73,0x5b26eccf,
  71650. 0xcb07c26c,0x14e2f350 },
  71651. { 0x4216946b,0x548d2a10,0x7a4bd92d,0x6e801f07,0x43695160,0x5996d0a3,
  71652. 0x63a197c9,0x0f1b5c2f,0x061f77c9,0x79da3c4f,0x93ff7b22,0x1c1cd634,
  71653. 0xa234123f,0x5e61b650,0xf284033c,0x826b34c5,0xc2f34214,0x718b90e8,
  71654. 0xae806ec5,0xa5f35620,0xe324a9b4,0xa2fae345,0x8b53cb51,0x8c0bb95e,
  71655. 0xf9965778,0xc94f6ac2,0x6b9def32,0x07ec607d,0xd0ed8f27,0x63bf1dba,
  71656. 0xdcb61e4f,0x58537e02 } },
  71657. /* 60 */
  71658. { { 0x64f80ba2,0x1f64b064,0x0559a45b,0xe8e055e7,0xf1f4b634,0xc3262b34,
  71659. 0xde8c8482,0xef4f7d5f,0xc30c780a,0x9d55dea0,0xcfa1e693,0x1740afb9,
  71660. 0x7460c34b,0x2cfe6a66,0x1187c1ee,0xf6695941,0x5f974d94,0x1382f277,
  71661. 0x004549eb,0x1ca0ace4,0xbabded02,0xf8244b3f,0x4e3653ea,0xc36f4d06,
  71662. 0xc55c5f83,0xeab9f0dc,0xacebce90,0xd93b9cef,0x19061425,0x16658e72,
  71663. 0x82d7970d,0x4857835f },
  71664. { 0xd2576210,0xdcd525bc,0xd51b5443,0x9f378aa7,0x1bd83994,0xfe97bf17,
  71665. 0xf38ac621,0x930d0f63,0x818408cc,0xaf8f2c17,0x260f53f6,0x2692c87e,
  71666. 0xdb0a75e4,0x0ee45407,0xffdb1b37,0x0ec47ae5,0x7aa6a44b,0x769129dc,
  71667. 0x2e40b75d,0xb6f932b2,0x95ef3b77,0xe06764d0,0x68bc63e8,0x28fd47f5,
  71668. 0x9c0014c0,0xd1810494,0xd7995d8e,0x90e2d3fd,0x6c2a85af,0xeb39a05d,
  71669. 0xa21f3128,0x6c0277bd } },
  71670. /* 61 */
  71671. { { 0xb509e7ef,0xe41b7086,0x3d7f9f91,0x8842ec7b,0x5526b88b,0xcd285f94,
  71672. 0x051dd0ab,0x6e44e064,0x774f1ceb,0x90198c10,0x123e661b,0x6ecabe98,
  71673. 0x32f647d9,0x44811136,0x26c52aee,0x1dd82b45,0x939dc9d5,0xd650907f,
  71674. 0xfcd455bf,0xbd5eeef2,0x8d2e5d7c,0x7815a4dd,0x88bc9f2a,0x5ad4ec92,
  71675. 0x57a3b322,0xc6f10d0b,0x20b9cbdb,0xe8d0c1e7,0x9b774ee8,0x5a0b071a,
  71676. 0xf22fcf8f,0x3067bc9a },
  71677. { 0xb7ca9326,0xe0e589f2,0xb1224f63,0x17a106fd,0x747a57bd,0xb2354521,
  71678. 0x62b0882e,0x2614982d,0x4391ffcf,0x7f3af544,0xa84e440d,0x1aaa337b,
  71679. 0x941bb071,0x28ea37b0,0x2e4a7f54,0xa957dcb4,0x1a6ad5fb,0xe7ab662c,
  71680. 0xf7c36a20,0xd135e381,0x9baa0b6b,0x42e7980c,0x94e4671f,0x4237030c,
  71681. 0x8b0922e3,0x24cc63ff,0x445a589f,0xd10d5279,0xa870ff6c,0xbb99d316,
  71682. 0xa996c195,0x390c83ca } },
  71683. /* 62 */
  71684. { { 0xffc4a73f,0x50d3fa82,0x3bd53303,0x2665d635,0x264bb77d,0x80a06f8a,
  71685. 0x22d73d84,0x81c04a6e,0x0323b8aa,0x2409cff5,0x8c4c4d5a,0x31dce217,
  71686. 0x0c0f9c19,0x374aa80e,0x00186bb8,0x0b25a387,0xaaf1487f,0xd0b77a10,
  71687. 0xab498de1,0x15f39ad5,0x1aa0c116,0x92e32da6,0x96e25ce8,0x228e3dbd,
  71688. 0x5e8646d1,0xb57c88dc,0x267b1c68,0x672b1164,0x600bdec5,0x5d0d807f,
  71689. 0x223e573a,0x3ea4007d },
  71690. { 0xa595d0a3,0xd76debd0,0xaff0b3b4,0xa6bd76cb,0x9b1bdb97,0xbf2c154f,
  71691. 0x4c714c71,0x62b19ab4,0x221af663,0xc9bf33b9,0x8c941ef6,0x23d87c49,
  71692. 0xd79f0f6d,0x255804c3,0x2a7acbc1,0x6f1a1005,0x550528af,0x5dab79d9,
  71693. 0xc8d16213,0xfd77a6f0,0xde5e1029,0x40508b6d,0xf95da12b,0xd95ac0f2,
  71694. 0x758a8ba1,0x8860af71,0x7160c8fb,0x0b194c83,0xce004d34,0xa40e6c80,
  71695. 0x6b14aaa0,0x09f82a17 } },
  71696. /* 63 */
  71697. { { 0xc21366dc,0x60abe588,0xaf75daf9,0x729c0a4f,0xacb93ed4,0x70501fd9,
  71698. 0x87a16d70,0xb97e744e,0x98e7361b,0xa42e0a7a,0x28b54cf3,0x1acdaff2,
  71699. 0xb7bd9078,0xf087ccbb,0x663250e7,0xda6f3983,0xbaf07c09,0x66d693ee,
  71700. 0x8cbaf157,0x79baf4c3,0xdfca99d0,0x5a984e07,0xf26d8dab,0xab4d3247,
  71701. 0x7eba36f9,0x4d0be701,0x0e8dd216,0x37bb9e65,0x531c4f03,0x72aa4e24,
  71702. 0xb753d85a,0x77d1e984 },
  71703. { 0xd8e62367,0xd9373239,0xb9820cf1,0x3361848b,0x5a9c97c4,0x00c7e344,
  71704. 0x14f960fc,0x9a0ec9ae,0x740474b5,0xcf41f0cf,0xece065d5,0xa5eede8f,
  71705. 0x9e808610,0xb1de5a4e,0xae0cf75d,0x17c44ae4,0x6b148d0b,0x2fa56323,
  71706. 0xd29ff2dc,0x64fa740f,0x88cb212e,0xc605eb8a,0x6a863016,0xf2c771ad,
  71707. 0x607b4c17,0x6d6112e7,0x40d49785,0xfe90ec07,0xe256e0e5,0x599be18b,
  71708. 0xca54adb0,0x4e6eabec } },
  71709. /* 64 */
  71710. { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41,
  71711. 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7,
  71712. 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b,
  71713. 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5,
  71714. 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1,
  71715. 0x04ecf056,0x325d2796 },
  71716. { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1,
  71717. 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153,
  71718. 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c,
  71719. 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9,
  71720. 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e,
  71721. 0xe32a79d3,0x19d48546 } },
  71722. /* 65 */
  71723. { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0,
  71724. 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea,
  71725. 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df,
  71726. 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634,
  71727. 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d,
  71728. 0xb4e453b0,0x1b3ace6c },
  71729. { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35,
  71730. 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630,
  71731. 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824,
  71732. 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387,
  71733. 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64,
  71734. 0x192f0a14,0x538ec33e } },
  71735. /* 66 */
  71736. { { 0xa19b56cf,0x193496fe,0x7bb99acd,0x663d77f4,0x57d0a881,0x8f04afa8,
  71737. 0x082835fd,0xcced3da2,0x5d82cec7,0x7e21faed,0xf8009c85,0x6e175b99,
  71738. 0x2d05a307,0xd9c6e31b,0x81487d82,0x96948d4a,0xd46f6655,0x86ebd3f2,
  71739. 0x773ccc49,0x86851aa8,0x8b1640a6,0x3e220f22,0x41a20b75,0x9f06e3a8,
  71740. 0x90ac0a6f,0x2cfffe5e,0x8ebeb3fb,0xf5a9b1da,0x6e08e2c9,0x2587d997,
  71741. 0x03e9f401,0x6fd60298 },
  71742. { 0x8eb7516a,0x54709f8d,0xbdc598ab,0x83058a74,0x87e801ce,0xd234dd98,
  71743. 0xd17b8a96,0xfd0f9d90,0x6e90f6ab,0xaa1e549f,0x5a7ed55b,0x2496ff80,
  71744. 0x6c254c19,0x0d9f657a,0xb8962575,0x3cdea49c,0x2dff27de,0xb685a3f0,
  71745. 0xdb8bc04b,0x3c50e7fd,0x987236b0,0x904ff0ff,0xbb0d5055,0x494298fd,
  71746. 0xe14be8d0,0x34b3386d,0x7c3d30d6,0x7ad34e9c,0xe159fdd9,0x1f2b32bd,
  71747. 0xc761e5c0,0x84cfa23c } },
  71748. /* 67 */
  71749. { { 0x8b99b964,0x13bc11eb,0x58e2fc47,0x8e280c0a,0xd4c9a54b,0x870fbc49,
  71750. 0xbf6e20fa,0x37a334a2,0xd7c88cfa,0xee583d0d,0xef4af1da,0x05e029a8,
  71751. 0x0c2ef8a6,0x6d55e234,0x209e9b62,0x61b6fdfe,0xbb8e080f,0x3b1dad26,
  71752. 0x9392fc1a,0x5adbc162,0x0aae3f4e,0x02ac0fe6,0xc2bf4d5b,0x8d99801a,
  71753. 0xc282fed2,0x2333f93f,0xb52db33f,0x16dcb10c,0xc55752e7,0x09f90f84,
  71754. 0xc84a0d8e,0x287d4c51 },
  71755. { 0x0e9867da,0x5fa58201,0x1a874cda,0x614589b3,0xfbdee22e,0x005e27c5,
  71756. 0xe612bda8,0xe357fef5,0x2d3635f9,0x4e0dbedf,0x6f125a86,0x62be70e4,
  71757. 0x0d94a2e5,0xa09b9884,0x28b5e5d1,0x7eb99a15,0x751028b5,0x21b9416e,
  71758. 0xe06d2cc4,0x1b137fd7,0xfea09845,0x6fa1f517,0xffcecbd7,0x3ba1e966,
  71759. 0x832f453e,0xd4c89a4a,0xeca68fa1,0x07b1e2af,0x4bd395a3,0xd0fb4453,
  71760. 0xd8ef9e13,0x0132a3dc } },
  71761. /* 68 */
  71762. { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8,
  71763. 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699,
  71764. 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984,
  71765. 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32,
  71766. 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076,
  71767. 0xb6f8aa25,0x13cbee76 },
  71768. { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23,
  71769. 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492,
  71770. 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e,
  71771. 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50,
  71772. 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c,
  71773. 0xe02e8967,0x4e0a1ada } },
  71774. /* 69 */
  71775. { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67,
  71776. 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198,
  71777. 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7,
  71778. 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d,
  71779. 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6,
  71780. 0x9f99c999,0x733e30d9 },
  71781. { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7,
  71782. 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a,
  71783. 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a,
  71784. 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0,
  71785. 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492,
  71786. 0xb79a5c0c,0x56facb39 } },
  71787. /* 70 */
  71788. { { 0xa3018bfa,0x019165a2,0x9ffad984,0x100c6b24,0x55341a9b,0xbbf1b1f6,
  71789. 0x25dc4cc9,0xe6bd1d97,0x2bfffe60,0x52850ed5,0x7e5509ab,0x24e992cc,
  71790. 0x4ceb59f1,0xff6c502e,0x1aa7d148,0x2f0b3573,0xe7e3aa46,0xe90c1ddd,
  71791. 0xd1142880,0xbaec9f45,0x65be5dd5,0x475cfd26,0x1febce13,0x83abb14e,
  71792. 0x80942d30,0x6aba4829,0x297e82c8,0x1e1b235d,0x50d8218d,0xb771cdbe,
  71793. 0xd94d6cbb,0x88599266 },
  71794. { 0x155ccaf2,0x08847290,0x7c5b773e,0x8679ebc7,0xb2dd08ed,0xa88b2dd1,
  71795. 0x87d475db,0x960a180e,0x6694d02a,0x80fdb6b7,0x3f3f9e96,0x3e8758c9,
  71796. 0x4ad836c4,0xbda3f6fa,0x32fb387d,0x9400c581,0x2550200f,0x25a78542,
  71797. 0x776ecf18,0x2a97c351,0x566db59a,0x03ebf46e,0x26545eda,0x4743a280,
  71798. 0xcf74ab44,0xed169d84,0x88cb3f69,0xbaab931d,0xd8257196,0x70ae932c,
  71799. 0xa0c09719,0x797224a6 } },
  71800. /* 71 */
  71801. { { 0x441f3567,0x632923f8,0x2e24bf1d,0xc11c3168,0xb7671fff,0x4b97726b,
  71802. 0x7a5e1a22,0x601746a7,0x3addb417,0x53dddea0,0x7f59b846,0x57867a3c,
  71803. 0x56cd7ff7,0xb012a987,0xf19ba9a8,0x1bd5fec9,0xf8306748,0x750379a2,
  71804. 0xab8c05d1,0x7763445d,0x7903f42a,0x5d7f441b,0xa903e46d,0xc011674d,
  71805. 0xadd126c1,0x1b1d3c4d,0x61455b40,0xa2752aac,0x555c356e,0x4da42a68,
  71806. 0xd820852c,0x3ff09c15 },
  71807. { 0xf9cb7784,0x4c0a1bce,0x2422f305,0xaec539bc,0x0c414aa7,0x5f40f9fd,
  71808. 0xffd42bc4,0xd3aa316c,0x2f358e15,0x42f5a4c3,0xd6e27682,0x00bdcd9e,
  71809. 0xf8a5ecee,0x069f789f,0x05e14f5d,0x8078018e,0x8b40c741,0x2bb3e493,
  71810. 0x7917f72d,0x5dbc8c1d,0xcc57150c,0xe0eea664,0xc3fa8920,0xa25ecc5a,
  71811. 0x1c797164,0x3c21b0f5,0x634ad16b,0x8f09a2f2,0x58391d9a,0x8e730fc5,
  71812. 0x4fdfae4c,0x47ef1805 } },
  71813. /* 72 */
  71814. { { 0x3da285e4,0x9965f3d1,0x3a01e3f4,0xba7d4dba,0x61214ad0,0x4738413a,
  71815. 0x22397549,0xd3b7d535,0x5a730b92,0xa53dbdcf,0x332d165d,0x3130d92b,
  71816. 0x82f97ef4,0x44a28541,0x44dce1b6,0xbf62221c,0x7e2a0ec9,0xbba13858,
  71817. 0xcbfad998,0x33f32c8d,0xb5fed44b,0x409e5f3f,0xc66217bb,0x5c328c65,
  71818. 0xfcdf71a9,0xb00db69f,0xb8920788,0xa23c2a21,0x3ae6464b,0xf8ab28e6,
  71819. 0xb8de0861,0x1a6b6e9c },
  71820. { 0x06af77aa,0xaf6ec2b6,0xa887f065,0x2e60f5cd,0x9f498c56,0x87d21400,
  71821. 0xfcbaaf4b,0xdb595b59,0x271ab855,0x0fb592a1,0xd4349b0c,0xa0ce10e5,
  71822. 0x887d8c9c,0x9d6187d8,0x154bd6db,0x03ee95f9,0x5d06c999,0x8fe53213,
  71823. 0xfb6a64d0,0xf4a7bc30,0x66a4cb60,0x3d22af0d,0x5d37367c,0x16952cef,
  71824. 0x997d8e55,0x6f0ea734,0x731732d0,0xb447c70f,0xa9cb3942,0x00ab3034,
  71825. 0x28510fd0,0x79dd0180 } },
  71826. /* 73 */
  71827. { { 0x3ac7424e,0x04e0033a,0x60fda4d0,0xdb06b688,0xbcb772fb,0x236a9766,
  71828. 0xf297cda4,0x294a8e2b,0xdb013c6e,0x4b0aab85,0x8723a3ad,0x3d2aec98,
  71829. 0x13c84a6b,0x0cae32cd,0x70ec169e,0x21888f5e,0x42a88262,0x739633bd,
  71830. 0x7b60d9b8,0x68ac792e,0x10769fe1,0x89f2b722,0xd24bed34,0x8f3fcfe6,
  71831. 0xa3eb24aa,0xd35efb88,0x484c706b,0xddecfa3f,0x929ece0d,0x7cc119a9,
  71832. 0x8d405436,0x87e5ad45 },
  71833. { 0x7d1000a7,0xba99aa9d,0xae823833,0x8b94affc,0xdfb83dc5,0xc8229628,
  71834. 0x845a418d,0x2f59fe11,0x5d417054,0xa8b970f8,0x72b71581,0x8918c265,
  71835. 0xc0d1dd17,0xe4ef477d,0x3afad7c0,0xb50b4cf3,0x01870a5b,0x21baea79,
  71836. 0xbb3a2868,0xc77087f9,0x124a59cd,0x7857531e,0x57f43239,0xed74c26f,
  71837. 0x0164c94a,0xd5f5ae25,0xf094bf74,0x6608b7e2,0xfdceea32,0xf4cdb5ba,
  71838. 0x990cc045,0x0b712519 } },
  71839. /* 74 */
  71840. { { 0x88d5c64d,0x5a290ca1,0xa7492534,0x0596d749,0x2a00e925,0xa04b0d3d,
  71841. 0xcaf7b66b,0x082cd02c,0xecdded83,0x912b50c2,0xff31646e,0x813ce9de,
  71842. 0xc75fff95,0x62ae70c7,0x7e2a4615,0x6f6852e0,0x03804fd1,0x320fd7d0,
  71843. 0x8218e8d9,0xb1a2a4dd,0xafc645d7,0x4918a6fb,0xe8d9fdbe,0xfb080fa1,
  71844. 0x4470b6ee,0x33d4d08a,0x6d974ef7,0xd2ba2077,0x69dae5d2,0x8ecb95a7,
  71845. 0x7d69596d,0x7a3f423a },
  71846. { 0x9a929387,0x362d2ca6,0xcb1c1fff,0xabdb7581,0x7e51b6cb,0xd892ec9f,
  71847. 0x3a4e131f,0xee8d8632,0x5bd87561,0x4680e3f1,0xd4e7e732,0xe3a597e1,
  71848. 0x5581fefe,0x3cc72b7c,0xca8cae0b,0xf3e77f8a,0x5e2fd4af,0xfcc7d7dc,
  71849. 0x21355b79,0xdd3a4552,0xa2c07177,0x546b24f2,0x0689621f,0x415b532d,
  71850. 0x3f78163e,0x2be9af51,0x33d7ed21,0x27d63b9b,0x96802943,0xab019ef2,
  71851. 0x1623faf4,0x2da5fc55 } },
  71852. /* 75 */
  71853. { { 0xc8a5c600,0x62429cf3,0x3fe33e7c,0xa7a80c22,0x0a57ddcb,0x9ffda740,
  71854. 0x925b0c74,0xd1ae156d,0x6b100eb0,0x097a43f9,0xef943c81,0x169e945c,
  71855. 0x1128cf24,0xa1f734e5,0x419f0133,0x04387c4a,0x01044024,0xc007868b,
  71856. 0x90359cf2,0xe5416abf,0x478d54e3,0xf9c76fee,0x42a2173e,0x66219da6,
  71857. 0x9fe30141,0x61e03156,0x93ef247e,0xa0ff5ce3,0x072b6592,0x811792ba,
  71858. 0x70c854d3,0x855f0219 },
  71859. { 0x847314c4,0x61fbfb6c,0xeb45b96a,0x97906155,0x6ba2afac,0x7102e146,
  71860. 0xab949781,0xed51f975,0xc110c4fe,0x9d2f5b17,0xaff57667,0x7ac8ce70,
  71861. 0x6eb244e7,0xe7366a21,0x551c65c7,0xdd1bbcec,0xe1a859de,0xb525060a,
  71862. 0x8ba7d2e7,0x7a048174,0xab8ea8c4,0xe1a2c541,0x6fdff078,0x6e7824c3,
  71863. 0x14874b04,0x79b49fc7,0x06b1f733,0x22ae337f,0x6f8fe6cf,0x1c352192,
  71864. 0x525d0797,0x292236cf } },
  71865. /* 76 */
  71866. { { 0x7d8b29dc,0xcdb8d80a,0x08ea648a,0xd17a2024,0xae92be91,0x7db12c5e,
  71867. 0xfda72fbc,0x1f347d18,0x9e760c6f,0x11374b40,0xd8e38d91,0x7361e8f1,
  71868. 0x739ac1f4,0x7714be9d,0xb4df5c4e,0xc1f9701c,0x6f72cae1,0xd9138ed8,
  71869. 0x6ad180c4,0x1c7fe1f7,0x9e2dbf9c,0xf8c185be,0x7c70c44d,0x835db269,
  71870. 0xb0d15b5f,0xf997cfea,0x61e6545e,0x5101445a,0x25184e5e,0x16b06884,
  71871. 0x7521e7aa,0x7cfac359 },
  71872. { 0x3c0bc53a,0x81182167,0x7e751367,0x84b5ede3,0xa3657a18,0x3ca255fd,
  71873. 0xba1fdd98,0x096abbf4,0xc5da77d8,0x9ce8369f,0xaab342c5,0xf27b9ae7,
  71874. 0x972059f1,0x06c91bd6,0x914ecfe9,0xee0dab30,0x93f53f12,0xbb647fbb,
  71875. 0xffa57e0e,0x30c38a7a,0x9f2ad607,0x517d06ef,0xbb99dcc9,0x49728d87,
  71876. 0x446080a1,0xb0034af1,0x12b9c17d,0xcc810c3f,0x772a22a0,0x7225f14f,
  71877. 0x1ddf82bd,0x6ce3dc7f } },
  71878. /* 77 */
  71879. { { 0xa4397830,0xc07cd835,0xf4733306,0x4dd9290c,0x29989e8c,0xdd35d3a8,
  71880. 0x563d8152,0x79902559,0xe87de61b,0xf278d911,0x1024e35c,0x9c7340c7,
  71881. 0x4a0d0e59,0x2d444461,0xf32626a1,0x63e7608f,0xc4c9baa9,0x627a37e9,
  71882. 0x76fffd25,0x0c56dc51,0xcef2a1cd,0xcb6defc8,0xefc559d9,0xcbcc0d56,
  71883. 0x041cb692,0xe45f3fc5,0xe5161e09,0xcd05c239,0x5c3b559c,0x2a731ee9,
  71884. 0xa3d0a16d,0x85151122 },
  71885. { 0x86ff19e2,0x782d0335,0x1da28603,0xc2c60daa,0x557c7eed,0xb2e78cfe,
  71886. 0x1bc4e8b0,0xa8f6f984,0x3df35c67,0xcc1f9b4b,0x4764462a,0x96e13603,
  71887. 0x7c7ae0b0,0xbf910b97,0x51435956,0x27c7f305,0xf631eae5,0xc14db15c,
  71888. 0x7e69b34c,0xa51d6142,0x5fc12ff2,0xdec82851,0xfb887162,0xfcceae13,
  71889. 0xde1488bd,0xda332ac1,0x2ee3e74c,0xa20374e2,0xf0ae069c,0x597ea1a1,
  71890. 0x77bdec04,0x8b1159f2 } },
  71891. /* 78 */
  71892. { { 0x2f961d30,0x4af71a44,0x7ac7248f,0xbdf968a8,0xb1a906cd,0xd32df87c,
  71893. 0x04abf925,0x00c10e26,0xb9f04d4c,0xb8711759,0x939705da,0x00d54e60,
  71894. 0xc9f80849,0xf7587433,0x6a7a2375,0x2e9abade,0x94ac17ac,0x5676d478,
  71895. 0xc202d99c,0x4ca0525b,0xabfae73d,0x95b8bcad,0x3405991b,0x2371ed38,
  71896. 0x458a99c3,0x2b69e47a,0x2b78c866,0x7cac0b18,0xe0232c7c,0x6ceaa79b,
  71897. 0x588f7459,0x0bd86433 },
  71898. { 0x7e734189,0xdea1a8b4,0xcfe5fa17,0x52c5ac88,0x11437664,0x444a4d4e,
  71899. 0xaf9e9750,0xc2522308,0xd30c6b3b,0x78b1d0c3,0x4c6df477,0x2edae5f0,
  71900. 0x2ee88dd7,0x53131d9a,0xacc93e34,0xc4e380ee,0xa8db0e8e,0xd499b1ac,
  71901. 0x7f5d49d7,0x77348c16,0x1556ccd7,0xc9663257,0x2611d13d,0x65ce0e8c,
  71902. 0xb5a2fdcc,0x2c95fe66,0x8658faa1,0x26698832,0x31c32c98,0xda87d1f4,
  71903. 0xfcd91907,0x46650598 } },
  71904. /* 79 */
  71905. { { 0x6b4a5efa,0x4c6c13cc,0x1d07b265,0xc481989b,0x8bdc69c0,0x10b966ce,
  71906. 0x2c2531d4,0xf54cfaa2,0xcad0a100,0xcb5f1808,0xee5da449,0xbeb52538,
  71907. 0xbedd83cc,0xa6240085,0xd6255c78,0xe792dacf,0x2062058f,0x88371906,
  71908. 0xed1658c1,0x96615e83,0x7d28d542,0x4b549b27,0x83b75df3,0xeaf127db,
  71909. 0x17fbb942,0x4f60df6d,0xf6f7c930,0xd08631db,0x6018789f,0x17c38f98,
  71910. 0xb9a9280c,0x0c43574a },
  71911. { 0x1d20cad0,0x76eb324c,0x8c61108a,0x90decb09,0x6f06d36d,0xa6e9d39c,
  71912. 0xbc0da197,0x6cd978ba,0x507ac5ce,0x5948b1c0,0xc5497eb5,0x2bd47164,
  71913. 0x4d5914e3,0x2a9c4c0f,0xa759f03c,0x772c5046,0x69ac847e,0xe7d7328a,
  71914. 0x3048b330,0xa8d57d0c,0x40f7bace,0xe60034e0,0xa85f1790,0x823d9193,
  71915. 0x5c859736,0xa6e9b66c,0x679e1022,0x22ca2c7a,0x09023fa4,0x00e7a19c,
  71916. 0x2726d5b9,0x324999f1 } },
  71917. /* 80 */
  71918. { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6,
  71919. 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c,
  71920. 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e,
  71921. 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb,
  71922. 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52,
  71923. 0xf18c2b91,0x57ea2b4b },
  71924. { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a,
  71925. 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee,
  71926. 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069,
  71927. 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b,
  71928. 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927,
  71929. 0xea7935c9,0x60480b46 } },
  71930. /* 81 */
  71931. { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7,
  71932. 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117,
  71933. 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5,
  71934. 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0,
  71935. 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb,
  71936. 0x9a8f88cc,0x0774a0d3 },
  71937. { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f,
  71938. 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61,
  71939. 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91,
  71940. 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df,
  71941. 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303,
  71942. 0x2432014b,0x08151954 } },
  71943. /* 82 */
  71944. { { 0xfb7b2108,0xf9236d89,0xad75f9aa,0x3ecc83cc,0xb4e1da11,0xf7c72b15,
  71945. 0x0315c362,0x552aeaef,0xf272fe3f,0x11e140ed,0x87843ee8,0x99d79bf6,
  71946. 0x1d9bb25b,0xce6b54fd,0x5b1bad74,0xb20b0e21,0x5b84c90d,0x54a0214f,
  71947. 0xfca6cec9,0x459bbf52,0x9e4df76f,0xe363c48d,0xd64cf17e,0x3045f84e,
  71948. 0xf62ada48,0x8402a167,0x6a74ca01,0x2c9e1bf3,0xf691c42d,0xe8cf9d41,
  71949. 0xc2c4b874,0x5abf2178 },
  71950. { 0xf3b3bccd,0x4777966b,0xbe3e0caa,0x0047e0f0,0x8c7d5043,0xcb8383b3,
  71951. 0x946fd5fc,0xe77e3baf,0xe9ec0e87,0x79baa785,0xc8a18d25,0xd83c557c,
  71952. 0x25befcfe,0x9b96e5af,0x98c71b61,0x4f05d15e,0x77e62da1,0x081f991a,
  71953. 0xcbaa3821,0x1c6ec781,0xe54d9bfb,0x7522f65d,0x44ed1430,0xf5d05573,
  71954. 0x95cafdda,0x3035b31f,0x6378f5bf,0x47e67f43,0x5270b9d9,0x029f7cad,
  71955. 0x4d916a48,0x15ad1587 } },
  71956. /* 83 */
  71957. { { 0xaa588ae4,0x00de2ece,0xa371a232,0x552ebc58,0x71230444,0xd00ea934,
  71958. 0xe4b1832d,0xafbfa67d,0xb689e843,0x29216341,0x61f4e2e8,0x1f96bbbd,
  71959. 0x04c29dc5,0x95420684,0x42317fd1,0xc7fe3827,0x63483162,0xe0a0aec6,
  71960. 0x0700184f,0xfc2b94d1,0xfe1fbd85,0x07219973,0xfb074352,0x648b6ab1,
  71961. 0xc46e5392,0x23bbdaad,0x00fa56ff,0x0db8dd1f,0x866725f6,0x104815eb,
  71962. 0x52e81963,0x3f9c4cca },
  71963. { 0x32ce637e,0xff36b297,0xf5d25cdd,0x81a15f2d,0x8b02ad97,0x1a1d052d,
  71964. 0xcfbab3e9,0x2e5f3bbc,0x614eeb75,0x60d2cbd7,0xcd5a793a,0xd4491843,
  71965. 0xcdba2144,0x2242cf75,0x88b99766,0xa20705e7,0xec77e132,0x64e12cc0,
  71966. 0xb61a9b05,0xb1c14df6,0x74825b5a,0x8fd97f04,0x3da31223,0x95604821,
  71967. 0x4d30c70d,0xde486727,0x1c12ee69,0xbcab8f15,0x668d893d,0x5dc638b4,
  71968. 0x223f574b,0x6479dad6 } },
  71969. /* 84 */
  71970. { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28,
  71971. 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20,
  71972. 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1,
  71973. 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55,
  71974. 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7,
  71975. 0xf0860497,0x1fe09f94 },
  71976. { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c,
  71977. 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a,
  71978. 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994,
  71979. 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa,
  71980. 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c,
  71981. 0xdb62526a,0x4de95786 } },
  71982. /* 85 */
  71983. { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96,
  71984. 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5,
  71985. 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5,
  71986. 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc,
  71987. 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e,
  71988. 0xe636980c,0x1c94418b },
  71989. { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a,
  71990. 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4,
  71991. 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98,
  71992. 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474,
  71993. 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422,
  71994. 0xb55235ba,0x611bfbb2 } },
  71995. /* 86 */
  71996. { { 0xf00ad2a1,0xbdbaa55e,0x14a290d7,0x29efa85e,0xe92b1694,0x3b4a4768,
  71997. 0x11ec8130,0x67111bcd,0x88bd27b2,0x0e425702,0xd9a03c06,0xf28cf2a3,
  71998. 0xf318884a,0xbb7c8d2d,0xe3aaeb20,0xe2ea1462,0x43b85d77,0x33535804,
  71999. 0x554ee9bd,0x81ee4482,0xe6aa198f,0xeb2eee9e,0xc26c5944,0x7a5aa804,
  72000. 0x82ab167c,0xa0ef2da5,0x02fe21a5,0x5a2ab476,0x3370298e,0x169cb3b8,
  72001. 0x0eb3aa8d,0x86e6c544 },
  72002. { 0x0b793d9b,0xede03321,0x1ddb5ece,0xf79fade1,0x68930b64,0xf73fda92,
  72003. 0xfe4fd1b2,0x06aad97d,0x92a4dc88,0x073a5b1d,0xbc976d75,0x8af8cbd8,
  72004. 0x63ce26c0,0x60b4abb1,0xdcb1fb06,0x9c8300a9,0xda95b3d3,0x335a594c,
  72005. 0xb37eac87,0x1f97d7d4,0x20eefaab,0xa3d2eba2,0xf3e828c8,0x3258c906,
  72006. 0x85ab7781,0xc832616f,0x8c28b617,0x72597192,0x3233b82d,0xcd7196bc,
  72007. 0x19fa126d,0x83867eb9 } },
  72008. /* 87 */
  72009. { { 0x22474edb,0x774fe73e,0x1a84e1ae,0x2a766394,0x9c6dd6e3,0x270329ad,
  72010. 0x14f8bf5d,0x00c4a415,0xd2267b90,0x3ce2ea37,0x11d24fae,0x12753015,
  72011. 0x263a1b78,0x7c14d854,0x1ae0b206,0x20c8401b,0x081f49fc,0xf32a011b,
  72012. 0x959c6df8,0x1e8123fb,0x800e1d06,0xa328dc7c,0x24259a9a,0x5876a378,
  72013. 0xb7ef6c37,0x23ada8b5,0xa93d4c9f,0x023f6b6e,0xffb6389f,0x89f5414d,
  72014. 0xe628b39e,0x4b26bba2 },
  72015. { 0x5d318454,0xd30b1cb4,0xd7436cb6,0x123b749f,0x568a7461,0x3110c726,
  72016. 0x1c84fd1e,0xc85de123,0x08403d55,0xa5f8d6e6,0x9b1fabf8,0x395b6e13,
  72017. 0x3cfedce0,0xfe6d68c3,0x94b91110,0x1d90381f,0x2dcc6eb7,0xf0a8ea81,
  72018. 0x7e90ca2b,0x59e80413,0xc8a25c5a,0xbeb5fc07,0x5d84663c,0x009c253a,
  72019. 0x910b6a7c,0x00b15073,0x4108f8d5,0x8607da4c,0xcb901e65,0x02c3d9c3,
  72020. 0x2c9615c6,0x4d697bc5 } },
  72021. /* 88 */
  72022. { { 0xefa8fb40,0xe0db1ef0,0x5ba3989c,0x29021c5b,0x809d19df,0xa8d6fb15,
  72023. 0x4c1219e1,0x6b787b73,0x14ef05e2,0x6417e168,0x8f9796e2,0x449342db,
  72024. 0xbf84421b,0x2f878a5e,0xe94a4536,0xe71916d7,0xae119693,0x9818bba3,
  72025. 0x5768804e,0xec674be9,0xf8424f8a,0x0a26074c,0x466ce6ab,0xdbc93b9d,
  72026. 0xc920078b,0xb3f15a98,0x3870f1a3,0x9d10fd0d,0xe4e785a7,0xa61241d9,
  72027. 0xe6c8cd80,0x76ca87a1 },
  72028. { 0xe02e48b7,0x4357fb56,0xcc09e9c6,0xfbd14b13,0x24069cf0,0xdb5f2435,
  72029. 0x2c3b01a9,0xf878165c,0xe6956dad,0xe549e7c4,0xbbd60b68,0xf2fe9538,
  72030. 0x059dc653,0x952f856b,0xb377fe9b,0xd3f60225,0xbfe908c4,0x6a0c7328,
  72031. 0xbc8f5f2d,0xce6aa2d3,0x24425050,0xf7213443,0x3d3b3ce5,0x17e1266a,
  72032. 0xc1677512,0x75b5e43f,0x37fb894a,0x15927062,0x2be3e375,0x15260753,
  72033. 0x6da3b7be,0x27e7f2c6 } },
  72034. /* 89 */
  72035. { { 0xe6a15883,0x638f65ad,0x66afdb33,0xd4a7e68c,0xd3f12de5,0x6207b6ab,
  72036. 0x37b87810,0x1c6ff950,0x64acf6d3,0xc0d44cb2,0xf2be78c2,0x163ac601,
  72037. 0x1636980e,0x1c63cc5a,0x95c9349b,0x3e92cfe8,0x41ec7220,0x7738e0d8,
  72038. 0x2d5fa961,0x6169d764,0xc3e028e9,0x2aa776c1,0xb16d5409,0x93dc5646,
  72039. 0x706df4d9,0xa0b27fb5,0xce9c6b97,0x9e991170,0x53c85f40,0xea8e42be,
  72040. 0x83246528,0x02e96437 },
  72041. { 0xae78ea1f,0x91540add,0x7b670e96,0x51a1b74d,0xf7006826,0xf9936441,
  72042. 0x7d7520c7,0x8f97d6ea,0x69ce12e1,0x0faa6a02,0x79208342,0x2590aca8,
  72043. 0x75614436,0x7a483863,0xf381408f,0x07c6149e,0xd7853406,0x733bf584,
  72044. 0x9abbb6f7,0x8761b010,0xf528a09a,0xe4eb249f,0x2e00ae3c,0x08781ed8,
  72045. 0x2178effa,0x864c1b25,0x9d513a7e,0xcc1e62a2,0x1919062f,0xedb8b94e,
  72046. 0x4f16527d,0x739f53da } },
  72047. /* 90 */
  72048. { { 0x924adc5f,0x7a5f4a88,0xa818f56d,0x95646c16,0x7795f954,0x0ec49129,
  72049. 0xd19c5400,0x2b48753d,0x205912b4,0x16fa236b,0xe87a4946,0x6b3d65f3,
  72050. 0x045fd066,0xa7174a01,0x12a5e140,0xb6350313,0xa96b8623,0xa79c4b44,
  72051. 0x9ab003d5,0x7a339d65,0x3826f31a,0xc72f30c6,0x6f7090cd,0xb4e7390c,
  72052. 0x906ebe24,0x59ac6c36,0xbba4505a,0x39a7f06d,0xc58c413a,0x839991e1,
  72053. 0xa20e0e84,0x020c23ff },
  72054. { 0xafc74661,0x120e4ada,0x277fc065,0x37bbcf63,0xb6dce799,0x41049cf6,
  72055. 0x7b161ba1,0x5b8d6b53,0xa9610fb2,0x22218431,0xdfdde769,0xde9ec9d1,
  72056. 0x42d80630,0xd32bfa4d,0x6244df4b,0x3885702a,0x45592dfb,0xcdedd1ed,
  72057. 0xfb4e01b8,0x0e1df45b,0x86e215b0,0x8f4bded2,0x6a937e6a,0x80935487,
  72058. 0x8130f723,0x415278ba,0x38a821f8,0xc6dc4692,0xfd8b4f8a,0x2207b119,
  72059. 0xf9269cef,0x76e7bf53 } },
  72060. /* 91 */
  72061. { { 0x27ebd187,0x5f128428,0xb65aadbb,0x8d3320ab,0x72258695,0xb042765a,
  72062. 0x8f0986ab,0xda3f33f9,0xaebff503,0x411807a7,0x825f71a5,0x25c776ca,
  72063. 0xff7df24b,0xc0de7bed,0x165f1fb4,0xda8b0f42,0x731f3ae3,0x5f3ff737,
  72064. 0x193e0a52,0x4cd1d7e7,0xb6b3ba46,0x8df84aa3,0xaa1f3782,0xba84b897,
  72065. 0xe7733ac7,0x6e7960cc,0x50981a21,0x4d46d6ab,0x7cbb80ed,0x1ec12c25,
  72066. 0x2b96ef09,0x79e7ad27 },
  72067. { 0x8f30caae,0x3cd970dc,0x0a6ebef4,0x85cabcf1,0xc714616d,0x63c1863e,
  72068. 0x519e3a98,0x1c50db0b,0x64cb13d6,0xf39b8963,0x22547b69,0xdf67d81f,
  72069. 0xd67db0cc,0x7157abb9,0x889491b7,0xccca25ba,0x7a27e0dc,0xf689207c,
  72070. 0x0fd43281,0x34ae8fbe,0x5720ec09,0xa5d91f73,0xcdfd7bed,0xb2f61909,
  72071. 0x4a039e32,0x1ec10232,0xdb0d8fdc,0xd3c3d65e,0x4fe5005d,0x32c916c8,
  72072. 0x4c0bea94,0x7f8c37ac } },
  72073. /* 92 */
  72074. { { 0x43ac05e5,0x33ec1e54,0xcd8d3825,0xda4a4da4,0x88bf9e2b,0x86d88c0b,
  72075. 0xb53811dc,0x34d71dd0,0xa3c3aba4,0x655040d2,0xb61611be,0x2bc40949,
  72076. 0x279a4fa0,0x1c2d426e,0x3b065ac3,0x535a5aa2,0xc52ea890,0xdaa8a32f,
  72077. 0x9fddad22,0x5a5deca7,0x2ab3b26f,0x911f05fd,0xf37cd81e,0x5dace7db,
  72078. 0x90d16b8c,0x0e0e44e7,0xe4f5894e,0x15e68aed,0xfc92a74f,0xafe04999,
  72079. 0x970e7c2f,0x1d7703aa },
  72080. { 0x3f0062a9,0xa8a4c81d,0xd96a20ba,0xe31eb2b8,0x864bd101,0x66dd98df,
  72081. 0x4413b614,0xba05f592,0xe9a555f8,0x51a67a0d,0x2e4b52d1,0xacc2f097,
  72082. 0x7184ab23,0xab5daaec,0x7c7f691b,0xce08b43e,0x76c427f4,0x520e530b,
  72083. 0xe423ebdc,0x7d352069,0x34df14ce,0x6b5e39e8,0x446305ac,0x3dcbf295,
  72084. 0xfe34cdc1,0x682cb2e1,0x111f5afb,0xd4ac45d1,0x47f296f9,0xc5ef63cd,
  72085. 0x93c20871,0x0a2c40ec } },
  72086. /* 93 */
  72087. { { 0xaf5747db,0x09bc384f,0xc06ab86b,0x3bad6086,0x9e7c1547,0xa406882e,
  72088. 0x55977abf,0x2d5326d1,0xda81deb0,0x063a9a05,0x524b6111,0x9a86e4a7,
  72089. 0x4ab2eb90,0x1402f87a,0xd5c600ba,0x7d0721d4,0xf289fdbf,0x1a2fd9a9,
  72090. 0xecde6f07,0xf5dce66d,0xdab9fa73,0x62171277,0x6c474bab,0x6d2dc49f,
  72091. 0x76eed033,0xdc017e1f,0x4da825d3,0xb97175c0,0x54b05e43,0x6c297e3d,
  72092. 0x56c9c87e,0x2efb4546 },
  72093. { 0x8b21c064,0xa4712b00,0x4a70629e,0xd186fe42,0x9b74f0af,0x6435b340,
  72094. 0x7ec9e629,0x6965aa43,0xc4c60d08,0xdda14673,0xbf3057aa,0x0b656670,
  72095. 0x3ce86f60,0x7f05e840,0x04401a16,0xc05073a9,0x294e607e,0x16b1e638,
  72096. 0x69cf7046,0x20783252,0xe8ce7d3a,0x2941141b,0x7577053d,0xd38ad8d3,
  72097. 0xcaa6630d,0xdba68fb3,0xe9504350,0xecbeaff1,0x1d2d760b,0x9f5166d5,
  72098. 0x462891e4,0x337532ce } },
  72099. /* 94 */
  72100. { { 0x3a00bb9b,0x3f111853,0x45f66685,0x2d2ffbae,0xd4aee24d,0x9ae11a85,
  72101. 0x0341856e,0x18ba1e1b,0x2731349f,0xa9ac8178,0x545715b5,0xc13dfd4a,
  72102. 0x5daad2ea,0xa5f7423c,0x535b76a7,0x30a483b9,0xff873e9b,0x92e9ada4,
  72103. 0x723a1055,0x15662d84,0x8edac4e0,0xb935497b,0x39d8fa70,0x61b6441a,
  72104. 0x40d1589f,0x1541d756,0xf0a05f0a,0x62994237,0x6bb28908,0xfd8b0034,
  72105. 0xd4cd32bf,0x192a2b5d },
  72106. { 0x365ced07,0x63576628,0x05de1d1f,0x029f32fb,0xbf40a7aa,0x6d17b9bc,
  72107. 0x9bb50a47,0x1b1b2a08,0x795a6278,0x9389abbb,0xb34fc19b,0x52cff60f,
  72108. 0x387d8739,0xf3ab9492,0x6920ccd6,0xa8f053e6,0x63a9b4f0,0x3ef2dd4b,
  72109. 0x51e82129,0x9ab0ede1,0x0838bfa1,0xafba0c0b,0x9ffc11be,0x2bd5a7ac,
  72110. 0x95cc0878,0x058bfd95,0xf8c2f0c6,0x686d48a3,0x1d9b31ba,0xc33abaaf,
  72111. 0x3bc0c268,0x632e2289 } },
  72112. /* 95 */
  72113. { { 0x15a1ccca,0x1c851d20,0x7e522bc3,0x4efe290c,0x18eab053,0x0b741d55,
  72114. 0xbc85e217,0xae656197,0x01cf8b29,0xae13141e,0x66948478,0x2e2cb593,
  72115. 0xc31bd8ae,0xeb57bb0f,0xc264e788,0xdecef5d6,0x9cb96d86,0x6fa856cc,
  72116. 0x279183da,0x2db16813,0x383d796a,0xf03f3820,0x1d0c6fed,0x58a456ff,
  72117. 0x8a6abd9b,0x25589805,0x83f96f19,0x339f52c5,0xda7e9ea7,0xcf6ded8f,
  72118. 0x5d1ccd45,0x68c3d9c1 },
  72119. { 0xe6b392b7,0x67e26265,0x775d9509,0xcec1d9bf,0xd76514f7,0xe16abcd4,
  72120. 0x0de72e1c,0xd86f59b2,0x1adfb033,0xa66e43cd,0x05e457cc,0xdb344340,
  72121. 0x5681daa2,0xb67a7916,0xf0114731,0xc32e7bab,0xd3b1e961,0x066fe16e,
  72122. 0xf63d26e6,0x924e298e,0x541add6d,0x9bea0dd8,0x9982f971,0xef9500df,
  72123. 0xc5f076ac,0x5c876e63,0xb23d396b,0x55e12ae5,0x2ec6747a,0x09efbb36,
  72124. 0x233286a5,0x8f2055ee } },
  72125. /* 96 */
  72126. { { 0xb82c1af0,0x4a4ab9e3,0xf2cae264,0xfc65e9e7,0x60187d46,0x4feaac0a,
  72127. 0xe393b363,0x27d3f335,0x819bacce,0x9c9f7c00,0xb8aa6611,0x3f7418b5,
  72128. 0x372aae95,0xffa94557,0x8db38589,0x937d7804,0x6f1fbc1c,0xd10c86df,
  72129. 0xa2f0a0ce,0x48aebd89,0x367439eb,0xae5d5fa2,0x3f17d2d8,0x103a6a0b,
  72130. 0x411d9894,0xf233f68a,0x218b67a2,0x7fece8b3,0x2319bf06,0x0422540f,
  72131. 0x340d322e,0x1292c8c9 },
  72132. { 0x0386463d,0xf5eb5587,0x0371d97f,0xd4bbc2b2,0x0b819c5a,0x1b364571,
  72133. 0xcf04ad41,0x0cbb42d6,0x66939ec1,0x5d819c76,0xa01847e7,0x8745ac13,
  72134. 0x1c7232e4,0x4f704b02,0xacb05780,0x2c9e58a0,0xb561e295,0x9523b8b3,
  72135. 0x79f9ba35,0x3384df00,0x1eaa9628,0x78231fc2,0x8aea2b90,0xa2eac54f,
  72136. 0x30d1c263,0x8075ed77,0xfb339000,0xacb44ed5,0xf011293a,0x92546ac2,
  72137. 0xeb821764,0x7c78762b } },
  72138. /* 97 */
  72139. { { 0x067902b6,0xb8f7d6fb,0xd1735980,0xb2823a43,0x59741ddd,0x062cfb12,
  72140. 0x4033f95c,0x6e391b07,0x68589b8c,0x3831d0a3,0x522290f2,0xe3474d49,
  72141. 0x222e1f3a,0x4dab14d6,0x53f08d39,0x8f00fcde,0x707f28f5,0x559917ae,
  72142. 0x068e607c,0x166aa0ba,0xd7e1f824,0x602713e7,0x4d6a328f,0x7c255540,
  72143. 0x9890cd2a,0x0d2e3264,0xeca0b20a,0xf2207944,0x52f4e09c,0x5c98dc07,
  72144. 0xd84de81d,0x69403504 },
  72145. { 0xe5407206,0xf8b7b366,0x0d88fa8c,0x1ecf54cf,0xf7272e6f,0x6fefe548,
  72146. 0x81ab4468,0xd6531372,0x4e474408,0x52cb5f0e,0x6490737f,0x9e426b3a,
  72147. 0x4980d071,0x2576c19b,0x0f272caf,0x91f34628,0x468f31c9,0x78e60a4f,
  72148. 0x90844d89,0x8776a329,0xb951582b,0x8a55700c,0x14b1adbf,0xab1af365,
  72149. 0xfbd343ef,0x22ebff92,0xb7d81f34,0x32f9fb01,0xba6b30e1,0xad850e06,
  72150. 0xbc5f9546,0x6da9e027 } },
  72151. /* 98 */
  72152. { { 0x5c9490ce,0x21eee4c2,0x0df68381,0xa96ec4a3,0xa4a9368e,0xe6c607e0,
  72153. 0x4bc262f3,0xd8b0492a,0x460c34ff,0x0846a210,0x28df33cd,0xf7ff7a64,
  72154. 0x21827612,0x10c55044,0x149bcd01,0x9d25fce9,0xcfc613dc,0x725611cd,
  72155. 0x97f51ce5,0x159f7e88,0x4e8c08b5,0x3fa3bf31,0x75e7538f,0xea156115,
  72156. 0x91c84020,0xd1e0a951,0xcf02ad0a,0x0d2268ba,0x058b8e5f,0xa04c6ac4,
  72157. 0xb3515912,0x773b40b9 },
  72158. { 0x3631cfd2,0x00ff2cdc,0x807737bc,0x14c4c2d3,0x338a5270,0xd600616a,
  72159. 0xb32cabde,0xd0e3306d,0xa70b17ca,0x336738ea,0x79f353ee,0xf2f4aa8d,
  72160. 0x576f3ad3,0x712f6ad9,0x89b2bce0,0xe4279852,0xda92ca30,0x05d8f94d,
  72161. 0xd8492dd9,0x9891d475,0x4d15e4bd,0x3e06a5ca,0x254eabbd,0x4725d4eb,
  72162. 0xc0ed513c,0x31394ace,0xbbfaae6c,0x7e0f9859,0x833fd137,0xdc125546,
  72163. 0xc56c4f75,0x12b46385 } },
  72164. /* 99 */
  72165. { { 0x932951de,0x810dbebd,0x5aa69c94,0x96959d42,0xecb2f08d,0x5fc49c04,
  72166. 0x2250b82c,0xac74f0cc,0x3aec4e1d,0x96a439a5,0x90499acd,0xc33cab9a,
  72167. 0x54d9b3af,0x2fccde66,0x3863ae8b,0xf4af285c,0x46febf88,0x2373373e,
  72168. 0x3c9ab7ed,0x751d672c,0xfe12020c,0xc1c51130,0x52f3e56e,0xad82402f,
  72169. 0xa4a64a81,0x3489ab7a,0xd9f163f2,0x0a1fb661,0x0e553317,0x17c69be1,
  72170. 0x7d88d417,0x61c1935e },
  72171. { 0x3492ae43,0x2e722d9b,0x0538f05a,0x1ef89d95,0x200aab63,0xae77e588,
  72172. 0xeba4b117,0x2872c120,0x3a461cb8,0x5c2432c8,0xcb938f26,0x315b3434,
  72173. 0x8c4c7dc0,0x05bf2ac5,0x596b378d,0xd2e501dd,0xcb890c30,0xa8506c9f,
  72174. 0x7c361f0c,0x3d0af461,0x5a35cbae,0x21f7b718,0xf3fc0138,0xbd1035f1,
  72175. 0x8b248edf,0x74628af5,0x48c9cae0,0x8d6421d0,0x2ca18773,0x75e3da39,
  72176. 0x71d3db94,0x27ad0df2 } },
  72177. /* 100 */
  72178. { { 0x305b5aed,0x9e3bda79,0x5998d6a7,0x2c67d4a4,0x0f7eb700,0xc855e1d3,
  72179. 0x147d1c44,0xc18a7e9e,0xc89540ed,0x3ea99618,0x7e6bfd20,0xa53be20a,
  72180. 0xecc14437,0xc9487e64,0x34ef85c6,0x72979207,0xd5e1ebd5,0xfa0d4e71,
  72181. 0x4d48d6b6,0xfda2b1e6,0x66e200d4,0x782a1e05,0x5a5366a1,0x2a3c70da,
  72182. 0x1a473738,0xfe3fbd2b,0x7fe020e8,0xd7ef8c06,0xeacfb665,0xec686fde,
  72183. 0x6dd1542f,0x5d9b5e27 },
  72184. { 0xcb3e472e,0x3637c5a5,0x30a1405e,0x2153d927,0xb4498558,0x009992e5,
  72185. 0xf39a0851,0x18f00ccd,0xb5c6c560,0x26237c11,0x1343540e,0x418ed408,
  72186. 0x7e7f3184,0xfef7cbf0,0xbf48576b,0xecd92366,0xbc94c91a,0x1b75be1a,
  72187. 0x4a162276,0x8e1778de,0xc5c6bcb8,0xc52e57d3,0x5ab71858,0x5cc382c7,
  72188. 0x3f6e39f9,0xe12c2c28,0xd62735fc,0x4c7e0ef2,0x835a5996,0xe071deb1,
  72189. 0xcbb8c766,0x24f891cd } },
  72190. /* 101 */
  72191. { { 0x6778c1e2,0x24ef60bf,0x00d5be5c,0xff49c03d,0x2f01a09f,0xec11986e,
  72192. 0xae096e58,0x59a728a4,0x7077984c,0xaabbcedb,0x870ca5a5,0xfb473bd2,
  72193. 0x4de30e3d,0x8c928c61,0x4f67abca,0x3fae7f9a,0xec21a9cf,0x83c2b2eb,
  72194. 0x9cd9b5de,0xafa70d62,0xc60b18df,0xadeaea59,0x4049b54c,0xd5fef7be,
  72195. 0x6dd310e3,0xfceebc76,0x8f6321cc,0x7748efe3,0x18ee8af5,0xfe9c32b1,
  72196. 0xd42df612,0x863ac3cf },
  72197. { 0xb85a2fe2,0x0a36fca7,0xee429dc6,0xf3e70d08,0x141c3944,0x8c9ba209,
  72198. 0x67272a0a,0x306a8106,0xf968bd06,0xe69a1555,0x153c603d,0xb86f7e47,
  72199. 0xef56e4fa,0x9706614a,0x98780b4c,0xc0dc36b8,0x3a1d3263,0x43657fe2,
  72200. 0x435522c9,0x01f97a86,0xedfef679,0xd91897f6,0x6daa17a0,0xebbe31d4,
  72201. 0x85accfbd,0x6f179100,0x8f9fc1de,0xe0da6e32,0xe1e7142c,0x1c9d53db,
  72202. 0x8b86725a,0x3e3f1b1e } },
  72203. /* 102 */
  72204. { { 0x7b7fbf05,0xb7ea15c0,0x1f1a3882,0x992f11b6,0xd1dcd1bc,0xc9ddd95a,
  72205. 0xad0f7e8b,0x31f5b7fa,0xfca7ab79,0x2936e5eb,0x19a55be6,0x30f417dc,
  72206. 0x43cde554,0x1f6f4e43,0x82f044bf,0x971f5e65,0x4288c408,0x73c3b8e4,
  72207. 0xb807f575,0x61aac59f,0x818b58f0,0xa64ee2dd,0x97a3b0d3,0x6f7a0a60,
  72208. 0x0394b058,0x8b85ecc8,0xbfb3517d,0x9a059474,0xa79c3f06,0x89ad5977,
  72209. 0x700a8025,0x81208ed8 },
  72210. { 0x14c4ce37,0x10935099,0xa1aa48a6,0xf34bb843,0x580d58e8,0x86007024,
  72211. 0xb375b8ba,0x6db42c49,0xed3bde83,0xac365524,0x649233b6,0x5521e1b4,
  72212. 0x64dd946f,0xbc7cc5d5,0xbfb5b6ae,0x9c14b035,0x0146c1a3,0x7f22ba18,
  72213. 0x872214f5,0x0b62fbbc,0xb4921764,0x3acfd7f7,0xcb4d6df1,0x5ff10da1,
  72214. 0x62600a91,0x660e2620,0x81d9167f,0x7ac7da9d,0xb6e7a199,0x6e8e260c,
  72215. 0x80deb3c2,0x44383fb8 } },
  72216. /* 103 */
  72217. { { 0xe44f9af6,0xe107f01d,0x8cb1fa1c,0x36381a4d,0xfb7dd493,0xe65be3ec,
  72218. 0x26a8839f,0xd0b8435a,0x3ec789d8,0xee60f915,0x2bcc5e1f,0xe25fea50,
  72219. 0x7e44a81c,0x0477c0c5,0x230ba5b8,0x349e9f83,0xde180dd9,0xdd42f32f,
  72220. 0x64a3d11c,0x8b039eaf,0xbeb7083a,0x80ef884e,0xf12742cb,0x288e60c4,
  72221. 0x720a0262,0x44156cc5,0x7253b77f,0xcd547de6,0xa6013a59,0x9829a6ec,
  72222. 0x0d548445,0x8aee708f },
  72223. { 0x32c54409,0x18f22d9c,0x75ebaac4,0xa9ebfa46,0x86284981,0x90e2e928,
  72224. 0x6b3a8e0c,0xd0201f6f,0xbd77641e,0xc973016c,0x70170575,0xf926f2f0,
  72225. 0xfec0ce01,0x4984048f,0xf319d304,0xbf696211,0xc91a88c4,0x74b5c844,
  72226. 0xe0030a82,0x4c40fbce,0xe4f6d521,0xbed67525,0x29d67d1e,0xaf7e47cc,
  72227. 0xc21d3536,0xfa307db8,0xbbb29405,0x56b6c46a,0x033e805f,0xf059a7e3,
  72228. 0x6096a5a0,0x970f61fe } },
  72229. /* 104 */
  72230. { { 0x1bec8e4a,0x1bc53d23,0x35a6034c,0x8809ac14,0x509e464d,0x4ee081da,
  72231. 0x8a488235,0x496ae1fd,0x325864b6,0xa1ae9863,0x74cd069f,0xbaca13e9,
  72232. 0xb1d8a6b4,0x3738cc58,0xe76b9da4,0x5fa71f58,0xc7eb16fb,0xc919be88,
  72233. 0xad4e429d,0xf5c8f13f,0x2499f9ed,0x4583b671,0xa10d8bd7,0xbce20115,
  72234. 0x5790bb7e,0xf66d7605,0x482b78dd,0x9316aede,0x75f855fa,0xe0d8fb2d,
  72235. 0x5a7dcca7,0x404b5b94 },
  72236. { 0x517a15c7,0xf9ee682a,0xef880202,0xaae4cfbc,0x5106a354,0xcee2c139,
  72237. 0x170febe7,0x5de60192,0x73d0c54b,0x589e39fd,0x8c9092b7,0x195c7135,
  72238. 0x0a7bfe5f,0xcb7ed53f,0xf61cc979,0x2bd9242a,0x5395f7d9,0x8d2ef16c,
  72239. 0x70b32f09,0x0d4ac1ca,0x52d185c1,0xa587526d,0x942d6195,0x2932b04a,
  72240. 0xa500b0ac,0xfe25a979,0x562fd230,0x5fa1f4ae,0x20da253c,0x60f55af2,
  72241. 0x83146002,0x7faa11b5 } },
  72242. /* 105 */
  72243. { { 0x6e402149,0xb0ba4f0c,0x963cc119,0x3584cc1d,0xa6527476,0x7740dc1a,
  72244. 0xc95715f2,0x3f77ff75,0x3f89fb0e,0xb2f234ad,0xef9be3ff,0x55159032,
  72245. 0x04237e82,0xfc9fb21d,0xa153ed93,0xeb2eff38,0x10041d13,0x89d53ae0,
  72246. 0x7f1bd828,0xcf2e545b,0x43953ea5,0xdd4a27ce,0xd85e75c8,0x00d2e5d4,
  72247. 0x241be1c3,0xeb93ed62,0x0242032d,0x1e53f25f,0xc3a4e701,0xb9957636,
  72248. 0xed98febf,0x14b63a52 },
  72249. { 0x71c43336,0x7610b553,0x23a4824b,0x19dfd4a6,0x0286051b,0x7b97a2e0,
  72250. 0x8f5f1edb,0x86abbb9c,0x9b67daad,0x67a57d77,0xcd5ffafb,0x8ace506d,
  72251. 0x89ac3c63,0x85da9f95,0x75a3d150,0x081cbaa8,0xe9346ed2,0x03353d8f,
  72252. 0xa1f9a02d,0xb2ab61f1,0x3a659c71,0xb0cb0937,0x4f5df8a1,0xb7e0e30b,
  72253. 0xeb7d5a1d,0x77c4c741,0x728e5cf0,0x8f046c9c,0xf7c171ac,0x32dd0bc7,
  72254. 0x836d2655,0x02485873 } },
  72255. /* 106 */
  72256. { { 0x75a4cd8d,0xcd40dd23,0x97bcba78,0x132ca433,0x258d61f5,0x30c5cd84,
  72257. 0xda1e8e68,0x0a7ec059,0x1d65d40a,0x07a8f171,0xf4350d76,0x869e655e,
  72258. 0x5983ae42,0xb98ce6f0,0x9d8bebd0,0x7b61391d,0xb1ba5d49,0x3a529e25,
  72259. 0x1f6b2cf6,0x46f732e9,0x3fa3b629,0xbd66ec6a,0xc3ef0ed2,0x397950ec,
  72260. 0x5f08b476,0xee9008cb,0x965a0e2e,0xfd6be425,0x1177bc87,0x78ed513c,
  72261. 0xfe512dae,0x6798cedf },
  72262. { 0x1b97c5c6,0x49e3f8fd,0x78c3b33f,0x39fbab3e,0x40f595ba,0x44274412,
  72263. 0x5d7d4376,0x174225b9,0x79c44777,0x880b3fcc,0x3296b245,0xdc3aca83,
  72264. 0x1734e184,0x55913df7,0x9c934472,0xa4db23d3,0xd1420a11,0xcebb3733,
  72265. 0xf3608bdc,0xb9d20cf9,0x30cfe13f,0xa618acf6,0x5f30874c,0x75f06b31,
  72266. 0x9f0005a5,0x506efe7f,0x01bfc9db,0x8aaea78c,0xf78e7c41,0xf9179255,
  72267. 0x52e96395,0x3ea7aed2 } },
  72268. /* 107 */
  72269. { { 0x5b06ae25,0x98617e04,0xcb5750ef,0xbcac148d,0x604c2ba2,0x91ea2f0e,
  72270. 0x76b78975,0x00c19f6b,0x651da181,0x79b9b6d0,0xc945705b,0xf3225beb,
  72271. 0x5c005bf1,0x30b435f3,0xbc24d86d,0x440b4482,0xd6373777,0x2b8f0996,
  72272. 0x1c44b4dc,0x65fd6c56,0x30906999,0xe9405ee6,0x08aa1ec1,0x19ff0924,
  72273. 0x3d2f2895,0xeef3246a,0xbc746797,0x016c3765,0xd0705f7e,0x62d2569f,
  72274. 0x05250044,0x6a8ad39c },
  72275. { 0x46be7282,0xe45f020d,0x21380f12,0x9405afed,0xd5da6ad0,0x4cdca5bd,
  72276. 0x7f8be61e,0xc2d6f184,0x596b8178,0x20132953,0x7a8df954,0x8d3b1e7b,
  72277. 0x39572b4d,0x757c61bb,0x80cc3b56,0xd749b57b,0x37b3ffec,0x9590ff93,
  72278. 0x145dc94d,0x39bbb653,0x2335e573,0x70c1c606,0xf763feba,0x9c2e72d7,
  72279. 0xcc61b732,0x4768e424,0xaa73f2ca,0x777d2fa6,0xc5cb58cd,0xdee4dbaa,
  72280. 0x9cfae1aa,0x1a181179 } },
  72281. /* 108 */
  72282. { { 0x77575ed0,0x6f6ff62f,0x7d1da99b,0x18f14fa9,0x69efd7f6,0x2e72aefb,
  72283. 0xddc28633,0xc45ab4cb,0x586c5834,0xb0e20d48,0x39775dd8,0xd397011a,
  72284. 0xf4134498,0x0130c808,0xf5115ed8,0x2d408eba,0x0260ded9,0xc506a05c,
  72285. 0x19cab911,0x9e5b7362,0xe8693a86,0x4cf508c6,0xcc773617,0x4e71245f,
  72286. 0x95d89ca3,0x2f71aa1f,0x607bbc98,0x4bba7c6a,0x212b7fd2,0xf3a515e7,
  72287. 0x9230f5a8,0x7d2ddc75 },
  72288. { 0x4ed2cae8,0x3d05816d,0xb9c00377,0x4cf6bc7d,0x646b08d4,0xc23e98e6,
  72289. 0x4b9c0180,0xf9ee6c61,0xef9179c1,0xe11c9a13,0x8ed9688a,0xa5b6147e,
  72290. 0xd06670a7,0x7afeb648,0x17685275,0xd670333c,0x75f9e8f2,0xa89dd969,
  72291. 0x37a68ade,0xbb57228d,0x454cb186,0x21a05d5e,0x063dd550,0x4810158f,
  72292. 0x4cb6caf3,0x92dd4f08,0x7854abe7,0x70c4d852,0x6e729d76,0x845969dc,
  72293. 0xb1bf40ba,0x5a52f87a } },
  72294. /* 109 */
  72295. { { 0x09ecacbd,0xed019e91,0x7b89bdea,0x6544023d,0x5707371e,0x7cc51f0b,
  72296. 0x16c8e217,0x14832b04,0x81259ab5,0xb1aa6682,0x23e361d4,0x6e100f92,
  72297. 0xe3a95c2a,0xe593eee9,0x16c10e26,0x699b6bbd,0x9473a13f,0xad487873,
  72298. 0xb274987c,0xf1c14dc5,0x2559e2e9,0x57dc0075,0xc3d47ad2,0x8449849d,
  72299. 0xdd527793,0x83df278a,0xeefd5b99,0x770e3ec8,0x76bd02a0,0x2ae58446,
  72300. 0x3e705ffe,0x17f02764 },
  72301. { 0x29abea1f,0xdda4010d,0x2407ac4c,0x636b9695,0x0433218b,0x96a60129,
  72302. 0x163d534a,0xf221fc3b,0xccc20565,0x05ba15be,0x96285577,0x1238e54d,
  72303. 0x878804d3,0x1b144257,0xa89a9fe4,0x96fbf304,0x4be642b1,0xc8a7f06c,
  72304. 0x6e2b085e,0xdd1a20e8,0xff4a591d,0x8f7f27c2,0xa4a343b8,0xc17b0753,
  72305. 0xbb173d4d,0x684b1e88,0x3dc07bbe,0x3accea44,0x4c441d77,0xdb15c88d,
  72306. 0x53e5957e,0x0ef0309a } },
  72307. /* 110 */
  72308. { { 0xfa8e5b60,0x4fc25721,0x691c0bb2,0x646938ad,0x0b0a2248,0xe46d4b76,
  72309. 0x7de16877,0x863f9ac2,0x2721c630,0x503bb6ef,0x0b67fb02,0xf8c199df,
  72310. 0xe07abd39,0x78c1ed72,0xb32f0dda,0xcf9deb7b,0x6c3c89f3,0xaff726f0,
  72311. 0x1972225a,0xb7008b2d,0x4f145f5c,0x8f5a6117,0x457c4f37,0x4e0e6f8c,
  72312. 0x1c453c64,0x8bbdaa44,0xa6e92c80,0x57be326d,0x5d773561,0xa9bc3fd9,
  72313. 0xbb37b72a,0x3d3b6cc6 },
  72314. { 0x9722c880,0x6e6f12cc,0x286b6889,0x3a1b6ae7,0xad2fafec,0xba1cc09b,
  72315. 0x43bb8bef,0xad64ad7a,0x97c3f4c3,0xa5af6a00,0xc353a91b,0x2afcb0d9,
  72316. 0x69ccbf6b,0xca13fcab,0xf2abc190,0x699a1391,0x23a247e5,0x2dbd5542,
  72317. 0x95488d9a,0xe206180f,0x1244cc3c,0xba9e7bff,0x87d3a365,0x29297abe,
  72318. 0xfa4ca5e2,0x4054fa38,0x67be1b6c,0xb390623d,0x78f41a44,0x1fa67c57,
  72319. 0xc7b544e7,0x2e946e43 } },
  72320. /* 111 */
  72321. { { 0xc60934ae,0x2980fddf,0x164206d1,0x2c3e7eff,0x416ed75a,0xf75e7f96,
  72322. 0x5cd0b2dc,0xfac60cf3,0x1faad87b,0xddc4bece,0x9849e5dd,0x753fa87c,
  72323. 0x2c1bf1ae,0xc5d516a3,0x14732b4b,0x565dbea8,0xce48696b,0x007ebe3a,
  72324. 0xcdb97694,0x40ca74d6,0x65e4e7be,0x3f5cd270,0x3aac4ebc,0x74847c01,
  72325. 0x43d6c3a1,0x6762e034,0x467a076a,0x690d8c95,0x1eda677d,0x768d78d6,
  72326. 0x0181d8c2,0x0997ce55 },
  72327. { 0x965a0b81,0x9297746c,0xe5e12dfa,0x48b58be6,0x715f437f,0x5573b3c4,
  72328. 0xb565c459,0xe425e907,0x1582797c,0x4f43f512,0x8ea5474f,0xe5dafa6f,
  72329. 0x13de04ac,0x2aeb8fbe,0xe8a07c83,0xed7f95f0,0x662c09fe,0x3e012a6e,
  72330. 0xc742cf17,0xbf96e9b8,0xe28a1c45,0x8ea5759a,0x5cf4e2f3,0x475941b4,
  72331. 0xf901a019,0x7dd3c02d,0x70916b2e,0xe7a4deea,0x2fa9b988,0x50b272b5,
  72332. 0xd0917fe6,0x96f9f09f } },
  72333. /* 112 */
  72334. { { 0x2c310a96,0x78e8aac4,0xf7a2a734,0x32a98303,0x23962207,0xc46ca83d,
  72335. 0xd9541280,0xad131e6e,0x2cabe911,0x5791fc5e,0x841b6c68,0x50cb77eb,
  72336. 0x3d3c8878,0xaff93dea,0xf1007bce,0x06541f1d,0x55cdf1fd,0x4ee729c2,
  72337. 0x323e3972,0xe0f71317,0xad4d08c1,0xa2de7a41,0xa35e22bf,0xa9912abf,
  72338. 0x89b03325,0xa050122b,0x06514d4e,0x8b9e51f4,0x79d3e0ab,0x423c7aad,
  72339. 0x40b8fea5,0x71998e26 },
  72340. { 0xceb6ed78,0x40140fcd,0x18534516,0x653cf377,0xe8d60dcc,0x0450b65a,
  72341. 0x9dac55f8,0xce6c1a76,0xae05686c,0x8a96a92d,0x12712562,0x2fe44762,
  72342. 0xa4f39425,0x747bcb50,0xfc531fc2,0xf0ec6ff2,0x10fe9ff0,0xc97c3447,
  72343. 0x9c792cff,0xfb488783,0x026fb019,0x552c5248,0xd804c290,0x4001a29c,
  72344. 0x35c8ca73,0x742b5ad8,0x6ee5dfa0,0xc3781f17,0x3dfa4ab1,0xca6b85f0,
  72345. 0x0b0d32ac,0x8389941a } },
  72346. /* 113 */
  72347. { { 0xde067dff,0xc0f062a2,0xbcb80162,0xd4f32690,0x0707a2bd,0x98cd990d,
  72348. 0xfae4a391,0x5afc63b8,0xb32ad814,0x684f1b7b,0xf199dfb1,0xb0a2dce2,
  72349. 0x48f25848,0x2260e17f,0xc2d5e862,0x7393db00,0x338cf171,0x9e88f854,
  72350. 0x02acf522,0x00679429,0x6835af3d,0x19157cb8,0xb8a2614c,0x2faa6f92,
  72351. 0x134ec46c,0x04ff95f5,0xfb7a8135,0xcf00626e,0xb37a4704,0x454b3d05,
  72352. 0x2694ec25,0x1fbfda31 },
  72353. { 0xc8f69c77,0xfdebb657,0xa3df88fa,0x92a8278b,0xc1fb78b4,0x463b5571,
  72354. 0x11c71a33,0xd2066a1a,0x089958b0,0x10c88143,0xcf9d67a6,0xb975c7e0,
  72355. 0x73037b8f,0xdaa5d208,0x40bf5861,0x5ee5005d,0x7dba69a9,0x300e6ce7,
  72356. 0xc962cc74,0x893c3cb3,0x4cf84055,0x0ac98629,0x225c9d70,0x0a7ef63a,
  72357. 0xb91e47e8,0xfe184869,0x8c2f84be,0x1b9d7deb,0xc0e278bf,0x67788915,
  72358. 0xc426f19e,0x4f9488ca } },
  72359. /* 114 */
  72360. { { 0xdd51b8ce,0x610dfcd4,0x36230e80,0x08579278,0x36599562,0xedc7ff1c,
  72361. 0xe2cae877,0x905ead4b,0xe7967608,0xa1c325d9,0xbd38926c,0x3e39eddd,
  72362. 0x5f6f0a4e,0xda92c868,0xf47a0fa4,0xe16f800a,0xe5f60aab,0x50b4db5b,
  72363. 0x983853d3,0x3665412f,0x9b79789c,0x64b62250,0x4e0e72b2,0xea560058,
  72364. 0xe555c2bb,0xabbd4901,0x17292e11,0x378419a7,0xe174218f,0x6e0b5aaa,
  72365. 0x8f796b92,0x688e0684 },
  72366. { 0x313b8f64,0xcdfef641,0x942c7462,0xaef11b7b,0x5c0d8abd,0x067cfb77,
  72367. 0xaf4041a9,0x608ea5f0,0x6935210f,0x23d5bd82,0x27917a08,0x5ab904fc,
  72368. 0x45d22d21,0x85dbb1fe,0x4d36159f,0xc3d5e509,0x1d39b8f2,0xaebb528e,
  72369. 0xf44acef0,0xdd5ca828,0x20c57a54,0x24209adf,0x78f95f44,0x5742b433,
  72370. 0xa9337d37,0xd11fa7d9,0xc64cfdb7,0xd66a0c09,0x9bb817ec,0x56e55b8f,
  72371. 0xe4c41265,0x1723c7e3 } },
  72372. /* 115 */
  72373. { { 0xdc8b43f3,0x9a6486d8,0x26409e68,0xfc3e0e61,0xd9b46003,0x1889c437,
  72374. 0x6284ec7b,0x3a850335,0x6a9dbaea,0x5a3665c4,0xe978933c,0x7bf6941d,
  72375. 0x69341490,0x1ed5a510,0x8cb8002d,0x664a7b7a,0x60ed0a59,0x603f76e4,
  72376. 0x1f4ebf27,0xc3e06ba3,0xf2c38a7f,0x296ced41,0xcf1db08a,0x2ac18f79,
  72377. 0xcde7a3b6,0xc919e882,0xdbf68b06,0x15e77d29,0x4e947cb5,0x21978baa,
  72378. 0x7630993a,0x84bf542b },
  72379. { 0xe364f21e,0xc1decda9,0x012e557e,0x0d6cf345,0x588f90e1,0xba246848,
  72380. 0xe3b104b8,0x9f6dda4b,0xe3aef57a,0x6bf7a346,0xe8327ea9,0x210299fe,
  72381. 0xda95e6c7,0xaa99f487,0xd2cdf645,0x24ff813e,0x8bd414b8,0xd1dbb2d2,
  72382. 0xcafa1a61,0x065101af,0x9cdebda4,0x7d9f4b9a,0xe41039e4,0xaf41b395,
  72383. 0xc50adf42,0xe3e9e6ba,0x341e9e49,0x4f2133ae,0xcb157f23,0x4968c0f3,
  72384. 0xda068153,0x383f827b } },
  72385. /* 116 */
  72386. { { 0x6583ff4c,0x2ec46a21,0x4ad709e7,0x4e645a29,0xc04ca12a,0xdc66e9cf,
  72387. 0x9160a7e5,0x82f128f4,0x569c762e,0xbfb227b1,0xc2edb8e7,0xf80c7963,
  72388. 0x49a0f688,0xa7dafe06,0x2d14b8cc,0xb7e41754,0x86de40be,0x3a0c5c53,
  72389. 0x1db79331,0xf0d05286,0xfbfe071b,0xb902ce69,0x210e9903,0x61e46956,
  72390. 0xf703ebb8,0xfaef874e,0xdd5f78b6,0xf668947e,0x5af5ea3a,0x6fe86547,
  72391. 0x43f94625,0x3b121f15 },
  72392. { 0x659275e9,0x5b26e847,0x6d0fce50,0x47581cfd,0x8aa3f1ef,0x55f5cbfd,
  72393. 0xe484e60e,0x1e7be315,0xfe9698e4,0xd8f1a20f,0x7ab04784,0x25d46da9,
  72394. 0x834cdb3e,0xa526db75,0x8d08a009,0x1fd408d9,0x5b5ca816,0xfc004b20,
  72395. 0x65e4bbe8,0x5b3e3bb3,0x759bb6ef,0xf50cc125,0xc2fac737,0xf05fa817,
  72396. 0xd273951a,0x9ee102d2,0xfecb3367,0x2a8e540b,0x2a6a515f,0x673446fb,
  72397. 0x37290c83,0x5505e1d1 } },
  72398. /* 117 */
  72399. { { 0xd15e68a6,0x0c3014a1,0x64dd35e5,0x6f9f0b26,0x03ad67f9,0x18c3742d,
  72400. 0xd2c14484,0x74818c0e,0x0d41a3cb,0xc5181169,0xc49f3e9e,0x65c8c83f,
  72401. 0x2c279386,0x9b260c61,0xced04e9c,0xf6086fae,0xfd7c4758,0xa7b2cceb,
  72402. 0x90297fd8,0x4b3c3133,0x09701ac8,0xca8264e8,0x508b3762,0x9f976a87,
  72403. 0x983a8dfe,0x5d582714,0xd9d598e9,0x350d2669,0x0f6fd348,0x85cb89cb,
  72404. 0xa574317c,0x617d80d4 },
  72405. { 0x70022b67,0x4cef267e,0x3768b94a,0x80536bb5,0xd2784462,0x3153a566,
  72406. 0x38243919,0x49054d44,0x5df78c4a,0x8d11e172,0xd5a1e35a,0x9b252a71,
  72407. 0x8171e31d,0x07866c80,0x1b38a00e,0x0a8501db,0xce770236,0x2ed932b8,
  72408. 0x8edaf7d0,0xa2d77609,0xb93006e9,0x3aee5dab,0xbbfeb036,0xfaffc8c4,
  72409. 0x4e21b38b,0x077b9678,0xdca8e069,0x491fc59f,0x0e938471,0x3f624f55,
  72410. 0x7cd1780b,0x5156f508 } },
  72411. /* 118 */
  72412. { { 0x0206e8d0,0x58234e22,0x7f15af32,0xf5f6f5d4,0xd638950f,0xafab7289,
  72413. 0x7d4495f4,0x66ec4d09,0x68da80a9,0xad890c5d,0x64f8a36b,0xe4aa0920,
  72414. 0x0f4d5c5f,0x799e257e,0x24495e31,0x44c677ae,0xa5b8e352,0x720387b3,
  72415. 0x75a287b9,0x703790f4,0xc3c1f2f7,0x54895cc5,0x41a7fa41,0xb8680f9b,
  72416. 0xb00b008b,0xfcd47458,0xba6473cb,0x149cc838,0xac9be19a,0x78ed5f7a,
  72417. 0xb33765ba,0x5254599c },
  72418. { 0xa21b54c4,0x08739679,0xb6497d9d,0x029ece2a,0xc8488640,0xf14f1a92,
  72419. 0xe9fa79d9,0xae48dcff,0x46c208db,0x14b911c2,0xdae3f69e,0x5ab0fbf2,
  72420. 0xd1edb838,0x180ac87e,0x188586bb,0x146fd718,0x5467cbd0,0x210eb654,
  72421. 0x1667cfee,0xaa239408,0xb73d1a60,0xdb125c1a,0x881c1cbe,0xde685300,
  72422. 0x37c30232,0xfe34c713,0x6f3c8d18,0xc6c6070e,0xb4af4e83,0x07e365ba,
  72423. 0xdcf82b45,0x22f0a7ed } },
  72424. /* 119 */
  72425. { { 0xea7f1b7f,0xe262791f,0xdcff09d4,0x9c3d8c5d,0x39c7dc58,0x86c2a9c3,
  72426. 0x4276e8c0,0x4dad4017,0xe9fe1d56,0x0a918f59,0x2aa810c9,0xb8d79670,
  72427. 0x4aa5cdc4,0xeb7a8836,0xe7afa72e,0xfc4c23bb,0x4ac86908,0x4dbb5c9e,
  72428. 0x6a0c7e6f,0x37e39013,0x49c218d2,0x855d7001,0x94b324a2,0xe475bc67,
  72429. 0x6287a071,0xc98a8dc6,0x5fb4323c,0x395a299b,0x0c0389e9,0xe186c3ee,
  72430. 0x16734c46,0x79f81e6f },
  72431. { 0x364f3c4e,0x83f2c1f3,0x1367e14b,0x536b2ac5,0x5933e43d,0x44a6dcfc,
  72432. 0x10d961fe,0x34e59475,0x7e3f2aae,0x08234ece,0xbdea7f25,0xcb92e00a,
  72433. 0xa791a124,0x1efba4f0,0x1192d53a,0xc2086fd2,0xb51c8af6,0xfec0d0fc,
  72434. 0xdc0f1b5f,0x48d1b2ca,0x812dbe19,0xb07a388f,0xdedbdd45,0x40873a6a,
  72435. 0xd702589a,0xbc2a1268,0x17e27b64,0xbbf6e3a8,0x6d386e85,0x73ee5663,
  72436. 0x9de7c000,0x442ecd37 } },
  72437. /* 120 */
  72438. { { 0x8a2f90a6,0xb4cd1ae6,0x6f5ad0cc,0xf277d41d,0x401d4b8e,0x6a3828c4,
  72439. 0xd8376631,0xe817a134,0xf5e1124b,0x142b758d,0xfd6b95e4,0x25fbc69d,
  72440. 0xd74a9e3e,0xa30c9f5f,0xd89663ce,0x5ac0f163,0x0ce6386d,0x32a9eef7,
  72441. 0xd8ed5544,0x7a690ea5,0x9889427a,0x5de23ff0,0xeaaced58,0x75ad36a5,
  72442. 0xd3e18465,0x3514a6c1,0x7f093910,0x3d9162c3,0xe33d56e8,0x5c10add9,
  72443. 0x06aa691e,0x85176b73 },
  72444. { 0x28a21e38,0xa32110fa,0x5773d538,0x97b6379d,0x2d020dc4,0xd3697bbf,
  72445. 0x961833cd,0x59177593,0xe5fa8516,0x6d7045fa,0x786ab5d2,0x3390f29a,
  72446. 0xdc4f5b70,0xac0bda30,0xdcc615c6,0xcca0240a,0xc5146d91,0x8e1f1702,
  72447. 0xa72cef87,0xceb472d0,0x0b669ba1,0x84840708,0x7e61aa0a,0x79b08f9d,
  72448. 0x4669560b,0x388160be,0x948eb71e,0x23935c2d,0x9431590c,0xd7fd83c0,
  72449. 0x6e5768b3,0x8ab154bb } },
  72450. /* 121 */
  72451. { { 0x353c4a96,0x28686003,0x905cd835,0x4e5c60e8,0x8f66f8cc,0xbd591364,
  72452. 0x9faccf9e,0xb6b80b98,0xe32639e5,0xbc1c1fae,0x278aadeb,0x2f6396d2,
  72453. 0x1898202d,0x00a796d0,0x3a474835,0x18ab548f,0xb31b0e3e,0xacd056c3,
  72454. 0x0164512d,0x15ba68dd,0x4b03f3bc,0x203836d9,0xd8f206c5,0xd64eca6b,
  72455. 0x9f1779b6,0x931a361e,0x52ab34a8,0xd82690fc,0x92922e22,0x342bb8e0,
  72456. 0xe00b02a9,0x1bfcdd84 },
  72457. { 0x75a365d9,0x310b9a43,0x08d8fb03,0xd4ade15e,0xd742df83,0x9c9753d7,
  72458. 0xde318742,0xcf7309d4,0x3360ace0,0x1228e212,0xf7669643,0x1043d238,
  72459. 0xf90f5a53,0xfc2adbed,0x7b5f9397,0x41d64cb7,0xc446d010,0x5200b30a,
  72460. 0x231720fe,0xc3c8642d,0xb9aa2075,0xfcc0122d,0x041eae47,0x856e3b12,
  72461. 0x68c876a4,0x45864455,0x233606b1,0x1a1c7842,0x227757bf,0x9b766d1f,
  72462. 0xf7b9d4f1,0x25b78a3b } },
  72463. /* 122 */
  72464. { { 0x156707ce,0x90835718,0x4314f90a,0x9bdc2398,0x8be57dbd,0x017c885a,
  72465. 0xad63a4b8,0xd4bba225,0x15aacffd,0x5ce71b86,0x72954722,0x5f266475,
  72466. 0x4f0ad3dd,0x0a80f1f7,0xfc352ed7,0x010538a3,0x4203c6ca,0xf8a64045,
  72467. 0x330c73b4,0x2b2c7a88,0x02dcac1b,0xb3433ee6,0xed2b17c7,0x2e0499cf,
  72468. 0xbd6329c7,0x9f8681a4,0x36fadc37,0x38979946,0x92b7895b,0xdc5650c8,
  72469. 0x65a51cf0,0x70ab9570 },
  72470. { 0x7b585d93,0x46778ec4,0xa633fe4e,0xca6d3610,0x4ea0311a,0x21da154e,
  72471. 0xbd64002f,0xaf22190b,0xd91cb7a9,0x9e633ac7,0xee6837d7,0xed13c31f,
  72472. 0x1616ee8a,0xda4a07d7,0x3afcd616,0xd78a2732,0xba14d694,0xc06696e5,
  72473. 0x4df58420,0x733754d7,0x2778e3c9,0xe85e504e,0x55b5a5c2,0x3055aa0c,
  72474. 0x8a3acb5c,0x313df538,0x2a088eda,0x5896acb5,0x84c85dde,0xfc8842a0,
  72475. 0x51dde6be,0x5fec9f79 } },
  72476. /* 123 */
  72477. { { 0xfe519f99,0x5ebc2c7c,0xe5410353,0xe396bd80,0x8a3988f3,0xaded9402,
  72478. 0xd601bda1,0x1c03b735,0x14ce64ac,0xfd302036,0x01240290,0x5837ebe9,
  72479. 0xa554097d,0xcaaea1a3,0xb0b88139,0xdce73d25,0xecb090b9,0x35ed412b,
  72480. 0xd63dab3c,0x99029ff7,0x062db071,0x555437d9,0x42a4c11d,0x277d2f56,
  72481. 0x24fc9109,0x477fa645,0x2799254d,0x7b12e9b7,0xd84c618c,0x7ad2ae22,
  72482. 0xce8ed195,0x0a8d5663 },
  72483. { 0x0a21fde1,0x43ac5163,0x6903d849,0xcfcf5dd6,0x5fdd6281,0x6d2499ee,
  72484. 0x77a49a34,0x4dedc6f0,0x2875c06f,0x46bda2c0,0x347b8046,0xd0e0e0f6,
  72485. 0x5e67836f,0x1058169b,0xde8a8042,0xc961912a,0xa93b3d32,0xdf3fea0a,
  72486. 0x0c576bc5,0x9f138edb,0xd8d37e47,0x7971ad6e,0xcce5e7cb,0xeab85739,
  72487. 0x1d202b40,0x88a4b434,0xe3a1fd26,0x5d842557,0xb3a86f91,0x872fabd5,
  72488. 0x6aa4629f,0x95b93493 } },
  72489. /* 124 */
  72490. { { 0x99f951de,0x9998a701,0xf058db45,0x8fade596,0xf3d03dd3,0x4d479c1e,
  72491. 0x33b141d3,0x6e928d5d,0xacfe8a40,0x9a465800,0xc1cefa3d,0xd108ad2f,
  72492. 0xe013726e,0x64b96921,0x8e83bb9f,0xb9b6a6b6,0x1242e544,0x29f1e6dc,
  72493. 0x2f65966b,0xd3f8f676,0x5e105b41,0xa34dd096,0x16011e1c,0xd4e9139a,
  72494. 0x2515541b,0xeea4dc68,0xc822166d,0x6f8030ac,0x31d16124,0xbdc7ae1d,
  72495. 0x621afa7d,0x2e25ef51 },
  72496. { 0xdd8e7357,0x2533cf8f,0xeaceddb8,0x333ba218,0x0784d2ac,0x68e3e31d,
  72497. 0xf2804ae2,0x1c927f36,0x77e7ad7e,0x01433d22,0x587f78a0,0x0b401cf0,
  72498. 0xaa0027ae,0x9dfcf036,0x1d9a46b5,0xc9e46c8b,0x1f288d32,0xaa6de486,
  72499. 0x1b8a043d,0xdd56da2f,0xf2d0bb56,0x346230e5,0x19defb56,0x19f0b6e4,
  72500. 0x21d2c874,0x55ec37cd,0xb70e45b3,0x3dbf0397,0xac7ce852,0xf0862a8d,
  72501. 0xe141f3d6,0x87979ea7 } },
  72502. /* 125 */
  72503. { { 0x7f1c747f,0x9b7e7b3f,0xc6e63369,0x151a4c1d,0xb372dba0,0x4273ff70,
  72504. 0xd3ee54fe,0xca6d2234,0xd33cae0f,0x12fc8e0c,0x5dd6f10c,0x27328538,
  72505. 0xf01a9cf9,0xc86f3fbd,0xe36cae91,0x5322677f,0x2fefea44,0x39a70033,
  72506. 0xce8af217,0x2c9ca328,0xf6a731f4,0xc0256776,0x66a96813,0xc687b3df,
  72507. 0x8db2eda8,0x194aab12,0xeec4febd,0xde30dc5a,0x979241b2,0xc052236a,
  72508. 0xc23d4c16,0x3ec98802 },
  72509. { 0x4072f74d,0x0f9e760c,0xab594059,0xe78eb0de,0xc9b009c2,0xdb3dea40,
  72510. 0x38b59ae5,0x47e875f0,0x2b4daa06,0xf40eb436,0x090f3788,0x9a6a4f92,
  72511. 0xedbfaf8b,0xefebe9af,0x9867e256,0xf87f96a5,0x75ab6aeb,0x1e6fed23,
  72512. 0x3fdb13cb,0x17f2782a,0x70fa2621,0x5102c71e,0xfd4c0dbe,0x5d2b06ec,
  72513. 0x30347297,0x537cc268,0x2b67e780,0x8dbf5e2b,0xba25da32,0x2f633f3a,
  72514. 0xefaec914,0x3e9315e8 } },
  72515. /* 126 */
  72516. { { 0x239a9ea9,0x9255cfa5,0x0be33a62,0x20f3c690,0x9cb642bd,0x759eeb4b,
  72517. 0x00bae718,0x3316c546,0xf3410f84,0x874a76d5,0x90f129b6,0x123b502e,
  72518. 0x12851f1c,0xadc8f9a8,0x1b62408c,0xf57b764a,0x1a80777b,0x116ec01f,
  72519. 0x1f0ddc5c,0x746ecef2,0xe5a6a5a7,0x3c49d47c,0x06e955ba,0x1e15dbe7,
  72520. 0xb45d79b0,0x629c0c79,0x778d1087,0x11278308,0x8c6a22d7,0x22585dc7,
  72521. 0x0a682791,0x2ed02a0d },
  72522. { 0x4daa2682,0x53043416,0x01359625,0x0e26d32b,0xbd867097,0x449c834a,
  72523. 0xee77ae2e,0x11a19d2b,0x3af6c169,0x39bd529a,0x5cd61054,0x36cca5c0,
  72524. 0xdc6c0fe1,0x6370a59b,0xb93d5135,0xca420d27,0x554c451a,0xd8730d45,
  72525. 0x96cdebf2,0xebd258c9,0xa50f9a05,0x0cb1b990,0x7b0f0151,0x69a8c97a,
  72526. 0x11d217e1,0x2cc36d34,0x752f75e8,0xf117688a,0xa09b2a61,0x1db01394,
  72527. 0xa9efd7dd,0x14627844 } },
  72528. /* 127 */
  72529. { { 0x232803cf,0x6bca3aed,0x9a96ff34,0xc1e4398b,0x74ab788b,0xcaf6757f,
  72530. 0x7e68c04d,0xc3a53e00,0x5cb7cd20,0x5f969c19,0xdc068bca,0xf28b65a6,
  72531. 0x1d863032,0xe3ca01d3,0x87808e14,0x9b733b81,0xefe618be,0xb5d704d9,
  72532. 0xb01b946d,0x276f3542,0xfbedddbf,0xe057e19e,0x903275ce,0x7d182f2b,
  72533. 0x880f7bc6,0x3cdc5f77,0x78476c14,0xd6f03d3f,0xa9ba5072,0x035f5557,
  72534. 0xb4029628,0x7acb57b6 },
  72535. { 0x44e6b07c,0xd2413569,0xe1c7345d,0x451c4cc9,0xe273b9fb,0x407444d8,
  72536. 0xb88e34fc,0xfe496079,0xf152776d,0x77d184cf,0xc742299c,0x6d1033b9,
  72537. 0x77bf2897,0x29a0a684,0xee8f0420,0x59ffdf10,0x44bb56d6,0x4e17146c,
  72538. 0xfb9ae855,0x831d06c2,0xd93e7cd5,0xb2cb82db,0x3c96b607,0x83381c46,
  72539. 0x7549e2a8,0x06aed251,0x774a21d4,0xef97891c,0x8675fbdd,0xae9807c7,
  72540. 0x6363516c,0x6a5a05b9 } },
  72541. /* 128 */
  72542. { { 0x6a8f4f33,0x92e71ea6,0x4dea8f4a,0xf2fc6fc6,0xfee88461,0xd356252c,
  72543. 0x08954d08,0x59b0a83e,0x468ab766,0x5bd68c23,0x900f8d04,0x40281357,
  72544. 0x52b867ae,0x181c19c0,0x18764c41,0x986a5169,0x13575d24,0xcb01dfae,
  72545. 0x593677b7,0x17269ae5,0x46dc9b19,0xf6d17025,0xc40097c8,0x8de68499,
  72546. 0x259c407b,0x76df0032,0x17d29d8b,0x4091aad9,0x4a7ab5f6,0xa7f46d21,
  72547. 0x70ece48c,0x688054b4 },
  72548. { 0x51a5b86c,0xf0d168aa,0x95777247,0x2437e4d8,0xf1720329,0xae844076,
  72549. 0x9647a54e,0x0a7ac87d,0x0405622c,0x1e597a4b,0xf0a79f2f,0xedefe5c6,
  72550. 0x4d55156d,0xaf3ef0c2,0xef047cf6,0x917fb04e,0x54b62137,0x3792799f,
  72551. 0x314be0b8,0x875ea32f,0x0c466b0c,0xe157c65b,0x7e218978,0xd28c90ce,
  72552. 0xcde587af,0xb90fc3ba,0x8b877bed,0xdd32d71c,0xca8e10cd,0x3b432200,
  72553. 0xd94f6e53,0x0021f419 } },
  72554. /* 129 */
  72555. { { 0x43519d26,0x2191122c,0x40a51845,0xbdafac1d,0x548bb89f,0xcc6f71e9,
  72556. 0x16844bf9,0x9ef3375c,0x178e8d55,0xe7789f79,0x1f8be1c5,0x04f599b6,
  72557. 0x2cbbde40,0x8088c99a,0x893206c9,0x8939a260,0xfcd30851,0xa1ae4bff,
  72558. 0xe08feafe,0x664cb3fe,0xff14aabc,0x61f38099,0x2a841ef9,0x0d8394cc,
  72559. 0x17f01db6,0x75fad8ad,0x6debb773,0x6fc34576,0xa4252512,0x1e716b05,
  72560. 0x29e1ed9f,0x79855880 },
  72561. { 0x95106473,0xa2cb3aaa,0x5a61da04,0x95fafa41,0x539563c0,0xfd3c9362,
  72562. 0x95312b87,0xbaa48091,0xbf885c76,0x6c7e7582,0x230c78d5,0x70f6dab6,
  72563. 0x7747440d,0x8ce3051c,0xffdb6186,0x6dbebd14,0x190e4096,0xb0e041fa,
  72564. 0x6ee62e2a,0xba10c466,0x74f333d6,0x93d57e2a,0xfe7b9b66,0x006aadc4,
  72565. 0x06d2837d,0xfaf72f6c,0x910741ea,0x318cc5e6,0x65692477,0x9c502609,
  72566. 0x1d0fb08d,0x95d823c3 } },
  72567. /* 130 */
  72568. { { 0x140528a5,0x6aeebd86,0x53979bc8,0xf268c2ba,0x4ec144ab,0xb1bc9b8a,
  72569. 0x82a7d7ed,0x1efabb0d,0x4e0118d8,0xf12c70d1,0xa1c1558e,0x31607168,
  72570. 0xe4b7e73e,0x33e428b7,0x83aec9dd,0x63176637,0xe12ac35c,0x5172ffbe,
  72571. 0xbc17b2a4,0x37df0bfb,0x741f812a,0x4212f870,0xe2888f9c,0x3dcecbdb,
  72572. 0x756ca55d,0xa9dc15aa,0xb9028e41,0xf31918ec,0x6aeadb03,0x7ede0285,
  72573. 0x78654f54,0x0e2708d5 },
  72574. { 0xcde20f88,0x2270cc53,0x5f5b1039,0x9338272c,0x5dcb1dbf,0x5042e19e,
  72575. 0xb72d74c1,0x4b3de219,0x2aaaaa55,0x16c49a8b,0xbba86ba6,0x008443e5,
  72576. 0x20cf1695,0xee6bcd72,0xa89abd11,0x59ffac6b,0xf115639d,0x2831217b,
  72577. 0xf34cba52,0xe4d28af2,0x0727a906,0xf27f03e7,0x69017766,0x6842c79f,
  72578. 0x7a81123e,0xcb3469bd,0xa42973b8,0x48c0f346,0x23990dbd,0xfc5784a6,
  72579. 0xfb299678,0x0d3dab3b } },
  72580. /* 131 */
  72581. { { 0xce29c3cc,0x8f8376e6,0xf016cbc6,0xcb0507ec,0x5e394ce1,0xdebff996,
  72582. 0x73c50d41,0x24fc526f,0x2d16ce3d,0x4edd5a54,0x91c13141,0xbb37bdd9,
  72583. 0xe33a8606,0xe3442ef2,0xc0629da8,0x2ae90337,0x592ab331,0x57faec64,
  72584. 0xd82b857b,0x1a938997,0xa3373176,0xad6c8cb9,0x9086751f,0x82595de2,
  72585. 0x18c17196,0xa81e97fb,0xbf697357,0xe4f48a13,0x5cb89f69,0xa1387c2e,
  72586. 0x5874b426,0x530b4eeb },
  72587. { 0xbab7b5ae,0xe9f275a1,0x03a57bf4,0xbb69dc4d,0xa45c505b,0xc974dc4a,
  72588. 0x416ac402,0x726369f3,0xaed985dc,0x735e4e78,0xcdd446a1,0x0548d879,
  72589. 0x9e16b02a,0x84ceb069,0x789b11a6,0xf73f6fa4,0xb2a4e784,0x6aa0c41f,
  72590. 0x93a9b697,0xb1f76902,0xf03a8ab2,0x814cce00,0x844d66c1,0x64cb255b,
  72591. 0x30952201,0xb794e7d6,0x3da32271,0xe052d4e4,0x08b6a4d9,0x5278b2e7,
  72592. 0x80c6577f,0x90942552 } },
  72593. /* 132 */
  72594. { { 0x0d5b4c2f,0xd269a14d,0x5c8a649c,0x2b8fc59b,0xb0e37d4a,0x95becb3a,
  72595. 0x9111037e,0xfda1a768,0x94e35322,0x5810e05a,0xa178fafc,0xa24dcc12,
  72596. 0x8e3dce62,0x5c2c63b2,0x9452c444,0x995c3f17,0x42d45161,0x35330ec3,
  72597. 0xb4ef8129,0xa025a60a,0x8bae9c13,0x85493252,0xe2e3caf8,0x25d1a606,
  72598. 0x3649bf47,0xd44091ab,0x704ec5f1,0xc7d0afbf,0xbd8b3333,0x27bd1d62,
  72599. 0xcfe616f5,0x50570111 },
  72600. { 0xf534356b,0xd0084ace,0x4b4b0fbc,0x9df1de05,0xcee04dc1,0x021afe05,
  72601. 0x361b78e1,0x64bde688,0xef78d38b,0xa324fcc7,0xeb0a5e4e,0xfeb372ce,
  72602. 0x65811996,0xef04fcb3,0x5eb0ab4e,0x7dce5d50,0x238c586e,0x1e29b588,
  72603. 0xbcd80037,0xde5e3197,0x4806b9cf,0x8bf5e451,0xd18e67ab,0x4330968b,
  72604. 0xf9f63fad,0x26a7d04e,0xb5c18bb4,0xa1c7f123,0x25dce22c,0x485b8482,
  72605. 0xd540e79f,0x8ff0b36f } },
  72606. /* 133 */
  72607. { { 0x3ff42cff,0x99f2e2f4,0x1c35317c,0xa3c19f9d,0xaba1b545,0xdb749392,
  72608. 0x4afa9a32,0x84232b05,0xd7dcd436,0x0b855d46,0x45cf9915,0x8ac35e20,
  72609. 0xf001a218,0xd7cf22c7,0xed408305,0x057d35ae,0x553ccfcd,0x25a4a519,
  72610. 0x93e2b939,0x5e565793,0x3422ec27,0xa20332b0,0x3ac53958,0x9b09005e,
  72611. 0x79e9b163,0x628051a3,0xfc6618d6,0xb4a0dc09,0x6748e7af,0x9e0e857f,
  72612. 0xc577d63e,0x71b28eee },
  72613. { 0x99726bf8,0x4942b0cd,0x1c208f3c,0x1290a3b9,0xb0598eaa,0xfd7290e7,
  72614. 0xa25a9128,0xc6a7791f,0xc037d7da,0x2d33db24,0x70e2837b,0xc21efeb0,
  72615. 0xe3dae2a0,0xbf70d96e,0x85076027,0x43ed8191,0x4d4ad7e3,0x4aeb0aa8,
  72616. 0xe8c5b74c,0xbc75101f,0xad26ebdd,0xdbfb2a6e,0x6b78aa4e,0xba812068,
  72617. 0xe1159848,0xc94aa8f2,0x3eba5c4e,0x0d10d9db,0x6318295a,0xce7fec47,
  72618. 0x330d925a,0x7294711a } },
  72619. /* 134 */
  72620. { { 0x32bbd495,0xfce45904,0xbe54973f,0x330f4dd1,0x5d9c3f4e,0x006bee1d,
  72621. 0x59ba7204,0x40ee6078,0x42c2c768,0xc194fd3f,0xe9fe88be,0xa0e76b12,
  72622. 0xec2b0210,0x17cddddb,0x00811ec7,0x689d436b,0x284be9e4,0xa6a6ba37,
  72623. 0x007d4114,0xabc395b2,0x0f11e744,0xf8cdf9f3,0xe9396402,0xc5febec8,
  72624. 0xeeb46285,0x8a751743,0xc6e0d137,0x99bf8782,0xbeb292e3,0x3965e170,
  72625. 0x5801fd5f,0x001c39d8 },
  72626. { 0xda4a0912,0xf4805cb9,0x4410bca4,0xd27cb76a,0xec71d65b,0xef3dcb8e,
  72627. 0x4816849a,0x780fbb2b,0xa8b24635,0xef6a7026,0x12c44e68,0x15625c88,
  72628. 0x4d7a74a8,0x624c232c,0x4b1631e4,0x81a77037,0xdb917c2e,0x04e4f7f1,
  72629. 0x1f61ed95,0x1d0465fd,0xcbde6e3d,0xb1048049,0xd7131fcf,0x637ce0c1,
  72630. 0x8ada4715,0x22e4dbc2,0xace99726,0xf7530c5c,0xee287450,0xa0160dcc,
  72631. 0xbb91af13,0x9132e670 } },
  72632. /* 135 */
  72633. { { 0x7996099d,0x8057efe2,0xa06e608c,0xb72344db,0xd0958588,0xeb4a8740,
  72634. 0x79e5aee9,0xe53daf06,0x908a2fad,0xc9560a9a,0x107e706a,0x7f4be131,
  72635. 0x2830246a,0x6d5f3d9b,0x27cca3e6,0xa5f8e8da,0x4c28f292,0xeb51dca6,
  72636. 0xf31dfd78,0x4cfa310e,0x2ca073e5,0x92e0c7c2,0xa40da683,0x102f1694,
  72637. 0x750d38fc,0x16bb07cc,0xbadae035,0x703e83e2,0xb4d3c9dd,0xea93c066,
  72638. 0x79940ed1,0x7d0b03e5 },
  72639. { 0x4dd94c63,0x5fe7ea30,0x738b0b3a,0x57ef01c5,0xa14e6b4b,0x9534a78c,
  72640. 0xa5353276,0x07622cde,0x7c22d006,0xaf696a07,0x7d46b209,0x733c1886,
  72641. 0x626c2b4a,0x9654ccbb,0xa84f3c4c,0xa098d3a1,0x2d734b74,0x3596f9ed,
  72642. 0x5d551c90,0xdfd3021a,0x1ec5123f,0xe2ba7d2f,0xb2c1aa39,0xf9726925,
  72643. 0xf8eb2927,0xd2e75d0e,0x19192a6f,0xfaba712e,0x9b83e50e,0xa606b43a,
  72644. 0xdab5de60,0x31b1782f } },
  72645. /* 136 */
  72646. { { 0x4034db92,0x878dba45,0x8f34dc4d,0xa3977901,0xdf754c33,0x8d004f2e,
  72647. 0xcd563a88,0xeaa5954a,0xbb5ffad1,0xa29d6c89,0xb0d8bdb8,0xa8adf655,
  72648. 0x8cdbdb47,0xf7fb842d,0x80d3205b,0xb72e3a03,0x7cac7ca9,0xc335b0b2,
  72649. 0xd8a5475d,0xffc60bcb,0xeba4d25f,0x736f7719,0x0c50fca6,0x3d901c38,
  72650. 0x80c01900,0x1fdacf7b,0x5681f84d,0x75cf658f,0x5cefbbc1,0x57a7e634,
  72651. 0x3e07ed1f,0x6fc0fbe5 },
  72652. { 0xb81b0e5f,0x496d116b,0x2ac853b8,0xd82dd2a5,0x327387f0,0x357e22d4,
  72653. 0xba912c59,0x3e332a84,0x49d5dcc1,0x8b71c643,0x438d85d3,0x0c982ee9,
  72654. 0xbf7fcd4e,0x90b9553c,0x38fed5e3,0x2cb39bbc,0x5ac42903,0xa2c67c9c,
  72655. 0xbf07da55,0xebf21217,0xa0b9e4ee,0x55ac05ad,0x8ee9e0c6,0x10bb12c2,
  72656. 0x48bb6e3f,0x5cf3aee5,0x8b046e91,0x4ae7269c,0xaa0e553f,0xcb266012,
  72657. 0xa94c8fc8,0x701935a1 } },
  72658. /* 137 */
  72659. { { 0xa4626dea,0xde58d41d,0x15b9039f,0x25ef66ca,0x3164e65b,0x99a810a4,
  72660. 0x748cfccf,0x9fe6daad,0x2f142fa9,0x7ab9a6bd,0x5d471796,0xa4cba168,
  72661. 0x6bc3a39b,0x12d30b36,0x8bf45076,0x1f46a5dc,0x1421ac0e,0xb868e529,
  72662. 0x59bba1c4,0x7a686206,0xda698b90,0x2b4b552e,0xe5453707,0x5039dcd4,
  72663. 0x9e90165f,0x42a07a9e,0xd7d45dfc,0xa838fff3,0x3b5ceb30,0x41991e5a,
  72664. 0x969ca600,0x6c961ec8 },
  72665. { 0xc4e7eb46,0x703bdc1b,0x596c7b48,0xd6bac557,0x66afd74d,0x4f9917cd,
  72666. 0x656ce6f3,0x56355105,0x32497175,0x3d1fb50c,0x63effb2d,0xfda6783e,
  72667. 0xeefaa2bd,0xbd79f1f3,0x17af9ef7,0xa4efbe54,0x5a55b7a4,0x6cef6462,
  72668. 0x1a713304,0x116f3238,0xb95625a3,0xdb2a2a7f,0x0b027e96,0x6a0aa43a,
  72669. 0x4832b3bc,0x458fe5d2,0x5adfaac0,0x523418df,0xc49e7f9a,0xc05a89cb,
  72670. 0x69e24b53,0x830883d8 } },
  72671. /* 138 */
  72672. { { 0x02557389,0x959b1c62,0xadefc0bc,0x5fe5ce97,0x8330f383,0x893bbe7f,
  72673. 0x16cfb81e,0x27e0c6af,0xd04428fd,0x6f64e65b,0xb79e6182,0x53de9245,
  72674. 0x487e11ca,0x08a313c1,0x445bce93,0x65cec3b9,0xd67ed49e,0x33bc0314,
  72675. 0x30782352,0x69f36b24,0x93ad31d2,0xd78e5daf,0xc780890c,0xf2682b70,
  72676. 0x9e45efe9,0x7015c34f,0xe6cbafea,0x135d4ba4,0x7e3fcc6c,0x43a378a4,
  72677. 0x96638f8c,0x2376f97f },
  72678. { 0xae575b99,0x0a6e1ec0,0x81b970dc,0x7e14cb4f,0xd3a73947,0xf00a3824,
  72679. 0xfb235a9d,0x0b4b9c81,0x5bf62944,0x8d15115f,0x1e165d7a,0xcfd35b43,
  72680. 0xb2ee3e3b,0x5d12fea2,0xf5182e7b,0x629984a6,0xc365d08e,0x4e43e2f3,
  72681. 0x30f36e72,0x99327091,0xfd345401,0x698b4a00,0xbaf96dce,0x23c4fd0e,
  72682. 0x23675554,0xa60ba0ae,0xb0325784,0x51bdac2d,0x215464a1,0x8ab4190a,
  72683. 0x6bf10296,0x8c461661 } },
  72684. /* 139 */
  72685. { { 0x2d1f36a5,0xeffca258,0x894c5f2d,0x0eded2b2,0x43ced84f,0x35a5cdb8,
  72686. 0xdb0e3b9b,0x290f8982,0x0719a112,0xcce0eaf0,0x39a362d6,0xd0e657e4,
  72687. 0x62697e47,0x5516a55d,0x8e636514,0x269e1f77,0xd50269bc,0x5e3dedcb,
  72688. 0x441c57c5,0xecec2300,0xc705578d,0xdb83f31c,0x1e489eab,0x1bdefb73,
  72689. 0x395fcdb4,0x20b678cf,0xff9db001,0x908cf91c,0x55f52cc8,0xcbebc6f4,
  72690. 0xb4c61162,0x155ea622 },
  72691. { 0x876fa42e,0x94be2f1f,0x7fadeee7,0xab5e8749,0x38c865af,0x692e70f5,
  72692. 0xdf8059b0,0x16e99b84,0x8b5a7ac9,0x0ceb606e,0x2d463d2b,0xced23357,
  72693. 0x2a9a09a0,0x2d0f2623,0x3861fbdf,0x2529998c,0xc1be310b,0x711888a7,
  72694. 0x0d8aade3,0x9b1229c5,0x3b13533d,0xdbcf9b78,0xff029708,0x3ca746f8,
  72695. 0xda83ef88,0xa5a013a1,0x4ab28444,0x8e904d18,0xbcbd4aba,0x2fe84b3d,
  72696. 0x259058c3,0x8f570f24 } },
  72697. /* 140 */
  72698. { { 0x2ca9c508,0xdeb66c8a,0x69d6b780,0x2dc5bec2,0x88ead600,0x16d61266,
  72699. 0x49d72614,0x61841b97,0xce472e6f,0x41e40e6c,0x1fa7a876,0xada24264,
  72700. 0xcc3997a0,0x45b9fd33,0x7c15dcf4,0xb25e8fa9,0x12e9629d,0x0124ceb2,
  72701. 0x7db3d956,0x3a8c72c6,0x7c1a7844,0x8e2ded2b,0x6dd027ff,0x94ab09c6,
  72702. 0x7e7a2bc6,0xf89a057d,0xcf70c763,0xad8bf226,0xc8a26212,0x4cb268e7,
  72703. 0xb2c44c1d,0x3d171e87 },
  72704. { 0x8ce49820,0x382ac16e,0xc0c44dc9,0x24ee45e2,0x73e858c4,0x0ec67912,
  72705. 0x46327cf9,0x918cb25c,0xc6159c1f,0x43e3876b,0x37545cb3,0xb6b6e0e0,
  72706. 0x5d12347e,0x64b839ab,0xa300d541,0x72e09274,0x881c1169,0x26ab28e6,
  72707. 0xeb75a843,0x4a580fff,0x359120df,0x0a5802ca,0x3209f4a3,0x7fee82d0,
  72708. 0x8e6a9380,0xb518016b,0xc2ee11ca,0xb99c6c70,0xab9d4ec7,0x16105af1,
  72709. 0x34cd9004,0x234e98f8 } },
  72710. /* 141 */
  72711. { { 0x14db9cda,0xff435208,0x96adec90,0x99cfdc47,0xaf458b6d,0x843aaa6f,
  72712. 0x743eaa31,0x3f1f7415,0x61735d81,0x915e192e,0x0ac595d5,0x3441a22d,
  72713. 0xc044bc8d,0x704bbf67,0xbe23a236,0x2f960471,0x15d1d557,0xcc326388,
  72714. 0x76b1dd94,0x9410230b,0x0c1c8a67,0xf2e5439f,0x833c910d,0x56b141ac,
  72715. 0x865b84df,0x467c999f,0x21f02b7b,0x1b0251fa,0x96216950,0xde5b5260,
  72716. 0xce3a1e93,0x6a2130e3 },
  72717. { 0x4b3ca1a7,0xd21b67a0,0x00c0ce80,0xaf42ed53,0x932cf07a,0x22ccd368,
  72718. 0x5c25c35a,0x36523a81,0x8dd04d06,0xecdd3958,0xb2f93a3b,0x73da3502,
  72719. 0xd5e5b530,0x4c5e0c3c,0x13268777,0xef9f5486,0x1e742292,0xed87fefc,
  72720. 0xa24e5ede,0x6d9ac29e,0x33849f1a,0x08abc9f0,0x40f23905,0xb09b2292,
  72721. 0x7f934353,0x6791072c,0xe6aeb550,0x102a6381,0x96feb870,0x3ee07409,
  72722. 0x9c4d2830,0x34f06faa } },
  72723. /* 142 */
  72724. { { 0x2348f005,0x869dc79f,0xdf4920b1,0x9b5c5d71,0x6dee64a4,0xfd1b57ca,
  72725. 0xe82a4fb4,0x21b7f734,0xb9578366,0x637cb834,0x7d287d96,0xc934101b,
  72726. 0x0392ecab,0x1590f8ac,0x7f75f4e3,0x280dc373,0x6a61ac62,0x8b36f50f,
  72727. 0xa65568da,0x74f58304,0xd930870a,0x80d792a9,0xfc8895cc,0x6d17b192,
  72728. 0x4914939f,0x498392fa,0xd41d5b9e,0xaf36027d,0x5caa82b5,0x452d79e2,
  72729. 0xf4115d1a,0x764d47b1 },
  72730. { 0xa2ee8b9c,0x5df22303,0x85dfcd48,0x1b9f72d3,0x10813a37,0x6b42b983,
  72731. 0x3de741f5,0xe28c523b,0xf303bb5b,0x0857625a,0xac9bf9af,0x926f299a,
  72732. 0x0d445b34,0x21beac08,0xd6ba2c0e,0x6a523a02,0x7fce2864,0xe302a1b1,
  72733. 0xe300c1ea,0x4516a235,0x7b4a9311,0x4543736a,0xc0cc89f7,0xd3c0b9e8,
  72734. 0x40ed88de,0x0481904f,0x3cb7fc70,0x4f269b56,0x321b9738,0x09a1d53a,
  72735. 0x230a3810,0x1c0dd9c3 } },
  72736. /* 143 */
  72737. { { 0xc46a7d9a,0xffaa1f67,0xbedf91cc,0x64743334,0x47a42f2e,0x45833a74,
  72738. 0x241ffaa9,0x67980051,0x335efe6b,0x70979a84,0xf08b2403,0x5f0613f5,
  72739. 0x64f211dc,0x6bb22fcd,0xa0572cfc,0xe1b8b2a3,0x7950a14a,0x19e0eb41,
  72740. 0x3eb6cd4c,0xe634bb29,0x470a25ff,0x31a04b25,0xa3d15a0a,0xa41f7ac9,
  72741. 0xbf2fede9,0xefed85ec,0x81b94a00,0x1f581f5f,0x9ef4a15c,0xaa3996b0,
  72742. 0xb06041bc,0x52d8be39 },
  72743. { 0xfd631a2f,0xbd1536f6,0xb351a8dc,0x91fae7f0,0x9b126212,0xd1a590c7,
  72744. 0x2bd0f435,0x52d4875f,0x92b0ea70,0x9aedb6d3,0xb83ab89e,0x0bd0abdc,
  72745. 0x89fe192c,0x827a1062,0x102a0bda,0x6566a960,0xce036814,0xda083037,
  72746. 0x58639405,0x30bed79f,0xdbca8df9,0x972019b6,0xefdaa3f5,0x89201286,
  72747. 0x5236b892,0xb337b996,0x28fc2e73,0x11d3e38e,0x880e8da3,0x70787f41,
  72748. 0xdae4a45d,0x6cff6367 } },
  72749. /* 144 */
  72750. { { 0xf89a8bb4,0xbd3d0433,0x93b98f71,0x42144c33,0x03470a2d,0x82b616c8,
  72751. 0xe5da089e,0x98fcc757,0x7bf5fda6,0x542354ef,0x9ebd34cc,0x1885c253,
  72752. 0xbec5dd0d,0x2e20b285,0x782a1bca,0xe71bbbe1,0x9b854ef0,0x959ded30,
  72753. 0x8997fa6a,0x17249979,0xd81f3c45,0x50cf8fa8,0x60c11152,0xa9a3b517,
  72754. 0xecf845ea,0xc9b0ef7d,0xb9fed11b,0xc9339e23,0x28256080,0xc93e9c5c,
  72755. 0x613ec1e7,0x1d2c8217 },
  72756. { 0x987cfc93,0x7381347d,0xf187f810,0x047603bb,0x1250ca31,0x3fa6bc9d,
  72757. 0xbb055bf3,0x480091e0,0x3a3af87c,0xbdf95f1a,0x140540ab,0xe2687770,
  72758. 0xd7fe045b,0x998df730,0xb723bc2d,0xb398135f,0x15ebec46,0xac230f8c,
  72759. 0x5f5561c0,0xe08e1830,0xda60a47f,0x7c0fbf4c,0xe16d4bfc,0x06e95c24,
  72760. 0x74617e92,0x74163495,0x4ae0c20e,0x39719869,0x2131e2b6,0xfe269312,
  72761. 0x0a537722,0x25486e36 } },
  72762. /* 145 */
  72763. { { 0x53572806,0x618795ca,0x656968e1,0xb2c89449,0x3fb323ae,0x149c2c97,
  72764. 0x409bc7d6,0xfb15de26,0xc79121b3,0xa90cda72,0x204cabbb,0x6d2fa14e,
  72765. 0x91604125,0xcbcda6f7,0xb435f947,0x25086261,0xc282eb10,0xdb686c38,
  72766. 0xf1a791cb,0x51016d62,0x61a2266c,0x6b1c7ed1,0x271d74a6,0x26780666,
  72767. 0x824287a4,0xb5ffeda1,0xbbe4f0f3,0xcbe503ff,0xb9482a74,0xd7f7f0be,
  72768. 0x088493f1,0x751b2358 },
  72769. { 0xe9c9be68,0xd597b9d6,0x67d10c6c,0x1794b5c4,0x7762b2f4,0xa88cdc3d,
  72770. 0xa1b44e11,0x6d94a63a,0xaaa8eca8,0xfb0bbbb9,0xc963d87f,0xf4b0f2d0,
  72771. 0x5dc7075d,0xb753062c,0x49933989,0xfed726ac,0x57f9ccde,0x5da60638,
  72772. 0x75f8c766,0x221c392a,0x5dc672ca,0xcd264d95,0xb66ecc8d,0x7004ff22,
  72773. 0x18a458ba,0xfb1aa9ae,0x8babd653,0xea9644df,0x2ba0de7c,0xa9378e80,
  72774. 0xca2c6c75,0x144cc12d } },
  72775. /* 146 */
  72776. { { 0x2989aa3a,0x593a0a1d,0x59e6e64d,0xd83f2283,0xd32e732e,0xe938b0cb,
  72777. 0x3c3cb249,0xf4c464c5,0xf89ea6ac,0x9750a5f8,0x346cfc32,0x467e5bbf,
  72778. 0x37b2b809,0xc9bfab9d,0x3b339c6d,0xf8eb7453,0x3b766dee,0x3fe01fbe,
  72779. 0xef6aea27,0xb3154254,0x7be61b10,0x555c3df2,0xdd818488,0x70fb6d81,
  72780. 0xbbe714f9,0xda1af3a4,0x9d18f693,0x575f2017,0x2465b839,0xdc08fc6b,
  72781. 0x6b84a951,0x874ecf33 },
  72782. { 0xbbb3f6be,0x624af83e,0x08bb423d,0xf578fbb9,0xd7873527,0x5623b0ba,
  72783. 0xa62e0442,0xc3659bd8,0xfe236f79,0x2903b167,0xe53f26a6,0x55a430c6,
  72784. 0x3ad712cf,0x222547ae,0x76eb272b,0xb73890d7,0x3d628df9,0x95b4f70b,
  72785. 0x53eae4ac,0x9f0e13b0,0xe7f2174e,0x5b4f5138,0x98dbae17,0x75482cf9,
  72786. 0x44518480,0x2b69bbde,0xcafef15c,0x4f279652,0xb6bcaf19,0xa0a3ef2b,
  72787. 0xce4c634f,0x31fb8581 } },
  72788. /* 147 */
  72789. { { 0x615cd607,0x398306d1,0xaa32c3a6,0x680c9faa,0x7779131d,0xe87a705b,
  72790. 0x36708b00,0x1031013a,0x9445297f,0x814fa0e1,0xa6a79b56,0x70c5583a,
  72791. 0x4b16bed4,0x03039cbf,0xaaaaf8d3,0x18a7ca8d,0x5cdb68a5,0xf33159e7,
  72792. 0xd23814fa,0xdea0e738,0x8d0f4f9f,0xeb352718,0xdcdff032,0xb0b76609,
  72793. 0x3d48338b,0x65ba8ea9,0x55dd507a,0x18044d82,0x4a4a50b4,0x844a223e,
  72794. 0x18e19e54,0x98323000 },
  72795. { 0x57f3d5a6,0x28a21027,0x6e8cadcd,0xffce5648,0x02551f3b,0x9590381b,
  72796. 0x935ebdf1,0xb26cc64f,0xc083aa6e,0x60611291,0x88e4cf41,0xcd988a66,
  72797. 0xdd53b1b5,0x581c3f73,0x77fc621d,0x78c804a9,0xfadca2fa,0x31874330,
  72798. 0xc83ccf02,0xf7008da4,0xa79a4707,0xc4122a1d,0x4a915eb5,0x9a8e0d3f,
  72799. 0xd0123660,0xa2de157d,0x65ead2a0,0x45ef43b2,0x188db285,0xd0a22ade,
  72800. 0x922e0caa,0x8abbe39e } },
  72801. /* 148 */
  72802. { { 0x3a2d2f01,0xb4446905,0x5dc6685c,0xd27c3193,0x1d74a027,0x6a908bbf,
  72803. 0x5b50ec1d,0x01da350f,0x3f3c2e26,0x1d3dd45e,0xb836ee92,0xf66e11d0,
  72804. 0x474b979c,0x7e03908f,0x98b87834,0x19e7c5b9,0xbd3d1de9,0xa741d3fe,
  72805. 0x1ef6059b,0x63c68e8d,0x3674e247,0x9b9ff939,0x3e7e67f6,0x1d7d53e7,
  72806. 0xaee9e248,0x698dc326,0xb3bd984c,0x52f23eda,0x6f8fe8a7,0xf95e31b0,
  72807. 0xc3d0ba95,0x0f15b4d0 },
  72808. { 0x790a8d85,0x8f2f6635,0xe2595af1,0x51bffbae,0x24b51287,0xd15b7ec6,
  72809. 0x3234715d,0x7639b6ab,0x2bc5441d,0x0cdd5299,0xf6d05833,0x54800ea4,
  72810. 0xf6d6e360,0x21efd752,0x19290613,0xc0b7ffe5,0xeea898cd,0xb68a5825,
  72811. 0x22982266,0xecedba92,0xbbd06bb2,0x678a91b0,0x4bb6b0cb,0xb2436dc0,
  72812. 0xcaf8ea98,0xcf7a99e7,0x71aa05bb,0xb92d0e6e,0xf5993eb1,0xbf8d0471,
  72813. 0x20385ddb,0x515db378 } },
  72814. /* 149 */
  72815. { { 0x6f5bef22,0xee43eaaa,0x20348712,0x952d2698,0x7a3af6c6,0x1e4c484e,
  72816. 0x9a8c9403,0x18d434c6,0x5001899a,0x63e5d741,0xfe8ea40c,0x5238dbbc,
  72817. 0x96798721,0xca6cc8d2,0x04acbde8,0x73db6aee,0xb7f993ce,0xbf69328d,
  72818. 0xad45e334,0xa3f79bbf,0x7c1f1630,0x8c51ec93,0x9b00a6de,0x4907325f,
  72819. 0x12d82bc3,0x49e6acb4,0x0ec59fc9,0x5901b36d,0x9cf34e3b,0xcb09b710,
  72820. 0x1abf4c02,0x2de0487e },
  72821. { 0x8dd9d484,0x18b722f3,0x7c77bacc,0x83349393,0x93d92b8a,0x58dbb8f1,
  72822. 0x8e3fac25,0x80d78d50,0x745f4a7d,0xf0500981,0x877cc29d,0xd072bfed,
  72823. 0xc30a89f8,0x67abf8f2,0x9a0820d7,0x92c567ea,0x8a3a5738,0x425ab12e,
  72824. 0xf055521b,0xc162faeb,0xb94ea5e9,0xee1c4f26,0x3d71e546,0x1e414994,
  72825. 0x43e8be1d,0x258183b8,0xef9eae0b,0x44917c82,0x73874a30,0x6813a457,
  72826. 0xcc42f86e,0x6f6ac071 } },
  72827. /* 150 */
  72828. { { 0x4dd6e3b1,0xd38822ad,0xad620869,0xfc78e1cc,0x2cacde80,0xe7843845,
  72829. 0xa8469fe3,0x121cc14a,0xe67e8ef2,0x8e8f3da7,0x4d347448,0xdb83d16e,
  72830. 0x798631f4,0x3ba1dd98,0x0a4c4c17,0xdfab5977,0x3edc701f,0x1f0a1306,
  72831. 0x6cd8ff28,0x4649d601,0xbcc55bc9,0x2267230b,0x5760412a,0x02a19c60,
  72832. 0x328faef6,0xc719d5f1,0xf67eaad9,0x27cb969e,0x719bafb5,0xf342530e,
  72833. 0xff5a82cb,0x6e2c24cc },
  72834. { 0xadaf8793,0x6313024b,0x035c948e,0x944bccf1,0x953500bf,0xe9a066b7,
  72835. 0x1d116765,0x7991a946,0x9fd93c78,0x95addb2e,0xe92e5495,0x05d2c037,
  72836. 0x9f03e5cf,0xcb145b18,0x95aa1f72,0x81ae48ca,0x135a6e4f,0x203f2702,
  72837. 0x49b2a7d5,0x2bcef5a2,0x02d7f2a3,0x0687a900,0x6c6745b0,0x2f7d3228,
  72838. 0x86507305,0x3da8a875,0x2e8dc58f,0xbe38b884,0xdbf11185,0x6b48bf34,
  72839. 0x97c08f91,0x5af7fd0d } },
  72840. /* 151 */
  72841. { { 0xf4a224a5,0x55f9b950,0xcc50273a,0x41904574,0x643f1fd5,0x34f81330,
  72842. 0x0e50f783,0x996801bb,0x89581712,0x866d7403,0xa4091d36,0xdb9a405d,
  72843. 0x16a46fe7,0xf1e379df,0x83bf9168,0x8d04a93f,0x32b20bca,0xae4c8335,
  72844. 0xf72a1c10,0x99d334b1,0xd8195db4,0x8fbc9977,0xfba14b5d,0xcaeb3dff,
  72845. 0x76daf476,0x60fef022,0xdb5b72f4,0x4b948dfe,0xb6dfb062,0x5185c925,
  72846. 0x9609d4ae,0x27a9c381 },
  72847. { 0xf12a93af,0x73c37346,0x5536634d,0x028b707c,0x498193d1,0x8efa58d5,
  72848. 0xef21b69d,0x4f83a5cc,0xa788a0e2,0x05cbb0a3,0x65b13c98,0x01031781,
  72849. 0x2b73784c,0xfea20e58,0xe50361f2,0xdf9713a0,0xd0cc22d9,0x31449a0f,
  72850. 0x7c5e2e1b,0x183752e7,0xb67044cf,0x6e44d6bd,0x733e177a,0x012dde95,
  72851. 0x08ee2c23,0x68b49669,0x1f5f1949,0xd9bb0541,0x6acd886f,0x95182c71,
  72852. 0xfbde9244,0x1c690694 } },
  72853. /* 152 */
  72854. { { 0x3a880026,0x5db67d17,0x125d95f2,0x89c4f0a0,0x3f6cb7a4,0x29050551,
  72855. 0x5cbbdca5,0x3eb231d1,0x972bcbd3,0xf8cffc99,0xad55a03a,0xcb4ef4d4,
  72856. 0x22867c2f,0x944d47ca,0x0ead1aa5,0x96d88548,0xcbc8b045,0x76a57cf8,
  72857. 0x005e55a0,0xdfe5844b,0x1d18a097,0x5e9e7e19,0x52923c74,0x957a26e8,
  72858. 0x7f5db339,0xd0867b79,0x63bed0c8,0x2553408e,0x689ad23c,0x1596e5d5,
  72859. 0xa504c339,0x7b8c13d6 },
  72860. { 0x52fb6901,0x2fc43aad,0x16ca253b,0x1c0313f9,0x515aadc6,0x1475830a,
  72861. 0x7f577dc2,0xc93d1926,0xf723c0dd,0x26e52e8e,0x3eb9f6da,0x2f1e0eb8,
  72862. 0xf180376d,0x9979de82,0xb0834939,0x43e28ecb,0xa39c38e7,0x9a2d51dc,
  72863. 0xa8e3f6b5,0x6e6063a9,0x4b9b3270,0x4cf1da3a,0xd2f8915d,0x6e5348a2,
  72864. 0x50507912,0x5e75e3e0,0x20d383fa,0xaeffce57,0x8fd2fb29,0x1d6d53cc,
  72865. 0x696f4cd0,0x0e3c3ef6 } },
  72866. /* 153 */
  72867. { { 0x21ee1d83,0x3bc337c1,0x787b7788,0x97e08f6d,0x138fa4ce,0xbf709fcc,
  72868. 0xa0348e58,0xbaf77647,0xa55e672d,0x04f8babc,0x7d5ec5dd,0x0ed2919d,
  72869. 0x33e99218,0x8ce64bff,0x24b059af,0xac09fc57,0xdc5e32ba,0x506831f9,
  72870. 0x465af6a9,0x26a22677,0xc97f1ff8,0x3c5efe66,0xbc6087fd,0x1515e0d6,
  72871. 0xaa8edc6b,0xb1a39c5e,0x0e79ed29,0x3dd816bb,0xbc3788b8,0x6cc13769,
  72872. 0xc092a51c,0x463098e3 },
  72873. { 0xc8bd0fa7,0x3a6408c7,0xce6bde49,0xd1764311,0x283ef7be,0xe315e108,
  72874. 0x99b5d938,0x8213cc77,0x45a49a6b,0xaf7f1581,0xe529e4d1,0xd00fdb0f,
  72875. 0xce66c9d6,0x55d38f77,0x1bd4b952,0xb4f7ccc0,0xaf71f986,0x8d975b49,
  72876. 0xcd64d00a,0x12b59fcb,0xa5a3bad7,0x1860e504,0x2b5c89f1,0x6d976044,
  72877. 0x7a3e231f,0xfed0c659,0x178cba92,0x58114c33,0x6698e11e,0xe2e74c06,
  72878. 0xa348b85a,0x7f8fd093 } },
  72879. /* 154 */
  72880. { { 0xc19428af,0xf24592ca,0x3a308665,0x192a1c81,0xe30bbd7f,0x42589812,
  72881. 0x836c6bb9,0x10db0723,0x598e4987,0x9c7a41e9,0x6ead6f4b,0x8aff179e,
  72882. 0x75862c44,0x70f8f9b9,0x6f21983e,0x6b3b0237,0x98e65152,0x25d83e9b,
  72883. 0xd751218a,0x3b2d26a8,0x9d6f1da6,0x9508281a,0xa5a81f74,0x8df78d05,
  72884. 0xe4687471,0xd79ee559,0x6787d8cc,0x2060ca57,0xa8476c95,0x427a84ff,
  72885. 0xe6435131,0x87b64c51 },
  72886. { 0x4b30d3c4,0x87f46f65,0x23b4ef14,0xcdec4c5c,0x63ca4d68,0xb3b74766,
  72887. 0xcf3fb56d,0x1df34269,0x0fd7d46a,0xd4f139c4,0x6a69a8bd,0xa3b7c7c7,
  72888. 0xcbadd7d2,0xee56b4c9,0xac942334,0xb28ff342,0x786f1da3,0x0046fdfa,
  72889. 0xb700c82e,0xce5d149c,0x50966597,0xca30ef81,0xfcff4bdd,0x44a20609,
  72890. 0x44925268,0x0f2f65e7,0xd4021f38,0xe5b6552c,0x042dbbd0,0x77ea9c2a,
  72891. 0xd9c062f5,0x8c95267c } },
  72892. /* 155 */
  72893. { { 0x5fc1abb1,0x6655032e,0x12fe4743,0x2215af54,0x29f05ef5,0xfd657560,
  72894. 0xdc191be9,0xb0e73325,0xc08639b0,0x7ab3c65e,0x1c3e6673,0x67507f51,
  72895. 0xc8615555,0x638befc3,0x42f0c4ad,0x5d0188cf,0xd896186d,0x843a301c,
  72896. 0xb2c6741e,0x045603f7,0xfa3cd1d0,0xf7545c0c,0x4a40672e,0xf612affd,
  72897. 0x45b9e8dd,0x56197c9f,0x87922d74,0xb453237d,0x4b2d59bf,0xbf132e3a,
  72898. 0xb84a6a16,0x8afa1b73 },
  72899. { 0xe793ac70,0x6b3596ea,0xeef6dd10,0x4c94ef8e,0x70422e40,0x926b4fa2,
  72900. 0xe9e5d763,0xc8c71dce,0xf512aadf,0x352fcb70,0xa883975f,0x1b7ba138,
  72901. 0x058c3b13,0x57991390,0x97740fd1,0x9692092a,0x160b0697,0x19ad945b,
  72902. 0x10837ab2,0xbc634388,0xf174bb71,0x76ee11c4,0xab1b80eb,0x6111bfc1,
  72903. 0x70ec458a,0xbc82bac8,0x312d3325,0xeee60127,0xb240adc8,0xb4118b1a,
  72904. 0x2b5a093c,0x67211191 } },
  72905. /* 156 */
  72906. { { 0xf55cf9bf,0x91e99306,0xa46b96d9,0x9b045308,0x9e7a65df,0xae3c1e1d,
  72907. 0xc731bcbb,0x453cb151,0xa4d58a61,0x14be5227,0x97c74cc2,0x39dac922,
  72908. 0x822e00d6,0x4d0f7a45,0xc62b03df,0xafeb1d51,0xbaa18b2d,0xbb1dc3a4,
  72909. 0xdf2b74f0,0x7f3c7178,0x896b6a33,0xfcd328a6,0x1dce055f,0xe95ed454,
  72910. 0x6a4e2b87,0x97fbc76b,0xfa59dce9,0xe5ec67f1,0xcc0367c1,0x052368ac,
  72911. 0x54e4a3fe,0x7c863916 },
  72912. { 0xca7388cf,0x55e94b5e,0xc0335d38,0x17cc0a60,0x616f85ba,0x9b69b78b,
  72913. 0x10122980,0x705d02ef,0x1cfd0a79,0x565a6e80,0x7d1ee352,0xeb74a96d,
  72914. 0x427b9dad,0x5c8832ed,0xe6d5330f,0x96ea8528,0x18d24ee8,0x30d8862b,
  72915. 0x9ff939f7,0x9cd38ed5,0x01060252,0x690fc9a2,0x2303b3ff,0xc62d88b8,
  72916. 0xdd52b469,0xfc42d7a4,0x8cad2d93,0x06f8dfa2,0x60920438,0x50236090,
  72917. 0xfce855ad,0x32582758 } },
  72918. /* 157 */
  72919. { { 0x359e8c60,0xeb20e45f,0x364ca186,0xc71bb8a5,0xdff8e110,0x02b15071,
  72920. 0x4c93e578,0x074e91d3,0xb829d0d8,0xc0326e00,0x626a83fa,0x3c192258,
  72921. 0xfb29a09e,0x387a64d5,0xe5ac5c82,0xcaaa3d34,0xada2da29,0x8ed685e5,
  72922. 0xeb29650e,0x92720267,0x763802f3,0xf7184b19,0xdf6b1aea,0x23f5dd0e,
  72923. 0x25e6125d,0xbe1fa347,0x0c872a1a,0xd6287f9d,0xac57c3af,0x49aa93d2,
  72924. 0x5bda7656,0x1a4e6a71 },
  72925. { 0x554d1267,0x1a126ede,0x1cd02b48,0x37f94533,0xce31fb1d,0xd70af04c,
  72926. 0x097dc012,0xcf410b0b,0x36c7b6c5,0x930e1d17,0xc6891085,0x902fee41,
  72927. 0x79fb638f,0x349ba4a7,0xacd6f8df,0xa16c5821,0x2e076ace,0xfb3b83c1,
  72928. 0xe501d14d,0x6b8d033b,0x20f2d2da,0x0593d452,0x99df1880,0x3752526d,
  72929. 0x9feb33a6,0xca32351c,0x1f6ef456,0xd91343bc,0x35b9dc8a,0xc74857db,
  72930. 0x85b4e832,0x856a7c93 } },
  72931. /* 158 */
  72932. { { 0x0d0a5583,0xa007d002,0xeda4658a,0x2f1301dd,0x34d939be,0x91c07964,
  72933. 0xa70c0836,0xa0cb6780,0xbe81e540,0xc0b4df95,0x5d4ac8b8,0x6cbbcd34,
  72934. 0x54756239,0x57c52ed0,0x1805ceb6,0xcac2dca4,0x79344255,0x915ee6ab,
  72935. 0x24c9a2a6,0x366def31,0x8c12c674,0xbd3b962f,0x7dbb7c3b,0xaab64f1b,
  72936. 0xe22bb95b,0x3c0e4553,0xc4c63b74,0x2408feba,0x2a4da631,0x3ca77312,
  72937. 0xc636da40,0x62889084 },
  72938. { 0x8cb8d208,0xa457fd53,0x543f06d4,0x7a8f8009,0xf2eff2ab,0xb66de154,
  72939. 0xf72517e7,0xfddb28eb,0xf9389d2c,0x0149fe66,0xd85b88ce,0x79e8773f,
  72940. 0x0ba543f7,0x452e090b,0xb0b03fc0,0xdeb9b5cf,0x6c5ed77b,0x3113448a,
  72941. 0x8ffc0372,0x3609f3cf,0x5c1b4c4a,0x2bc9c46d,0x8fa59be9,0xe66f3bf3,
  72942. 0xcdb02691,0x1396bf5f,0x009f88f9,0xf1ec59d4,0x2ad9dfe3,0xc2903456,
  72943. 0x5ada4d58,0x79d8122c } },
  72944. /* 159 */
  72945. { { 0xaa529507,0x14d4e4ce,0x74655d00,0x056a0814,0x4f0fc474,0xc0d30a38,
  72946. 0x3443cb8e,0x8a8203ea,0x97f1728d,0x33c62fb0,0xb520ef52,0x8a38dcfd,
  72947. 0x7cac9d3e,0xa0f90d5d,0x873cea50,0x28a7b0bf,0x6c6c41cb,0xd115ae3a,
  72948. 0xa13812c1,0xa35171da,0x624d507e,0x25d4bba5,0x7e98f42f,0x91dad289,
  72949. 0x96a41371,0xffd6b1e9,0xb69e5b77,0xd46c2125,0x20c4f707,0xc7d2b424,
  72950. 0x8142557a,0x2ab3af95 },
  72951. { 0x6a5372a6,0x86ca074c,0x56292ba7,0x728fb83e,0x77741cf5,0x745596dc,
  72952. 0x520ef49d,0x70b4cea1,0x61e46472,0x1472fe34,0x3fb8ac5d,0xf4d6bd66,
  72953. 0xc10bc071,0x46e52cc9,0x371a3461,0x28794efe,0x276fe877,0xa4850718,
  72954. 0x9bef5ab4,0xedad5773,0x3f15c815,0x24c2d9ff,0x8f8395c3,0x188950e5,
  72955. 0x80b6a855,0xbae40996,0x8a8803e1,0x4f53e22c,0x039d25ee,0xaf233f61,
  72956. 0x250409ca,0x07db2c35 } },
  72957. /* 160 */
  72958. { { 0x037d4703,0xc7f3b8db,0xc5f488b9,0xe83708df,0x8471d402,0x1fba830f,
  72959. 0x5a2faae9,0xa55ee8d2,0x5404fc1e,0xc2e5bf10,0xaa2d5651,0x647d5027,
  72960. 0x7ebaf5f9,0x37a53c0c,0x95b30abf,0x7adf0bb2,0xd64c93ba,0x5a62e1fe,
  72961. 0xe2ef4a78,0x7ffc18c0,0x4d2cd04f,0x139dd9d9,0x5ea0af02,0x253fbab7,
  72962. 0x0fef9acf,0x7c8100ea,0xc8615aa7,0x74c5384d,0x9fe52069,0xcb28682d,
  72963. 0xcf7dd759,0x08b6ca8f },
  72964. { 0x036c3b5a,0xe04e5bea,0x7f9f2b4b,0x38726102,0x29797c0f,0xa9fca570,
  72965. 0x82879ea3,0x1656180b,0x607f0ddf,0x153389bb,0x67b0e087,0x99a1223c,
  72966. 0x9d897fc7,0x0d1808ec,0x916edf19,0x9470711a,0x07217118,0xf8f52f2b,
  72967. 0xd18888b6,0x5d8b29ff,0x4cc6f900,0xef1e22c5,0xeb24877f,0xc4036165,
  72968. 0x35479525,0xfda95233,0x6861468a,0xd622a421,0x74faba08,0x5d043b07,
  72969. 0x0d31a7d2,0x2c337b02 } },
  72970. /* 161 */
  72971. { { 0xea22fa65,0x7b2305bc,0xd159f63a,0xbe183ef4,0x3f35923f,0x3473d87d,
  72972. 0xc11d7753,0xb27fb306,0x2a054cff,0x702e7e6b,0xaf185619,0x3ce9f97c,
  72973. 0x4e7d51c5,0x83550243,0xf356ac5b,0xa63e3d82,0xd7645131,0x867b7caa,
  72974. 0xa671fc9d,0xee85e6af,0x2b07cd77,0x3b985ede,0xffda5193,0x07d598b0,
  72975. 0xa942dc36,0xb10eca39,0x506218a9,0x17f3dcee,0x06b7d5ca,0x3d94e8d1,
  72976. 0xed8831c9,0x509b2634 },
  72977. { 0x48caed54,0xb1b9414e,0xcbf51e97,0x77a78c6c,0x4de9b258,0xa4688c8d,
  72978. 0x91ee3d78,0x0024137c,0xe30ee64c,0xa68f9234,0x88190d78,0x573255bc,
  72979. 0xba80690b,0x41e8e05f,0xec354f4c,0x50038d84,0xdfa52816,0xb18f02d6,
  72980. 0xccb63fda,0xc47f9007,0xe98ae455,0x29d480fb,0x5d0e319d,0x4ac45d22,
  72981. 0x026db719,0xd06f3575,0x2c3587b9,0x733b9e20,0x2c317727,0x22483992,
  72982. 0x54bb8752,0x1592d5a7 } },
  72983. /* 162 */
  72984. { { 0xcf7453f0,0x5778d9a2,0xed83c1f0,0xaffb899a,0xe0a82ba7,0xae6506d3,
  72985. 0xea3d5081,0x32c84e1a,0x810aa38b,0x9ad528c0,0xbd37d041,0xb1fdb020,
  72986. 0xd06ce41f,0x78d6cbe1,0x2e74b7f6,0xd287f0f0,0xc43bb022,0xf5cd2575,
  72987. 0xf81a71b3,0x6d28f2f3,0xc633e7f4,0xe65bb1f5,0xc4fc580e,0x32e5fc1c,
  72988. 0xbb7b07a5,0xcd55539f,0xc3caaf3a,0xb5a94471,0x4cc22d2d,0xb958bdf4,
  72989. 0x77a2777c,0x1614bdbd },
  72990. { 0xed0ab04d,0x4c1f0230,0x6e2082ea,0xae347b00,0xc42c5b5f,0x9f10bc63,
  72991. 0xde019935,0xb0539e6f,0x65dd0825,0xd89bd4e7,0xbbceda16,0x92260fef,
  72992. 0xe62aca32,0x8aaa755c,0x5ec82c5f,0xed762fa9,0x18650768,0x99e64c01,
  72993. 0xc92e348c,0x57dd6245,0x31ea6d68,0x0db88a77,0x07b44736,0xef0012ab,
  72994. 0x171d70fe,0xb9356b94,0x03f891b0,0xe68b0628,0xb79c20a2,0x3a54a53a,
  72995. 0xb00b0728,0x489656c7 } },
  72996. /* 163 */
  72997. { { 0x71353c25,0xe43649ba,0x13f67e24,0x517f27a1,0x1c1eb9e3,0x10bd333a,
  72998. 0x78e29bf9,0x94e1c05c,0x4743f15d,0x84fe7d97,0x90da2df0,0x9c874908,
  72999. 0x53673be1,0x82403fa7,0x1baea1b1,0x7ebf5db4,0x24180ead,0xcfe0ae35,
  73000. 0xc2f50c3f,0x1d15873f,0x70661cd9,0x16851ad6,0xa51e8c2c,0x802968d9,
  73001. 0xe0161099,0xe7d1a9cd,0xa8a7ea56,0x2b153c89,0x06e3c498,0x6d41b789,
  73002. 0xd6769dcb,0x082bb2e9 },
  73003. { 0xc4d6615f,0x6180ef46,0x01b9829c,0xfc629dc1,0x0fb264ca,0xde222ec0,
  73004. 0x10ecc2c4,0xc5457e06,0x1eea2c4d,0x95ce599f,0x8f9c5b2c,0x0433fa72,
  73005. 0xcd6310f9,0xee035462,0xce2e2253,0x84c57c3b,0x96d87e44,0x6c8ec31a,
  73006. 0xa452c5a7,0x30bfe393,0xa047b235,0xc592b140,0xc018545e,0x7bd8be18,
  73007. 0x5c178c46,0x794e0107,0x2e23005b,0x48471946,0x622a54f3,0x2665e237,
  73008. 0x901c9042,0x36451a46 } },
  73009. /* 164 */
  73010. { { 0x19893e71,0x17802d18,0x539a2082,0xa1765d8b,0x2302ecfc,0xfc6aea01,
  73011. 0x365bf59d,0x8d4cf51b,0x0d232a80,0x87741d72,0x18e80427,0xac343eb3,
  73012. 0xe74739ec,0x553ecb2f,0x1a8b07ca,0xaeca79a8,0x56f4ab3a,0x089ff322,
  73013. 0x3fa1d1f7,0x5e95d729,0xf62a9a16,0x260569ae,0xaa08ddc2,0x5e776232,
  73014. 0x1b7bb54a,0x93fabec3,0x743d56e7,0x48a20956,0xeb0ebeff,0x749cdb12,
  73015. 0x69b8fcf1,0x705307a4 },
  73016. { 0xe488310b,0x7a8e4c04,0x5325cd7b,0x12726e32,0x4983efac,0x5d0fd8b0,
  73017. 0x02ddb913,0x796e552c,0x77b9685c,0x0eeca3f7,0xb15f24a3,0x9b766e89,
  73018. 0x48efc979,0x7c2736d6,0xa8021c6c,0x3d619685,0xa0b2f1ea,0xfe33e278,
  73019. 0xb676d6b0,0x95c69879,0x1af4e0be,0xa0747319,0x36c4ee55,0xa2fab5f1,
  73020. 0x59e5f3b9,0x6938b8ff,0x39cafe6e,0x1e114da4,0x6a6ad120,0xc9595ec3,
  73021. 0x57e62aec,0x80f79bd0 } },
  73022. /* 165 */
  73023. { { 0x60af09b3,0x3cef42a7,0x933dfe14,0x3c016ebd,0xed85eaa8,0x720cf1e0,
  73024. 0xceaa3bc9,0xd4f5e99f,0xb7106f97,0x7216b9d2,0xc9668ad2,0x65f34c36,
  73025. 0x5b0c651f,0xa8fb82bc,0xf2fda4de,0x20f42f1c,0xd21f659e,0xeb31ab2c,
  73026. 0xa13d1618,0xb7a776c7,0x38662be5,0xec441022,0xcad08e0b,0xc825da70,
  73027. 0x022c0180,0x99299079,0x2aef9ffd,0x7623bda0,0xf5c58b50,0xde84f4f3,
  73028. 0xd824ff19,0x5f5a5da4 },
  73029. { 0x7e8311dc,0x5737257e,0x466cf136,0xdef94f51,0xb05ca21a,0xa73e1645,
  73030. 0x02e4ab37,0x38ea9b3c,0x8579165b,0x7760eac9,0xc24b01a4,0xdffdd047,
  73031. 0x3fb95584,0x188d4fd1,0x25548bda,0xfaac38b8,0x59e9dcac,0x1a79a6f0,
  73032. 0x09a2700f,0x983f720f,0xfb8a7e48,0x8cbba554,0x47a1fad5,0x38a19968,
  73033. 0x5abd6b5e,0x11856547,0xf3716ec2,0x75113d31,0x4212907b,0x1391e781,
  73034. 0x0dc15889,0x5319c801 } },
  73035. /* 166 */
  73036. { { 0x6b61c3af,0x2320136e,0x07b4bb68,0x1d40f2de,0x380c97f0,0x651dee7f,
  73037. 0x6a8c313a,0xa978ba70,0x2011ca10,0x22c587d6,0xab1f445b,0x48bba218,
  73038. 0xe50444e6,0x8c5eaf07,0x442fccf9,0x5549f02a,0x3d80493d,0x2564746f,
  73039. 0x79c04591,0x42d24f61,0xabdc8887,0x1600fa18,0xded38f8f,0x5cb8600a,
  73040. 0x923aeb46,0xa4bf9b90,0x1e1c578a,0xd63fee35,0xebb9ea14,0xf3c9c5ac,
  73041. 0xf11a4ff0,0x3d13314d },
  73042. { 0xb4513d1e,0xe5cc662d,0xd55952bd,0xde78a8c5,0xe7f86d0a,0xe8a37a3f,
  73043. 0x7a04f0c5,0xca2d12a4,0x2e25d06c,0x4c6696e4,0xb2136071,0x52614698,
  73044. 0x89f6e1cb,0xf4d2701b,0x80efd95e,0xaafd6177,0xc5bb6907,0xe6d73ac4,
  73045. 0x420db35a,0x49e874ac,0xf2751fa0,0x11631de4,0xa1fa2edd,0xb29f7336,
  73046. 0xb7fd794d,0x4c406864,0xe22f92a6,0x73cb21d3,0x2043cc76,0xeae904e6,
  73047. 0xb322c6ad,0x67f28a9f } },
  73048. /* 167 */
  73049. { { 0xca148ab5,0x7c17b258,0xb3c60051,0xb9a1976f,0xc8f28df9,0xea260698,
  73050. 0xe8d45017,0x87b2cc74,0x0578a422,0x37257329,0x17bec732,0x81d5ee25,
  73051. 0x1d48bbc4,0xd7411fcf,0x487f5cfe,0x46217e6b,0x41eb8e1b,0xcb007ac5,
  73052. 0xe05a00c8,0xc41c57a6,0xd2f9fa99,0x1f954d2b,0x40941cad,0x370bd5db,
  73053. 0x3829509d,0xe487879c,0x5ceca5ee,0x4c137552,0xfd3efb9e,0xe8ef7fa4,
  73054. 0x1bd1bdb2,0x5ff09174 },
  73055. { 0x579c6632,0x791912a4,0xb8a20815,0xbb19a44f,0x535639d3,0xf4f97b84,
  73056. 0xbc3c9bce,0xe57e2bcb,0xf19e6410,0x122b3f2b,0x1357d9ad,0x1f0189da,
  73057. 0x79e5ff66,0x675573bb,0xef2f3c4c,0x444e5c98,0x04d10731,0xd6f61e20,
  73058. 0xac75d635,0x0dfa366f,0x2c854f23,0x9fc47c86,0x0ad0850b,0xc04ae43e,
  73059. 0x2f720c32,0x5ce94f64,0xa753bc9d,0x67efae65,0xb0373a63,0xc27d30d3,
  73060. 0x29721646,0x6681013a } },
  73061. /* 168 */
  73062. { { 0xe84509df,0x1385d913,0xcf339376,0xe978bedd,0x3423a148,0x2df425d3,
  73063. 0xee8cb579,0x43fa0ae3,0x31c4553c,0xf015369d,0xdfbf1d48,0x05cf08bb,
  73064. 0x9444244a,0xadff4be6,0xa35dda33,0x01635f81,0xe76fab7c,0x085c8949,
  73065. 0x16737783,0x4bd7fcde,0xa254f8d2,0xfd8cb52c,0x413ec985,0x62168a66,
  73066. 0x7a9026cc,0xf2db9741,0x50e1e1b7,0x3962ee56,0xd3beffde,0xbee0a346,
  73067. 0x0bdfab1f,0x3b35b72f },
  73068. { 0x535c3749,0xbff8de9f,0x8add9c48,0x23c1f20f,0xc8f8f663,0xa975b37b,
  73069. 0xe8f3ae49,0x2529e475,0x1d5e2628,0xc32f10d5,0x67862f1d,0x5ac0d297,
  73070. 0x854cbe36,0x13c79338,0x4b67e462,0x48f004ef,0xe5d10ee1,0xfa37a150,
  73071. 0xd28288a0,0x4974778d,0xcfb73f4d,0x96830a66,0x07804952,0x9f444013,
  73072. 0x9760b694,0x8233c709,0x25b75c99,0x8340cca5,0xc771f99c,0x3f62e40b,
  73073. 0xcd95c685,0x47d0a1eb } },
  73074. /* 169 */
  73075. { { 0x652811f1,0x266f4fff,0x62ef3002,0xeaacaa93,0x50cba0ca,0x6c387a55,
  73076. 0x007f5467,0xa350142a,0x202f2673,0xc7fd102a,0x33dc6e65,0x5daee570,
  73077. 0x064a63d9,0x60682ec3,0x462b251e,0x46cf0bb0,0x5da936e7,0x0e030ca5,
  73078. 0x434265b5,0xc87a60f2,0x69b4e8f5,0x9637b2bb,0x7ad7770a,0x601fb58c,
  73079. 0xed3a15a6,0x1f2147f6,0x2995e961,0x05b47d5e,0x83213a16,0xcb0ca9b3,
  73080. 0x4995a85c,0x8f4b614a },
  73081. { 0x4b4eb3c1,0x5aa8ec19,0x20323a70,0x8c549ac4,0x4f6cc6aa,0x00d49322,
  73082. 0x45f9a5a3,0x0e53b9bb,0x0897abbb,0xe46ef110,0xd7acd7d0,0xfe873e57,
  73083. 0x0f7cb588,0x7cfccfe5,0xc85557d1,0x0ea53d65,0x7288f2e2,0xfdd9eb44,
  73084. 0xc0eb68a8,0xab2dedfa,0x08603a0c,0x58221470,0x00feb06c,0x69464689,
  73085. 0x25e5caac,0x804cf5bf,0x9fc91ae9,0xd8559858,0x73c45eae,0xed9378b1,
  73086. 0x524c9801,0x8f942d02 } },
  73087. /* 170 */
  73088. { { 0x8e845808,0x1f1ec302,0xb77abfc5,0xc302bffa,0xf8d97dc7,0x26afd4b9,
  73089. 0x3aac594b,0x3d3a83c4,0x674d94dc,0xe3b74bd1,0xcaa5911c,0x4464b737,
  73090. 0x871c2cd2,0x62925773,0x3b4440fe,0x419f2485,0xe052ad7d,0xdda6a0f3,
  73091. 0x846c86c0,0x645280d6,0xf8324f42,0xa25689fa,0x07cf117a,0xc74ad1e8,
  73092. 0x8ddc9db7,0x5626dea0,0x966fc85d,0x52620373,0xf3b1eb53,0xe0ad57c3,
  73093. 0x949c1acb,0x38300252 },
  73094. { 0x5e744723,0xa0ef5a40,0x1ae08481,0xdb5bcf75,0xfec1f76f,0xabfad8cc,
  73095. 0xfab37fc6,0xfba5d831,0xc8fedb78,0xbe39e248,0xad93f310,0xa5cfad5f,
  73096. 0x913d5c24,0x747fdb1e,0x4518b7f5,0x052a47c9,0x7cfb4327,0x9e208d6c,
  73097. 0x70e538be,0xb135cb9c,0x5bb17916,0x36352759,0x5b3106c7,0xa2c07880,
  73098. 0xc209bb06,0xd2d42a06,0xd3c504ad,0xb525b471,0x822ce034,0xc9f4b368,
  73099. 0xeb4185a5,0x15f18796 } },
  73100. /* 171 */
  73101. { { 0x0aee4684,0x094dea06,0x7cdbdbc8,0x42b21f06,0xb1931319,0xa439e149,
  73102. 0x81a7dba6,0xea4bdd41,0x3c2ae80f,0xc6213706,0x12823dc2,0xb58b0967,
  73103. 0x832611b1,0x7443d515,0x13c20384,0x2e16f831,0x2bd992d2,0x0ce204d6,
  73104. 0xf419388b,0x499dbcd6,0x1d3778c7,0x492ded1d,0xc5ddae73,0x9d5bd74f,
  73105. 0x994b6259,0xd4813d52,0x0e86ca68,0x191d9cf6,0xf3e9c2ac,0x562179ea,
  73106. 0x9fee1238,0x6146f1f3 },
  73107. { 0x078e2aa6,0xbd06d33e,0x9dee9265,0x693af7f7,0xdaa40e84,0xd56e0f81,
  73108. 0x9b9a407e,0x05fbbb88,0xede99519,0xdcf44adc,0x092dba39,0x7f71f8d3,
  73109. 0x4231774b,0x675b5da5,0xa5f605eb,0x7456a251,0x87a39a9e,0x9031d4af,
  73110. 0x05b474bd,0xdb430006,0xb665aa91,0xbda5dbf2,0x6631eeb4,0x5d1a3df5,
  73111. 0x62377c58,0x028149ef,0x685d0bff,0x2e1af4e9,0x82a465de,0xe0ea0875,
  73112. 0x06bd0050,0x95543f9e } },
  73113. /* 172 */
  73114. { { 0x85d7c6ef,0xf7cbc6f4,0x63b1bc24,0xcad8084d,0xbf8cba62,0xdf90ce88,
  73115. 0xb455c192,0x98e4b686,0x774fc6ed,0x6146b8d5,0x7ae20077,0x70e2389e,
  73116. 0x61c22529,0x5241c479,0x3884e5f5,0x7d221510,0x17e28273,0xd6d20ce2,
  73117. 0x4f2674f8,0xe3119f51,0x70c011db,0x85459055,0xfcfb760e,0xdfab75d9,
  73118. 0x9e8c2a19,0x9546362a,0x4a7d4b27,0x4b6d3f8a,0xee5d698c,0xa5c87104,
  73119. 0x2ba296ff,0x6db43478 },
  73120. { 0x5c3f0d95,0x06486493,0x4e748895,0x8917db82,0x6b2f3e44,0xf73fdf62,
  73121. 0x2b7f574b,0xc60edc54,0xaf732723,0xbe1c09a2,0x7cad114c,0x7d34669d,
  73122. 0x321aaff9,0x9646600a,0xed0cd61c,0xb94e2bba,0xdec4750e,0x866e1a41,
  73123. 0xb1a89f58,0xa1be990d,0xf2759693,0xc39e4d6c,0xc0e0dddf,0x11cfb780,
  73124. 0xd99c8a41,0xf0afcd7f,0x6e1c3050,0xcebffadb,0x96d2c6e4,0x4f3981b0,
  73125. 0x2ae27a94,0x07a791e7 } },
  73126. /* 173 */
  73127. { { 0x1e9f0300,0xe70e9047,0xbccdf904,0xe0253ad9,0xff053078,0x51c0289d,
  73128. 0xae893462,0xf1ef092e,0xa4846845,0x2c90a91a,0xf1dad4b4,0x1946eda0,
  73129. 0x33df67b2,0xf07650f3,0x0b15a014,0xc6e988db,0xb542f0f9,0x72e0c66e,
  73130. 0xe0c0378f,0x5d4b6311,0xae86950d,0x548badaa,0xb35f1c8f,0x6801638d,
  73131. 0x944d1ad4,0x129e3216,0x40471d32,0x9951bac8,0x85e94dde,0x03cc29f3,
  73132. 0x4543ecac,0x6d6acc2e },
  73133. { 0x57b2d299,0xeb999e95,0xe3d721cd,0x3a2bcd9b,0xbb4cb444,0x2e60384f,
  73134. 0xdc060faa,0xae177709,0x8c987cde,0x74f0e6d3,0x1076fbed,0x9a237cf8,
  73135. 0x7983fbff,0x69af1513,0x323f9584,0x6c3f7a1d,0x6db64398,0x3e21cacf,
  73136. 0x96703d92,0x7cd8134f,0xb8393f76,0x0755898f,0x2e825222,0x1b5b28bc,
  73137. 0x7924aa7c,0xb78799c1,0x81427a8a,0x1db378f2,0xff289492,0xd5a451b1,
  73138. 0x3d3c46ee,0x79d18212 } },
  73139. /* 174 */
  73140. { { 0x109d5589,0x1a3edff9,0x029b4499,0xded52eb4,0xb4b54adf,0x13eb9d30,
  73141. 0xa27bff67,0x4f9214c1,0x67f0f460,0x4c817ee7,0xc3a50e28,0xbadf8d83,
  73142. 0x94026237,0xc5dc03c9,0x966647c1,0x5f29581b,0x8a0687f3,0x10b6a089,
  73143. 0x31634517,0xae787cec,0x62e75188,0x2001dba5,0x45e2c3fb,0x55d4e1a7,
  73144. 0xb67d3395,0xbfcacdeb,0xbc6842ee,0xa1a0af9c,0x3e88580b,0x50590a2b,
  73145. 0xa784cdc8,0x73104491 },
  73146. { 0x2648d676,0x44ca2cdf,0x4f1b12b1,0x9a85eca5,0x2980e1eb,0x1b9dac94,
  73147. 0x1ac8aa89,0xf30d3709,0xc719e195,0x73072ab7,0x2f703797,0xba518c82,
  73148. 0xac0067f6,0xac090e14,0x8dcd2927,0x0e6cfc70,0x21e7da63,0x4f5889e2,
  73149. 0x8371c7c6,0xb4aaa40b,0x8f7878c9,0x1f9dabe2,0xd84caf3f,0xf78aed6b,
  73150. 0x9e0e1d92,0x3c39dd07,0x122424dc,0x680be5fb,0x0bdc0099,0xf41b214d,
  73151. 0x5180c54f,0x6a8f8fc9 } },
  73152. /* 175 */
  73153. { { 0x53235132,0x62a1ed63,0x59dba88b,0x1db233f1,0x291efdd8,0x85625452,
  73154. 0xb25111ae,0xc7505297,0x1d701bd8,0xb5921af9,0x9774f45d,0xb4d05d72,
  73155. 0xf18e73ff,0x6e3d4c5e,0x899b3038,0x897d985f,0xc89b1558,0x8a9c30fb,
  73156. 0x4d13181c,0x3c92d1a3,0x2223320e,0x292e86ba,0x01ceed02,0xcf2454c2,
  73157. 0x583f309f,0x27a45f74,0xad0fd1a3,0x75a6102c,0xcb9c7538,0xdb4f45d2,
  73158. 0xdb283fd7,0x4752d8c1 },
  73159. { 0xd5dff4d5,0x514d6cea,0x45a827f4,0x74cd5fdb,0x4fc7135e,0x1070a60c,
  73160. 0x1be5778e,0xdec0bb78,0x58dc6b08,0x271e12cd,0x54bc2496,0xb765089b,
  73161. 0x619098ac,0x6ddf2c63,0x67528832,0xfd6ebac6,0xc2508af1,0xeaa2d025,
  73162. 0x4dcfc1f0,0x13c2cda8,0x45510be0,0x1c7836a8,0x1a886801,0x3904688d,
  73163. 0xafaf2545,0x643132aa,0x2830a88d,0x49685577,0x8744b470,0x569491ca,
  73164. 0x75fb8552,0x3a6518f3 } },
  73165. /* 176 */
  73166. { { 0x224042a0,0xaaa8ed50,0x2452f1e6,0x6cb4e3b0,0x768211d8,0xedca5f4c,
  73167. 0xef4d5d3f,0x4e0fe3f9,0x522d46e5,0x33a8e2a4,0xf1446775,0x5998e21f,
  73168. 0xf592d01b,0x1496c50e,0x83a67739,0x69104c2f,0x472bbf00,0x28670bcb,
  73169. 0x503177bd,0x8ea883b2,0x7d2712a2,0xc5d8bc05,0xb439c994,0x41ef9317,
  73170. 0xdcda1aff,0x9801d3a8,0x7038f6fb,0xd686eeb5,0xfbfbf820,0xe80c5cd0,
  73171. 0xedc25817,0x540ac363 },
  73172. { 0xfe7f43df,0xa71969a9,0x2c1b9e4c,0xe6653808,0x859c2917,0xad9677d8,
  73173. 0x96aa4404,0xbaca9545,0xff1297da,0x0e9d855f,0x22aea7de,0x1f61897b,
  73174. 0x36f13f8e,0x96edccfd,0x16e200df,0x627d3070,0xc98988a4,0x729f0736,
  73175. 0x97f231d2,0x95e25e60,0xf6048752,0xaf7f221b,0x4019b299,0xd6682609,
  73176. 0x26b4b1d9,0x1d99de09,0x1acdd7a3,0xec47cf66,0x6ebe15e9,0x4de9f2b3,
  73177. 0xfa16974f,0x17db32ec } },
  73178. /* 177 */
  73179. { { 0x6cf40599,0x75ef6919,0x00c020ea,0x7ea10dfb,0xfcaaf679,0x3da5ae7b,
  73180. 0x88ddd678,0x0d663ca3,0x255bcfcd,0x5a21f8fe,0xe344bc7e,0xe9c3f538,
  73181. 0x548e0632,0x35f62b1d,0x43c6e64d,0x654f2425,0x26993627,0xc755a7a6,
  73182. 0xb0f41324,0xa3b7c5f7,0x3a2180f3,0x05697f79,0x1e81675b,0x6cf85fb1,
  73183. 0xe53428f5,0x6d3cdb35,0x52d28b02,0xe3aa1591,0xf7a3fb78,0xa8470255,
  73184. 0xa194445d,0x460bd01b },
  73185. { 0xc24d8077,0xbc34dc23,0x4c720d2c,0x82f4b580,0x6f5d1ffe,0xa29da911,
  73186. 0x92783ce2,0x578af520,0xb5904af3,0xe29f51ab,0xf7aa1190,0x46c570d7,
  73187. 0x571bddf0,0x4a522fba,0xae89bb51,0xbf4e2a06,0x59f3444d,0x799b35cc,
  73188. 0x26cc2557,0xc3028367,0xafcec177,0x94a4e985,0x7c36cbd0,0xadaf7dcb,
  73189. 0x75d39077,0xed31b787,0x2d3e24bc,0x52d6904f,0x1f95421b,0xc5ca2669,
  73190. 0x1734878d,0x7d342c3c } },
  73191. /* 178 */
  73192. { { 0x11fd127f,0xe5cf2c0a,0x119e4c5e,0x66d36bb8,0x6ef56ac3,0x621ab252,
  73193. 0xe5430675,0x30cfeaee,0xac3e9619,0x2ede27d2,0xf8fce671,0x6413513a,
  73194. 0x075f4c3d,0x6159c61b,0x59069d98,0xd447efe9,0xea76aea9,0xaf8d6f68,
  73195. 0x0f5bd164,0xac5dc61b,0x1e88bb98,0xdbab446e,0x1ba92320,0x618b8b16,
  73196. 0x78989865,0xa0eafb3c,0xc08b7e82,0x0c7abcc2,0x20d160bb,0x10f09b6e,
  73197. 0x8e4c63a7,0x5be0afa6 },
  73198. { 0x1bbbf49c,0x82ab6d38,0x8c0703fe,0x3e09ce49,0xe10f4263,0xeca58b5d,
  73199. 0xda5a4532,0xd9cc6581,0xf618f7b7,0x07e18876,0x250f7fe7,0x0419a5e3,
  73200. 0xde6b86be,0xbb1a9e90,0x37359169,0x584a7deb,0x5149db2c,0x38eb3489,
  73201. 0xb0ebabb8,0x14546a33,0xc2f88a92,0x0067f0b0,0x0a2db019,0xbde0dfe7,
  73202. 0xc63e6f3e,0xba51b06c,0xe9206fad,0xa19127b9,0xfe80dc0a,0xe4eb5e87,
  73203. 0xd4de30ae,0x1e6fccf5 } },
  73204. /* 179 */
  73205. { { 0xaa8ac924,0xb57dff66,0xc298b3e8,0x06e9ad31,0x65fb080c,0xd140e329,
  73206. 0x1d95c93f,0x7dab211d,0x8a180caa,0x6d68d842,0xa20ded69,0x1a929408,
  73207. 0x38df461f,0xa8151753,0x60eae932,0xff5604ae,0x7dae4c0b,0x901b9e49,
  73208. 0xde262e89,0x4573a97f,0xf1084983,0xed69d9a4,0x64724f1d,0x8ffa022f,
  73209. 0xea85a15f,0xd5f1c2e4,0x01453794,0x4c626ce9,0xbf0907dd,0x80440cd6,
  73210. 0x5ddaa837,0x4522d461 },
  73211. { 0xebfbe7c5,0x8895f079,0x84ef3446,0x30ea1ded,0xd4a1ab96,0x716a9eb6,
  73212. 0x50a30c68,0x1a4a5d22,0x0043bbaa,0x5a16631c,0x5010e5f5,0xbd107502,
  73213. 0x3d8c0556,0xbffe3e9d,0x07772419,0x31b30b18,0x84b82297,0x90ff7ef0,
  73214. 0xf21a18c3,0x00c37d75,0x565bb8f8,0x18d0a635,0x45e3bceb,0xbac1da2a,
  73215. 0x23f0b08d,0x1c38e90c,0x5fbc5ac5,0xf1ba1aa2,0xdda71fc6,0x09d5256b,
  73216. 0x6d7e40ba,0x346501a9 } },
  73217. /* 180 */
  73218. { { 0xcc2b0f1d,0x86be448c,0xac4c3703,0xe3eb45c9,0x9fc96bbf,0x5387f65d,
  73219. 0x5ae27fda,0xcef3c4e9,0x1bc18089,0xa008f776,0x22ca18a1,0xf374a084,
  73220. 0x53b73371,0xee882842,0x7cc09354,0xcb6fc6d8,0x61496d6b,0x8489ec1b,
  73221. 0x49e325c4,0xa92c29b9,0x7bdec166,0x15c6ca52,0xdcea2813,0x95444eee,
  73222. 0x3a21154f,0x34683eb3,0xd39061cf,0x8fb26f98,0x06c940bb,0xc3b08aa8,
  73223. 0xe554c96d,0x7c1d42cf },
  73224. { 0xdc110aa7,0x766e703f,0xf362e378,0xab7b79d7,0x5aadca3c,0xd259c75d,
  73225. 0x60be3373,0x2a6eca79,0x06c4e8ff,0xf4744a4b,0xf3b705bf,0xb2842cce,
  73226. 0xae304b53,0x1a3af5aa,0x1b2d31b8,0x7bbfa201,0x4bee88d9,0xc4ba6eba,
  73227. 0x565cb839,0x2d3565ce,0xdaf7ece8,0x24808696,0xe6959745,0x2c7ccce7,
  73228. 0xe94f9837,0xefd6eb3c,0x3811a326,0x0a33b4cf,0xfffa93a6,0x14203f43,
  73229. 0x73c31d90,0x031e9828 } },
  73230. /* 181 */
  73231. { { 0x765a17ff,0x4fefecfc,0xd1290a65,0xa09f3888,0x938da038,0xbf265c46,
  73232. 0xa169ad46,0x4bb6145d,0x23a62fe8,0x33cf8214,0xabc860a5,0x562df571,
  73233. 0x815c38c4,0xbf2a90fa,0x17eda875,0x45ba1d6e,0x946fa5e1,0x799d881a,
  73234. 0xb90f5a3b,0x6c1be784,0xb10ff52a,0x0910a37c,0xa4f4fd36,0xc38c1fe4,
  73235. 0x8e2d3ba0,0xc3180fc5,0xb17a6187,0x3e2ff050,0x943a35c2,0x3a00059b,
  73236. 0xa28cc51c,0x494d3645 },
  73237. { 0x4ba021f8,0x398426b6,0x796deb6c,0xd14c9083,0x7e36c762,0x6d2e5395,
  73238. 0x751cf216,0x8f556eca,0x19b24a19,0xdaca1e00,0x4b20c2ae,0x47887da4,
  73239. 0xff41a733,0x93ed4ccd,0x5c7c0cd7,0x8d717c44,0x91bf7009,0xcc48634a,
  73240. 0x3b59bbaf,0xa1f146f9,0xe5624f15,0xdd38bb39,0x303f8443,0x96d41aad,
  73241. 0x4bf104fc,0x6b670f03,0x29706582,0x0503f9ed,0xb34200f5,0x768e1f47,
  73242. 0xbbd4c6f3,0x3cfdcc5e } },
  73243. /* 182 */
  73244. { { 0xb523e13d,0x536c2a86,0x2920d0a0,0x1014a458,0xe7571296,0x3d52b478,
  73245. 0x7eb51bea,0x05746066,0x87b0e919,0x709f7861,0x686888e8,0x028aed88,
  73246. 0xd94afcd4,0x79a809d7,0xe2129af3,0x50c6032f,0x983c4082,0x75e4be72,
  73247. 0x7ab3be8e,0x98331bbb,0xb618c728,0xd31a032c,0x3f59c4a4,0x36dd85a1,
  73248. 0xed4f61e2,0xdbece345,0x1e571715,0xba7aaccd,0x64a1ebd7,0x138c58da,
  73249. 0x3d1aeea1,0x89296d0f },
  73250. { 0xcca82c97,0xb165288f,0x1427e8dc,0x26c6c12d,0x4c3edda9,0x66a94f07,
  73251. 0xeaa01ebe,0x94600e1e,0x30f5e86d,0x14abce7c,0xcb456a31,0x741d7020,
  73252. 0x279f42c2,0xab05aa13,0xd4238468,0x70b60faf,0x318d39e6,0xa18efec1,
  73253. 0x8920b318,0xeb07f1ac,0xd8399e03,0x01e3cba8,0x3c81a301,0x65f8932e,
  73254. 0xccc667d8,0xae8bca7d,0xa268607c,0xcee1ae79,0xcac0a12c,0x3182e64c,
  73255. 0x2b1a4c54,0x9233a2f7 } },
  73256. /* 183 */
  73257. { { 0x0acbee17,0x717e8df6,0x5c24fcdc,0x0f0959c2,0xe54ffcb0,0x46f09887,
  73258. 0xd285116b,0xb993deca,0xbba1fa51,0x0bfaa4f8,0xd0f2183e,0x9c9249ef,
  73259. 0x96847779,0xf93cb358,0x2322d421,0x284bfb7f,0xd42af009,0x40cc709a,
  73260. 0x9bb1d615,0xc69f2274,0x717c3c6a,0x76f50b3a,0xbb9c5eeb,0x8b21e985,
  73261. 0xa4783b5f,0x58fb19ae,0x52e1c3e7,0x04c86b9b,0xf2971ac8,0xaca59092,
  73262. 0x21ed8291,0x2bb26a69 },
  73263. { 0x15f81416,0x98a34435,0xaaff5bb4,0x086e72e7,0x0317261c,0x3d1f64de,
  73264. 0x5c0a1cfe,0x31c0786c,0xb3683401,0x542ea4d8,0x1a39b4cd,0x2f77273a,
  73265. 0xcbef27f1,0x14fe7ee1,0x16bb27dc,0xee7fc09e,0x410e5dc7,0xc0dccc17,
  73266. 0x1943b3dd,0xa3466742,0x3f31c1b7,0x92934b60,0xc22c1070,0x0186ded9,
  73267. 0x799f966b,0xa37ee8ba,0x249b0893,0x0f3bfcb4,0x2e92d4de,0xbae61447,
  73268. 0xe196eb08,0x937cb3f8 } },
  73269. /* 184 */
  73270. { { 0x16fbfdce,0x57c0e77c,0xc98d4cc0,0xea034cc9,0x42572d20,0xe7606d72,
  73271. 0x0019a83c,0x9861b55c,0xf1597162,0x80ba2803,0x05a0fd7b,0x0f4141dd,
  73272. 0x4b0daaa2,0x8865913b,0xaa3848ec,0xe6685746,0x3e0485d2,0x16d15a5a,
  73273. 0x3b6905dd,0x81c0c774,0x818af2ba,0xcec31b7d,0xd2b74b78,0x80d8f194,
  73274. 0x543e2f28,0xca659db2,0x9fb07c1c,0x31b83a7d,0x1f1048c0,0x86537fdc,
  73275. 0x78586a11,0x4d57bb07 },
  73276. { 0x53b396b6,0xbc4b768a,0x93b51dac,0xbc8b24c4,0xa30ae1b3,0x33e511eb,
  73277. 0x945147c5,0x893bbd95,0x179fe3ce,0x6cc86031,0x3f920bd4,0x34b0a167,
  73278. 0x6b256160,0xb32912eb,0x9d168d83,0xbc69a2a4,0xef0dd128,0xb4949e7a,
  73279. 0x872699e1,0x2613419a,0xbf21376b,0x06c58477,0xa4f97147,0xe55b1909,
  73280. 0x7b9b745f,0x63d6eb75,0x08df3c85,0xb5365b29,0x55fcfae3,0x0e257e43,
  73281. 0x979f2aa8,0x1067c118 } },
  73282. /* 185 */
  73283. { { 0x32bf8883,0xc8455084,0x6fd06667,0x4755286a,0x77c2335d,0xd70b0f8f,
  73284. 0x2f4a2c94,0x678e60da,0xd118acf5,0xa468d8ac,0xbf5b90d9,0xce93830b,
  73285. 0xed4e9104,0xea4b1c74,0x27776ea4,0xac67316d,0x361bab12,0xb98ad75c,
  73286. 0x99122451,0xc323d482,0x530a43ae,0x26440220,0x3292d5a5,0x3a44532e,
  73287. 0x5fecf1bc,0xdb48694b,0xc667b8b8,0xe4e0516e,0xa4306ade,0xb3aa595f,
  73288. 0xf34e9725,0x7e4f7091 },
  73289. { 0xb7f70919,0x3f3816e9,0x16b003f5,0x765216ed,0x778c99e5,0x46c6cff4,
  73290. 0x30a51810,0xe6a5abe8,0x45e728db,0xef6f49e6,0xcaccefd6,0x6fdd73ea,
  73291. 0x8c37f3f7,0xec394e6f,0xb6407fc3,0x73320802,0x96625cbd,0x988e8f7a,
  73292. 0x7cabfb00,0x83292363,0x407f359a,0x258ba9df,0xccbfae50,0xff01aee5,
  73293. 0xfe251813,0xfbeaeace,0x83f1cba1,0x9c69f161,0x9eadcdb5,0x512c58ad,
  73294. 0x6ccce8bd,0x2ae49cd4 } },
  73295. /* 186 */
  73296. { { 0xc40849f2,0x1239b0e3,0xa441098c,0x5136a4cd,0xe547f649,0x61535a99,
  73297. 0x7a9bbac6,0x92e4bdc4,0x53547af6,0x195a1646,0x8b47a74a,0x85ecb319,
  73298. 0x9de6a2b2,0x278553fc,0x0e2ba52d,0x471c038a,0x35bcba93,0x12ba1b88,
  73299. 0x6f31eca2,0xd4bf50da,0x802b32c6,0xd146e3f6,0x3c64c8c4,0x0c9c0131,
  73300. 0xeed21297,0xad30f12d,0x9c68530f,0x9b75bffb,0x8918de51,0x23c0ad3e,
  73301. 0xa73771b7,0x180e9d52 },
  73302. { 0x29ab77b0,0xc316542f,0xf7aee628,0xdd411d9c,0x353c2f40,0x044c0685,
  73303. 0x4b0ae4cf,0x638dc7e4,0x95fc266f,0xa0924185,0xfd2feb7d,0x639da671,
  73304. 0x5ea39798,0x56858ed5,0x58f3832a,0x7a694f31,0xd316d831,0xa94233c6,
  73305. 0x30a35a7b,0x2fcacb26,0xf1ff713b,0xfef8f7dd,0x59eee2f3,0x8b9b4525,
  73306. 0x156d064a,0xd1b4f91b,0x2f5cfcfc,0x177866c2,0x3777eb41,0x12bc2566,
  73307. 0xd8ab85b4,0x21ca6f3c } },
  73308. /* 187 */
  73309. { { 0xa3e66635,0x0e162b13,0x2a9f76af,0x1ef20a2b,0x46db3356,0xab473a30,
  73310. 0x7802bb8d,0x0840bd77,0xa699b44c,0x5b6baf5e,0x1b2207f1,0xc6e11900,
  73311. 0x790b0105,0xe5de16a9,0xdb67f004,0x22b12f15,0x8a025d25,0x185fad45,
  73312. 0xdf0a1142,0xbccf6953,0xf45034c0,0x4c42129b,0x1c277bff,0x0f740400,
  73313. 0x280a9e18,0x6e440b4c,0x842aa2b4,0x767de8f5,0x05e8d94f,0x3de20ab8,
  73314. 0x20227635,0x5aff5859 },
  73315. { 0xa8458e40,0x805acd20,0x149732bd,0x5a5557d8,0x5f1ca72d,0xc7074131,
  73316. 0x952b5323,0x7f2e269c,0x6494fadf,0x5c592556,0x1a7d2666,0x153b7acd,
  73317. 0x86fe2865,0xa6df063d,0x57d53b6b,0x1e91db13,0xe93ead01,0x9195bb89,
  73318. 0x2963bfe6,0x3d71e1af,0x88278886,0xfab2b9c2,0x3b859b6f,0x77836692,
  73319. 0xf7029dd1,0x6e695174,0x7b984561,0xc7987876,0x5907d849,0x64fb4f1d,
  73320. 0x88d8a977,0x3eab7e1c } },
  73321. /* 188 */
  73322. { { 0x52e5718b,0xc73a94b6,0xf4cee1e9,0xe3aefa54,0x553eedea,0x654e9e63,
  73323. 0x5f3aca1a,0xf2541e1b,0x0d083316,0xd7129489,0xfb7f950e,0x7965af63,
  73324. 0xc74e3e4a,0xd8fc9e0d,0xeaf79ebc,0xb4ee48d2,0x8b7787e6,0xa458a86a,
  73325. 0xf7cceaf0,0xd8c7621f,0xdf67980d,0x8228eeff,0xf9106727,0x210d4742,
  73326. 0xb07e3629,0x91f63501,0x7971e29d,0x441761c6,0x03a3b8a5,0xc0ccc65f,
  73327. 0x38e09544,0x3491da4f },
  73328. { 0xcb062eae,0x6706d046,0x5d08776d,0xee7db735,0x292315d2,0x80de8052,
  73329. 0xc402bbdb,0x40785662,0x26ed3337,0x5f93525c,0x7d568ed3,0x6cea14d6,
  73330. 0x66888b1e,0x916a1189,0x5dc71675,0x0fbd5205,0xe4575df2,0x833d1077,
  73331. 0xec092335,0x4e93100a,0x6cd85389,0x2f9e1d01,0x43226368,0xeebd3725,
  73332. 0x1ba4cfd7,0x401d172b,0x574c5838,0x377dab9d,0x80d517de,0xaeaa6958,
  73333. 0x6ad15a18,0x0c843dfd } },
  73334. /* 189 */
  73335. { { 0xc9373300,0x455811ff,0x99fdc300,0x1c39332a,0x353cb655,0xe19bb81c,
  73336. 0x96a83d27,0x774b924a,0xb2ee3f1a,0xcbfc8fcb,0x010d56c7,0xaf278ec4,
  73337. 0xe0abaf79,0x6fde682f,0x7339aebf,0x7566d072,0x71205db6,0xbd35ad5d,
  73338. 0x7051c9d0,0xb5bbe694,0xd3a3067c,0x577db480,0x572d7530,0x2c70ff54,
  73339. 0xe06d853d,0xe8615aec,0x05abfb5d,0x71999ccb,0xea0a8ed7,0xeeefc96b,
  73340. 0x35f6df69,0x2dcc469d },
  73341. { 0xc65f0e77,0xcca6cd06,0xbd71b14a,0xddcc7980,0x3c93cc00,0xb6221f8b,
  73342. 0xae8cbf57,0xddfcd5b3,0x76f8e63f,0xbc92973f,0x06e132b7,0xe9848a34,
  73343. 0xd51ec9e2,0x4cc59a03,0x3a33081a,0x9c9d32bb,0x80e8466b,0x00121052,
  73344. 0x1bbe7295,0xc2b0032a,0x24938448,0xdbfc6572,0xb6bba0ff,0xe972a0ce,
  73345. 0xc0a94802,0xf60c0a4f,0x599d8bc7,0xf62c41cc,0x312da0b8,0x820c96ee,
  73346. 0xcdbdf9fc,0x5a1a65db } },
  73347. /* 190 */
  73348. { { 0x42485684,0xbfba691a,0x29c470c9,0x613116b9,0xe62a0519,0xb4b01971,
  73349. 0x5ff499da,0xf3245aa6,0xa5238eff,0xc2ef87f4,0xcc9d5515,0xc16dc6ba,
  73350. 0x2dbdacac,0x5a7f227e,0xa9bbaecb,0x8dedaac4,0x2e7c9885,0xff308a6d,
  73351. 0xe6895593,0x4c6f2fc2,0x177e0611,0x3655f285,0x300b1bee,0xa63e8d06,
  73352. 0x13c17b54,0xbed0ce79,0xc4974262,0xca4abe35,0xbc4e4037,0xf4b44a17,
  73353. 0xefe5fbd9,0x5ae95099 },
  73354. { 0x804f7455,0x122e5ee7,0x22066682,0x341a4997,0x7795e333,0x97d24c31,
  73355. 0xe48efced,0x12f4123c,0x19fbc21c,0xe8738d92,0x0663a3ae,0xbb3bdc61,
  73356. 0x8593a6db,0x3603d8c2,0xe3c1ac75,0x926227f2,0x5eaae519,0xfea92ac0,
  73357. 0xfd6812ac,0x5b596f0b,0xfc2a82dc,0x3ce7e844,0x63522b27,0x3840481a,
  73358. 0x52867895,0x836088b1,0x26588688,0x21ffb7cc,0x2f4a7cac,0x0ca33161,
  73359. 0xa3edd298,0x4110667e } },
  73360. /* 191 */
  73361. { { 0xc2d04b63,0x81830357,0xf4929a18,0x3fc5a34d,0x22d195df,0xc73bf6da,
  73362. 0xcb432473,0x14df2f89,0xe997f138,0x345afe5c,0x8b9604f4,0xd8e3f5f9,
  73363. 0x50c10ae5,0xad7942e9,0xeed25ff3,0xcefd5447,0x0e73c0cc,0xbf68e51e,
  73364. 0xab54fa4c,0x5b1ad591,0x12b61c8c,0x8bbc1105,0xb5abf760,0xbb932913,
  73365. 0x01e79649,0xdb1231be,0x040ccbe7,0xd0a83e91,0x90a96db9,0x3dde426f,
  73366. 0x34df11ea,0x1cceb645 },
  73367. { 0x0c6d0f55,0x2d210c4f,0x9c673c9d,0x6cadf61b,0xa9ce3fbb,0xdd7f9919,
  73368. 0x93b063e4,0x135f494c,0x145a93be,0x580bdb3c,0x0f52ef7c,0x4d872332,
  73369. 0x8814bb6a,0x74d876e8,0xc7a97dee,0x4f6f723a,0x3e3cd833,0x7de2b8f0,
  73370. 0xae720270,0x6162f082,0xddfa486e,0xe88ec2d4,0x8d3a17c6,0xd965c859,
  73371. 0x3980171a,0x62e59e54,0xbbef6b22,0x0ab6285d,0x4d48b203,0x3cf45195,
  73372. 0x4ea25ea3,0x1f175233 } },
  73373. /* 192 */
  73374. { { 0x3467ea91,0x808a765b,0xfd2d9c45,0x3f4632ee,0x9cf2bc6f,0x7b75dc6d,
  73375. 0x359813ae,0xefc8d240,0xe44cbd8d,0x23ecb209,0x21525622,0x59ba10e3,
  73376. 0x3f1ee19a,0xfa14d934,0xfb0c48f7,0xdf97c21b,0xea30d437,0xc4e62890,
  73377. 0x651475c2,0xb286e2a4,0x126672a5,0x291f01e4,0x31aab3b8,0x9c6fda5c,
  73378. 0xe17d22ec,0xb7277a5a,0x914f0bad,0xbd88ed83,0x6a2392e1,0xd0b05d1b,
  73379. 0x65893c2b,0x4cb8af90 },
  73380. { 0xbb4b1953,0xa2b02057,0xf597f6ee,0x4ce08b44,0x5e6412c8,0x854f5d9b,
  73381. 0xb3cd4919,0x1913262d,0x6e42bb5d,0x902762e4,0xd78e7f60,0x8355c8e6,
  73382. 0x38b6c16c,0x8efaa824,0xe550f618,0xd0173790,0xe57d778e,0x118af462,
  73383. 0x715b4714,0xa16ad5e8,0x41dea4f9,0x900596c3,0x280ca610,0x2a957c32,
  73384. 0x374c65a1,0x2faee800,0x50080414,0xdb105127,0xff080fa1,0x8c1db931,
  73385. 0xd79878fc,0x486a5c25 } },
  73386. /* 193 */
  73387. { { 0x941b4f36,0x0521e213,0xf803b4f9,0xbaacfb14,0x52a54ba8,0xfdf1e22e,
  73388. 0x8fe4796c,0xacfabbba,0x58dbacb6,0xae0788db,0xc19dfa51,0xdf98d736,
  73389. 0x35a716ee,0x155c286a,0x9c86461b,0xbe7d4676,0x63a64a5e,0x50b6380f,
  73390. 0x9f609262,0x14b41914,0xa2dfc5b3,0x0919a7d0,0xcef466ac,0xc454da55,
  73391. 0x6986aaec,0x93fa4a24,0x71a49ced,0x5090b171,0xc1fa75ad,0x602f1d6c,
  73392. 0x78e4c054,0x5d269f89 },
  73393. { 0x14920419,0x3a74030c,0x90968739,0x0845d868,0xeeb70fa6,0x81b994c4,
  73394. 0xd9fc5bcb,0xabcaa06d,0xf58f8f2d,0x06539427,0xb1dc52aa,0x35c85f67,
  73395. 0x2c911baa,0x5a7d8d72,0xaec2d834,0x4041005c,0x7a8e5347,0xb5868a44,
  73396. 0x8de512c3,0x04ee180b,0x211168eb,0x4daa66e5,0x2317cd8a,0xc0bd5dab,
  73397. 0x61164df6,0xa1d4185d,0x1dbad7c9,0xacedca26,0x09b02683,0x0fe4b5ac,
  73398. 0x26d9550f,0x8ac9995a } },
  73399. /* 194 */
  73400. { { 0x2640a39d,0xb2c8dc9b,0xede0c9f9,0x21ff0b38,0xa1ecba0a,0x74f469bd,
  73401. 0x080d0417,0x8a902ccd,0xf4994604,0xe956fa32,0x9776ab15,0x348f85cf,
  73402. 0x0066f492,0xc21fc6ee,0xfeeef367,0x35b1ebfe,0x4613e5ed,0x7804581c,
  73403. 0xea6ba071,0xcbdfe8e6,0x950d73ed,0xddfcaa32,0x1da48889,0xc9747936,
  73404. 0xdbaffbd1,0xce867c8c,0x1cbaeae7,0xd267431f,0x897912c8,0x68255045,
  73405. 0xd7ea1e4d,0x0c7c1ddc },
  73406. { 0x1ce963a7,0x53aa30cc,0xc4c5fade,0x7352f64c,0x2828afbf,0x2b9aa2f8,
  73407. 0xca212107,0x64273c56,0x85a576dc,0xaadd7654,0x90b5c77c,0x6196ac3e,
  73408. 0xd1aaf39b,0x20d43e9f,0xcd05cbc4,0xfc392062,0x4c0ff2fd,0x14163872,
  73409. 0x2ae821e6,0xcf32b8d8,0x3fa7a3f0,0x5f58f943,0xf644ca92,0xaebf1d2d,
  73410. 0x1918a75f,0x0c061563,0x6b876118,0x7989b5ed,0xad412441,0xbf342445,
  73411. 0x1df633ab,0x24ffc9ae } },
  73412. /* 195 */
  73413. { { 0x93c7cb2b,0x89fcdc05,0x590053fb,0xc1243b95,0x6182343c,0x601debcf,
  73414. 0x66c18a63,0x364546ef,0xec913287,0xa5290701,0xf9788c31,0xc35b8026,
  73415. 0x92d1f7d7,0x852b862a,0x0aa79728,0x1809cb05,0xa3cb2005,0x897d467c,
  73416. 0x9ef5b946,0xf20c77c0,0xf2241984,0xc3372c42,0xf35bb206,0xda053e0d,
  73417. 0xa9c140b5,0xbc26c6d0,0xcb56fb33,0x61cfcc0c,0x299b3968,0x1c3cf9ef,
  73418. 0x40621ba4,0x89e4d3d1 },
  73419. { 0xa45a9be3,0xd35e80e7,0x07356fbd,0xc4daa578,0xb967bc2f,0x0186d62e,
  73420. 0x47cd16e3,0xa702679e,0x5f30ce9b,0xca2f1c02,0x1f864f50,0xf1205b46,
  73421. 0x85061d66,0x7fd6d797,0x8a08809e,0x47edc4f6,0x9a4d3ae2,0x5dac0449,
  73422. 0x6d1f9da8,0xf844664a,0xd7a83a71,0x9f30ce84,0xeaac33f1,0xe9382bac,
  73423. 0x948622ab,0x1f033831,0xf7681eb2,0xb037a4ba,0x99a1b5c7,0xd156a908,
  73424. 0xe6f1d0fb,0x675d3e6f } },
  73425. /* 196 */
  73426. { { 0x707193e5,0xd9767ffd,0x810358e5,0xe478aa91,0x328d8ef7,0x5634f9ff,
  73427. 0x6dbbd9a7,0x913a0ee8,0x7e215686,0x379b2968,0x89d9da38,0x903f410a,
  73428. 0x1b1334d2,0xd9f8d7b9,0xbd82efb5,0x9fe74229,0x3803c778,0xdb568b62,
  73429. 0xd3d25344,0x93e9a350,0x724497e8,0x559c35b0,0xa169e23b,0xc472d436,
  73430. 0xcc5b4c69,0x09864632,0x83c7f531,0x9f6d759d,0x1e497888,0xa91cf1db,
  73431. 0x60af1a4b,0x5f7f92fe },
  73432. { 0x0545167e,0xf18a1cc6,0xaffa88e0,0x55ee2e02,0x432a7bcf,0x24cdff51,
  73433. 0xa7510866,0x7382da42,0x40511af7,0xe894c11f,0x2aaf1423,0xaa4e4e31,
  73434. 0xf63dd2ae,0x8c3d36f0,0xd7660635,0xfc5c9550,0x37ea7eab,0x01253731,
  73435. 0x39b950f6,0x2a5cd598,0x40e63442,0x95a0f601,0xf2ac7045,0x905e238e,
  73436. 0x446b0f73,0x44bacc0e,0xc448578a,0x4cd4206e,0xa5bd7803,0x367b1aaa,
  73437. 0x0a2b458d,0x25beced9 } },
  73438. /* 197 */
  73439. { { 0x0c33a8fb,0x079a7382,0x0f25dc1d,0xcfbf6cd1,0xc6d482b6,0x4ffc73f8,
  73440. 0x07bf844a,0x3e51f18c,0x599162f0,0xa7651236,0x14013811,0xac59a74e,
  73441. 0xe55018a0,0x957a6865,0xe3ca09b1,0xe1ec51bd,0xa960253f,0xbc0c7eb3,
  73442. 0x7de03f84,0xe83bfd14,0x52fbdb09,0xc0540ed1,0xcea15ec1,0x6ba52edd,
  73443. 0x4b261307,0xf3d30ed5,0xe8397206,0x9bd7bae8,0x096373aa,0xf20d8692,
  73444. 0xc3b0bf63,0x0a616a4b },
  73445. { 0x6e1339c9,0x2075f3ed,0xbf8b00a6,0x7afaa072,0xbccd9b47,0xdfafec82,
  73446. 0x00ca54c7,0x4713158f,0x38bc31ae,0x449102f1,0x310dfc8a,0xaf98f158,
  73447. 0x59e954d4,0xc9ef2075,0xc527a0c4,0xe8021af9,0x7a192023,0x6e801277,
  73448. 0x7fb02377,0x635f538c,0xe8c9e951,0x5df1974f,0x15cc9097,0x0287faed,
  73449. 0xf7a5115c,0xfa0728f0,0x0fac623d,0x90dbfbe6,0x0311ba09,0xa8d40fd4,
  73450. 0x07c6464c,0x876d154e } },
  73451. /* 198 */
  73452. { { 0xc2d3ea8a,0xd3a4d6d2,0xa842600e,0x36be681b,0xe4070672,0xc53f100d,
  73453. 0x6a7d7a7b,0xe3e5b6fe,0x5d5e1a83,0x6e6994f9,0x76097c2a,0x07cacd22,
  73454. 0xa6791011,0x12d98dba,0x102e0e24,0xddfc4461,0xd493272a,0x4815dbc2,
  73455. 0xa9436696,0x7e38e64b,0x32b2bf90,0x4960eb1a,0xd928e28b,0xda457525,
  73456. 0x2a077c9e,0x72f75b39,0x7fd61d00,0x27760cbb,0x0f4b1456,0xaf235d1b,
  73457. 0xe76d1700,0x3040c23b },
  73458. { 0x4efa9a70,0xb10dc55b,0x53e86610,0xd4de414f,0x09f8a27f,0x3d95c113,
  73459. 0x06661d3c,0x505109a5,0x60eb513e,0xcaa2994a,0x1e7d338b,0x3ee41537,
  73460. 0x4651e71f,0x4fd145fc,0xcbc313b4,0x51bbf838,0x1eb92150,0xb039e078,
  73461. 0x14bf5ac7,0xe8696b44,0x8be0d48c,0x2d667188,0xdd8f2b6f,0xbe93b2f5,
  73462. 0xeb8a7f8a,0xc1dfd1e7,0x90f751c5,0x862b3dd9,0xa32a74be,0x1eb1ad58,
  73463. 0x1ebbc9a2,0x5486d79a } },
  73464. /* 199 */
  73465. { { 0xa1359e13,0xcb2e34ff,0x28196051,0x202d8dbf,0x23564b5e,0xe95e023d,
  73466. 0x42f6ac12,0xfb1340b6,0xb653725d,0x543ba852,0x8d2466ad,0x81aedcd6,
  73467. 0x547c728b,0xbf780224,0x9569fb65,0x559f8a11,0xdfb22ec9,0x505b7a62,
  73468. 0x9eed5e52,0x07107540,0x299f6f11,0x9c899288,0x3db6f8c7,0xa7d69261,
  73469. 0xb3ca79a9,0x30eb7fb3,0xfb2160b0,0xcab99bb8,0xd28b409a,0xd2012568,
  73470. 0x5ac45f8b,0x380f1b0f },
  73471. { 0xe6a0068f,0xc0b99e6b,0xc8a73753,0x4b67cf2a,0xb2faeb7c,0xa6c9a548,
  73472. 0x340260c3,0x7f417f99,0xcc0f739e,0x8ee56855,0x780949da,0xf08b510f,
  73473. 0x8d5c6eff,0xb1770fc2,0xfd96a7bb,0xb4f5abee,0xf2665a2a,0xa07b1136,
  73474. 0xb601dcf9,0x2fb380a4,0x162becc6,0xcc803614,0xee6b83b3,0x3498fb96,
  73475. 0xa8c17eeb,0xea9b0fd6,0xa177efc2,0x5834b5ba,0x5b110b3e,0x929044f5,
  73476. 0xebd7285e,0x4abedded } },
  73477. /* 200 */
  73478. { { 0x700ef376,0x3355e1b9,0x66cdabff,0xd56e5d9a,0x47e87646,0xb3dc2575,
  73479. 0x00f79369,0x28f44b8a,0xa0c52e29,0x08c32b1e,0x3729b392,0x5a78de12,
  73480. 0xb26d239d,0x4184519a,0xe0ce4a6b,0x23f6b4b7,0xacb2a9f9,0x235f6f8a,
  73481. 0xe2064a59,0xbb8bc454,0x1bf3062e,0x37efd034,0x94dff6f9,0x6bac683b,
  73482. 0x8aa7fa06,0xc3364b1e,0xce0b3745,0x0616772a,0xd1e3fb0f,0x46f08d08,
  73483. 0x18e132d3,0x6a20abb3 },
  73484. { 0x6a85cbc7,0xea831016,0x934f9aa7,0xd0990946,0xe778f1b3,0xc2211088,
  73485. 0x2247b799,0x7ea4ff8f,0x454484ce,0xb3171d71,0x4f98c364,0x29403949,
  73486. 0x97df1458,0x5da911f3,0x09439116,0xa6b58093,0x174238bc,0x75f9509a,
  73487. 0x8209758d,0xfeb51821,0xa47925d0,0xae0c6021,0xaf8a315e,0x0e946694,
  73488. 0x6bad04b7,0xae7af8a3,0xf072447d,0x44c15e7f,0xa5456ffe,0x5184668a,
  73489. 0xbf36b977,0x45e353a7 } },
  73490. /* 201 */
  73491. { { 0x93092f71,0x76056764,0xf5b92d71,0xeb66b6c2,0xe2c8b6c5,0x9db3149b,
  73492. 0x20c0363e,0xf62f583a,0x03cd7097,0x688acd33,0xebb916ac,0x85d0c0f8,
  73493. 0x84c19b0e,0x1bf7462c,0x7c4a6ad1,0xc76ed5f9,0xd119f369,0xec8b88ba,
  73494. 0xebe50b83,0x59b8371b,0x866706a6,0x0cc69508,0xf8373d2c,0x531c75a3,
  73495. 0x2a5a02fb,0x4e1cd3a3,0xda39a1d0,0xe8274778,0x75da333e,0xedfc5bbb,
  73496. 0xca79bd36,0x15941f24 },
  73497. { 0xa77dd512,0x42e8c0f8,0x1dc365f6,0xa91b59a7,0x08753862,0xe80d14cd,
  73498. 0xd272faca,0x1624230d,0x4027cb5a,0xeea3ec16,0xc1ef9f03,0xc1700b59,
  73499. 0x0da3148d,0xd411c127,0xc4181af1,0x801ee448,0x9e3a900b,0xedf28559,
  73500. 0x0d09affd,0x5d67b0bd,0x8b370024,0xd839df96,0xe6f836b8,0x3b6307e0,
  73501. 0xbd3201c9,0x5382e588,0x7a1d02bb,0x636d8a6b,0x968641e9,0x70b7db76,
  73502. 0x118fad03,0x6d17c34a } },
  73503. /* 202 */
  73504. { { 0xc181c99b,0xcf608841,0xc87bdcaf,0xb65dc901,0x3720dabe,0xb460b447,
  73505. 0x5377515b,0x4c79c396,0x0a96c277,0xd447f22e,0x2ac0f440,0x0d952130,
  73506. 0xc90583ad,0x8330b26b,0x928904a0,0xe25e977a,0x85c50b18,0x1deaffd9,
  73507. 0xa5ad5f6a,0xcf4dbcb7,0xc8a37ed5,0xcbcd0019,0x1e9850b6,0x7846dd90,
  73508. 0xb0b8e605,0x1ac8194a,0x34132f90,0xb9728571,0xf56ee28b,0x4ce9f149,
  73509. 0x3e9e1d4e,0x1ab9b5a4 },
  73510. { 0x314fa7a3,0x206dab92,0x478ff963,0xcc4af0f0,0x904d9fdb,0x4cce1713,
  73511. 0x12c045fe,0xac20a2eb,0xfd8f6d7d,0x44fc5478,0xca7b6ffa,0x886e72c5,
  73512. 0x6fd6f758,0x7fa4529b,0x92a820d5,0x4df1d1b1,0x2789f149,0x3d812f9f,
  73513. 0xaabb53d2,0x9842f083,0x2a03ab32,0x2648539b,0xb1512502,0x631ce090,
  73514. 0x731f6bd5,0xe1294d15,0x9436e634,0xb229361d,0x3ca966af,0x8c4281c4,
  73515. 0xc21ab3ed,0x24b34956 } },
  73516. /* 203 */
  73517. { { 0x659824e2,0x49bdcb86,0x4e13e74c,0x6dc4ce48,0x6bbe1eea,0xa4c01a26,
  73518. 0x1e3ec457,0x47b2b8e7,0x2f5a8e4b,0x7e8b15e0,0xe333530d,0xe81eb6e6,
  73519. 0x17a45202,0xacba369e,0xd70e4c9f,0x81241431,0x3e12beb8,0xc190af4b,
  73520. 0x11f486fd,0x53270523,0x29fb2bce,0x9f6c41e1,0xb70f6c08,0xbe6287eb,
  73521. 0x3feb4477,0x1479850a,0x9bcf18bb,0xfcfdfb11,0xda80d040,0x925c292f,
  73522. 0x7e3c5bf9,0x212d65e5 },
  73523. { 0xca15cf08,0x23adb386,0x81e172eb,0x4dfa4ac4,0x4d42d0c0,0x9d1dbf93,
  73524. 0x74404dc7,0xd9cf6073,0xe932bfcd,0x60508441,0x1c682a98,0x9ae910ca,
  73525. 0x41ac1cc0,0x9528fc18,0xdbbed630,0xe6a120ae,0x30ccf250,0x94e0e1ec,
  73526. 0xe58bbf2f,0xfe84ba54,0x9faa4415,0xc66d0b4f,0xecee7ce5,0x0c58f1e7,
  73527. 0x6fa6873a,0x7a1d43eb,0x399f1348,0x96c6c5a0,0xe6727ab7,0xe6ef9aaa,
  73528. 0x9a5c2447,0x66afa554 } },
  73529. /* 204 */
  73530. { { 0xc980e91d,0xda5aaba8,0x6ac98efa,0xa93cf509,0x8da32662,0xb0990e0a,
  73531. 0x0081453e,0x01d21530,0x3d71de84,0x2bb0d33e,0x3e19a012,0x465f6d80,
  73532. 0x78a838e7,0x5902ff4c,0x1931348c,0x74e2afb7,0x9cfb057b,0xa4932757,
  73533. 0x3ad03f8f,0x761ea642,0x58ffa40a,0xb7d4c245,0x77a87e30,0xb5e9c0d9,
  73534. 0xc9c84d26,0xd1c5edba,0x3d1963a0,0xeca8839a,0xebf6bf0d,0xbc6f2f35,
  73535. 0x0d58abdf,0x01ef0631 },
  73536. { 0x3ecdcbb0,0x2bf90316,0x27c1c955,0x19e2d728,0x9575c930,0x9e527030,
  73537. 0x96983930,0x0dc1c5a9,0x7cd082df,0xef9f80ff,0xdf97e051,0xcd915075,
  73538. 0x9cc61b55,0xf286fffe,0x80f24cc4,0x352db38f,0x36523ae3,0xed9b99ec,
  73539. 0x10b104a9,0x109a8ca8,0x305203ad,0xc2700fe7,0x769400f5,0x2a2ee24e,
  73540. 0xee0c452c,0xd595d399,0xf7f02a41,0x0ab75d6a,0x0db730b7,0x34108099,
  73541. 0x5e8d1202,0x0e4f5ffd } },
  73542. /* 205 */
  73543. { { 0x0ff14c38,0xbd1c6444,0xaece11f2,0x9a5b59fa,0x22af6330,0xaa4605a7,
  73544. 0x82af24ee,0xddc9f65a,0xeb9a1159,0xf4ee4bfe,0x74e84eaf,0x2463d076,
  73545. 0x0e0baace,0x88cbe1e0,0xd5fabdcb,0x7ca568ea,0xc57eb99d,0xbd80d524,
  73546. 0xe9be9873,0x9c46572c,0x7300b85e,0x918a1dcd,0x40f54176,0x49221312,
  73547. 0xb5b14236,0xf7e324ff,0x2434f16a,0x40dda501,0xa133d97c,0x08833421,
  73548. 0x0876f020,0x33d41161 },
  73549. { 0x9878e5ec,0x7531a36b,0x46918232,0x5de3e321,0xd0a30464,0xd15f9a33,
  73550. 0xaa173659,0x734c1b87,0xf925d4fe,0xac2094a2,0xc262b0f4,0x43c965a1,
  73551. 0x447d5cbc,0x759c903e,0x05239300,0x92af215e,0x1f593f34,0xfffb6d5f,
  73552. 0xc3cddb5f,0x65943b4b,0xbfdd5408,0x9d03a29c,0x198d76c0,0x8f7cda6b,
  73553. 0xc0f27b59,0xc0790a22,0x8cb58ccf,0xba557a84,0x76c54fdc,0x5922052d,
  73554. 0x47b6b466,0x2d3de7aa } },
  73555. /* 206 */
  73556. { { 0x65add3b7,0xaade7462,0xabf24c2a,0xe5888f35,0xe1a57d93,0xd41549ca,
  73557. 0x2c76f7bf,0x0e22e18e,0xbe3202b3,0x67f288ea,0x1d1d0f0a,0xb79a66ba,
  73558. 0x2881ad18,0x0e0ab749,0xc7adb0e9,0x7d424086,0x2842132f,0x870c32c5,
  73559. 0x58f9a09e,0x858477f1,0xec025589,0x422a9372,0xa5098777,0xbe428c5c,
  73560. 0x57660058,0x45b79564,0x957f37cf,0x6c7fc631,0xd6316289,0x8b7023dd,
  73561. 0x5b1c12a6,0x47003bb6 },
  73562. { 0xc91c1c96,0xd99401c1,0x27a12970,0xaa5dcdf9,0xc3c29107,0x3ab92e17,
  73563. 0xa3fe4710,0x26fce8f7,0x4ee998ee,0xb0d09d5e,0x8e3a41f8,0xafa62204,
  73564. 0xa26ca506,0xb1c012a5,0x99b57252,0x2c6f734c,0x512f7fe1,0x1093d79f,
  73565. 0xacee19a6,0x2f30906e,0x056d1ea6,0x6bff8381,0xeff35f21,0x61c75856,
  73566. 0xc1ad2224,0x6e07e978,0x6b20fde8,0x2cca6ca1,0x633fe81b,0xab4d6d2d,
  73567. 0xb06a2ce6,0x73dff504 } },
  73568. /* 207 */
  73569. { { 0xd8e20fb8,0x8b615805,0x82b533f0,0x7c6873e4,0x56a854ca,0x5205f001,
  73570. 0xcb369211,0x87fec6ac,0xc7f092b7,0x1fa3c0ec,0xe845fe4c,0x5b36647e,
  73571. 0xf8b1f112,0xd4781e85,0x8b0f1a6f,0xc6526839,0xdcb8eb92,0xceeb8c6c,
  73572. 0x8e5f6d52,0x133f0ead,0xc8d934dc,0x31883e23,0x428ac45a,0x214ed5bd,
  73573. 0xdbbfca85,0xf77ca492,0x07e5ae13,0xdf4113fe,0x72ab05fb,0x63e4a0d2,
  73574. 0x7148f535,0x7544d0b7 },
  73575. { 0x80797ace,0x4fe8d134,0xaf86d97e,0x216d6aa0,0xef5a68fc,0xdbf0a688,
  73576. 0x9f9b2684,0x18b26f45,0x8999d2fc,0x52fefcfa,0x62423955,0xd5af8d82,
  73577. 0xf63a3780,0x8f123469,0xdcd4feaf,0x2933454f,0xa73b5d09,0xba8018b7,
  73578. 0xe5552c18,0x9af1f276,0xff26bb1c,0xc5d4773d,0x06dd4f44,0x9ef49410,
  73579. 0x5f39ba49,0xad8f12f9,0xf66ca4f2,0x5767f6dc,0x7922f59a,0xba8773f1,
  73580. 0xc1e42d49,0x220081ea } },
  73581. /* 208 */
  73582. { { 0xba37a0ba,0x3043d573,0xdd176df6,0x05a431bc,0xc42070f7,0x03322cfc,
  73583. 0x67c2d109,0x5cabd30e,0xcbf8bcfa,0x362c95de,0x7787b10b,0xd767d277,
  73584. 0x6ec05e64,0x612c915e,0xce69c30e,0x9e669631,0x682e2635,0x27c9dd8f,
  73585. 0x95ffcc38,0x79021f12,0x8a2adca2,0x06a8ee79,0x4b5d500a,0x8e00e784,
  73586. 0x8d80d6c5,0x87746fc7,0x915f10cc,0x246053be,0x219f6fd8,0x844e328b,
  73587. 0x11bd3733,0x620541ac },
  73588. { 0x509e5a29,0x0f7fd382,0xb432531e,0x8748d7d0,0xcd3883b9,0x8f749354,
  73589. 0x8bfbb17a,0xc6b8ac74,0x05f2d2c5,0xa4616a66,0x1bcb1b83,0xb3d96625,
  73590. 0x2fee265a,0xcf753104,0xdb225058,0xc70d73fb,0xf0c2d556,0x1211d434,
  73591. 0x54b259b3,0x862061d8,0xc42b3f7d,0xffe4606d,0xe86a4949,0x4c5c8585,
  73592. 0x160eedac,0x04ddcc8b,0x568e2420,0x1804ce67,0x42141656,0x91f3855a,
  73593. 0xf932be97,0x7f378198 } },
  73594. /* 209 */
  73595. { { 0xdfa6639a,0x9a374bda,0x02ab7391,0x0cbd48d4,0x47031e2d,0x5c5ef236,
  73596. 0xd0599d1f,0xb49ee2bc,0xe0d38443,0xd285eb60,0x269392e8,0xdbbea92f,
  73597. 0xb8bc538f,0x91455fbf,0xe469b768,0xae259ff1,0x41de5682,0xc1cecb1f,
  73598. 0x9952d1ae,0xc876f071,0xe7bf7446,0x1ce25181,0x282ad2f1,0xcb93ad86,
  73599. 0x6ba4ef67,0x8fa3cd31,0xe507aa3e,0xfce68a04,0xa61bb608,0xced74170,
  73600. 0xf6ac10d0,0x6de716b3 },
  73601. { 0x172d6dc5,0xd4e58d04,0x6397c65c,0xbed2cde6,0x0c9eb4e8,0x7ae77e18,
  73602. 0x75fa2edb,0x56275468,0xa91e6738,0x4b30324e,0x235c8b2e,0x6023a856,
  73603. 0xa8f92887,0x9df6d6c2,0xf6f5e8b5,0xec2c185f,0x3ad5748a,0x7892e12b,
  73604. 0xd54aefbc,0x7aebb4f2,0xee868821,0x14915448,0xb1d9bd5b,0xa26c5f71,
  73605. 0x2ff00df7,0xe5ccd166,0xb95b1dee,0xebc99f17,0x3fe1f774,0x90983616,
  73606. 0xbb3d25b0,0x51f90830 } },
  73607. /* 210 */
  73608. { { 0xf2922461,0x49376fa1,0x1650d0d1,0xdbb1b1c3,0x0dd8608d,0x92b91c33,
  73609. 0x36b89906,0x3e612c4b,0xdf560052,0xe1977b0b,0x636a2545,0xf8afff70,
  73610. 0x11723d8e,0xcda7d278,0x81bde7ba,0x0b0bc4bb,0xed2a578e,0x3cb080b2,
  73611. 0x171b2e02,0x5bda0d0d,0x941bb9ae,0xf6df38cf,0xc14a65c5,0x85dd81db,
  73612. 0xc19dd98e,0x7f98c82d,0x52206f93,0xc613747f,0x5f5bbe78,0x9e13a2c2,
  73613. 0x0aa34be7,0x5eed218e },
  73614. { 0x01d4dc0b,0xe1565754,0xf566bb07,0xa1ae5f27,0xb82225d5,0xe985ebeb,
  73615. 0x1189ec6b,0x5f3ad21c,0xecce4d9d,0x17da518c,0xd6b65b59,0xc84a2d3e,
  73616. 0x8ffa771c,0x7f988175,0x2ac69a7a,0x50d6ae12,0xc6e6846d,0xcb7f30b1,
  73617. 0x5bd0bb13,0x8c023a60,0xd73f2407,0x9a10fecd,0xe5f0a996,0x8c5158cc,
  73618. 0xbd8f5806,0xd26bf615,0x915a46e1,0xaf32ea87,0x0287d308,0xeaf74e81,
  73619. 0xa6264254,0x8c14ba06 } },
  73620. /* 211 */
  73621. { { 0xb17ee201,0x0c877895,0x88e57a77,0xc05aa471,0x97822456,0x19c3e763,
  73622. 0xc9c3ba1d,0x0be6f8c0,0xb4389ebe,0xfe85f4ff,0x0ce7fbb6,0x538bccce,
  73623. 0x65266c64,0x876eab2a,0xcf9a3842,0x5c9ac690,0xccc8f981,0x9f5cf3b1,
  73624. 0x9cf687de,0xfa17be6a,0x83835c15,0xfcfc10fc,0x150ef2eb,0x086b0fdb,
  73625. 0x884a52e6,0x9f97ecd9,0xb0cd1eb8,0x416e6fa2,0x3ecc03ba,0xe2bd1599,
  73626. 0xeabb165e,0x645c0a5d },
  73627. { 0x50aa7e31,0xd94c4205,0x2f851da5,0xaec8df0c,0x3c726e6a,0x99646909,
  73628. 0x2619bf9a,0x72dbdc36,0xe253fbd5,0x1b4260e0,0x8c709e06,0x97c259fb,
  73629. 0xcddaec5b,0xfabf7cbb,0xe4b703e9,0xb4d5e8b1,0x0734efdd,0x1b06e56e,
  73630. 0x1f55f8a5,0x02d4a4f9,0x3f565c8d,0x7f8608ba,0x816d1d94,0x822f47d2,
  73631. 0x5ce7b136,0x0cc36156,0x31d04242,0xe46ee5ef,0x683567f6,0xb2a65f70,
  73632. 0xd2fa6c91,0x27e9ff40 } },
  73633. /* 212 */
  73634. { { 0xd7e952e7,0x75251893,0xc735bf18,0x15b30583,0x96fe0491,0x732b5992,
  73635. 0x806d2fca,0x27451858,0x1b885ed9,0x71ab76a0,0x6d9f55ec,0xbdce9d97,
  73636. 0x48f2ba9c,0x3da60b20,0x592b132b,0x6977c086,0x099051d7,0xb6dca9cb,
  73637. 0xd188ae25,0xd9c2ab23,0xe20aaf3d,0x9f469f3f,0x5aad74d0,0xdbd1f7cf,
  73638. 0x22a9eb3b,0x3d5efe5c,0x137010c4,0x8c5edfa2,0x57870260,0xada2217b,
  73639. 0x3dac9776,0x4feee567 },
  73640. { 0xb5d3d780,0x30e18d52,0x07166744,0x4dadb5d3,0x5a742156,0x320d386e,
  73641. 0x8d6bbb86,0x5d8c290e,0x2d263dd1,0x981a4323,0x98984636,0x33d0e7ca,
  73642. 0xa519acb1,0x5138784d,0xdddc81ff,0x832e3fab,0x3199a43a,0xfc278594,
  73643. 0x32743163,0x5b4cabcf,0x74f94fa7,0x9fa010bd,0x5694a627,0xc28a743d,
  73644. 0xcb657a24,0xc1d2a888,0xe86a25ea,0x7eef2503,0x04c561ff,0xed11a5d3,
  73645. 0x9c9ede0e,0x4fe818e7 } },
  73646. /* 213 */
  73647. { { 0x7fc1c7ff,0x00252c9d,0x9fa89ad1,0xa9bd419d,0x4064e9cc,0xc93a124a,
  73648. 0x43942ecc,0x384cbcb8,0x8749695b,0x004c21fd,0x421165bf,0x69c81d9f,
  73649. 0xdde01102,0xe2325628,0x5a9b004d,0xec937457,0xf6dcfc21,0xfb3346bf,
  73650. 0x4d372c7d,0xac4da64b,0xf20494e2,0xcecb7ad3,0xe867c150,0x562c41b5,
  73651. 0xc2b723d8,0x299395ce,0x7ee53231,0xc91adfc5,0xf10b6597,0xe06f1161,
  73652. 0xb74d3ffc,0x81915529 },
  73653. { 0x6ed9d4ee,0x8ec12431,0x689aff01,0x3dffa154,0x2a89a3f4,0x4aba349f,
  73654. 0xd467efb2,0x2db1e8e2,0x039102e2,0x18dea354,0xe52f082b,0x422ab853,
  73655. 0xed36dd47,0x7130a2c1,0x0295d1ee,0xca60e86d,0x7c7f5ad3,0xe6ac6808,
  73656. 0xde864658,0x0f83cecf,0x461d1265,0x72e66c21,0xbd385099,0xfeef4150,
  73657. 0xa6632289,0x0f183f3a,0x792dc795,0x275454be,0x11367702,0x2744c11b,
  73658. 0xe8ea6ef3,0x7d06bcc7 } },
  73659. /* 214 */
  73660. { { 0x7090212f,0x89285942,0x5521e844,0x691b7d4c,0xbe2dbb92,0x4c038422,
  73661. 0xbd81f880,0x317721ed,0xac89bc36,0xc136cbee,0x7b8f004d,0x4f71b60b,
  73662. 0x4e218ab8,0x269132d0,0xe6cc814d,0xb0e2496e,0x75fadc15,0x0b2ce317,
  73663. 0x66d223c5,0x82e3c084,0x4c612f8b,0x9721caa6,0xa4b65355,0x59a751eb,
  73664. 0xc7d3d9d1,0x3433aad5,0xe80d4246,0x1e61b9d2,0xfc673caa,0x149f655f,
  73665. 0xd0f9cb92,0x48b52b99 },
  73666. { 0xefdc05be,0xa3915399,0x13e095e9,0xde70db18,0xcddb3fda,0x447862e9,
  73667. 0x1a009451,0xa2b03162,0x23920ea3,0x4b27980c,0xa23b8feb,0xac5394f1,
  73668. 0x3e5616d4,0x163f7256,0xb714219a,0xaa0ff93f,0x93d62474,0xd26f96d2,
  73669. 0x7dcfe276,0xdd212ea8,0x47038d15,0xab27bf2f,0xf418168e,0xe58c8325,
  73670. 0xb32a989a,0xe3704222,0xbfc9f13b,0xa3694390,0x0d0684ad,0xf16e2606,
  73671. 0x9d8c76ec,0x17c0de87 } },
  73672. /* 215 */
  73673. { { 0xdcc01958,0xbca5f453,0x1ce88393,0x7d945954,0x561f5b6d,0x5e6350a1,
  73674. 0x7e2d36bc,0x291c3c86,0xa5ac3a6c,0xf6c7ed84,0xd98006cd,0x7913c40b,
  73675. 0x5671ec3b,0xf78bb087,0xb43e89a9,0x1c928f6e,0xae1ea1ed,0xfdf28df3,
  73676. 0xb924b2b5,0x62bba5b1,0x1a116e05,0x491d2705,0x167ed3e3,0x08ec02b7,
  73677. 0x5bc0b046,0xe291cf7b,0x8c5d7f59,0x30e50169,0xf5c799b7,0x0c7c350d,
  73678. 0x0ac6e1d7,0x6862b9e2 },
  73679. { 0x9ffa1f64,0x56c6f4e7,0xa1e24349,0xfed6a91a,0xcdb75232,0xe9a0ee0c,
  73680. 0x0322d607,0xbfc90b37,0x462fef87,0x29480ad2,0xc2bfcf34,0xfc214969,
  73681. 0xa539e38f,0x6e5211e0,0x12a5149c,0x2a59ec26,0xd706b532,0x195fe212,
  73682. 0xe99c8429,0xf77fb108,0x5dc80482,0x74ceaea3,0xbd92d298,0xa5a6030b,
  73683. 0xaaea15ee,0xad42dca5,0x4987109c,0xd6ac3bc7,0x290af649,0xc64e1c40,
  73684. 0x51f8de6c,0x5093fa2d } },
  73685. /* 216 */
  73686. { { 0x4c2d553b,0xc4cf3280,0x3b966c29,0xdc1abe22,0x2296914a,0x556a549c,
  73687. 0x999976c9,0xd8c9f8b5,0x776e83f3,0xc22c57bd,0x7c85ec57,0x4f2942ab,
  73688. 0x6e2c61f5,0xef3407e5,0xf213db48,0xf005e8ca,0xf32698c7,0x470c853d,
  73689. 0xcac0a54b,0xe6f488d7,0x60b7501e,0xb6bd6bed,0x714a4bd9,0xf0103106,
  73690. 0x6e098894,0x5285bc3b,0xf5f92a00,0xec06741a,0xef7ef24a,0x32f16426,
  73691. 0x6c77a438,0x12f9c44d },
  73692. { 0x83313a1c,0x1951e964,0x33c58b37,0x98edd3da,0xc7ac4044,0x4edbbf52,
  73693. 0x0dcb5ee8,0x866ca6f7,0x6dd422f8,0xec0ae8f5,0x0661ec2e,0x1077bc54,
  73694. 0xd422523c,0x6d39913a,0x58e7cb3e,0xd105e1e8,0xc979bb45,0x47c9397f,
  73695. 0x0997b592,0x3221d4a9,0xe8952fe7,0x0ef628a3,0x4e946241,0xd08d5827,
  73696. 0x59780f40,0x64cbed0f,0x08e110ec,0x13d7c227,0x7679b1a3,0xd186d866,
  73697. 0x26ae1d18,0x02f75e4e } },
  73698. /* 217 */
  73699. { { 0x47f307d7,0x1b637ebf,0xd0141477,0x6b644a6a,0x2e05a80c,0x82a33d65,
  73700. 0xfed07b31,0xc8f1a0f3,0x3696e597,0xc09ee7f9,0xc7ffc01e,0xcdaa7ec3,
  73701. 0xf8f373b9,0x549f88fe,0xc3bb8989,0xc88d1961,0xdfcaa7b7,0xd92a4fe9,
  73702. 0x3ae4ab20,0x12ff9ee2,0xf5ecb1a5,0xf5aea641,0xe32fb47d,0xe769237f,
  73703. 0x25d085c0,0x96a5c420,0x26c755a2,0xdc912558,0x9bce9723,0x580b985f,
  73704. 0x63961941,0x72b1b566 },
  73705. { 0x790e5558,0x9d708a08,0x0689af80,0x98536041,0x42313b5f,0xe85e7b8a,
  73706. 0x55a49d1a,0xe6ba1292,0xac371b0b,0x5e76c4b0,0x938e6e19,0x58504f39,
  73707. 0x60ae9a21,0x8dd41422,0x968485ce,0xd8b04e9b,0x887efe43,0xf94c4ba5,
  73708. 0xf11c5e73,0x11268e67,0xcf6b99c4,0x92623e28,0x7a0a9662,0xf2d0aaa8,
  73709. 0x4ca02ed3,0xb266772a,0x2d63b551,0x68ee8e4e,0x2e78b5b5,0xcdebb299,
  73710. 0xe17225ad,0x5df19216 } },
  73711. /* 218 */
  73712. { { 0x8df2e7e3,0x20027e1e,0xd8da07de,0xb183cc68,0x4b4ae694,0xce35ba69,
  73713. 0x3ca62e88,0x896d97df,0x52efed2c,0x3de4713b,0x26bd084f,0xd006c40e,
  73714. 0xfc81923b,0x1e9b71bb,0x1aacc6b0,0x9991c7b6,0x8f656840,0x650c9364,
  73715. 0x87f47524,0x138561d1,0xbffd3ca2,0x610f2b11,0xfa191418,0x96915faf,
  73716. 0x955e5309,0x8f1236de,0xa1872d79,0x613cbeea,0x66a2a48b,0x7f7b44ea,
  73717. 0xe0a89c32,0x452265c2 },
  73718. { 0x25430010,0x4ad5ec79,0xebd090c0,0xcac786ff,0x20a9d3f5,0xa5f9f4ff,
  73719. 0xa3edc65f,0xfcbf4112,0x0cf3eb11,0x8824839c,0x8aa5b700,0xb8dd6d4e,
  73720. 0xb7568ab8,0xe2271dfd,0xb744560e,0xe43ec373,0x1cf75296,0x78eaf926,
  73721. 0x3fa96d9b,0x1809ae0e,0xdc25dfd5,0x0b312d2d,0x6bab7711,0x6b8f78b4,
  73722. 0xb5ecf1e4,0x069efc8d,0x609fecaa,0xc1952bae,0x5f4dbde1,0x43e302ed,
  73723. 0x1e078555,0x14b02bf9 } },
  73724. /* 219 */
  73725. { { 0xb87e5b57,0x2c71c768,0xf531a557,0x0bcc78f7,0xf7597dc8,0x4ff93f8b,
  73726. 0x139e175f,0xb28e026d,0xcb94ca6c,0x6b83b727,0x0079f7fc,0x2eafe3b2,
  73727. 0xcf3bd170,0x2aca54de,0x6af0dc6c,0x17c4133c,0xccf5e35e,0xbea1e665,
  73728. 0x345505c6,0xa6691a48,0xe6100b89,0x2633abd0,0xc17d0388,0x966c6706,
  73729. 0x1a0cf90c,0x7aefffbe,0xd0add64c,0x4d847be7,0xaea2aa46,0xd49bcdfb,
  73730. 0x2cc7d0a5,0x85e07e74 },
  73731. { 0x0bc25bca,0x23aae0a6,0xe44f64ec,0x6e8e55f1,0xb607b773,0xe1e696d8,
  73732. 0xd3005909,0xaa90a746,0x2cbc4990,0x072b1ccd,0xc68e2f5d,0x0d0fe6c6,
  73733. 0x53e28ec9,0x920ec5f0,0xf0040cc1,0x79b21fb4,0xfcc4a2c7,0xa7375bd3,
  73734. 0xe1bac7dd,0xf5f5def9,0x35c0f8d3,0xdc315d79,0x2cacd318,0x7117c170,
  73735. 0xe926f71c,0x6f2823c4,0xed02f39a,0x38db58bb,0x7db69323,0xe5b49231,
  73736. 0x8d49f430,0x0964039f } },
  73737. /* 220 */
  73738. { { 0x56999eba,0x21774f16,0xb1de6305,0x3d8ee287,0xde0b2669,0xd81af726,
  73739. 0x3f8942a1,0x37446939,0xea03e13c,0xbcf6b615,0x94e273cf,0xd30c0c35,
  73740. 0xc6725c56,0x4fd33a56,0xa8be97a2,0xa57534ad,0x7c22a251,0x799242a6,
  73741. 0x9d0c5c49,0x4e51bdb5,0xc6a42768,0xd7cd76cc,0xd426bf59,0x914097ac,
  73742. 0x66e9beb2,0x59404a2c,0x5c96e3e9,0x4738fe98,0xaad666d0,0xbcbb3e0e,
  73743. 0x63bc5e56,0x626b0fd2 },
  73744. { 0xe1a1ec42,0x47217dba,0xab5acc50,0xaa6ae7db,0x865331d1,0xb7e1ab1e,
  73745. 0x3d30126f,0xb8453070,0xdee61851,0x280649e0,0xea689544,0x8806f4a3,
  73746. 0xcb56f632,0x4bbe43ad,0xbcaff94f,0x036b9bda,0xbd0637be,0x0d941e65,
  73747. 0x686f3abb,0x82179d44,0xaad6afd6,0x1486912c,0xff7e1534,0x9a3b891e,
  73748. 0xeb86fd96,0x88c426ce,0x117928c3,0xb56e6a81,0x96399e00,0x933e7135,
  73749. 0xa17b6ac1,0x09bbddd9 } },
  73750. /* 221 */
  73751. { { 0xe4fd3673,0x75e39c1d,0xa65c8e07,0xf880d9d1,0x7289c7fe,0x4725c1dc,
  73752. 0x3529d200,0x5b6735ee,0x3c747af3,0xc1f8f2ed,0x912efdf5,0x5cf3998f,
  73753. 0x49859c39,0xed722618,0x0e69795d,0x23793a2f,0x86b1d2a7,0x8a6ab8d6,
  73754. 0x22a882e4,0x00c815de,0xf9db8d7e,0xbe77d6fc,0x02267547,0x0886fb32,
  73755. 0x49c10edc,0xb62687d4,0x7c83ed4c,0x9f1c3e17,0x5af366ea,0xe6d5d7f0,
  73756. 0xd1efad24,0x2eaa01b8 },
  73757. { 0x1f357c74,0x5e47fb70,0xa9e3b794,0x93085c4a,0x6e85a905,0x4f098733,
  73758. 0xbe0244c9,0xf53808ff,0xa3b5660d,0x91dddf93,0xf3b95ed6,0x8b76377b,
  73759. 0xbb3920d4,0x91b911b7,0x86a13cf3,0x7ccf08bf,0xea018e58,0x53ed8f97,
  73760. 0x78c55194,0xb1ea4343,0xe0d2d5a6,0x8e6adde9,0x9b96259a,0xfc2b248f,
  73761. 0xeef17ddd,0x96ebceae,0x557f9c85,0xf694b443,0x07d5bba8,0x48cd150f,
  73762. 0xb4c1986b,0x02d31de9 } },
  73763. /* 222 */
  73764. { { 0xde79499d,0xa6bb9e1e,0xfd0fc2ad,0xf6ca8ff8,0x1a7d9356,0xbec0f8e8,
  73765. 0xe8f06327,0xbc3d1c9f,0x3b300beb,0x805c7217,0x413c181b,0x00420a08,
  73766. 0xf0ca9d01,0x9e9a167e,0x1aeeddd6,0x076c909d,0x8e3a8a72,0x64a1997f,
  73767. 0xa77b429e,0x3ce7f7a7,0x5c94d3e9,0xaac0fbf4,0xe6d48407,0xf37694a7,
  73768. 0xa91921e7,0xf56679e2,0xee1dbbd6,0xf23fe0f3,0xcbf9fa99,0xc7917566,
  73769. 0xe0f4d765,0x965860f2 },
  73770. { 0x7fa5f79c,0xe734702b,0x5af2d26d,0x930bd426,0x6c73e0ce,0x45bd8b98,
  73771. 0x4ee44a2d,0x7dbe7bed,0x956c8a1a,0xc129e024,0x77cdf80e,0x6fdc05ac,
  73772. 0x589ca59b,0x70a6ba2b,0x999825af,0xfc484021,0x7a23f0b6,0x1d284b54,
  73773. 0x28a0a8af,0xb1da10a4,0x2b2af6d8,0xb1eb1b31,0x33935ee3,0xf051443a,
  73774. 0x8effa6ec,0x7a07eb26,0xd662654c,0x16ee4086,0x4549ee4c,0x7a7bc501,
  73775. 0x1fa98a52,0x65081032 } },
  73776. /* 223 */
  73777. { { 0xb67ed9b2,0x49f0e460,0xc36d93d2,0x0cda0fd0,0x88c75e1c,0xbb5963e9,
  73778. 0x614bc0c9,0x757bbe93,0x9a768605,0x9a9b8801,0x48edc544,0xa8b7e2af,
  73779. 0xb51a5985,0x9e77ed9e,0xebbf024c,0xdd025274,0x1545c636,0x598b6288,
  73780. 0x4800dba0,0x39bdaed0,0x81e2a23a,0x7fc20139,0x550cb4f2,0xdc66fd5c,
  73781. 0xb52068c7,0xad27032f,0x8169fa15,0xc9a0bcae,0x3a7ca8a2,0x60606f21,
  73782. 0x9862652f,0x98295046 },
  73783. { 0x2e11c128,0x3e374600,0x0e6dca7e,0x80dfae5d,0xd9552264,0xe44016e2,
  73784. 0x880b7143,0xf65f88f2,0x526b881c,0xca3d28d4,0xdfb86afe,0xf9c59dd1,
  73785. 0x4c74f958,0x548860c2,0x9cb69f4f,0xd06ea43c,0x7334ecec,0x5343c9ae,
  73786. 0x35329713,0x5cc2ccd6,0x5f3a6c0c,0xa95ff403,0xb372653b,0x2e01a1cc,
  73787. 0xa250523d,0x31510fdf,0xa6227eb2,0xeee538e2,0xca23cd10,0xeadfc8a0,
  73788. 0x3e78f54b,0x4b7e6e1b } },
  73789. /* 224 */
  73790. { { 0xdb5f928b,0x79c9076f,0xb7347cec,0xe6250bb6,0xac00ec41,0x54b67798,
  73791. 0x9d9619c7,0x900d20ba,0x59e4343f,0xed42c0d0,0x451935d7,0x3df39e85,
  73792. 0x64f701ce,0x26391182,0xe1f87aac,0xce8f2554,0x65f91aaa,0xfddd6789,
  73793. 0xa324539f,0x96cd163f,0x4bace995,0x5c815f2c,0xa94f9ea5,0xd78c8c2a,
  73794. 0xef24e455,0x7ab2aff4,0x1cddc26a,0xf0ed6409,0x00ca2822,0x954a420b,
  73795. 0xd3297658,0x0611c4c5 },
  73796. { 0xa9e81829,0xf192001c,0x08a282cc,0xded33320,0x8f9ded9b,0x0bfd7de1,
  73797. 0xb7889003,0x6793ac0d,0x3577a5dd,0xbb00d91d,0x802d3c2b,0xe17a23a7,
  73798. 0xfb549014,0xff95f88c,0xc71b6e07,0x7cd1bf4b,0x23588c8b,0x2e3b24a0,
  73799. 0xa4112076,0x9b5335b8,0xc4056d30,0x2481c05e,0xe916a1b5,0x55c7410c,
  73800. 0x850179f4,0xbbe03271,0xb3cd1208,0x15e6c177,0x90cbfe50,0x509a24c0,
  73801. 0x1c108566,0x82079529 } },
  73802. /* 225 */
  73803. { { 0x1c7d353e,0x5d2d3cff,0x7de0ce3b,0xd5e7eccd,0x6ca87635,0xb4b1075f,
  73804. 0x25f9ad3e,0xda8404e0,0x205cb5ae,0x6b963e89,0x09f221a1,0x9e5ee0d8,
  73805. 0xea41aca4,0xd64c85d9,0x34442a34,0x6a46c4e9,0x3cf655a4,0xac6ff97e,
  73806. 0xe5417d7c,0x76565c1e,0xeebf9c4c,0x681009a9,0x88da6388,0x95b61d39,
  73807. 0xf6b472c6,0x6402b46a,0x0b7f1171,0x1fde5165,0xbe0c05e3,0x94f8f273,
  73808. 0xa88344a7,0x7487b036 },
  73809. { 0x9c3e2370,0xa860e575,0xf8048719,0x19d58193,0xa6e2f9aa,0x3a0dbf3c,
  73810. 0x6144719b,0xb6c7e959,0xdeffec21,0xa9049c74,0x3f50cebf,0x8ba064b2,
  73811. 0x49a1de15,0xb12822c0,0xb1d527f2,0xb654b7d9,0x0ffd0430,0xc470859d,
  73812. 0x4f05446b,0x37c74a67,0xa3add995,0xe553251b,0xe33533b5,0x4a3ed6cb,
  73813. 0x27e419ce,0x2f2f44d0,0xa5d1b979,0x2d84ee82,0xdb6fa69f,0xcc76b123,
  73814. 0x21fa3bdd,0x834f85c5 } },
  73815. /* 226 */
  73816. { { 0x2ce9b31a,0x329347c1,0xfe3fb3b7,0x1d88522a,0x52ff90fd,0x4bcefb4d,
  73817. 0x2b1a081d,0x53b17386,0x2a411f08,0x538c11ba,0x141b603a,0x7895b93c,
  73818. 0xb10bd741,0x2993b9aa,0x09912986,0xccbbd046,0xeea0aba5,0x669fafb0,
  73819. 0x35661897,0xd4844622,0x367ffa54,0x4a63b89c,0x1c3478da,0xcbad5d1d,
  73820. 0xaa6034f7,0xc5339227,0xe61b1391,0x0e6d705f,0xf74ff515,0xdd14b660,
  73821. 0x5332b54c,0x639d8b0a },
  73822. { 0x162217cd,0xfa423162,0x811c28e6,0x2e0e4a2a,0x21766dc0,0x68d9ce18,
  73823. 0x046a06ef,0x51263739,0xdde92101,0x44eea231,0x114298d3,0x0607c8f2,
  73824. 0x63d957e9,0x27f272ba,0xa5e8cae1,0xe7ce80cc,0x24f7a63f,0x5816ebe2,
  73825. 0x89673e34,0x4dece5a7,0x536babd4,0x13756a22,0xe3bf77af,0x644d61ae,
  73826. 0x2bcf98bc,0x60b2bf6e,0x29fa962c,0x3b0b59f3,0xabb50023,0xb0769a1a,
  73827. 0x0c75402c,0x40903136 } },
  73828. /* 227 */
  73829. { { 0x1670433f,0x84d2873a,0x25493dfc,0xc9394df6,0x80fcf89e,0xeb05a19a,
  73830. 0xdb297616,0xe39e4310,0xd9e63046,0x50742dc9,0x1de9ca9e,0xf31ad8c8,
  73831. 0xfb7b1d0d,0x86aabf94,0x1b3c82d1,0x36cda27a,0x39702d84,0xfb1a2ef4,
  73832. 0x46081299,0x280bfddc,0xd2396238,0xe4b2b48d,0x7b3c9353,0x2db2c2f3,
  73833. 0x12fb8a69,0xd5b5b317,0x08180474,0xf9b87a3b,0x1e952578,0xd8590986,
  73834. 0xf37a2bc8,0x80668eed },
  73835. { 0xb39a0249,0xe2edcd35,0xb2f8aeae,0xaf230cd4,0x7223df05,0x295b15e4,
  73836. 0xe0e937f4,0xbb66982a,0x8cbc9162,0x019d2b72,0xcf49dca1,0x5c512ae9,
  73837. 0x630f07b4,0x11b491a7,0xa03874e9,0x48d4f34c,0x44cb7433,0xc1fd0ea6,
  73838. 0xf95b30c3,0x13f79ae1,0xed8b60ac,0x40362d4d,0x61ead81c,0x9e8314ff,
  73839. 0x498c3d28,0xed600dd4,0xc2521702,0x5fcb1c19,0x3a9c1f33,0x592329fc,
  73840. 0x1bde6ce9,0x04677548 } },
  73841. /* 228 */
  73842. { { 0x39233c96,0xee3de56e,0x80737eaf,0x868c409c,0x201abc68,0xacae11bd,
  73843. 0x2b486205,0x0f2cea9b,0x6f19056c,0xe32387e1,0xa5dc2a41,0xea75365a,
  73844. 0x12b4be86,0x76c29acc,0x8d63294d,0xa01fcab7,0x0cab9f24,0x81dbe88b,
  73845. 0xf414c054,0x76646e5b,0xcb96b7aa,0xfe111893,0x7664e097,0xb649f5b1,
  73846. 0x53fcf5a9,0xa196422e,0x0b7ff634,0x5978c9bd,0x3c229895,0xb5feb38e,
  73847. 0x0833c456,0x038a49fb },
  73848. { 0x13e93257,0x35e3818c,0xa612741b,0x14cebc9d,0x7caac06b,0x4f6e9249,
  73849. 0x3daa1116,0x82278e33,0x4de2034a,0xe7cc565e,0x0a1ba630,0xbb7dc95f,
  73850. 0x66956fbd,0x81dd9f23,0xbb132dd6,0xc63e6319,0xfc241337,0x6e22b022,
  73851. 0x7e8beb1c,0x23848193,0xd8c938ac,0x83b1994d,0xa6bb5644,0xb54cfaca,
  73852. 0x06f91807,0x1a7cd44e,0xa8f8d9f3,0x1dd439bb,0x7f74a8e6,0x660c2a78,
  73853. 0x121b5660,0x4bb76e22 } },
  73854. /* 229 */
  73855. { { 0xe6354817,0x7a151e8a,0xf038b438,0x33d494ea,0x85958986,0x4c86c688,
  73856. 0x1dcbac12,0x72153827,0xc0edad06,0xf487af8c,0xe500e5d6,0xad33051f,
  73857. 0xd6e47f55,0x0a711b1b,0x8c746ad5,0xa68709a7,0x6402f35e,0x27f17262,
  73858. 0xfb30c130,0xc6d08efa,0xc06c7497,0x9ef1c041,0xdcc3e2da,0xd0c74ece,
  73859. 0x092e1073,0x30c5f96e,0x2aa12b74,0x0f1393cf,0x2107eb02,0x24584016,
  73860. 0x7b76f98b,0x8843d25f },
  73861. { 0xedb2a83e,0x4e1501dc,0x2bb8d724,0xbcfe8fb0,0xd925df62,0x09020659,
  73862. 0x42ab6fc3,0x3c715dcf,0xa0f09dfd,0x73c05055,0xe3590aea,0x126745d8,
  73863. 0x76ff749e,0x5382f4d8,0xa920c663,0xfc69feef,0x9fd711ca,0xde160211,
  73864. 0x9075c4d5,0x4219c3bd,0x3ded6bf2,0x3800cbd1,0x6263a116,0x8c7ea0eb,
  73865. 0x7d264c37,0x35bd7958,0x7159c98c,0x56e22e45,0xfa7373b5,0x71bf2a2d,
  73866. 0x8935c949,0x0503f939 } },
  73867. /* 230 */
  73868. { { 0x71dad4f6,0x65addc66,0x024bea1b,0x238e4889,0xf605d3dd,0xfb76c8e2,
  73869. 0xb0d96b89,0x13d5f5de,0x6601b2cb,0xe0b5ba35,0x83e3d254,0xe37d491d,
  73870. 0x240c8ea7,0xe8860423,0xe91c99ba,0x374182f3,0xa87ad919,0x26c2caf9,
  73871. 0xf574f295,0x4b13040a,0x944000a3,0x5b9bced1,0x06df42e7,0x4ccc57be,
  73872. 0x4bd1089d,0x22e8ec50,0xdddbb500,0x0c53177a,0x9ecfeadb,0x690d31d2,
  73873. 0x176668f9,0x735778fe },
  73874. { 0x843c1137,0x0f86ee3e,0x3f0b73cd,0x3c1c42fa,0x8ab20e3a,0x0e75679d,
  73875. 0x16242fae,0x6f95f1f4,0x39b092e4,0x7b88e11c,0x4c236ac0,0x1629403e,
  73876. 0x2dac02e6,0x66105f41,0x862e0632,0x74dc28a7,0xf3b23c8d,0x2118ffb2,
  73877. 0x0745ffbf,0x1182417c,0x4c05711e,0x49b55a04,0xcefbe4de,0x2c665b74,
  73878. 0x97bf7107,0x1cc4c01d,0xc54f0676,0xb2ca06da,0x7450d0f8,0xfc599daa,
  73879. 0x1a3182a1,0x52e637a6 } },
  73880. /* 231 */
  73881. { { 0x6bebc6db,0x481700f1,0xf9503d92,0x4a6b45db,0x5d153919,0xc715cd3c,
  73882. 0xe5ad2abc,0x942a1c05,0xab7b466f,0x36a82433,0xba13918b,0xba413bed,
  73883. 0x90f4e6ce,0x698a5624,0xf3f1f3ca,0xbb720da6,0x63471ab3,0x2116d41d,
  73884. 0x303d3609,0xe00d2227,0x463ba69e,0x7fd4cc00,0x62845fd1,0xac609e4d,
  73885. 0x80adc9c7,0x63603b2c,0x45fafbca,0xbf16fc9a,0xc4bc94ab,0x41007f7f,
  73886. 0xa74b1698,0x7c916b4f },
  73887. { 0x78bac2d4,0xc1026f91,0x2601a875,0x8a2e8098,0x0073d640,0xad2f276e,
  73888. 0xfcc1fb88,0x443610c4,0xca6b291f,0x5727b822,0x88ec60fc,0x0645532c,
  73889. 0xed9ad48b,0x51e48899,0xf543f103,0x841b48b5,0xd591ceeb,0xa6ccb1be,
  73890. 0x9dcf5a8b,0xfc4adf0f,0xb347ddb4,0x3a7ca020,0xcb44c521,0xaa1accc2,
  73891. 0x0527c0c4,0x773b6828,0x7023cf50,0xaa374c10,0x6b74c926,0x733d1000,
  73892. 0x77a8d07c,0x1ff3916f } },
  73893. /* 232 */
  73894. { { 0xf997939d,0xaa218fe4,0x791583b3,0x3d4dfbbb,0x87f7560b,0xb3a7b5da,
  73895. 0x5da92c98,0xa9c02801,0x46666f4a,0xe1eb4aad,0x14ce9dd7,0x2eb17a51,
  73896. 0xef8f3076,0xf46a66a4,0x810e546e,0x900b45c6,0x4baf04dd,0xf7af2258,
  73897. 0x5c84d42f,0x3cc1c872,0x8e4c83de,0x3093f225,0x170d88b2,0x62fade41,
  73898. 0xac076e44,0xe19612e4,0x32dd141b,0xf48d7346,0x925e34da,0xc1b1f759,
  73899. 0x072b90c9,0x19ed1a56 },
  73900. { 0x6c735473,0x9cf7fcde,0x6003bc3e,0xaab88e67,0xfb199bb8,0x12187cbc,
  73901. 0x9accccbd,0xbb730441,0xb0f65459,0x214aff3c,0x6f926282,0x6aec81a3,
  73902. 0x9f9d20b8,0xaa82cb32,0x5773cc90,0x82f3f90f,0xf62257e1,0x4af60e6b,
  73903. 0xbd4762df,0xf18b44bf,0xdb970753,0x3948b129,0x7c22c18e,0xc6e920e9,
  73904. 0x57be97ad,0x393d6208,0x46b637f9,0xe8d7382c,0xf1fed1d5,0xf6625ccb,
  73905. 0x68681599,0x6f31e0f9 } },
  73906. /* 233 */
  73907. { { 0x82b8f204,0xc45afe55,0xd358b54a,0xac0441b6,0xacd5f5ed,0x7213e7bf,
  73908. 0x139bcd93,0x1914c70b,0x96dbcbb0,0x714b4581,0x1ed35d21,0xe9297d35,
  73909. 0x6a3e1f20,0x8f640837,0x2f3cd705,0x150a8a9d,0xdcdd9f6d,0xfb36e801,
  73910. 0x5cf56d82,0x5a54eb65,0x92aa5a21,0x7610500c,0x3b089f03,0xd10d0ae2,
  73911. 0xc42b66e8,0x491b2079,0x0eee8d48,0x4af1ae3d,0x41556f45,0x137e4c28,
  73912. 0x63d8a7e6,0x875e3308 },
  73913. { 0xaf6c0acc,0xdc80fddc,0xbb1e7c08,0xd5ad1e66,0x828585ad,0xdc717ae1,
  73914. 0x275c7da6,0xbdc54340,0xd26b9e15,0xf4b4c852,0x6a05fa50,0x5f0a1fbf,
  73915. 0x817bcb32,0xc6f81e47,0x70ff2e1d,0x2cbd4328,0x67c7f7fc,0x8a249016,
  73916. 0xb585a6c4,0xd045acb7,0x4666c057,0x2e972ad4,0xe6d7d63d,0xc74d87cf,
  73917. 0x0e274144,0xf7067d87,0x8b2584ae,0xb2ca157a,0x75f0fdeb,0x495c5bfb,
  73918. 0xf386e009,0x5abb0581 } },
  73919. /* 234 */
  73920. { { 0xf0c97f57,0x8be62d2b,0x962f28c7,0x0fe04871,0x47b50abb,0xc548a467,
  73921. 0x44fa09ed,0xf6b26e03,0xab05a96e,0xfd44c6e3,0x70e6ae82,0xedb0032c,
  73922. 0xd7e4899d,0x28bd402b,0x9b7c11c2,0x43f2e963,0xce913716,0x0ec3fc0e,
  73923. 0x02fd0f8c,0x769b8bc9,0x7cabc3ac,0x9d9cb3aa,0x06924cc9,0xe88a8892,
  73924. 0x42609014,0xa51461aa,0x962e79e0,0xc7f4aa8b,0x8b1b3e80,0x4ef0210a,
  73925. 0x1bfee4bc,0x70544680 },
  73926. { 0x121901c1,0xfab3d713,0xfead54aa,0xe90a2627,0xbc08ba23,0x64f6d285,
  73927. 0x36ec227e,0x8d993015,0x06c191ab,0x99a16ab9,0xf649ce2c,0x86b1cf5b,
  73928. 0x66be3a80,0x59206759,0xccba2cf0,0x18836279,0xeff53486,0x2c157b87,
  73929. 0x4b223af2,0xbfac9896,0x0aae7a57,0xcd0fd4f0,0x63218a80,0xdaddb940,
  73930. 0xdf88f14e,0x3844bb79,0xb71ed9fd,0xc1b3e3d4,0xd6205036,0x6c634a13,
  73931. 0xb8680a6b,0x6f56aecf } },
  73932. /* 235 */
  73933. { { 0xd9205c5d,0xb01dc803,0x67123929,0x68955f7d,0x9d9b6565,0x3debbffd,
  73934. 0xd3b1acfe,0xb844395e,0x6094eeff,0x04328b21,0x22991feb,0x6631ffa8,
  73935. 0x190dd075,0x0dde66e6,0xe8577c05,0x75b03c55,0x91722407,0x6c91ce5f,
  73936. 0x8ebb3a3f,0x9a288a40,0x058a1396,0x1d376f8a,0x9a6e0676,0xf3a59457,
  73937. 0x7b71d288,0x103029c5,0xb44c30c0,0x0843f428,0x730e0b9c,0xd8e6aff8,
  73938. 0x4ed644ad,0x7b6be811 },
  73939. { 0x3d3aa54e,0x3ec38e4a,0xd83d509a,0x10233943,0x243955e2,0xf84aa621,
  73940. 0xf51d3d44,0x29104717,0x7eca4e37,0x62d2442c,0x85fa55de,0x8c5a523d,
  73941. 0x851da1b5,0xc6f5ccda,0x20001468,0x044bcaa8,0xe01702e0,0xf7501e68,
  73942. 0xe6a0acec,0xf0819359,0xac0ef0b2,0x33dda6ad,0xfd964f01,0x97aeedc8,
  73943. 0x530b90d8,0x48dacd0e,0xb84122eb,0x4c5fad6f,0xd700a1de,0x2284ec1e,
  73944. 0xdbca5474,0x86f9a835 } },
  73945. /* 236 */
  73946. { { 0x450cc69f,0x0e1d9055,0xc9edf98f,0x50eb14bc,0xee7eba01,0x1bb94e77,
  73947. 0x998f8e53,0x5f7a6737,0x1b16eef0,0x588384e3,0xd85c5e15,0xbb928723,
  73948. 0xcbd952aa,0xfe51e345,0x7e241674,0xc5d0ee28,0x100182f0,0xfdc146ef,
  73949. 0xe7f5be2c,0x0f739e92,0xb656bd3e,0x501ab3af,0x5168e289,0xb1552dde,
  73950. 0xb8ee104a,0x940dfe31,0xc4304475,0x42923603,0xc460a913,0x9306f114,
  73951. 0x03b51f86,0x5bfa9faf },
  73952. { 0x107b258e,0x2a23f52c,0xd66341dc,0x989e82bb,0x823cff1a,0x54a3ced8,
  73953. 0x719b491f,0xf45b7794,0x2433dfb8,0x898c2218,0xc49250ee,0x0f9dd91c,
  73954. 0x4fa17655,0x50c2a2ae,0x2c327f45,0xf7aa1ce4,0x583b1e41,0x13a15ad6,
  73955. 0xa1bfad9e,0x9aa0d5a5,0x8e1fbdcd,0x9b1caa28,0x915f7f87,0xaf9283b6,
  73956. 0x87e81a1e,0xc10e4e0c,0x1080d296,0x04fdca56,0x12755bd8,0x6acc9616,
  73957. 0x828feeda,0x1b1266aa } },
  73958. /* 237 */
  73959. { { 0x774ee49c,0x4ebc0a00,0xcb6237d7,0x776f6852,0x5df938a3,0xfc0544ac,
  73960. 0xb6fbfbbd,0xc3388ec8,0x745f2eae,0x84ac8bcd,0xb1ece937,0xa9c56609,
  73961. 0x7de8fa13,0x656fb6ac,0xa532b871,0x5f8ded74,0xaa889f09,0xab0d428b,
  73962. 0x10b7aec2,0x43b27f28,0xfeecb34c,0x26426e1e,0x9e89c2db,0x44431b6b,
  73963. 0x39211090,0xaac4bc5d,0x4fd81058,0x926f7368,0x471ef60e,0x452fa691,
  73964. 0x218d7a23,0x33517fdb },
  73965. { 0x593c4a36,0xa9c33f46,0x36b1a9ee,0xac69d718,0x4277beec,0x55a20c1d,
  73966. 0x7e4f179c,0x3e8ca24e,0xd46d88a2,0x57373369,0x730702f8,0x71ceb1cc,
  73967. 0x35eed574,0x8b184d97,0x0704cec2,0x7f4517a2,0xd7062a53,0x7f129d18,
  73968. 0xb1d77e1c,0x07a4571b,0x8350d8b2,0x774ac309,0x61fab8ef,0x27b2919f,
  73969. 0xb5dd801b,0xa7c4cc13,0x1434591f,0xe7e6255b,0x5a3592b3,0x349937b8,
  73970. 0x30c77549,0x31fac63d } },
  73971. /* 238 */
  73972. { { 0x04913fb6,0x2ee8cf1b,0x1769a6b3,0x7e401350,0x783e61f0,0x790ebb71,
  73973. 0xe27f2ffe,0x1e5107f9,0xedaf89bf,0x124ba67f,0xe58de68d,0x189200e1,
  73974. 0x6df5abee,0x962732a3,0xacbeb4aa,0x72cc37cf,0xe93c5a76,0xb0c5fa96,
  73975. 0xde63393b,0x4c2a317c,0x830b2d6c,0x97f65e67,0x1be5b96a,0x4afc3504,
  73976. 0x730ce66d,0x0bf40a60,0x9340d84f,0x96a1ba79,0x07626b08,0x3ee18254,
  73977. 0x7ab0cbf5,0x01db35db },
  73978. { 0xac0efee2,0x6e0fbc2d,0xd71dbb45,0x8406ebcd,0x19b69abe,0xe72bde3e,
  73979. 0x37e01822,0x49cb7e61,0x11458b4c,0xcbb8c01c,0x687c5d63,0x420b4847,
  73980. 0x454c6776,0x1847dfa1,0xd1839d18,0xbede911d,0x278df046,0x1b9dc9c9,
  73981. 0x881a336c,0x294bd62b,0x93e77adc,0x7f096879,0x43ce3ba7,0x7ac90665,
  73982. 0x7764eefc,0x148695fd,0x9ac465cf,0xe0c20f0b,0xa6e2cdb1,0x636e8d28,
  73983. 0xd755341d,0x7b6ba98c } },
  73984. /* 239 */
  73985. { { 0xc1881ab4,0xcb1d9e03,0xb3168c88,0x19c25d55,0x282364ce,0xa82d3d47,
  73986. 0xf161aa24,0x95994390,0xe1ebb2c9,0x7838bc00,0xbdec7a75,0x8fd5dfcc,
  73987. 0x4ff7220a,0x4dd203c2,0x0efeff48,0x5ec173b3,0x16428b35,0x99f1d2b3,
  73988. 0x056e813f,0xc06bd9e5,0xc0b319f1,0x929172ba,0xfd223b15,0x6ae0e384,
  73989. 0x98d091ed,0xbd01059e,0xa654648e,0x6b3168e4,0x3375e798,0x2211447f,
  73990. 0x71eb4508,0x47e81019 },
  73991. { 0xbc8c290d,0x7045d45a,0x810fb33a,0xa33d1355,0x46fbbf2f,0x2baf0092,
  73992. 0x385c7cd9,0xacff3f1b,0xe161985c,0xc5b150ec,0x2a888748,0xc6ee0a7f,
  73993. 0x5e88dcc8,0x9d888c8e,0xccb86443,0x4dd735f2,0x3c40f6f2,0xcc1e13b7,
  73994. 0xf3fed691,0xfc3a25ff,0x257ee5c7,0x4cb43b17,0xf32db135,0xaa654f93,
  73995. 0x02dff2d3,0x44f58d0a,0xa8ca6394,0x78e3f188,0xf3e86697,0x39646cce,
  73996. 0xe0dce87b,0x785b1902 } },
  73997. /* 240 */
  73998. { { 0xa92f9a20,0xfcce2361,0x9d64540e,0xb7bdca87,0x1d00d7c5,0xd4739a85,
  73999. 0x2e97c926,0x067ac8dc,0x78da6a8b,0x2aea3ffe,0x63c51b69,0x6828bf54,
  74000. 0x7155141a,0x76f1c479,0x3977d810,0xf4bcbef6,0x541bce7a,0x75bc4949,
  74001. 0xd17041a5,0xe01f4066,0x87755eaf,0xd282d5bd,0x59e7ae80,0x6e2107dd,
  74002. 0x382ab36f,0xaa56e166,0xb9d1d634,0x65ee8ef6,0xce4ed844,0x99a2160a,
  74003. 0xb7712c27,0x6557c367 },
  74004. { 0xd75b6e52,0x561b0268,0x118d0e89,0xb0813640,0x6a2eb1ae,0xcff53330,
  74005. 0x6d090894,0x4e462226,0xb5fc1d48,0xbb351227,0x57a3062d,0x9365ea07,
  74006. 0xd66e2dc5,0x4caca37b,0xb9095887,0x220d7d23,0x8c4473bf,0x9c0fd393,
  74007. 0x6787da4f,0xadff370a,0xd057f4b8,0xef0aebcc,0x1173f33a,0x205e744c,
  74008. 0x925a26b4,0xb8d1f0a5,0x722fbbfd,0xa9364f49,0x8227d284,0xc891ae77,
  74009. 0xa0e08ab4,0x15c40d04 } },
  74010. /* 241 */
  74011. { { 0x2a0e18d1,0x9baf169a,0x4c0327c2,0x9971c017,0x7bc262ce,0xd81a323f,
  74012. 0x818ff379,0x2099db8d,0x4cd3c330,0x663f663d,0x011a0553,0xef5325c3,
  74013. 0xf980a470,0x9cd70bdc,0x1c9ed070,0xe64452d1,0xac676e13,0xafbf43f4,
  74014. 0xae85c2a5,0x97bec0a6,0x470490c4,0x2faae550,0x491e6ba9,0x0ab97a87,
  74015. 0xaafa9914,0x4055f537,0x36726557,0xfc95adbb,0xd119d6bf,0x646343b9,
  74016. 0x9d341e37,0x788e94a0 },
  74017. { 0x9c53461a,0x053a6fe5,0x08e3b6ed,0x75ec897e,0x0768d939,0xa8f5d2f3,
  74018. 0xcc213d4f,0x9bd6bff6,0x05b0147c,0x590c7b41,0x7c7b8169,0x20a3628b,
  74019. 0x5bce78e9,0xc66a086e,0x4dec1d8f,0x3dd4d282,0xc19dcce9,0x890acf44,
  74020. 0xd8435a7e,0x6632d875,0xea6381b2,0x590167c1,0xf0dcc128,0xb2259797,
  74021. 0x46f8d463,0x91a612b4,0xc15efa39,0x42185d78,0x119f6788,0xdf55ec37,
  74022. 0x780dea93,0x91b19cc6 } },
  74023. /* 242 */
  74024. { { 0xcb5d8b80,0xebf2709d,0xfc35660e,0x03b96182,0x055ef969,0xb873d991,
  74025. 0xe47c4342,0xd1ea4b4d,0xd54f8867,0xcc4b9244,0xfd8d77ef,0x93b1a2ca,
  74026. 0xe8c1f563,0x068d24e7,0x49973056,0x5f5fabb6,0x0542374f,0x83248c50,
  74027. 0x3f38e913,0xc36de2b5,0x7bb680be,0xed07e8eb,0xd8f313b5,0x964813d7,
  74028. 0xafd2d392,0x7bb6a069,0x0848a31a,0xc06d848e,0xe4f0c325,0x6867fb2f,
  74029. 0x067343af,0x3c2ba834 },
  74030. { 0x9d3ad63b,0xab62d775,0x59e0eb1f,0x3f9cab97,0x3885e117,0x70332a63,
  74031. 0xe20b2f9e,0xf22cafce,0x49eca947,0xb529ba7e,0x6228d88d,0x24954216,
  74032. 0x39239561,0x80ea23ec,0xd4370644,0x1b8907e7,0x563e4e44,0x4b7fa455,
  74033. 0xb2a4b0fa,0xcca9829e,0x48060792,0xd0a720a4,0x246991ce,0x8ccdda0c,
  74034. 0x348d086b,0x37a2325b,0xf60aee13,0x566ed509,0x147f253f,0x3d30e091,
  74035. 0xc1073bd8,0x1fa627a5 } },
  74036. /* 243 */
  74037. { { 0x42478fd4,0xa11222a2,0x670b2000,0xacf4c6f1,0x8359c6de,0xf71bb04f,
  74038. 0x7b93cdbc,0x618e2829,0x230db60b,0x96e1bae3,0x965b3b29,0xf17fd3b4,
  74039. 0xbc7055dd,0xa58639c6,0x4b817d7f,0xc3ea92ed,0xd23b08a4,0x9082b2a6,
  74040. 0xdc17010e,0x8471228a,0x20e89d97,0x753b9e46,0x03ff77c9,0xcf7e4f97,
  74041. 0x2bbe60e5,0x6c3f8245,0xb80e017d,0x9e432cbc,0xc0a45edb,0x150a5acd,
  74042. 0x4798743e,0x67b8bd05 },
  74043. { 0xf4797cf7,0xe66079b4,0xd03fde02,0xe31c998a,0x54caaef1,0x5aa3763a,
  74044. 0xf7649711,0x64d9a1fe,0xaf29b1a7,0x7ce0dc73,0xfb66ca93,0x6661b083,
  74045. 0x32fb6a78,0xbf4d74fe,0xdf00a561,0x25f6ef09,0x831d1159,0x2bc4383f,
  74046. 0x536bde37,0x6d5cc10c,0x882cc65b,0xd4945f9f,0x451a99b8,0x81f48f13,
  74047. 0x6bac11a4,0x140161cd,0xf18a4a0a,0x9d94d4ed,0xa467a824,0x65363165,
  74048. 0xa4c9aedf,0x74297aa9 } },
  74049. /* 244 */
  74050. { { 0xe21124ba,0xc49758a4,0xa87ffbd2,0x99bd8198,0x3d6638a8,0x45fbcdd1,
  74051. 0x15f7bf76,0x94645ff8,0xc4e6d57e,0x5fa6736f,0x92e61db9,0x1eae6475,
  74052. 0xcbdf944a,0x79575c0c,0x25b31d74,0xa3d13047,0x4cab5ae6,0x7881df22,
  74053. 0x1a2887f2,0x8dbfd299,0xa26ac459,0x23d07590,0xd8661d4a,0x2e589852,
  74054. 0x8a0140f7,0x37b5c13b,0x3fb3782a,0x0f94199e,0x1bc14e90,0x722aa059,
  74055. 0xd55bbb12,0x89aab7ba },
  74056. { 0xd656bdc7,0x8b345a96,0xe176cd3b,0x43bdc8af,0x32d64c43,0xd69518b6,
  74057. 0x79b82b41,0xfcf364a7,0xffb0cf82,0x907b344e,0x5101287b,0xf3d0c83c,
  74058. 0x34cd90ef,0xe9f26a59,0x07082b5c,0xe5f5aaf2,0xece7c165,0x4eb72c75,
  74059. 0xbe986cd6,0xe9590a81,0xff1536aa,0xfeef498f,0xa8263d5e,0x04560243,
  74060. 0x54ae872b,0x940be14f,0xe3207686,0xbee7bcc9,0xc1bc4d7a,0xd496a27d,
  74061. 0x5940ab46,0x002dc297 } },
  74062. /* 245 */
  74063. { { 0xb69d60c3,0xee533937,0xfe972755,0x260be552,0xc0c725a6,0xb11fb78d,
  74064. 0xcab2e7c2,0x6982c27e,0xee2322cb,0x4bceedd9,0x122704f7,0x952b19ed,
  74065. 0x854a6165,0x2df4c285,0x7b192485,0xba40b5bf,0x0119f52a,0xfcbca950,
  74066. 0xe5add86f,0x7467d1cb,0xd9d0f2c1,0x9bf536fb,0xb8d4ebc9,0x3c296e34,
  74067. 0x05a81317,0x0495f8f4,0x73335f76,0x8c59e8d6,0xe0542122,0x0b53d324,
  74068. 0x3c3bda73,0x4d564535 },
  74069. { 0x7e5c0877,0x7322f800,0x0ca9a764,0x481b43e6,0xa2c12716,0x231f4f4b,
  74070. 0xed3136c2,0x09596857,0x38db30de,0xae826322,0x99908ebc,0x652fad40,
  74071. 0xaf0d231e,0x0b8d1814,0x09cbc349,0x2680c54b,0x4bf3bf8e,0xfd4562f3,
  74072. 0x092b595f,0x2985090b,0x5e15fc34,0xe6f39ca4,0xbc378168,0x70175191,
  74073. 0x845a4a87,0x906944b3,0x82a1541a,0xacc6d74a,0xb155c8b4,0xadc9bab3,
  74074. 0x77306c62,0x1f2f89ce } },
  74075. /* 246 */
  74076. { { 0x9affefdf,0x8253ef41,0x4cf9256b,0x05d7ece5,0xb444e483,0x377002f2,
  74077. 0xcba5471f,0xb189755f,0xd5cbe015,0xc88483cb,0x6a0b8429,0x254f7c69,
  74078. 0x61f3f61d,0x18850bd4,0x0a247157,0x7ba21089,0xd92eeb0d,0x35abbc2e,
  74079. 0x965dec89,0xfb56cabe,0xbc55684a,0x9da23724,0x6a7a7492,0xd8ba396f,
  74080. 0x2ef4ba46,0xfcb90db7,0x9909b27a,0xdd234fe0,0x76f4366e,0xbdf3c164,
  74081. 0x17e50d47,0x09c8097f },
  74082. { 0x60050c07,0x6a04b140,0x43a8e37e,0xc29e8318,0xbb55e41f,0xcb9429b2,
  74083. 0x2ce60e3a,0xed2fea5a,0xdb9d82f4,0xdc7b1ff3,0x687d37fa,0x48ebecc3,
  74084. 0xecb07539,0x79153e32,0x57075692,0x6a60054f,0x800759ba,0x3871cd0c,
  74085. 0x30922df1,0x17a7386f,0x83357b7c,0x4e9fc59e,0x39415186,0x1d26b3a9,
  74086. 0xd34db889,0x912a0222,0x59fcdb71,0x6672fcf4,0x44ff3036,0x5a3f268d,
  74087. 0x6911e16c,0x6f113ed3 } },
  74088. /* 247 */
  74089. { { 0x1836f1c9,0x52a9df59,0x4232307d,0xfa6519f5,0x5ded285a,0x8406c701,
  74090. 0xaf627f75,0x0a1545ca,0xace0417d,0xae1111ee,0xa6113443,0xfb28bdf6,
  74091. 0x52dbcbcb,0xde9ef0ab,0x7813e658,0xe9dc181b,0x99127225,0x0b1dabdb,
  74092. 0x22814c59,0x5f0598e3,0xd934ee7e,0x5c3b966e,0xb99ba4bf,0x4eb84eda,
  74093. 0x3c1b55e7,0xb2919a34,0x94aa860f,0xa9addb49,0xf6811ff6,0x1b7220df,
  74094. 0xd1a183e2,0x6636a23b },
  74095. { 0x20587283,0xdf5d5a2d,0xef07fc5d,0x0b3822c9,0x0ef6de38,0x1786bd55,
  74096. 0x25d1671d,0x163cf907,0x1cdb1def,0x74bf971f,0x0842fc4a,0x5749e830,
  74097. 0x27f854f7,0x0e2edbc7,0xbce24acb,0xbb27bbda,0x05bed08d,0xc1b19cec,
  74098. 0xf7c904bc,0xaada123e,0xd89982db,0x02429f1b,0x65f6e632,0x49d3616e,
  74099. 0xee59fd32,0xa3789fa8,0xfe9f29f5,0x160ba3ba,0xaf5378a0,0x0f2d3b61,
  74100. 0x73c2a6f8,0x7aeecc76 } },
  74101. /* 248 */
  74102. { { 0xdc43b0db,0xf3a4757c,0x98119cad,0x3d8a4e85,0x4616c156,0xf8095bf6,
  74103. 0x4f533e97,0x3e2a07bc,0x39cfc5ad,0xa9824367,0xcd68052c,0x18a6ba3a,
  74104. 0x8a1cec66,0xbd60e590,0x02b1b695,0xae3841a5,0x190a195b,0x986dff12,
  74105. 0xad31fd9b,0x2df2beac,0xcc728f7b,0x7d893224,0x0cf0a992,0xc38ea738,
  74106. 0x586a44ea,0xa8439a80,0x1615f03c,0xede7f7f0,0x27a1f885,0x48249908,
  74107. 0xb78a7645,0x28ec4006 },
  74108. { 0xa2fe0009,0xe1820c2e,0xf13874e9,0xe11ba5d2,0xc524db52,0x97522454,
  74109. 0x7fede529,0x4d477426,0x9b2500d4,0x01d3419a,0x1869244b,0xce08a492,
  74110. 0xdd1be1b9,0xba169023,0x32a301e0,0x242c3e54,0x70906788,0x9b56f7ba,
  74111. 0xc74a8cc4,0xf0ad2a09,0xd76f9439,0x99cd1841,0x621fb60e,0xeddafe0b,
  74112. 0xbc397634,0x056bee54,0xff7f0a84,0x4653f860,0x2011c0af,0x6bd4876f,
  74113. 0x0c9525c3,0x134f4cc7 } },
  74114. /* 249 */
  74115. { { 0xe938dff4,0x9621a3ec,0x486a79a3,0x7d101a7b,0xde950537,0xf2c4ef97,
  74116. 0xe65d87db,0xf3184099,0x373b8cfa,0xb89c7ffb,0xe842916e,0x68baa505,
  74117. 0x4ebea764,0xa790fd09,0xe592892b,0x679df6d4,0xfcfed741,0x2023331c,
  74118. 0x9880ff21,0x0bf4efd2,0xd0344501,0x7ca78ddd,0x342858c8,0x2cb09ecb,
  74119. 0x2575487a,0x9e5eb6dc,0xebcb0491,0x50675a15,0x7381d471,0x09d2e74f,
  74120. 0x83d3d6f4,0x6ea37829 },
  74121. { 0x4e5cc40a,0xc65c094b,0x1af37dfb,0x7a2e3f6a,0xf9026e44,0xef677e9d,
  74122. 0x93880f53,0xb7878c95,0x7f644aa9,0x4aa30b07,0x2f208c3c,0xa0c51683,
  74123. 0x658d663b,0x7c0277ae,0xae1d9130,0xef0b3c38,0x695c3ea4,0x302f37a7,
  74124. 0x6a0c5e0d,0xe004c1c5,0x20cbcf9f,0x9fd495c4,0x568a0e7c,0x706d5b9d,
  74125. 0x59286454,0x8b225dff,0x8d9a709c,0x527d4465,0x87c08d68,0x47c558da,
  74126. 0xbb4ef07d,0x606ee6e6 } },
  74127. /* 250 */
  74128. { { 0x57c621f6,0x02d99fc7,0x7fe83d48,0x292e40c1,0x9ef199b0,0x1bdfc7a1,
  74129. 0xe62c7666,0x78a04102,0xe6738753,0x16cda370,0x1e3a65af,0xbc81974d,
  74130. 0xf78fe209,0x19742048,0xbf5981c6,0xc83a058a,0x9c89702d,0xf26b2434,
  74131. 0x9d1a678a,0x988b2f1e,0xff29ae29,0x472bf9b0,0x1d7cf5ec,0xa143e398,
  74132. 0xb268ddd8,0x9c9d7e45,0x5fc4ff76,0x166cda55,0xa4aa7673,0x6044cdf0,
  74133. 0xe9148707,0x49dba6f7 },
  74134. { 0xa758e37a,0x20e47fb2,0x2d8eaf66,0xaf6b31d7,0x6f9c2210,0x352ad5f9,
  74135. 0x90efc32b,0x0093f727,0x41e4b264,0x435c99dc,0x05b15795,0xbfa878e0,
  74136. 0x0e673575,0x99c520a4,0x87eea759,0xca682594,0xf12a348b,0x029f7b81,
  74137. 0x2aa2ce35,0xa547cc18,0xead5e2c5,0xa11d874b,0x55682cdf,0x9af0349b,
  74138. 0x8bbe8e66,0xf86ebfea,0xf55394ab,0x3dab8782,0xebc8eb8f,0x458bf797,
  74139. 0x9b7de78c,0x4890a7a4 } },
  74140. /* 251 */
  74141. { { 0x8da995f6,0xd7299689,0xec6156ef,0xd39eaae7,0x356a82d5,0x6959040c,
  74142. 0xc135bcfe,0xb2046b21,0x0f595c78,0xea720b64,0xe7c5fb40,0x02824efa,
  74143. 0x0edb3bfc,0x97d8fd4c,0x79f24ebe,0x12f02905,0x187ea6b9,0x16fc47cf,
  74144. 0x789d5c23,0xc219fd27,0x89263ecc,0x233a6b6c,0x8b6d30a6,0x823634b2,
  74145. 0xc9b33680,0xca352e25,0x40c77456,0x9388d6ca,0x3c92065b,0xf8e55b0b,
  74146. 0x02439a76,0x5c17474b },
  74147. { 0x8aaccab5,0xd888e7c2,0xaaced05b,0x18027836,0xccec0f65,0x185b877d,
  74148. 0x125c2882,0x93cadc1c,0x67fdc54c,0x45df540a,0xc2788a33,0x4f3c86e2,
  74149. 0xe3a0fa2c,0x3e874469,0x273983cf,0xc59daa47,0x4a96d8a5,0x3063c48b,
  74150. 0xc2e58915,0xc38d2bcf,0x84e428c3,0x90e78b87,0xf0c4fd53,0x900a292c,
  74151. 0x941e6005,0xb7f92db7,0x6ca53a1c,0x95679241,0xb1ab0fa7,0x35f6f31d,
  74152. 0x7b58408c,0x5d675eb4 } },
  74153. /* 252 */
  74154. { { 0x870c6025,0xaeee1a77,0x91a2dfca,0xfc4a23b7,0x386b64c4,0x7b0e60c4,
  74155. 0xe5ae72b1,0xd5d5b17d,0x9eefa212,0x6dfc88ac,0xd4038b96,0x4feaefbe,
  74156. 0x8e2d2ecc,0x099ac356,0x012af207,0x548ea612,0x89c31218,0x4ffed9db,
  74157. 0xe0e67331,0x1c1e91c4,0xaf8300e0,0x009bb64f,0x6773c3be,0x8780501c,
  74158. 0xc08219fa,0xe0cd6ede,0xf81b06ff,0x7c055e07,0xe080b36f,0x82b63f9c,
  74159. 0x0a9feca3,0x02fccbaf },
  74160. { 0xb47cac61,0x9991d4d1,0xab86e12c,0x2e9d1687,0x2b94f042,0x8c6855ec,
  74161. 0x48e648e5,0xca400519,0xef89ac57,0x9ba91fb2,0x1be792cd,0x4f419206,
  74162. 0xbd0f1e15,0x82d221cb,0xfc444019,0x062eb13b,0x99790fdc,0xf3a97c32,
  74163. 0x6067a64b,0x4e796d94,0x6d23775a,0xc46dd300,0xed7f0f23,0x8672c4d5,
  74164. 0x3b4f63d7,0x821851dc,0xd26273f2,0x50a3ae0c,0xeac60f6f,0x800e58fc,
  74165. 0x13845545,0x56f1e456 } },
  74166. /* 253 */
  74167. { { 0x32c24f3b,0x01ccb3f6,0x06d817e6,0x99eb1c7f,0x6aa26776,0x8dc640bb,
  74168. 0x0845d5e0,0x7838affe,0xf81a79a8,0xf34fecb1,0x3e6819b0,0x6a2e282d,
  74169. 0x8237a4b8,0xc4b977ce,0x87636439,0x0f46b3db,0x97970497,0xa465f540,
  74170. 0x8791be43,0xd7e08762,0x34198ec6,0x00220b6c,0x093d94bb,0x57b38637,
  74171. 0x29d690b2,0x84012e16,0x20aad1a4,0x02ec9db5,0x85dc34e3,0xafee2fc6,
  74172. 0x25500cf8,0x911d1936 },
  74173. { 0xf5e5af5b,0x13b1bd58,0x7b6a22a7,0xa7ca263b,0xf3af2adc,0xab6bec4d,
  74174. 0xa04420bd,0x16651e59,0x4ba36c11,0x3b448b3b,0xff424310,0x3c62bfcd,
  74175. 0xf1a96cbb,0xde15c4a5,0xe4d1f980,0xbe0ad8a1,0x36673a3a,0x812bd14e,
  74176. 0x9212acdd,0x40303af6,0x576095ce,0x8f6dab9c,0x107f5ca5,0x7df1882a,
  74177. 0x8896a3b0,0xb903e63c,0xd863b3f0,0xf5048544,0xc09887de,0x5e5019b9,
  74178. 0xa0f53865,0x2be744fe } },
  74179. /* 254 */
  74180. { { 0x5b50f324,0x054cd05f,0x1ea3c7a2,0xb9b1eb24,0x7ff8e6b7,0x4a858a5c,
  74181. 0xec040882,0xd83902fe,0xd0cba9bd,0x72b26494,0xb29c9e1e,0xd0176f90,
  74182. 0xcebadb81,0x05d4eb02,0x372b8bfc,0x874405b1,0x79ead190,0x5c412881,
  74183. 0xec2b48cd,0xd44a3dd3,0x3f4d5033,0x84499a77,0x564c3a09,0xb37b38cd,
  74184. 0xf42e803b,0x80e99497,0xb8f518b2,0xc07b47a0,0x3568fde4,0xc710e3c5,
  74185. 0xcead0e7a,0x735f542f },
  74186. { 0x38380039,0xcaa9a171,0xf74d19c8,0xadfafe17,0xccbc1a8b,0x92d4393e,
  74187. 0xfe029705,0x3c5dbf39,0x930e9b36,0x4552b5ab,0x2afd494a,0x7ee63032,
  74188. 0x3f02ac43,0x826a9ad7,0x99356298,0x98c53562,0x7342bb39,0x0c869f87,
  74189. 0xe4f9b79a,0xd7510020,0xd34789a9,0x6361d1a4,0xcfa85637,0xf0ded5ba,
  74190. 0x88ac07e4,0x407ee73f,0x09ef1cbd,0xfac7d03f,0x4d475bad,0x25d697cb,
  74191. 0x14bd399e,0x1e984c9d } },
  74192. /* 255 */
  74193. { { 0x4850c817,0xc76d0561,0x3489812d,0xb08a5b19,0x5e58cbbe,0x7273d154,
  74194. 0x4be61e5a,0x8900b5fa,0xd7aeb8e1,0xaa088691,0xd35a3d4b,0xe66666af,
  74195. 0x57ec7d3d,0x38a2c199,0x668d6f5c,0xa0648e8f,0x7adc1746,0x1f9fc92c,
  74196. 0x843065c3,0x23a116c0,0x61e6ae69,0x36370a20,0x2aa47e73,0x626c3736,
  74197. 0xdeff6d84,0x540c25f2,0xcdbed2d4,0x9804824c,0x039a9492,0x4b5bfce0,
  74198. 0x76942e01,0x6c474a56 },
  74199. { 0x7d88e3a1,0x3aeb9a41,0xc484742a,0x105d3c88,0x3fe61131,0xe59de8d1,
  74200. 0x1a869e8b,0x148f5b6b,0xaa75d90a,0x7a8abc59,0x62146013,0x2f0c9bc7,
  74201. 0xc3824cd9,0x43faa747,0x6a5d0b92,0x81763a18,0x9bcbaebc,0xbbc341bc,
  74202. 0xf745d1dd,0xe1813160,0xb75ce5f4,0xa53ce52d,0xd50de4c2,0x15eae66c,
  74203. 0x75d7656d,0x5ed8996c,0xc4ca552a,0xe4ff5711,0x3c5305b4,0x215e985a,
  74204. 0xfa1ba2ce,0x6b258954 } },
  74205. };
  74206. /* Multiply the base point of P1024 by the scalar and return the result.
  74207. * If map is true then convert result to affine coordinates.
  74208. *
  74209. * Stripe implementation.
  74210. * Pre-generated: 2^0, 2^128, ...
  74211. * Pre-generated: products of all combinations of above.
  74212. * 8 doubles and adds (with qz=1)
  74213. *
  74214. * r Resulting point.
  74215. * k Scalar to multiply by.
  74216. * map Indicates whether to convert result to affine.
  74217. * ct Constant time required.
  74218. * heap Heap to use for allocation.
  74219. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  74220. */
  74221. static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k,
  74222. int map, int ct, void* heap)
  74223. {
  74224. return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table,
  74225. k, map, ct, heap);
  74226. }
  74227. #endif
  74228. /* Multiply the base point of P1024 by the scalar and return the result.
  74229. * If map is true then convert result to affine coordinates.
  74230. *
  74231. * km Scalar to multiply by.
  74232. * r Resulting point.
  74233. * map Indicates whether to convert result to affine.
  74234. * heap Heap to use for allocation.
  74235. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  74236. */
  74237. int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap)
  74238. {
  74239. #ifdef WOLFSSL_SP_SMALL_STACK
  74240. sp_point_1024* point = NULL;
  74241. sp_digit* k = NULL;
  74242. #else
  74243. sp_point_1024 point[1];
  74244. sp_digit k[32];
  74245. #endif
  74246. int err = MP_OKAY;
  74247. #ifdef WOLFSSL_SP_SMALL_STACK
  74248. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  74249. DYNAMIC_TYPE_ECC);
  74250. if (point == NULL)
  74251. err = MEMORY_E;
  74252. if (err == MP_OKAY) {
  74253. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap,
  74254. DYNAMIC_TYPE_ECC);
  74255. if (k == NULL)
  74256. err = MEMORY_E;
  74257. }
  74258. #endif
  74259. if (err == MP_OKAY) {
  74260. sp_1024_from_mp(k, 32, km);
  74261. err = sp_1024_ecc_mulmod_base_32(point, k, map, 1, heap);
  74262. }
  74263. if (err == MP_OKAY) {
  74264. err = sp_1024_point_to_ecc_point_32(point, r);
  74265. }
  74266. #ifdef WOLFSSL_SP_SMALL_STACK
  74267. if (k != NULL)
  74268. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  74269. if (point != NULL)
  74270. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  74271. #endif
  74272. return err;
  74273. }
  74274. /* Multiply the base point of P1024 by the scalar, add point a and return
  74275. * the result. If map is true then convert result to affine coordinates.
  74276. *
  74277. * km Scalar to multiply by.
  74278. * am Point to add to scalar multiply result.
  74279. * inMont Point to add is in montgomery form.
  74280. * r Resulting point.
  74281. * map Indicates whether to convert result to affine.
  74282. * heap Heap to use for allocation.
  74283. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  74284. */
  74285. int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am,
  74286. int inMont, ecc_point* r, int map, void* heap)
  74287. {
  74288. #ifdef WOLFSSL_SP_SMALL_STACK
  74289. sp_point_1024* point = NULL;
  74290. sp_digit* k = NULL;
  74291. #else
  74292. sp_point_1024 point[2];
  74293. sp_digit k[32 + 32 * 2 * 37];
  74294. #endif
  74295. sp_point_1024* addP = NULL;
  74296. sp_digit* tmp = NULL;
  74297. int err = MP_OKAY;
  74298. #ifdef WOLFSSL_SP_SMALL_STACK
  74299. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
  74300. DYNAMIC_TYPE_ECC);
  74301. if (point == NULL)
  74302. err = MEMORY_E;
  74303. if (err == MP_OKAY) {
  74304. k = (sp_digit*)XMALLOC(
  74305. sizeof(sp_digit) * (32 + 32 * 2 * 37),
  74306. heap, DYNAMIC_TYPE_ECC);
  74307. if (k == NULL)
  74308. err = MEMORY_E;
  74309. }
  74310. #endif
  74311. if (err == MP_OKAY) {
  74312. addP = point + 1;
  74313. tmp = k + 32;
  74314. sp_1024_from_mp(k, 32, km);
  74315. sp_1024_point_from_ecc_point_32(addP, am);
  74316. }
  74317. if ((err == MP_OKAY) && (!inMont)) {
  74318. err = sp_1024_mod_mul_norm_32(addP->x, addP->x, p1024_mod);
  74319. }
  74320. if ((err == MP_OKAY) && (!inMont)) {
  74321. err = sp_1024_mod_mul_norm_32(addP->y, addP->y, p1024_mod);
  74322. }
  74323. if ((err == MP_OKAY) && (!inMont)) {
  74324. err = sp_1024_mod_mul_norm_32(addP->z, addP->z, p1024_mod);
  74325. }
  74326. if (err == MP_OKAY) {
  74327. err = sp_1024_ecc_mulmod_base_32(point, k, 0, 0, heap);
  74328. }
  74329. if (err == MP_OKAY) {
  74330. sp_1024_proj_point_add_32(point, point, addP, tmp);
  74331. if (map) {
  74332. sp_1024_map_32(point, point, tmp);
  74333. }
  74334. err = sp_1024_point_to_ecc_point_32(point, r);
  74335. }
  74336. #ifdef WOLFSSL_SP_SMALL_STACK
  74337. if (k != NULL)
  74338. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  74339. if (point)
  74340. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  74341. #endif
  74342. return err;
  74343. }
  74344. #ifndef WOLFSSL_SP_SMALL
  74345. /* Generate a pre-computation table for the point.
  74346. *
  74347. * gm Point to generate table for.
  74348. * table Buffer to hold pre-computed points table.
  74349. * len Length of table.
  74350. * heap Heap to use for allocation.
  74351. * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is
  74352. * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise.
  74353. */
  74354. int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len,
  74355. void* heap)
  74356. {
  74357. #ifdef WOLFSSL_SP_SMALL_STACK
  74358. sp_point_1024* point = NULL;
  74359. sp_digit* t = NULL;
  74360. #else
  74361. sp_point_1024 point[1];
  74362. sp_digit t[38 * 2 * 32];
  74363. #endif
  74364. int err = MP_OKAY;
  74365. if ((gm == NULL) || (len == NULL)) {
  74366. err = BAD_FUNC_ARG;
  74367. }
  74368. if ((err == MP_OKAY) && (table == NULL)) {
  74369. *len = sizeof(sp_table_entry_1024) * 256;
  74370. err = LENGTH_ONLY_E;
  74371. }
  74372. if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) {
  74373. err = BUFFER_E;
  74374. }
  74375. #ifdef WOLFSSL_SP_SMALL_STACK
  74376. if (err == MP_OKAY) {
  74377. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  74378. DYNAMIC_TYPE_ECC);
  74379. if (point == NULL)
  74380. err = MEMORY_E;
  74381. }
  74382. if (err == MP_OKAY) {
  74383. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 38 * 2 * 32, heap,
  74384. DYNAMIC_TYPE_ECC);
  74385. if (t == NULL)
  74386. err = MEMORY_E;
  74387. }
  74388. #endif
  74389. if (err == MP_OKAY) {
  74390. sp_1024_point_from_ecc_point_32(point, gm);
  74391. err = sp_1024_gen_stripe_table_32(point,
  74392. (sp_table_entry_1024*)table, t, heap);
  74393. }
  74394. if (err == 0) {
  74395. *len = sizeof(sp_table_entry_1024) * 256;
  74396. }
  74397. #ifdef WOLFSSL_SP_SMALL_STACK
  74398. if (t != NULL)
  74399. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  74400. if (point != NULL)
  74401. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  74402. #endif
  74403. return err;
  74404. }
  74405. #else
  74406. /* Generate a pre-computation table for the point.
  74407. *
  74408. * gm Point to generate table for.
  74409. * table Buffer to hold pre-computed points table.
  74410. * len Length of table.
  74411. * heap Heap to use for allocation.
  74412. * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is
  74413. * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise.
  74414. */
  74415. int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len,
  74416. void* heap)
  74417. {
  74418. int err = 0;
  74419. if ((gm == NULL) || (len == NULL)) {
  74420. err = BAD_FUNC_ARG;
  74421. }
  74422. if ((err == 0) && (table == NULL)) {
  74423. *len = 0;
  74424. err = LENGTH_ONLY_E;
  74425. }
  74426. if ((err == 0) && (*len != 0)) {
  74427. err = BUFFER_E;
  74428. }
  74429. if (err == 0) {
  74430. *len = 0;
  74431. }
  74432. (void)heap;
  74433. return err;
  74434. }
  74435. #endif
  74436. /* Multiply the point by the scalar and return the result.
  74437. * If map is true then convert result to affine coordinates.
  74438. *
  74439. * km Scalar to multiply by.
  74440. * gm Point to multiply.
  74441. * table Pre-computed points.
  74442. * r Resulting point.
  74443. * map Indicates whether to convert result to affine.
  74444. * heap Heap to use for allocation.
  74445. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  74446. */
  74447. int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table,
  74448. ecc_point* r, int map, void* heap)
  74449. {
  74450. #ifdef WOLFSSL_SP_SMALL_STACK
  74451. sp_point_1024* point = NULL;
  74452. sp_digit* k = NULL;
  74453. #else
  74454. sp_point_1024 point[1];
  74455. sp_digit k[32];
  74456. #endif
  74457. int err = MP_OKAY;
  74458. #ifdef WOLFSSL_SP_SMALL_STACK
  74459. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  74460. DYNAMIC_TYPE_ECC);
  74461. if (point == NULL) {
  74462. err = MEMORY_E;
  74463. }
  74464. if (err == MP_OKAY) {
  74465. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, DYNAMIC_TYPE_ECC);
  74466. if (k == NULL)
  74467. err = MEMORY_E;
  74468. }
  74469. #endif
  74470. if (err == MP_OKAY) {
  74471. sp_1024_from_mp(k, 32, km);
  74472. sp_1024_point_from_ecc_point_32(point, gm);
  74473. #ifndef WOLFSSL_SP_SMALL
  74474. err = sp_1024_ecc_mulmod_stripe_32(point, point,
  74475. (const sp_table_entry_1024*)table, k, map, 0, heap);
  74476. #else
  74477. (void)table;
  74478. err = sp_1024_ecc_mulmod_32(point, point, k, map, 0, heap);
  74479. #endif
  74480. }
  74481. if (err == MP_OKAY) {
  74482. err = sp_1024_point_to_ecc_point_32(point, r);
  74483. }
  74484. #ifdef WOLFSSL_SP_SMALL_STACK
  74485. if (k != NULL)
  74486. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  74487. if (point != NULL)
  74488. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  74489. #endif
  74490. return err;
  74491. }
  74492. /* Multiply p* in projective coordinates by q*.
  74493. *
  74494. * r.x = p.x - (p.y * q.y)
  74495. * r.y = (p.x * q.y) + p.y
  74496. *
  74497. * px [in,out] A single precision integer - X ordinate of number to multiply.
  74498. * py [in,out] A single precision integer - Y ordinate of number to multiply.
  74499. * q [in] A single precision integer - multiplier.
  74500. * t [in] Two single precision integers - temps.
  74501. */
  74502. static void sp_1024_proj_mul_qx1_32(sp_digit* px, sp_digit* py,
  74503. const sp_digit* q, sp_digit* t)
  74504. {
  74505. sp_digit* t1 = t;
  74506. sp_digit* t2 = t + 2 * 32;
  74507. /* t1 = p.x * q.y */
  74508. sp_1024_mont_mul_32(t1, px, q, p1024_mod, p1024_mp_mod);
  74509. /* t2 = p.y * q.y */
  74510. sp_1024_mont_mul_32(t2, py, q, p1024_mod, p1024_mp_mod);
  74511. /* r.x = p.x - (p.y * q.y) */
  74512. sp_1024_mont_sub_32(px, px, t2, p1024_mod);
  74513. /* r.y = (p.x * q.y) + p.y */
  74514. sp_1024_mont_add_32(py, t1, py, p1024_mod);
  74515. }
  74516. /* Square p* in projective coordinates.
  74517. *
  74518. * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2
  74519. * py' = 2 * p.x * p.y
  74520. *
  74521. * px [in,out] A single precision integer - X ordinate of number to square.
  74522. * py [in,out] A single precision integer - Y ordinate of number to square.
  74523. * t [in] Two single precision integers - temps.
  74524. */
  74525. static void sp_1024_proj_sqr_32(sp_digit* px, sp_digit* py, sp_digit* t)
  74526. {
  74527. sp_digit* t1 = t;
  74528. sp_digit* t2 = t + 2 * 32;
  74529. /* t1 = p.x + p.y */
  74530. sp_1024_mont_add_32(t1, px, py, p1024_mod);
  74531. /* t2 = p.x - p.y */
  74532. sp_1024_mont_sub_32(t2, px, py, p1024_mod);
  74533. /* r.y = p.x * p.y */
  74534. sp_1024_mont_mul_32(py, px, py, p1024_mod, p1024_mp_mod);
  74535. /* r.x = (p.x + p.y) * (p.x - p.y) */
  74536. sp_1024_mont_mul_32(px, t1, t2, p1024_mod, p1024_mp_mod);
  74537. /* r.y = (p.x * p.y) * 2 */
  74538. sp_1024_mont_dbl_32(py, py, p1024_mod);
  74539. }
  74540. #ifdef WOLFSSL_SP_SMALL
  74541. /* Perform the modular exponentiation in Fp* for SAKKE.
  74542. *
  74543. * Simple square and multiply when expontent bit is one algorithm.
  74544. * Square and multiply performed in Fp*.
  74545. *
  74546. * base [in] Base. MP integer.
  74547. * exp [in] Exponent. MP integer.
  74548. * res [out] Result. MP integer.
  74549. * returns 0 on success and MEMORY_E if memory allocation fails.
  74550. */
  74551. int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res)
  74552. {
  74553. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  74554. defined(WOLFSSL_SP_SMALL_STACK)
  74555. sp_digit* td;
  74556. sp_digit* t;
  74557. sp_digit* tx;
  74558. sp_digit* ty;
  74559. sp_digit* b;
  74560. sp_digit* e;
  74561. #else
  74562. sp_digit t[36 * 2 * 32];
  74563. sp_digit tx[2 * 32];
  74564. sp_digit ty[2 * 32];
  74565. sp_digit b[2 * 32];
  74566. sp_digit e[2 * 32];
  74567. #endif
  74568. sp_digit* r;
  74569. int err = MP_OKAY;
  74570. int bits;
  74571. int i;
  74572. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  74573. defined(WOLFSSL_SP_SMALL_STACK)
  74574. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 40 * 32 * 2, NULL,
  74575. DYNAMIC_TYPE_TMP_BUFFER);
  74576. if (td == NULL) {
  74577. err = MEMORY_E;
  74578. }
  74579. #endif
  74580. if (err == MP_OKAY) {
  74581. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  74582. defined(WOLFSSL_SP_SMALL_STACK)
  74583. t = td;
  74584. tx = td + 36 * 32 * 2;
  74585. ty = td + 37 * 32 * 2;
  74586. b = td + 38 * 32 * 2;
  74587. e = td + 39 * 32 * 2;
  74588. #endif
  74589. r = ty;
  74590. bits = mp_count_bits(exp);
  74591. sp_1024_from_mp(b, 32, base);
  74592. sp_1024_from_mp(e, 32, exp);
  74593. XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32);
  74594. sp_1024_mul_32(b, b, p1024_norm_mod);
  74595. err = sp_1024_mod_32(b, b, p1024_mod);
  74596. }
  74597. if (err == MP_OKAY) {
  74598. XMEMCPY(ty, b, sizeof(sp_digit) * 32);
  74599. for (i = bits - 2; i >= 0; i--) {
  74600. sp_1024_proj_sqr_32(tx, ty, t);
  74601. if ((e[i / 32] >> (i % 32)) & 1) {
  74602. sp_1024_proj_mul_qx1_32(tx, ty, b, t);
  74603. }
  74604. }
  74605. }
  74606. if (err == MP_OKAY) {
  74607. sp_1024_mont_inv_32(tx, tx, t);
  74608. XMEMSET(tx + 32, 0, sizeof(sp_digit) * 32);
  74609. sp_1024_mont_reduce_32(tx, p1024_mod, p1024_mp_mod);
  74610. XMEMSET(ty + 32, 0, sizeof(sp_digit) * 32);
  74611. sp_1024_mont_reduce_32(ty, p1024_mod, p1024_mp_mod);
  74612. sp_1024_mul_32(r, tx, ty);
  74613. err = sp_1024_mod_32(r, r, p1024_mod);
  74614. }
  74615. if (err == MP_OKAY) {
  74616. err = sp_1024_to_mp(r, res);
  74617. }
  74618. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  74619. defined(WOLFSSL_SP_SMALL_STACK)
  74620. if (td != NULL) {
  74621. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  74622. }
  74623. #endif
  74624. return err;
  74625. }
  74626. #else
  74627. /* Pre-computed table for exponentiating g.
  74628. * Striping: 8 points at a distance of (128 combined for
  74629. * a total of 256 points.
  74630. */
  74631. static const sp_digit sp_1024_g_table[256][32] = {
  74632. { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74633. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74634. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74635. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74636. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74637. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74638. 0x00000000, 0x00000000 },
  74639. { 0x335c1685, 0x170a46d2, 0xe1007a58, 0xeac9e971, 0x43ca4a73,
  74640. 0x40e8f3df, 0x82642475, 0x2646f815, 0xb36576d1, 0x3af49bb4,
  74641. 0x72bf1afb, 0xd89e2d14, 0x2fd151e6, 0x27be882c, 0x8f88717c,
  74642. 0xaddedc85, 0x16ac6c6f, 0xd6d859bf, 0x2d8eae58, 0x0e741a1b,
  74643. 0x61c1f30d, 0x6faf7a00, 0x9b67e096, 0x66dbd09a, 0x7d3b4f7d,
  74644. 0x21f11c06, 0xc727c98e, 0x6152ba02, 0xe86cb221, 0xafd58891,
  74645. 0x6bd3baf4, 0x59e93c6a },
  74646. { 0x71dd4594, 0xe54dd36f, 0x00aef1e6, 0xbbc9cc9f, 0xa19f6530,
  74647. 0x9ea5a44e, 0x3f520928, 0x8588aa99, 0x8f5c1418, 0x9753794c,
  74648. 0xc11399fa, 0x118bd792, 0xf5cb6ab5, 0xb9bd3afd, 0x2ecb9652,
  74649. 0x813d1cb2, 0x40389813, 0xfd456267, 0x4ac8431c, 0x51f7119b,
  74650. 0x0a180eb6, 0xdd9f6a91, 0x9f7bfa2e, 0x13946d17, 0x50a9d0d9,
  74651. 0x16f18631, 0x6f8373d3, 0x5f19c20d, 0x9b6a52b9, 0xbe85ac6a,
  74652. 0x74f62e03, 0x63ef187b },
  74653. { 0x016f45e7, 0x7c376b7f, 0x2bec82f8, 0x1c1bdb57, 0xce429b60,
  74654. 0x7392f741, 0xc7afd81d, 0x6fdbf0a2, 0x7241098b, 0xbda41b1f,
  74655. 0xbb60f8cf, 0x5b407474, 0xb330bc4d, 0x933e0d41, 0x733fa3be,
  74656. 0xae182830, 0x0f5c6cd1, 0xa0ed299b, 0x3f9860c8, 0x7ff3354e,
  74657. 0x15559c41, 0xb1360986, 0x129f85cb, 0xab0cb63c, 0x47685fbe,
  74658. 0x682ecc49, 0xeb199633, 0x505e8ec2, 0xddac2cda, 0x90dcc794,
  74659. 0xf192da23, 0x4fe6791c },
  74660. { 0x05e8733c, 0x94a423d5, 0x1d5717c1, 0xcc845e65, 0xe961b322,
  74661. 0x237c7e88, 0xdb4181cc, 0x0c4471c6, 0x713bd721, 0x00c875e2,
  74662. 0xb2c17b09, 0x9dfde9ed, 0xe88ceaf6, 0x430a6de5, 0x7b81cea6,
  74663. 0xaaa7a61a, 0x233f98d5, 0xea52d026, 0x60689a9a, 0xb55efdd0,
  74664. 0x5cac4aab, 0x30cfa7ce, 0x8e950761, 0xfa4db114, 0x4e9a1e52,
  74665. 0x309570c4, 0x1a040170, 0x18c21f61, 0xbe78d9d2, 0x555d1ffe,
  74666. 0x561db297, 0x04482a18 },
  74667. { 0x73d486d8, 0xe7758ac2, 0x61cdc1e7, 0x8169f946, 0x2188ab4f,
  74668. 0x723c99fc, 0xf3373630, 0xa0e54f02, 0xbd8c2260, 0x560bee25,
  74669. 0x4531bc60, 0x28fc307c, 0x7e44feb5, 0xd6f21f1a, 0x57128d37,
  74670. 0xc8e4499c, 0xd7b2ea45, 0x963b053e, 0x32a3d222, 0x40c27a04,
  74671. 0x35459668, 0x5b51854d, 0xd73557e9, 0x66e1a49f, 0x8692077a,
  74672. 0x0d267fd9, 0xe7342702, 0xfa1350d3, 0x68ccdb44, 0x1a9c3f25,
  74673. 0xdedbf89f, 0x833a0ff8 },
  74674. { 0xab376b76, 0xa8c419c7, 0x27d0f0cc, 0x3b7294f3, 0xa90c514d,
  74675. 0xe56bb9e2, 0xa62575a6, 0x931ba51e, 0x098c0a88, 0x56fee07b,
  74676. 0xb4c16a2a, 0x04be5aee, 0xe6eb260b, 0xe513350b, 0xa1d5c270,
  74677. 0x339edad6, 0xe9dbadd1, 0xf366ed59, 0x2dd06ec0, 0x4213be88,
  74678. 0xcb1187db, 0x22d639c8, 0xd8a1058a, 0x1fec95e1, 0xa2b744f1,
  74679. 0x03f73ea6, 0xf4f05c0c, 0x741fd51a, 0x85f811a0, 0x2e2df95a,
  74680. 0xeb24965f, 0x692b3ce3 },
  74681. { 0xd2a127b4, 0x0ce6cb72, 0x8f92816f, 0x66a46ea5, 0x47a37616,
  74682. 0x43ecf463, 0xe0ab96ee, 0x163d9a01, 0xb2edbe8c, 0xc8145c6d,
  74683. 0x4de4e665, 0x2f426cae, 0x74e252f9, 0x174d0b40, 0x7d2af831,
  74684. 0x54c240d7, 0x3d652936, 0x581fa397, 0xa09d4695, 0x05b9491c,
  74685. 0x5452643c, 0x8c4e8533, 0xd4128327, 0x32d64331, 0x70361f25,
  74686. 0x64479038, 0x89ef09f2, 0x774191b1, 0x81de5fe0, 0xc0cf0aaf,
  74687. 0xf40042d6, 0x333e430a },
  74688. { 0xcf26d3b7, 0x5df04de4, 0xb53f79be, 0x57a77306, 0x1808b664,
  74689. 0xa4013c5f, 0x85037360, 0xef291ea4, 0x0b061037, 0x1ffc9d7d,
  74690. 0x65c913bb, 0xd9d04dd9, 0xf13b8587, 0x948a37af, 0xfe3ee755,
  74691. 0xb5443483, 0x04631386, 0x3fc21e74, 0xcddeb58c, 0xb3a104e5,
  74692. 0x6572cd52, 0x94fe1862, 0x15aaa408, 0xeb9a71a1, 0x459ea462,
  74693. 0x8adc6fe5, 0x4aeb02a3, 0xbb18d175, 0x2f7791d1, 0xae127636,
  74694. 0xd6bbd708, 0x10e8b31d },
  74695. { 0x3ed9f1af, 0xb87f03e5, 0x56676166, 0x03ad2477, 0x74ce15b8,
  74696. 0x38dcd630, 0x26b1e85b, 0x1877e2b0, 0x1af99c15, 0xb1654d17,
  74697. 0x9382547a, 0x9782e9e4, 0x26d55ef5, 0x6dc7fc7c, 0x2fbeb54c,
  74698. 0x9038f95d, 0x036c0357, 0xfe590dfe, 0x4fdc3f7f, 0xcfcb6eae,
  74699. 0xf35e1a88, 0xcb1fbc54, 0xda0a5568, 0x3c8e1db2, 0x5b6f5557,
  74700. 0x9a87393f, 0xe7ac0a06, 0x38646b32, 0x2a8495ab, 0xfd261c83,
  74701. 0x0cdcc4bc, 0x6485524c },
  74702. { 0xc4a6ff2a, 0x1abfb3e2, 0x35a6428a, 0x2aa03fba, 0x89aff742,
  74703. 0x884227f0, 0xba5dbd93, 0x2337883a, 0xd2a182cb, 0x38186ae9,
  74704. 0x49a01f05, 0xb9f0764d, 0x917b1e7a, 0x92411feb, 0x570cbb5b,
  74705. 0x700b1903, 0xb914be7c, 0x5d5181d5, 0x1981182d, 0x135c4437,
  74706. 0x574b9997, 0x32758d24, 0x632d28b2, 0xa650a8f5, 0xfa383f09,
  74707. 0x24078bac, 0x00a33d80, 0x6546a60c, 0x2df8b449, 0xa4061c7a,
  74708. 0xf234563c, 0x1f76f3f2 },
  74709. { 0x44c436b0, 0x9aa2c143, 0x1f69c87a, 0x79070556, 0x5f6db2df,
  74710. 0x35f3117b, 0xed56ba82, 0x85761f41, 0x7d0afa48, 0xf831464f,
  74711. 0x3adce71e, 0xa99f2915, 0x116b7488, 0xb27bf693, 0x9bb9443a,
  74712. 0xa98a5a8c, 0x2ee5fde8, 0x7f878026, 0x1812acb7, 0x3a6f93dd,
  74713. 0xdc84bc92, 0xaf92a4cc, 0xf1d4995a, 0x3c2562af, 0x04ed899d,
  74714. 0xfd9fc33c, 0x4ed2a538, 0xc028ca94, 0x049ea726, 0xd0f367bb,
  74715. 0x3d108e05, 0x04924ffb },
  74716. { 0xc673562f, 0x06548e3d, 0xe2eae48c, 0xd3b33025, 0x5e1c6977,
  74717. 0xe61fd32b, 0x6ebe557b, 0x424e2064, 0x41d6e18e, 0x767391c0,
  74718. 0x14d7e95b, 0x4b8ebb8e, 0x20991b8c, 0x4ae8b7d4, 0xe01290d3,
  74719. 0xf8a0df66, 0x925e5f4e, 0xc97e24a3, 0x1508272a, 0x79a7b2cb,
  74720. 0x25072661, 0xb40b072e, 0x9062fa49, 0xdad9e182, 0xf3c53bce,
  74721. 0x8780a784, 0x9f142799, 0x58a82b76, 0xc1468426, 0x08cd849c,
  74722. 0xc380ae35, 0x4dfce809 },
  74723. { 0xd527b780, 0x45069cb2, 0x977930dd, 0xd52da015, 0xe27d0263,
  74724. 0x10cc600b, 0xbb2d1b2b, 0x34102c26, 0x554adf3c, 0x4c652623,
  74725. 0x45f0ff47, 0xd6891382, 0xca916e7c, 0x83fa8cc5, 0xd15c8d8a,
  74726. 0x1e10f139, 0x81dc56b3, 0xf173dc2e, 0x5c4ed9ba, 0x7fcecb04,
  74727. 0x47d01228, 0x307fd7d8, 0x9f3a532f, 0x24a57153, 0xe2153c22,
  74728. 0x59e9e81d, 0xe428a408, 0xc562595d, 0x9339bd23, 0xdc7daff8,
  74729. 0xb8a06802, 0x0d075908 },
  74730. { 0xde085f2a, 0x870af2a7, 0xbe99b2e5, 0x88fcd24f, 0x59ca413b,
  74731. 0x88c0d261, 0x8559f851, 0x1f02a2e4, 0xf622da0d, 0x83b96021,
  74732. 0x6dca3615, 0x5c05c2f5, 0x7910c682, 0x0148cf1c, 0x272695be,
  74733. 0x392f2896, 0xa8d64ef6, 0x883d0bb5, 0x1cfcbc52, 0xef0d2244,
  74734. 0x526117e5, 0xf5dafcec, 0xf04928e9, 0xb68612b9, 0x393f2e2a,
  74735. 0x283f744d, 0x700c1151, 0xfbeed7ed, 0xa4360dfe, 0xf2cde215,
  74736. 0x2f08535a, 0x24fa961c },
  74737. { 0x616df7f6, 0x0767db3f, 0xfbd90326, 0x643057d8, 0x6e82d544,
  74738. 0x174daa90, 0x689643db, 0x2284f345, 0xcc89a060, 0x18b191df,
  74739. 0xd6c27d12, 0xbab46af4, 0xc9895145, 0x5a57f486, 0xcc942f9e,
  74740. 0xc03214e9, 0x41950158, 0x273e1c8f, 0x39ad43ab, 0x8ceb759f,
  74741. 0xe50ee173, 0x5e1b8b7f, 0x8f4d7d4e, 0xf635b1fc, 0x755603f3,
  74742. 0x8eff77e3, 0x7752fa60, 0x201f61d1, 0x4a6fb6e1, 0x94d7a03d,
  74743. 0xfc4f0114, 0x371cc23d },
  74744. { 0xda90c351, 0x289b115d, 0x364d9c06, 0x6d196ebf, 0xf650b31b,
  74745. 0x77a89202, 0x6f57642f, 0xcc28c164, 0x08100127, 0xdc4f7e36,
  74746. 0xdc4c807b, 0x8836cd08, 0xe00240f2, 0x1280f156, 0x99cb3953,
  74747. 0x3f9a6d78, 0x3a802038, 0x40a494d3, 0xe87d3474, 0x45697e91,
  74748. 0x26dde24a, 0x70d97d07, 0x7640c30e, 0x06f6a58d, 0x5ba6e6c6,
  74749. 0x03c2c0e8, 0xf1bc13e8, 0x330f6a7a, 0xc9f4d78f, 0x3e602e4f,
  74750. 0x0c80fb7f, 0x92b6bca0 },
  74751. { 0x5f00822e, 0x2e3d5c83, 0xb8b16f12, 0x0e825712, 0x92b0a330,
  74752. 0x81c329c4, 0xa7cc1954, 0x6b4e32ad, 0x1bb1413f, 0x0bee9cee,
  74753. 0x4a92ca27, 0xedfb7baa, 0xea3b9153, 0xcd472afa, 0x00f0c0f9,
  74754. 0xe8f09e7e, 0x5cdebb70, 0xa4e1d872, 0x4a9b63b6, 0xfe2bae08,
  74755. 0x3fd58f65, 0xf40141b8, 0xa3b62759, 0xd7ec5eda, 0x790e3088,
  74756. 0x9aaf6e67, 0x1f277e31, 0x215ad830, 0xcf33871c, 0xe7db4b98,
  74757. 0x4f02f89d, 0x71ff62c9 },
  74758. { 0x2a4a84d9, 0xaa4c7102, 0x5ebc71e6, 0xe2ee4acd, 0xf1cd6578,
  74759. 0x3b11a8a5, 0xfff120a5, 0x83f5ef9f, 0x09e65033, 0xa4c598e1,
  74760. 0xca044180, 0xe1e9f990, 0xf59828c1, 0x8b832d46, 0x33af536b,
  74761. 0x753f28a0, 0xb6d4f68a, 0x92edc4b1, 0x72ccd1f0, 0xedde692a,
  74762. 0xd2226432, 0xd3aa0f7d, 0xa3d2661c, 0x38dbb63e, 0xfdc37dda,
  74763. 0xf1e19fc6, 0x84ef6b4c, 0x6c18b350, 0xdf1bba69, 0xe6a83fe9,
  74764. 0x5f958273, 0x40fd47e7 },
  74765. { 0x267140a4, 0x5b88b746, 0xeab6f2fb, 0x6dbbfc1e, 0x69862548,
  74766. 0xdd9ec88e, 0x2eb6efc2, 0x69beeba1, 0x8ac8ff88, 0xcfc2214a,
  74767. 0xb5a21950, 0x95d5c96e, 0x4171fb69, 0x93389c05, 0x1b468337,
  74768. 0x2d85d452, 0x4113425c, 0x14d68a08, 0xec6c2174, 0xe52c0139,
  74769. 0xf730084d, 0x20cf0b97, 0x1f578aa3, 0x1ac16a26, 0xf9b6ae43,
  74770. 0x18b9fab3, 0xd854a695, 0x68d82111, 0xdffbe286, 0x0b334d98,
  74771. 0xe639338c, 0x5b1c1157 },
  74772. { 0x72b6bb8f, 0x90edaab1, 0x02fc92c2, 0x8dc64ed2, 0xfe694c73,
  74773. 0xf42ba3c5, 0xcb54dce4, 0x316dc65f, 0x632420dc, 0xcb2d66a3,
  74774. 0x056dcf94, 0x16e706e7, 0xa4f32c9d, 0x2809c764, 0xea6edca8,
  74775. 0xab18d830, 0x81c65f57, 0x4fd1ace6, 0x7da12c10, 0x1f91651c,
  74776. 0xc7791a48, 0x0ac3bd66, 0x785e67a3, 0xb6ad1cf4, 0xda0fd591,
  74777. 0xe4d3fc44, 0x6e1c6344, 0xce164801, 0x33e50ab3, 0x84de9cb8,
  74778. 0xa756eef4, 0x963ab83a },
  74779. { 0xdf4ea5a3, 0x944b47d8, 0x5cfe45fe, 0x96568815, 0x8a3c3564,
  74780. 0xd16e7d58, 0xe7c99e15, 0x84e55b3e, 0xf55071bc, 0x3fee204d,
  74781. 0x04057dce, 0x71006f29, 0xbba75570, 0xfe8c390d, 0x3319adac,
  74782. 0x3645bcb6, 0x7c20bfd8, 0x8189e8b0, 0x7d7d9578, 0x8e550969,
  74783. 0xb99f4e3b, 0x037d1321, 0xa60cfb6a, 0x011b2521, 0x837382da,
  74784. 0x66594aaa, 0x83c1dc07, 0xc89b91fd, 0x076b9884, 0x6b82b899,
  74785. 0xbe45c558, 0x443480fc },
  74786. { 0x9114221a, 0xf8ffffb4, 0x3e857a7a, 0x4aec4f2e, 0x0fa54787,
  74787. 0x42e2d0e4, 0xd6f96152, 0xef3e6b31, 0xfbfe9b77, 0xb2296537,
  74788. 0xfb43a86a, 0xc2a9d0f2, 0x24572ac6, 0x241284ed, 0xe721ba7b,
  74789. 0xa3868917, 0xc117a78d, 0xdbef7c00, 0xd31605ac, 0x38149071,
  74790. 0x065a8ee9, 0xc2dada9e, 0xc442be82, 0xd5b138d8, 0xf6d72b58,
  74791. 0x9b6c224b, 0x8eb03e6d, 0xb9d355cf, 0xa1700371, 0xab6d1eb0,
  74792. 0xcffaa7eb, 0x97118a88 },
  74793. { 0xcdecb5d8, 0xbf9c59a2, 0xa93a6866, 0x8083c81b, 0x04774fbf,
  74794. 0x24e0dd81, 0xa02070b4, 0xe779a3ca, 0x0fbfb781, 0x9d352fbb,
  74795. 0x3ef2a1c4, 0xa8b0d820, 0x14b3e501, 0xb858637b, 0x8a882ff2,
  74796. 0x5ba70a49, 0x3b06efa5, 0xa2730083, 0x102fee2a, 0xa42c02f4,
  74797. 0x8a0223a5, 0xe4e76299, 0x85c3fc72, 0xdba2ba26, 0xfe52eae7,
  74798. 0x554fe763, 0x270f45f6, 0x30b5405a, 0xa573387c, 0xd56a177a,
  74799. 0x4b71fa82, 0x17c0778d },
  74800. { 0x2735e37b, 0x0e6dff1d, 0x656ec572, 0xc9884e56, 0x9ebba978,
  74801. 0xa2f5ac9d, 0xba09f3c4, 0x40fa4518, 0xf5b04377, 0x8c3fa177,
  74802. 0x967a2eca, 0xa1a1decd, 0x0528bd40, 0x768bca70, 0x18691c4a,
  74803. 0xf224952b, 0xe86d5fd5, 0x16e12c45, 0x37859a6a, 0x7a0d9157,
  74804. 0xa0ffce0e, 0x723f4309, 0xa96cc9a3, 0x5a8db79b, 0x1ad23a38,
  74805. 0x6dd12ae0, 0xe2bf5d84, 0x9ffec3a1, 0xa452ed66, 0xd6ce84e1,
  74806. 0x571fe4c6, 0x1219d5c8 },
  74807. { 0x262969eb, 0x43eaa67f, 0x2f03e773, 0x3a3ab39d, 0x57bb0909,
  74808. 0xe6127e51, 0x8d150274, 0x0f82b0ed, 0xe580bdbd, 0xffffcad8,
  74809. 0xa9743e6b, 0x51d3d075, 0x8bac11d6, 0x1484bdb1, 0xeb24c388,
  74810. 0x95cd9990, 0x7fac67c6, 0x216a61d0, 0xa04e6b87, 0x4308f762,
  74811. 0xcba57cc8, 0x2865dd61, 0xd234a07a, 0x3c296b0d, 0x3a0793f9,
  74812. 0x76f92839, 0x0be29ece, 0x70b57e1f, 0x7e626f42, 0x1314a82f,
  74813. 0xd657f230, 0x2c8d7ab2 },
  74814. { 0x0825e4d6, 0x67cf5892, 0x6ef83b44, 0xdf51eaa5, 0x1310108d,
  74815. 0x63e665d8, 0x8dd0963f, 0x229f89f5, 0x9df6436a, 0x8c4b14dd,
  74816. 0xd45ebba7, 0x99dae469, 0x5a4df381, 0x118aab77, 0x29e37feb,
  74817. 0xda8978bd, 0xaca2d7ef, 0x69ced5aa, 0xc67d6a8a, 0x6c98d05d,
  74818. 0x77f84a34, 0x7474bf0d, 0xed8cd59a, 0xd4428b2e, 0xd1d398fb,
  74819. 0xb0fd1cd5, 0x94a20b11, 0x596013db, 0x1b404c44, 0x96eb705a,
  74820. 0x4b09d958, 0x2299d277 },
  74821. { 0xc64397e6, 0x5b9cd58d, 0xbf6dd31e, 0xac198f1e, 0x3e9f1db2,
  74822. 0x5866d8e1, 0x8fcdc68c, 0x405ae287, 0xe53c01fd, 0xa4b280cd,
  74823. 0x411db5f6, 0xdc963f2d, 0xbec4f8a0, 0xed5d5189, 0x916ee98b,
  74824. 0x336fd13d, 0x042df48e, 0x6925b1b3, 0xace0074e, 0x0cf56291,
  74825. 0x25317e95, 0xe8d38b48, 0x821c446b, 0xc7ad1d2b, 0xf0b65934,
  74826. 0x71c44135, 0x52ca0d50, 0x971b736f, 0x27b46c26, 0xaf9ffa57,
  74827. 0x1936618e, 0x21ac6779 },
  74828. { 0x2d7fbcd2, 0xab420e3f, 0x97bdfc18, 0x12722473, 0x4df5d4b4,
  74829. 0x492033f8, 0x3807b7d3, 0x6fcd4236, 0xb33c3625, 0xdfc19b09,
  74830. 0xa0f22814, 0x13d6f375, 0x037c19b8, 0x70978a59, 0x0ff27b9c,
  74831. 0x4f398997, 0x615a4389, 0xfc0e1a45, 0x3e602f74, 0xffa3496a,
  74832. 0xb261ca1c, 0xc3f1c431, 0xee0164cd, 0x612211db, 0xe7f7be9f,
  74833. 0x30463ee4, 0x92c2e1bb, 0x015f7e78, 0x24483a56, 0x663d88d6,
  74834. 0x0e62d9d8, 0x0e8ec1e7 },
  74835. { 0x8a0878dd, 0xa88ccc29, 0x6640071a, 0x99ac175d, 0xa5173617,
  74836. 0x90344820, 0xdd58a315, 0x316d023e, 0x88d221a1, 0x30785bd4,
  74837. 0x959c48e3, 0xb74b3de7, 0x4c67a771, 0x42ee0382, 0xe0b91453,
  74838. 0x59ef6cdd, 0x9b237e91, 0x7830ae28, 0x495d8325, 0xe1847a4c,
  74839. 0xd0773666, 0x67b1217e, 0xa294a325, 0x58192c86, 0x864d8326,
  74840. 0x76aa0f56, 0xf4b13e5b, 0xe2a2bd12, 0x1b6b73fd, 0xd850c1c0,
  74841. 0x5d103635, 0x653a795f },
  74842. { 0x50dcb199, 0xcfe28985, 0x7fa02b60, 0xb35b8e5e, 0xc97603d0,
  74843. 0xbca7d7c3, 0x27f131b5, 0xb0e5288d, 0xe2b12d52, 0x3aa704de,
  74844. 0x1db725c7, 0xe206b1d8, 0xc5d1b113, 0x0b12839a, 0xdb45d763,
  74845. 0x14f970cb, 0xb2125e8e, 0xc997f93e, 0xee7daa26, 0xbd75739c,
  74846. 0x1fef20e9, 0x46ecbd3f, 0x7c6a42b1, 0xf994a114, 0x27fb0fd1,
  74847. 0xd289eb4f, 0x9a40da4b, 0x11186d31, 0xfb9d7976, 0x083f65a5,
  74848. 0xd444675e, 0x30dfc47b },
  74849. { 0x9eaadfe8, 0xbcfc5ae2, 0xb4d4e812, 0x25027e54, 0x8b533561,
  74850. 0xab0702df, 0x56a6a214, 0xa2b9c204, 0x3059068e, 0xb1a3df7a,
  74851. 0x9883110f, 0xa3514b21, 0xc4b78e1c, 0xb7be2336, 0x3e2f6984,
  74852. 0x17073ce6, 0x2ddf7ac6, 0x86e114a6, 0x07d7c3c8, 0x276192bf,
  74853. 0xeb1ae289, 0x5da69e0b, 0x25184939, 0x983af175, 0x407a3aa0,
  74854. 0x9ac52a4d, 0xae0fe218, 0x1535c7da, 0x397f2501, 0xe16fe872,
  74855. 0x54c212cf, 0x572a591f },
  74856. { 0x09a5553a, 0x49668419, 0x327733bc, 0x3f054318, 0x3eefd690,
  74857. 0xf9ceb4b2, 0xf22126d4, 0xbd3cbf9b, 0x2fed9578, 0x6d9671c0,
  74858. 0xca0306d8, 0xbba597ce, 0x3d674fe5, 0xb705ed61, 0x67f33f76,
  74859. 0xf1d3622b, 0x11cb8c31, 0x15bcf3c6, 0xe53d1aa9, 0xa38467dc,
  74860. 0xf908ab43, 0x902fe929, 0x8d15767a, 0x6e3e499d, 0x90afd07b,
  74861. 0x8142db5c, 0x6c8b190e, 0x120c6fbc, 0x24919a4e, 0x80c86553,
  74862. 0xd8c82c3c, 0x65c2cbe1 },
  74863. { 0xa660bb63, 0x684cda20, 0x86e86245, 0x27dc3b0a, 0x6ba0eed7,
  74864. 0x76472cf6, 0x679dd158, 0x79c162e5, 0x08452d44, 0xb6884277,
  74865. 0x413f579e, 0x829bc6b3, 0x95011770, 0x92ea15ec, 0x47738183,
  74866. 0x5e34e300, 0x73e1d2f1, 0x8c3ca349, 0x229bd3de, 0xa5c4f1dc,
  74867. 0x94ef7ed3, 0x783eff1b, 0xdfae7a1a, 0x46db738d, 0x1a099852,
  74868. 0x4353d72e, 0xa0dcf4ab, 0x2533ad58, 0x0e7888b9, 0xd8055016,
  74869. 0x3ba77f66, 0x831440d5 },
  74870. { 0xf611b2da, 0xf43e2e32, 0xd0fa46ac, 0x5d066e29, 0x820b3c0d,
  74871. 0xe897f3e8, 0x1d3e44f0, 0xc45c28e6, 0xdfd27a66, 0x929d7f66,
  74872. 0x101e8517, 0x735b860a, 0x3de078dd, 0xea3fce98, 0x638ce11a,
  74873. 0xc9977db5, 0x48536b3b, 0x0488382f, 0x64cadfc6, 0x7e0c7a3c,
  74874. 0x82147b71, 0x3cd17f7f, 0x1b411e3e, 0xe95663cc, 0x985fb46d,
  74875. 0x5739ac8f, 0xbcf119ca, 0x385399cd, 0xe15a2815, 0x4a985a70,
  74876. 0x6d5f4566, 0x504c3a8a },
  74877. { 0xb8fa53c7, 0x00b55283, 0x509474e3, 0x985cff38, 0x437ce25f,
  74878. 0x234d241c, 0xe5a129ed, 0x29832430, 0xaabcc674, 0x6ad38956,
  74879. 0x7ee81ee1, 0xa2dc001d, 0x670b2702, 0x4c23c6b6, 0xa6e8a3bb,
  74880. 0xb35e567e, 0xa69673ea, 0xbc70b3ce, 0xe6e28eac, 0x85a7a9c3,
  74881. 0x5537b7da, 0x2ae684de, 0x6de937dc, 0x5ecac3e5, 0xf8430422,
  74882. 0xbf2ea6c9, 0x77fdc520, 0x38caf7d0, 0x69f56add, 0xc27af0b1,
  74883. 0xc71d21d2, 0x496e4699 },
  74884. { 0x9fa93467, 0xba14fc82, 0x0eb2a614, 0xc2e37684, 0x4833e09b,
  74885. 0x659bcfaf, 0x3686bdcc, 0xbc859752, 0x81f3216a, 0x40bfd080,
  74886. 0x17c081b8, 0xc463bda6, 0xbb04793b, 0xbd01fa86, 0x2cd640c5,
  74887. 0x5a21ece6, 0x2203d5c4, 0x97bf6a54, 0x951167b7, 0xceb40edc,
  74888. 0x765ba268, 0xd67aacaf, 0xaeab51f9, 0x8ba0d9e9, 0xb0d6863a,
  74889. 0xc14b215e, 0xe5f06952, 0x354cdcdb, 0xcb3744b5, 0x4f2b5ccf,
  74890. 0x13037fe8, 0x13389173 },
  74891. { 0x45003cd1, 0xee680640, 0x44ae2ac6, 0xfdac17bc, 0xde8e5314,
  74892. 0x4bcd419f, 0xc7cea95c, 0x81e34eb9, 0x38f37e01, 0xbb57762d,
  74893. 0x260990c8, 0xecc4cfb0, 0x50a34a7b, 0x0bc493f9, 0x543304ef,
  74894. 0x68074172, 0x6bc8aa2a, 0xaec0fcb2, 0x3b45fea5, 0x9e7a9b46,
  74895. 0x55fbdbac, 0x4bb2952e, 0x0485dff4, 0x50f0c0a6, 0x4dea4796,
  74896. 0x02c5104d, 0x695e3a02, 0xd2cefa09, 0x6da1f345, 0x4c8102b4,
  74897. 0xf3833fbd, 0x422eb573 },
  74898. { 0xa6ad3f47, 0xac592eb6, 0x9714ba0e, 0xb0861f6d, 0x07281459,
  74899. 0x57c1e919, 0x64ea5803, 0xcf7c94e2, 0x54b12723, 0x725376ac,
  74900. 0xdafb736a, 0xf2a6ba41, 0xcba03cdc, 0xc89e8920, 0x5b0fd3ad,
  74901. 0xf2e20cb4, 0xd66059fe, 0x26ea5a54, 0x889df8bc, 0xee63fa8b,
  74902. 0x66a3f2bf, 0x40f1c7e1, 0x747312e1, 0x09febc9c, 0x727999ff,
  74903. 0x7d19b9c2, 0xb7fd2b05, 0xa9fbbb4c, 0xa0da2dc6, 0xcfba27d7,
  74904. 0x2c252582, 0x368541cf },
  74905. { 0x22799d37, 0x510d3c9e, 0xacfa333a, 0x1b677de5, 0x080f795b,
  74906. 0x4e6ae18f, 0xafc8dfc2, 0x69b53c2a, 0x0e842dc2, 0x797541b6,
  74907. 0xac067fe8, 0xd5a6f2af, 0xbd07d877, 0xd0208a03, 0x654be2f2,
  74908. 0x34b473f0, 0xf515e23e, 0xe67c102a, 0x2ac1af48, 0xb00dbf9d,
  74909. 0xb6a13d00, 0xe264fa41, 0x97e94c11, 0x1669786a, 0x86a586f4,
  74910. 0x09d8cf2d, 0xc7f927e9, 0x073bf869, 0x2241a566, 0xb8977880,
  74911. 0x22261334, 0x59a5bf59 },
  74912. { 0x81347191, 0xe9d1c91e, 0xeb969972, 0x186c1abc, 0xa9d46a7f,
  74913. 0x07888767, 0xdaa7d397, 0xda93cfcc, 0xd91b9aa0, 0x08bee9f1,
  74914. 0xf8dd3c6c, 0x8267fd78, 0x94228100, 0xf93860d0, 0xdadb47fb,
  74915. 0x6a6a71aa, 0xa6156f8a, 0x9caa06b7, 0x39848bc9, 0xaa1b05e0,
  74916. 0x2aaa9135, 0x36ddc237, 0xb13f3bd1, 0x77e7e079, 0x4acc5f4d,
  74917. 0x8d0b5cbe, 0x984cfd36, 0x04da45f8, 0xd3d3e0f8, 0xf14ef618,
  74918. 0x43eb799c, 0x467564c1 },
  74919. { 0xb6fff5d7, 0x8d725904, 0x92dc4752, 0x037f33af, 0x6d20b8aa,
  74920. 0x9095d575, 0x43baec39, 0x32235fc1, 0x68a2b9b0, 0xa2feb4af,
  74921. 0x94d35c61, 0x61c50318, 0xea877486, 0xac92b6a2, 0x011bc6f3,
  74922. 0x8eb48b15, 0xc79edcb2, 0xa28fe128, 0xa5d2a006, 0x9f71bc0c,
  74923. 0x2f15b850, 0xf3167732, 0x7a036218, 0xfe8d728c, 0x4f81e09e,
  74924. 0x068f39cb, 0x7b7c50d9, 0x1773f016, 0xed6a1e03, 0x0d0f7adb,
  74925. 0x4ee984d5, 0x8a0dee16 },
  74926. { 0x47366e6f, 0x504991bf, 0xe86c3005, 0xb8084d9f, 0xa40cce36,
  74927. 0x14c4c751, 0x3f1961e2, 0xbbb46aa6, 0x40445e43, 0x56a785f9,
  74928. 0xc91e215f, 0xdb8d1b57, 0xc7ee808d, 0x6a8e453e, 0xbbaa1e8c,
  74929. 0xc0367ef8, 0xe3e18109, 0x310d91f1, 0x7e20a2c3, 0xf97cfd0e,
  74930. 0x554cc277, 0xf1e80c84, 0x7b628403, 0xe89bbc1d, 0x3fe0a17c,
  74931. 0x7778a966, 0xc1f00073, 0x9e9db19f, 0xb6f6bed2, 0x2ce7fe7d,
  74932. 0xee97ce23, 0x7b04b5d2 },
  74933. { 0x82c5faf8, 0x5b546bc7, 0x8eb81097, 0x1a734c5e, 0xe77851e0,
  74934. 0x3d566861, 0xe956d51f, 0x833a1013, 0xc3c3c37c, 0xc7351731,
  74935. 0xe0c148ec, 0x607738fb, 0xe1bbef41, 0x2ec6f0bb, 0xcfa51857,
  74936. 0x0aa2ac6e, 0x66e3adf0, 0x072902d7, 0xc622d6e3, 0xcd4d5089,
  74937. 0xa6dd802f, 0x3ae21b23, 0x33886372, 0xe5465a55, 0xa8d81822,
  74938. 0xd85119a0, 0x3786977a, 0x4f14d032, 0x9c7b272c, 0x515b081c,
  74939. 0xc99be31c, 0x1c6a95a4 },
  74940. { 0xc2821363, 0xa6b14ad5, 0x4d17de1c, 0x829c1823, 0xccade848,
  74941. 0xaef5d2c4, 0x82489e27, 0xf412ab39, 0xf081d927, 0x92c9c098,
  74942. 0x75cbad1f, 0x6f87bdf4, 0x1a1d9fb1, 0xf4aadab8, 0xb75f3b76,
  74943. 0x475a7923, 0xdbbba8fe, 0x99dd0ad6, 0x4b70ab45, 0x836f6164,
  74944. 0x34bd9af1, 0x2a464881, 0xba9abda3, 0x5c91226e, 0xe65625fb,
  74945. 0x4cec8709, 0x0818e4be, 0xd4b3919e, 0x14f6879c, 0xa5c09c84,
  74946. 0x30a864c9, 0x72708a02 },
  74947. { 0xf34a466c, 0x4f33c0b1, 0x7f9d45ba, 0xa1bae09c, 0x0e28785c,
  74948. 0xd70f0fee, 0x90880881, 0x824c7146, 0xbb043da3, 0xe2416c2a,
  74949. 0xcec6f432, 0x733da713, 0xc9793e1c, 0x2b590649, 0xb35c9365,
  74950. 0xdb62d5b0, 0x3e5c1b2a, 0x355eb6e2, 0xbb16b515, 0xcfe8b5ce,
  74951. 0xf709691c, 0x9e081869, 0x61a85bd5, 0xc865f9fb, 0xfae103f7,
  74952. 0xf169d3cc, 0x73467e9d, 0x9525c473, 0x43695113, 0x7db55c0b,
  74953. 0x73265d21, 0x7491c74c },
  74954. { 0x80d2b94d, 0x312ed5bf, 0xba4b260b, 0x1b8ac633, 0xd62219a1,
  74955. 0xac86c58c, 0xaeb82c8e, 0x317ccf6b, 0x59ef9ced, 0x2dfb29ee,
  74956. 0xe42bcd5a, 0xdaa7d898, 0x5974b201, 0x93e295c8, 0xd9fc5adc,
  74957. 0x69e75784, 0x012aa3ba, 0xd6c4709f, 0xc85d3cb9, 0x1fda9f37,
  74958. 0xd3dd4abd, 0xe5487e25, 0x0b3ba22e, 0x00fd4b01, 0xc6e8dcbb,
  74959. 0xcb591493, 0xbce68664, 0xb7329fab, 0x68906b76, 0x6829d1c2,
  74960. 0x74176841, 0x8bcfd3e5 },
  74961. { 0xd3c8c314, 0x06882734, 0x11870833, 0x95f0b2f1, 0xc068ba16,
  74962. 0xb937f7c3, 0x77924787, 0x5365e0d8, 0x1f992227, 0x15527e5e,
  74963. 0x27dffd4f, 0x0a069648, 0x2f586389, 0xd58b3df2, 0x6af20ead,
  74964. 0x83446b89, 0x50746257, 0x09d7970b, 0x4022a691, 0xd9e8d206,
  74965. 0x671ec379, 0xd1e5f8af, 0x057fe91e, 0x6f542509, 0x52890418,
  74966. 0xf14dda81, 0x1db932ad, 0xbd78010e, 0x905a9378, 0x3e18d1e4,
  74967. 0xbd37ab49, 0x53cadcf7 },
  74968. { 0x5e53d0ff, 0x1bb5edf7, 0x888abf67, 0xd886606c, 0x12206d15,
  74969. 0x6491b0f8, 0xe22b6a33, 0xb3018345, 0xb173b317, 0xaba6794b,
  74970. 0x7dc9e595, 0x8c1e5867, 0x239624d1, 0x4e106482, 0xda55dd53,
  74971. 0x61752e59, 0x9e42879c, 0x018b4eab, 0x491f2bed, 0xcaf6784b,
  74972. 0x1e79429e, 0x3dcdb9d2, 0x10f26224, 0x36941485, 0xa650ec5c,
  74973. 0x106f190a, 0xb69a9760, 0x7542a5ae, 0xc32d1046, 0x69bd75e9,
  74974. 0xbf8c62b1, 0x90849964 },
  74975. { 0x5a93c661, 0xb1390cf6, 0x9db5f056, 0x18486264, 0xa51a1788,
  74976. 0x92a93a9d, 0x6772de9a, 0x1b0cbb8f, 0x7c71487c, 0x6e67febd,
  74977. 0x4e62423e, 0xf9b4382d, 0xbb5a42f8, 0x96fda50e, 0x6089a4f2,
  74978. 0xc921b337, 0x875ec516, 0x49d32d7b, 0xc410124b, 0xbd86d2ca,
  74979. 0xc421fb7a, 0xf6862209, 0xf6b7de33, 0x3e1949ab, 0xe93c9268,
  74980. 0xcdee18f0, 0x08dc4cc0, 0xd4edbd5e, 0x73580d22, 0xc2b75be4,
  74981. 0x468cd7e8, 0x3d7f6ffa },
  74982. { 0xdffbd5d1, 0xea7b290c, 0x970338df, 0x9d759da6, 0x90feedc9,
  74983. 0x56680b08, 0x42dce68e, 0xbc690af5, 0xb2ae4d82, 0x8519df2b,
  74984. 0x7f195b60, 0x5612467f, 0xd83c21f4, 0x659a342c, 0x55651633,
  74985. 0x55771bf5, 0x548ba562, 0x5fc68935, 0x9492f23a, 0xb5419203,
  74986. 0x9c9c6017, 0x567528e3, 0x511e6019, 0x3f064ed4, 0x1d16a555,
  74987. 0x303f9eb9, 0x2254abee, 0x3e18c4fd, 0xfd434e7c, 0x40994d6f,
  74988. 0x6dde74e6, 0x8fb12d3f },
  74989. { 0x293cb7a4, 0x6c6381a2, 0xb87b7e4d, 0x453e09f0, 0x078ac3ef,
  74990. 0x4f212823, 0x578cae91, 0xe89ffad0, 0x716ba4dd, 0x4a2b696a,
  74991. 0xf6f580a0, 0x14681a14, 0x4c2f1307, 0x1358f97b, 0x2932fb89,
  74992. 0x87896996, 0x268a5af7, 0x29dd850a, 0xfe239f83, 0xaf771f6d,
  74993. 0x4f47499d, 0x5f20fd2e, 0x867ca0e9, 0x9b643e77, 0x375981ec,
  74994. 0xe7858ecd, 0x19ab1c97, 0xbe946a59, 0x06ff3453, 0x4f9303a2,
  74995. 0x75d237b1, 0x3fcc6731 },
  74996. { 0xdf21f920, 0x509debd5, 0xc1401b90, 0xfaf70e1f, 0x95a64aaf,
  74997. 0x2429cbfd, 0x2c37a122, 0xf2120855, 0x7deb926b, 0x1d4c93f4,
  74998. 0x9fb3f1dc, 0x12f3e4c0, 0x5b51bc46, 0x56085a59, 0xf10fdbd2,
  74999. 0x2a2f5d62, 0xdf0cb3c2, 0x60dd62cf, 0x6b0f254b, 0x154424a3,
  75000. 0x564612b7, 0xc3a5a05d, 0xa1f5249c, 0xbebe30cf, 0x7e62a188,
  75001. 0x24ec6903, 0xaf429939, 0x75f0fbac, 0xb3fa8685, 0xd41345dc,
  75002. 0xc7151c34, 0x645146fd },
  75003. { 0xba1924f9, 0xecec633a, 0x006326e1, 0xbba6f136, 0x7e50fc17,
  75004. 0x203757ac, 0xef3d8e00, 0xca531919, 0x51dc5a74, 0x9545a6aa,
  75005. 0xd31412b8, 0x6e21d58f, 0x7bb1d000, 0x01bc3005, 0x6ed1a9c3,
  75006. 0xf1789c69, 0x9858fa48, 0x7af2d35f, 0x8197be85, 0x434d09b9,
  75007. 0x29aa265d, 0x1dc07755, 0xc058fa80, 0xcad03be7, 0x54ba14ce,
  75008. 0x92d70a9f, 0x6c050a74, 0x6dc78505, 0x4d005dda, 0x2a7ca4a9,
  75009. 0xabfb9f2e, 0x448d3d72 },
  75010. { 0x29b33989, 0xdc56f145, 0xa9ae815a, 0x868351bc, 0x4b074414,
  75011. 0xb3f45613, 0x3cd9f33b, 0x955ce42a, 0x5ff6e4a3, 0x13ade4ec,
  75012. 0xa50eaa91, 0xd3aac715, 0x5666efdf, 0x0c61ec99, 0xf6a4470a,
  75013. 0x108a28b8, 0xe54844c9, 0x402ef584, 0xd0e2f337, 0xb825b162,
  75014. 0xb46f7cbc, 0x3dcd131f, 0x96f2fd89, 0x208178ec, 0x25928c78,
  75015. 0x4d8c5d67, 0x9963c459, 0x285a33df, 0xd92a309f, 0x72497175,
  75016. 0xcb7019a5, 0x76881479 },
  75017. { 0x91767eed, 0xba43a114, 0x92bf65db, 0x5e11b9ad, 0x03a5e21a,
  75018. 0xe8a22ce0, 0x2a335415, 0x63604421, 0x4a9ead62, 0xc2c563b4,
  75019. 0xa0b2aee5, 0x4bc06264, 0x8bf2e1d7, 0x75b8d575, 0xd08a265d,
  75020. 0x1cff0ee7, 0xb0b712a7, 0x17914e1d, 0x4b18692d, 0xc35925d0,
  75021. 0x56cce815, 0xde253f4c, 0x9fff0e3a, 0xa479241c, 0xddabed19,
  75022. 0x50b9d06e, 0x59fae506, 0x67135260, 0x532ce180, 0xf37600fb,
  75023. 0x5e5a8626, 0x670eb01c },
  75024. { 0x73cdbb43, 0xdf73c0af, 0x7f2431ad, 0xcf08ecc5, 0x2a1a3845,
  75025. 0x91780541, 0x9224ddf1, 0x69a104f2, 0xbeac7eff, 0x4352f38d,
  75026. 0x7c2d1322, 0xfc3b3b4e, 0xb5e4b476, 0xa69e9430, 0x975a46f0,
  75027. 0x7d932340, 0x5d64eece, 0x8093899e, 0xdb2345e9, 0x7b821250,
  75028. 0x7f4b796b, 0x23552932, 0x4bb90b1f, 0x2ee9cc15, 0x9112f7d6,
  75029. 0x1fa9c8f5, 0x1cbaae32, 0x2d0f2f98, 0x0075166a, 0xb77f0366,
  75030. 0x635dff27, 0x504852e7 },
  75031. { 0xa2f392fa, 0x2f0f3ce5, 0xec6c9078, 0x326c076a, 0x84baaaf6,
  75032. 0xad01de92, 0xcbe8e993, 0xb01b16d3, 0x2d950908, 0x71305c24,
  75033. 0x3853af38, 0xc66fd617, 0xd3c429a0, 0x7735140e, 0x1fabf027,
  75034. 0x8a31b12a, 0x058b3177, 0xa0530002, 0xa9c7deb9, 0xabffd9fc,
  75035. 0xe8667d30, 0xd05ef69b, 0xe9a9e13f, 0x2f3a7308, 0xb91eae9c,
  75036. 0x3f4c9a19, 0x618ce6c4, 0x50d0cee7, 0x5240f8b0, 0xfb24dc40,
  75037. 0xf7e90cc4, 0x992fe151 },
  75038. { 0x38f197aa, 0x4454db31, 0x87872f98, 0xa4ded69d, 0x44f0a828,
  75039. 0x97b427b0, 0xa31e48c6, 0x9821e1ae, 0xdd98efec, 0xe38cb09f,
  75040. 0x480cb3ae, 0x20b84fa8, 0x47475573, 0xba5bb4a8, 0xcd50e96b,
  75041. 0xa9be080a, 0xef103550, 0xc4451e9c, 0xc441325c, 0x626ee75f,
  75042. 0x38a5e33d, 0x6eea5e98, 0xa2b0abd2, 0x7321beb9, 0x9b6082a9,
  75043. 0xca92e484, 0x992bcc2a, 0x1dc8168a, 0x9c8eb9fb, 0x134ecf4b,
  75044. 0x4c5b71e0, 0x5a68bfa8 },
  75045. { 0xff0a2bfb, 0xb4ff3b45, 0x5502f8b0, 0xd105fff9, 0x5b1c0c26,
  75046. 0x14de5885, 0x0d3b9d04, 0xed16865b, 0x026d3917, 0x2f5a2453,
  75047. 0xf4db3c0e, 0x6a22f493, 0xe2418f2e, 0x4871548a, 0x509bef61,
  75048. 0x6ab363a8, 0xb8cbbbec, 0x91ca1e3a, 0x4011a396, 0x71e0dc98,
  75049. 0x0d5ca577, 0xff982e0a, 0x81897bc1, 0xeb40b045, 0x085ad5e7,
  75050. 0x4bc24a46, 0xa6337b7c, 0xd15c8fa0, 0xbef1628f, 0x56ce6ef7,
  75051. 0x9f5ef439, 0x78acfdf9 },
  75052. { 0xf8520189, 0x45bf7f15, 0xc77f61c4, 0x954202a0, 0xdfa22e1b,
  75053. 0x39edc6b9, 0x1f4a3487, 0xd2d60267, 0x4814cc52, 0xcd933929,
  75054. 0x05e9f123, 0xde76a124, 0xae36b6f7, 0xe2306ea0, 0xb83a58e0,
  75055. 0x53815218, 0xa041231a, 0x9862bb76, 0xbf31be71, 0xe8da253c,
  75056. 0x37de861f, 0x2dfc5332, 0x90ae4890, 0xf25c93f6, 0x8baa6ed2,
  75057. 0x66bcb8f0, 0x908b4a29, 0x6f10ae0f, 0xb061c949, 0x8cb4b48c,
  75058. 0xd075a366, 0x0ad92d73 },
  75059. { 0xc2ca548a, 0xbfb95fed, 0x80cd89ab, 0x4778c620, 0x3466c280,
  75060. 0xbe99154b, 0xd4be8902, 0xea3be093, 0x13e681ed, 0x847b7995,
  75061. 0x02f40161, 0xf22a8f4b, 0x4aeb7fe8, 0x3ef2cb4d, 0xb3aed5f6,
  75062. 0x9adc5151, 0x98c31163, 0xec1ccfd1, 0xa3d7d88f, 0xdc2ac17b,
  75063. 0x46421097, 0x08fa64d3, 0x94b90bcf, 0x5ebf80b7, 0x0b50a9eb,
  75064. 0x1b78b4ba, 0x279aa66b, 0x1a4fe934, 0x075b3ced, 0x8ef4dcaf,
  75065. 0x70a6e9ae, 0x95bbd8a0 },
  75066. { 0xe614bbd0, 0x59f92495, 0xb823e363, 0x7567a887, 0xfc1bd6a7,
  75067. 0xe247c9ec, 0x8e835c42, 0x2bfaaf47, 0xaade066a, 0x314ef4e0,
  75068. 0x5c16d336, 0x072baa63, 0xe2f0e389, 0xfa429c71, 0xbd07d90f,
  75069. 0xcac1e5d0, 0x514f5c04, 0x69ff35ea, 0xc0554ec1, 0x893053fc,
  75070. 0x2a35947f, 0xab1d86b7, 0x2aebe487, 0xe29fb060, 0xdfb9cf21,
  75071. 0xa0a10d6d, 0xf20dfcf5, 0xad147059, 0xb8867a2a, 0x480dc66f,
  75072. 0xc125a919, 0x375a884f },
  75073. { 0x1217f7ea, 0x178cbe2e, 0x875c6dab, 0x1a161e2a, 0x1bdb1a54,
  75074. 0xf7707ec0, 0xe4fd73ca, 0x678864a0, 0xd13a0d86, 0xbaebc664,
  75075. 0xc8d30668, 0x40325f99, 0x2f1c5950, 0xb93ed9c9, 0x541e0667,
  75076. 0xfdf36763, 0xb91a6763, 0xfd97fbb0, 0x6079c9a0, 0x26aa69ea,
  75077. 0x1eaa8c47, 0xc7303c80, 0xafa63c55, 0xdec75c81, 0x4fd12adb,
  75078. 0x01cdcde2, 0x1968838a, 0x9fe0dda7, 0x38415379, 0x66bb093b,
  75079. 0x08cb84ec, 0x268d818b },
  75080. { 0x41580555, 0x73dae358, 0x473d103b, 0x4fc32e67, 0xbeccc1ab,
  75081. 0x240c1013, 0xb24ee9de, 0xda4099f2, 0x9fa8e066, 0x37b0cb5b,
  75082. 0x6438d7ee, 0xb5ae04e4, 0x2b720140, 0x7f7d3164, 0x339e4a78,
  75083. 0x86ef4edb, 0x3a7d8375, 0xa5e77eed, 0xbd707c2e, 0x883fad37,
  75084. 0x0f979189, 0x816b633a, 0x2e7a208e, 0xe24c028a, 0x4435516a,
  75085. 0x1171fe3c, 0x4f5f2bf5, 0x3eb93b33, 0x01b53a56, 0x8419ed4b,
  75086. 0x056ca44b, 0x8b02735c },
  75087. { 0xe1019195, 0xb89bb464, 0xf3fc28c1, 0x1de4c026, 0x2bfc3b21,
  75088. 0xac120e6e, 0x91bdf92f, 0xec71bc5a, 0x0d995bc9, 0x485d7ab4,
  75089. 0xe6491ffe, 0x97c6768e, 0xafbce265, 0xd9552d19, 0x8e1b76c2,
  75090. 0xbae6c7fe, 0xd7e3ad1b, 0x167d8281, 0x5e989734, 0x3e149af9,
  75091. 0x8a0c8182, 0xd1f0024c, 0xc3006c0d, 0xf571ffdb, 0x58773d4c,
  75092. 0xb32ecf7e, 0xfd3540d8, 0x5822a782, 0x04365042, 0x5ab45c3f,
  75093. 0x4b4d85fe, 0x400e3aa0 },
  75094. { 0x5e46e4a2, 0x47321649, 0x24136074, 0x37a2ed64, 0xc60ec77d,
  75095. 0x659223b1, 0xe5e0ac2e, 0x5e13aac3, 0xc5107ab7, 0xda17c41b,
  75096. 0x73c253db, 0x65b22ec9, 0xa5012296, 0xff3867b8, 0x0621a99b,
  75097. 0xfed660d5, 0xc89fc3f5, 0xa3c28506, 0xf16451a7, 0x3ed350b9,
  75098. 0x67cb586f, 0x27c3e032, 0x967185b1, 0xc807c779, 0x4a13009b,
  75099. 0x09c157d4, 0xadaf1f4d, 0x362f7647, 0xf3a6a198, 0x4a42b9ac,
  75100. 0x8da6e039, 0x131c3da2 },
  75101. { 0xa7da83ba, 0x4a785ff1, 0xd04f4436, 0xf415b425, 0xec03f812,
  75102. 0x7c0899bd, 0x80f5f4a2, 0xc58d411a, 0xfda251b9, 0x3d32d610,
  75103. 0xcd3b2f32, 0x99bb4504, 0xf4c2083c, 0x198c444b, 0x730e83fd,
  75104. 0x60c261af, 0xcb02db90, 0x060ca4df, 0x9df1e7c8, 0x0ff7838b,
  75105. 0xc4c690c9, 0x6b79cf97, 0x5d75f154, 0x131514d7, 0x1cb0e8ff,
  75106. 0xa7c074f1, 0xb2c17615, 0xb920aac1, 0x44aa0ff0, 0xde8098ad,
  75107. 0x34545ce9, 0x71d1a46a },
  75108. { 0xfa1b382e, 0x76178f76, 0x772dda0d, 0xa0d8ecc3, 0xc5d4d130,
  75109. 0xaa5aab2a, 0x8d72622c, 0x27d38ba4, 0xca3bed06, 0xc5410db6,
  75110. 0x793ceccf, 0xf637a588, 0x6e65e3d7, 0x1f65dafd, 0x60a45641,
  75111. 0xc3b44a85, 0x4f78540b, 0x0f47b3a8, 0x5e4d60f6, 0x824fdadd,
  75112. 0x17d3b6d5, 0xd8ccf90c, 0x325fc13a, 0x008eabdf, 0x3648fab9,
  75113. 0x3e90d716, 0x24c52d4b, 0x3964ff3a, 0x533d0acb, 0xb95cc416,
  75114. 0x1167f521, 0x6cd2699f },
  75115. { 0x12f4f3ac, 0x2d8c0b3b, 0x99d1bdfb, 0xb03dcfe2, 0x30f37326,
  75116. 0x540034f8, 0x7c5a8c82, 0x22dd6893, 0xcd8f1442, 0xeb7093d0,
  75117. 0x585742f2, 0x892795a7, 0x087adadd, 0xe15f282c, 0x16ab7b5e,
  75118. 0x7bbdc749, 0xa58acbb4, 0xd30fe40b, 0xe2bac39b, 0x0de417eb,
  75119. 0xc61a04bc, 0x4b4b19a6, 0xf2735569, 0x9338c34d, 0x30ab196f,
  75120. 0xe8f03742, 0x6c88c965, 0xfa2efcb8, 0xc7eeb826, 0x19eee274,
  75121. 0xda345dc2, 0x327c063f },
  75122. { 0x5b47cd53, 0xab399eff, 0x1943aefe, 0xbbe9869d, 0x1402a866,
  75123. 0xe64ecc7b, 0xb1c25a16, 0xc3e7c2aa, 0x022de271, 0xc4216b79,
  75124. 0x366d6a5f, 0xe58dfcc8, 0xda813336, 0xd159509e, 0x130bfb7c,
  75125. 0x370400f2, 0x93b48780, 0x1be4e059, 0x39f3cd22, 0x0623a1fe,
  75126. 0xeecb4f87, 0x72aa22b2, 0x6c27b83b, 0x1af4c496, 0xda5fa5bf,
  75127. 0x7a42a94b, 0x48b01af2, 0x9afba822, 0x3670112c, 0xeb6b9d2a,
  75128. 0xc0df6856, 0x020f19d1 },
  75129. { 0xa4dbba20, 0x37051a86, 0xdb1de5c5, 0xb618ebc6, 0xe6525840,
  75130. 0x9a780a19, 0xd2bccc4d, 0x9440302d, 0x10285a24, 0xe9ff023d,
  75131. 0x3a486268, 0x3b937ee3, 0x4cd61147, 0xe37ee2f2, 0xa3d057cf,
  75132. 0x79fbbfd3, 0xccddefce, 0x5fba16d3, 0x5b231727, 0x916058ec,
  75133. 0x720c3adb, 0x47699ebe, 0x8b4f6bba, 0x26274386, 0xf18a0770,
  75134. 0x54b0092a, 0xacca1160, 0x99d090eb, 0x0c888f60, 0xf757e1ff,
  75135. 0xb0050544, 0x79e72720 },
  75136. { 0x2820a239, 0x632acf25, 0xaae6b310, 0xb1a3974e, 0x48c0a1df,
  75137. 0xd61fd6ba, 0x5a3ee7aa, 0xd2453c39, 0xb980446d, 0x548455a0,
  75138. 0xde16676f, 0x9f29d97b, 0x789375a1, 0xf252ca0c, 0x7743a985,
  75139. 0xe961af3e, 0x66cdbd8d, 0x70c79c56, 0xcbc538f9, 0x14a3854e,
  75140. 0xa126851c, 0x58daa73a, 0x2a9f558c, 0xe9b5bb45, 0xfbd15e05,
  75141. 0x37af7f83, 0x38a1939d, 0xa4487927, 0x9511a056, 0xe428b2b5,
  75142. 0x7015846d, 0x001d3ce3 },
  75143. { 0xe145b1d7, 0xd6be36b9, 0x009c5664, 0xf3e3938a, 0xe7c0f6db,
  75144. 0x2e562e7d, 0xc343f539, 0x951044e6, 0xd90897b1, 0xa5ab62b8,
  75145. 0x512f797c, 0xb1a1f70b, 0x750f28e4, 0x91cdd754, 0xffb8165d,
  75146. 0xb4c80e2f, 0x594d02b3, 0x65ed39c7, 0x56833edc, 0xcc12a49d,
  75147. 0xf3693a18, 0xe73694bc, 0xfcd2c404, 0x34cc134a, 0x11d40194,
  75148. 0x071bd5fc, 0xfc585e46, 0x05759047, 0x790b7a04, 0xb3280360,
  75149. 0x40afc684, 0x4bb8c6fc },
  75150. { 0xfd0f8796, 0x3120e2dd, 0xb133c9de, 0x6968a40d, 0xa9369c6e,
  75151. 0xfea366c0, 0x6007273b, 0x37e5b6d6, 0x8cb81439, 0x39e4ecf0,
  75152. 0x9febc005, 0x487fe9cd, 0x0199b53c, 0xeb8af444, 0x293519eb,
  75153. 0x2f124e3b, 0xc82c9c16, 0x860c218a, 0x709dc590, 0xacd1d6f2,
  75154. 0x36d50529, 0x5696d545, 0x59120bfc, 0xc03f5df9, 0x10ffa690,
  75155. 0x99a3e88d, 0x6c432827, 0xd4f9cfa5, 0x9a135d89, 0x2e8fea9e,
  75156. 0xb6a77e78, 0x3699a881 },
  75157. { 0x1eb1c64d, 0x5bca3372, 0xf1d28154, 0xe9cf3a2d, 0x6537106f,
  75158. 0xb7e2e9b3, 0x4f7cbf4d, 0x06c17151, 0x2058b37f, 0xcbde416e,
  75159. 0x8834e9c5, 0x82c53a7e, 0xe9ac3a75, 0x94dbdfe2, 0xc5e67c02,
  75160. 0x795ec6cb, 0x1426a80d, 0x8c23c25f, 0x6a8d4f9f, 0xee2cd20d,
  75161. 0xd3b7c235, 0x838daa54, 0x3d7a4d52, 0xb9e08ec0, 0x781cb473,
  75162. 0xca9475e9, 0x5ec31caa, 0x7271f39e, 0x82535187, 0x1df08e9f,
  75163. 0x208aff8b, 0x4f3a4b03 },
  75164. { 0x1ed095f8, 0x0f7b8107, 0xda226d4e, 0x23e37fa6, 0xafb36d1d,
  75165. 0x8b0f9852, 0x07d8e311, 0xb114634e, 0xe3e0f16e, 0xb9634a97,
  75166. 0x421eec37, 0x2454bb9c, 0xd72b21c1, 0xb4ecd5db, 0x6df20d7c,
  75167. 0xf9603868, 0xdf86e0a2, 0x9f5359fd, 0x5ac488aa, 0xc43d54fa,
  75168. 0xd1049df4, 0x56d714ab, 0xb020607a, 0x13152b3e, 0x7a02325e,
  75169. 0x49be1c18, 0x52ae84db, 0x44f24f4a, 0x0b5a7b80, 0x9e525c03,
  75170. 0xa6d179fd, 0x6d874446 },
  75171. { 0xbe9a42f5, 0xd29d07aa, 0x3781ccc8, 0x1fd5316c, 0x9dc69ea1,
  75172. 0x71a75a6d, 0x88fee91a, 0x4e19e0df, 0xf8d44f12, 0x99c2b4dc,
  75173. 0x31ae94e4, 0x05f6df92, 0xcf28ccc2, 0x27fba876, 0xf57f7ceb,
  75174. 0x6e1a0f01, 0xf3fd3b74, 0xe03f1f34, 0x42c1d213, 0xa0edc4a7,
  75175. 0x7deb8580, 0x5caac270, 0xaf0848bc, 0x0f5d791f, 0x07ac759d,
  75176. 0x17f514ad, 0x904fc531, 0x95a39734, 0x7bb70f3d, 0x95a4aca9,
  75177. 0xff9c5609, 0x3cf384c9 },
  75178. { 0xce1fc9e3, 0x700506ba, 0x676b0399, 0x49721742, 0xe72bf7b3,
  75179. 0x2b4a1b8d, 0x79b209f7, 0xca8602a8, 0xce26a8e1, 0x90580b90,
  75180. 0xfe24f39a, 0x1ef339b7, 0x629362e1, 0xb6c5d991, 0x577b24f4,
  75181. 0x51174e1a, 0x05e451e9, 0xf380fcb5, 0x148321bd, 0xf4d97afb,
  75182. 0x747e5d2a, 0x099806bb, 0xbe99a608, 0x85525d65, 0xd455e820,
  75183. 0x264828d9, 0xd8560a65, 0x8c8c5405, 0x71030770, 0x3c67e73c,
  75184. 0xee73df26, 0x2b248850 },
  75185. { 0x8541159f, 0x2173cde6, 0x4fb410b2, 0x78224c18, 0x1f2ca1c7,
  75186. 0x07a28619, 0xa8b23e40, 0x52c207d6, 0xa6b2344a, 0x071a0210,
  75187. 0xb5ed2945, 0xdb0e587c, 0x810fcc6c, 0x6c56b8ef, 0x62d843b9,
  75188. 0x1248c58f, 0x74c66975, 0x4b90363d, 0xe66c66f6, 0x6348f7f2,
  75189. 0xc126bcbe, 0xb2f9d441, 0x73ce49e8, 0xac07f2a3, 0xe81b0df0,
  75190. 0x52486758, 0x1d4621d1, 0xa108b54d, 0x74414a1c, 0x17261ece,
  75191. 0x6a3ac215, 0x938b3bcc },
  75192. { 0xe4ded340, 0xa9e4a16b, 0x80e88036, 0x8e65fb2a, 0xdcd73acb,
  75193. 0x97089606, 0xaaa657a9, 0x1c3a0434, 0x49101b06, 0xf304fc58,
  75194. 0xda0bb64c, 0xe60fb61a, 0xf5542df5, 0x818c2aec, 0x56f76d5f,
  75195. 0x74020576, 0x92533d97, 0xb566b790, 0x74d6eb5f, 0xae4655e5,
  75196. 0xa55b44b7, 0x60f7a1b5, 0x93747ea5, 0x7970179b, 0xf2dace56,
  75197. 0x8ae7e0e8, 0x84e83c06, 0x98474607, 0x15307341, 0x24e8c9ed,
  75198. 0xd9e89d6b, 0x6cff58a5 },
  75199. { 0x03e51f68, 0x508c01b0, 0x1d2fe7d6, 0xe1d1f225, 0x09bd8805,
  75200. 0xf7998d0b, 0x03e415b7, 0x255e907a, 0x607d9798, 0xd148467d,
  75201. 0x9b453896, 0x055c3b1e, 0x809f50f4, 0x35001013, 0xd0233fdc,
  75202. 0xfbbb2fa6, 0xff1820b8, 0x0b680b0a, 0x38d317e0, 0xb1d404dc,
  75203. 0xccc8c7df, 0x133d5444, 0x6ec13f84, 0x7fa847e6, 0x046e2e48,
  75204. 0xc33f83d8, 0x4863b3ac, 0x3c627fc5, 0xeb936af7, 0x5f67f8aa,
  75205. 0x31b79327, 0x5fe4ac8f },
  75206. { 0x8b6f401e, 0x581aa4bf, 0xad5c7ed4, 0x05db12a3, 0x6fb07b4a,
  75207. 0x7b018726, 0x9c22bcd4, 0xfdd11f04, 0x69371c95, 0x5454a7d4,
  75208. 0x99a46eaf, 0x066c55fb, 0x7fef96d0, 0x18637c7c, 0x6b83e95c,
  75209. 0xbafc1d34, 0x00bb42dc, 0x55c38593, 0x34e7e712, 0xdd8dec2b,
  75210. 0xb184cee8, 0x69c9cfb0, 0x49a27864, 0x8dcc0c42, 0x2010f2e7,
  75211. 0x290d95f2, 0x6977a420, 0x86e254c9, 0xeb2abdad, 0x20931c89,
  75212. 0x121c0548, 0x81377164 },
  75213. { 0x9c5a8edf, 0x6266b25e, 0x1078a7ad, 0x6e1388c2, 0x4876eedf,
  75214. 0x5f02737d, 0x62744617, 0x242fa7f9, 0xb385382a, 0x3e2cfbd9,
  75215. 0x02f71bef, 0xbadad7b1, 0x677d0a92, 0x562abcfa, 0x51fdff34,
  75216. 0x573ebd17, 0x7c250c78, 0xd7f65852, 0xc47ca896, 0xe0cf16ee,
  75217. 0x67622c9e, 0x8ccd79b0, 0xf8f2c075, 0x31fc5882, 0xa6008515,
  75218. 0x9232b37e, 0x82e8c5ba, 0x4d7bb361, 0xd2f146fe, 0xbf24735c,
  75219. 0x9cd2db98, 0x79c280ee },
  75220. { 0xf2b48122, 0xbdcc8203, 0xb04ac48e, 0xa8c04916, 0x9fc4885e,
  75221. 0xacf064dc, 0x82c1001c, 0xab838997, 0x676de250, 0x7339e721,
  75222. 0x8e1ab820, 0x17aa5aea, 0x6bc14b2e, 0x24d28ca0, 0x816b6230,
  75223. 0x570c5bb7, 0xcee6b606, 0x6c51235c, 0x183eae42, 0x1b2bf89f,
  75224. 0x9c66274b, 0x3e3af3c6, 0xb51e38bc, 0xe0b04426, 0x73e40e3b,
  75225. 0x26dbc58e, 0xb5be5be4, 0x3f9dd578, 0x52c8f408, 0x9fd9f791,
  75226. 0xa9e3ff4f, 0x758073a4 },
  75227. { 0x8691ca22, 0x7d27b057, 0x13a2a1b6, 0xf206bfd6, 0xac795413,
  75228. 0xe84bd385, 0x75536607, 0xc5d18a2a, 0xc8a0e24c, 0x2e166de7,
  75229. 0x3c474dbd, 0x56d5750c, 0x1366843a, 0xdef444c1, 0xcf4b8432,
  75230. 0x14646e53, 0xa9fd9783, 0x4bc0d030, 0x297ee203, 0xbda4c824,
  75231. 0xfd7be6c7, 0x3d0b10bf, 0x08c7f3ff, 0x2d216476, 0xb4fd4c45,
  75232. 0x06e52599, 0x49e9e104, 0xfbab9fa1, 0x8661d32d, 0x9342a7fa,
  75233. 0xfaf66aa8, 0x3f3e3458 },
  75234. { 0x951597aa, 0x51ec35af, 0x49df64eb, 0xb677d4ac, 0x9bf4eff5,
  75235. 0x0276cd9c, 0x515a2935, 0x423eca49, 0xfd9bb9c3, 0x8a696553,
  75236. 0xede1f09c, 0xf99ee9df, 0x199e5f98, 0xb8fa2956, 0x35292c32,
  75237. 0xb7638758, 0xfc40e81b, 0x8734eddc, 0x65457d95, 0xd82d5e9f,
  75238. 0x30c78d2b, 0xc8ee323e, 0xc1433d67, 0xe77b2e4c, 0x3c8314ae,
  75239. 0x56d9f807, 0x2a0e2f63, 0x441eede2, 0x6c48295e, 0x1e9e17ed,
  75240. 0x34c294ef, 0x640d20c4 },
  75241. { 0x3284d513, 0x4e9a0b8e, 0xf315053a, 0x074c3545, 0x45acd52a,
  75242. 0xb36e7407, 0x1de50db7, 0xd80bdcfc, 0x2549fc46, 0x8d9d47dc,
  75243. 0x303f07a8, 0x29b6ef13, 0x6d4ad4c2, 0x4e461aca, 0xfc9f1b73,
  75244. 0xca8e351d, 0x57460e65, 0x8bc4094d, 0x0f32d367, 0xb6302b33,
  75245. 0x285742e8, 0x69a074b6, 0x876c29c3, 0xdfe52b11, 0x912bd17a,
  75246. 0xf39e4609, 0x349aa639, 0x8ee40d66, 0xc72e05c1, 0xb968902a,
  75247. 0xc0d92816, 0x0f9c1ca8 },
  75248. { 0x67433df3, 0x1ebbaab3, 0x15d3628c, 0xb6aa5347, 0x97f0c5cc,
  75249. 0x13a320d8, 0x65e408f9, 0x72c918cb, 0xd5373451, 0x4b638854,
  75250. 0x0b4dca09, 0x731399a3, 0x0a3b1326, 0xcf256730, 0x6608b388,
  75251. 0x5ea60dfa, 0x7b290dfd, 0x58ad74b0, 0xd7694f9b, 0x83202789,
  75252. 0xb6630fb1, 0x48593db8, 0xc65e3eaf, 0x3db47f70, 0x3e7263f8,
  75253. 0x63949c91, 0xe6e6ff33, 0x9b9acec6, 0x098a8240, 0x34bd9ba7,
  75254. 0x45d36ec5, 0x7e31c12f },
  75255. { 0x0dfd2dd7, 0xbe281d68, 0x24ab61d8, 0x1efacb00, 0x94431f97,
  75256. 0xb9c3005f, 0x959cb3bc, 0x660c8dfa, 0xcffbb406, 0xfdd5fc30,
  75257. 0x7969a10d, 0x7a4631be, 0xde13fd1b, 0x336e309e, 0xfc947076,
  75258. 0x76b3bfad, 0xdcc72223, 0xfa91925d, 0x156c4ee1, 0x741f0d73,
  75259. 0x0e2b3747, 0x4f64ee41, 0xefc4d93c, 0x86be92d3, 0xfc4fbb2e,
  75260. 0xc53b7e03, 0x337ca1bb, 0xac196cf5, 0x7e23ba60, 0x4de41a30,
  75261. 0x326d5357, 0x1a219c45 },
  75262. { 0xaa4db0bc, 0xfdcf7ef8, 0x7b6c9963, 0x2e231806, 0x3d8a192f,
  75263. 0xc2639067, 0xffdc7771, 0xc0cec2e2, 0xa2fc0edb, 0x997c8e35,
  75264. 0x82cc6043, 0x78e10ec1, 0x2b0c8120, 0xfd0de2cb, 0x69e57f8e,
  75265. 0x4d6c457f, 0x5b53f1c3, 0x953e69b2, 0xc4f89cb8, 0x422a330a,
  75266. 0x95566be6, 0x92ff2329, 0x437442d1, 0x73cd502d, 0xbea69403,
  75267. 0xf04ce590, 0xf8030662, 0x6ac1537e, 0xb6d0bf93, 0xe02bcf77,
  75268. 0xbc90192f, 0x17aaa999 },
  75269. { 0x8e55db2e, 0x0d3d5643, 0x3b946851, 0x835dee43, 0x5b88462f,
  75270. 0x1a1440e5, 0xea17e27c, 0xa6ff3b35, 0xdd95f7a9, 0x23f99c36,
  75271. 0xbdd672cf, 0x7217fdd9, 0xdd2045c0, 0xf400ac1e, 0x4ff06b25,
  75272. 0x94b55c87, 0x0e4a49be, 0x0a44a0e5, 0xb43b6813, 0xe8925e91,
  75273. 0x214f96c5, 0x78bedde1, 0x0f97fa97, 0x0f456a4c, 0xa5bfd267,
  75274. 0xa28fd86b, 0xbe7608ef, 0x3b4b2d8f, 0x226474bc, 0xfbd5ff8c,
  75275. 0xa5f3b24a, 0x6b282af0 },
  75276. { 0x6341a595, 0x78fc025f, 0xa445e28c, 0x591c38d6, 0xeb446842,
  75277. 0x72bd6e3d, 0x75547833, 0x3f9466d3, 0x083e16c4, 0x911414d3,
  75278. 0x95a7acb4, 0x145d9466, 0x8fd2fb64, 0x102ddf09, 0x0bfd87b1,
  75279. 0x2a2b2d2d, 0x59455088, 0x69e9be5c, 0xa80245de, 0xee378bf4,
  75280. 0xb2306b0e, 0x80b0bd68, 0xc2be9f3d, 0x76a545c6, 0x4802c245,
  75281. 0x429d167b, 0x2b412dfb, 0x13e64427, 0xee8d9762, 0xb664f529,
  75282. 0x54706ebf, 0x6d4f5d23 },
  75283. { 0x00ba9f88, 0x35c8f2b6, 0x7bb6d0bf, 0xfdc807e0, 0xb3b81e5b,
  75284. 0x0a126d42, 0xa7ac781e, 0x335ce6ce, 0xf37dcba6, 0x3e308e6f,
  75285. 0x63c96487, 0x028dca62, 0x8818434d, 0x72eba57e, 0x79b78a26,
  75286. 0xa9e3d59f, 0x2f07aea3, 0xd2f0a7dd, 0x24d05f74, 0xe0fe4678,
  75287. 0x0116deb6, 0xb2085170, 0x58f37580, 0x9c2a5e92, 0x74070bb3,
  75288. 0xe78bd7a5, 0xb9977d90, 0x551fc872, 0x40db81b4, 0x6eda93c4,
  75289. 0xd65d34ad, 0x4aaf0b4f },
  75290. { 0x3514c7af, 0x9bef2506, 0xbc181ead, 0xb09e7dad, 0x8fa3ec58,
  75291. 0xef3cae87, 0x173b8685, 0xd8dbfab5, 0x921d32dd, 0xb2490fc0,
  75292. 0x8bd9c466, 0x4eef386b, 0xa061dbdb, 0xc1cdd52f, 0x25bc04db,
  75293. 0x64de989a, 0x85728636, 0x06f9836b, 0x8be44aa0, 0x11a5a804,
  75294. 0x097018c7, 0x16dede4e, 0xb2c11fb1, 0x72aec577, 0xa721ecd9,
  75295. 0x144dade1, 0xd6ebf3a9, 0xf99c526b, 0x1c2e14d7, 0xa1d4165b,
  75296. 0x82bc6337, 0x8b2cbd39 },
  75297. { 0x8a52e991, 0x28ec1bf2, 0xcf9d42ec, 0x0ba202f6, 0xc634ea45,
  75298. 0x8307d130, 0xc5762b9c, 0x3fc257b3, 0x487c2a2d, 0xbd3298d1,
  75299. 0xa319488a, 0xca14f1a7, 0x06ba06d2, 0xc70ca93b, 0xee405e89,
  75300. 0x9aa3f4b3, 0x35deeae7, 0xcc64eeb3, 0x03bf1d4c, 0xd155f578,
  75301. 0x45616bfd, 0x041ec0b5, 0x086e33f6, 0x23df80e6, 0xf0243cf5,
  75302. 0x399a79c8, 0x874ccd58, 0x86c2824e, 0x8fc5c831, 0x220eeaec,
  75303. 0x7dbe3670, 0x57e28304 },
  75304. { 0xfbcdf666, 0x6e60b698, 0x8bebb1d2, 0xbdd06a99, 0x80498436,
  75305. 0x4044adba, 0x522bc88d, 0xd76bf75e, 0x28423b20, 0x655c4b9b,
  75306. 0x53398a72, 0x65c0f492, 0x0ca37601, 0x76d4f2b7, 0x2030fa5a,
  75307. 0x46989925, 0xb6054705, 0x96b37e87, 0x53de1b2f, 0xef96f731,
  75308. 0xad54ef05, 0x5ecbbc8c, 0xa93617b0, 0xeb289d0a, 0x7cba217d,
  75309. 0x3ac0fbd5, 0x19d4a2d7, 0xd0d3cb56, 0xc91d6063, 0xe8bee9d4,
  75310. 0x696ffda6, 0x4f12e037 },
  75311. { 0x15f1a610, 0x4ccfa422, 0x3786519a, 0x804a5c55, 0x73838134,
  75312. 0x1246a454, 0x4b284e2a, 0xfa15b484, 0x146d1320, 0x36464c65,
  75313. 0x70a8a0fa, 0xfb6ba88c, 0x93c4804e, 0x74e7cee7, 0xb95ae16a,
  75314. 0x8c34d22c, 0xf9c1d4dd, 0x9d9ed89f, 0x32025371, 0x61a0866d,
  75315. 0x9bd6444a, 0x45b232b2, 0xf277bab1, 0xf888e92c, 0xa9448b02,
  75316. 0x73e69c6e, 0x5b521ecb, 0x1a496ea9, 0x5858afb2, 0xa8f78ea7,
  75317. 0xb1266f91, 0x83d2333e },
  75318. { 0x67b478d7, 0x1c633288, 0x50a2fc9c, 0xa1ee1ae1, 0x18d2241b,
  75319. 0x05b6ab30, 0x893cd696, 0x69f1f288, 0xa8117a87, 0x159d6660,
  75320. 0x70e73d77, 0xe8120119, 0x93f55f0a, 0x528fef00, 0xd854dfb2,
  75321. 0xb3978db8, 0xf45d9fbb, 0xd6b43ef6, 0xd5bee397, 0x17de4bfe,
  75322. 0x6bf76dad, 0xa01e0f59, 0x3d40754c, 0x28b2280e, 0xf8e86ef3,
  75323. 0x8edb6122, 0xb7d1e586, 0x8226b6af, 0x2f40a55b, 0x46353215,
  75324. 0xc5a31621, 0x7362f13e },
  75325. { 0x73c0c430, 0x792eb27c, 0xa51c3657, 0x8cc0a65f, 0xd2194f1b,
  75326. 0x50a5cece, 0x814b4947, 0x18945688, 0x4b6fbbf4, 0xbbf0a81a,
  75327. 0xf0aa8608, 0x376f4f58, 0x3987795e, 0xd9361d68, 0xe3a8d0d5,
  75328. 0xb6510cd8, 0xb6c1a455, 0x63e2fdbf, 0xaec891f9, 0x2c91154e,
  75329. 0xff568f64, 0x0eb1e715, 0x2f2b399e, 0xe7af9cd7, 0x89f0bf0b,
  75330. 0x1fc39bac, 0x90983695, 0xf0861d92, 0xda0a20a8, 0xd9b16f02,
  75331. 0xa38c0ead, 0x2f10693f },
  75332. { 0x0c06ded2, 0x07a6ce91, 0x2fd9087b, 0xf974842f, 0xa9f635a6,
  75333. 0xe468bfd6, 0x1ed60626, 0x04b61891, 0x369ee548, 0x1fb2f89f,
  75334. 0xdc96a201, 0x9cbd1113, 0x10d633ac, 0x6759acfe, 0x8faa629e,
  75335. 0x64ba66fc, 0x47f38283, 0xa686ae49, 0xd59cda99, 0x828c3a05,
  75336. 0x08ea2f6e, 0x7c7afb14, 0xaf3953c8, 0x2551c8e4, 0x9daa9e4f,
  75337. 0x5b53d279, 0xad6f1940, 0x1eff68d4, 0x96437cdb, 0x2775dbdd,
  75338. 0x4fe7a043, 0x985f83e4 },
  75339. { 0xeaf45294, 0x89603c16, 0xc24b5751, 0x70131160, 0x39d6b52d,
  75340. 0x4c112018, 0xed943340, 0x7079cf02, 0x74f41b68, 0x0c5b028b,
  75341. 0x9c8ac1e1, 0x3dc3f076, 0xf8b24f0e, 0x5ac5eea3, 0xe34c5c22,
  75342. 0xee6684ba, 0x9abc452a, 0xa5259e63, 0xe9df45cc, 0xb07d2cd1,
  75343. 0x1a443cfa, 0x07019c93, 0x92c003b3, 0x68fddaa9, 0x0d8cbc2e,
  75344. 0x2d9f179c, 0x1e781ca7, 0xbbf15a6f, 0x50dcc799, 0x54d779d5,
  75345. 0x0fe962f1, 0x0c88e540 },
  75346. { 0xe8f44357, 0x84f71a6a, 0x3a3cab6a, 0xf75b4bf6, 0x5aebc680,
  75347. 0x334c9d9e, 0x8a753ef2, 0xcecaf084, 0x075e3c8e, 0xe28014c1,
  75348. 0xf74f8d3a, 0xbb9d5a38, 0xb80e32ae, 0x75988464, 0xf2bc3792,
  75349. 0x7b328e6f, 0xeed0e197, 0xebbb1faf, 0x5a33065a, 0x674eac95,
  75350. 0x922dbce8, 0x8c19fd8f, 0x987b907a, 0x8c17ae85, 0x3b3a2cd7,
  75351. 0x89f33627, 0xfa87772f, 0xebaea019, 0x3a25ced6, 0x4e5de499,
  75352. 0xaf110715, 0x8e2560b8 },
  75353. { 0x3141aba6, 0x56d3746c, 0xbab2cf9e, 0x45a1079f, 0x9cdd27c7,
  75354. 0xb6382831, 0x9dfd950e, 0x22237632, 0x3a9408ff, 0x1e0b15cd,
  75355. 0xb1160118, 0x49a80200, 0xa383bba7, 0x2719db5d, 0x651046d5,
  75356. 0x6078340a, 0x97523b1f, 0x8929d4de, 0x8e0a28ab, 0x4040345c,
  75357. 0x0adf09c7, 0x61275ac2, 0x2331d611, 0xb41ab265, 0x5391ca50,
  75358. 0x230cc77c, 0x8f922315, 0x88be0c92, 0x92fd9a29, 0xfef3d92b,
  75359. 0x8324f2e5, 0x59005f22 },
  75360. { 0x3c4c1c74, 0x6bb1750c, 0xe966fb79, 0xbe73aac0, 0x66c5973f,
  75361. 0x85a75d92, 0x3a8656b6, 0x8c97f932, 0x50446cde, 0x2b7043b1,
  75362. 0x3ff3897f, 0x548916f7, 0xb18b72b2, 0x913dd01c, 0x488c0de6,
  75363. 0xd0a751f1, 0x8558ca58, 0x19175714, 0x44a663da, 0x97714301,
  75364. 0xb0e08618, 0x2df190ac, 0xf39ead9c, 0x0080fc0c, 0x17382da1,
  75365. 0x0085ac6e, 0x3262a338, 0xe9791851, 0xb43bae8d, 0xe4495936,
  75366. 0xd783df6e, 0x57a78e26 },
  75367. { 0x40dbddd8, 0x161b346f, 0x9410c3ac, 0x2b49a927, 0x1886cf3b,
  75368. 0x8c542783, 0x33b93deb, 0x72df3232, 0x40df579d, 0x9c8d59f5,
  75369. 0xc20ef500, 0xe5d7a67d, 0x67f08643, 0xc46b3918, 0xad96adc3,
  75370. 0xecfa2445, 0x0c4544d0, 0x658f589b, 0xe08417d7, 0xe6ec9301,
  75371. 0xc454e288, 0x6ca5ef6a, 0xac0f462d, 0x4191048f, 0x08d8a036,
  75372. 0x852407d8, 0xf6d35b7e, 0xb4c533a7, 0x8f6ada87, 0x3251e412,
  75373. 0x81c472e8, 0x1ca370c5 },
  75374. { 0xa801b68a, 0x94bd5171, 0xfd1998b3, 0x7312879c, 0x41163202,
  75375. 0x4905aabf, 0xf5b01fdb, 0xb5fe87f4, 0x9cda128b, 0x78de523a,
  75376. 0xc7bd31f7, 0x0bf161a1, 0x23904c35, 0xb5decfd0, 0xe188f12d,
  75377. 0x224b2882, 0xf99dae74, 0x0dd2801d, 0x08cd1cd2, 0xcad467b5,
  75378. 0xc0867e39, 0x6c311c3d, 0x2b425072, 0x71a11720, 0x2efd9003,
  75379. 0x83bf464e, 0x1dbd3b03, 0x53d0448a, 0xe6265baa, 0x32db52f4,
  75380. 0x4c33ac79, 0x2584b34c },
  75381. { 0x2aeec688, 0x3cb86389, 0x45fbe523, 0xa5e740ba, 0xfd60b5f8,
  75382. 0x422e71f7, 0x4874913d, 0x455d185c, 0xfa17d80d, 0x04c2bb36,
  75383. 0xac054524, 0x3f271854, 0xa8b9a657, 0x76dd3045, 0x62ee7cc8,
  75384. 0x2e42c3e1, 0x4df6c7d0, 0x00266706, 0xdc7cb488, 0x5927dd51,
  75385. 0x187897e0, 0x6b3faabe, 0xf2d5737c, 0xfe6ad22e, 0xff51a9ff,
  75386. 0xafb60269, 0x69807baa, 0xe1c83545, 0x951ca49a, 0xacddb6ff,
  75387. 0x3f9ab085, 0x7e811374 },
  75388. { 0x830a88b1, 0xad722a8b, 0xce1117e1, 0x91918ea8, 0x0409b47d,
  75389. 0x3e02d0b8, 0x6c46d1d3, 0xb53812d3, 0xe589669c, 0x2fd09db0,
  75390. 0x15b0cd5e, 0x9845cd06, 0x2386c453, 0x0c1c155a, 0xf5ff43cb,
  75391. 0xda774de5, 0xe391c0cd, 0xbb076b98, 0x5004f286, 0x97d71eff,
  75392. 0xaeec0bfe, 0x23e0b46c, 0x32a1ad94, 0xe4538667, 0x396da422,
  75393. 0xfe0c9f81, 0x63db2bfe, 0x6376c1a2, 0xba56fa91, 0x001c7918,
  75394. 0xdf8485a6, 0x436b8c64 },
  75395. { 0x8ab764bc, 0x88117e9d, 0xa077df84, 0xdfa61e94, 0x0c18eebd,
  75396. 0x5a7765d3, 0xfc9451dc, 0x548916af, 0x071a347a, 0x01a52e33,
  75397. 0xb23b41df, 0x633b95de, 0x43c8c286, 0xdd7d68c9, 0x18d97068,
  75398. 0xe4f9d41e, 0x8c92799d, 0x79908b90, 0xd47394a3, 0xe614148e,
  75399. 0xcd51e53f, 0xe5018517, 0x0243dcb6, 0x5060075e, 0x17954405,
  75400. 0xe5dcde62, 0x537da5ff, 0x6f7c90e1, 0x0768cb66, 0x1df7aae4,
  75401. 0x6dbe95e1, 0x5266ca9e },
  75402. { 0x1386b3db, 0x84ddee6d, 0x7c38e540, 0xf9e4af5a, 0xeb04f49d,
  75403. 0xb3418440, 0xfde5a4fd, 0x2138a1e8, 0x30257cfc, 0x3e6e6924,
  75404. 0x19fd70c1, 0x3519c6e3, 0x86c31ff0, 0x8f34e174, 0x940ce1e8,
  75405. 0xf1e298fd, 0x14960d7c, 0x6fb8cb1d, 0x2b2f3bff, 0x207c1347,
  75406. 0x146ef8ff, 0x899a20b4, 0x7bd3e220, 0x7dec362b, 0x626bea27,
  75407. 0xa975044e, 0x4fb4cb67, 0x0f32b449, 0x1fc6703a, 0xc17a0920,
  75408. 0x9cd84a2b, 0x41f325b9 },
  75409. { 0xce2843a4, 0x312ed513, 0x00728afc, 0xe748498e, 0x4d864ce5,
  75410. 0xa8ef2822, 0xa620083b, 0x34064704, 0x4bed338d, 0x5905e1d9,
  75411. 0x063e7b38, 0x2a578cb5, 0x289e7bb9, 0x98276d96, 0xf17b7341,
  75412. 0xdfe2dc47, 0x1dac8944, 0x5923521f, 0x23400aa7, 0x3db6d28d,
  75413. 0xa761ba43, 0xc647705e, 0x9bfd07dd, 0x8947ba6d, 0x242ca8fd,
  75414. 0x00f2e3ac, 0xeb8c3468, 0x49ef4670, 0xd9aa18fd, 0x7db3d37b,
  75415. 0xe58cea9e, 0x56b30fb6 },
  75416. { 0xcd80a428, 0x07ecdcaa, 0x8732c891, 0x7af922dc, 0x3ada441f,
  75417. 0x20d88798, 0x924b008a, 0x3bed9a44, 0xb2e81c3a, 0x2123533c,
  75418. 0x65f807d3, 0xc34e4075, 0x1f2faecb, 0x0bfaefa5, 0xade8a88d,
  75419. 0x78b634a5, 0x94392a91, 0xc4e0b7f8, 0x90bb1cd8, 0x30922377,
  75420. 0xf87204ae, 0xdea9b4fa, 0x85d3cd83, 0x3edf81f5, 0xc6523a79,
  75421. 0x58f88c51, 0x17c0d969, 0xe472fb8b, 0xdccf7f07, 0x899081e5,
  75422. 0x58bdd146, 0x1353cc57 },
  75423. { 0x39bf6e18, 0x28a56497, 0x649b89c7, 0x59e8b5a2, 0xdce8b8e7,
  75424. 0x8d9434a0, 0x2047040c, 0xd935bf51, 0x6a7b8e82, 0x2ab3a164,
  75425. 0x27f81294, 0xf1583ed6, 0x72d67297, 0x8416a7e0, 0xcd39e42b,
  75426. 0x49685d86, 0x958ddbad, 0x8a797fc7, 0x155ce6de, 0xa558f928,
  75427. 0xf8a36235, 0x75f4e570, 0x52877ae5, 0xbc69cfc0, 0xa6b16ebd,
  75428. 0x8f4193a9, 0xbb1cc1f1, 0x8d1df43c, 0x5a21e789, 0x723a830e,
  75429. 0xf451df58, 0x3ec2185d },
  75430. { 0x1f0bc2d7, 0xb9d4c7d7, 0x6e51d412, 0x6982c6cc, 0xa09f80f6,
  75431. 0x92e02d93, 0x047ae09c, 0xb7dd2d25, 0x37f351f9, 0x3503149f,
  75432. 0xc77850be, 0x69d49ce1, 0x12f0d2c8, 0x60242acb, 0x7bc28b9d,
  75433. 0xba188c56, 0x06bc0550, 0x8e406121, 0x8d7d4329, 0xb0d84b1f,
  75434. 0xd38951e0, 0xb4a67ae7, 0x8bc97607, 0xb527c57b, 0x5497aa72,
  75435. 0xbc93c5f3, 0x39bdd666, 0x5f1de8cc, 0xe9d447a3, 0x3087dc5c,
  75436. 0xa211abe5, 0x89b356b6 },
  75437. { 0xdfdcc837, 0xed6db0af, 0xa871b7a9, 0x0fb80baa, 0x1c1d4b72,
  75438. 0x413abfc9, 0xadac9e5c, 0xf5b56bf7, 0x8b8657a3, 0x5664a2da,
  75439. 0x0e41d94e, 0x11b04f72, 0x37433658, 0x63e11d26, 0xf426daea,
  75440. 0xee628ece, 0xcb162dc2, 0x011619c9, 0x87648643, 0x9cf5817f,
  75441. 0x5584bc86, 0xe1bb9702, 0x00bf7928, 0x2cc27cef, 0xdc60eee5,
  75442. 0x4ef3a80e, 0x87adc2f9, 0x7e1202be, 0x8a0d4f52, 0x656f18e0,
  75443. 0x57c5d126, 0x39c4f10d },
  75444. { 0xe88aecd3, 0xb3a9b68c, 0xa518aa9d, 0x555b0918, 0x4bd4ee54,
  75445. 0xedc1cdad, 0x02068d84, 0x79b68b67, 0x811ac72d, 0x7dac80d0,
  75446. 0xa81a0a78, 0x6d1e6d35, 0x3bd16283, 0xc841e9ea, 0x894c4444,
  75447. 0xa7bc1775, 0xf1aa1202, 0xf2b63725, 0xc7d4c556, 0xbec7767e,
  75448. 0xd46ff51b, 0x2817ebb3, 0x73f7e339, 0xfde5be8d, 0x5aed24c4,
  75449. 0x44c6c977, 0xb6e579cf, 0x0b9a1707, 0x9069fbcc, 0xcff16478,
  75450. 0x49152b00, 0x414b542d },
  75451. { 0x606e173b, 0x33c31e58, 0x90e6713a, 0x5b7f4e1b, 0xdebb20af,
  75452. 0x425fb512, 0x05120e70, 0xc788c617, 0x9013e4ec, 0x3ef05602,
  75453. 0x81c6e6d7, 0x9f9d35ac, 0x9450690a, 0xe131e88f, 0x44af082e,
  75454. 0x708f9b32, 0x1ba2aea9, 0xb2e4d66c, 0x740db29c, 0xaf1f4a6e,
  75455. 0xd1843007, 0x74ab9248, 0xed556a6c, 0x13338ef8, 0x270d17a6,
  75456. 0xf48e623e, 0x9608f5bf, 0x3c7362fa, 0x444e8515, 0x43977874,
  75457. 0xe00b8b2a, 0x52678d6a },
  75458. { 0xdf36aeb4, 0x5dff1c59, 0xa92bc0ab, 0x52d6653c, 0x927a5f81,
  75459. 0x0e03f496, 0x2dfd491f, 0x8509d414, 0xa571f89b, 0x258c2c52,
  75460. 0x93334485, 0x2bd61804, 0x3f7d9e09, 0x1a33e94f, 0x2c1bf906,
  75461. 0xfab418d3, 0x5aa5695c, 0xf39c490e, 0xf6d2d7ff, 0x0e41196e,
  75462. 0x0f7948a9, 0x3ecd4075, 0xd3053b4f, 0x4b58f9b2, 0x5d9974c9,
  75463. 0xb8ee842a, 0xbf22f682, 0x23a59c1d, 0xc8efcea6, 0x045ac614,
  75464. 0xc10ceedd, 0x7040ba5b },
  75465. { 0x515a1a96, 0x2c364f81, 0x184327e0, 0x31a63503, 0x1ad93d4f,
  75466. 0x0a096650, 0x273b6173, 0x9d7694f1, 0xd2cda9d2, 0x8886d876,
  75467. 0x2814c177, 0x1e01a742, 0x8667696b, 0x3492276b, 0x5b25f006,
  75468. 0x2fd4f0c6, 0xfb294c4a, 0x6527349f, 0xde1d336f, 0xc1fe0d8a,
  75469. 0xe7e3860e, 0xaf9a23e8, 0xb774c31e, 0x97d2b721, 0x4365784a,
  75470. 0xfac3e582, 0x70f4eaa3, 0xff2dff4e, 0xfe873248, 0x3d281e1a,
  75471. 0x0bd1c9c1, 0x9043a6d6 },
  75472. { 0x766c7937, 0x1511a0fe, 0xabbc3be3, 0x1b2ded5c, 0xe00888ac,
  75473. 0x2ac160cc, 0x616200f3, 0x928754bd, 0x34a2ea06, 0xb801c83d,
  75474. 0x9cbe106f, 0x8ad7a03a, 0xcedfcd94, 0x996b0822, 0xe4069880,
  75475. 0xc3c3463a, 0xf597f663, 0xfb12ea4d, 0x40c92af9, 0x2c8d3834,
  75476. 0x4e8da154, 0x79bc85c6, 0xdb4e801a, 0x95771fa2, 0x1e3579b2,
  75477. 0x7bd2c138, 0xffaad078, 0xe45c75df, 0xb73eac46, 0xb0760a3c,
  75478. 0x3a125f35, 0x26362b48 },
  75479. { 0xeefc3e89, 0x25c68d28, 0x69e9ee71, 0x2d0ee877, 0xaf5e4b75,
  75480. 0x8b07bb86, 0xcb86b333, 0xdb709072, 0xff552bac, 0xfd3d20ea,
  75481. 0x4c0da1e9, 0xa5eeb2b1, 0x44f97145, 0x391f688a, 0x1e06d485,
  75482. 0x21fbd310, 0xbea9cd49, 0x45e4f2a5, 0xa7bf21da, 0x7b60d464,
  75483. 0x054d5471, 0x193f88c8, 0xbee0f2e9, 0x5ace53d1, 0xc1439273,
  75484. 0x92c26563, 0x96c6b5ee, 0x9c86e0b2, 0x09ff59ba, 0x452fe231,
  75485. 0x555c935e, 0x2e952b20 },
  75486. { 0xd75f886e, 0x2a846bca, 0xd43dfc58, 0xe68a5dbe, 0x007b1b86,
  75487. 0x103e45b6, 0x355ff2b5, 0x580e2ec9, 0xa263ecc9, 0xbc702f26,
  75488. 0x181e5e33, 0x2835b386, 0x6c122076, 0x025113ec, 0x7fbd856d,
  75489. 0xa5c26e3a, 0x9d6ebcb1, 0x8ef83fb3, 0xa44d2fa8, 0x7aaa53f2,
  75490. 0x53b1fa97, 0x7c14ef33, 0x17559a30, 0xff604a11, 0xb09377e0,
  75491. 0x2bcd96b0, 0xdb2f0273, 0xa5c14896, 0xeb53ef06, 0x1c0a84c9,
  75492. 0x30378e4b, 0x1236d017 },
  75493. { 0xc084373b, 0xd7481c8f, 0x646097ae, 0x29ae4768, 0x613bc34b,
  75494. 0x1300dfa0, 0x934bc2b0, 0x3712714c, 0x0e2be7e2, 0x86524629,
  75495. 0xed010800, 0x554fbb9f, 0x42314576, 0xf0ec0b38, 0x330a3282,
  75496. 0x65baf594, 0x706ef817, 0x3bdde1a8, 0xba7530e9, 0x7d2c727d,
  75497. 0x74cc95cb, 0xbb0c5d66, 0x2438906d, 0xb3fcd365, 0xd14658f3,
  75498. 0x19881941, 0x6c97f0e9, 0xe616f555, 0x4b9ec7ea, 0x353c2d85,
  75499. 0x620cb56e, 0x02a48014 },
  75500. { 0x506ccd38, 0x11d6d23d, 0x9059baa6, 0x229a1c54, 0x69d011c5,
  75501. 0x717c9c27, 0xd828937d, 0xe87e1b46, 0x83835083, 0xf5d63bbb,
  75502. 0xaadac258, 0xf0a7b427, 0x9f154d1f, 0x99ab26bd, 0x8ec955fd,
  75503. 0xdec0ffbf, 0x49fcb880, 0xee957c67, 0x1e0114de, 0x32395dee,
  75504. 0x369f46c7, 0x192a64b7, 0x91eb2599, 0x43044660, 0xa2e8c3da,
  75505. 0xbe2da887, 0xc3556d18, 0xa44e2c25, 0xb55f75f3, 0x31390414,
  75506. 0x8f217fe0, 0x1d8bde6f },
  75507. { 0xa2028924, 0x03cd39f8, 0xb06ecb9f, 0x6e54f19c, 0xd6f05846,
  75508. 0x862bbcb7, 0x5a060776, 0xdbe06716, 0xb10fec10, 0x9397c97a,
  75509. 0x6f1bb65c, 0xf4213826, 0xa672ba38, 0x414deccb, 0xf88b05e6,
  75510. 0x594d4d43, 0xac94d4d1, 0x7993f57a, 0xbfb17638, 0x74fc2a6a,
  75511. 0xb6fc655a, 0xd8196b5b, 0xee8d2139, 0xdc375c84, 0x360d3a26,
  75512. 0xb9b00a02, 0xdeb93b87, 0xb36ed35c, 0xcc83209e, 0xf565b28b,
  75513. 0xc61013c1, 0x349c6943 },
  75514. { 0x4de6c88a, 0xd1b39444, 0x4700207e, 0xd5c2c471, 0x21c2b780,
  75515. 0xb6f458a2, 0x0850993e, 0x749f7564, 0xbaef0c18, 0x400ba579,
  75516. 0x737c70f0, 0x2d742938, 0x21467ebf, 0xc5a8e2ec, 0x5337f453,
  75517. 0x243a666e, 0xed0bd50a, 0xc991f1c7, 0xf4bd1f91, 0x3a7f3e90,
  75518. 0x5f0e129b, 0x96089e8a, 0x07389635, 0xd0d3a177, 0x27182ac9,
  75519. 0x9cf842d5, 0x0817c5c2, 0x21195299, 0x87255769, 0xa32f327e,
  75520. 0x89c2d8fa, 0x056587ab },
  75521. { 0x1ce4733d, 0x008562ed, 0x98e51444, 0x5faff7cb, 0xa9ab46b9,
  75522. 0x5f03021f, 0xb61a8c13, 0x89494c5e, 0x36b35976, 0x57c95036,
  75523. 0x2ac2d2f6, 0x6be84c8f, 0x9bd2703e, 0x0e5b34d8, 0x7e872abb,
  75524. 0xc4ad918f, 0xc4052ee1, 0xc2a89e9f, 0x3190b51e, 0xc2caee3f,
  75525. 0x6fff254f, 0x58fd1437, 0x883e0972, 0x6f3c0d68, 0x0fb15438,
  75526. 0x63d0a0e9, 0xf6caae00, 0xc438764b, 0x3f1d0f6c, 0x815f1565,
  75527. 0xb86cdbde, 0x1b87f2ed },
  75528. { 0x2b0b15b1, 0x35792bbb, 0xce6ba779, 0xa3e4b5a7, 0xdd8f3779,
  75529. 0xfbacffd9, 0xc298d1ef, 0x005450bd, 0xc47031c6, 0x0e3f5556,
  75530. 0x95d68066, 0x0770f07a, 0x2d1052c2, 0xce3e84e0, 0x7aa8cc54,
  75531. 0xb050791e, 0xba3223a3, 0x4d621e73, 0x39632990, 0x87b9b94d,
  75532. 0x7eb8056d, 0x8df9cb47, 0xedfca0cc, 0xe2430de8, 0x9712a0ca,
  75533. 0x374bf416, 0x88848a99, 0xbe3f3c77, 0xc4a3e59e, 0xb22b87b1,
  75534. 0x3e95bc23, 0x8e0227c4 },
  75535. { 0x3210964d, 0x000e22a8, 0xff056eeb, 0xdccd5df5, 0xdaf1ead7,
  75536. 0x02173a1f, 0x67cdcae3, 0xd02833e0, 0x8bdcc90c, 0x1cc574cb,
  75537. 0x3224b4f5, 0x86eca714, 0xbb3f8298, 0xd00e603a, 0x0c1a8deb,
  75538. 0xb98ece1b, 0x378c261d, 0x228a46e4, 0xa6165e5d, 0xc6f9dd0d,
  75539. 0x4b7ef0e2, 0xb3ae3899, 0xbda9f306, 0x3a3c16b3, 0x38a084db,
  75540. 0x5e9a26d3, 0x5394e950, 0x528e5993, 0x4ea206bc, 0x848ecb11,
  75541. 0x40545d6e, 0x14b15ab5 },
  75542. { 0x664c59a2, 0x0f6d86c9, 0x60fd7aa5, 0x3dfe2be1, 0x9072cb8e,
  75543. 0x33f9b569, 0x8176a7e0, 0x5f2325d9, 0x4587080b, 0x79a0d4e7,
  75544. 0x0d5d4e05, 0xa4ee0def, 0xc87b28e1, 0xc0ad9ffa, 0x3f09b4ee,
  75545. 0xd6f18d2f, 0x292e9d87, 0xcc896ae7, 0x6094763c, 0xca88953d,
  75546. 0x18fbf9fa, 0xdbee97a8, 0x4b63d701, 0xdf20e0e9, 0x47ea722f,
  75547. 0xcbba6e30, 0x612b571f, 0xce57e1ca, 0x009a55f5, 0x1e16ac76,
  75548. 0xc4389e2e, 0x742bbed8 },
  75549. { 0xc1dc2c73, 0x23ea86dc, 0xc1643abf, 0x4bbbfd5b, 0x24d8ca1f,
  75550. 0x07f8fa1f, 0x8cb5cac7, 0xde68a6e0, 0x54e66a7d, 0x7d54c64b,
  75551. 0xa9b7ad78, 0x789dba22, 0xe364ab94, 0x4d88d540, 0x1f72e011,
  75552. 0xc8c2e02d, 0x46e2a278, 0x4c826057, 0x4b187c7d, 0xe6c35bb3,
  75553. 0xeb8fe0c9, 0xed8b3dfe, 0x7d11e415, 0xb6bc34e8, 0xb865c7f9,
  75554. 0xb3908bbf, 0xe1ecc17c, 0x717d1ce6, 0xf7cdd69b, 0x151e3308,
  75555. 0xb5c94124, 0x97bd5a14 },
  75556. { 0x81e82861, 0xe01c62fe, 0xdd42c40e, 0x703d4b6d, 0xe65e91e5,
  75557. 0x7e52e55b, 0x5abbbfdd, 0xb8b49374, 0xc72a45f4, 0xb4f15f52,
  75558. 0x550f29d8, 0xce8435a8, 0x582de75f, 0x9df76b9b, 0xa20c8b96,
  75559. 0x52e84c5f, 0x0a8a0af4, 0xaf77d2d1, 0xca6013c3, 0x0389bbd8,
  75560. 0x26f8305f, 0xb0d9b9ba, 0x0cec8b9a, 0xf053e848, 0xffabda18,
  75561. 0x4d63367a, 0xa6424c2a, 0x50f53be4, 0x864fba2e, 0xf892c58c,
  75562. 0x48cc5469, 0x317c6d31 },
  75563. { 0x2cb7d42b, 0x0c3525b0, 0x310facae, 0x55240bc9, 0xff20408f,
  75564. 0x8d5d2022, 0xe0c10ea0, 0x6b01402f, 0x718eb23d, 0x7fbef68a,
  75565. 0x41252a19, 0xa0146b5a, 0x110e0d6e, 0x59afce48, 0x022de181,
  75566. 0xe9a1d27f, 0xdc3f49da, 0x6db96d16, 0xefbe4008, 0xfc1ae3f5,
  75567. 0xeccbc11c, 0xf9d70641, 0x525f8636, 0x49022279, 0xc2763c30,
  75568. 0x3769796a, 0x1d90630b, 0x9cc3483c, 0xee3d3f17, 0x451651f0,
  75569. 0x9da0b8fd, 0x6ae59739 },
  75570. { 0xbff4d2ee, 0x57b13bc7, 0x30b173d8, 0x20754229, 0x0794936c,
  75571. 0xb6254bd5, 0x5efd55be, 0x1d5f232a, 0x4e0c3389, 0xc06f4a85,
  75572. 0x8e61f944, 0xcf2c5b59, 0xfd5f87b7, 0xc564861f, 0x5a2afa4c,
  75573. 0xee261fb1, 0x2d97a774, 0xb0ff7226, 0xd6cf007a, 0x1a89ae22,
  75574. 0xd346f214, 0x28880534, 0x97b6497e, 0x8fe73bff, 0xfa2afffc,
  75575. 0x8a8595b2, 0xf151a726, 0x9ef9cf3e, 0xe744b82b, 0xa84ee5f1,
  75576. 0xbc63fe72, 0x6649048d },
  75577. { 0x1e8b760d, 0x91b7bb78, 0x25aadaa0, 0xd47b0bd8, 0xfab5226f,
  75578. 0x81493d9f, 0xbffc148e, 0x4a6dd226, 0xa29be3db, 0x5a032f8a,
  75579. 0x34b0ab0b, 0x318dbc70, 0x7d654868, 0xdcccbfb5, 0x9c581e46,
  75580. 0x8506ab37, 0x2830ece2, 0x09136a6e, 0xcf6c80c7, 0x48b79356,
  75581. 0xef6b1e86, 0xfa176377, 0x83f0f1c9, 0x2c9c1cc1, 0x16abeddd,
  75582. 0x96f0526d, 0xa93b0de4, 0x3e0e98e2, 0x0f13873a, 0x6f2d7ada,
  75583. 0xf3fa49ec, 0x4eb93b5c },
  75584. { 0xe11fae32, 0xbd89f7e5, 0xc4023f51, 0xd13d74f5, 0x491c3f6f,
  75585. 0x1b0014df, 0x555279b7, 0x1d849a57, 0x05ba0068, 0xbb9e8897,
  75586. 0xc13ca2ca, 0x82222419, 0xfd33676f, 0xafbbb685, 0x75878a2a,
  75587. 0x931c3f52, 0xef3d5173, 0x12aeefef, 0xbd8a6878, 0x189a5cc8,
  75588. 0xd99f0c16, 0x82cffdb3, 0xa19d48b6, 0xbf565406, 0xe9c6c4e0,
  75589. 0x5605e223, 0x86804172, 0x53e781de, 0xc7001cc8, 0xcdf5c90b,
  75590. 0x7c043f68, 0x2b582d93 },
  75591. { 0x81abc2ae, 0xa1165c82, 0xe2b69eca, 0xa73380f5, 0x07fff66f,
  75592. 0xc097b3d2, 0x54776506, 0x5d603826, 0xb57fa21c, 0xdcbac9f3,
  75593. 0xc98dbdd5, 0x78750db4, 0xd9eff32a, 0x85e21103, 0x2f11c41c,
  75594. 0xceed172c, 0x9e348c09, 0xa8e39264, 0x831eddfb, 0x71cb936b,
  75595. 0xf50864a3, 0x915c3d06, 0xe93acfcd, 0xfe8e33cd, 0xb3f2f7aa,
  75596. 0x4bee10d7, 0xeb7cee9a, 0xc1d8eb48, 0xfa574afd, 0x4fa49ce3,
  75597. 0x862db4c0, 0x78615109 },
  75598. { 0x7ae72c21, 0x3fe3f480, 0xfd0f0da5, 0x631aa144, 0xf8c3a454,
  75599. 0xc76ee1e8, 0x51b4f1ab, 0x379ae094, 0xd7cdbb24, 0x2a3a4397,
  75600. 0x82bd5fcd, 0x7a14cffe, 0xf427ef5a, 0xbbe4ed12, 0x284d3ccf,
  75601. 0x9b0a43ee, 0x8eec6e1e, 0x57b78b93, 0x67b8e87b, 0x18d404e4,
  75602. 0x34374c20, 0x0c8adc05, 0x5428deb5, 0x64373605, 0xc3afa2cf,
  75603. 0xb4d80ec0, 0x3aa956f9, 0x6d51f93c, 0x84161c68, 0x9f9a28ab,
  75604. 0x6bc9c025, 0x540b6bb7 },
  75605. { 0x321d315d, 0x04e1734c, 0xd86e05d0, 0x4ef56612, 0xbba8cd81,
  75606. 0xeafae145, 0xacdc789a, 0x1fb07a49, 0x5877570f, 0x6a21e9ad,
  75607. 0xb9bc53de, 0x2e4a837e, 0x1d6298eb, 0x436db293, 0xea362f45,
  75608. 0x43afbc78, 0xaabf6585, 0x2a973d97, 0x0c924d60, 0xdce7dabe,
  75609. 0x7cadf0e9, 0xf69d98f0, 0x75020538, 0xe0b505a1, 0x4461cd29,
  75610. 0x3db7d1a3, 0x5e20e818, 0xe1c28776, 0x52dd50f6, 0x2ca25867,
  75611. 0x92e0388c, 0x897cab14 },
  75612. { 0x0d8bab8a, 0x59ed3813, 0xa438200a, 0xc11d364c, 0x40581415,
  75613. 0x0687bf2c, 0x7ac89674, 0x86ad0d3a, 0xb97411a0, 0x44928105,
  75614. 0xf383371c, 0x74984b11, 0x0d1a831e, 0x70d2ed84, 0x6c912fe0,
  75615. 0xd883628b, 0x14fa88d2, 0x44f8f7fb, 0xcf0ac93e, 0x564f2a4d,
  75616. 0xa6c24fa6, 0x82f629aa, 0xbf6cd949, 0xab906ba3, 0x20a5182d,
  75617. 0x2c822e67, 0x30eb93a5, 0x2ff47dac, 0xfff673aa, 0xdc62c4a4,
  75618. 0x476b0ec5, 0x64b00763 },
  75619. { 0xb3c9a404, 0x1e3f533e, 0xb7ef9952, 0xb1db7f73, 0x6c253693,
  75620. 0xc7f13e29, 0x0738eed4, 0x7ce7f4c4, 0xce26cad0, 0xccfd3b33,
  75621. 0x01ec5cf1, 0xd8784935, 0xdc084e01, 0x3f8fc09d, 0xc39b5acf,
  75622. 0x217cab32, 0x9ef5551c, 0x42daf0bb, 0xe1217a95, 0xfbc76f56,
  75623. 0xc237002a, 0x80178b12, 0xb070a293, 0x0b52c39f, 0x576ca964,
  75624. 0xe3925153, 0x19d68e36, 0x25559424, 0x09e50e84, 0x291fb82c,
  75625. 0x6618ed8c, 0x7dd22ea6 },
  75626. { 0x49cbb3bf, 0x7ffe844b, 0x5562fb25, 0xde0cc704, 0x9f5a845a,
  75627. 0x1e6ee537, 0xe51277fc, 0x956d7f26, 0x30635718, 0x2c75d4b9,
  75628. 0x96957f34, 0x39a14892, 0x82e5742b, 0x8cf4eb32, 0x83247b72,
  75629. 0x6b0d3ddd, 0x201a4237, 0x67a9f633, 0x1414a485, 0x416403c1,
  75630. 0xb6f6a916, 0x60afd447, 0xdac6f790, 0x95f94930, 0xbd3b9d82,
  75631. 0x685ff94b, 0x51cadf0f, 0x5c8f98fc, 0xb13b7489, 0x9559c88a,
  75632. 0x5f18fcc8, 0x31377c66 },
  75633. { 0x7dcfb35f, 0x35c5de09, 0x01cc36f8, 0x2dccca9f, 0x7576cb63,
  75634. 0x7e93e85d, 0xf7b4b375, 0x0c2dd48a, 0xb09a19b5, 0x9d95cd4f,
  75635. 0x71bfe607, 0x752ed159, 0x2596dad2, 0x439880cf, 0x69e90a6f,
  75636. 0xe52efb53, 0x03d3e60a, 0x44097663, 0xa95070e0, 0xfcf364fa,
  75637. 0x05624dd2, 0xd8f993b6, 0x00d5e467, 0xb35a9824, 0x0c8f4524,
  75638. 0xe289d024, 0x648a0179, 0xef45423c, 0x587edabd, 0x3a5fd695,
  75639. 0xa11e5271, 0x3dacc50c },
  75640. { 0x6499ae4c, 0xcb3e4f94, 0x7053c527, 0xa46dcbe1, 0xbe782e8a,
  75641. 0x807f5ce9, 0xd8481e45, 0xb6c64d28, 0xaa286fd0, 0xf35e4518,
  75642. 0xdf1cdb49, 0xf7b7b9ba, 0xaec23eaf, 0xf3fb6210, 0xb9bfd2fb,
  75643. 0x0a9ba385, 0x8807f3a0, 0xe51a0d53, 0xb17b2842, 0x7ab24404,
  75644. 0xf9dd9f0a, 0x6fd57687, 0xf3e9df64, 0xcd1efdb4, 0x60df194d,
  75645. 0x5dd2df7a, 0xe069df05, 0xbed3f2c3, 0x23248a31, 0x469b7561,
  75646. 0x694744f7, 0x866949e1 },
  75647. { 0x3f4ab07a, 0x3a9a0da5, 0xf54a6fbf, 0x2cd6f333, 0xb23cf290,
  75648. 0x0c92e921, 0x848e3d58, 0xc9581c3e, 0xd3b218ab, 0x93af1fbd,
  75649. 0x066cb4d7, 0x38598ea1, 0x990c03a0, 0x5001394e, 0x7d0877b5,
  75650. 0x3b664b1e, 0xd74c7091, 0xd79db1bb, 0x4e2d5dd0, 0x852d4435,
  75651. 0x3329db82, 0x0d2b841b, 0x7b96d480, 0xfa844eb0, 0xc295dc46,
  75652. 0x37a50569, 0x94f7ec4e, 0xc2d38373, 0x5b083177, 0xdc3884ff,
  75653. 0x8b1fa598, 0x574352b8 },
  75654. { 0x0d5d7ce9, 0xed2193f7, 0x0b487eaf, 0x3c19fd26, 0x7be65fd0,
  75655. 0x7c44ab59, 0x78270d56, 0xdd9da860, 0xbaa70198, 0x8a84ec00,
  75656. 0x285985df, 0x2ec27e49, 0xde2028d8, 0x996ccaf0, 0x61c2201d,
  75657. 0x4e7648c7, 0x091c19eb, 0xa96335bc, 0xf0d6782b, 0x253a3a69,
  75658. 0xd2946493, 0x3f204340, 0x099f6873, 0x444521a1, 0x6996011a,
  75659. 0x5fcbcc09, 0xf853a94e, 0x3884d5d8, 0xd3b6a3a1, 0x2418c624,
  75660. 0x06ae3c4f, 0x3e431af2 },
  75661. { 0x83d381f1, 0xf967d939, 0xd0c033c3, 0x36501aae, 0x54410768,
  75662. 0xbf3af4d0, 0x5093a6d3, 0xa86d1598, 0xd92f2900, 0x43ae0741,
  75663. 0x36f0b755, 0xfeb2afa6, 0xaa456d6f, 0xd090a6a3, 0xaefdb646,
  75664. 0x336a4fda, 0x1a942f7d, 0xfd1bfe44, 0x851ee41e, 0x7fc2a3ed,
  75665. 0x11e935c5, 0x4f1c9686, 0x53bbb343, 0xcd577666, 0xad896c2a,
  75666. 0xf26931ba, 0x86bbfa41, 0x8a0fbbd1, 0xa203cef1, 0x1c3d7d82,
  75667. 0xe2664d35, 0x6dad3f15 },
  75668. { 0x12ec35a1, 0xd1940b7d, 0xe7dfb128, 0x6219c5b6, 0xf13321d5,
  75669. 0x2cc278c6, 0x33c58eb6, 0x5e76904a, 0xd9903c43, 0x15090f55,
  75670. 0xc3d96a19, 0x061bc926, 0x8c0acba7, 0x974a9f03, 0x7198b21b,
  75671. 0x7a414021, 0xf8958c6f, 0xb069599d, 0xbebd0129, 0x517f2f1d,
  75672. 0xdf3a8dc3, 0x1109a613, 0x672375c5, 0x08e58448, 0x9383d2d3,
  75673. 0x56590ba4, 0x0bff837c, 0xfc3ee7c6, 0x27d2d55f, 0xc87a5390,
  75674. 0x5f517a3f, 0x2438e9d4 },
  75675. { 0x8815af3c, 0xc4a45308, 0xf3c9bed5, 0xe55f1a32, 0x97b65ddf,
  75676. 0xaef1cdc9, 0x12e51eb5, 0x61c61d94, 0xe63f2490, 0xbd0dac54,
  75677. 0xd0b3e231, 0x6f14429c, 0xf1da6010, 0xf737c3c2, 0x6bbc4fb1,
  75678. 0x7150e04b, 0x1be281cb, 0x205b4c89, 0xd7701f5b, 0xf1b4633c,
  75679. 0x2a513490, 0x8b33ef46, 0x68f1f7f2, 0xddb47c73, 0xbd416b67,
  75680. 0xf4ada511, 0xff795bb3, 0x9d2a97cd, 0x96200e67, 0x00a8b7b2,
  75681. 0xafe30e01, 0x13f39011 },
  75682. { 0x7bd0c827, 0x3dd296ef, 0x4a29ff46, 0x506110f3, 0x1c9a515a,
  75683. 0xf8793068, 0x268bca77, 0xde8d8045, 0x998045df, 0xcbb83024,
  75684. 0x68c0e584, 0x3f90d710, 0x263b6062, 0x2a838ca8, 0x535c5d0b,
  75685. 0x293bb5e7, 0x56415110, 0xceea99d5, 0x1bbda005, 0xfe311ad0,
  75686. 0xa4d8d018, 0x2497e0bf, 0x1cf2b866, 0x33dd77a0, 0xd8c4ba8b,
  75687. 0xbc075b73, 0x722b7bc9, 0x298466d4, 0xcbda1b0b, 0x17a7ce24,
  75688. 0x680703b6, 0x458d4b6b },
  75689. { 0x4d54d8b2, 0x8a26a20e, 0x4d320a0d, 0x05a5696e, 0xf994f700,
  75690. 0x698b5858, 0x2f6549a8, 0x7a4adc3c, 0x3694d00d, 0x1812e819,
  75691. 0x730402bd, 0x46b9b000, 0xa1b36410, 0xe10a1449, 0x99230220,
  75692. 0xeae95ea5, 0x1b4820c3, 0x3efc2e9b, 0x85c9eb8a, 0xfe5b5cb5,
  75693. 0x97847064, 0x21ae0319, 0x8f27d49f, 0x68ef0b70, 0x2f72556b,
  75694. 0x3259ef18, 0x624db01a, 0x00ae0457, 0x5668f95c, 0x628e3b06,
  75695. 0xb6fbbf91, 0x5f13f5fa },
  75696. { 0x3a9b0dc6, 0x7c6ed9ae, 0x6f883ec8, 0xaea1bde9, 0xea8b3677,
  75697. 0xea66bf88, 0x9a66e3ab, 0xdefa6abc, 0x68217ffd, 0xc4d3317b,
  75698. 0x290df05c, 0xf741c8f2, 0x7d11674e, 0x1f0fdf17, 0xc35989ca,
  75699. 0xfdf0ece7, 0x6b9c482d, 0x0eed92df, 0x55bf1ca7, 0x73713e66,
  75700. 0x25cec99c, 0x90acb290, 0xe803e69c, 0x37c9e3a2, 0x17713a1a,
  75701. 0x7c0a3c53, 0x6f5a174d, 0x350dc565, 0x05f802f6, 0x11625a44,
  75702. 0xa37ba4a2, 0x2196495d },
  75703. { 0x13142680, 0x00cb2fd3, 0x65d14cf4, 0xab9e91d7, 0xdfe2669e,
  75704. 0xc6a0ceab, 0x0ae22bc5, 0xbeefce58, 0xcb6ec250, 0x3c2b7986,
  75705. 0xd738f1ff, 0x84adb1a2, 0x516ec8ec, 0x9709bc28, 0x8e8f7db5,
  75706. 0xf3693129, 0x95b197f9, 0xc48efc6b, 0x9aaaa404, 0x9ff10952,
  75707. 0x144154b0, 0x2c3c8cbd, 0x427f3435, 0x33ef7bc3, 0xd21897c1,
  75708. 0x04a17940, 0x6ce548a0, 0x5aa0c47d, 0x3d56fa62, 0x2971cea7,
  75709. 0x04475f08, 0x93ad0eb0 },
  75710. { 0x988a9963, 0x7a0b6967, 0x6515e8dd, 0x61e477f7, 0x3b6b50f2,
  75711. 0x6274e386, 0xd33922de, 0x63a9b8d5, 0x687a5b3d, 0x3c38d3fb,
  75712. 0x1302e323, 0x18f6f09c, 0xe02fcccf, 0x254c05c3, 0x26e662f7,
  75713. 0xc04ed0b7, 0x143fe079, 0x1d5646b8, 0xc9016c8c, 0xef8a9448,
  75714. 0xf823d797, 0xe5674c4b, 0xbccde451, 0x0586f72f, 0x4417eade,
  75715. 0xc5fc88d5, 0x576e588d, 0x2b952209, 0x5844d1f9, 0x4408dd42,
  75716. 0xea41c034, 0x73f8c3f0 },
  75717. { 0x5df763dd, 0x89534fc8, 0x3ac71836, 0x3b1427f3, 0x6e8f15a0,
  75718. 0x0db5be17, 0xcb20888e, 0x1d390944, 0x857caea6, 0x7804c9ad,
  75719. 0x519f7bf3, 0xaa584428, 0x293aa8cf, 0x626eecf1, 0xea36a015,
  75720. 0x749e0d98, 0x3321edcd, 0xefff6dae, 0x28b791cc, 0x963deea6,
  75721. 0x2d16e361, 0xa14e0552, 0xb15ae206, 0xa2e058fc, 0xfca325e4,
  75722. 0x0f268745, 0x21341a8a, 0x7cf9d407, 0x7caa51b8, 0xdfed25d9,
  75723. 0xadbedd75, 0x0108ae39 },
  75724. { 0xa9e88f63, 0x54d178f3, 0xab0c7325, 0xaa05b11e, 0xe261d8a6,
  75725. 0x773a53e6, 0x8d0b91c8, 0x24db7dae, 0xe9bb004d, 0xde10b073,
  75726. 0x54e3090b, 0xfc8befe7, 0x0cc69c89, 0x16af0599, 0x9d59511a,
  75727. 0xddc83803, 0x46c5dafc, 0xc3f65b99, 0x1ee0a599, 0xfbbe4be8,
  75728. 0xfb3a9b17, 0x88891e36, 0x445dad00, 0x0c9aad75, 0xd5097e1f,
  75729. 0xdffc46ab, 0xac85a4e1, 0x8848089b, 0xa0c45233, 0x348bb42f,
  75730. 0xeb13c1df, 0x807c06d8 },
  75731. { 0x98ee0ef6, 0x00a969ec, 0x8bb7b7af, 0xba9d5483, 0xa02f8fdb,
  75732. 0x24484c92, 0x8b70557c, 0x7bdb201a, 0x60ad1af2, 0xe59343e4,
  75733. 0x998c95fb, 0x53a9a942, 0xda861d3b, 0x974db3de, 0xed399c0e,
  75734. 0xce1525c9, 0xf72109bd, 0x89b56881, 0x998211a4, 0x08ff7d15,
  75735. 0xef0f275a, 0x5df76b3a, 0xfa2f358b, 0x93f180f7, 0xc39b0634,
  75736. 0xaac4ffcf, 0x17583b53, 0x2692c626, 0xb55399fc, 0xb2fdfa36,
  75737. 0x99607a61, 0x16424c6c },
  75738. { 0xdd2744a9, 0x5dd65c55, 0xfe3af418, 0x2544c1c2, 0xefe8b089,
  75739. 0x32c82e99, 0xa9df691a, 0x30b7ab25, 0x9be99674, 0x98384550,
  75740. 0xcaf2d122, 0xbcecd258, 0xbcc77272, 0x88ae4098, 0x4b8efa0c,
  75741. 0xd4396141, 0xed64d12c, 0x44ff67b9, 0x2e7f3404, 0xa9e655e4,
  75742. 0x45b0e9eb, 0x3d16fc45, 0xf03ded28, 0x474a3e14, 0xacccb85c,
  75743. 0xa3c9adff, 0x7253a51b, 0x3dfe6bc1, 0xfb5831b1, 0xdddaf4b9,
  75744. 0xa4f4478a, 0x5544e602 },
  75745. { 0xbaa80b4f, 0x897c5313, 0x63bdc8ef, 0x0122716f, 0x7b42c5a8,
  75746. 0xae2742db, 0x0883308c, 0xe9d9e1e9, 0x2d341ab1, 0x352c8c3f,
  75747. 0xed945870, 0x163d0500, 0xc290d9d8, 0x8349dd73, 0x1f6c7d29,
  75748. 0x2053c5e0, 0xcb42033c, 0x83107446, 0x09d09af1, 0x76c88bd2,
  75749. 0xb2794681, 0xd0f70e6e, 0x19b1b540, 0x720b59de, 0x22994b43,
  75750. 0x80b7ecdc, 0x2dec53cf, 0xc1a4cdce, 0x1ed60f42, 0xdd7d3edd,
  75751. 0xe241d261, 0x5735995c },
  75752. { 0xa0237056, 0xdc4ba3fb, 0x33ab3388, 0x6856c164, 0x271ec612,
  75753. 0xc01eebbd, 0xe3031bec, 0xabdeb033, 0x6118a1f5, 0x4eee4419,
  75754. 0x5b600f33, 0xec497421, 0x08868773, 0x1b7185cf, 0x7c1b7dfd,
  75755. 0x7b0c46cd, 0x4a4c5e89, 0xd143b2da, 0xbb1ff94d, 0xdb9a5984,
  75756. 0xc9cf3465, 0xac3904e4, 0xeace64c9, 0xf8729bc0, 0x768ad99a,
  75757. 0x5cc22821, 0x8a9540c2, 0xbbd3b081, 0x049a6917, 0xe468ed5f,
  75758. 0x3ec45ef0, 0x885486df },
  75759. { 0x4bdff464, 0x6a942c93, 0x25a7b451, 0x3db2719f, 0x325be324,
  75760. 0xccb0070b, 0x19fe3339, 0x2055a31b, 0x241ee8ff, 0xaca69ae8,
  75761. 0x55ef8def, 0x7607dd08, 0x1a1b73c6, 0x9e24960f, 0x71d36810,
  75762. 0xbcb0e8a2, 0x6885e6b9, 0x29e11aa2, 0x185eae19, 0x98b5d0ab,
  75763. 0x0f81f91c, 0x1a0b96e4, 0x994fc503, 0x4d0e8bcf, 0xf119d6e0,
  75764. 0x33d81697, 0xaaa4ce0c, 0x29083287, 0xc91ff9d7, 0xc5dd4d3e,
  75765. 0xd4ab962d, 0x31cecfe8 },
  75766. { 0xfc8b21e8, 0x437bfd9a, 0xb19436df, 0xe5dd32b3, 0x921c36a0,
  75767. 0xfe5902d4, 0xa3d0fa90, 0x8e9de84d, 0x5bb523bd, 0x9663e6ad,
  75768. 0xaecd6975, 0x9800a23f, 0xb4fbb59c, 0x1009c0d9, 0xc9d20ff1,
  75769. 0x839aa7bd, 0xecd6fa3d, 0xf502f66d, 0xc5516ca9, 0x480ed4fb,
  75770. 0x6c742ac4, 0x65ffa5f6, 0xff3252f8, 0x2b7c7945, 0x75d9cb3d,
  75771. 0x72fefc05, 0xd6d6f1d2, 0x11b0863b, 0x9a6a4ec3, 0x5d8f3cf0,
  75772. 0xda2547b3, 0x6961b46a },
  75773. { 0xcb35e2ac, 0xd07b587e, 0x57af14d9, 0x1ed5546b, 0xdb28a04c,
  75774. 0xeca17a5b, 0x709d54f0, 0xa1f91d44, 0x9c6f400e, 0xa6e719fd,
  75775. 0xfb8ce190, 0x4e4b88ed, 0x246e3fd2, 0xf9781edd, 0xb655af5d,
  75776. 0xd67120e6, 0x93413ca7, 0xda782d1d, 0x9707fa21, 0x697e20a2,
  75777. 0x54e84123, 0x1eb51f32, 0x36051f9f, 0x2e254d9e, 0x73ce5be9,
  75778. 0xddaec42b, 0xcd3f794f, 0x89a9a32e, 0x0781aad9, 0x1964e22f,
  75779. 0x53755212, 0x6a63a90c },
  75780. { 0x3d7acbbb, 0x76554e00, 0xb74f6108, 0x2c01668a, 0x388c519b,
  75781. 0xe4a29672, 0x3eb94d4f, 0x01667714, 0x0cd6d2f6, 0x086a3cdf,
  75782. 0x7b370f7f, 0xf8658021, 0x5a4d3e7c, 0x658880c1, 0x5ba3f4a1,
  75783. 0xd6ed5816, 0x5ca471dd, 0xabcc7813, 0xe844a576, 0x809bf074,
  75784. 0x6ea502ea, 0xa53a81b3, 0x0e021ed3, 0xc20b9307, 0x8617f165,
  75785. 0x8c27f892, 0x8235cd0b, 0xa5476446, 0x82552961, 0xffc89ffd,
  75786. 0xd151d90e, 0x51ed4a22 },
  75787. { 0x449701b4, 0x37d6963a, 0xbb27caf2, 0xea8d91a3, 0xb572965f,
  75788. 0x3ef9be15, 0xdb50bf7d, 0x75a7a055, 0xce643b9b, 0xfd67480e,
  75789. 0x6ceb5d5e, 0xf2a60d2d, 0x5ed7c897, 0x68fc320c, 0x28ce685f,
  75790. 0x41c53cf6, 0x7106615e, 0x0e29711f, 0x23500ecc, 0x7a872138,
  75791. 0x6c29fe48, 0xaf0a9260, 0xe1ef9712, 0x93df3f2a, 0xd2d169bf,
  75792. 0x0d5f6fb1, 0x74a9793c, 0xeb7afe26, 0xe9f49256, 0x4173d94a,
  75793. 0x2b8b5ce5, 0x2d6951bc },
  75794. { 0x904e222e, 0xdd007d9f, 0x86f4e109, 0x333f248f, 0x8f429eee,
  75795. 0xd4994e8b, 0xcfc77518, 0x29573415, 0x0b0f42f1, 0x6e7fea3a,
  75796. 0xc2743519, 0xc795cb7d, 0x711e71a0, 0x820a8f66, 0x2b874f55,
  75797. 0x83d95d9c, 0xe70e1627, 0xd4b64d78, 0x8b92a742, 0x924353f5,
  75798. 0x447b5e6d, 0x322048b1, 0xbcf931a0, 0x0bad730c, 0xa7af2268,
  75799. 0x75c4d089, 0xb83b93f9, 0x464904c1, 0x165b3aee, 0xa24eba02,
  75800. 0xe08cc5f0, 0x65c48e78 },
  75801. { 0xde222c22, 0x1a1c73ce, 0xfcea23b4, 0x5683d8cd, 0xb2143b06,
  75802. 0x0301cb14, 0x59fcec77, 0x284adf8f, 0x31204cef, 0xfb1c581c,
  75803. 0x94735107, 0xf54d3eee, 0x4d3188c0, 0xdbf67f0b, 0x10f18d12,
  75804. 0x76a3f2d1, 0x07d3e013, 0x3809fa28, 0x25e7ece0, 0xf06f0a46,
  75805. 0xb2895d2e, 0xd82867ed, 0x08b0553a, 0xe106f489, 0xef245445,
  75806. 0xe2280fa6, 0xa8d9a3cb, 0x402d5785, 0xd438ba2d, 0xf63dd9ff,
  75807. 0x7a6b226f, 0x36b5cd2c },
  75808. { 0x545679a7, 0x87ff4e20, 0x4520c750, 0x64d80b41, 0x9b459cd8,
  75809. 0x90a357fa, 0xc85af1a3, 0xa19eaf39, 0x8d935a5e, 0x0d475d79,
  75810. 0x781a678a, 0x74501983, 0x0cc2e810, 0x74839779, 0x2f412244,
  75811. 0xc6a21d11, 0x36a51a37, 0x8d0e85f9, 0xeaa74df8, 0xff50151e,
  75812. 0x93cf99c4, 0x14e182a7, 0x376a9ab6, 0x45593df1, 0x522389ff,
  75813. 0x18f73caf, 0xf7445e8a, 0xd27cc960, 0x39a51dc8, 0x0692f4c5,
  75814. 0xdb39bfd8, 0x08d7c144 },
  75815. { 0x3ecca773, 0x809c0d96, 0xd48c2156, 0x87ea9192, 0xdb6bd641,
  75816. 0xf0eccd74, 0x2a678cdf, 0x77312374, 0xd1587b7e, 0x7a966d8b,
  75817. 0x6130a4c6, 0xf3c1a101, 0x5fce17bd, 0x7cc6e838, 0xa8de7aa4,
  75818. 0x95e95bb8, 0x898308e3, 0x3fe1e8b5, 0xe347694a, 0x0197243e,
  75819. 0xbb0cd2bf, 0xf3fe9c42, 0x0f9b2b49, 0xb5905264, 0xc7367d1f,
  75820. 0x4c385e8b, 0xb5ee147b, 0x1d3050ae, 0x04004ad9, 0x8e2c3879,
  75821. 0xbab70202, 0x5f2aa8ee },
  75822. { 0x1266524b, 0xe208d464, 0xd0a19f66, 0xb7bf3880, 0xda106ebf,
  75823. 0xa5aa685e, 0xe642dd46, 0x0a69e8d3, 0xc682e4d6, 0xef349c61,
  75824. 0x0fcb534c, 0x26f6ee3b, 0x05eb67b8, 0x7daba127, 0x18be05f6,
  75825. 0x2babb27e, 0x8e2d85d1, 0x959afcba, 0xe2d9d386, 0xedcf2d1a,
  75826. 0x1ea6f06e, 0x59dc52e6, 0x866e5ae8, 0xc28278b4, 0x02bcd3c7,
  75827. 0xd9ff0340, 0x784be82f, 0xe884ac76, 0x83c9f224, 0xa3164980,
  75828. 0xb46ff949, 0x62501a98 },
  75829. { 0xad264086, 0x563f7d9a, 0xa5e0e4bd, 0xca6a33db, 0x8c8d3d67,
  75830. 0xe8253002, 0x46e64b19, 0xa288dac8, 0x20aa4536, 0xfa3c9197,
  75831. 0xed553eac, 0x8130c9b0, 0x2ea8abd3, 0x622806e0, 0xceccfe77,
  75832. 0x52fbf54d, 0x4f0d1b70, 0xbd9a8e31, 0xd59b1741, 0x519d2133,
  75833. 0x9a6fea8a, 0xfd74101c, 0xb5c4eb10, 0xd1acf7a0, 0x91f9da5e,
  75834. 0x78499b73, 0xc0dea586, 0xabaa4c49, 0xa1f3531a, 0xcc9c5f73,
  75835. 0xfd3fc665, 0x497b15fe },
  75836. { 0xf45568e9, 0x8a56cbaa, 0xc7192a6f, 0xf491a0fe, 0x9ab2539a,
  75837. 0xdbb03dd3, 0x4ac37da9, 0xc86522f8, 0x02a0f5b4, 0x8c8cdba2,
  75838. 0xa29c539f, 0x8109fc75, 0xca90f02e, 0x9cd06d31, 0x3e216dbf,
  75839. 0x8f31f044, 0xba3ebd91, 0x99aa68ac, 0x42c007f4, 0x2a80d0d2,
  75840. 0x86a9b7ce, 0xdd8dffbf, 0xd6308edc, 0x405d3e84, 0x068012ca,
  75841. 0xdafa33fe, 0xedea1071, 0xc2eebd13, 0x2ff637e6, 0xb7ae7e5c,
  75842. 0x9e514cb7, 0x18d46a6c },
  75843. { 0xa78b7802, 0x868cbb22, 0x497cbaf4, 0x0745ddb2, 0x42ae8add,
  75844. 0xc4eb2f3e, 0xb4ceb4e4, 0xac0abcda, 0xa325fd40, 0x2e0d8325,
  75845. 0x13ac7345, 0x6cfe0571, 0xb14171b9, 0x7407a788, 0x6da7a52b,
  75846. 0x70eb0603, 0xd85176ac, 0xab0b36f9, 0x7c2954f3, 0x14109d29,
  75847. 0xdcd705ad, 0x370de9c8, 0x7bb5e751, 0x3f0db5cd, 0xa06e708c,
  75848. 0x45f93d41, 0x7e93050d, 0x10d54f8a, 0x5a38fef9, 0x69e6f8e4,
  75849. 0xd3f62e40, 0x55044601 },
  75850. { 0x06cb9cc9, 0xd1c5c910, 0x41d00014, 0x542074d7, 0x11236fb8,
  75851. 0x7cd8663e, 0x29ad5f82, 0x39721ffe, 0x2951fc83, 0x1d21fbfa,
  75852. 0x400d144f, 0x1cde06e7, 0x91792e6b, 0x9042596b, 0x29ad5166,
  75853. 0x3365c8e5, 0x9aeefe98, 0xe2220e85, 0x70c2aee3, 0xbcb53189,
  75854. 0x9ff100bc, 0x477ca3db, 0xf532973f, 0x27074176, 0x9a2bd01b,
  75855. 0xa12118ac, 0x3dd79f93, 0xf3425209, 0xc6f5d7db, 0x563a8ff7,
  75856. 0xd7b0ec4f, 0x0da313fc },
  75857. { 0x15aa2557, 0x37125a8c, 0x00893e9c, 0xca21d70c, 0x67b8a823,
  75858. 0x48713994, 0x7cb0042a, 0x0d3e9a74, 0xc9e2ce18, 0x2d2bf4ff,
  75859. 0x049aeac2, 0xd5531a0d, 0xf03d0660, 0x4d29a616, 0x1f1b7f00,
  75860. 0x473d50d6, 0xca3de50c, 0x3af0ecbb, 0x09c28f27, 0xe2959bea,
  75861. 0xf8704664, 0x6d7c2ea0, 0x731083ef, 0xadfae4e1, 0x941c2554,
  75862. 0x50940c26, 0xa1162d03, 0x44167410, 0x1e82290e, 0x620230d8,
  75863. 0xdb414acc, 0x63630be8 },
  75864. { 0x8a7d2e41, 0xbf8d5222, 0xeb62f879, 0x49e75823, 0x6c402d89,
  75865. 0x1b4d33dd, 0xde2c59ad, 0x883e04d6, 0x49b9dc38, 0xbf3f38f4,
  75866. 0xb4b70c4c, 0x9d997d18, 0x13cea045, 0x1f69b20c, 0x58e2606d,
  75867. 0xca3d7025, 0x261d1b79, 0x3d4fd977, 0x5a1436fa, 0x56aeafa8,
  75868. 0xbb443c07, 0x369b3e98, 0xe558f6be, 0xfce5186c, 0xf8ac8f89,
  75869. 0xeb0cd478, 0xd5e5aa72, 0x68074f37, 0x68544eb0, 0x295845c0,
  75870. 0xf16688ed, 0x306a9871 },
  75871. { 0x634ec136, 0xbc451e9d, 0x0e6f658f, 0x1edf27ca, 0xc0db4120,
  75872. 0xa9be0152, 0xc5bfee67, 0x87b6ef20, 0x9a2d6023, 0x35283238,
  75873. 0xc7afb899, 0x60e564d8, 0x0ac9c2de, 0x4af22bc0, 0x82a9d22b,
  75874. 0x28e6f631, 0xf532701b, 0xc075c701, 0x82075f91, 0xf6d418f8,
  75875. 0x1beaa511, 0xf9fa628d, 0x6e72a13d, 0x551e7a17, 0x77f4c01c,
  75876. 0x9306215b, 0x93c9d588, 0x71aba731, 0x58e57cd4, 0x6443ebe0,
  75877. 0xe8103e37, 0x2833ac41 },
  75878. { 0x8da5ec5c, 0x7e564b86, 0x1c08db24, 0xac3d9da8, 0x8c57a728,
  75879. 0x9d7c1f0b, 0x9d343dc2, 0x3512afe7, 0xfdc60339, 0xb438e4cf,
  75880. 0xdcfa1941, 0x7d5a2700, 0x27320449, 0xd5f323f8, 0x1393c6e6,
  75881. 0x1b87a58e, 0x04baa431, 0xecb68bd1, 0x4722b4d7, 0xc09c1c5a,
  75882. 0x206b5faa, 0xf42faa97, 0x9976327e, 0xe1dcbcd6, 0x087787d9,
  75883. 0x655ba9e4, 0xde5c0191, 0xbd59c757, 0x0bcf3538, 0x673020ed,
  75884. 0xa49d6303, 0x120cd454 },
  75885. { 0xcab0f9ee, 0xebfdb8f4, 0x2cce58ee, 0xbc003ef0, 0x5a8d0665,
  75886. 0x9b6a6841, 0x9b957774, 0x642ed3a6, 0x4721ab5c, 0x3de487f0,
  75887. 0x21a4f0d3, 0xef2ff380, 0x29dbddcd, 0xbd16f558, 0x0e93dff2,
  75888. 0x2ef05b4b, 0x0bc9aec1, 0xde1faa12, 0xd467fa92, 0x66dae2c2,
  75889. 0x5eb33e34, 0x758daf64, 0x8f0103cb, 0xa67ad9f6, 0x9be02430,
  75890. 0x151f693a, 0xeb4054bc, 0xd5698496, 0x7019336e, 0x8ef1677e,
  75891. 0x7fdeea3e, 0x021cfd16 },
  75892. { 0xdf5c36f3, 0x5c73715f, 0xd64ad254, 0x703bde37, 0xf2cf7713,
  75893. 0x55368d10, 0x0f3993c8, 0x1e5ec7b7, 0x304ae4ca, 0xfdb16776,
  75894. 0x3d3bb18b, 0x0d8f717e, 0x66343d5a, 0x5267073f, 0x156008b5,
  75895. 0xfaeb52ef, 0x224a470f, 0xb97ad5f9, 0xed2ab51a, 0xaf86e391,
  75896. 0x9974302c, 0xdc0c7e57, 0xfd0ae28a, 0xc88fa817, 0xbf8ed59c,
  75897. 0x807c22df, 0xeb128bb6, 0x5dedc231, 0xa20595a3, 0x71edcd9c,
  75898. 0xc73cf78e, 0x07265b46 },
  75899. { 0xbd66232f, 0x73dd99f0, 0xc4027716, 0xc59aaf89, 0x5b860fc4,
  75900. 0xaf826dfa, 0x7a943f3b, 0x239ea8aa, 0x523c428d, 0x0e0e1b1a,
  75901. 0x6973b95a, 0x55ea0e3a, 0x2557753b, 0xea399caa, 0x06957b1f,
  75902. 0xf8adf72f, 0x3bd34302, 0x0389f341, 0xf8a43a97, 0x333f27d0,
  75903. 0xadaf796f, 0xcd9c0c08, 0x49c12aa2, 0x6dcca49b, 0x7a0ac6e9,
  75904. 0xdd88deee, 0x0644080e, 0x8f47575d, 0x0cc2f4bd, 0x6e9d667d,
  75905. 0x31d1496c, 0x36c5754b },
  75906. { 0xf323d84b, 0x9120046e, 0x7e789c4f, 0xa6991122, 0x921b8055,
  75907. 0x4b0eaf4e, 0x8079974e, 0x6339844a, 0x740f8c79, 0xc905466a,
  75908. 0xcd6def49, 0x1c18d0f7, 0x4b23e4ba, 0x5297da6b, 0xc41800c5,
  75909. 0x1c09dff3, 0x37ef6777, 0x6c49075b, 0x50513ded, 0xa94c3a40,
  75910. 0x6b0b1705, 0x3d6742e9, 0xc48af5ae, 0xc0784494, 0xc95822de,
  75911. 0x40c01532, 0xc164d94f, 0xa2ddade5, 0xa2975eb5, 0xfc8a8ac9,
  75912. 0x1946944e, 0x06fbf861 },
  75913. { 0x3f45aa97, 0x2d65338e, 0x1d040feb, 0xd83b58c8, 0x0fdef8b9,
  75914. 0x05fef59b, 0xe4d7417c, 0x7beb071a, 0xb30a1a23, 0x982b61f5,
  75915. 0xfb65bd03, 0x4c5f2a2a, 0x5cbf6bf3, 0xe40abc9d, 0xf06612a5,
  75916. 0x422c326d, 0x9571ae28, 0xc921e69d, 0x23d3434e, 0x7c88b10b,
  75917. 0x9da07933, 0x96d2e957, 0x3619cf4d, 0x833d46a1, 0xd95eefa1,
  75918. 0xd9d19653, 0xa03e8f0e, 0x2a7d8411, 0x04bb5ab1, 0x5e642953,
  75919. 0x1f0fa9ea, 0x5e9ca0fd },
  75920. { 0x197c5dc4, 0x5bd54571, 0xe78a95a2, 0xe2da40bf, 0xffdb0eb2,
  75921. 0x65fb9efc, 0x0d17467c, 0xe952dc2c, 0xc758c6a3, 0xc1fc9c7b,
  75922. 0xd4034a9a, 0xfc79562c, 0x61f64b56, 0x26e36fbe, 0x1e84728b,
  75923. 0x6adc4b9e, 0xa8f9ac8a, 0x7f165fd3, 0x03e3e013, 0x7bc93a45,
  75924. 0x656478e3, 0xeacc5513, 0x064ddc77, 0xd3391717, 0x76936914,
  75925. 0x75b318dc, 0x362424a6, 0x69b1f1c7, 0x49955f34, 0x8cc2045b,
  75926. 0xc6836af8, 0x940622b3 },
  75927. { 0x0d997973, 0x4710ccb7, 0xd3f8f115, 0x3b29625d, 0x5b97abd5,
  75928. 0x8cf0c4d5, 0x673e14a5, 0xc6321e0a, 0x3d262246, 0x0541af9d,
  75929. 0x6fc83b11, 0xde6d8754, 0xf01652a4, 0x47e97da8, 0xad9802b6,
  75930. 0x0f82b3a6, 0xae9c44b2, 0x69aa4075, 0xced2bf77, 0xaf3f5de2,
  75931. 0x497a40da, 0x1ef1ea8a, 0x3c23ba9c, 0x2e0f8608, 0xf190a2c8,
  75932. 0xd8a998a4, 0xcfde3368, 0xe2b49c8c, 0xbde6bd71, 0xb9f49824,
  75933. 0x785bedb6, 0x80bb1664 },
  75934. { 0xfd145cb5, 0x05e575fe, 0xac5e6883, 0x155ee561, 0x8793b273,
  75935. 0x461e70cf, 0x133b2338, 0x9f1553de, 0xa2a7ba07, 0x2fb9e0c3,
  75936. 0x3e7086fa, 0xc3bfd6a8, 0x8bb4cb93, 0xb6ba8500, 0x76f82dbd,
  75937. 0x0b66d789, 0x54eb49ff, 0x7d5a6ff6, 0x1f20b322, 0xcd65d237,
  75938. 0x54e29cdc, 0x79ea49c2, 0xcb118ff9, 0x64975963, 0xcc58000b,
  75939. 0x969598dd, 0x110c779c, 0x95107918, 0x63b85a35, 0xedfc1548,
  75940. 0x41212350, 0x077ba5ea },
  75941. { 0xcdd86f61, 0x0b3a38d3, 0x0502a0ab, 0x43121445, 0x806d0272,
  75942. 0x1912edc5, 0x8a32f10f, 0x01dc1f98, 0x0e80c760, 0xbb1d31d1,
  75943. 0xf464e8b3, 0xd46ec7e5, 0x9abf49ee, 0xd569af36, 0x2cdade77,
  75944. 0x9d286ea7, 0x45ad5920, 0x2be7020d, 0x6299ae7f, 0xabe5236e,
  75945. 0xd3f55c07, 0xc93179bd, 0x52350e80, 0x8138995a, 0xaff07586,
  75946. 0x0901265c, 0xf4739653, 0x5b3c81b2, 0x9bc77d21, 0xbaf7581d,
  75947. 0x4591a2e2, 0x6b2006df },
  75948. { 0x965b1bc1, 0xb2fe50a8, 0x962bb4fd, 0x931f536a, 0x000e7f99,
  75949. 0xd5718d33, 0x53d5125e, 0x84728f25, 0xd2125caf, 0x4f8a6184,
  75950. 0x357f679e, 0x54f1a701, 0x1531c05a, 0x70a9f40c, 0x6fa8b775,
  75951. 0x10d0cb97, 0x9dc12ce9, 0xb476f41e, 0x2755f894, 0x5c8d7a75,
  75952. 0x625741a4, 0xd6c12e10, 0xc917b16c, 0x262a6fb8, 0x38d6b0a0,
  75953. 0x24d116e6, 0x32c38e83, 0x849540c0, 0x66868afc, 0x855b911c,
  75954. 0xbd26b550, 0x53217ea6 },
  75955. { 0x259f52b4, 0xfc840473, 0xe621146c, 0x968da9cb, 0xcacbd26e,
  75956. 0x964eb85e, 0xe4a54344, 0xab7daa2d, 0x381a4ff7, 0x6dc3b848,
  75957. 0x41c815ef, 0xa07a96b3, 0xc3d4b1e1, 0xc4fae9e8, 0x42ce9ea8,
  75958. 0x0f938d1e, 0x35cc052f, 0xa727dacc, 0xe9a06f07, 0xc81e01c9,
  75959. 0x4a6d65a1, 0xa9e08dcb, 0x6044a9a6, 0xf8e2d173, 0xf2bd295b,
  75960. 0x99893dd0, 0xf9781b12, 0xa08d3379, 0x61830ac2, 0x64bd6001,
  75961. 0xd9adbeef, 0x0386931e },
  75962. { 0xd09885a5, 0xd0d7abb3, 0xe355bb07, 0xed9d2b67, 0x536ebaed,
  75963. 0x3bc238cf, 0x699ce4d6, 0x61ca2e78, 0x111594cd, 0x354ff447,
  75964. 0x03316ad2, 0x55cbe709, 0x49fff5c4, 0x418679fd, 0x0f9c6c40,
  75965. 0x75bacd75, 0x2972721a, 0x677edc88, 0xe5ef502f, 0x82596887,
  75966. 0xbf320e0e, 0x459e9367, 0x8bbdccb2, 0x81ce36ef, 0xb766863d,
  75967. 0x1ba097fc, 0xd58c6db8, 0xcd3a21d6, 0xb4a8748b, 0x0e4967cd,
  75968. 0x15041c20, 0x2caaf749 },
  75969. { 0x6ed20424, 0x44f98006, 0x22471545, 0xb3e4ea23, 0x781a8c86,
  75970. 0x268ed1a5, 0x7ae5b70b, 0x48d0ab75, 0x356d3982, 0x6ca8b320,
  75971. 0x2df31fa4, 0x9ce8e681, 0xd925dcf2, 0xb909d232, 0xf56723de,
  75972. 0x302c8f78, 0xabac96f9, 0x11725d69, 0x57d1a170, 0x656a47ca,
  75973. 0xc18a2be7, 0x6bb5d511, 0xad50d9d9, 0xb56e45f1, 0x70b05518,
  75974. 0x36e886e2, 0x09d8ff91, 0xc7c71f3d, 0x9350361e, 0x65a1bbe2,
  75975. 0x45fe3bd8, 0x86d7f532 },
  75976. { 0xb0bf719a, 0x99f16eb6, 0x8bc3d913, 0xb6975098, 0x26cd01b4,
  75977. 0xfae50e52, 0x90898d1c, 0xd3e3ac54, 0x887ec666, 0x4da3b9db,
  75978. 0xfbea45b8, 0x58300644, 0x8355b058, 0x369f3bd9, 0x579bcc13,
  75979. 0x0fb239a8, 0x6e2bd811, 0x4f5b4539, 0x24198fd2, 0x007f3baf,
  75980. 0x8837d51d, 0x68a676db, 0xeae75b16, 0x68eeea62, 0x3db6083c,
  75981. 0x5ffe5f94, 0x7d836c5a, 0x52c94d0f, 0xcbc1ff85, 0x5a4c3c6f,
  75982. 0x86c0b4dd, 0x682a55e3 },
  75983. { 0x587495aa, 0xc8f235a4, 0x34c7245d, 0x2276026c, 0xb75a46e3,
  75984. 0xd6ae0cc5, 0xecc3e5e7, 0x890d3965, 0x14296629, 0x1b13342f,
  75985. 0x8a877227, 0xc89927e6, 0x2324a68b, 0x1543f27e, 0x49cdc21a,
  75986. 0x6c447684, 0x1452d0ac, 0x9bc7fd4f, 0xff4b045c, 0x2cc30a31,
  75987. 0x852f7611, 0x415d46a0, 0xc6fdd7a6, 0xad737052, 0x7b4c7c91,
  75988. 0xdcecc3ab, 0x7688d70c, 0xd2cdf01b, 0xe40d3905, 0x054f2542,
  75989. 0xfefe4dcd, 0x02227fa6 },
  75990. { 0xb751948b, 0x1805efd9, 0xfdfd225d, 0x8efeed46, 0x4f2c8b22,
  75991. 0xcb128e09, 0x96f7c5e5, 0x9d1090bf, 0xb4cbeca0, 0x0959d044,
  75992. 0x8e08cb04, 0x21c955f9, 0x68fa4fce, 0xbc1f279d, 0x0710ae9a,
  75993. 0xb021e14e, 0x881167f4, 0x64d16e9f, 0xbbc9f1a5, 0xf5a5c22e,
  75994. 0xe3420eea, 0x5f3716df, 0xd5c4e843, 0x971eb915, 0x28ffba81,
  75995. 0x64fc55fc, 0x7dd37578, 0x3427e54d, 0x15ebc7d0, 0x446e6a62,
  75996. 0x29269778, 0x547e249a },
  75997. { 0xa1ffda27, 0x4706868a, 0x7955cf50, 0xb4e6cdcc, 0x0a63f3d8,
  75998. 0xf65151e1, 0x9de5e70a, 0x5b4127ea, 0xf9342823, 0x3d2c09ba,
  75999. 0xaa2f7d51, 0x18c99d83, 0xddeec025, 0xa0c5bb1d, 0x03dcf1ce,
  76000. 0x7ffddf84, 0x616fdeda, 0xe57e4d29, 0x7932a1f0, 0xd2456569,
  76001. 0x3191d4e3, 0x7475e0e8, 0xc220218b, 0x3479bea1, 0x8bcb2505,
  76002. 0xfceb5c90, 0x3c6132e6, 0x1c685cea, 0xbfe6c1eb, 0xc42dc745,
  76003. 0xd2b08eea, 0x45a41cc0 },
  76004. { 0x4dbbf0e1, 0x3ea9b2c7, 0xa17cf70e, 0x41ff962f, 0x5eeb4c66,
  76005. 0xdc1ea758, 0xa9beb17e, 0x4f5412d2, 0xa285741a, 0x2c9e4f52,
  76006. 0x984fd11f, 0x93df7da4, 0x0df3184e, 0xb2afbddc, 0x2421e375,
  76007. 0x96323d25, 0x49df781e, 0xc87be1e4, 0x3d589bea, 0x145601ed,
  76008. 0x28fff6dd, 0x0f0bd9bd, 0x8a0f298c, 0x2d3259d4, 0xd88e6944,
  76009. 0x362d7a77, 0xb6ac2af6, 0xa84c06b6, 0xd087da02, 0xba850ac9,
  76010. 0x42ee40c8, 0x128763c9 },
  76011. { 0xacbac178, 0x29a80f07, 0x34b08f6e, 0x7cc20044, 0x70feded2,
  76012. 0xe9631d14, 0x86615767, 0xb2115da3, 0xcb088548, 0x7c75f5c4,
  76013. 0x9a2e8e03, 0x5b29d213, 0x8b881752, 0xfe9fda66, 0xc1de7ebc,
  76014. 0x3f1d8d88, 0x03218123, 0xb476565e, 0xb1c995f3, 0x07365561,
  76015. 0xb13eb71b, 0x2160cb18, 0x99b3a0eb, 0x7e8da513, 0xb20fcd74,
  76016. 0x5e8ca1f9, 0xb4126d72, 0x6a7e0067, 0x68bb637f, 0x1e8204b7,
  76017. 0xfc4f74d2, 0x75e96bcc },
  76018. { 0x0d19716e, 0x189d1fdc, 0x7c384525, 0xdf585058, 0xea987d2a,
  76019. 0x64a846d1, 0x6c07150f, 0x12b6bf83, 0x4d6fd5b7, 0x91d85d46,
  76020. 0x4f53f55f, 0xa9788836, 0x81509129, 0x60083bd8, 0xea876f48,
  76021. 0xa7672683, 0xc15b2489, 0xe80b2e7a, 0x42d1d992, 0x985ef8d2,
  76022. 0xcf3de492, 0x9c57b029, 0xb1487627, 0xfe02f83c, 0x8ae5b687,
  76023. 0xaeba4fe4, 0x5d6b8196, 0x8a86f09b, 0xa16e523d, 0xd88f566b,
  76024. 0xba268949, 0x309a6e9a },
  76025. { 0xbdfbe97a, 0xef27ee50, 0xb8c50c4d, 0x1a5fe70f, 0x7fe09f5c,
  76026. 0xcc7beb01, 0xbed36cc5, 0x8fa15a85, 0x7550ed3a, 0xc0c3acdb,
  76027. 0xeb908681, 0xc581ef87, 0xc49d5ccb, 0xa15b3362, 0x1fa264e8,
  76028. 0x0fbb1714, 0x8e1eee88, 0x267f8d8f, 0x21c2b63d, 0xd31ccfd6,
  76029. 0x53be7efd, 0x924dbe7d, 0xdb2a358a, 0xd42e877f, 0x75d68ac1,
  76030. 0xcf9673c7, 0x714fea55, 0xe35978fd, 0x5769b202, 0xeeb36653,
  76031. 0xd7593789, 0x0458258a },
  76032. { 0xa042dbdf, 0x5df71a74, 0x5779dfa2, 0x2d405857, 0x0d2e6657,
  76033. 0x0e66cba7, 0xca2e892e, 0x285d6745, 0x0f0e6b5f, 0xf56a8def,
  76034. 0xa30767c3, 0xe0ee851d, 0x43346b9c, 0x98c05658, 0xd6b3c742,
  76035. 0xb35fce26, 0x39777e00, 0xc0895bff, 0xe7b6d886, 0x83c8f6a6,
  76036. 0x4f02904b, 0xbee14843, 0x2e84ec34, 0x7f74915b, 0x96d10991,
  76037. 0xbaaf663c, 0xe41facc0, 0x004b8757, 0x6f86c029, 0xa2b880e5,
  76038. 0x95b77358, 0x53f4a3e0 },
  76039. { 0x89fc48e7, 0x11bb08ce, 0xafab5aeb, 0xba60c577, 0xa0c1cb5a,
  76040. 0xf06bcbf8, 0x79757cb6, 0x7d2efaea, 0x76319160, 0xe26d90b1,
  76041. 0x2b77b7a9, 0x42aa1ab6, 0x285df2bf, 0x38eec0cd, 0xf3a8f7f0,
  76042. 0xd35947f5, 0xfc1cb5b5, 0x97c8dc0e, 0xc45845cf, 0xfeb8cca0,
  76043. 0x249e26f2, 0x16e8d989, 0x483ed89a, 0x7c264e6d, 0x51d91073,
  76044. 0x13a3f145, 0x305e99f0, 0x8501562e, 0x6908d563, 0xaaf98d74,
  76045. 0xd723d236, 0x0a99e653 },
  76046. { 0xabbc0559, 0x23536f46, 0x9aa1a160, 0xc163067b, 0x0c1681b5,
  76047. 0x229fd229, 0x1378e907, 0x61254be1, 0xab793a2d, 0xc60ff57a,
  76048. 0x466552db, 0xa6f2df8b, 0x8c170a36, 0x9ad31893, 0x29b74d9a,
  76049. 0xc5cd9abe, 0xf7848523, 0xcf747273, 0x0d0e3063, 0xc126a93a,
  76050. 0x4248e3d8, 0xfe2021e3, 0x8323ddfa, 0xd97343ee, 0x332639e7,
  76051. 0x9f768775, 0x75325548, 0x9650fc31, 0x3eebf7ea, 0xb595dbd1,
  76052. 0x010fcbc0, 0x3a95cb45 },
  76053. { 0x39d7ff2e, 0x954e68cb, 0xc1d5c48f, 0x8dd1cb4b, 0x7169438a,
  76054. 0x02a92c77, 0x91cad8ce, 0x7965c0b0, 0x32cd08d2, 0x0c5798ab,
  76055. 0xa6902bda, 0x1a5bc3c3, 0x5186d218, 0x545d0925, 0xd27e64db,
  76056. 0xf0077cdb, 0x8cd092da, 0x0157caa4, 0x24532ab3, 0x2a2fa3a0,
  76057. 0x41ccaba3, 0xa5fb639b, 0x4744aee6, 0x01702dc1, 0xcdba93da,
  76058. 0x485bb436, 0x329784f1, 0x93597f66, 0xdad672c3, 0x5d713c1d,
  76059. 0x030b7245, 0x366d222e },
  76060. { 0x573ea5b2, 0xd50b4875, 0xa90da44d, 0x0fce401b, 0x7a1a0310,
  76061. 0x7b53fa65, 0xcf114460, 0x722a80a5, 0xa538bf49, 0x0b8ebf05,
  76062. 0xd32acd21, 0xae141147, 0x7b5ad07d, 0x6692712c, 0x3f48ca07,
  76063. 0x6dc5fee7, 0x2b8a78d8, 0x98ed1499, 0xdd2f1759, 0x4e8b3145,
  76064. 0x5f971b8e, 0x43408de1, 0xadf1b368, 0x055ea6dd, 0xe5932b7e,
  76065. 0x4bb76e73, 0xd30893fd, 0x44287153, 0x0661bfda, 0x173dccd2,
  76066. 0x79defd25, 0x9072ba99 },
  76067. { 0x9620ea39, 0x474de4dd, 0xc831cee8, 0xfbf1649f, 0xcd3a9c43,
  76068. 0x0b0e8bb1, 0x3f3df1d5, 0x6a38286f, 0x8f0ec9b3, 0x4ed072b3,
  76069. 0x729c09e3, 0xa6e4c987, 0x8ad12242, 0xea3e8ac6, 0xfbdfa5ba,
  76070. 0x6ae0e22b, 0xb0a0f592, 0x56171ecf, 0x6b871f8d, 0x33b2886d,
  76071. 0x35e11bda, 0x6b19bea9, 0x7f0f153f, 0x4d815a40, 0x7d6c02ee,
  76072. 0x7e608d97, 0xb6a88f46, 0x7e8f23d9, 0x439d1654, 0x26ac9652,
  76073. 0x35546c29, 0x8d92c6bd },
  76074. { 0xabeb0ff7, 0xb3e0d7ce, 0x3e0e42f8, 0xfbe35254, 0xde808499,
  76075. 0x57d1b226, 0x1cd44bc3, 0x9ece2e1f, 0x435cfee1, 0x1245adbc,
  76076. 0xf93f581c, 0x874ee840, 0xbda0b947, 0x916a779c, 0xfa57ae0a,
  76077. 0xabcc815a, 0xf0a621b0, 0x97adec2d, 0x81f90bdc, 0xbe6a502b,
  76078. 0x53bde63d, 0x54bf9de1, 0x78884c25, 0xa88fdabf, 0xcbbb5470,
  76079. 0x30aa52b1, 0x29053ef5, 0xf805396c, 0x8dd827ea, 0x8d43d898,
  76080. 0x5c1ae5c0, 0x4e4bec17 },
  76081. { 0xfcc09676, 0xbf8483a2, 0x19ea9a94, 0x457c4a3f, 0xd702a5dd,
  76082. 0xa6852ef3, 0x843fe7d8, 0xe7915fd2, 0x16e35158, 0x644bba98,
  76083. 0x9ed746f0, 0x8d1b95d0, 0xb90af0b5, 0x47704581, 0xd4fd135e,
  76084. 0x0bd4bc6b, 0xb4e833a5, 0xa6dce067, 0xff56a9a1, 0x2c0e8f30,
  76085. 0xec2c63fe, 0xa9c80800, 0x98f508a8, 0x449c20a5, 0x3292813a,
  76086. 0x02b94cb3, 0xec7e81a2, 0x647e3d28, 0xb4877677, 0x72e67d1a,
  76087. 0x6f9ded24, 0x7a4aa3f5 },
  76088. { 0xe27a0045, 0x559ef1ba, 0xb242cb50, 0xdc812d4f, 0x39cf8d24,
  76089. 0x23a478e4, 0x9b3f9c54, 0x97544fc5, 0xaffa1fcf, 0x5ac68132,
  76090. 0x34a2c83b, 0x74f8fee0, 0xcd3f4bb7, 0x96cc640f, 0xb0512ea6,
  76091. 0x775dce9d, 0xcdce381e, 0x67dca19d, 0xa9d3fe55, 0xc1eeb3f3,
  76092. 0x1a19274f, 0x38e0bf42, 0x28d69b12, 0x15992fb4, 0x9fd09df8,
  76093. 0x48fcebde, 0xb41ab5df, 0xdc9dfa4f, 0xc0a269c5, 0x0cbd7dc8,
  76094. 0xf7f0ade1, 0x60282a7b },
  76095. { 0xdceea2e7, 0x7c07e538, 0x3c42061d, 0x38a322c8, 0x4f1f6516,
  76096. 0x676828f9, 0xc7776a10, 0xf21b69fb, 0xb5e6b405, 0xc63a3417,
  76097. 0x91a7b642, 0x4c99f258, 0x2cad1440, 0x38692ca8, 0x00869bcd,
  76098. 0xf1e82ffe, 0x16fe466a, 0xc30b714e, 0x19019138, 0x5fb742f9,
  76099. 0x0fa516ae, 0xe90166d0, 0xd8c73a43, 0x5550f7ac, 0xfbc5c372,
  76100. 0x2d6a407d, 0x68cc39ed, 0xe47a7539, 0x4a5fbe70, 0x3fd286d9,
  76101. 0x23c6b942, 0x5f4ae9c7 },
  76102. { 0x53f4d561, 0xd96a2dda, 0x16da1992, 0x286d45d0, 0xfdd4b051,
  76103. 0x449a01fb, 0x9f2195ea, 0x25488a0d, 0xa37661b3, 0xc4151b0a,
  76104. 0xf9e5ee02, 0xb98c471e, 0xa8658817, 0xa4bca86e, 0x7a68fc0a,
  76105. 0xbbcadb87, 0x6b7366a9, 0x88b34649, 0x15661c2d, 0x32ee98d4,
  76106. 0xc901420c, 0xf5b3b4c6, 0x2f2752af, 0xa2352735, 0x510e4d9c,
  76107. 0x2f64ce73, 0xaca4aa80, 0x939a7f26, 0x401aa503, 0x9cd3e291,
  76108. 0xdc46afd2, 0x92a01423 },
  76109. { 0x1c2f7dbd, 0xe9f24be1, 0xb7d527fa, 0xda8c900f, 0x8648f128,
  76110. 0x963e25bb, 0x48141941, 0x9ab713e2, 0x7a6756fb, 0xe87f7d01,
  76111. 0x058d90bd, 0x274dd85e, 0x82566abd, 0x823fee7a, 0x74240195,
  76112. 0x9f6230d7, 0xacb5e46e, 0x04579f2c, 0x16a4c87e, 0x2a226263,
  76113. 0xd99b0857, 0x9ca19a43, 0xe488789e, 0x86dc2ba3, 0x9406c3bd,
  76114. 0xf960b5b9, 0x8960957e, 0x6f2c428b, 0x161c515b, 0x90748706,
  76115. 0xaa88cb9b, 0x0fc8fe1e },
  76116. { 0xfeb90f2d, 0x68ae1bed, 0xa48b1559, 0xf393bb3c, 0xf64e9635,
  76117. 0x2be62f9c, 0xf8be75c2, 0x354c2410, 0x5e6f7529, 0xbd7ea703,
  76118. 0x162cab31, 0xc264868e, 0xc860f3ff, 0xb1391e70, 0x1d89837e,
  76119. 0xdf367c75, 0x2bf32941, 0xe150b6b4, 0x78c1318f, 0x95e8f46e,
  76120. 0xa2c4b160, 0x2b3f1dab, 0x701afbf3, 0xc6ccf5ce, 0x5e8874c5,
  76121. 0x3ad27530, 0x5dc6dcbe, 0x39285e51, 0xd99892dd, 0x3c954d86,
  76122. 0xdfd3789f, 0x2d0ba862 },
  76123. { 0xb472e1af, 0xeacd8ee8, 0xb76abbcc, 0xeb354eae, 0xd0d93fbd,
  76124. 0x9b520bf8, 0xfe6fc706, 0xfccd60d7, 0xa4ee2f39, 0xa9353dde,
  76125. 0x9a81e51e, 0x5eb0925e, 0xd1366777, 0xee334da1, 0xd5354d69,
  76126. 0xc1d28c9f, 0x92a5ed54, 0xb9771755, 0xb7f70d81, 0x5d3e367f,
  76127. 0xa933ae7a, 0x7be7eeca, 0xe23cfbb7, 0x264cf1f9, 0x89497681,
  76128. 0x0d129f4a, 0x09b6235b, 0x705375a4, 0x48a376da, 0xccf64c75,
  76129. 0x4d41dbfc, 0x963c8712 },
  76130. { 0xde36a814, 0xbae290cb, 0x733b12b5, 0x9bdb0195, 0xf77fe0e1,
  76131. 0x0ebad867, 0x29720cea, 0x0a7d19fd, 0x9029ec72, 0x434d7651,
  76132. 0xbb51911e, 0x856aff17, 0xd80a7f60, 0xd0a25d9a, 0xf848c106,
  76133. 0xffca86af, 0x43ad749c, 0x53e8bdf9, 0xe3e696bb, 0xfb9e0284,
  76134. 0xeeee4215, 0x3eb6630a, 0x2ecf3c63, 0x9d8fbb9e, 0x4e00c0c0,
  76135. 0x71da4ffa, 0x5d57beac, 0xb296be59, 0xa8cec7ef, 0x1751fbad,
  76136. 0xff55d7bd, 0x2d03eb3c },
  76137. { 0x04f2ec1d, 0xeb16925f, 0x0d147ee2, 0xa878f276, 0xaad9d9e0,
  76138. 0x442df604, 0x3f71035b, 0x891df44b, 0x8cb95d5b, 0xc28272b3,
  76139. 0x5ee8ed23, 0x6f14efb5, 0x13b0f3e3, 0xf3c4460f, 0x6bd7335e,
  76140. 0x889f9bd7, 0xf755ba6e, 0x889ee771, 0xed219b6c, 0x626984fe,
  76141. 0xec2ee411, 0x2d44c737, 0x63efcd37, 0xb94385a2, 0x6637826b,
  76142. 0xd909321b, 0x3ee6b7a7, 0xc24f8a79, 0xa7cf61b7, 0xa3ca8d24,
  76143. 0xc54bacd9, 0x842e40c1 },
  76144. { 0xa661d843, 0x5a268ed6, 0x4f5b30cd, 0x02328cca, 0x1311e177,
  76145. 0x16e6fed1, 0xc6695967, 0x690decb4, 0x57b2e280, 0xbdac5bf6,
  76146. 0x1efe42d0, 0x827f82ca, 0xca5fca2f, 0xc554ec0a, 0xdde45506,
  76147. 0xac5276c1, 0xe3077513, 0xb7f4cb08, 0xcc8797cc, 0x8caf6d9a,
  76148. 0x0d9332d2, 0xd5964814, 0x285a409f, 0xcc6ae297, 0x6223d093,
  76149. 0x7773c2a5, 0x5128fc09, 0x2d5266ac, 0xbc31fe6c, 0xa596b7cb,
  76150. 0xcac91328, 0x0e63319a },
  76151. { 0xf0360ac2, 0xb5cd2fad, 0x285e605a, 0x86b660de, 0xe25b9b14,
  76152. 0x82c6cf10, 0xaa9ac554, 0x9d5fa38d, 0x526c070e, 0x3dfcf1b8,
  76153. 0x3fccc52d, 0x0379a96b, 0x0bfcc7f5, 0xe3659c29, 0x69d3e6a1,
  76154. 0x5b1a3db5, 0x9b7b42d5, 0xb41528b5, 0x9c22a006, 0x934defa4,
  76155. 0x9b4ce3b6, 0x90f38018, 0xb3abaf32, 0xb073bc04, 0xff8389e2,
  76156. 0x27a5a222, 0xffa5a35b, 0x0b7a9d51, 0x28e1a7c2, 0x4939ecef,
  76157. 0x1872705a, 0x88839da2 },
  76158. { 0x701ce29a, 0x56b66c30, 0x58981d50, 0x3acaf126, 0x105f9f21,
  76159. 0xd4dafc0c, 0x373e3d13, 0xfee571e6, 0xfa2ee3ca, 0xe7269c86,
  76160. 0xdd20385a, 0xf5cca64a, 0x3000e9ac, 0x217f2757, 0x0e7273ef,
  76161. 0xc934db47, 0x355b6776, 0x4294f4f7, 0x6fc05180, 0x1faa36b9,
  76162. 0xb052190b, 0x8f88b1db, 0xe9eaef52, 0x35791b90, 0xdb681b90,
  76163. 0xf37fb2eb, 0x4415c369, 0x39d0a51d, 0x1d2e21c9, 0xfc59cca7,
  76164. 0xa1f50c26, 0x64128cfe },
  76165. { 0xe8f5b0b5, 0xf03678a2, 0xd340f059, 0x5c7e249c, 0x93ca7cec,
  76166. 0x41440441, 0xbc83af98, 0x075ca346, 0xfaa8bbb0, 0xf39f0033,
  76167. 0xf38230f7, 0x3d18f0ed, 0xd448f345, 0x78dff00c, 0xd51aa475,
  76168. 0x849228c0, 0x30c928d1, 0xdd4e2708, 0x8f12cfd3, 0xc66ba686,
  76169. 0x88b3a206, 0x091049db, 0x016dae01, 0xd865d059, 0xe253e37d,
  76170. 0x4599e905, 0x7ce9871b, 0x322cf0c2, 0x174a132e, 0x014f54da,
  76171. 0xbdabcbda, 0x93634a09 },
  76172. { 0xa9a2e304, 0x62826b27, 0xc1a4c124, 0xc57e1866, 0x22381710,
  76173. 0x913ab832, 0xa9847cfe, 0x7e9b6b85, 0x2b5f46fd, 0x29655cf1,
  76174. 0x8038e66d, 0x7295572b, 0x6fa95eab, 0xe4cba601, 0xb9deda81,
  76175. 0xbbc11071, 0x3f1cf61e, 0x97f0009a, 0x373e0cfb, 0x5372777b,
  76176. 0xd139d63b, 0x302f909c, 0x4f87d78e, 0x1ed672da, 0xb4048763,
  76177. 0x362077a3, 0x9dcc22b2, 0xc408c32d, 0x26deeee7, 0x4b4c5bf2,
  76178. 0xbc06357e, 0x266cb467 },
  76179. { 0xb56363e8, 0x6faa4154, 0x3c1aa4db, 0x4b4fd078, 0x2b9e6597,
  76180. 0x14358dde, 0xfa004b84, 0x5b34ae3e, 0xf19911a6, 0xcf44b2ec,
  76181. 0xa536bf78, 0x55caa833, 0x8870dc95, 0x606e1eb9, 0x09f3511d,
  76182. 0xe3c3287d, 0x9d5cf364, 0x68b2f4eb, 0x63ab8c9e, 0xc154e892,
  76183. 0xc36ab611, 0x1548828e, 0xa1b7d120, 0x0932bfcb, 0x5315b8d7,
  76184. 0x7ee7b5bc, 0xf7473ac1, 0x782fd0d1, 0x3c8f2af3, 0xbcb029a8,
  76185. 0x52454ee1, 0x4b1d5a1b },
  76186. { 0x63d52c0c, 0x12fe5174, 0x188c099d, 0x3735525e, 0x360e3956,
  76187. 0x5c621563, 0xacfa5a43, 0x88b3f1ca, 0x797e8107, 0x90123a0a,
  76188. 0xb15e080a, 0xba31f6b5, 0xfca3dada, 0xd7de5e12, 0x0df511c8,
  76189. 0x3287361b, 0x65757d4e, 0x7cc800d4, 0x5207ec91, 0x10810f3d,
  76190. 0x30eea0e3, 0x0d4e56f1, 0x3ea5a2ec, 0xbbf7ee13, 0xbe6abbd0,
  76191. 0x6fc07762, 0x120bf619, 0xc831fdce, 0xb622d42a, 0xe07439fa,
  76192. 0x508e4b27, 0x8186b93f },
  76193. { 0x09312867, 0xc619d154, 0xbfaf7db4, 0x7e042c05, 0x1f5f5dda,
  76194. 0xc1cf1668, 0xa4fc3d82, 0x50aa5057, 0xce68b8fe, 0xed30ed65,
  76195. 0xbeb4d644, 0xecb01c0b, 0x831c0497, 0x7b5dc444, 0x9b7d9b1c,
  76196. 0x351e6a00, 0xd9477c91, 0x4bb863b9, 0x05d4110a, 0xaba65891,
  76197. 0x43580b7a, 0x30086cf4, 0x90be357e, 0xb139c076, 0x27b5214e,
  76198. 0x12bfff1a, 0x22c3ab57, 0x79cfc6d7, 0xf34a9bfa, 0x4743de57,
  76199. 0xc9ee2b2a, 0x0bf97e97 },
  76200. { 0xdda19e96, 0x96ec4ec8, 0x6c306e8b, 0x54ce18ea, 0x65f6918a,
  76201. 0x7e83612b, 0x0d9a0d99, 0x1ac6f68b, 0x62fdcc09, 0x98a697a4,
  76202. 0x95bc3e13, 0x65ce25f1, 0xb3939730, 0x1896ecda, 0x32f12806,
  76203. 0x9eb81a0f, 0x1d2dc7df, 0xd3d7416e, 0xad473599, 0xe22c7976,
  76204. 0x9f5ef439, 0x3de37a9a, 0x9e69d94e, 0x6b7ac0ab, 0x0a9d0bc8,
  76205. 0xe6bfa9e0, 0x5676f120, 0x576a870d, 0xfeaac23f, 0x3bd91bb4,
  76206. 0x3e40aabb, 0x8fe5482c },
  76207. { 0xce9a4d1e, 0x85ae67c2, 0x4f1d2038, 0x4c3eb803, 0x25d06192,
  76208. 0x5c6c8f3a, 0x308fb41c, 0x803de0ad, 0xe71c294e, 0x9961f5bc,
  76209. 0xf02eb0da, 0xdc62078d, 0xb64ae8b6, 0xc87ef515, 0x50b4d18f,
  76210. 0x69679f1e, 0x52199f43, 0xc5c009a1, 0x0f640a5f, 0xa7d484be,
  76211. 0x23dab566, 0x4c918bb1, 0x64275d2c, 0xa67c114c, 0xcad2ded6,
  76212. 0x95a913b9, 0x6b4b5c8d, 0x189ed18b, 0xb42d3bf6, 0x4aeb6206,
  76213. 0xbbc8bc3f, 0x3928c669 },
  76214. { 0xdacb4b64, 0xde4bea4a, 0xf26179a1, 0x03f62a44, 0x7a9112a4,
  76215. 0xf3aac94e, 0xd36f331e, 0x90448fbd, 0x407b85c4, 0x426042bc,
  76216. 0x2121b77b, 0x5ad8a596, 0x67cee984, 0x31674a4f, 0x4e3b2f0d,
  76217. 0x7fae8bbe, 0xa7c930eb, 0x681df6dd, 0xc259d0d4, 0xadeefa98,
  76218. 0xbea1c1fd, 0x1b14d9e6, 0x21d405d1, 0x3baadc8b, 0x73892754,
  76219. 0xf01dff93, 0xf071cde4, 0x81c35b3e, 0x9150d0d9, 0x1704d2e1,
  76220. 0x355134f6, 0x6ccc888f },
  76221. { 0x7ad7504c, 0xf8d36f0e, 0xf7959ddd, 0xbca3265f, 0xfede67aa,
  76222. 0x0dcd1ede, 0xbaebf32f, 0x1276f4ce, 0x014edcfc, 0x6825a6e6,
  76223. 0x99ad8eb7, 0x0b8c1a82, 0x09b8ce1e, 0x312024a9, 0x9cbd351a,
  76224. 0xcb8fd98b, 0xfab1e8be, 0xa4841378, 0x3973cacf, 0x17ed0f5d,
  76225. 0x259d5254, 0xa17e1484, 0x74b91393, 0x53d5b843, 0x1aca3ce9,
  76226. 0x8f792b21, 0xc8c0f815, 0x035ff110, 0xad4ed7bd, 0x6afa6357,
  76227. 0xb26faef9, 0x2f151980 },
  76228. { 0x29d2d439, 0x0c8631da, 0xbc039955, 0x121fbbc2, 0x6c05b75b,
  76229. 0x3e5a9792, 0xb6ce47ec, 0x6d6cf4c0, 0x9d88c658, 0xbaaa1767,
  76230. 0xf3355a17, 0x031db9e7, 0x0aef5a85, 0x8381e3d8, 0x15a31bdf,
  76231. 0xc71db290, 0x9498fd7d, 0x638f6b74, 0x13beeef6, 0x44edf3f9,
  76232. 0xf4ab67b3, 0xe6173271, 0xfd22df11, 0x3a202c70, 0x205c4e92,
  76233. 0xf7be0389, 0xa8eb9920, 0x1c219085, 0xbeb54aaa, 0x6c805ce8,
  76234. 0x0ac58d65, 0x354b05b7 },
  76235. { 0x7a9170e9, 0x7171e236, 0x4cad50cd, 0x01eec42d, 0x3cddccfb,
  76236. 0xffbe824f, 0xa66cae1a, 0xa73e8ce3, 0x965c7d01, 0xb7138a7f,
  76237. 0x5c3d971e, 0x00058e3f, 0x2ff0a72b, 0x52591ac3, 0xbbbce76f,
  76238. 0xa32fb5bc, 0xa9f81a18, 0xf3241ab8, 0xeca68630, 0xf31d3332,
  76239. 0x4482f13b, 0x847af9fc, 0xa4681be2, 0x6196e217, 0xe55efcf9,
  76240. 0x9938f932, 0x70acc705, 0x3e7dacb8, 0xcf09fac2, 0xd41be893,
  76241. 0xae3523a1, 0x48dc55c4 },
  76242. { 0xa5092193, 0x8e623826, 0x6898970c, 0xe46ec362, 0x25c9eb41,
  76243. 0x2f1356af, 0x83c7d245, 0x41780640, 0x97d00e38, 0x982def67,
  76244. 0xa512151c, 0x382eb6e7, 0x8af58869, 0x154e1077, 0x8a51cf02,
  76245. 0x18707075, 0x71313c58, 0xcdeba9f7, 0xba155904, 0x5d67b973,
  76246. 0x1d0d7b3a, 0x851c9f4b, 0x8b8af2cd, 0x19f29d71, 0x986b8d62,
  76247. 0xcb94ccff, 0xb93b9c33, 0x8725e24b, 0x66e38c68, 0x405ce4c5,
  76248. 0x0b6dc021, 0x5f6a8edd },
  76249. { 0x8f9a8690, 0x83704ca5, 0x2f76a407, 0x3f369766, 0x69201028,
  76250. 0xfbc12d8c, 0xbce3a4cf, 0x4cd58f16, 0x04aab26d, 0x7804664a,
  76251. 0x4ea457a8, 0x005cfbba, 0xb8a59794, 0x537951b3, 0x4fe1f739,
  76252. 0x4ca2b9e4, 0xdf325797, 0xe4428acd, 0x0ea243db, 0x648da342,
  76253. 0xf43ce01e, 0xcce6562b, 0xf27db490, 0x840f0421, 0x8bfb7cf0,
  76254. 0x156ccb70, 0x5a8797d3, 0x9b33480d, 0x9eb814bb, 0x2e12e07a,
  76255. 0xca7f87ac, 0x1ca65072 },
  76256. { 0x2b9d25a0, 0xfbb321cf, 0x40a746db, 0x66affdca, 0x59e368b5,
  76257. 0xc1c1530e, 0x7d80068f, 0x56ed1ea4, 0x5647dd68, 0x9b74d8fe,
  76258. 0x89b78da8, 0x1d96b507, 0x8bbe3391, 0x39b75243, 0x0d858c5f,
  76259. 0xef8d443e, 0x9646aa34, 0x4dd2db49, 0xe667543c, 0x7fad3bd1,
  76260. 0x68980985, 0xd0d710c0, 0x49facaba, 0x9f7aff32, 0x14f9a192,
  76261. 0x055dec1c, 0x1fb307a1, 0xaca66399, 0x35ffff64, 0xac44fd91,
  76262. 0xcbad3cee, 0x462cafb6 },
  76263. { 0xde3237dd, 0x1660a647, 0x82b87404, 0x95f735cc, 0xddfa55f8,
  76264. 0xf7879f59, 0x726b914a, 0x15ef043e, 0x1c93e298, 0x1875393d,
  76265. 0x6ef18331, 0xa1a2be74, 0x25a9a12b, 0x4e7e8dfc, 0xa9c3917f,
  76266. 0xdfefc97d, 0x0a2ebe41, 0xbc875d03, 0xa732d1cc, 0x0f75d235,
  76267. 0xd9baa6d3, 0x06fee7fe, 0x65f48576, 0xaa784fab, 0x513f83c0,
  76268. 0x23155e22, 0x3e8f9d13, 0xd2fb7718, 0xb546eafd, 0x2a291503,
  76269. 0x6cd93608, 0x1293c98c },
  76270. { 0x49d53b77, 0x72781251, 0x96eafac7, 0xa6ab403d, 0x4a36b711,
  76271. 0xb7d7c7db, 0x87e771c1, 0x8238c708, 0x33b37522, 0x495f6abf,
  76272. 0x8c87530d, 0xb0b0289c, 0xe77b111a, 0xca83cb86, 0xa1bd189e,
  76273. 0xbe1c0fb8, 0x1ae9d7c7, 0x58cfb2fb, 0x4940c3e8, 0xd05c23c5,
  76274. 0x74ad9107, 0x16e79e41, 0x064e7142, 0xa0a47f05, 0xfdfd614f,
  76275. 0xc6929cd4, 0x3946988b, 0xedb2584c, 0xe46f8fb1, 0x73e4b5f3,
  76276. 0x68ea94ba, 0x53b79aa1 },
  76277. { 0x44bbb6a1, 0x216fafce, 0x67821728, 0xd3a5bba0, 0xa9dd939a,
  76278. 0xef1e4b30, 0xf19efafe, 0x022eaf3d, 0x7b4ec014, 0xfed5abce,
  76279. 0x512c6738, 0x64968ee6, 0x29fe89a2, 0x23119869, 0x47397c05,
  76280. 0x0d539d8d, 0x234596c4, 0x6400bc54, 0x5346611d, 0xb9287f58,
  76281. 0xc9d5da0f, 0x04099903, 0xc83af2a8, 0xe5ef4997, 0x328151e1,
  76282. 0xc89dc01b, 0x58401104, 0x150fb4a9, 0xf3872c9d, 0x40a6f7d5,
  76283. 0x56c2e833, 0x8290d6d1 },
  76284. { 0xd8546946, 0xf84637c6, 0x69ec57fa, 0xda134a39, 0xd789007e,
  76285. 0xd42359a4, 0x0dc7b809, 0xb42557fe, 0x2d6784a9, 0xe62ae52d,
  76286. 0x0bcadb5f, 0xa2714ca6, 0x33aafca5, 0xcc208de6, 0xed967811,
  76287. 0x2380ed5c, 0xdb321660, 0x6e6b55e9, 0xa675235a, 0x1bead02c,
  76288. 0xb33fa0e1, 0x51cc6ef9, 0xf06a2a08, 0xfd223e26, 0xec47b3cf,
  76289. 0x00f332e1, 0xa0aa984e, 0x459f297b, 0xee952e14, 0x6fa1d969,
  76290. 0x304fabb0, 0x506ef1ab },
  76291. { 0x35bff163, 0x11b4eb27, 0xea9fa984, 0x7130b96f, 0x9deb27ce,
  76292. 0x66aceb3f, 0x9dd1c3d5, 0xa2daf1a5, 0xa73075aa, 0xf5090a7e,
  76293. 0xe3071b58, 0x36a6af39, 0xdf73ad9c, 0xa28d633d, 0xbdc89a16,
  76294. 0xdd354cac, 0xd4dcbc3c, 0xdfea3423, 0x379d92d1, 0x6eec74d2,
  76295. 0x8eed6765, 0xe14a456f, 0xfa8feb1f, 0xfabe7743, 0xb98fcbc7,
  76296. 0x1404ccf8, 0xf71a706e, 0x6ccd2fbf, 0x4d85c678, 0xdaaf3fdb,
  76297. 0x15200344, 0x415b7dbf },
  76298. { 0x7d8377a7, 0x97010586, 0xcb803272, 0x068a3d68, 0xf03a4c32,
  76299. 0xfd67d289, 0x93c8f290, 0x4bc7095d, 0xe9e5a2b8, 0x712fa13c,
  76300. 0x0feb9f3b, 0xfc6ac6c6, 0x6e0e54c2, 0x0cda36d9, 0x86320a01,
  76301. 0x45499751, 0x97f00f11, 0xf9318c91, 0xe6936508, 0x01dc4c3f,
  76302. 0x85f068aa, 0x769a2ef9, 0xa2b5511c, 0x3522cef0, 0xb4122e05,
  76303. 0x006965ed, 0xc175d43f, 0xfce0fafc, 0xec831d59, 0x525dc9bd,
  76304. 0xaf58879d, 0x1ec314f1 },
  76305. { 0x2c8310c2, 0x0663feef, 0x457e3f74, 0xaa7e14da, 0xe5346887,
  76306. 0x392b10fc, 0x637ec2c5, 0xcde4a38f, 0xb542f8df, 0x50773320,
  76307. 0xf7de1711, 0x341302f9, 0xae4b9bc6, 0x018b1c63, 0xdd2f9e6f,
  76308. 0xf001c46e, 0x26eccfa0, 0xd3bb0a97, 0x7746e0c7, 0xa931b99d,
  76309. 0xf5875aec, 0xe0c8b6f7, 0x96939c82, 0xbb32f17c, 0x3de5a664,
  76310. 0x765135d2, 0x52abfa6b, 0x71936cb4, 0x2dc105de, 0xad5cc08f,
  76311. 0x7fff5788, 0x17e91d12 },
  76312. { 0xb7e051ca, 0xbe92ced3, 0x19c776d4, 0xc644d4fd, 0x0086784b,
  76313. 0xc8ab4b52, 0xce9d6b31, 0x3ea66227, 0xd289e9c7, 0x395249a3,
  76314. 0xd12a19ee, 0x54509e65, 0x8c365aec, 0xa7bd4692, 0x77963e0e,
  76315. 0x354997e4, 0xb599732d, 0x0d765957, 0x91d4a3b6, 0x99584aeb,
  76316. 0x1deb3e28, 0x6e653ea4, 0x572571df, 0xca7c98ed, 0xb18ae1f9,
  76317. 0xf301a38f, 0x63f7b97e, 0x1629f7c2, 0xafc4a0d5, 0xdf242282,
  76318. 0x3ddd0c01, 0x118f3b4b },
  76319. { 0x7ad4762b, 0x74a0a0a8, 0x8c58d175, 0x1aef84da, 0x4cf76d86,
  76320. 0x16ff4960, 0x7e60d98b, 0xc0be8786, 0x3ecc1dba, 0x83637ffb,
  76321. 0x5dd6147a, 0xc244a609, 0x5b0846e5, 0xa3e17834, 0xe77a4c05,
  76322. 0x735eb686, 0xdf758695, 0x5bc18b4f, 0x1bdfe52f, 0x15618d0b,
  76323. 0x00715ba1, 0x878ecc0d, 0xc2dd617f, 0x1dbdbd1a, 0x21b61710,
  76324. 0x21d2b631, 0x44f593c2, 0x22ce8a79, 0x44f17024, 0x3b9b536a,
  76325. 0x8d03e727, 0x01d0a67c },
  76326. { 0x1e46533c, 0x7b964236, 0xfb88c2ae, 0xe9477990, 0xa42c4a18,
  76327. 0x019b5d16, 0xd83c7a45, 0x7135e81d, 0x4cb663e3, 0x74a69bdd,
  76328. 0xe76c0d63, 0x7b67ecdb, 0x11e68da6, 0x03d54521, 0xd2e8650a,
  76329. 0x596cceb5, 0x2af03b37, 0xcd572dfd, 0xfabd5952, 0x52364ba1,
  76330. 0xb4ed8569, 0x7f47d456, 0xc950d5d4, 0x5ad8b572, 0x486e2f84,
  76331. 0xcadd2dfa, 0xc56bb044, 0xdd527b43, 0x997c08e6, 0xc9adba24,
  76332. 0x7da6320f, 0x1b625b06 },
  76333. { 0x4fd8446d, 0x44dfaa7b, 0xaf6febeb, 0xc01b2f01, 0xfe8838b5,
  76334. 0xbf444388, 0xbba9758b, 0xf33c434f, 0x87156bc9, 0x2b971cba,
  76335. 0x1f49098b, 0x6b245e5c, 0x2b41c5dd, 0x87dcb534, 0x34d852d7,
  76336. 0xdb1f80c6, 0x2433da34, 0x6d6e3258, 0x3f7df0c2, 0xf6682065,
  76337. 0x360cb365, 0xc4ca567c, 0x9826656a, 0x321faac2, 0xbf069768,
  76338. 0x13f5ca6f, 0xa7076639, 0x15397921, 0x8400736e, 0xbdf14328,
  76339. 0x19fc948d, 0x333eca96 },
  76340. { 0xac775d81, 0x23337948, 0xd41dbbca, 0x38c2518f, 0xbcfce948,
  76341. 0x623c7a4f, 0x54703fe7, 0xaad36236, 0x13fb3b5b, 0x2b3a13a4,
  76342. 0x7f5c01f0, 0x5db3565a, 0x52359661, 0xd72408dc, 0x1d616e91,
  76343. 0x5a17f8e5, 0xcb25b999, 0x90c16eeb, 0x3393743e, 0xf35e8cf1,
  76344. 0xe54b64a7, 0x987da74a, 0x65cd449d, 0x557b322a, 0x37e7b15d,
  76345. 0x765082a5, 0xf2cd134f, 0x4d25c742, 0x4ccf0746, 0xae9d9c07,
  76346. 0x8728d135, 0x72fc2110 },
  76347. { 0xf96004c8, 0xa906b203, 0x458055ff, 0xd83f95cf, 0x55f35909,
  76348. 0xd77d5867, 0xe550c8ee, 0x4a9ea6fb, 0x55a06081, 0x91c8cca9,
  76349. 0xbce82062, 0x4a1fee78, 0x9a3df85e, 0xeb9ade06, 0x7d3de666,
  76350. 0xfbbdcf0c, 0x5d336d51, 0x228a391b, 0x5c2ffc3c, 0x760f8d28,
  76351. 0x2f7b165b, 0x1ee48de3, 0x56177040, 0x03803d84, 0x9deff9a0,
  76352. 0xe573f648, 0xa17e35a4, 0xe1a2738e, 0x8840a6c6, 0x238ef17c,
  76353. 0xb11ed92d, 0x480946f8 },
  76354. { 0xfd71f119, 0x84c747a8, 0x53eb3695, 0x19e65c5e, 0x6298587a,
  76355. 0x0e2f6786, 0xab18d6f4, 0x48a48899, 0xc630b8c0, 0xa1a99024,
  76356. 0x2caaf892, 0x84975096, 0xe20fd624, 0xc8869aba, 0x6c2b7dd4,
  76357. 0x3b72b04d, 0x0992f7d0, 0xe2775eb6, 0x7d06e684, 0x0089c06e,
  76358. 0xe4bbd007, 0xcb3b4361, 0x4ba846e4, 0xa1ae666b, 0x46464d9e,
  76359. 0xc01c2eb2, 0xc1f8539f, 0xf86f2be6, 0xcf68afc7, 0x16e8e8ae,
  76360. 0xc7386902, 0x8dab61fd },
  76361. { 0xd54d1d45, 0x42a5c903, 0xff4f9ba2, 0xacd4297e, 0x34d478b4,
  76362. 0x2d88b520, 0x08c4621a, 0x35b2ba2b, 0x34865402, 0xd3d239bb,
  76363. 0x911f32e6, 0x1de76aed, 0x3f06fdc2, 0x877f8bcf, 0x9ec51502,
  76364. 0x802714c1, 0xa590700d, 0xa10444eb, 0x31dcc957, 0x8694229f,
  76365. 0xb8169fed, 0x5ece77ab, 0x2caf080e, 0x55be8a15, 0xcbd7cef1,
  76366. 0x3eb21b14, 0x67b97ee1, 0x9def7ad1, 0x118f690c, 0xe03ca879,
  76367. 0xf99b29e7, 0x6f77e62d },
  76368. { 0xe40bbf59, 0xa271bded, 0x6401aad6, 0x177ba453, 0x73541cd1,
  76369. 0x1755e035, 0x4b71b02f, 0x3465b466, 0xa813359f, 0x22eb7113,
  76370. 0x6f38eac7, 0x9792a8fd, 0xff3bf3b5, 0x11aa012f, 0xf85c3fbf,
  76371. 0x99aafabf, 0x06c0cc42, 0x91e0a2ef, 0x773b7b3a, 0x314d5d57,
  76372. 0xd669840a, 0xae5e2e76, 0x2e5a8be6, 0x86136073, 0xc1cf5580,
  76373. 0xee6d7578, 0x68bed102, 0x2344e00f, 0x8184f0eb, 0x799d7886,
  76374. 0xc3d2cf80, 0x63819c91 },
  76375. { 0x7884b073, 0xca5392e1, 0xeb1267ea, 0x9ec3a1fc, 0x907038a7,
  76376. 0x3d07f5f0, 0xe4c47b70, 0xcb2ac07c, 0x1bf96b91, 0xf96664ee,
  76377. 0x2aea4fbf, 0xebf57589, 0xfade6500, 0x5aabf391, 0x171d1204,
  76378. 0xc5b3376f, 0xa0d3d81a, 0x1ff60c51, 0x976a844b, 0x10b2cfe7,
  76379. 0xbda6125a, 0xe131cc9a, 0x4ebd453e, 0xe0fc16d3, 0x504b6bc1,
  76380. 0xc0d0319a, 0x0a2f8cab, 0xe43a0be7, 0x55e49b47, 0xc80afeec,
  76381. 0x8265d7ee, 0x67d48d12 },
  76382. { 0xea2d56d6, 0x068d59a7, 0x27480a63, 0xd71abd0e, 0xae7366cd,
  76383. 0x6bd11db0, 0x07204ebc, 0xfbb639ca, 0xf77e6293, 0x89a242e7,
  76384. 0x75ba8c3d, 0xdee7ca2b, 0x64a2f9a8, 0x472ddc3d, 0x7561a010,
  76385. 0x84229df4, 0xc5b649d4, 0x95f62c85, 0x4dc927cd, 0xfdd56b1b,
  76386. 0x5ee60596, 0xfe8bb120, 0xabf29401, 0x3efcaa50, 0x10d1c184,
  76387. 0xd4900d0f, 0x28b01df5, 0x2cf113a9, 0x1f0e43f5, 0xa3d7ebc3,
  76388. 0xe8384dc7, 0x27950e38 },
  76389. { 0xe1d0fa79, 0xeab21ff0, 0x048b5de9, 0x4b9fd033, 0x2fe374cb,
  76390. 0x4c934689, 0x4eb21f6b, 0xbb4827fa, 0xa925e7e7, 0x46716f79,
  76391. 0x7dd4c531, 0x1442bf36, 0xd2e96ddf, 0x2073954c, 0x8502aa89,
  76392. 0x4e0141ae, 0x8eef6cc9, 0x8ee00e1a, 0x5880cdaf, 0x55ce8491,
  76393. 0x69628046, 0xff3aba5c, 0x5d15dfbf, 0x335cc4f8, 0x9f684f25,
  76394. 0xa7f0440c, 0xbb1e5bd8, 0xae80453f, 0xff2225ab, 0xa1c99813,
  76395. 0x79b25d71, 0x54ff7884 },
  76396. { 0xde40b068, 0x27c6ee30, 0xe6f3a51e, 0x9226465b, 0xfa3b21f6,
  76397. 0xe24a4604, 0xc0418115, 0x50a5a5ad, 0x8df90d2b, 0xe3285441,
  76398. 0xdcb0c00f, 0xbb74e58f, 0x4a2c08e3, 0xc68f1b3b, 0x0ccd9ec9,
  76399. 0x339df081, 0xb786ea9f, 0x915362dc, 0xc955aead, 0x28945e31,
  76400. 0x8b6a6c6b, 0xd6a2c01d, 0x3678a427, 0x069e82dc, 0x28c9302c,
  76401. 0x17875500, 0x9fa101e6, 0x8acda965, 0xee30b286, 0x4e4e4573,
  76402. 0x3f1830fe, 0x8adbad85 },
  76403. { 0x0969d524, 0x060ae11f, 0xf39bcc79, 0xf42fdaf7, 0x7cc1fcc2,
  76404. 0x3cec6766, 0xe2336d4f, 0x456b9cf2, 0x8e1c0f7f, 0x6aa1f5de,
  76405. 0x0984fb0e, 0xcdbc2ad2, 0x1b464b28, 0x4090cfa6, 0x1243f3ef,
  76406. 0x40d86f30, 0xcd5e87e7, 0x95b16ccc, 0x3026cd41, 0x403f168c,
  76407. 0x816c0730, 0xdbe386cb, 0x58407a1d, 0x14eb86f3, 0x1717e1af,
  76408. 0xf588b4f8, 0x66cbc96c, 0xb75c41a6, 0x027e71c1, 0xf342c1aa,
  76409. 0xc0945e5f, 0x73930036 },
  76410. { 0x22cdaf42, 0x954f757d, 0xf4181aab, 0x788b591d, 0xf5514f25,
  76411. 0x8b986819, 0xf18fd5bc, 0x69642e08, 0x022ceb91, 0x92b305d1,
  76412. 0x6a4f6985, 0x1715903e, 0x61179cae, 0x4bd7d69d, 0xd29c01aa,
  76413. 0xdacdfd5d, 0xd91108cc, 0x705ddd5a, 0x64ac8f15, 0x434ac7b1,
  76414. 0xb524632f, 0x61a514e1, 0x731fc447, 0x45b9e61b, 0xe0961b31,
  76415. 0xcf561348, 0x73eaf223, 0x9c28a967, 0xaa7c99d3, 0x5bd10182,
  76416. 0xe42965e2, 0x8bc6ec4a },
  76417. { 0xe7f2a32b, 0xd096e5c0, 0x09388a30, 0xff54800c, 0x401e360c,
  76418. 0x06fe437c, 0xbb6054a6, 0x6655fc9c, 0x8457aa6e, 0x510e1860,
  76419. 0x2b29b2b7, 0xa0acfca2, 0x51b7da61, 0x732483e3, 0x6be6c8ca,
  76420. 0xe31471ee, 0x8b65c9a1, 0xe565431c, 0x48d65cbb, 0xfc9ac3b9,
  76421. 0xae9b2aa8, 0xd308fc21, 0xaa60aa6a, 0xd6a7df0d, 0x982fc0d4,
  76422. 0x2844d96a, 0x5847a4d7, 0xab012c2c, 0xdceb8955, 0x2b3c8f71,
  76423. 0xbe9c7e15, 0x8e85437d },
  76424. };
  76425. /* Perform the modular exponentiation in Fp* for SAKKE.
  76426. *
  76427. * Base is fixed to be the g parameter - a precomputed table is used.
  76428. *
  76429. * Striping: 128 points at a distance of 8 combined.
  76430. * Total of 256 points in table.
  76431. * Square and multiply performed in Fp*.
  76432. *
  76433. * base [in] Base. MP integer.
  76434. * exp [in] Exponent. MP integer.
  76435. * res [out] Result. MP integer.
  76436. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  76437. * and MEMORY_E if memory allocation fails.
  76438. */
  76439. int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res)
  76440. {
  76441. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76442. defined(WOLFSSL_SP_SMALL_STACK)
  76443. sp_digit* td;
  76444. sp_digit* t;
  76445. sp_digit* tx;
  76446. sp_digit* ty;
  76447. #else
  76448. sp_digit t[36 * 2 * 32];
  76449. sp_digit tx[2 * 32];
  76450. sp_digit ty[2 * 32];
  76451. #endif
  76452. sp_digit* r = NULL;
  76453. unsigned char e[128];
  76454. int err = MP_OKAY;
  76455. int i;
  76456. int y;
  76457. (void)base;
  76458. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76459. defined(WOLFSSL_SP_SMALL_STACK)
  76460. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 38 * 32 * 2, NULL,
  76461. DYNAMIC_TYPE_TMP_BUFFER);
  76462. if (td == NULL) {
  76463. err = MEMORY_E;
  76464. }
  76465. #endif
  76466. if (err == MP_OKAY) {
  76467. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76468. defined(WOLFSSL_SP_SMALL_STACK)
  76469. t = td;
  76470. tx = td + 36 * 32 * 2;
  76471. ty = td + 37 * 32 * 2;
  76472. #endif
  76473. r = ty;
  76474. (void)mp_to_unsigned_bin_len(exp, e, 128);
  76475. XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32);
  76476. y = e[112] >> 7;
  76477. y |= (e[96] >> 7) << 1;
  76478. y |= (e[80] >> 7) << 2;
  76479. y |= (e[64] >> 7) << 3;
  76480. y |= (e[48] >> 7) << 4;
  76481. y |= (e[32] >> 7) << 5;
  76482. y |= (e[16] >> 7) << 6;
  76483. y |= (e[0] >> 7) << 7;
  76484. XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 32);
  76485. for (i = 126; i >= 0; i--) {
  76486. y = (e[127 - (i / 8)] >> (i & 0x7)) & 1;
  76487. y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1;
  76488. y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2;
  76489. y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3;
  76490. y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4;
  76491. y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5;
  76492. y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6;
  76493. y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7;
  76494. sp_1024_proj_sqr_32(tx, ty, t);
  76495. sp_1024_proj_mul_qx1_32(tx, ty, sp_1024_g_table[y], t);
  76496. }
  76497. }
  76498. if (err == MP_OKAY) {
  76499. sp_1024_mont_inv_32(tx, tx, t);
  76500. sp_1024_mont_mul_32(r, tx, ty, p1024_mod, p1024_mp_mod);
  76501. XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
  76502. sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
  76503. err = sp_1024_to_mp(r, res);
  76504. }
  76505. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76506. defined(WOLFSSL_SP_SMALL_STACK)
  76507. if (td != NULL) {
  76508. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  76509. }
  76510. #endif
  76511. return err;
  76512. }
  76513. #endif /* WOLFSSL_SP_SMALL */
  76514. /* Multiply p* by q* in projective coordinates.
  76515. *
  76516. * p.x' = (p.x * q.x) - (p.y * q.y)
  76517. * p.y' = (p.x * q.y) + (p.y * q.x)
  76518. * But applying Karatsuba:
  76519. * v0 = p.x * q.x
  76520. * v1 = p.y * q.y
  76521. * p.x' = v0 - v1
  76522. * p.y' = (px + py) * (qx + qy) - v0 - v1
  76523. *
  76524. * px [in,out] A single precision integer - X ordinate of number to multiply.
  76525. * py [in,out] A single precision integer - Y ordinate of number to multiply.
  76526. * qx [in] A single precision integer - X ordinate of number of
  76527. * multiplier.
  76528. * qy [in] A single precision integer - Y ordinate of number of
  76529. * multiplier.
  76530. * t [in] Two single precision integers - temps.
  76531. */
  76532. static void sp_1024_proj_mul_32(sp_digit* px, sp_digit* py,
  76533. const sp_digit* qx, const sp_digit* qy, sp_digit* t)
  76534. {
  76535. sp_digit* t1 = t;
  76536. sp_digit* t2 = t + 2 * 32;
  76537. /* t1 = px + py */
  76538. sp_1024_mont_add_32(t1, px, py, p1024_mod);
  76539. /* t2 = qx + qy */
  76540. sp_1024_mont_add_32(t2, qx, qy, p1024_mod);
  76541. /* t2 = (px + py) * (qx + qy) */
  76542. sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod);
  76543. /* t1 = py * qy */
  76544. sp_1024_mont_mul_32(t1, py, qy, p1024_mod, p1024_mp_mod);
  76545. /* t2 = (px + py) * (qx + qy) - (py * qy) */
  76546. sp_1024_mont_sub_32(t2, t2, t1, p1024_mod);
  76547. /* px = px * qx */
  76548. sp_1024_mont_mul_32(px, px, qx, p1024_mod, p1024_mp_mod);
  76549. /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */
  76550. sp_1024_mont_sub_32(py, t2, px, p1024_mod);
  76551. /* px = (px * qx) - (py * qy)*/
  76552. sp_1024_mont_sub_32(px, px, t1, p1024_mod);
  76553. }
  76554. #ifndef WOLFSSL_SP_SMALL
  76555. /*
  76556. * Convert point from projective to affine but keep in Montgomery form.
  76557. *
  76558. * p [in,out] Point to convert.
  76559. * t [in] Temporary numbers: 2.
  76560. */
  76561. static void sp_1024_mont_map_32(sp_point_1024* p, sp_digit* t)
  76562. {
  76563. sp_digit* t1 = t;
  76564. sp_digit* t2 = t + 2 * 32;
  76565. sp_1024_mont_inv_32(t1, p->z, t2);
  76566. sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod);
  76567. sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod);
  76568. sp_1024_mont_mul_32(p->x, p->x, t2, p1024_mod, p1024_mp_mod);
  76569. sp_1024_mont_mul_32(p->y, p->y, t1, p1024_mod, p1024_mp_mod);
  76570. XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 32);
  76571. }
  76572. #endif /* WOLFSSL_SP_SMALL */
  76573. /*
  76574. * Calculate gradient of line through P, P and [-2]P, accumulate line and
  76575. * double P.
  76576. *
  76577. * Calculations:
  76578. * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
  76579. * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2
  76580. * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
  76581. * v* = v*^2 * r*
  76582. * p'.x = l^2 - 8 * p.y^2 * p.x
  76583. * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4
  76584. * p'.z = 2 * p.y * p.z
  76585. *
  76586. * @param [in,out] vx X-ordinate of projective value in F*.
  76587. * @param [in,out] vy Y-ordinate of projective value in F*.
  76588. * @param [in,out] p ECC point - point on E(F_p^2) to double.
  76589. * @param [in] q ECC point - second point on E(F_P^2).
  76590. * @param [in] t SP temporaries (6 used).
  76591. */
  76592. static void sp_1024_accumulate_line_dbl_32(sp_digit* vx, sp_digit* vy,
  76593. sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
  76594. {
  76595. sp_digit* t1 = t + 0 * 32;
  76596. sp_digit* pz2 = t + 2 * 32;
  76597. sp_digit* rx = t + 4 * 32;
  76598. sp_digit* ry = t + 6 * 32;
  76599. sp_digit* l = t + 8 * 32;
  76600. sp_digit* ty = t + 10 * 32;
  76601. /* v = v^2 */
  76602. sp_1024_proj_sqr_32(vx, vy, t);
  76603. /* pz2 = p.z^2 */
  76604. sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod);
  76605. /* t1 = p.x + p.z^2 */
  76606. sp_1024_mont_add_32(ty, p->x, pz2, p1024_mod);
  76607. /* l = p.x - p.z^2 */
  76608. sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod);
  76609. /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
  76610. sp_1024_mont_mul_32(t1, l, ty, p1024_mod, p1024_mp_mod);
  76611. /* l = 3 * (p.x^2 - p.z^4) */
  76612. sp_1024_mont_tpl_32(l, t1, p1024_mod);
  76613. /* t1 = q.x * p.z^2 */
  76614. sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
  76615. /* t1 = p.x + q.x * p.z^2 */
  76616. sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
  76617. /* r.x = l * (p.x + q.x * p.z^2) */
  76618. sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod);
  76619. /* r.y = 2 * p.y */
  76620. sp_1024_mont_dbl_32(ry, p->y, p1024_mod);
  76621. /* ty = 4 * p.y ^ 2 */
  76622. sp_1024_mont_sqr_32(ty, ry, p1024_mod, p1024_mp_mod);
  76623. /* t1 = 2 * p.y ^ 2 */
  76624. sp_1024_mont_div2_32(t1, ty, p1024_mod);
  76625. /* r.x -= 2 * (p.y ^ 2) */
  76626. sp_1024_mont_sub_32(rx, rx, t1, p1024_mod);
  76627. /* p'.z = p.y * 2 * p.z */
  76628. sp_1024_mont_mul_32(p->z, p->z, ry, p1024_mod, p1024_mp_mod);
  76629. /* r.y = p'.z * p.z^2 */
  76630. sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
  76631. /* r.y = p'.z * p.z^2 * q.y */
  76632. sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod);
  76633. /* v = v^2 * r */
  76634. sp_1024_proj_mul_32(vx, vy, rx, ry, t);
  76635. /* Double point using previously calculated values
  76636. * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
  76637. * ty = 4 * p.y^2
  76638. * p'.z = 2 * p.y * p.z
  76639. */
  76640. /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */
  76641. sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod);
  76642. /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */
  76643. sp_1024_mont_div2_32(t1, t1, p1024_mod);
  76644. /* p'.y = 4 * p.y^2 * p.x */
  76645. sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
  76646. /* p'.x = l^2 */
  76647. sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod);
  76648. /* p'.x = l^2 - 4 * p.y^2 * p.x */
  76649. sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
  76650. /* p'.x = l^2 - 8 * p.y^2 * p.x */
  76651. sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
  76652. /* p'.y = 4 * p.y^2 * p.x - p.x' */
  76653. sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod);
  76654. /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */
  76655. sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod);
  76656. /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */
  76657. sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod);
  76658. }
  76659. #ifdef WOLFSSL_SP_SMALL
  76660. /*
  76661. * Calculate gradient of line through C, P and -C-P, accumulate line and
  76662. * add P to C.
  76663. *
  76664. * Calculations:
  76665. * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z
  76666. * r.y = (c.x - p.x * c.z^2) * q.y * c.z
  76667. * v* = v* * r*
  76668. * r = p.y * c.z^3 - c.y
  76669. * c'.x = r^2 + h^3 - 2 * c.x * h^2
  76670. * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3
  76671. * c'.z = (c.x - p.x * c.z^2) * c.z
  76672. *
  76673. * @param [in,out] vx X-ordinate of projective value in F*.
  76674. * @param [in,out] vy Y-ordinate of projective value in F*.
  76675. * @param [in,out] c ECC point - current point on E(F_p^2) to be added
  76676. * to.
  76677. * @param [in] p ECC point - point on E(F_p^2) to add.
  76678. * @param [in] q ECC point - second point on E(F_P^2).
  76679. * @param [in] qx_px SP that is a constant value across adds.
  76680. * @param [in] t SP temporaries (6 used).
  76681. */
  76682. static void sp_1024_accumulate_line_add_one_32(sp_digit* vx, sp_digit* vy,
  76683. sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px,
  76684. sp_digit* t)
  76685. {
  76686. sp_digit* t1 = t;
  76687. sp_digit* t2 = t + 2 * 32;
  76688. sp_digit* rx = t + 4 * 32;
  76689. sp_digit* ry = t + 6 * 32;
  76690. sp_digit* h = t + 8 * 32;
  76691. sp_digit* r = t + 10 * 32;
  76692. /* r.x = (q.x + p.x) * c.y */
  76693. sp_1024_mont_mul_32(rx, qx_px, c->y, p1024_mod, p1024_mp_mod);
  76694. /* t2 = c.z^2 */
  76695. sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod);
  76696. /* t1 = q.x * c.z^2 */
  76697. sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod);
  76698. /* t1 = q.x * c.z^2 + c.x */
  76699. sp_1024_mont_add_32(h, t1, c->x, p1024_mod);
  76700. /* r = p.y * c.z */
  76701. sp_1024_mont_mul_32(ry, p->y, c->z, p1024_mod, p1024_mp_mod);
  76702. /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
  76703. sp_1024_mont_mul_32(t1, h, ry, p1024_mod, p1024_mp_mod);
  76704. /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */
  76705. sp_1024_mont_mul_32(r, ry, t2, p1024_mod, p1024_mp_mod);
  76706. /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
  76707. sp_1024_mont_sub_32(rx, rx, t1, p1024_mod);
  76708. /* t1 = p.x * c.z^2 */
  76709. sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod);
  76710. /* h = c.x - p.x * c.z^2 */
  76711. sp_1024_mont_sub_32(h, c->x, t1, p1024_mod);
  76712. /* c'.z = (c.x - p.x * c.z^2) * c.z */
  76713. sp_1024_mont_mul_32(c->z, h, c->z, p1024_mod, p1024_mp_mod);
  76714. /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */
  76715. sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
  76716. /* v = v * r */
  76717. sp_1024_proj_mul_32(vx, vy, rx, ry, t);
  76718. /* Add p to c using previously calculated values.
  76719. * h = c.x - p.x * c.z^2
  76720. * r = p.y * c.z^3
  76721. * c'.z = (c.x - p.x * c.z^2) * c.z
  76722. */
  76723. /* r = p.y * c.z^3 - c.y */
  76724. sp_1024_mont_sub_32(r, r, c->y, p1024_mod);
  76725. /* t1 = r^2 */
  76726. sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod);
  76727. /* t2 = h^2 */
  76728. sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod);
  76729. /* ry = c.x * h^2 */
  76730. sp_1024_mont_mul_32(ry, c->x, rx, p1024_mod, p1024_mp_mod);
  76731. /* t2 = h^3 */
  76732. sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod);
  76733. /* c->x = r^2 + h^3 */
  76734. sp_1024_mont_add_32(c->x, t1, t2, p1024_mod);
  76735. /* t1 = 2 * c.x * h^2 */
  76736. sp_1024_mont_dbl_32(t1, ry, p1024_mod);
  76737. /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */
  76738. sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod);
  76739. /* ry = c'.x - c.x * h^2 */
  76740. sp_1024_mont_sub_32(t1, c->x, ry, p1024_mod);
  76741. /* ry = r * (c'.x - c.x * h^2) */
  76742. sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
  76743. /* t2 = c.y * h^3 */
  76744. sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod);
  76745. /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */
  76746. sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod);
  76747. }
  76748. /*
  76749. * Calculate r = pairing <P, Q>.
  76750. *
  76751. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  76752. *
  76753. * @param [in] key SAKKE key.
  76754. * @param [in] p First point on E(F_p)[q].
  76755. * @param [in] q Second point on E(F_p)[q].
  76756. * @param [in] r Result of calculation.
  76757. * @return 0 on success.
  76758. * @return MEMORY_E when dynamic memory allocation fails.
  76759. * @return Other -ve value on internal failure.
  76760. */
  76761. int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
  76762. {
  76763. int err = MP_OKAY;
  76764. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76765. defined(WOLFSSL_SP_SMALL_STACK)
  76766. sp_digit* td = NULL;
  76767. sp_digit* t;
  76768. sp_digit* vx;
  76769. sp_digit* vy;
  76770. sp_digit* qx_px;
  76771. #else
  76772. sp_digit t[36 * 2 * 32];
  76773. sp_digit vx[2 * 32];
  76774. sp_digit vy[2 * 32];
  76775. sp_digit qx_px[2 * 32];
  76776. sp_point_1024 pd;
  76777. sp_point_1024 qd;
  76778. sp_point_1024 cd;
  76779. #endif
  76780. sp_point_1024* p = NULL;
  76781. sp_point_1024* q = NULL;
  76782. sp_point_1024* c = NULL;
  76783. sp_digit* r = NULL;
  76784. int i;
  76785. err = sp_1024_point_new_32(NULL, pd, p);
  76786. if (err == MP_OKAY) {
  76787. err = sp_1024_point_new_32(NULL, qd, q);
  76788. }
  76789. if (err == MP_OKAY) {
  76790. err = sp_1024_point_new_32(NULL, cd, c);
  76791. }
  76792. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76793. defined(WOLFSSL_SP_SMALL_STACK)
  76794. if (err == MP_OKAY) {
  76795. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 32 * 2, NULL,
  76796. DYNAMIC_TYPE_TMP_BUFFER);
  76797. if (td == NULL) {
  76798. err = MEMORY_E;
  76799. }
  76800. }
  76801. #endif
  76802. if (err == MP_OKAY) {
  76803. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76804. defined(WOLFSSL_SP_SMALL_STACK)
  76805. t = td;
  76806. vx = td + 36 * 32 * 2;
  76807. vy = td + 37 * 32 * 2;
  76808. qx_px = td + 38 * 32 * 2;
  76809. #endif
  76810. r = vy;
  76811. sp_1024_point_from_ecc_point_32(p, pm);
  76812. sp_1024_point_from_ecc_point_32(q, qm);
  76813. err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
  76814. }
  76815. if (err == MP_OKAY) {
  76816. err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
  76817. }
  76818. if (err == MP_OKAY) {
  76819. err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
  76820. }
  76821. if (err == MP_OKAY) {
  76822. err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
  76823. }
  76824. if (err == MP_OKAY) {
  76825. err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
  76826. }
  76827. if (err == MP_OKAY) {
  76828. XMEMCPY(c, p, sizeof(sp_point_1024));
  76829. XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
  76830. vx[0] = 1;
  76831. XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
  76832. sp_1024_mont_add_32(qx_px, q->x, p->x, p1024_mod);
  76833. for (i = 1020; i >= 0; i--) {
  76834. /* Accumulate line into v and double point. */
  76835. sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
  76836. if ((i > 0) && ((p1024_order[i / 32] >> (i % 32)) & 1)) {
  76837. /* Accumulate line into v and add P into C. */
  76838. sp_1024_accumulate_line_add_one_32(vx, vy, c, p, q, qx_px, t);
  76839. }
  76840. }
  76841. /* Final exponentiation */
  76842. sp_1024_proj_sqr_32(vx, vy, t);
  76843. sp_1024_proj_sqr_32(vx, vy, t);
  76844. /* Convert from PF_p[q] to F_p */
  76845. sp_1024_mont_inv_32(vx, vx, t);
  76846. sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
  76847. XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
  76848. sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
  76849. err = sp_1024_to_mp(r, res);
  76850. }
  76851. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  76852. defined(WOLFSSL_SP_SMALL_STACK)
  76853. if (td != NULL) {
  76854. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  76855. }
  76856. #endif
  76857. sp_1024_point_free_32(c, 1, NULL);
  76858. sp_1024_point_free_32(q, 1, NULL);
  76859. sp_1024_point_free_32(p, 1, NULL);
  76860. return err;
  76861. }
  76862. #else
  76863. /*
  76864. * Calculate gradient of line through C, P and -C-P, accumulate line and
  76865. * add P to C.
  76866. *
  76867. * Both C and P have z ordinates to use in the calculation.
  76868. *
  76869. * Calculations:
  76870. * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
  76871. * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
  76872. * v* = v* * r*
  76873. * h = p.x * c.z^2 - c.x * p.z^2
  76874. * r = p.y * c.z^3 - c.y * p.z^3
  76875. * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
  76876. * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
  76877. * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
  76878. *
  76879. * @param [in,out] vx X-ordinate of projective value in F*.
  76880. * @param [in,out] vy Y-ordinate of projective value in F*.
  76881. * @param [in,out] c ECC point - current point on E(F_p^2) to be added
  76882. * to.
  76883. * @param [in,out] p ECC point - point on E(F_p^2) to add.
  76884. * @param [in,out] q ECC point - second point on E(F_P^2).
  76885. * @param [in,out] t SP temporaries (6 used).
  76886. * @param [in,out] neg Indicates to use negative P.
  76887. * @return 0 on success.
  76888. * @return MEMORY_E when dynamic memory allocation fails.
  76889. * @return Other -ve value on internal failure.
  76890. */
  76891. static void sp_1024_accumulate_line_add_n_32(sp_digit* vx, sp_digit* vy,
  76892. const sp_point_1024* p, const sp_point_1024* q,
  76893. sp_point_1024* c, sp_digit* t, int neg)
  76894. {
  76895. sp_digit* t1 = t;
  76896. sp_digit* t2 = t + 2 * 32;
  76897. sp_digit* rx = t + 4 * 32;
  76898. sp_digit* ry = t + 6 * 32;
  76899. sp_digit* h = t + 8 * 32;
  76900. sp_digit* r = t + 10 * 32;
  76901. /* h = p.z^2 */
  76902. sp_1024_mont_sqr_32(h, p->z, p1024_mod, p1024_mp_mod);
  76903. /* rx = q.x * p.z^2 */
  76904. sp_1024_mont_mul_32(rx, q->x, h, p1024_mod, p1024_mp_mod);
  76905. /* rx = q.x * p.z^2 + p.x */
  76906. sp_1024_mont_add_32(t2, rx, p->x, p1024_mod);
  76907. /* c.y = c.y * p.z */
  76908. sp_1024_mont_mul_32(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
  76909. /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
  76910. sp_1024_mont_mul_32(rx, t2, t1, p1024_mod, p1024_mp_mod);
  76911. /* c.y = c.y * p.z^3 */
  76912. sp_1024_mont_mul_32(c->y, t1, h, p1024_mod, p1024_mp_mod);
  76913. /* t2 = c.z^2 */
  76914. sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod);
  76915. /* t1 = q.x * c.z^2 */
  76916. sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod);
  76917. /* t1 = q.x * c.z^2 + c.x */
  76918. sp_1024_mont_add_32(t1, t1, c->x, p1024_mod);
  76919. /* c.x = c.x * p.z^2 */
  76920. sp_1024_mont_mul_32(c->x, c->x, h, p1024_mod, p1024_mp_mod);
  76921. /* r = p.y * c.z */
  76922. sp_1024_mont_mul_32(r, p->y, c->z, p1024_mod, p1024_mp_mod);
  76923. if (neg) {
  76924. /* r = -p.y * c.z */
  76925. sp_1024_mont_sub_32(r, p1024_mod, r, p1024_mod);
  76926. }
  76927. /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
  76928. sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
  76929. /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
  76930. sp_1024_mont_sub_32(rx, ry, rx, p1024_mod);
  76931. /* t1 = p.x * c.z^2 */
  76932. sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod);
  76933. /* h = p.x * c.z^2 - c.x * p.z^2 */
  76934. sp_1024_mont_sub_32(h, t1, c->x, p1024_mod);
  76935. /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
  76936. sp_1024_mont_mul_32(t1, h, c->z, p1024_mod, p1024_mp_mod);
  76937. /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
  76938. sp_1024_mont_mul_32(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
  76939. /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
  76940. sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
  76941. /* r = p.y * c.z^3 */
  76942. sp_1024_mont_mul_32(t1, r, t2, p1024_mod, p1024_mp_mod);
  76943. /* r = p.y * c.z^3 - c.y * p.z^3 */
  76944. sp_1024_mont_sub_32(r, t1, c->y, p1024_mod);
  76945. /* v = v * r */
  76946. sp_1024_proj_mul_32(vx, vy, rx, ry, t);
  76947. /* Add p to c using previously calculated values.
  76948. * h = p.x * c.z^2 - c.x * p.z^2
  76949. * r = p.y * c.z^3 - c.y * p.z^3
  76950. * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
  76951. */
  76952. /* t1 = r^2 */
  76953. sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod);
  76954. /* t2 = h^2 */
  76955. sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod);
  76956. /* ry = c.x * p.z^2 * h^2 */
  76957. sp_1024_mont_mul_32(ry, rx, c->x, p1024_mod, p1024_mp_mod);
  76958. /* t2 = h^3 */
  76959. sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod);
  76960. /* c'.x = r^2 - h^3 */
  76961. sp_1024_mont_sub_32(c->x, t1, t2, p1024_mod);
  76962. /* t1 = 2 * c.x * p.z^2 * h^2 */
  76963. sp_1024_mont_dbl_32(t1, ry, p1024_mod);
  76964. /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
  76965. sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod);
  76966. /* ry = c.x * p.z^2 * h^2 - c'.x */
  76967. sp_1024_mont_sub_32(t1, ry, c->x, p1024_mod);
  76968. /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
  76969. sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod);
  76970. /* t2 = c.y * p.z^3 * h^3 */
  76971. sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod);
  76972. /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
  76973. sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod);
  76974. }
  76975. /*
  76976. * Perform n accumulate doubles and doubles of P.
  76977. *
  76978. * py = 2 * p.y
  76979. *
  76980. * For each double:
  76981. * Calculate gradient of line through P, P and [-2]P, accumulate line and
  76982. * double P.
  76983. *
  76984. * Calculations:
  76985. * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
  76986. * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
  76987. * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
  76988. * v* = v*^2 * r*
  76989. * p'.x = l^2 - 2 * py^2 * p.x
  76990. * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
  76991. * p'.z = py * p.z
  76992. *
  76993. * Finally:
  76994. * p'.y = py' / 2
  76995. *
  76996. * @param [in,out] vx X-ordinate of projective value in F*.
  76997. * @param [in,out] vy Y-ordinate of projective value in F*.
  76998. * @param [in,out] p ECC point - point on E(F_p^2) to double.
  76999. * @param [in] q ECC point - second point on E(F_P^2).
  77000. * @param [in] n Number of times to double.
  77001. * @param [in] t SP temporaries (6 used).
  77002. */
  77003. static void sp_1024_accumulate_line_dbl_n_32(sp_digit* vx, sp_digit* vy,
  77004. sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
  77005. {
  77006. sp_digit* t1 = t + 0 * 32;
  77007. sp_digit* pz2 = t + 2 * 32;
  77008. sp_digit* rx = t + 4 * 32;
  77009. sp_digit* ry = t + 6 * 32;
  77010. sp_digit* l = t + 8 * 32;
  77011. sp_digit* ty = t + 10 * 32;
  77012. int i;
  77013. /* py = 2 * p.y */
  77014. sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
  77015. for (i = 0; i < n; i++) {
  77016. /* v = v^2 */
  77017. sp_1024_proj_sqr_32(vx, vy, t);
  77018. /* pz2 = p.z^2 */
  77019. sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod);
  77020. /* t1 = p.x + p.z^2 */
  77021. sp_1024_mont_add_32(t1, p->x, pz2, p1024_mod);
  77022. /* l = p.x - p.z^2 */
  77023. sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod);
  77024. /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
  77025. sp_1024_mont_mul_32(ty, l, t1, p1024_mod, p1024_mp_mod);
  77026. /* l = 3 * (p.x^2 - p.z^4) */
  77027. sp_1024_mont_tpl_32(l, ty, p1024_mod);
  77028. /* t1 = q.x * p.z^2 */
  77029. sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
  77030. /* t1 = p.x + q.x * p.z^2 */
  77031. sp_1024_mont_add_32(t1, p->x, t1, p1024_mod);
  77032. /* r.x = l * (p.x + q.x * p.z^2) */
  77033. sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod);
  77034. /* ty = py ^ 2 */
  77035. sp_1024_mont_sqr_32(ty, p->y, p1024_mod, p1024_mp_mod);
  77036. /* t1 = py ^ 2 / 2 */
  77037. sp_1024_mont_div2_32(t1, ty, p1024_mod);
  77038. /* r.x -= py ^ 2 / 2 */
  77039. sp_1024_mont_sub_32(rx, rx, t1, p1024_mod);
  77040. /* p'.z = py * pz */
  77041. sp_1024_mont_mul_32(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
  77042. /* r.y = p'.z * p.z^2 */
  77043. sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
  77044. /* r.y = p'.z * p.z^2 * q.y */
  77045. sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod);
  77046. /* v = v^2 * r */
  77047. sp_1024_proj_mul_32(vx, vy, rx, ry, t);
  77048. /* Double point using previously calculated values
  77049. * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
  77050. * ty = py^2
  77051. * p'.z = py * p.z
  77052. */
  77053. /* t1 = py^2 ^ 2 = py^4 */
  77054. sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod);
  77055. /* py' = py^2 * p. x */
  77056. sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
  77057. /* p'.x = l^2 */
  77058. sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod);
  77059. /* p'.x = l^2 - py^2 * p.x */
  77060. sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
  77061. /* p'.x = l^2 - 2 * p.y^2 * p.x */
  77062. sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod);
  77063. /* py' = py^2 * p.x - p.x' */
  77064. sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod);
  77065. /* py' = (p.y^2 * p.x - p'.x) * l */
  77066. sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod);
  77067. /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
  77068. sp_1024_mont_dbl_32(p->y, p->y, p1024_mod);
  77069. /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
  77070. sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod);
  77071. }
  77072. /* p'.y = py' / 2 */
  77073. sp_1024_mont_div2_32(p->y, p->y, p1024_mod);
  77074. }
  77075. /* Operations to perform based on order - 1.
  77076. * Sliding window. Start at bottom and stop when bottom bit is one.
  77077. * Subtract if top bit in window is one.
  77078. * Width of 6 bits.
  77079. * Pairs: #dbls, add/subtract window value
  77080. */
  77081. static const signed char sp_1024_order_op[] = {
  77082. 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
  77083. -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
  77084. -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
  77085. 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
  77086. -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
  77087. -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
  77088. -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
  77089. -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
  77090. -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
  77091. 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
  77092. -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
  77093. -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
  77094. 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
  77095. -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
  77096. 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
  77097. -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
  77098. 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
  77099. -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
  77100. -3, 1,
  77101. };
  77102. /*
  77103. * Calculate r = pairing <P, Q>.
  77104. *
  77105. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  77106. *
  77107. * Sliding window. Start at bottom and stop when bottom bit is one.
  77108. * Subtract if top bit in window is one.
  77109. * Width of 6 bits.
  77110. *
  77111. * @param [in] pm First point on E(F_p)[q].
  77112. * @param [in] qm Second point on E(F_p)[q].
  77113. * @param [in] res Result of calculation.
  77114. * @return 0 on success.
  77115. * @return MEMORY_E when dynamic memory allocation fails.
  77116. */
  77117. int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
  77118. {
  77119. int err;
  77120. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77121. defined(WOLFSSL_SP_SMALL_STACK)
  77122. sp_digit* td = NULL;
  77123. sp_digit* t;
  77124. sp_digit* vx;
  77125. sp_digit* vy;
  77126. sp_digit (*pre_vx)[64];
  77127. sp_digit (*pre_vy)[64];
  77128. sp_digit (*pre_nvy)[64];
  77129. sp_point_1024* pre_p;
  77130. #else
  77131. sp_digit t[36 * 2 * 32];
  77132. sp_digit vx[2 * 32];
  77133. sp_digit vy[2 * 32];
  77134. sp_digit pre_vx[16][64];
  77135. sp_digit pre_vy[16][64];
  77136. sp_digit pre_nvy[16][64];
  77137. sp_point_1024 pre_p[16];
  77138. sp_point_1024 pd;
  77139. sp_point_1024 qd;
  77140. sp_point_1024 cd;
  77141. #endif
  77142. sp_point_1024* p = NULL;
  77143. sp_point_1024* q = NULL;
  77144. sp_point_1024* c = NULL;
  77145. sp_digit* r = NULL;
  77146. int i;
  77147. int j;
  77148. err = sp_1024_point_new_32(NULL, pd, p);
  77149. if (err == MP_OKAY) {
  77150. err = sp_1024_point_new_32(NULL, qd, q);
  77151. }
  77152. if (err == MP_OKAY) {
  77153. err = sp_1024_point_new_32(NULL, cd, c);
  77154. }
  77155. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77156. defined(WOLFSSL_SP_SMALL_STACK)
  77157. if (err == MP_OKAY) {
  77158. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL,
  77159. DYNAMIC_TYPE_TMP_BUFFER);
  77160. if (td == NULL) {
  77161. err = MEMORY_E;
  77162. }
  77163. }
  77164. #endif
  77165. if (err == MP_OKAY) {
  77166. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77167. defined(WOLFSSL_SP_SMALL_STACK)
  77168. t = td;
  77169. vx = td + 36 * 32 * 2;
  77170. vy = td + 37 * 32 * 2;
  77171. pre_vx = (sp_digit(*)[64])(td + 38 * 32 * 2);
  77172. pre_vy = (sp_digit(*)[64])(td + 54 * 32 * 2);
  77173. pre_nvy = (sp_digit(*)[64])(td + 70 * 32 * 2);
  77174. pre_p = (sp_point_1024*)(td + 86 * 32 * 2);
  77175. #endif
  77176. r = vy;
  77177. sp_1024_point_from_ecc_point_32(p, pm);
  77178. sp_1024_point_from_ecc_point_32(q, qm);
  77179. err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
  77180. }
  77181. if (err == MP_OKAY) {
  77182. err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
  77183. }
  77184. if (err == MP_OKAY) {
  77185. err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
  77186. }
  77187. if (err == MP_OKAY) {
  77188. err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
  77189. }
  77190. if (err == MP_OKAY) {
  77191. err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
  77192. }
  77193. if (err == MP_OKAY) {
  77194. /* Generate pre-computation table: 1, 3, ... , 31 */
  77195. XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
  77196. XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
  77197. pre_vx[0][0] = 1;
  77198. XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
  77199. sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
  77200. /* [2]P for adding */
  77201. XMEMCPY(c, p, sizeof(sp_point_1024));
  77202. XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
  77203. vx[0] = 1;
  77204. XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
  77205. sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
  77206. /* 3, 5, ... */
  77207. for (i = 1; i < 16; i++) {
  77208. XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
  77209. XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
  77210. XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
  77211. sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
  77212. sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
  77213. q, &pre_p[i], t, 0);
  77214. sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
  77215. }
  77216. j = sp_1024_order_op[0] / 2;
  77217. XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
  77218. XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
  77219. XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
  77220. /* Accumulate line into v and double point n times. */
  77221. sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
  77222. sp_1024_order_op[1], t);
  77223. for (i = 2; i < 290; i += 2) {
  77224. j = sp_1024_order_op[i];
  77225. if (j > 0) {
  77226. j /= 2;
  77227. /* Accumulate line into v and add P into C. */
  77228. sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
  77229. sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
  77230. t, 0);
  77231. }
  77232. else {
  77233. j = -j / 2;
  77234. /* Accumulate line into v and add P into C. */
  77235. sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
  77236. sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c,
  77237. t, 1);
  77238. }
  77239. /* Accumulate line into v and double point n times. */
  77240. sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q,
  77241. sp_1024_order_op[i + 1], t);
  77242. }
  77243. /* Final exponentiation */
  77244. sp_1024_proj_sqr_32(vx, vy, t);
  77245. sp_1024_proj_sqr_32(vx, vy, t);
  77246. /* Convert from PF_p[q] to F_p */
  77247. sp_1024_mont_inv_32(vx, vx, t);
  77248. sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
  77249. XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
  77250. sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
  77251. err = sp_1024_to_mp(r, res);
  77252. }
  77253. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77254. defined(WOLFSSL_SP_SMALL_STACK)
  77255. if (td != NULL) {
  77256. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  77257. }
  77258. #endif
  77259. sp_1024_point_free_32(c, 1, NULL);
  77260. sp_1024_point_free_32(q, 1, NULL);
  77261. sp_1024_point_free_32(p, 1, NULL);
  77262. return err;
  77263. }
  77264. #endif /* WOLFSSL_SP_SMALL */
  77265. #ifdef WOLFSSL_SP_SMALL
  77266. /*
  77267. * Generate table for pairing.
  77268. *
  77269. * Small implementation does not use a table - returns 0 length.
  77270. *
  77271. * pm [in] Point to generate table for.
  77272. * table [in] Generated table.
  77273. * len [in,out] On in, the size of the buffer.
  77274. * On out, length of table generated.
  77275. * @return 0 on success.
  77276. * LENGTH_ONLY_E when table is NULL and only length returned.
  77277. * BUFFER_E when len is too small.
  77278. */
  77279. int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
  77280. word32* len)
  77281. {
  77282. int err = 0;
  77283. if (table == NULL) {
  77284. *len = 0;
  77285. err = LENGTH_ONLY_E;
  77286. }
  77287. else if (*len != 0) {
  77288. err = BUFFER_E;
  77289. }
  77290. (void)*pm;
  77291. return err;
  77292. }
  77293. /*
  77294. * Calculate r = pairing <P, Q>.
  77295. *
  77296. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  77297. *
  77298. * Small implementation does not use a table - use the normal implementation.
  77299. *
  77300. * @param [in] pm First point on E(F_p)[q].
  77301. * @param [in] qm Second point on E(F_p)[q].
  77302. * @param [in] res Result of calculation.
  77303. * @param [in] table Precomputed table of values.
  77304. * @param [in] len Length of precomputed table of values in bytes.
  77305. * @return 0 on success.
  77306. * @return MEMORY_E when dynamic memory allocation fails.
  77307. */
  77308. int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
  77309. mp_int* res, const byte* table, word32 len)
  77310. {
  77311. (void)table;
  77312. (void)len;
  77313. return sp_Pairing_1024(pm, qm, res);
  77314. }
  77315. #else
  77316. /*
  77317. * Calc l and c for the point when doubling p.
  77318. *
  77319. * l = 3 * (p.x^2 - 1) / (2 * p.y)
  77320. * c = l * p.x - p.y
  77321. *
  77322. * @param [out] lr Gradient result - table entry.
  77323. * @param [out] cr Constant result - table entry.
  77324. * @param [in] px X-ordinate of point to double.
  77325. * @param [in] py Y-ordinate of point to double.
  77326. * @param [in] t SP temporaries (3 used).
  77327. */
  77328. static void sp_1024_accum_dbl_calc_lc_32(sp_digit* lr, sp_digit* cr,
  77329. const sp_digit* px, const sp_digit* py, sp_digit* t)
  77330. {
  77331. sp_digit* t1 = t + 33 * 2 * 32;
  77332. sp_digit* t2 = t + 34 * 2 * 32;
  77333. sp_digit* l = t + 35 * 2 * 32;
  77334. /* l = 1 / 2 * p.y */
  77335. sp_1024_mont_dbl_32(l, py, p1024_mod);
  77336. sp_1024_mont_inv_32(l, l, t);
  77337. /* t1 = p.x^2 */
  77338. sp_1024_mont_sqr_32(t1, px, p1024_mod, p1024_mp_mod);
  77339. /* t1 = p.x - 1 */
  77340. sp_1024_mont_sub_32(t1, t1, p1024_norm_mod, p1024_mod);
  77341. /* t1 = 3 * (p.x^2 - 1) */
  77342. sp_1024_mont_dbl_32(t2, t1, p1024_mod);
  77343. sp_1024_mont_add_32(t1, t1, t2, p1024_mod);
  77344. /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
  77345. sp_1024_mont_mul_32(l, l, t1, p1024_mod, p1024_mp_mod);
  77346. /* t2 = l * p.x */
  77347. sp_1024_mont_mul_32(t2, l, px, p1024_mod, p1024_mp_mod);
  77348. /* c = t2 = l * p.x - p.y */
  77349. sp_1024_mont_sub_32(t2, t2, py, p1024_mod);
  77350. XMEMCPY(lr, l, sizeof(sp_digit) * 32);
  77351. XMEMCPY(cr, t2, sizeof(sp_digit) * 32);
  77352. }
  77353. /*
  77354. * Calc l and c when adding p and c.
  77355. *
  77356. * l = (c.y - p.y) / (c.x - p.x)
  77357. * c = (p.x * c.y - cx * p.y) / (cx - p.x)
  77358. *
  77359. * @param [out] lr Gradient result - table entry.
  77360. * @param [out] cr Constant result - table entry.
  77361. * @param [in] px X-ordinate of point to add.
  77362. * @param [in] py Y-ordinate of point to add.
  77363. * @param [in] cx X-ordinate of current point.
  77364. * @param [in] cy Y-ordinate of current point.
  77365. * @param [in] t SP temporaries (3 used).
  77366. */
  77367. static void sp_1024_accum_add_calc_lc_32(sp_digit* lr, sp_digit* cr,
  77368. const sp_digit* px, const sp_digit* py, const sp_digit* cx,
  77369. const sp_digit* cy, sp_digit* t)
  77370. {
  77371. sp_digit* t1 = t + 33 * 2 * 32;
  77372. sp_digit* c = t + 34 * 2 * 32;
  77373. sp_digit* l = t + 35 * 2 * 32;
  77374. /* l = 1 / (c.x - p.x) */
  77375. sp_1024_mont_sub_32(l, cx, px, p1024_mod);
  77376. sp_1024_mont_inv_32(l, l, t);
  77377. /* c = p.x * c.y */
  77378. sp_1024_mont_mul_32(c, px, cy, p1024_mod, p1024_mp_mod);
  77379. /* t1 = c.x * p.y */
  77380. sp_1024_mont_mul_32(t1, cx, py, p1024_mod, p1024_mp_mod);
  77381. /* c = (p.x * c.y) - (c.x * p.y) */
  77382. sp_1024_mont_sub_32(c, c, t1, p1024_mod);
  77383. /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
  77384. sp_1024_mont_mul_32(c, c, l, p1024_mod, p1024_mp_mod);
  77385. /* t1 = c.y - p.y */
  77386. sp_1024_mont_sub_32(t1, cy, py, p1024_mod);
  77387. /* l = (c.y - p.y) / (c.x - p.x) */
  77388. sp_1024_mont_mul_32(l, t1, l, p1024_mod, p1024_mp_mod);
  77389. XMEMCPY(lr, l, sizeof(sp_digit) * 32);
  77390. XMEMCPY(cr, c, sizeof(sp_digit) * 32);
  77391. }
  77392. /*
  77393. * Calculate vx and vy given gradient l and constant c and point q.
  77394. *
  77395. * l is a the gradient and is multiplied by q->x.
  77396. * c is a the constant that is added to the multiplicative result.
  77397. * q->y is the y-ordinate in result to multiply.
  77398. *
  77399. * if dbl
  77400. * v* = v*^2
  77401. * r.x = l * q.x + c
  77402. * r.y = q->y
  77403. * v* = v* * r*
  77404. *
  77405. * @param [in,out] vx X-ordinate of projective value in F*.
  77406. * @param [in,out] vy Y-ordinate of projective value in F*.
  77407. * @param [in] l Gradient to multiply with.
  77408. * @param [in] c Constant to add with.
  77409. * @param [in] q ECC point - second point on E(F_P^2).
  77410. * @param [in] t SP temporaries (3 used).
  77411. * @param [in] dbl Indicates whether this is for doubling. Otherwise
  77412. * adding.
  77413. */
  77414. static void sp_1024_accumulate_line_lc_32(sp_digit* vx, sp_digit* vy,
  77415. const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
  77416. sp_digit* t, int dbl)
  77417. {
  77418. sp_digit* rx = t + 4 * 2 * 32;
  77419. /* v = v^2 */
  77420. if (dbl) {
  77421. sp_1024_proj_sqr_32(vx, vy, t);
  77422. }
  77423. /* rx = l * q.x + c */
  77424. sp_1024_mont_mul_32(rx, l, q->x, p1024_mod, p1024_mp_mod);
  77425. sp_1024_mont_add_32(rx, rx, c, p1024_mod);
  77426. /* v = v^2 * r */
  77427. sp_1024_proj_mul_32(vx, vy, rx, q->y, t);
  77428. }
  77429. /* Operations to perform based on order - 1.
  77430. * Sliding window. Start at bottom and stop when bottom bit is one.
  77431. * Subtract if top bit in window is one.
  77432. * Width of 6 bits.
  77433. * Pairs: #dbls, add/subtract window value
  77434. */
  77435. static const signed char sp_1024_order_op_pre[] = {
  77436. 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
  77437. -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
  77438. -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
  77439. 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
  77440. -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
  77441. -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
  77442. -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
  77443. -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
  77444. -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
  77445. 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
  77446. -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
  77447. -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
  77448. 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
  77449. -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
  77450. 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
  77451. -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
  77452. 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
  77453. -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
  77454. -3, 1,
  77455. };
  77456. /*
  77457. * Generate table for pairing.
  77458. *
  77459. * Calculate the graident (l) and constant (c) at each step of the way.
  77460. * Sliding window. Start at bottom and stop when bottom bit is one.
  77461. * Subtract if top bit in window is one.
  77462. * Width of 6 bits.
  77463. *
  77464. * pm [in] Point to generate table for.
  77465. * table [in] Generated table.
  77466. * len [in,out] On in, the size of the buffer.
  77467. * On out, length of table generated.
  77468. * @return 0 on success.
  77469. * LENGTH_ONLY_E when table is NULL and only length returned.
  77470. * BUFFER_E when len is too small.
  77471. * MEMORY_E when dynamic memory allocation fauls.
  77472. */
  77473. int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
  77474. word32* len)
  77475. {
  77476. int err = 0;
  77477. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77478. defined(WOLFSSL_SP_SMALL_STACK)
  77479. sp_digit* td = NULL;
  77480. sp_digit* t;
  77481. sp_point_1024* pre_p;
  77482. #else
  77483. sp_digit t[36 * 2 * 32];
  77484. sp_point_1024 pre_p[16];
  77485. sp_point_1024 pd;
  77486. sp_point_1024 cd;
  77487. sp_point_1024 negd;
  77488. #endif
  77489. sp_point_1024* p = NULL;
  77490. sp_point_1024* c = NULL;
  77491. sp_point_1024* neg = NULL;
  77492. int i;
  77493. int j;
  77494. int k;
  77495. sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
  77496. if (table == NULL) {
  77497. *len = sizeof(sp_table_entry_1024) * 1167;
  77498. err = LENGTH_ONLY_E;
  77499. }
  77500. if ((err == MP_OKAY) &&
  77501. (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
  77502. err = BUFFER_E;
  77503. }
  77504. if (err == MP_OKAY) {
  77505. err = sp_1024_point_new_32(NULL, pd, p);
  77506. }
  77507. if (err == MP_OKAY) {
  77508. err = sp_1024_point_new_32(NULL, cd, c);
  77509. }
  77510. if (err == MP_OKAY) {
  77511. err = sp_1024_point_new_32(NULL, negd, neg);
  77512. }
  77513. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77514. defined(WOLFSSL_SP_SMALL_STACK)
  77515. if (err == MP_OKAY) {
  77516. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 32 * 2 + 16 *
  77517. sizeof(sp_point_1024), NULL, DYNAMIC_TYPE_TMP_BUFFER);
  77518. if (td == NULL) {
  77519. err = MEMORY_E;
  77520. }
  77521. }
  77522. #endif
  77523. if (err == MP_OKAY) {
  77524. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77525. defined(WOLFSSL_SP_SMALL_STACK)
  77526. t = td;
  77527. pre_p = (sp_point_1024*)(td + 36 * 32 * 2);
  77528. #endif
  77529. sp_1024_point_from_ecc_point_32(p, pm);
  77530. err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
  77531. }
  77532. if (err == MP_OKAY) {
  77533. err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
  77534. }
  77535. if (err == MP_OKAY) {
  77536. XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  77537. neg->infinity = 0;
  77538. c->infinity = 0;
  77539. /* Generate pre-computation table: 1, 3, ... , 31 */
  77540. XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
  77541. /* [2]P for adding */
  77542. sp_1024_proj_point_dbl_32(c, p, t);
  77543. /* 1, 3, ... */
  77544. for (i = 1; i < 16; i++) {
  77545. sp_1024_proj_point_add_32(&pre_p[i], &pre_p[i-1], c, t);
  77546. sp_1024_mont_map_32(&pre_p[i], t);
  77547. }
  77548. k = 0;
  77549. j = sp_1024_order_op_pre[0] / 2;
  77550. XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
  77551. for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
  77552. sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x,
  77553. c->y, t);
  77554. k++;
  77555. sp_1024_proj_point_dbl_32(c, c, t);
  77556. sp_1024_mont_map_32(c, t);
  77557. }
  77558. for (i = 2; i < 290; i += 2) {
  77559. j = sp_1024_order_op_pre[i];
  77560. if (j > 0) {
  77561. sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
  77562. pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
  77563. k++;
  77564. sp_1024_proj_point_add_32(c, c, &pre_p[j/2], t);
  77565. sp_1024_mont_map_32(c, t);
  77566. }
  77567. else {
  77568. XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
  77569. sp_1024_mont_sub_32(neg->y, p1024_mod, pre_p[-j / 2].y,
  77570. p1024_mod);
  77571. XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
  77572. sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y,
  77573. neg->x, neg->y, c->x, c->y, t);
  77574. k++;
  77575. sp_1024_proj_point_add_32(c, c, neg, t);
  77576. sp_1024_mont_map_32(c, t);
  77577. }
  77578. for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
  77579. sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x,
  77580. c->y, t);
  77581. k++;
  77582. sp_1024_proj_point_dbl_32(c, c, t);
  77583. sp_1024_mont_map_32(c, t);
  77584. }
  77585. }
  77586. *len = sizeof(sp_table_entry_1024) * 1167;
  77587. }
  77588. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77589. defined(WOLFSSL_SP_SMALL_STACK)
  77590. if (td != NULL) {
  77591. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  77592. }
  77593. #endif
  77594. sp_1024_point_free_32(neg, 1, NULL);
  77595. sp_1024_point_free_32(c, 1, NULL);
  77596. sp_1024_point_free_32(p, 1, NULL);
  77597. return err;
  77598. }
  77599. /*
  77600. * Calculate r = pairing <P, Q>.
  77601. *
  77602. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  77603. *
  77604. * Sliding window. Start at bottom and stop when bottom bit is one.
  77605. * Subtract if top bit in window is one.
  77606. * Width of 6 bits.
  77607. * Pre-generate values in window (1, 3, ...) - only V.
  77608. * Table contains all gradient l and a constant for each point on the path.
  77609. *
  77610. * @param [in] pm First point on E(F_p)[q].
  77611. * @param [in] qm Second point on E(F_p)[q].
  77612. * @param [in] res Result of calculation.
  77613. * @param [in] table Precomputed table of values.
  77614. * @param [in] len Length of precomputed table of values in bytes.
  77615. * @return 0 on success.
  77616. * @return MEMORY_E when dynamic memory allocation fails.
  77617. */
  77618. int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
  77619. mp_int* res, const byte* table, word32 len)
  77620. {
  77621. int err = 0;
  77622. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77623. defined(WOLFSSL_SP_SMALL_STACK)
  77624. sp_digit* td = NULL;
  77625. sp_digit* t;
  77626. sp_digit* vx;
  77627. sp_digit* vy;
  77628. sp_digit (*pre_vx)[64];
  77629. sp_digit (*pre_vy)[64];
  77630. sp_digit (*pre_nvy)[64];
  77631. #else
  77632. sp_digit t[36 * 2 * 32];
  77633. sp_digit vx[2 * 32];
  77634. sp_digit vy[2 * 32];
  77635. sp_digit pre_vx[16][64];
  77636. sp_digit pre_vy[16][64];
  77637. sp_digit pre_nvy[16][64];
  77638. sp_point_1024 pd;
  77639. sp_point_1024 qd;
  77640. sp_point_1024 cd;
  77641. #endif
  77642. sp_point_1024* p = NULL;
  77643. sp_point_1024* q = NULL;
  77644. sp_point_1024* c = NULL;
  77645. sp_digit* r = NULL;
  77646. int i;
  77647. int j;
  77648. int k;
  77649. const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
  77650. if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
  77651. err = BUFFER_E;
  77652. }
  77653. if (err == MP_OKAY) {
  77654. err = sp_1024_point_new_32(NULL, pd, p);
  77655. }
  77656. if (err == MP_OKAY) {
  77657. err = sp_1024_point_new_32(NULL, qd, q);
  77658. }
  77659. if (err == MP_OKAY) {
  77660. err = sp_1024_point_new_32(NULL, cd, c);
  77661. }
  77662. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77663. defined(WOLFSSL_SP_SMALL_STACK)
  77664. if (err == MP_OKAY) {
  77665. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 32 * 2, NULL,
  77666. DYNAMIC_TYPE_TMP_BUFFER);
  77667. if (td == NULL) {
  77668. err = MEMORY_E;
  77669. }
  77670. }
  77671. #endif
  77672. if (err == MP_OKAY) {
  77673. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77674. defined(WOLFSSL_SP_SMALL_STACK)
  77675. t = td;
  77676. vx = td + 36 * 32 * 2;
  77677. vy = td + 37 * 32 * 2;
  77678. pre_vx = (sp_digit(*)[64])(td + 38 * 32 * 2);
  77679. pre_vy = (sp_digit(*)[64])(td + 54 * 32 * 2);
  77680. pre_nvy = (sp_digit(*)[64])(td + 70 * 32 * 2);
  77681. #endif
  77682. r = vy;
  77683. sp_1024_point_from_ecc_point_32(p, pm);
  77684. sp_1024_point_from_ecc_point_32(q, qm);
  77685. err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod);
  77686. }
  77687. if (err == MP_OKAY) {
  77688. err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod);
  77689. }
  77690. if (err == MP_OKAY) {
  77691. err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod);
  77692. }
  77693. if (err == MP_OKAY) {
  77694. err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod);
  77695. }
  77696. if (err == MP_OKAY) {
  77697. err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod);
  77698. }
  77699. if (err == MP_OKAY) {
  77700. /* Generate pre-computation table: 1, 3, ... , 31 */
  77701. XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32);
  77702. pre_vx[0][0] = 1;
  77703. XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32);
  77704. sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
  77705. /* [2]P for adding */
  77706. XMEMCPY(c, p, sizeof(sp_point_1024));
  77707. XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32);
  77708. vx[0] = 1;
  77709. XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32);
  77710. sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t);
  77711. /* 3, 5, ... */
  77712. for (i = 1; i < 16; i++) {
  77713. XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32);
  77714. XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32);
  77715. sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t);
  77716. sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c,
  77717. q, p, t, 0);
  77718. sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i],
  77719. p1024_mod);
  77720. }
  77721. XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 32);
  77722. c->infinity = 0;
  77723. j = sp_1024_order_op_pre[0] / 2;
  77724. XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32);
  77725. XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32);
  77726. k = 0;
  77727. for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
  77728. /* Accumulate line into v and double point. */
  77729. sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
  77730. precomp[k].y, q, t, 1);
  77731. k++;
  77732. }
  77733. for (i = 2; i < 290; i += 2) {
  77734. sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
  77735. precomp[k].y, q, t, 0);
  77736. k++;
  77737. j = sp_1024_order_op_pre[i];
  77738. if (j > 0) {
  77739. j /= 2;
  77740. /* Accumulate line into v. */
  77741. sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t);
  77742. }
  77743. else {
  77744. j = -j / 2;
  77745. /* Accumulate line into v. */
  77746. sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t);
  77747. }
  77748. for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
  77749. /* Accumulate line into v and double point. */
  77750. sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x,
  77751. precomp[k].y, q, t, 1);
  77752. k++;
  77753. }
  77754. }
  77755. /* Final exponentiation */
  77756. sp_1024_proj_sqr_32(vx, vy, t);
  77757. sp_1024_proj_sqr_32(vx, vy, t);
  77758. /* Convert from PF_p[q] to F_p */
  77759. sp_1024_mont_inv_32(vx, vx, t);
  77760. sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod);
  77761. XMEMSET(r + 32, 0, sizeof(sp_digit) * 32);
  77762. sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod);
  77763. err = sp_1024_to_mp(r, res);
  77764. }
  77765. #if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
  77766. defined(WOLFSSL_SP_SMALL_STACK)
  77767. if (td != NULL) {
  77768. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  77769. }
  77770. #endif
  77771. sp_1024_point_free_32(c, 1, NULL);
  77772. sp_1024_point_free_32(q, 1, NULL);
  77773. sp_1024_point_free_32(p, 1, NULL);
  77774. return err;
  77775. }
  77776. #endif /* WOLFSSL_SP_SMALL */
  77777. #ifdef HAVE_ECC_CHECK_KEY
  77778. /* Read big endian unsigned byte array into r.
  77779. *
  77780. * r A single precision integer.
  77781. * size Maximum number of bytes to convert
  77782. * a Byte array.
  77783. * n Number of bytes in array to read.
  77784. */
  77785. static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
  77786. {
  77787. int i;
  77788. int j;
  77789. byte* d;
  77790. for (i = n - 1,j = 0; i >= 3; i -= 4) {
  77791. r[j] = ((sp_digit)a[i - 0] << 0) |
  77792. ((sp_digit)a[i - 1] << 8) |
  77793. ((sp_digit)a[i - 2] << 16) |
  77794. ((sp_digit)a[i - 3] << 24);
  77795. j++;
  77796. }
  77797. if (i >= 0) {
  77798. r[j] = 0;
  77799. d = (byte*)r;
  77800. switch (i) {
  77801. case 2: d[n - 1 - 2] = a[2]; //fallthrough
  77802. case 1: d[n - 1 - 1] = a[1]; //fallthrough
  77803. case 0: d[n - 1 - 0] = a[0]; //fallthrough
  77804. }
  77805. j++;
  77806. }
  77807. for (; j < size; j++) {
  77808. r[j] = 0;
  77809. }
  77810. }
  77811. /* Check that the x and y ordinates are a valid point on the curve.
  77812. *
  77813. * point EC point.
  77814. * heap Heap to use if dynamically allocating.
  77815. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  77816. * not on the curve and MP_OKAY otherwise.
  77817. */
  77818. static int sp_1024_ecc_is_point_32(const sp_point_1024* point,
  77819. void* heap)
  77820. {
  77821. #ifdef WOLFSSL_SP_SMALL_STACK
  77822. sp_digit* t1 = NULL;
  77823. #else
  77824. sp_digit t1[32 * 4];
  77825. #endif
  77826. sp_digit* t2 = NULL;
  77827. sp_int32 n;
  77828. int err = MP_OKAY;
  77829. #ifdef WOLFSSL_SP_SMALL_STACK
  77830. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, heap, DYNAMIC_TYPE_ECC);
  77831. if (t1 == NULL)
  77832. err = MEMORY_E;
  77833. #endif
  77834. (void)heap;
  77835. if (err == MP_OKAY) {
  77836. t2 = t1 + 2 * 32;
  77837. /* y^2 - x^3 - a.x = b */
  77838. sp_1024_sqr_32(t1, point->y);
  77839. (void)sp_1024_mod_32(t1, t1, p1024_mod);
  77840. sp_1024_sqr_32(t2, point->x);
  77841. (void)sp_1024_mod_32(t2, t2, p1024_mod);
  77842. sp_1024_mul_32(t2, t2, point->x);
  77843. (void)sp_1024_mod_32(t2, t2, p1024_mod);
  77844. sp_1024_mont_sub_32(t1, t1, t2, p1024_mod);
  77845. /* y^2 - x^3 + 3.x = b, when a = -3 */
  77846. sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
  77847. sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
  77848. sp_1024_mont_add_32(t1, t1, point->x, p1024_mod);
  77849. n = sp_1024_cmp_32(t1, p1024_mod);
  77850. sp_1024_cond_sub_32(t1, t1, p1024_mod, ~(n >> 31));
  77851. sp_1024_norm_32(t1);
  77852. if (!sp_1024_iszero_32(t1)) {
  77853. err = MP_VAL;
  77854. }
  77855. }
  77856. #ifdef WOLFSSL_SP_SMALL_STACK
  77857. if (t1 != NULL)
  77858. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  77859. #endif
  77860. return err;
  77861. }
  77862. /* Check that the x and y ordinates are a valid point on the curve.
  77863. *
  77864. * pX X ordinate of EC point.
  77865. * pY Y ordinate of EC point.
  77866. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  77867. * not on the curve and MP_OKAY otherwise.
  77868. */
  77869. int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
  77870. {
  77871. #ifdef WOLFSSL_SP_SMALL_STACK
  77872. sp_point_1024* pub = NULL;
  77873. #else
  77874. sp_point_1024 pub[1];
  77875. #endif
  77876. const byte one[1] = { 1 };
  77877. int err = MP_OKAY;
  77878. #ifdef WOLFSSL_SP_SMALL_STACK
  77879. pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL,
  77880. DYNAMIC_TYPE_ECC);
  77881. if (pub == NULL)
  77882. err = MEMORY_E;
  77883. #endif
  77884. if (err == MP_OKAY) {
  77885. sp_1024_from_mp(pub->x, 32, pX);
  77886. sp_1024_from_mp(pub->y, 32, pY);
  77887. sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
  77888. err = sp_1024_ecc_is_point_32(pub, NULL);
  77889. }
  77890. #ifdef WOLFSSL_SP_SMALL_STACK
  77891. if (pub != NULL)
  77892. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  77893. #endif
  77894. return err;
  77895. }
  77896. /* Check that the private scalar generates the EC point (px, py), the point is
  77897. * on the curve and the point has the correct order.
  77898. *
  77899. * pX X ordinate of EC point.
  77900. * pY Y ordinate of EC point.
  77901. * privm Private scalar that generates EC point.
  77902. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  77903. * not on the curve, ECC_INF_E if the point does not have the correct order,
  77904. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  77905. * MP_OKAY otherwise.
  77906. */
  77907. int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
  77908. const mp_int* privm, void* heap)
  77909. {
  77910. #ifdef WOLFSSL_SP_SMALL_STACK
  77911. sp_digit* priv = NULL;
  77912. sp_point_1024* pub = NULL;
  77913. #else
  77914. sp_digit priv[32];
  77915. sp_point_1024 pub[2];
  77916. #endif
  77917. sp_point_1024* p = NULL;
  77918. const byte one[1] = { 1 };
  77919. int err = MP_OKAY;
  77920. /* Quick check the lengs of public key ordinates and private key are in
  77921. * range. Proper check later.
  77922. */
  77923. if (((mp_count_bits(pX) > 1024) ||
  77924. (mp_count_bits(pY) > 1024) ||
  77925. ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
  77926. err = ECC_OUT_OF_RANGE_E;
  77927. }
  77928. #ifdef WOLFSSL_SP_SMALL_STACK
  77929. if (err == MP_OKAY) {
  77930. pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
  77931. DYNAMIC_TYPE_ECC);
  77932. if (pub == NULL)
  77933. err = MEMORY_E;
  77934. }
  77935. if (err == MP_OKAY && privm) {
  77936. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap,
  77937. DYNAMIC_TYPE_ECC);
  77938. if (priv == NULL)
  77939. err = MEMORY_E;
  77940. }
  77941. #endif
  77942. if (err == MP_OKAY) {
  77943. p = pub + 1;
  77944. sp_1024_from_mp(pub->x, 32, pX);
  77945. sp_1024_from_mp(pub->y, 32, pY);
  77946. sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one));
  77947. if (privm)
  77948. sp_1024_from_mp(priv, 32, privm);
  77949. /* Check point at infinitiy. */
  77950. if ((sp_1024_iszero_32(pub->x) != 0) &&
  77951. (sp_1024_iszero_32(pub->y) != 0)) {
  77952. err = ECC_INF_E;
  77953. }
  77954. }
  77955. /* Check range of X and Y */
  77956. if ((err == MP_OKAY) &&
  77957. ((sp_1024_cmp_32(pub->x, p1024_mod) >= 0) ||
  77958. (sp_1024_cmp_32(pub->y, p1024_mod) >= 0))) {
  77959. err = ECC_OUT_OF_RANGE_E;
  77960. }
  77961. if (err == MP_OKAY) {
  77962. /* Check point is on curve */
  77963. err = sp_1024_ecc_is_point_32(pub, heap);
  77964. }
  77965. if (err == MP_OKAY) {
  77966. /* Point * order = infinity */
  77967. err = sp_1024_ecc_mulmod_32(p, pub, p1024_order, 1, 1, heap);
  77968. }
  77969. /* Check result is infinity */
  77970. if ((err == MP_OKAY) && ((sp_1024_iszero_32(p->x) == 0) ||
  77971. (sp_1024_iszero_32(p->y) == 0))) {
  77972. err = ECC_INF_E;
  77973. }
  77974. if (privm) {
  77975. if (err == MP_OKAY) {
  77976. /* Base * private = point */
  77977. err = sp_1024_ecc_mulmod_base_32(p, priv, 1, 1, heap);
  77978. }
  77979. /* Check result is public key */
  77980. if ((err == MP_OKAY) &&
  77981. ((sp_1024_cmp_32(p->x, pub->x) != 0) ||
  77982. (sp_1024_cmp_32(p->y, pub->y) != 0))) {
  77983. err = ECC_PRIV_KEY_E;
  77984. }
  77985. }
  77986. #ifdef WOLFSSL_SP_SMALL_STACK
  77987. if (pub != NULL)
  77988. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  77989. if (priv != NULL)
  77990. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  77991. #endif
  77992. return err;
  77993. }
  77994. #endif
  77995. #endif /* WOLFSSL_SP_1024 */
  77996. #endif /* WOLFCRYPT_HAVE_SAKKE */
  77997. #endif /* WOLFSSL_HAVE_SP_ECC */
  77998. #endif /* WOLFSSL_SP_ARM_CORTEX_M_ASM */
  77999. #endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */